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