1 /* Bind and unbind a cache from the filesystem backing it
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
12 #include <linux/module.h>
13 #include <linux/init.h>
14 #include <linux/sched.h>
15 #include <linux/completion.h>
16 #include <linux/slab.h>
18 #include <linux/file.h>
19 #include <linux/namei.h>
20 #include <linux/mount.h>
21 #include <linux/statfs.h>
22 #include <linux/ctype.h>
25 static int cachefiles_daemon_add_cache(struct cachefiles_cache
*caches
);
28 * bind a directory as a cache
30 int cachefiles_daemon_bind(struct cachefiles_cache
*cache
, char *args
)
32 _enter("{%u,%u,%u,%u,%u,%u},%s",
41 /* start by checking things over */
42 ASSERT(cache
->fstop_percent
>= 0 &&
43 cache
->fstop_percent
< cache
->fcull_percent
&&
44 cache
->fcull_percent
< cache
->frun_percent
&&
45 cache
->frun_percent
< 100);
47 ASSERT(cache
->bstop_percent
>= 0 &&
48 cache
->bstop_percent
< cache
->bcull_percent
&&
49 cache
->bcull_percent
< cache
->brun_percent
&&
50 cache
->brun_percent
< 100);
53 pr_err("'bind' command doesn't take an argument");
57 if (!cache
->rootdirname
) {
58 pr_err("No cache directory specified");
62 /* don't permit already bound caches to be re-bound */
63 if (test_bit(CACHEFILES_READY
, &cache
->flags
)) {
64 pr_err("Cache already bound");
68 /* make sure we have copies of the tag and dirname strings */
70 /* the tag string is released by the fops->release()
71 * function, so we don't release it on error here */
72 cache
->tag
= kstrdup("CacheFiles", GFP_KERNEL
);
78 return cachefiles_daemon_add_cache(cache
);
84 static int cachefiles_daemon_add_cache(struct cachefiles_cache
*cache
)
86 struct cachefiles_object
*fsdef
;
89 struct dentry
*graveyard
, *cachedir
, *root
;
90 const struct cred
*saved_cred
;
95 /* we want to work under the module's security ID */
96 ret
= cachefiles_get_security_ID(cache
);
100 cachefiles_begin_secure(cache
, &saved_cred
);
102 /* allocate the root index object */
105 fsdef
= kmem_cache_alloc(cachefiles_object_jar
, GFP_KERNEL
);
107 goto error_root_object
;
109 ASSERTCMP(fsdef
->backer
, ==, NULL
);
111 atomic_set(&fsdef
->usage
, 1);
112 fsdef
->type
= FSCACHE_COOKIE_TYPE_INDEX
;
114 _debug("- fsdef %p", fsdef
);
116 /* look up the directory at the root of the cache */
117 ret
= kern_path(cache
->rootdirname
, LOOKUP_DIRECTORY
, &path
);
119 goto error_open_root
;
121 cache
->mnt
= path
.mnt
;
124 /* check parameters */
126 if (!root
->d_inode
||
127 !root
->d_inode
->i_op
->lookup
||
128 !root
->d_inode
->i_op
->mkdir
||
129 !root
->d_inode
->i_op
->setxattr
||
130 !root
->d_inode
->i_op
->getxattr
||
131 !root
->d_sb
->s_op
->statfs
||
132 !root
->d_sb
->s_op
->sync_fs
)
133 goto error_unsupported
;
136 if (root
->d_sb
->s_flags
& MS_RDONLY
)
137 goto error_unsupported
;
139 /* determine the security of the on-disk cache as this governs
140 * security ID of files we create */
141 ret
= cachefiles_determine_cache_security(cache
, root
, &saved_cred
);
143 goto error_unsupported
;
145 /* get the cache size and blocksize */
146 ret
= vfs_statfs(&path
, &stats
);
148 goto error_unsupported
;
151 if (stats
.f_bsize
<= 0)
152 goto error_unsupported
;
155 if (stats
.f_bsize
> PAGE_SIZE
)
156 goto error_unsupported
;
158 cache
->bsize
= stats
.f_bsize
;
160 if (stats
.f_bsize
< PAGE_SIZE
)
161 cache
->bshift
= PAGE_SHIFT
- ilog2(stats
.f_bsize
);
163 _debug("blksize %u (shift %u)",
164 cache
->bsize
, cache
->bshift
);
166 _debug("size %llu, avail %llu",
167 (unsigned long long) stats
.f_blocks
,
168 (unsigned long long) stats
.f_bavail
);
170 /* set up caching limits */
171 do_div(stats
.f_files
, 100);
172 cache
->fstop
= stats
.f_files
* cache
->fstop_percent
;
173 cache
->fcull
= stats
.f_files
* cache
->fcull_percent
;
174 cache
->frun
= stats
.f_files
* cache
->frun_percent
;
176 _debug("limits {%llu,%llu,%llu} files",
177 (unsigned long long) cache
->frun
,
178 (unsigned long long) cache
->fcull
,
179 (unsigned long long) cache
->fstop
);
181 stats
.f_blocks
>>= cache
->bshift
;
182 do_div(stats
.f_blocks
, 100);
183 cache
->bstop
= stats
.f_blocks
* cache
->bstop_percent
;
184 cache
->bcull
= stats
.f_blocks
* cache
->bcull_percent
;
185 cache
->brun
= stats
.f_blocks
* cache
->brun_percent
;
187 _debug("limits {%llu,%llu,%llu} blocks",
188 (unsigned long long) cache
->brun
,
189 (unsigned long long) cache
->bcull
,
190 (unsigned long long) cache
->bstop
);
192 /* get the cache directory and check its type */
193 cachedir
= cachefiles_get_directory(cache
, root
, "cache");
194 if (IS_ERR(cachedir
)) {
195 ret
= PTR_ERR(cachedir
);
196 goto error_unsupported
;
199 fsdef
->dentry
= cachedir
;
200 fsdef
->fscache
.cookie
= NULL
;
202 ret
= cachefiles_check_object_type(fsdef
);
204 goto error_unsupported
;
206 /* get the graveyard directory */
207 graveyard
= cachefiles_get_directory(cache
, root
, "graveyard");
208 if (IS_ERR(graveyard
)) {
209 ret
= PTR_ERR(graveyard
);
210 goto error_unsupported
;
213 cache
->graveyard
= graveyard
;
215 /* publish the cache */
216 fscache_init_cache(&cache
->cache
,
217 &cachefiles_cache_ops
,
219 fsdef
->dentry
->d_sb
->s_id
);
221 fscache_object_init(&fsdef
->fscache
, NULL
, &cache
->cache
);
223 ret
= fscache_add_cache(&cache
->cache
, &fsdef
->fscache
, cache
->tag
);
225 goto error_add_cache
;
228 set_bit(CACHEFILES_READY
, &cache
->flags
);
231 pr_info("File cache on %s registered\n", cache
->cache
.identifier
);
233 /* check how much space the cache has */
234 cachefiles_has_space(cache
, 0, 0);
235 cachefiles_end_secure(cache
, saved_cred
);
239 dput(cache
->graveyard
);
240 cache
->graveyard
= NULL
;
245 fsdef
->dentry
= NULL
;
248 kmem_cache_free(cachefiles_object_jar
, fsdef
);
250 cachefiles_end_secure(cache
, saved_cred
);
251 pr_err("Failed to register: %d", ret
);
256 * unbind a cache on fd release
258 void cachefiles_daemon_unbind(struct cachefiles_cache
*cache
)
262 if (test_bit(CACHEFILES_READY
, &cache
->flags
)) {
263 pr_info("File cache on %s unregistering\n",
264 cache
->cache
.identifier
);
266 fscache_withdraw_cache(&cache
->cache
);
269 dput(cache
->graveyard
);
272 kfree(cache
->rootdirname
);
273 kfree(cache
->secctx
);