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
9 * File operations for common magic files in rcfs,
10 * the user interface for CKRM.
13 * Latest version, more details at http://ckrm.sf.net
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.
25 * Created from code kept earlier in fs/rcfs/magic_*.c
29 #include <linux/module.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>
42 #include <linux/rcfs.h>
47 /******************************************************
50 * generic macros to assist in writing magic fileops
52 *****************************************************/
55 #define MAGIC_SHOW(FUNC) \
57 FUNC ## _show(struct seq_file *s, void *v) \
60 ckrm_core_class_t *core ; \
62 core = (ckrm_core_class_t *) \
63 (((struct rcfs_inode_info *)s->private)->core); \
65 if (!ckrm_is_core_valid(core)) { \
69 if (core->classtype->show_ ## FUNC) \
70 rc = (* core->classtype->show_ ## FUNC)(core, s); \
76 #define MAGIC_OPEN(FUNC) \
78 FUNC ## _open(struct inode *inode, struct file *file) \
80 struct rcfs_inode_info *ri; \
83 if (file->f_dentry && file->f_dentry->d_parent) { \
85 ri = RCFS_I(file->f_dentry->d_parent->d_inode); \
86 ret = single_open(file,FUNC ## _show, (void *)ri); \
91 #define MAGIC_CLOSE(FUNC) \
93 FUNC ## _close(struct inode *inode, struct file *file) \
95 return single_release(inode,file); \
100 #define MAGIC_PARSE(FUNC) \
102 FUNC ## _parse(char *options, char **resstr, char **otherstr) \
109 while ((p = strsep(&options, ",")) != NULL) { \
110 substring_t args[MAX_OPT_ARGS]; \
116 token = match_token(p, FUNC##_tokens, args); \
118 case FUNC ## _res_type: \
119 *resstr = match_strdup(args); \
122 *otherstr = match_strdup(args); \
131 #define MAGIC_WRITE(FUNC,CLSTYPEFUN) \
133 FUNC ## _write(struct file *file, const char __user *buf, \
134 size_t count, loff_t *ppos) \
136 struct rcfs_inode_info *ri = \
137 RCFS_I(file->f_dentry->d_parent->d_inode); \
138 char *optbuf, *otherstr=NULL, *resname=NULL; \
140 ckrm_core_class_t *core ; \
143 if (!ckrm_is_core_valid(core)) \
146 if ((ssize_t) count < 0 \
147 || (ssize_t) count > FUNC ## _max_input_size) \
150 if (!access_ok(VERIFY_READ, buf, count)) \
153 down(&(ri->vfs_inode.i_sem)); \
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'; \
160 done = FUNC ## _parse(optbuf, &resname, &otherstr); \
163 printk(KERN_ERR "Error parsing FUNC \n"); \
164 goto FUNC ## _write_out; \
167 if (core->classtype-> CLSTYPEFUN) { \
168 rc = (*core->classtype->CLSTYPEFUN) \
169 (core, resname, otherstr); \
171 printk(KERN_ERR "FUNC_write: CLSTYPEFUN error\n"); \
172 goto FUNC ## _write_out; \
176 FUNC ## _write_out: \
177 up(&(ri->vfs_inode.i_sem)); \
181 return rc ? rc : count; \
185 #define MAGIC_RD_FILEOPS(FUNC) \
186 struct file_operations FUNC ## _fileops = { \
187 .open = FUNC ## _open, \
189 .llseek = seq_lseek, \
190 .release = FUNC ## _close, \
192 EXPORT_SYMBOL(FUNC ## _fileops);
195 #define MAGIC_RDWR_FILEOPS(FUNC) \
196 struct file_operations FUNC ## _fileops = { \
197 .open = FUNC ## _open, \
199 .llseek = seq_lseek, \
200 .release = FUNC ## _close, \
201 .write = FUNC ## _write, \
203 EXPORT_SYMBOL(FUNC ## _fileops);
206 /********************************************************************************
209 * pseudo file for manually reclassifying members to a class
211 *******************************************************************************/
213 #define TARGET_MAX_INPUT_SIZE 100
216 target_write(struct file *file, const char __user *buf,
217 size_t count, loff_t *ppos)
219 struct rcfs_inode_info *ri= RCFS_I(file->f_dentry->d_inode);
222 ckrm_classtype_t *clstype;
225 if ((ssize_t) count < 0 || (ssize_t) count > TARGET_MAX_INPUT_SIZE)
228 if (!access_ok(VERIFY_READ, buf, count))
231 down(&(ri->vfs_inode.i_sem));
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';
238 clstype = ri->core->classtype;
239 if (clstype->forced_reclassify)
240 rc = (* clstype->forced_reclassify)(ri->core,optbuf);
242 up(&(ri->vfs_inode.i_sem));
244 return !rc ? count : rc;
248 struct file_operations target_fileops = {
249 .write = target_write,
251 EXPORT_SYMBOL(target_fileops);
255 /********************************************************************************
258 * Set/get configuration parameters of a class.
260 *******************************************************************************/
262 /* Currently there are no per-class config parameters defined.
263 * Use existing code as a template
266 #define config_max_input_size 300
268 enum config_token_t {
269 config_str, config_res_type, config_err
272 static match_table_t config_tokens = {
273 {config_res_type,"res=%s"},
274 {config_str, "config=%s"},
280 MAGIC_WRITE(config,set_config);
285 MAGIC_RDWR_FILEOPS(config);
288 /********************************************************************************
291 * List members of a class
293 *******************************************************************************/
297 MAGIC_CLOSE(members);
299 MAGIC_RD_FILEOPS(members);
302 /********************************************************************************
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.
309 *******************************************************************************/
311 #define stats_max_input_size 50
314 stats_res_type, stats_str,stats_err
317 static match_table_t stats_tokens = {
318 {stats_res_type,"res=%s"},
325 MAGIC_WRITE(stats,reset_stats);
330 MAGIC_RDWR_FILEOPS(stats);
333 /********************************************************************************
336 * Set/get shares of a taskclass.
337 * Share types and semantics are defined by rcfs and ckrm core
339 *******************************************************************************/
342 #define SHARES_MAX_INPUT_SIZE 300
344 /* The enums for the share types should match the indices expected by
345 array parameter to ckrm_set_resshare */
347 /* Note only the first NUM_SHAREVAL enums correspond to share types,
348 the remaining ones are for token matching purposes */
351 MY_GUAR, MY_LIM, TOT_GUAR, MAX_LIM, SHARE_RES_TYPE, SHARE_ERR
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"},
366 shares_parse(char *options, char **resstr, struct ckrm_shares *shares)
374 while ((p = strsep(&options, ",")) != NULL) {
376 substring_t args[MAX_OPT_ARGS];
382 token = match_token(p, shares_tokens, args);
385 *resstr = match_strdup(args);
388 if (match_int(args, &option))
390 shares->my_guarantee = option;
393 if (match_int(args, &option))
395 shares->my_limit = option;
398 if (match_int(args, &option))
400 shares->total_guarantee = option;
403 if (match_int(args, &option))
405 shares->max_limit = option;
417 shares_write(struct file *file, const char __user *buf,
418 size_t count, loff_t *ppos)
420 struct inode *inode = file->f_dentry->d_inode;
421 struct rcfs_inode_info *ri;
424 struct ckrm_core_class *core;
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,
437 if ((ssize_t) count < 0 || (ssize_t) count > SHARES_MAX_INPUT_SIZE)
440 if (!access_ok(VERIFY_READ, buf, count))
443 ri = RCFS_I(file->f_dentry->d_parent->d_inode);
445 if (!ri || !ckrm_is_core_valid((ckrm_core_class_t *)(ri->core))) {
446 printk(KERN_ERR "shares_write: Error accessing core class\n");
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';
458 done = shares_parse(optbuf, &resname, &newshares);
460 printk(KERN_ERR "Error parsing shares\n");
465 if (core->classtype->set_shares) {
466 rc = (*core->classtype->set_shares)(core,resname,&newshares);
468 printk(KERN_ERR "shares_write: resctlr share set error\n");
473 printk(KERN_ERR "Set %s shares to %d %d %d %d\n",
475 newshares.my_guarantee,
477 newshares.total_guarantee,
478 newshares.max_limit);
495 MAGIC_RDWR_FILEOPS(shares);
500 * magic file creation/deletion
506 rcfs_clear_magic(struct dentry *parent)
508 struct dentry *mftmp, *mfdentry ;
510 list_for_each_entry_safe(mfdentry, mftmp, &parent->d_subdirs, d_child) {
512 if (!rcfs_is_magic(mfdentry))
515 if (rcfs_delete_internal(mfdentry))
516 printk(KERN_ERR "rcfs_clear_magic: error deleting one\n");
522 EXPORT_SYMBOL(rcfs_clear_magic);
526 rcfs_create_magic(struct dentry *parent, struct rcfs_magf magf[], int count)
529 struct dentry *mfdentry;
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);
537 RCFS_I(mfdentry->d_inode)->core = RCFS_I(parent->d_inode)->core;
538 mfdentry->d_fsdata = &RCFS_IS_MAGIC;
540 mfdentry->d_inode->i_fop = magf[i].i_fop;
542 mfdentry->d_inode->i_op = magf[i].i_op;
546 EXPORT_SYMBOL(rcfs_create_magic);