This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / fs / cachefiles / cf-proc.c
1 /* cf-proc.c: /proc/fs/cachefiles interface
2  *
3  * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells (dhowells@redhat.com)
5  *
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.
10  */
11
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>
17 #include <linux/fs.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>
25 #include "internal.h"
26
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);
38
39 struct proc_dir_entry *cachefiles_proc;
40
41 static unsigned long cachefiles_open;
42
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,
48 };
49
50 struct cachefiles_proc_cmd {
51         char name[8];
52         int (*handler)(struct cachefiles_cache *cache, char *args);
53 };
54
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     },
64         { "",           NULL                    }
65 };
66
67
68 /*****************************************************************************/
69 /*
70  * do various checks
71  */
72 static int cachefiles_proc_open(struct inode *inode, struct file *file)
73 {
74         struct cachefiles_cache *cache;
75
76         _enter("");
77
78         /* only the superuser may do this */
79         if (!capable(CAP_SYS_ADMIN))
80                 return -EPERM;
81
82         /* /proc/fs/cachefiles may only be open once at a time */
83         if (xchg(&cachefiles_open, 1) == 1)
84                 return -EBUSY;
85
86         /* allocate a cache record */
87         cache = kzalloc(sizeof(struct cachefiles_cache), GFP_KERNEL);
88         if (!cache) {
89                 cachefiles_open = 0;
90                 return -ENOMEM;
91         }
92
93         cache->active_nodes = RB_ROOT;
94         rwlock_init(&cache->active_lock);
95
96         /* set default caching limits
97          * - limit at 1% free space
98          * - cull below 5% free space
99          * - cease culling above 7% free space
100          */
101         cache->brun_percent = 7;
102         cache->bcull_percent = 5;
103         cache->bstop_percent = 1;
104
105         file->private_data = cache;
106         cache->cachefilesd = file;
107         return 0;
108 }
109
110 /*****************************************************************************/
111 /*
112  * release a cache
113  */
114 static int cachefiles_proc_release(struct inode *inode, struct file *file)
115 {
116         struct cachefiles_cache *cache = file->private_data;
117
118         _enter("");
119
120         ASSERT(cache);
121
122         set_bit(CACHEFILES_DEAD, &cache->flags);
123
124         cachefiles_proc_unbind(cache);
125
126         ASSERT(!cache->active_nodes.rb_node);
127
128         /* clean up the control file interface */
129         cache->cachefilesd = NULL;
130         file->private_data = NULL;
131         cachefiles_open = 0;
132
133         kfree(cache);
134
135         _leave("");
136         return 0;
137 }
138
139 /*****************************************************************************/
140 /*
141  * read the cache state
142  */
143 static ssize_t cachefiles_proc_read(struct file *file, char __user *_buffer,
144                                     size_t buflen, loff_t *pos)
145 {
146         struct cachefiles_cache *cache = file->private_data;
147         char buffer[256];
148         int n;
149
150         _enter(",,%zu,", buflen);
151
152         if (!test_bit(CACHEFILES_READY, &cache->flags))
153                 return 0;
154
155         /* check how much space the cache has */
156         cachefiles_has_space(cache, 0);
157
158         /* summarise */
159         n = snprintf(buffer, sizeof(buffer),
160                      "cull=%c"
161                      " brun=%llx"
162                      " bcull=%llx"
163                      " bstop=%llx",
164                      test_bit(CACHEFILES_CULLING, &cache->flags) ? '1' : '0',
165                      cache->brun,
166                      cache->bcull,
167                      cache->bstop
168                      );
169
170         if (n > buflen)
171                 return -EMSGSIZE;
172
173         if (copy_to_user(_buffer, buffer, n) != 0)
174                 return -EFAULT;
175
176         return n;
177 }
178
179 /*****************************************************************************/
180 /*
181  * command the cache
182  */
183 static ssize_t cachefiles_proc_write(struct file *file,
184                                      const char __user *_data, size_t datalen,
185                                      loff_t *pos)
186 {
187         const struct cachefiles_proc_cmd *cmd;
188         struct cachefiles_cache *cache = file->private_data;
189         ssize_t ret;
190         char *data, *args, *cp;
191
192         _enter(",,%zu,", datalen);
193
194         ASSERT(cache);
195
196         if (test_bit(CACHEFILES_DEAD, &cache->flags))
197                 return -EIO;
198
199         if (datalen < 0 || datalen > PAGE_SIZE - 1)
200                 return -EOPNOTSUPP;
201
202         /* drag the command string into the kernel so we can parse it */
203         data = kmalloc(datalen + 1, GFP_KERNEL);
204         if (!data)
205                 return -ENOMEM;
206
207         ret = -EFAULT;
208         if (copy_from_user(data, _data, datalen) != 0)
209                 goto error;
210
211         data[datalen] = '\0';
212
213         ret = -EINVAL;
214         if (memchr(data, '\0', datalen))
215                 goto error;
216
217         /* strip any newline */
218         cp = memchr(data, '\n', datalen);
219         if (cp) {
220                 if (cp == data)
221                         goto error;
222
223                 *cp = '\0';
224         }
225
226         /* parse the command */
227         ret = -EOPNOTSUPP;
228
229         for (args = data; *args; args++)
230                 if (isspace(*args))
231                         break;
232         if (*args) {
233                 if (args == data)
234                         goto error;
235                 *args = '\0';
236                 for (args++; isspace(*args); args++)
237                         continue;
238         }
239
240         /* run the appropriate command handler */
241         for (cmd = cachefiles_proc_cmds; cmd->name[0]; cmd++)
242                 if (strcmp(cmd->name, data) == 0)
243                         goto found_command;
244
245 error:
246         kfree(data);
247         _leave(" = %d", ret);
248         return ret;
249
250 found_command:
251         mutex_lock(&file->f_dentry->d_inode->i_mutex);
252
253         ret = -EIO;
254         if (!test_bit(CACHEFILES_DEAD, &cache->flags))
255                 ret = cmd->handler(cache, args);
256
257         mutex_unlock(&file->f_dentry->d_inode->i_mutex);
258
259         if (ret == 0)
260                 ret = datalen;
261         goto error;
262 }
263
264 /*****************************************************************************/
265 /*
266  * give a range error for cache space constraints
267  * - can be tail-called
268  */
269 static int cachefiles_proc_range_error(struct cachefiles_cache *cache, char *args)
270 {
271         kerror("Free space limits must be in range"
272                " 0%%<=bstop<bcull<brun<100%%");
273
274         return -EINVAL;
275 }
276
277 /*****************************************************************************/
278 /*
279  * set the percentage of blocks at which to stop culling
280  * - command: "brun <N>%"
281  */
282 static int cachefiles_proc_brun(struct cachefiles_cache *cache, char *args)
283 {
284         unsigned long brun;
285
286         _enter(",%s", args);
287
288         if (!*args)
289                 return -EINVAL;
290
291         brun = simple_strtoul(args, &args, 10);
292         if (args[0] != '%' || args[1] != '\0')
293                 return -EINVAL;
294
295         if (brun <= cache->bcull_percent || brun >= 100)
296                 return cachefiles_proc_range_error(cache, args);
297
298         cache->brun_percent = brun;
299         return 0;
300 }
301
302 /*****************************************************************************/
303 /*
304  * set the percentage of blocks at which to start culling
305  * - command: "bcull <N>%"
306  */
307 static int cachefiles_proc_bcull(struct cachefiles_cache *cache, char *args)
308 {
309         unsigned long bcull;
310
311         _enter(",%s", args);
312
313         if (!*args)
314                 return -EINVAL;
315
316         bcull = simple_strtoul(args, &args, 10);
317         if (args[0] != '%' || args[1] != '\0')
318                 return -EINVAL;
319
320         if (bcull <= cache->bstop_percent || bcull >= cache->brun_percent)
321                 return cachefiles_proc_range_error(cache, args);
322
323         cache->bcull_percent = bcull;
324         return 0;
325 }
326
327 /*****************************************************************************/
328 /*
329  * set the percentage of blocks at which to stop allocating
330  * - command: "bstop <N>%"
331  */
332 static int cachefiles_proc_bstop(struct cachefiles_cache *cache, char *args)
333 {
334         unsigned long bstop;
335
336         _enter(",%s", args);
337
338         if (!*args)
339                 return -EINVAL;
340
341         bstop = simple_strtoul(args, &args, 10);
342         if (args[0] != '%' || args[1] != '\0')
343                 return -EINVAL;
344
345         if (bstop < 0 || bstop >= cache->bcull_percent)
346                 return cachefiles_proc_range_error(cache, args);
347
348         cache->bstop_percent = bstop;
349         return 0;
350 }
351
352 /*****************************************************************************/
353 /*
354  * set the cache directory
355  * - command: "dir <name>"
356  */
357 static int cachefiles_proc_dir(struct cachefiles_cache *cache, char *args)
358 {
359         char *dir;
360
361         _enter(",%s", args);
362
363         if (!*args) {
364                 kerror("Empty directory specified");
365                 return -EINVAL;
366         }
367
368         if (cache->rootdirname) {
369                 kerror("Second cache directory specified");
370                 return -EEXIST;
371         }
372
373         dir = kstrdup(args, GFP_KERNEL);
374         if (!dir)
375                 return -ENOMEM;
376
377         cache->rootdirname = dir;
378         return 0;
379 }
380
381 /*****************************************************************************/
382 /*
383  * set the cache tag
384  * - command: "tag <name>"
385  */
386 static int cachefiles_proc_tag(struct cachefiles_cache *cache, char *args)
387 {
388         char *tag;
389
390         _enter(",%s", args);
391
392         if (!*args) {
393                 kerror("Empty tag specified");
394                 return -EINVAL;
395         }
396
397         if (cache->tag)
398                 return -EEXIST;
399
400         tag = kstrdup(args, GFP_KERNEL);
401         if (!tag)
402                 return -ENOMEM;
403
404         cache->tag = tag;
405         return 0;
406 }
407
408 /*****************************************************************************/
409 /*
410  * request a node in the cache be culled
411  * - command: "cull <dirfd> <name>"
412  */
413 static int cachefiles_proc_cull(struct cachefiles_cache *cache, char *args)
414 {
415         struct dentry *dir;
416         struct file *dirfile;
417         int dirfd, fput_needed, ret;
418
419         _enter(",%s", args);
420
421         dirfd = simple_strtoul(args, &args, 0);
422
423         if (!args || !isspace(*args))
424                 goto inval;
425
426         while (isspace(*args))
427                 args++;
428
429         if (!*args)
430                 goto inval;
431
432         if (strchr(args, '/'))
433                 goto inval;
434
435         if (!test_bit(CACHEFILES_READY, &cache->flags)) {
436                 kerror("cull applied to unready cache");
437                 return -EIO;
438         }
439
440         if (test_bit(CACHEFILES_DEAD, &cache->flags)) {
441                 kerror("cull applied to dead cache");
442                 return -EIO;
443         }
444
445         /* extract the directory dentry from the fd */
446         dirfile = fget_light(dirfd, &fput_needed);
447         if (!dirfile) {
448                 kerror("cull dirfd not open");
449                 return -EBADF;
450         }
451
452         dir = dget(dirfile->f_dentry);
453         fput_light(dirfile, fput_needed);
454         dirfile = NULL;
455
456         if (!S_ISDIR(dir->d_inode->i_mode))
457                 goto notdir;
458
459         ret = cachefiles_cull(cache, dir, args);
460
461         dput(dir);
462         _leave(" = %d", ret);
463         return ret;
464
465 notdir:
466         dput(dir);
467         kerror("cull command requires dirfd to be a directory");
468         return -ENOTDIR;
469
470 inval:
471         kerror("cull command requires dirfd and filename");
472         return -EINVAL;
473 }
474
475 /*****************************************************************************/
476 /*
477  * set debugging mode
478  * - command: "debug <mask>"
479  */
480 static int cachefiles_proc_debug(struct cachefiles_cache *cache, char *args)
481 {
482         unsigned long mask;
483
484         _enter(",%s", args);
485
486         mask = simple_strtoul(args, &args, 0);
487
488         if (!args || !isspace(*args))
489                 goto inval;
490
491         cachefiles_debug = mask;
492         _leave(" = 0");
493         return 0;
494
495 inval:
496         kerror("debug command requires mask");
497         return -EINVAL;
498 }