1 /* cf-proc.c: /proc/fs/cachefiles interface
3 * Copyright (C) 2006 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 License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, 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/namespace.h>
22 #include <linux/statfs.h>
23 #include <linux/proc_fs.h>
24 #include <linux/ctype.h>
27 static int cachefiles_proc_open(struct inode *, struct file *);
28 static int cachefiles_proc_release(struct inode *, struct file *);
29 static ssize_t cachefiles_proc_read(struct file *, char __user *, size_t, loff_t *);
30 static ssize_t cachefiles_proc_write(struct file *, const char __user *, size_t, loff_t *);
31 static int cachefiles_proc_brun(struct cachefiles_cache *cache, char *args);
32 static int cachefiles_proc_bcull(struct cachefiles_cache *cache, char *args);
33 static int cachefiles_proc_bstop(struct cachefiles_cache *cache, char *args);
34 static int cachefiles_proc_cull(struct cachefiles_cache *cache, char *args);
35 static int cachefiles_proc_debug(struct cachefiles_cache *cache, char *args);
36 static int cachefiles_proc_dir(struct cachefiles_cache *cache, char *args);
37 static int cachefiles_proc_tag(struct cachefiles_cache *cache, char *args);
39 struct proc_dir_entry *cachefiles_proc;
41 static unsigned long cachefiles_open;
43 struct file_operations cachefiles_proc_fops = {
44 .open = cachefiles_proc_open,
45 .release = cachefiles_proc_release,
46 .read = cachefiles_proc_read,
47 .write = cachefiles_proc_write,
50 struct cachefiles_proc_cmd {
52 int (*handler)(struct cachefiles_cache *cache, char *args);
55 static const struct cachefiles_proc_cmd cachefiles_proc_cmds[] = {
56 { "bind", cachefiles_proc_bind },
57 { "brun", cachefiles_proc_brun },
58 { "bcull", cachefiles_proc_bcull },
59 { "bstop", cachefiles_proc_bstop },
60 { "cull", cachefiles_proc_cull },
61 { "debug", cachefiles_proc_debug },
62 { "dir", cachefiles_proc_dir },
63 { "tag", cachefiles_proc_tag },
68 /*****************************************************************************/
72 static int cachefiles_proc_open(struct inode *inode, struct file *file)
74 struct cachefiles_cache *cache;
78 /* only the superuser may do this */
79 if (!capable(CAP_SYS_ADMIN))
82 /* /proc/fs/cachefiles may only be open once at a time */
83 if (xchg(&cachefiles_open, 1) == 1)
86 /* allocate a cache record */
87 cache = kzalloc(sizeof(struct cachefiles_cache), GFP_KERNEL);
93 cache->active_nodes = RB_ROOT;
94 rwlock_init(&cache->active_lock);
96 /* set default caching limits
97 * - limit at 1% free space
98 * - cull below 5% free space
99 * - cease culling above 7% free space
101 cache->brun_percent = 7;
102 cache->bcull_percent = 5;
103 cache->bstop_percent = 1;
105 file->private_data = cache;
106 cache->cachefilesd = file;
110 /*****************************************************************************/
114 static int cachefiles_proc_release(struct inode *inode, struct file *file)
116 struct cachefiles_cache *cache = file->private_data;
122 set_bit(CACHEFILES_DEAD, &cache->flags);
124 cachefiles_proc_unbind(cache);
126 ASSERT(!cache->active_nodes.rb_node);
128 /* clean up the control file interface */
129 cache->cachefilesd = NULL;
130 file->private_data = NULL;
139 /*****************************************************************************/
141 * read the cache state
143 static ssize_t cachefiles_proc_read(struct file *file, char __user *_buffer,
144 size_t buflen, loff_t *pos)
146 struct cachefiles_cache *cache = file->private_data;
150 _enter(",,%zu,", buflen);
152 if (!test_bit(CACHEFILES_READY, &cache->flags))
155 /* check how much space the cache has */
156 cachefiles_has_space(cache, 0);
159 n = snprintf(buffer, sizeof(buffer),
164 test_bit(CACHEFILES_CULLING, &cache->flags) ? '1' : '0',
173 if (copy_to_user(_buffer, buffer, n) != 0)
179 /*****************************************************************************/
183 static ssize_t cachefiles_proc_write(struct file *file,
184 const char __user *_data, size_t datalen,
187 const struct cachefiles_proc_cmd *cmd;
188 struct cachefiles_cache *cache = file->private_data;
190 char *data, *args, *cp;
192 _enter(",,%zu,", datalen);
196 if (test_bit(CACHEFILES_DEAD, &cache->flags))
199 if (datalen < 0 || datalen > PAGE_SIZE - 1)
202 /* drag the command string into the kernel so we can parse it */
203 data = kmalloc(datalen + 1, GFP_KERNEL);
208 if (copy_from_user(data, _data, datalen) != 0)
211 data[datalen] = '\0';
214 if (memchr(data, '\0', datalen))
217 /* strip any newline */
218 cp = memchr(data, '\n', datalen);
226 /* parse the command */
229 for (args = data; *args; args++)
236 for (args++; isspace(*args); args++)
240 /* run the appropriate command handler */
241 for (cmd = cachefiles_proc_cmds; cmd->name[0]; cmd++)
242 if (strcmp(cmd->name, data) == 0)
247 _leave(" = %d", ret);
251 mutex_lock(&file->f_dentry->d_inode->i_mutex);
254 if (!test_bit(CACHEFILES_DEAD, &cache->flags))
255 ret = cmd->handler(cache, args);
257 mutex_unlock(&file->f_dentry->d_inode->i_mutex);
264 /*****************************************************************************/
266 * give a range error for cache space constraints
267 * - can be tail-called
269 static int cachefiles_proc_range_error(struct cachefiles_cache *cache, char *args)
271 kerror("Free space limits must be in range"
272 " 0%%<=bstop<bcull<brun<100%%");
277 /*****************************************************************************/
279 * set the percentage of blocks at which to stop culling
280 * - command: "brun <N>%"
282 static int cachefiles_proc_brun(struct cachefiles_cache *cache, char *args)
291 brun = simple_strtoul(args, &args, 10);
292 if (args[0] != '%' || args[1] != '\0')
295 if (brun <= cache->bcull_percent || brun >= 100)
296 return cachefiles_proc_range_error(cache, args);
298 cache->brun_percent = brun;
302 /*****************************************************************************/
304 * set the percentage of blocks at which to start culling
305 * - command: "bcull <N>%"
307 static int cachefiles_proc_bcull(struct cachefiles_cache *cache, char *args)
316 bcull = simple_strtoul(args, &args, 10);
317 if (args[0] != '%' || args[1] != '\0')
320 if (bcull <= cache->bstop_percent || bcull >= cache->brun_percent)
321 return cachefiles_proc_range_error(cache, args);
323 cache->bcull_percent = bcull;
327 /*****************************************************************************/
329 * set the percentage of blocks at which to stop allocating
330 * - command: "bstop <N>%"
332 static int cachefiles_proc_bstop(struct cachefiles_cache *cache, char *args)
341 bstop = simple_strtoul(args, &args, 10);
342 if (args[0] != '%' || args[1] != '\0')
345 if (bstop < 0 || bstop >= cache->bcull_percent)
346 return cachefiles_proc_range_error(cache, args);
348 cache->bstop_percent = bstop;
352 /*****************************************************************************/
354 * set the cache directory
355 * - command: "dir <name>"
357 static int cachefiles_proc_dir(struct cachefiles_cache *cache, char *args)
364 kerror("Empty directory specified");
368 if (cache->rootdirname) {
369 kerror("Second cache directory specified");
373 dir = kstrdup(args, GFP_KERNEL);
377 cache->rootdirname = dir;
381 /*****************************************************************************/
384 * - command: "tag <name>"
386 static int cachefiles_proc_tag(struct cachefiles_cache *cache, char *args)
393 kerror("Empty tag specified");
400 tag = kstrdup(args, GFP_KERNEL);
408 /*****************************************************************************/
410 * request a node in the cache be culled
411 * - command: "cull <dirfd> <name>"
413 static int cachefiles_proc_cull(struct cachefiles_cache *cache, char *args)
416 struct file *dirfile;
417 int dirfd, fput_needed, ret;
421 dirfd = simple_strtoul(args, &args, 0);
423 if (!args || !isspace(*args))
426 while (isspace(*args))
432 if (strchr(args, '/'))
435 if (!test_bit(CACHEFILES_READY, &cache->flags)) {
436 kerror("cull applied to unready cache");
440 if (test_bit(CACHEFILES_DEAD, &cache->flags)) {
441 kerror("cull applied to dead cache");
445 /* extract the directory dentry from the fd */
446 dirfile = fget_light(dirfd, &fput_needed);
448 kerror("cull dirfd not open");
452 dir = dget(dirfile->f_dentry);
453 fput_light(dirfile, fput_needed);
456 if (!S_ISDIR(dir->d_inode->i_mode))
459 ret = cachefiles_cull(cache, dir, args);
462 _leave(" = %d", ret);
467 kerror("cull command requires dirfd to be a directory");
471 kerror("cull command requires dirfd and filename");
475 /*****************************************************************************/
478 * - command: "debug <mask>"
480 static int cachefiles_proc_debug(struct cachefiles_cache *cache, char *args)
486 mask = simple_strtoul(args, &args, 0);
488 if (!args || !isspace(*args))
491 cachefiles_debug = mask;
496 kerror("debug command requires mask");