diff options
Diffstat (limited to 'fs/sysfs/inode.c')
| -rw-r--r-- | fs/sysfs/inode.c | 103 |
1 files changed, 55 insertions, 48 deletions
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 10d1b52899f1..9236635111f4 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
| @@ -1,7 +1,11 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * inode.c - basic inode and dentry operations. | 2 | * fs/sysfs/inode.c - basic sysfs inode and dentry operations |
| 3 | * | 3 | * |
| 4 | * sysfs is Copyright (c) 2001-3 Patrick Mochel | 4 | * Copyright (c) 2001-3 Patrick Mochel |
| 5 | * Copyright (c) 2007 SUSE Linux Products GmbH | ||
| 6 | * Copyright (c) 2007 Tejun Heo <teheo@suse.de> | ||
| 7 | * | ||
| 8 | * This file is released under the GPLv2. | ||
| 5 | * | 9 | * |
| 6 | * Please see Documentation/filesystems/sysfs.txt for more information. | 10 | * Please see Documentation/filesystems/sysfs.txt for more information. |
| 7 | */ | 11 | */ |
| @@ -14,7 +18,6 @@ | |||
| 14 | #include <linux/capability.h> | 18 | #include <linux/capability.h> |
| 15 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
| 16 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
| 17 | #include <asm/semaphore.h> | ||
| 18 | #include "sysfs.h" | 21 | #include "sysfs.h" |
| 19 | 22 | ||
| 20 | extern struct super_block * sysfs_sb; | 23 | extern struct super_block * sysfs_sb; |
| @@ -34,16 +37,6 @@ static const struct inode_operations sysfs_inode_operations ={ | |||
| 34 | .setattr = sysfs_setattr, | 37 | .setattr = sysfs_setattr, |
| 35 | }; | 38 | }; |
| 36 | 39 | ||
| 37 | void sysfs_delete_inode(struct inode *inode) | ||
| 38 | { | ||
| 39 | /* Free the shadowed directory inode operations */ | ||
| 40 | if (sysfs_is_shadowed_inode(inode)) { | ||
| 41 | kfree(inode->i_op); | ||
| 42 | inode->i_op = NULL; | ||
| 43 | } | ||
| 44 | return generic_delete_inode(inode); | ||
| 45 | } | ||
| 46 | |||
| 47 | int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) | 40 | int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) |
| 48 | { | 41 | { |
| 49 | struct inode * inode = dentry->d_inode; | 42 | struct inode * inode = dentry->d_inode; |
| @@ -133,8 +126,22 @@ static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) | |||
| 133 | */ | 126 | */ |
| 134 | static struct lock_class_key sysfs_inode_imutex_key; | 127 | static struct lock_class_key sysfs_inode_imutex_key; |
| 135 | 128 | ||
| 129 | static int sysfs_count_nlink(struct sysfs_dirent *sd) | ||
| 130 | { | ||
| 131 | struct sysfs_dirent *child; | ||
| 132 | int nr = 0; | ||
| 133 | |||
| 134 | for (child = sd->s_dir.children; child; child = child->s_sibling) | ||
| 135 | if (sysfs_type(child) == SYSFS_DIR) | ||
| 136 | nr++; | ||
| 137 | |||
| 138 | return nr + 2; | ||
| 139 | } | ||
| 140 | |||
| 136 | static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) | 141 | static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) |
| 137 | { | 142 | { |
| 143 | struct bin_attribute *bin_attr; | ||
| 144 | |||
| 138 | inode->i_blocks = 0; | 145 | inode->i_blocks = 0; |
| 139 | inode->i_mapping->a_ops = &sysfs_aops; | 146 | inode->i_mapping->a_ops = &sysfs_aops; |
| 140 | inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; | 147 | inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; |
| @@ -150,6 +157,32 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) | |||
| 150 | set_inode_attr(inode, sd->s_iattr); | 157 | set_inode_attr(inode, sd->s_iattr); |
| 151 | } else | 158 | } else |
| 152 | set_default_inode_attr(inode, sd->s_mode); | 159 | set_default_inode_attr(inode, sd->s_mode); |
| 160 | |||
| 161 | |||
| 162 | /* initialize inode according to type */ | ||
| 163 | switch (sysfs_type(sd)) { | ||
| 164 | case SYSFS_DIR: | ||
| 165 | inode->i_op = &sysfs_dir_inode_operations; | ||
| 166 | inode->i_fop = &sysfs_dir_operations; | ||
| 167 | inode->i_nlink = sysfs_count_nlink(sd); | ||
| 168 | break; | ||
| 169 | case SYSFS_KOBJ_ATTR: | ||
| 170 | inode->i_size = PAGE_SIZE; | ||
| 171 | inode->i_fop = &sysfs_file_operations; | ||
| 172 | break; | ||
| 173 | case SYSFS_KOBJ_BIN_ATTR: | ||
| 174 | bin_attr = sd->s_bin_attr.bin_attr; | ||
| 175 | inode->i_size = bin_attr->size; | ||
| 176 | inode->i_fop = &bin_fops; | ||
| 177 | break; | ||
| 178 | case SYSFS_KOBJ_LINK: | ||
| 179 | inode->i_op = &sysfs_symlink_inode_operations; | ||
| 180 | break; | ||
| 181 | default: | ||
| 182 | BUG(); | ||
| 183 | } | ||
| 184 | |||
| 185 | unlock_new_inode(inode); | ||
| 153 | } | 186 | } |
| 154 | 187 | ||
| 155 | /** | 188 | /** |
| @@ -177,50 +210,24 @@ struct inode * sysfs_get_inode(struct sysfs_dirent *sd) | |||
| 177 | return inode; | 210 | return inode; |
| 178 | } | 211 | } |
| 179 | 212 | ||
| 180 | /** | ||
| 181 | * sysfs_instantiate - instantiate dentry | ||
| 182 | * @dentry: dentry to be instantiated | ||
| 183 | * @inode: inode associated with @sd | ||
| 184 | * | ||
| 185 | * Unlock @inode if locked and instantiate @dentry with @inode. | ||
| 186 | * | ||
| 187 | * LOCKING: | ||
| 188 | * None. | ||
| 189 | */ | ||
| 190 | void sysfs_instantiate(struct dentry *dentry, struct inode *inode) | ||
| 191 | { | ||
| 192 | BUG_ON(!dentry || dentry->d_inode); | ||
| 193 | |||
| 194 | if (inode->i_state & I_NEW) | ||
| 195 | unlock_new_inode(inode); | ||
| 196 | |||
| 197 | d_instantiate(dentry, inode); | ||
| 198 | } | ||
| 199 | |||
| 200 | int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) | 213 | int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) |
| 201 | { | 214 | { |
| 202 | struct sysfs_addrm_cxt acxt; | 215 | struct sysfs_addrm_cxt acxt; |
| 203 | struct sysfs_dirent **pos, *sd; | 216 | struct sysfs_dirent *sd; |
| 204 | 217 | ||
| 205 | if (!dir_sd) | 218 | if (!dir_sd) |
| 206 | return -ENOENT; | 219 | return -ENOENT; |
| 207 | 220 | ||
| 208 | sysfs_addrm_start(&acxt, dir_sd); | 221 | sysfs_addrm_start(&acxt, dir_sd); |
| 209 | 222 | ||
| 210 | for (pos = &dir_sd->s_children; *pos; pos = &(*pos)->s_sibling) { | 223 | sd = sysfs_find_dirent(dir_sd, name); |
| 211 | sd = *pos; | 224 | if (sd) |
| 212 | 225 | sysfs_remove_one(&acxt, sd); | |
| 213 | if (!sysfs_type(sd)) | 226 | |
| 214 | continue; | 227 | sysfs_addrm_finish(&acxt); |
| 215 | if (!strcmp(sd->s_name, name)) { | ||
| 216 | *pos = sd->s_sibling; | ||
| 217 | sd->s_sibling = NULL; | ||
| 218 | sysfs_remove_one(&acxt, sd); | ||
| 219 | break; | ||
| 220 | } | ||
| 221 | } | ||
| 222 | 228 | ||
| 223 | if (sysfs_addrm_finish(&acxt)) | 229 | if (sd) |
| 224 | return 0; | 230 | return 0; |
| 225 | return -ENOENT; | 231 | else |
| 232 | return -ENOENT; | ||
| 226 | } | 233 | } |
