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 <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>
41 #include <linux/rcfs.h>
43 /******************************************************
46 * generic macros to assist in writing magic fileops
48 *****************************************************/
50 #define MAGIC_SHOW(FUNC) \
52 FUNC ## _show(struct seq_file *s, void *v) \
56 ckrm_core_class_t *core ; \
58 core = (ckrm_core_class_t *) \
59 (((struct rcfs_inode_info *)s->private)->core); \
61 if (!ckrm_is_core_valid(core)) { \
65 if (core->classtype->show_ ## FUNC) \
66 rc = (* core->classtype->show_ ## FUNC)(core, s); \
68 if (s->count == precnt) \
69 seq_printf(s, "No data to display\n"); \
73 #define MAGIC_OPEN(FUNC) \
75 FUNC ## _open(struct inode *inode, struct file *file) \
77 struct rcfs_inode_info *ri; \
80 if (file->f_dentry && file->f_dentry->d_parent) { \
82 ri = RCFS_I(file->f_dentry->d_parent->d_inode); \
83 ret = single_open(file,FUNC ## _show, (void *)ri); \
88 #define MAGIC_CLOSE(FUNC) \
90 FUNC ## _close(struct inode *inode, struct file *file) \
92 return single_release(inode,file); \
95 #define MAGIC_PARSE(FUNC) \
97 FUNC ## _parse(char *options, char **resstr, char **otherstr) \
105 while ((p = strsep(&options, ",")) != NULL) { \
106 substring_t args[MAX_OPT_ARGS]; \
112 token = match_token(p, FUNC##_tokens, args); \
114 case FUNC ## _res_type: \
115 *resstr = match_strdup(args); \
118 *otherstr = match_strdup(args); \
129 #define MAGIC_WRITE(FUNC,CLSTYPEFUN) \
131 FUNC ## _write(struct file *file, const char __user *buf, \
132 size_t count, loff_t *ppos) \
134 struct rcfs_inode_info *ri = \
135 RCFS_I(file->f_dentry->d_parent->d_inode); \
136 char *optbuf, *otherstr=NULL, *resname=NULL; \
138 ckrm_core_class_t *core ; \
141 if (!ckrm_is_core_valid(core)) \
144 if ((ssize_t) count < 0 \
145 || (ssize_t) count > FUNC ## _max_input_size) \
148 if (!access_ok(VERIFY_READ, buf, count)) \
151 down(&(ri->vfs_inode.i_sem)); \
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'; \
158 done = FUNC ## _parse(optbuf, &resname, &otherstr); \
161 printk(KERN_ERR "Error parsing FUNC \n"); \
162 goto FUNC ## _write_out; \
165 if (core->classtype-> CLSTYPEFUN) { \
166 rc = (*core->classtype->CLSTYPEFUN) \
167 (core, resname, otherstr); \
169 printk(KERN_ERR "FUNC_write: CLSTYPEFUN error\n"); \
170 goto FUNC ## _write_out; \
174 FUNC ## _write_out: \
175 up(&(ri->vfs_inode.i_sem)); \
179 return rc ? rc : count; \
182 #define MAGIC_RD_FILEOPS(FUNC) \
183 struct file_operations FUNC ## _fileops = { \
184 .open = FUNC ## _open, \
186 .llseek = seq_lseek, \
187 .release = FUNC ## _close, \
189 EXPORT_SYMBOL(FUNC ## _fileops);
191 #define MAGIC_RDWR_FILEOPS(FUNC) \
192 struct file_operations FUNC ## _fileops = { \
193 .open = FUNC ## _open, \
195 .llseek = seq_lseek, \
196 .release = FUNC ## _close, \
197 .write = FUNC ## _write, \
199 EXPORT_SYMBOL(FUNC ## _fileops);
201 /******************************************************************************
204 * pseudo file for manually reclassifying members to a class
206 *****************************************************************************/
208 #define TARGET_MAX_INPUT_SIZE 100
211 target_write(struct file *file, const char __user * buf,
212 size_t count, loff_t * ppos)
214 struct rcfs_inode_info *ri = RCFS_I(file->f_dentry->d_inode);
217 ckrm_classtype_t *clstype;
219 if ((ssize_t) count < 0 || (ssize_t) count > TARGET_MAX_INPUT_SIZE)
222 if (!access_ok(VERIFY_READ, buf, count))
225 down(&(ri->vfs_inode.i_sem));
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';
232 clstype = ri->core->classtype;
233 if (clstype->forced_reclassify)
234 rc = (*clstype->forced_reclassify) (ri->core, optbuf);
236 up(&(ri->vfs_inode.i_sem));
238 return (!rc ? count : rc);
242 struct file_operations target_fileops = {
243 .write = target_write,
246 EXPORT_SYMBOL(target_fileops);
248 /******************************************************************************
251 * Set/get configuration parameters of a class.
253 *****************************************************************************/
255 /* Currently there are no per-class config parameters defined.
256 * Use existing code as a template
259 #define config_max_input_size 300
261 enum config_token_t {
262 config_str, config_res_type, config_err
265 static match_table_t config_tokens = {
266 {config_res_type, "res=%s"},
267 {config_str, "config=%s"},
272 MAGIC_WRITE(config, set_config);
277 MAGIC_RDWR_FILEOPS(config);
279 /******************************************************************************
282 * List members of a class
284 *****************************************************************************/
288 MAGIC_CLOSE(members);
290 MAGIC_RD_FILEOPS(members);
292 /******************************************************************************
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.
299 *****************************************************************************/
301 #define stats_max_input_size 50
304 stats_res_type, stats_str, stats_err
307 static match_table_t stats_tokens = {
308 {stats_res_type, "res=%s"},
314 MAGIC_WRITE(stats, reset_stats);
319 MAGIC_RDWR_FILEOPS(stats);
321 /******************************************************************************
324 * Set/get shares of a taskclass.
325 * Share types and semantics are defined by rcfs and ckrm core
327 *****************************************************************************/
329 #define SHARES_MAX_INPUT_SIZE 300
331 /* The enums for the share types should match the indices expected by
332 array parameter to ckrm_set_resshare */
334 /* Note only the first NUM_SHAREVAL enums correspond to share types,
335 the remaining ones are for token matching purposes */
338 MY_GUAR, MY_LIM, TOT_GUAR, MAX_LIM, SHARE_RES_TYPE, SHARE_ERR
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"},
352 shares_parse(char *options, char **resstr, struct ckrm_shares *shares)
360 while ((p = strsep(&options, ",")) != NULL) {
362 substring_t args[MAX_OPT_ARGS];
368 token = match_token(p, shares_tokens, args);
371 *resstr = match_strdup(args);
374 if (match_int(args, &option))
376 shares->my_guarantee = option;
379 if (match_int(args, &option))
381 shares->my_limit = option;
384 if (match_int(args, &option))
386 shares->total_guarantee = option;
389 if (match_int(args, &option))
391 shares->max_limit = option;
402 shares_write(struct file *file, const char __user * buf,
403 size_t count, loff_t * ppos)
405 struct inode *inode = file->f_dentry->d_inode;
406 struct rcfs_inode_info *ri;
409 struct ckrm_core_class *core;
411 char *resname = NULL;
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,
422 if ((ssize_t) count < 0 || (ssize_t) count > SHARES_MAX_INPUT_SIZE)
425 if (!access_ok(VERIFY_READ, buf, count))
428 ri = RCFS_I(file->f_dentry->d_parent->d_inode);
430 if (!ri || !ckrm_is_core_valid((ckrm_core_class_t *) (ri->core))) {
431 printk(KERN_ERR "shares_write: Error accessing core class\n");
438 optbuf = kmalloc(SHARES_MAX_INPUT_SIZE, GFP_KERNEL);
444 __copy_from_user(optbuf, buf, count);
445 if (optbuf[count - 1] == '\n')
446 optbuf[count - 1] = '\0';
448 done = shares_parse(optbuf, &resname, &newshares);
450 printk(KERN_ERR "Error parsing shares\n");
455 if (core->classtype->set_shares) {
456 rc = (*core->classtype->set_shares) (core, resname, &newshares);
459 "shares_write: resctlr share set error\n");
464 printk(KERN_ERR "Set %s shares to %d %d %d %d\n",
466 newshares.my_guarantee,
468 newshares.total_guarantee, newshares.max_limit);
484 MAGIC_RDWR_FILEOPS(shares);
487 * magic file creation/deletion
491 int rcfs_clear_magic(struct dentry *parent)
493 struct dentry *mftmp, *mfdentry;
495 list_for_each_entry_safe(mfdentry, mftmp, &parent->d_subdirs, d_child) {
497 if (!rcfs_is_magic(mfdentry))
500 if (rcfs_delete_internal(mfdentry))
502 "rcfs_clear_magic: error deleting one\n");
509 EXPORT_SYMBOL(rcfs_clear_magic);
511 int rcfs_create_magic(struct dentry *parent, struct rcfs_magf magf[], int count)
514 struct dentry *mfdentry;
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);
522 RCFS_I(mfdentry->d_inode)->core = RCFS_I(parent->d_inode)->core;
523 mfdentry->d_fsdata = &RCFS_IS_MAGIC;
525 mfdentry->d_inode->i_fop = magf[i].i_fop;
527 mfdentry->d_inode->i_op = magf[i].i_op;
532 EXPORT_SYMBOL(rcfs_create_magic);