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.
12 * Latest version, more details at http://ckrm.sf.net
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
24 * Created from code kept earlier in fs/rcfs/magic_*.c
27 #include <linux/module.h>
29 #include <linux/namei.h>
30 #include <linux/namespace.h>
31 #include <linux/dcache.h>
32 #include <linux/seq_file.h>
33 #include <linux/init.h>
34 #include <linux/string.h>
35 #include <linux/smp_lock.h>
36 #include <linux/parser.h>
37 #include <asm/uaccess.h>
39 #include <linux/rcfs.h>
44 * generic macros to assist in writing magic fileops
48 #define MAGIC_SHOW(FUNC) \
50 FUNC ## _show(struct seq_file *s, void *v) \
54 ckrm_core_class_t *core ; \
56 core = (ckrm_core_class_t *) \
57 (((struct rcfs_inode_info *)s->private)->core); \
59 if (!ckrm_is_core_valid(core)) { \
63 if (core->classtype->show_ ## FUNC) \
64 rc = (* core->classtype->show_ ## FUNC)(core, s); \
66 if (s->count == precnt) \
67 seq_printf(s, "No data to display\n"); \
71 #define MAGIC_OPEN(FUNC) \
73 FUNC ## _open(struct inode *inode, struct file *file) \
75 struct rcfs_inode_info *ri; \
78 if (file->f_dentry && file->f_dentry->d_parent) { \
80 ri = RCFS_I(file->f_dentry->d_parent->d_inode); \
81 ret = single_open(file,FUNC ## _show, (void *)ri); \
86 #define MAGIC_CLOSE(FUNC) \
88 FUNC ## _close(struct inode *inode, struct file *file) \
90 return single_release(inode,file); \
93 #define MAGIC_PARSE(FUNC) \
95 FUNC ## _parse(char *options, char **resstr, char **otherstr) \
103 while ((p = strsep(&options, ",")) != NULL) { \
104 substring_t args[MAX_OPT_ARGS]; \
110 token = match_token(p, FUNC##_tokens, args); \
112 case FUNC ## _res_type: \
113 *resstr = match_strdup(args); \
114 if (!strcmp(#FUNC, "config")) { \
115 char *str = p + strlen(p) + 1; \
116 *otherstr = kmalloc(strlen(str) + 1, \
118 if (*otherstr == NULL) { \
123 strcpy(*otherstr, str); \
129 *otherstr = match_strdup(args); \
135 return (*resstr != NULL); \
138 #define MAGIC_WRITE(FUNC,CLSTYPEFUN) \
140 FUNC ## _write(struct file *file, const char __user *buf, \
141 size_t count, loff_t *ppos) \
143 struct rcfs_inode_info *ri = \
144 RCFS_I(file->f_dentry->d_parent->d_inode); \
145 char *optbuf, *otherstr=NULL, *resname=NULL; \
147 ckrm_core_class_t *core ; \
150 if (!ckrm_is_core_valid(core)) \
153 if ((ssize_t) count < 0 \
154 || (ssize_t) count > FUNC ## _max_input_size) \
157 if (!access_ok(VERIFY_READ, buf, count)) \
160 down(&(ri->vfs_inode.i_sem)); \
162 optbuf = kmalloc(FUNC ## _max_input_size, GFP_KERNEL); \
163 __copy_from_user(optbuf, buf, count); \
164 if (optbuf[count-1] == '\n') \
165 optbuf[count-1]='\0'; \
167 done = FUNC ## _parse(optbuf, &resname, &otherstr); \
170 printk(KERN_ERR "Error parsing FUNC \n"); \
171 goto FUNC ## _write_out; \
174 if (core->classtype-> CLSTYPEFUN) { \
175 rc = (*core->classtype->CLSTYPEFUN) \
176 (core, resname, otherstr); \
178 printk(KERN_ERR "FUNC_write: CLSTYPEFUN error\n"); \
179 goto FUNC ## _write_out; \
183 FUNC ## _write_out: \
184 up(&(ri->vfs_inode.i_sem)); \
188 return rc ? rc : count; \
191 #define MAGIC_RD_FILEOPS(FUNC) \
192 struct file_operations FUNC ## _fileops = { \
193 .open = FUNC ## _open, \
195 .llseek = seq_lseek, \
196 .release = FUNC ## _close, \
198 EXPORT_SYMBOL(FUNC ## _fileops);
200 #define MAGIC_RDWR_FILEOPS(FUNC) \
201 struct file_operations FUNC ## _fileops = { \
202 .open = FUNC ## _open, \
204 .llseek = seq_lseek, \
205 .release = FUNC ## _close, \
206 .write = FUNC ## _write, \
208 EXPORT_SYMBOL(FUNC ## _fileops);
211 * Shared function used by Members / Reclassify
214 #define MEMBERS_MAX_INPUT_SIZE 100
217 members_reclassify_write(struct file *file, const char __user * buf,
218 size_t count, loff_t * ppos, int manual)
220 struct rcfs_inode_info *ri = RCFS_I(file->f_dentry->d_inode);
223 ckrm_classtype_t *clstype;
225 if ((ssize_t) count < 0 || (ssize_t) count > MEMBERS_MAX_INPUT_SIZE)
227 if (!access_ok(VERIFY_READ, buf, count))
229 down(&(ri->vfs_inode.i_sem));
230 optbuf = kmalloc(MEMBERS_MAX_INPUT_SIZE, GFP_KERNEL);
231 __copy_from_user(optbuf, buf, count);
232 if (optbuf[count - 1] == '\n')
233 optbuf[count - 1] = '\0';
234 clstype = ri->core->classtype;
235 if (clstype->forced_reclassify)
236 rc = (*clstype->forced_reclassify) (manual ? ri->core: NULL, optbuf);
237 up(&(ri->vfs_inode.i_sem));
239 return (!rc ? count : rc);
246 * pseudo file for reclassification of an object through CE
250 reclassify_write(struct file *file, const char __user * buf,
251 size_t count, loff_t * ppos)
253 return members_reclassify_write(file,buf,count,ppos,0);
256 struct file_operations reclassify_fileops = {
257 .write = reclassify_write,
260 EXPORT_SYMBOL_GPL(reclassify_fileops);
265 * Set/get configuration parameters of a class.
269 * Currently there are no per-class config parameters defined.
270 * Use existing code as a template
273 #define config_max_input_size 300
275 enum config_token_t {
276 config_str, config_res_type, config_err
279 static match_table_t config_tokens = {
280 {config_res_type, "res=%s"},
285 MAGIC_WRITE(config, set_config);
290 MAGIC_RDWR_FILEOPS(config);
295 * List members of a class
300 MAGIC_CLOSE(members);
303 members_write(struct file *file, const char __user * buf,
304 size_t count, loff_t * ppos)
306 return members_reclassify_write(file,buf,count,ppos,1);
309 MAGIC_RDWR_FILEOPS(members);
314 * Get/reset class statistics
315 * No standard set of stats defined. Each resource controller chooses
316 * its own set of statistics to maintain and export.
319 #define stats_max_input_size 50
322 stats_res_type, stats_str, stats_err
325 static match_table_t stats_tokens = {
326 {stats_res_type, "res=%s"},
332 MAGIC_WRITE(stats, reset_stats);
337 MAGIC_RDWR_FILEOPS(stats);
342 * Set/get shares of a taskclass.
343 * Share types and semantics are defined by rcfs and ckrm core
346 #define SHARES_MAX_INPUT_SIZE 300
349 * The enums for the share types should match the indices expected by
350 * array parameter to ckrm_set_resshare
352 * Note only the first NUM_SHAREVAL enums correspond to share types,
353 * the remaining ones are for token matching purposes
357 MY_GUAR, MY_LIM, TOT_GUAR, MAX_LIM, SHARE_RES_TYPE, SHARE_ERR
360 /* Token matching for parsing input to this magic file */
361 static match_table_t shares_tokens = {
362 {SHARE_RES_TYPE, "res=%s"},
363 {MY_GUAR, "guarantee=%d"},
364 {MY_LIM, "limit=%d"},
365 {TOT_GUAR, "total_guarantee=%d"},
366 {MAX_LIM, "max_limit=%d"},
371 shares_parse(char *options, char **resstr, struct ckrm_shares *shares)
378 while ((p = strsep(&options, ",")) != NULL) {
379 substring_t args[MAX_OPT_ARGS];
384 token = match_token(p, shares_tokens, args);
387 *resstr = match_strdup(args);
390 if (match_int(args, &option))
392 shares->my_guarantee = option;
395 if (match_int(args, &option))
397 shares->my_limit = option;
400 if (match_int(args, &option))
402 shares->total_guarantee = option;
405 if (match_int(args, &option))
407 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;
426 char *resname = NULL;
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,
436 if ((ssize_t) count < 0 || (ssize_t) count > SHARES_MAX_INPUT_SIZE)
438 if (!access_ok(VERIFY_READ, buf, count))
440 ri = RCFS_I(file->f_dentry->d_parent->d_inode);
441 if (!ri || !ckrm_is_core_valid((ckrm_core_class_t *) (ri->core))) {
442 printk(KERN_ERR "shares_write: Error accessing core class\n");
447 optbuf = kmalloc(SHARES_MAX_INPUT_SIZE, GFP_KERNEL);
452 __copy_from_user(optbuf, buf, count);
453 if (optbuf[count - 1] == '\n')
454 optbuf[count - 1] = '\0';
455 done = shares_parse(optbuf, &resname, &newshares);
457 printk(KERN_ERR "Error parsing shares\n");
461 if (core->classtype->set_shares) {
462 rc = (*core->classtype->set_shares) (core, resname, &newshares);
465 "shares_write: resctlr share set error\n");
469 printk(KERN_ERR "Set %s shares to %d %d %d %d\n",
471 newshares.my_guarantee,
473 newshares.total_guarantee, newshares.max_limit);
487 MAGIC_RDWR_FILEOPS(shares);
490 * magic file creation/deletion
493 int rcfs_clear_magic(struct dentry *parent)
495 struct dentry *mftmp, *mfdentry;
497 list_for_each_entry_safe(mfdentry, mftmp, &parent->d_subdirs, d_child) {
498 if (!rcfs_is_magic(mfdentry))
500 if (rcfs_delete_internal(mfdentry))
502 "rcfs_clear_magic: error deleting one\n");
507 EXPORT_SYMBOL_GPL(rcfs_clear_magic);
509 int rcfs_create_magic(struct dentry *parent, struct rcfs_magf magf[], int count)
512 struct dentry *mfdentry;
514 for (i = 0; i < count; i++) {
515 mfdentry = rcfs_create_internal(parent, &magf[i], 0);
516 if (IS_ERR(mfdentry)) {
517 rcfs_clear_magic(parent);
520 RCFS_I(mfdentry->d_inode)->core = RCFS_I(parent->d_inode)->core;
521 mfdentry->d_fsdata = &RCFS_IS_MAGIC;
523 mfdentry->d_inode->i_fop = magf[i].i_fop;
525 mfdentry->d_inode->i_op = magf[i].i_op;
530 EXPORT_SYMBOL_GPL(rcfs_create_magic);