aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysfs/inode.c')
-rw-r--r--fs/sysfs/inode.c103
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
20extern struct super_block * sysfs_sb; 23extern 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
37void 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
47int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) 40int 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 */
134static struct lock_class_key sysfs_inode_imutex_key; 127static struct lock_class_key sysfs_inode_imutex_key;
135 128
129static 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
136static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) 141static 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 */
190void 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
200int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) 213int 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}