This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / fs / rcfs / magic.c
1 /* 
2  * fs/rcfs/magic.c 
3  *
4  * Copyright (C) Shailabh Nagar,      IBM Corp. 2004
5  *           (C) Vivek Kashyap,       IBM Corp. 2004
6  *           (C) Chandra Seetharaman, IBM Corp. 2004
7  *           (C) Hubertus Franke,     IBM Corp. 2004
8  * 
9  * File operations for common magic files in rcfs, 
10  * the user interface for CKRM. 
11  * 
12  * 
13  * Latest version, more details at http://ckrm.sf.net
14  * 
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 2 of the License, or
18  * (at your option) any later version.
19  *
20  */
21
22 /* Changes
23  *
24  * 23 Apr 2004
25  *        Created from code kept earlier in fs/rcfs/magic_*.c
26  *
27  */
28
29 #include <linux/module.h>
30 #include <linux/fs.h>
31 #include <linux/namei.h>
32 #include <linux/namespace.h>
33 #include <linux/dcache.h>
34 #include <linux/seq_file.h>
35 #include <linux/init.h>
36 #include <linux/string.h>
37 #include <linux/smp_lock.h>
38 #include <linux/parser.h>
39 #include <asm/uaccess.h>
40
41 #include <linux/rcfs.h>
42
43 /******************************************************
44  * Macros
45  *
46  * generic macros to assist in writing magic fileops
47  *
48  *****************************************************/
49
50 #define MAGIC_SHOW(FUNC)                                               \
51 static int                                                             \
52 FUNC ## _show(struct seq_file *s, void *v)                             \
53 {                                                                      \
54         int rc=0;                                                      \
55         ssize_t precnt;                                                \
56         ckrm_core_class_t *core ;                                      \
57                                                                        \
58         core = (ckrm_core_class_t *)                                   \
59                 (((struct rcfs_inode_info *)s->private)->core);        \
60                                                                        \
61         if (!ckrm_is_core_valid(core)) {                               \
62                 return -EINVAL;                                        \
63         }                                                              \
64         precnt = s->count ;                                            \
65         if (core->classtype->show_ ## FUNC)                            \
66                 rc = (* core->classtype->show_ ## FUNC)(core, s);      \
67                                                                        \
68         if (s->count == precnt)                                        \
69                 seq_printf(s, "No data to display\n");                 \
70         return rc;                                                     \
71 };
72
73 #define MAGIC_OPEN(FUNC)                                               \
74 static int                                                             \
75 FUNC ## _open(struct inode *inode, struct file *file)                  \
76 {                                                                      \
77         struct rcfs_inode_info *ri;                                    \
78         int ret=-EINVAL;                                               \
79                                                                        \
80         if (file->f_dentry && file->f_dentry->d_parent) {              \
81                                                                        \
82                 ri = RCFS_I(file->f_dentry->d_parent->d_inode);        \
83                 ret = single_open(file,FUNC ## _show, (void *)ri);     \
84         }                                                              \
85         return ret;                                                    \
86 }
87
88 #define MAGIC_CLOSE(FUNC)                                              \
89 static int                                                             \
90 FUNC ## _close(struct inode *inode, struct file *file)                 \
91 {                                                                      \
92         return single_release(inode,file);                             \
93 }
94
95 #define MAGIC_PARSE(FUNC)                                              \
96 static int                                                             \
97 FUNC ## _parse(char *options, char **resstr, char **otherstr)          \
98 {                                                                      \
99         char *p;                                                       \
100         *resstr = NULL;                                                \
101                                                                        \
102         if (!options)                                                  \
103                 return -EINVAL;                                        \
104                                                                        \
105         while ((p = strsep(&options, ",")) != NULL) {                  \
106                 substring_t args[MAX_OPT_ARGS];                        \
107                 int token;                                             \
108                                                                        \
109                 if (!*p)                                               \
110                         continue;                                      \
111                                                                        \
112                 token = match_token(p, FUNC##_tokens, args);           \
113                 switch (token) {                                       \
114                 case FUNC ## _res_type:                                \
115                         *resstr = match_strdup(args);                  \
116                         break;                                         \
117                 case FUNC ## _str:                                     \
118                         *otherstr = match_strdup(args);                \
119                         break;                                         \
120                 default:                                               \
121                         return -EINVAL;                                \
122                 }                                                      \
123         }                                                              \
124         if (*resstr)                                                   \
125                 return 0;                                              \
126         return -EINVAL;                                                \
127 }
128
129 #define MAGIC_WRITE(FUNC,CLSTYPEFUN)                                   \
130 static ssize_t                                                         \
131 FUNC ## _write(struct file *file, const char __user *buf,              \
132                            size_t count, loff_t *ppos)                 \
133 {                                                                      \
134         struct rcfs_inode_info *ri =                                   \
135                 RCFS_I(file->f_dentry->d_parent->d_inode);             \
136         char *optbuf, *otherstr=NULL, *resname=NULL;                   \
137         int done, rc = 0;                                              \
138         ckrm_core_class_t *core ;                                      \
139                                                                        \
140         core = ri->core;                                               \
141         if (!ckrm_is_core_valid(core))                                 \
142                 return -EINVAL;                                        \
143                                                                        \
144         if ((ssize_t) count < 0                                        \
145             || (ssize_t) count > FUNC ## _max_input_size)              \
146                 return -EINVAL;                                        \
147                                                                        \
148         if (!access_ok(VERIFY_READ, buf, count))                       \
149                 return -EFAULT;                                        \
150                                                                        \
151         down(&(ri->vfs_inode.i_sem));                                  \
152                                                                        \
153         optbuf = kmalloc(FUNC ## _max_input_size, GFP_KERNEL);         \
154         __copy_from_user(optbuf, buf, count);                          \
155         if (optbuf[count-1] == '\n')                                   \
156                 optbuf[count-1]='\0';                                  \
157                                                                        \
158         done = FUNC ## _parse(optbuf, &resname, &otherstr);            \
159                                                                        \
160         if (!done) {                                                   \
161                 printk(KERN_ERR "Error parsing FUNC \n");              \
162                 goto FUNC ## _write_out;                               \
163         }                                                              \
164                                                                        \
165         if (core->classtype-> CLSTYPEFUN) {                            \
166                 rc = (*core->classtype->CLSTYPEFUN)                    \
167                         (core, resname, otherstr);                     \
168                 if (rc) {                                              \
169                         printk(KERN_ERR "FUNC_write: CLSTYPEFUN error\n");   \
170                         goto FUNC ## _write_out;                       \
171                 }                                                      \
172         }                                                              \
173                                                                        \
174 FUNC ## _write_out:                                                    \
175         up(&(ri->vfs_inode.i_sem));                                    \
176         kfree(optbuf);                                                 \
177         kfree(otherstr);                                               \
178         kfree(resname);                                                \
179         return rc ? rc : count;                                        \
180 }
181
182 #define MAGIC_RD_FILEOPS(FUNC)                                         \
183 struct file_operations FUNC ## _fileops = {                            \
184         .open           = FUNC ## _open,                               \
185         .read           = seq_read,                                    \
186         .llseek         = seq_lseek,                                   \
187         .release        = FUNC ## _close,                              \
188 };                                                                     \
189 EXPORT_SYMBOL(FUNC ## _fileops);
190
191 #define MAGIC_RDWR_FILEOPS(FUNC)                                       \
192 struct file_operations FUNC ## _fileops = {                            \
193         .open           = FUNC ## _open,                               \
194         .read           = seq_read,                                    \
195         .llseek         = seq_lseek,                                   \
196         .release        = FUNC ## _close,                              \
197         .write          = FUNC ## _write,                              \
198 };                                                                     \
199 EXPORT_SYMBOL(FUNC ## _fileops);
200
201 /******************************************************************************
202  * Target
203  *
204  * pseudo file for manually reclassifying members to a class
205  *
206  *****************************************************************************/
207
208 #define TARGET_MAX_INPUT_SIZE 100
209
210 static ssize_t
211 target_write(struct file *file, const char __user * buf,
212              size_t count, loff_t * ppos)
213 {
214         struct rcfs_inode_info *ri = RCFS_I(file->f_dentry->d_inode);
215         char *optbuf;
216         int rc = -EINVAL;
217         ckrm_classtype_t *clstype;
218
219         if ((ssize_t) count < 0 || (ssize_t) count > TARGET_MAX_INPUT_SIZE)
220                 return -EINVAL;
221
222         if (!access_ok(VERIFY_READ, buf, count))
223                 return -EFAULT;
224
225         down(&(ri->vfs_inode.i_sem));
226
227         optbuf = kmalloc(TARGET_MAX_INPUT_SIZE, GFP_KERNEL);
228         __copy_from_user(optbuf, buf, count);
229         if (optbuf[count - 1] == '\n')
230                 optbuf[count - 1] = '\0';
231
232         clstype = ri->core->classtype;
233         if (clstype->forced_reclassify)
234                 rc = (*clstype->forced_reclassify) (ri->core, optbuf);
235
236         up(&(ri->vfs_inode.i_sem));
237         kfree(optbuf);
238         return (!rc ? count : rc);
239
240 }
241
242 struct file_operations target_fileops = {
243         .write = target_write,
244 };
245
246 EXPORT_SYMBOL(target_fileops);
247
248 /******************************************************************************
249  * Config
250  *
251  * Set/get configuration parameters of a class. 
252  *
253  *****************************************************************************/
254
255 /* Currently there are no per-class config parameters defined.
256  * Use existing code as a template
257  */
258
259 #define config_max_input_size  300
260
261 enum config_token_t {
262         config_str, config_res_type, config_err
263 };
264
265 static match_table_t config_tokens = {
266         {config_res_type, "res=%s"},
267         {config_str, "config=%s"},
268         {config_err, NULL},
269 };
270
271 MAGIC_PARSE(config);
272 MAGIC_WRITE(config, set_config);
273 MAGIC_SHOW(config);
274 MAGIC_OPEN(config);
275 MAGIC_CLOSE(config);
276
277 MAGIC_RDWR_FILEOPS(config);
278
279 /******************************************************************************
280  * Members
281  *
282  * List members of a class
283  *
284  *****************************************************************************/
285
286 MAGIC_SHOW(members);
287 MAGIC_OPEN(members);
288 MAGIC_CLOSE(members);
289
290 MAGIC_RD_FILEOPS(members);
291
292 /******************************************************************************
293  * Stats
294  *
295  * Get/reset class statistics
296  * No standard set of stats defined. Each resource controller chooses
297  * its own set of statistics to maintain and export.
298  *
299  *****************************************************************************/
300
301 #define stats_max_input_size  50
302
303 enum stats_token_t {
304         stats_res_type, stats_str, stats_err
305 };
306
307 static match_table_t stats_tokens = {
308         {stats_res_type, "res=%s"},
309         {stats_str, NULL},
310         {stats_err, NULL},
311 };
312
313 MAGIC_PARSE(stats);
314 MAGIC_WRITE(stats, reset_stats);
315 MAGIC_SHOW(stats);
316 MAGIC_OPEN(stats);
317 MAGIC_CLOSE(stats);
318
319 MAGIC_RDWR_FILEOPS(stats);
320
321 /******************************************************************************
322  * Shares
323  *
324  * Set/get shares of a taskclass.
325  * Share types and semantics are defined by rcfs and ckrm core 
326  * 
327  *****************************************************************************/
328
329 #define SHARES_MAX_INPUT_SIZE  300
330
331 /* The enums for the share types should match the indices expected by
332    array parameter to ckrm_set_resshare */
333
334 /* Note only the first NUM_SHAREVAL enums correspond to share types,
335    the remaining ones are for token matching purposes */
336
337 enum share_token_t {
338         MY_GUAR, MY_LIM, TOT_GUAR, MAX_LIM, SHARE_RES_TYPE, SHARE_ERR
339 };
340
341 /* Token matching for parsing input to this magic file */
342 static match_table_t shares_tokens = {
343         {SHARE_RES_TYPE, "res=%s"},
344         {MY_GUAR, "guarantee=%d"},
345         {MY_LIM, "limit=%d"},
346         {TOT_GUAR, "total_guarantee=%d"},
347         {MAX_LIM, "max_limit=%d"},
348         {SHARE_ERR, NULL}
349 };
350
351 static int
352 shares_parse(char *options, char **resstr, struct ckrm_shares *shares)
353 {
354         char *p;
355         int option;
356
357         if (!options)
358                 return 1;
359
360         while ((p = strsep(&options, ",")) != NULL) {
361
362                 substring_t args[MAX_OPT_ARGS];
363                 int token;
364
365                 if (!*p)
366                         continue;
367
368                 token = match_token(p, shares_tokens, args);
369                 switch (token) {
370                 case SHARE_RES_TYPE:
371                         *resstr = match_strdup(args);
372                         break;
373                 case MY_GUAR:
374                         if (match_int(args, &option))
375                                 return 0;
376                         shares->my_guarantee = option;
377                         break;
378                 case MY_LIM:
379                         if (match_int(args, &option))
380                                 return 0;
381                         shares->my_limit = option;
382                         break;
383                 case TOT_GUAR:
384                         if (match_int(args, &option))
385                                 return 0;
386                         shares->total_guarantee = option;
387                         break;
388                 case MAX_LIM:
389                         if (match_int(args, &option))
390                                 return 0;
391                         shares->max_limit = option;
392                         break;
393                 default:
394                         return 0;
395                 }
396
397         }
398         return 1;
399 }
400
401 static ssize_t
402 shares_write(struct file *file, const char __user * buf,
403              size_t count, loff_t * ppos)
404 {
405         struct inode *inode = file->f_dentry->d_inode;
406         struct rcfs_inode_info *ri;
407         char *optbuf;
408         int rc = 0;
409         struct ckrm_core_class *core;
410         int done;
411         char *resname = NULL;
412
413         struct ckrm_shares newshares = {
414                 CKRM_SHARE_UNCHANGED,
415                 CKRM_SHARE_UNCHANGED,
416                 CKRM_SHARE_UNCHANGED,
417                 CKRM_SHARE_UNCHANGED,
418                 CKRM_SHARE_UNCHANGED,
419                 CKRM_SHARE_UNCHANGED
420         };
421
422         if ((ssize_t) count < 0 || (ssize_t) count > SHARES_MAX_INPUT_SIZE)
423                 return -EINVAL;
424
425         if (!access_ok(VERIFY_READ, buf, count))
426                 return -EFAULT;
427
428         ri = RCFS_I(file->f_dentry->d_parent->d_inode);
429
430         if (!ri || !ckrm_is_core_valid((ckrm_core_class_t *) (ri->core))) {
431                 printk(KERN_ERR "shares_write: Error accessing core class\n");
432                 return -EFAULT;
433         }
434
435         down(&inode->i_sem);
436
437         core = ri->core;
438         optbuf = kmalloc(SHARES_MAX_INPUT_SIZE, GFP_KERNEL);
439         if (!optbuf) {
440                 up(&inode->i_sem);
441                 return -ENOMEM;
442         }
443
444         __copy_from_user(optbuf, buf, count);
445         if (optbuf[count - 1] == '\n')
446                 optbuf[count - 1] = '\0';
447
448         done = shares_parse(optbuf, &resname, &newshares);
449         if (!done) {
450                 printk(KERN_ERR "Error parsing shares\n");
451                 rc = -EINVAL;
452                 goto write_out;
453         }
454
455         if (core->classtype->set_shares) {
456                 rc = (*core->classtype->set_shares) (core, resname, &newshares);
457                 if (rc) {
458                         printk(KERN_ERR
459                                "shares_write: resctlr share set error\n");
460                         goto write_out;
461                 }
462         }
463
464         printk(KERN_ERR "Set %s shares to %d %d %d %d\n",
465                resname,
466                newshares.my_guarantee,
467                newshares.my_limit,
468                newshares.total_guarantee, newshares.max_limit);
469
470         rc = count;
471
472       write_out:
473
474         up(&inode->i_sem);
475         kfree(optbuf);
476         kfree(resname);
477         return rc;
478 }
479
480 MAGIC_SHOW(shares);
481 MAGIC_OPEN(shares);
482 MAGIC_CLOSE(shares);
483
484 MAGIC_RDWR_FILEOPS(shares);
485
486 /*
487  * magic file creation/deletion
488  *
489  */
490
491 int rcfs_clear_magic(struct dentry *parent)
492 {
493         struct dentry *mftmp, *mfdentry;
494
495         list_for_each_entry_safe(mfdentry, mftmp, &parent->d_subdirs, d_child) {
496
497                 if (!rcfs_is_magic(mfdentry))
498                         continue;
499
500                 if (rcfs_delete_internal(mfdentry))
501                         printk(KERN_ERR
502                                "rcfs_clear_magic: error deleting one\n");
503         }
504
505         return 0;
506
507 }
508
509 EXPORT_SYMBOL(rcfs_clear_magic);
510
511 int rcfs_create_magic(struct dentry *parent, struct rcfs_magf magf[], int count)
512 {
513         int i;
514         struct dentry *mfdentry;
515
516         for (i = 0; i < count; i++) {
517                 mfdentry = rcfs_create_internal(parent, &magf[i], 0);
518                 if (IS_ERR(mfdentry)) {
519                         rcfs_clear_magic(parent);
520                         return -ENOMEM;
521                 }
522                 RCFS_I(mfdentry->d_inode)->core = RCFS_I(parent->d_inode)->core;
523                 mfdentry->d_fsdata = &RCFS_IS_MAGIC;
524                 if (magf[i].i_fop)
525                         mfdentry->d_inode->i_fop = magf[i].i_fop;
526                 if (magf[i].i_op)
527                         mfdentry->d_inode->i_op = magf[i].i_op;
528         }
529         return 0;
530 }
531
532 EXPORT_SYMBOL(rcfs_create_magic);