diff options
| -rw-r--r-- | Documentation/filesystems/configfs/configfs.txt | 57 | ||||
| -rw-r--r-- | fs/configfs/configfs_internal.h | 14 | ||||
| -rw-r--r-- | fs/configfs/dir.c | 18 | ||||
| -rw-r--r-- | fs/configfs/file.c | 255 | ||||
| -rw-r--r-- | fs/configfs/inode.c | 2 | ||||
| -rw-r--r-- | include/linux/configfs.h | 50 |
6 files changed, 374 insertions, 22 deletions
diff --git a/Documentation/filesystems/configfs/configfs.txt b/Documentation/filesystems/configfs/configfs.txt index af68efdbbfad..e5fe521eea1d 100644 --- a/Documentation/filesystems/configfs/configfs.txt +++ b/Documentation/filesystems/configfs/configfs.txt | |||
| @@ -51,15 +51,27 @@ configfs tree is always there, whether mounted on /config or not. | |||
| 51 | An item is created via mkdir(2). The item's attributes will also | 51 | An item is created via mkdir(2). The item's attributes will also |
| 52 | appear at this time. readdir(3) can determine what the attributes are, | 52 | appear at this time. readdir(3) can determine what the attributes are, |
| 53 | read(2) can query their default values, and write(2) can store new | 53 | read(2) can query their default values, and write(2) can store new |
| 54 | values. Like sysfs, attributes should be ASCII text files, preferably | 54 | values. Don't mix more than one attribute in one attribute file. |
| 55 | with only one value per file. The same efficiency caveats from sysfs | 55 | |
| 56 | apply. Don't mix more than one attribute in one attribute file. | 56 | There are two types of configfs attributes: |
| 57 | 57 | ||
| 58 | Like sysfs, configfs expects write(2) to store the entire buffer at | 58 | * Normal attributes, which similar to sysfs attributes, are small ASCII text |
| 59 | once. When writing to configfs attributes, userspace processes should | 59 | files, with a maximum size of one page (PAGE_SIZE, 4096 on i386). Preferably |
| 60 | first read the entire file, modify the portions they wish to change, and | 60 | only one value per file should be used, and the same caveats from sysfs apply. |
| 61 | then write the entire buffer back. Attribute files have a maximum size | 61 | Configfs expects write(2) to store the entire buffer at once. When writing to |
| 62 | of one page (PAGE_SIZE, 4096 on i386). | 62 | normal configfs attributes, userspace processes should first read the entire |
| 63 | file, modify the portions they wish to change, and then write the entire | ||
| 64 | buffer back. | ||
| 65 | |||
| 66 | * Binary attributes, which are somewhat similar to sysfs binary attributes, | ||
| 67 | but with a few slight changes to semantics. The PAGE_SIZE limitation does not | ||
| 68 | apply, but the whole binary item must fit in single kernel vmalloc'ed buffer. | ||
| 69 | The write(2) calls from user space are buffered, and the attributes' | ||
| 70 | write_bin_attribute method will be invoked on the final close, therefore it is | ||
| 71 | imperative for user-space to check the return code of close(2) in order to | ||
| 72 | verify that the operation finished successfully. | ||
| 73 | To avoid a malicious user OOMing the kernel, there's a per-binary attribute | ||
| 74 | maximum buffer value. | ||
| 63 | 75 | ||
| 64 | When an item needs to be destroyed, remove it with rmdir(2). An | 76 | When an item needs to be destroyed, remove it with rmdir(2). An |
| 65 | item cannot be destroyed if any other item has a link to it (via | 77 | item cannot be destroyed if any other item has a link to it (via |
| @@ -171,6 +183,7 @@ among other things. For that, it needs a type. | |||
| 171 | struct configfs_item_operations *ct_item_ops; | 183 | struct configfs_item_operations *ct_item_ops; |
| 172 | struct configfs_group_operations *ct_group_ops; | 184 | struct configfs_group_operations *ct_group_ops; |
| 173 | struct configfs_attribute **ct_attrs; | 185 | struct configfs_attribute **ct_attrs; |
| 186 | struct configfs_bin_attribute **ct_bin_attrs; | ||
| 174 | }; | 187 | }; |
| 175 | 188 | ||
| 176 | The most basic function of a config_item_type is to define what | 189 | The most basic function of a config_item_type is to define what |
| @@ -201,6 +214,32 @@ be called whenever userspace asks for a read(2) on the attribute. If an | |||
| 201 | attribute is writable and provides a ->store method, that method will be | 214 | attribute is writable and provides a ->store method, that method will be |
| 202 | be called whenever userspace asks for a write(2) on the attribute. | 215 | be called whenever userspace asks for a write(2) on the attribute. |
| 203 | 216 | ||
| 217 | [struct configfs_bin_attribute] | ||
| 218 | |||
| 219 | struct configfs_attribute { | ||
| 220 | struct configfs_attribute cb_attr; | ||
| 221 | void *cb_private; | ||
| 222 | size_t cb_max_size; | ||
| 223 | }; | ||
| 224 | |||
| 225 | The binary attribute is used when the one needs to use binary blob to | ||
| 226 | appear as the contents of a file in the item's configfs directory. | ||
| 227 | To do so add the binary attribute to the NULL-terminated array | ||
| 228 | config_item_type->ct_bin_attrs, and the item appears in configfs, the | ||
| 229 | attribute file will appear with the configfs_bin_attribute->cb_attr.ca_name | ||
| 230 | filename. configfs_bin_attribute->cb_attr.ca_mode specifies the file | ||
| 231 | permissions. | ||
| 232 | The cb_private member is provided for use by the driver, while the | ||
| 233 | cb_max_size member specifies the maximum amount of vmalloc buffer | ||
| 234 | to be used. | ||
| 235 | |||
| 236 | If binary attribute is readable and the config_item provides a | ||
| 237 | ct_item_ops->read_bin_attribute() method, that method will be called | ||
| 238 | whenever userspace asks for a read(2) on the attribute. The converse | ||
| 239 | will happen for write(2). The reads/writes are bufferred so only a | ||
| 240 | single read/write will occur; the attributes' need not concern itself | ||
| 241 | with it. | ||
| 242 | |||
| 204 | [struct config_group] | 243 | [struct config_group] |
| 205 | 244 | ||
| 206 | A config_item cannot live in a vacuum. The only way one can be created | 245 | A config_item cannot live in a vacuum. The only way one can be created |
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h index b65d1ef532d5..ccc31fa6f1a7 100644 --- a/fs/configfs/configfs_internal.h +++ b/fs/configfs/configfs_internal.h | |||
| @@ -53,13 +53,14 @@ struct configfs_dirent { | |||
| 53 | #define CONFIGFS_ROOT 0x0001 | 53 | #define CONFIGFS_ROOT 0x0001 |
| 54 | #define CONFIGFS_DIR 0x0002 | 54 | #define CONFIGFS_DIR 0x0002 |
| 55 | #define CONFIGFS_ITEM_ATTR 0x0004 | 55 | #define CONFIGFS_ITEM_ATTR 0x0004 |
| 56 | #define CONFIGFS_ITEM_BIN_ATTR 0x0008 | ||
| 56 | #define CONFIGFS_ITEM_LINK 0x0020 | 57 | #define CONFIGFS_ITEM_LINK 0x0020 |
| 57 | #define CONFIGFS_USET_DIR 0x0040 | 58 | #define CONFIGFS_USET_DIR 0x0040 |
| 58 | #define CONFIGFS_USET_DEFAULT 0x0080 | 59 | #define CONFIGFS_USET_DEFAULT 0x0080 |
| 59 | #define CONFIGFS_USET_DROPPING 0x0100 | 60 | #define CONFIGFS_USET_DROPPING 0x0100 |
| 60 | #define CONFIGFS_USET_IN_MKDIR 0x0200 | 61 | #define CONFIGFS_USET_IN_MKDIR 0x0200 |
| 61 | #define CONFIGFS_USET_CREATING 0x0400 | 62 | #define CONFIGFS_USET_CREATING 0x0400 |
| 62 | #define CONFIGFS_NOT_PINNED (CONFIGFS_ITEM_ATTR) | 63 | #define CONFIGFS_NOT_PINNED (CONFIGFS_ITEM_ATTR | CONFIGFS_ITEM_BIN_ATTR) |
| 63 | 64 | ||
| 64 | extern struct mutex configfs_symlink_mutex; | 65 | extern struct mutex configfs_symlink_mutex; |
| 65 | extern spinlock_t configfs_dirent_lock; | 66 | extern spinlock_t configfs_dirent_lock; |
| @@ -72,6 +73,8 @@ extern struct inode * configfs_new_inode(umode_t mode, struct configfs_dirent *, | |||
| 72 | extern int configfs_create(struct dentry *, umode_t mode, void (*init)(struct inode *)); | 73 | extern int configfs_create(struct dentry *, umode_t mode, void (*init)(struct inode *)); |
| 73 | 74 | ||
| 74 | extern int configfs_create_file(struct config_item *, const struct configfs_attribute *); | 75 | extern int configfs_create_file(struct config_item *, const struct configfs_attribute *); |
| 76 | extern int configfs_create_bin_file(struct config_item *, | ||
| 77 | const struct configfs_bin_attribute *); | ||
| 75 | extern int configfs_make_dirent(struct configfs_dirent *, | 78 | extern int configfs_make_dirent(struct configfs_dirent *, |
| 76 | struct dentry *, void *, umode_t, int); | 79 | struct dentry *, void *, umode_t, int); |
| 77 | extern int configfs_dirent_is_ready(struct configfs_dirent *); | 80 | extern int configfs_dirent_is_ready(struct configfs_dirent *); |
| @@ -88,7 +91,7 @@ extern void configfs_release_fs(void); | |||
| 88 | extern struct rw_semaphore configfs_rename_sem; | 91 | extern struct rw_semaphore configfs_rename_sem; |
| 89 | extern const struct file_operations configfs_dir_operations; | 92 | extern const struct file_operations configfs_dir_operations; |
| 90 | extern const struct file_operations configfs_file_operations; | 93 | extern const struct file_operations configfs_file_operations; |
| 91 | extern const struct file_operations bin_fops; | 94 | extern const struct file_operations configfs_bin_file_operations; |
| 92 | extern const struct inode_operations configfs_dir_inode_operations; | 95 | extern const struct inode_operations configfs_dir_inode_operations; |
| 93 | extern const struct inode_operations configfs_root_inode_operations; | 96 | extern const struct inode_operations configfs_root_inode_operations; |
| 94 | extern const struct inode_operations configfs_symlink_inode_operations; | 97 | extern const struct inode_operations configfs_symlink_inode_operations; |
| @@ -119,6 +122,13 @@ static inline struct configfs_attribute * to_attr(struct dentry * dentry) | |||
| 119 | return ((struct configfs_attribute *) sd->s_element); | 122 | return ((struct configfs_attribute *) sd->s_element); |
| 120 | } | 123 | } |
| 121 | 124 | ||
| 125 | static inline struct configfs_bin_attribute *to_bin_attr(struct dentry *dentry) | ||
| 126 | { | ||
| 127 | struct configfs_attribute *attr = to_attr(dentry); | ||
| 128 | |||
| 129 | return container_of(attr, struct configfs_bin_attribute, cb_attr); | ||
| 130 | } | ||
| 131 | |||
| 122 | static inline struct config_item *configfs_get_config_item(struct dentry *dentry) | 132 | static inline struct config_item *configfs_get_config_item(struct dentry *dentry) |
| 123 | { | 133 | { |
| 124 | struct config_item * item = NULL; | 134 | struct config_item * item = NULL; |
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index a7a1b218f308..7ae97e83f121 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
| @@ -255,6 +255,12 @@ static void configfs_init_file(struct inode * inode) | |||
| 255 | inode->i_fop = &configfs_file_operations; | 255 | inode->i_fop = &configfs_file_operations; |
| 256 | } | 256 | } |
| 257 | 257 | ||
| 258 | static void configfs_init_bin_file(struct inode *inode) | ||
| 259 | { | ||
| 260 | inode->i_size = 0; | ||
| 261 | inode->i_fop = &configfs_bin_file_operations; | ||
| 262 | } | ||
| 263 | |||
| 258 | static void init_symlink(struct inode * inode) | 264 | static void init_symlink(struct inode * inode) |
| 259 | { | 265 | { |
| 260 | inode->i_op = &configfs_symlink_inode_operations; | 266 | inode->i_op = &configfs_symlink_inode_operations; |
| @@ -423,7 +429,9 @@ static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * den | |||
| 423 | spin_unlock(&configfs_dirent_lock); | 429 | spin_unlock(&configfs_dirent_lock); |
| 424 | 430 | ||
| 425 | error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG, | 431 | error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG, |
| 426 | configfs_init_file); | 432 | (sd->s_type & CONFIGFS_ITEM_BIN_ATTR) ? |
| 433 | configfs_init_bin_file : | ||
| 434 | configfs_init_file); | ||
| 427 | if (error) { | 435 | if (error) { |
| 428 | configfs_put(sd); | 436 | configfs_put(sd); |
| 429 | return error; | 437 | return error; |
| @@ -583,6 +591,7 @@ static int populate_attrs(struct config_item *item) | |||
| 583 | { | 591 | { |
| 584 | struct config_item_type *t = item->ci_type; | 592 | struct config_item_type *t = item->ci_type; |
| 585 | struct configfs_attribute *attr; | 593 | struct configfs_attribute *attr; |
| 594 | struct configfs_bin_attribute *bin_attr; | ||
| 586 | int error = 0; | 595 | int error = 0; |
| 587 | int i; | 596 | int i; |
| 588 | 597 | ||
| @@ -594,6 +603,13 @@ static int populate_attrs(struct config_item *item) | |||
| 594 | break; | ||
