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 0;                                              \
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                         if (!strcmp(#FUNC, "config")) {                \
117                                 char *str = p + strlen(p) + 1;         \
118                                 *otherstr = kmalloc(strlen(str) + 1,   \
119                                                          GFP_KERNEL);  \
120                                 if (*otherstr == NULL) {               \
121                                         kfree(*resstr);                \
122                                         *resstr = NULL;                \
123                                         return 0;                      \
124                                 } else {                               \
125                                         strcpy(*otherstr, str);        \
126                                         return 1;                      \
127                                 }                                      \
128                         }                                              \
129                         break;                                         \
130                 case FUNC ## _str:                                     \
131                         *otherstr = match_strdup(args);                \
132                         break;                                         \
133                 default:                                               \
134                         return 0;                                      \
135                 }                                                      \
136         }                                                              \
137         return (*resstr != NULL);                                      \
138 }
139
140 #define MAGIC_WRITE(FUNC,CLSTYPEFUN)                                   \
141 static ssize_t                                                         \
142 FUNC ## _write(struct file *file, const char __user *buf,              \
143                            size_t count, loff_t *ppos)                 \
144 {                                                                      \
145         struct rcfs_inode_info *ri =                                   \
146                 RCFS_I(file->f_dentry->d_parent->d_inode);             \
147         char *optbuf, *otherstr=NULL, *resname=NULL;                   \
148         int done, rc = 0;                                              \
149         ckrm_core_class_t *core ;                                      \
150                                                                        \
151         core = ri->core;                                               \
152         if (!ckrm_is_core_valid(core))                                 \
153                 return -EINVAL;                                        \
154                                                                        \
155         if ((ssize_t) count < 0                                        \
156             || (ssize_t) count > FUNC ## _max_input_size)              \
157                 return -EINVAL;                                        \
158                                                                        \
159         if (!access_ok(VERIFY_READ, buf, count))                       \
160                 return -EFAULT;                                        \
161                                                                        \
162         down(&(ri->vfs_inode.i_sem));                                  \
163                                                                        \
164         optbuf = kmalloc(FUNC ## _max_input_size, GFP_KERNEL);         \
165         __copy_from_user(optbuf, buf, count);                          \
166         if (optbuf[count-1] == '\n')                                   \
167                 optbuf[count-1]='\0';                                  \
168                                                                        \
169         done = FUNC ## _parse(optbuf, &resname, &otherstr);            \
170                                                                        \
171         if (!done) {                                                   \
172                 printk(KERN_ERR "Error parsing FUNC \n");              \
173                 goto FUNC ## _write_out;                               \
174         }                                                              \
175                                                                        \
176         if (core->classtype-> CLSTYPEFUN) {                            \
177                 rc = (*core->classtype->CLSTYPEFUN)                    \
178                         (core, resname, otherstr);                     \
179                 if (rc) {                                              \
180                         printk(KERN_ERR "FUNC_write: CLSTYPEFUN error\n");   \
181                         goto FUNC ## _write_out;                       \
182                 }                                                      \
183         }                                                              \
184                                                                        \
185 FUNC ## _write_out:                                                    \
186         up(&(ri->vfs_inode.i_sem));                                    \
187         kfree(optbuf);                                                 \
188         kfree(otherstr);                                               \
189         kfree(resname);                                                \
190         return rc ? rc : count;                                        \
191 }
192
193 #define MAGIC_RD_FILEOPS(FUNC)                                         \
194 struct file_operations FUNC ## _fileops = {                            \
195         .open           = FUNC ## _open,                               \
196         .read           = seq_read,                                    \
197         .llseek         = seq_lseek,                                   \
198         .release        = FUNC ## _close,                              \
199 };                                                                     \
200 EXPORT_SYMBOL(FUNC ## _fileops);
201
202 #define MAGIC_RDWR_FILEOPS(FUNC)                                       \
203 struct file_operations FUNC ## _fileops = {                            \
204         .open           = FUNC ## _open,                               \
205         .read           = seq_read,                                    \
206         .llseek         = seq_lseek,                                   \
207         .release        = FUNC ## _close,                              \
208         .write          = FUNC ## _write,                              \
209 };                                                                     \
210 EXPORT_SYMBOL(FUNC ## _fileops);
211
212 /******************************************************************************
213  * Shared function used by Target / Reclassify
214  *
215  *
216  *****************************************************************************/
217
218 #define TARGET_MAX_INPUT_SIZE 100
219
220 static ssize_t
221 target_reclassify_write(struct file *file, const char __user * buf,
222                         size_t count, loff_t * ppos, int manual)
223 {
224         struct rcfs_inode_info *ri = RCFS_I(file->f_dentry->d_inode);
225         char *optbuf;
226         int rc = -EINVAL;
227         ckrm_classtype_t *clstype;
228
229         if ((ssize_t) count < 0 || (ssize_t) count > TARGET_MAX_INPUT_SIZE)
230                 return -EINVAL;
231
232         if (!access_ok(VERIFY_READ, buf, count))
233                 return -EFAULT;
234
235         down(&(ri->vfs_inode.i_sem));
236
237         optbuf = kmalloc(TARGET_MAX_INPUT_SIZE, GFP_KERNEL);
238         __copy_from_user(optbuf, buf, count);
239         if (optbuf[count - 1] == '\n')
240                 optbuf[count - 1] = '\0';
241
242         clstype = ri->core->classtype;
243         if (clstype->forced_reclassify)
244                 rc = (*clstype->forced_reclassify) (manual ? ri->core: NULL, optbuf);
245
246         up(&(ri->vfs_inode.i_sem));
247         kfree(optbuf);
248         return (!rc ? count : rc);
249
250 }
251
252 /******************************************************************************
253  * Target
254  *
255  * pseudo file for manually reclassifying members to a class
256  *
257  *****************************************************************************/
258
259 static ssize_t
260 target_write(struct file *file, const char __user * buf,
261              size_t count, loff_t * ppos)
262 {
263         return target_reclassify_write(file,buf,count,ppos,1);
264 }
265
266 struct file_operations target_fileops = {
267         .write = target_write,
268 };
269
270 EXPORT_SYMBOL(target_fileops);
271
272 /******************************************************************************
273  * Reclassify
274  *
275  * pseudo file for reclassification of an object through CE
276  *
277  *****************************************************************************/
278
279 static ssize_t
280 reclassify_write(struct file *file, const char __user * buf,
281                  size_t count, loff_t * ppos)
282 {
283         return target_reclassify_write(file,buf,count,ppos,0);
284 }
285
286 struct file_operations reclassify_fileops = {
287         .write = reclassify_write,
288 };
289
290 EXPORT_SYMBOL(reclassify_fileops);
291
292 /******************************************************************************
293  * Config
294  *
295  * Set/get configuration parameters of a class. 
296  *
297  *****************************************************************************/
298
299 /* Currently there are no per-class config parameters defined.
300  * Use existing code as a template
301  */
302
303 #define config_max_input_size  300
304
305 enum config_token_t {
306         config_str, config_res_type, config_err
307 };
308
309 static match_table_t config_tokens = {
310         {config_res_type, "res=%s"},
311         {config_err, NULL},
312 };
313
314 MAGIC_PARSE(config);
315 MAGIC_WRITE(config, set_config);
316 MAGIC_SHOW(config);
317 MAGIC_OPEN(config);
318 MAGIC_CLOSE(config);
319
320 MAGIC_RDWR_FILEOPS(config);
321
322 /******************************************************************************
323  * Members
324  *
325  * List members of a class
326  *
327  *****************************************************************************/
328
329 MAGIC_SHOW(members);
330 MAGIC_OPEN(members);
331 MAGIC_CLOSE(members);
332
333 MAGIC_RD_FILEOPS(members);
334
335 /******************************************************************************
336  * Stats
337  *
338  * Get/reset class statistics
339  * No standard set of stats defined. Each resource controller chooses
340  * its own set of statistics to maintain and export.
341  *
342  *****************************************************************************/
343
344 #define stats_max_input_size  50
345
346 enum stats_token_t {
347         stats_res_type, stats_str, stats_err
348 };
349
350 static match_table_t stats_tokens = {
351         {stats_res_type, "res=%s"},
352         {stats_str, NULL},
353         {stats_err, NULL},
354 };
355
356 MAGIC_PARSE(stats);
357 MAGIC_WRITE(stats, reset_stats);
358 MAGIC_SHOW(stats);
359 MAGIC_OPEN(stats);
360 MAGIC_CLOSE(stats);
361
362 MAGIC_RDWR_FILEOPS(stats);
363
364 /******************************************************************************
365  * Shares
366  *
367  * Set/get shares of a taskclass.
368  * Share types and semantics are defined by rcfs and ckrm core 
369  * 
370  *****************************************************************************/
371
372 #define SHARES_MAX_INPUT_SIZE  300
373
374 /* The enums for the share types should match the indices expected by
375    array parameter to ckrm_set_resshare */
376
377 /* Note only the first NUM_SHAREVAL enums correspond to share types,
378    the remaining ones are for token matching purposes */
379
380 enum share_token_t {
381         MY_GUAR, MY_LIM, TOT_GUAR, MAX_LIM, SHARE_RES_TYPE, SHARE_ERR
382 };
383
384 /* Token matching for parsing input to this magic file */
385 static match_table_t shares_tokens = {
386         {SHARE_RES_TYPE, "res=%s"},
387         {MY_GUAR, "guarantee=%d"},
388         {MY_LIM, "limit=%d"},
389         {TOT_GUAR, "total_guarantee=%d"},
390         {MAX_LIM, "max_limit=%d"},
391         {SHARE_ERR, NULL}
392 };
393
394 static int
395 shares_parse(char *options, char **resstr, struct ckrm_shares *shares)
396 {
397         char *p;
398         int option;
399
400         if (!options)
401                 return 1;
402
403         while ((p = strsep(&options, ",")) != NULL) {
404
405                 substring_t args[MAX_OPT_ARGS];
406                 int token;
407
408                 if (!*p)
409                         continue;
410
411                 token = match_token(p, shares_tokens, args);
412                 switch (token) {
413                 case SHARE_RES_TYPE:
414                         *resstr = match_strdup(args);
415                         break;
416                 case MY_GUAR:
417                         if (match_int(args, &option))
418                                 return 0;
419                         shares->my_guarantee = option;
420                         break;
421                 case MY_LIM:
422                         if (match_int(args, &option))
423                                 return 0;
424                         shares->my_limit = option;
425                         break;
426                 case TOT_GUAR:
427                         if (match_int(args, &option))
428                                 return 0;
429                         shares->total_guarantee = option;
430                         break;
431                 case MAX_LIM:
432                         if (match_int(args, &option))
433                                 return 0;
434                         shares->max_limit = option;
435                         break;
436                 default:
437                         return 0;
438                 }
439
440         }
441         return 1;
442 }
443
444 static ssize_t
445 shares_write(struct file *file, const char __user * buf,
446              size_t count, loff_t * ppos)
447 {
448         struct inode *inode = file->f_dentry->d_inode;
449         struct rcfs_inode_info *ri;
450         char *optbuf;
451         int rc = 0;
452         struct ckrm_core_class *core;
453         int done;
454         char *resname = NULL;
455
456         struct ckrm_shares newshares = {
457                 CKRM_SHARE_UNCHANGED,
458                 CKRM_SHARE_UNCHANGED,
459                 CKRM_SHARE_UNCHANGED,
460                 CKRM_SHARE_UNCHANGED,
461                 CKRM_SHARE_UNCHANGED,
462                 CKRM_SHARE_UNCHANGED
463         };
464
465         if ((ssize_t) count < 0 || (ssize_t) count > SHARES_MAX_INPUT_SIZE)
466                 return -EINVAL;
467
468         if (!access_ok(VERIFY_READ, buf, count))
469                 return -EFAULT;
470
471         ri = RCFS_I(file->f_dentry->d_parent->d_inode);
472
473         if (!ri || !ckrm_is_core_valid((ckrm_core_class_t *) (ri->core))) {
474                 printk(KERN_ERR "shares_write: Error accessing core class\n");
475                 return -EFAULT;
476         }
477
478         down(&inode->i_sem);
479
480         core = ri->core;
481         optbuf = kmalloc(SHARES_MAX_INPUT_SIZE, GFP_KERNEL);
482         if (!optbuf) {
483                 up(&inode->i_sem);
484                 return -ENOMEM;
485         }
486
487         __copy_from_user(optbuf, buf, count);
488         if (optbuf[count - 1] == '\n')
489                 optbuf[count - 1] = '\0';
490
491         done = shares_parse(optbuf, &resname, &newshares);
492         if (!done) {
493                 printk(KERN_ERR "Error parsing shares\n");
494                 rc = -EINVAL;
495                 goto write_out;
496         }
497
498         if (core->classtype->set_shares) {
499                 rc = (*core->classtype->set_shares) (core, resname, &newshares);
500                 if (rc) {
501                         printk(KERN_ERR
502                                "shares_write: resctlr share set error\n");
503                         goto write_out;
504                 }
505         }
506
507         printk(KERN_DEBUG "Set %s shares to %d %d %d %d\n",
508                resname,
509                newshares.my_guarantee,
510                newshares.my_limit,
511                newshares.total_guarantee, newshares.max_limit);
512
513         rc = count;
514
515       write_out:
516
517         up(&inode->i_sem);
518         kfree(optbuf);
519         kfree(resname);
520         return rc;
521 }
522
523 MAGIC_SHOW(shares);
524 MAGIC_OPEN(shares);
525 MAGIC_CLOSE(shares);
526
527 MAGIC_RDWR_FILEOPS(shares);
528
529 /*
530  * magic file creation/deletion
531  *
532  */
533
534 int rcfs_clear_magic(struct dentry *parent)
535 {
536         struct dentry *mftmp, *mfdentry;
537
538         list_for_each_entry_safe(mfdentry, mftmp, &parent->d_subdirs, d_child) {
539
540                 if (!rcfs_is_magic(mfdentry))
541                         continue;
542
543                 if (rcfs_delete_internal(mfdentry))
544                         printk(KERN_ERR
545                                "rcfs_clear_magic: error deleting one\n");
546         }
547
548         return 0;
549
550 }
551
552 EXPORT_SYMBOL(rcfs_clear_magic);
553
554 int rcfs_create_magic(struct dentry *parent, struct rcfs_magf magf[], int count)
555 {
556         int i;
557         struct dentry *mfdentry;
558
559         for (i = 0; i < count; i++) {
560                 mfdentry = rcfs_create_internal(parent, &magf[i], 0);
561                 if (IS_ERR(mfdentry)) {
562                         rcfs_clear_magic(parent);
563                         return -ENOMEM;
564                 }
565                 RCFS_I(mfdentry->d_inode)->core = RCFS_I(parent->d_inode)->core;
566                 mfdentry->d_fsdata = &RCFS_IS_MAGIC;
567                 if (magf[i].i_fop)
568                         mfdentry->d_inode->i_fop = magf[i].i_fop;
569                 if (magf[i].i_op)
570                         mfdentry->d_inode->i_op = magf[i].i_op;
571         }
572         return 0;
573 }
574
575 EXPORT_SYMBOL(rcfs_create_magic);