Blame view
fs/sysfs/dir.c
24 KB
1da177e4c Linux-2.6.12-rc2 |
1 |
/* |
6d66f5cd2 sysfs: add copyri... |
2 3 4 5 6 7 8 9 10 |
* fs/sysfs/dir.c - sysfs core and dir operation implementation * * Copyright (c) 2001-3 Patrick Mochel * Copyright (c) 2007 SUSE Linux Products GmbH * Copyright (c) 2007 Tejun Heo <teheo@suse.de> * * This file is released under the GPLv2. * * Please see Documentation/filesystems/sysfs.txt for more information. |
1da177e4c Linux-2.6.12-rc2 |
11 12 13 14 15 16 17 18 |
*/ #undef DEBUG #include <linux/fs.h> #include <linux/mount.h> #include <linux/module.h> #include <linux/kobject.h> |
5f45f1a78 [PATCH] remove du... |
19 |
#include <linux/namei.h> |
2b611bb7a sysfs: allocate i... |
20 |
#include <linux/idr.h> |
8619f9798 sysfs: slim down ... |
21 |
#include <linux/completion.h> |
869512ab5 sysfs: cleanup se... |
22 |
#include <linux/mutex.h> |
c6f877338 SYSFS: Explicitly... |
23 |
#include <linux/slab.h> |
4c3da2209 sysfs: Don't leak... |
24 |
#include <linux/security.h> |
1da177e4c Linux-2.6.12-rc2 |
25 |
#include "sysfs.h" |
3007e997d sysfs: use sysfs_... |
26 |
DEFINE_MUTEX(sysfs_mutex); |
f7a75f0a4 spin_lock_unlocke... |
27 |
DEFINE_SPINLOCK(sysfs_assoc_lock); |
1da177e4c Linux-2.6.12-rc2 |
28 |
|
f7a75f0a4 spin_lock_unlocke... |
29 |
static DEFINE_SPINLOCK(sysfs_ino_lock); |
2b611bb7a sysfs: allocate i... |
30 |
static DEFINE_IDA(sysfs_ino_ida); |
b6b4a4399 sysfs: move s_act... |
31 |
/** |
0c73f18b7 sysfs: use singly... |
32 33 34 35 |
* sysfs_link_sibling - link sysfs_dirent into sibling list * @sd: sysfs_dirent of interest * * Link @sd into its sibling list which starts from |
bc747f37a sysfs: move sysfs... |
36 |
* sd->s_parent->s_dir.children. |
0c73f18b7 sysfs: use singly... |
37 38 |
* * Locking: |
3007e997d sysfs: use sysfs_... |
39 |
* mutex_lock(sysfs_mutex) |
0c73f18b7 sysfs: use singly... |
40 |
*/ |
41fc1c274 sysfs: make sysfs... |
41 |
static void sysfs_link_sibling(struct sysfs_dirent *sd) |
0c73f18b7 sysfs: use singly... |
42 43 |
{ struct sysfs_dirent *parent_sd = sd->s_parent; |
4f72c0cab sysfs: use rb-tre... |
44 45 |
struct rb_node **p; struct rb_node *parent; |
7f9838fd0 sysfs: count subd... |
46 47 |
if (sysfs_type(sd) == SYSFS_DIR) parent_sd->s_dir.subdirs++; |
a406f7584 sysfs: use rb-tre... |
48 49 50 51 52 53 54 55 56 57 |
p = &parent_sd->s_dir.inode_tree.rb_node; parent = NULL; while (*p) { parent = *p; #define node rb_entry(parent, struct sysfs_dirent, inode_node) if (sd->s_ino < node->s_ino) { p = &node->inode_node.rb_left; } else if (sd->s_ino > node->s_ino) { p = &node->inode_node.rb_right; } else { |
c4253cb07 sysfs: add unsign... |
58 59 60 |
printk(KERN_CRIT "sysfs: inserting duplicate inode '%lx' ", (unsigned long) sd->s_ino); |
a406f7584 sysfs: use rb-tre... |
61 62 63 |
BUG(); } #undef node |
3efa65b92 sysfs: Simplify r... |
64 |
} |
a406f7584 sysfs: use rb-tre... |
65 66 |
rb_link_node(&sd->inode_node, parent, p); rb_insert_color(&sd->inode_node, &parent_sd->s_dir.inode_tree); |
4f72c0cab sysfs: use rb-tre... |
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
p = &parent_sd->s_dir.name_tree.rb_node; parent = NULL; while (*p) { int c; parent = *p; #define node rb_entry(parent, struct sysfs_dirent, name_node) c = strcmp(sd->s_name, node->s_name); if (c < 0) { p = &node->name_node.rb_left; } else { p = &node->name_node.rb_right; } #undef node } rb_link_node(&sd->name_node, parent, p); rb_insert_color(&sd->name_node, &parent_sd->s_dir.name_tree); |
0c73f18b7 sysfs: use singly... |
84 85 86 87 88 89 90 |
} /** * sysfs_unlink_sibling - unlink sysfs_dirent from sibling list * @sd: sysfs_dirent of interest * * Unlink @sd from its sibling list which starts from |
bc747f37a sysfs: move sysfs... |
91 |
* sd->s_parent->s_dir.children. |
0c73f18b7 sysfs: use singly... |
92 93 |
* * Locking: |
3007e997d sysfs: use sysfs_... |
94 |
* mutex_lock(sysfs_mutex) |
0c73f18b7 sysfs: use singly... |
95 |
*/ |
41fc1c274 sysfs: make sysfs... |
96 |
static void sysfs_unlink_sibling(struct sysfs_dirent *sd) |
0c73f18b7 sysfs: use singly... |
97 |
{ |
7f9838fd0 sysfs: count subd... |
98 99 |
if (sysfs_type(sd) == SYSFS_DIR) sd->s_parent->s_dir.subdirs--; |
a406f7584 sysfs: use rb-tre... |
100 |
rb_erase(&sd->inode_node, &sd->s_parent->s_dir.inode_tree); |
4f72c0cab sysfs: use rb-tre... |
101 |
rb_erase(&sd->name_node, &sd->s_parent->s_dir.name_tree); |
0c73f18b7 sysfs: use singly... |
102 103 104 |
} /** |
b6b4a4399 sysfs: move s_act... |
105 106 107 108 109 110 111 112 113 |
* sysfs_get_active - get an active reference to sysfs_dirent * @sd: sysfs_dirent to get an active reference to * * Get an active reference of @sd. This function is noop if @sd * is NULL. * * RETURNS: * Pointer to @sd on success, NULL on failure. */ |
e72ceb8cc sysfs: Remove sys... |
114 |
struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) |
b6b4a4399 sysfs: move s_act... |
115 |
{ |
8619f9798 sysfs: slim down ... |
116 117 118 119 120 121 122 123 124 125 126 |
if (unlikely(!sd)) return NULL; while (1) { int v, t; v = atomic_read(&sd->s_active); if (unlikely(v < 0)) return NULL; t = atomic_cmpxchg(&sd->s_active, v, v + 1); |
846f99749 sysfs: Add lockde... |
127 128 |
if (likely(t == v)) { rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_); |
8619f9798 sysfs: slim down ... |
129 |
return sd; |
846f99749 sysfs: Add lockde... |
130 |
} |
8619f9798 sysfs: slim down ... |
131 132 133 134 |
if (t < 0) return NULL; cpu_relax(); |
b6b4a4399 sysfs: move s_act... |
135 |
} |
b6b4a4399 sysfs: move s_act... |
136 137 138 139 140 141 142 143 144 |
} /** * sysfs_put_active - put an active reference to sysfs_dirent * @sd: sysfs_dirent to put an active reference to * * Put an active reference to @sd. This function is noop if @sd * is NULL. */ |
e72ceb8cc sysfs: Remove sys... |
145 |
void sysfs_put_active(struct sysfs_dirent *sd) |
b6b4a4399 sysfs: move s_act... |
146 |
{ |
8619f9798 sysfs: slim down ... |
147 148 149 150 |
int v; if (unlikely(!sd)) return; |
846f99749 sysfs: Add lockde... |
151 |
rwsem_release(&sd->dep_map, 1, _RET_IP_); |
8619f9798 sysfs: slim down ... |
152 153 154 155 156 |
v = atomic_dec_return(&sd->s_active); if (likely(v != SD_DEACTIVATED_BIAS)) return; /* atomic_dec_return() is a mb(), we'll always see the updated |
58f2a4c79 sysfs: remove s_s... |
157 |
* sd->u.completion. |
8619f9798 sysfs: slim down ... |
158 |
*/ |
58f2a4c79 sysfs: remove s_s... |
159 |
complete(sd->u.completion); |
b6b4a4399 sysfs: move s_act... |
160 161 162 |
} /** |
b6b4a4399 sysfs: move s_act... |
163 164 165 |
* sysfs_deactivate - deactivate sysfs_dirent * @sd: sysfs_dirent to deactivate * |
8619f9798 sysfs: slim down ... |
166 |
* Deny new active references and drain existing ones. |
b6b4a4399 sysfs: move s_act... |
167 |
*/ |
fb6896da3 sysfs: restructur... |
168 |
static void sysfs_deactivate(struct sysfs_dirent *sd) |
b6b4a4399 sysfs: move s_act... |
169 |
{ |
8619f9798 sysfs: slim down ... |
170 171 |
DECLARE_COMPLETION_ONSTACK(wait); int v; |
b6b4a4399 sysfs: move s_act... |
172 |
|
58f2a4c79 sysfs: remove s_s... |
173 |
BUG_ON(!(sd->s_flags & SYSFS_FLAG_REMOVED)); |
a2db68428 sysfs: Only take ... |
174 175 176 |
if (!(sysfs_type(sd) & SYSFS_ACTIVE_REF)) return; |
58f2a4c79 sysfs: remove s_s... |
177 |
sd->u.completion = (void *)&wait; |
8619f9798 sysfs: slim down ... |
178 |
|
846f99749 sysfs: Add lockde... |
179 |
rwsem_acquire(&sd->dep_map, 0, 0, _RET_IP_); |
8619f9798 sysfs: slim down ... |
180 |
/* atomic_add_return() is a mb(), put_active() will always see |
58f2a4c79 sysfs: remove s_s... |
181 |
* the updated sd->u.completion. |
b6b4a4399 sysfs: move s_act... |
182 |
*/ |
8619f9798 sysfs: slim down ... |
183 |
v = atomic_add_return(SD_DEACTIVATED_BIAS, &sd->s_active); |
846f99749 sysfs: Add lockde... |
184 185 |
if (v != SD_DEACTIVATED_BIAS) { lock_contended(&sd->dep_map, _RET_IP_); |
8619f9798 sysfs: slim down ... |
186 |
wait_for_completion(&wait); |
846f99749 sysfs: Add lockde... |
187 |
} |
8619f9798 sysfs: slim down ... |
188 |
|
846f99749 sysfs: Add lockde... |
189 190 |
lock_acquired(&sd->dep_map, _RET_IP_); rwsem_release(&sd->dep_map, 1, _RET_IP_); |
b6b4a4399 sysfs: move s_act... |
191 |
} |
42b37df6a sysfs: make sysfs... |
192 |
static int sysfs_alloc_ino(ino_t *pino) |
2b611bb7a sysfs: allocate i... |
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
{ int ino, rc; retry: spin_lock(&sysfs_ino_lock); rc = ida_get_new_above(&sysfs_ino_ida, 2, &ino); spin_unlock(&sysfs_ino_lock); if (rc == -EAGAIN) { if (ida_pre_get(&sysfs_ino_ida, GFP_KERNEL)) goto retry; rc = -ENOMEM; } *pino = ino; return rc; } static void sysfs_free_ino(ino_t ino) { spin_lock(&sysfs_ino_lock); ida_remove(&sysfs_ino_ida, ino); spin_unlock(&sysfs_ino_lock); } |
fa7f912ad sysfs: move relea... |
217 218 |
void release_sysfs_dirent(struct sysfs_dirent * sd) { |
13b3086d2 sysfs: add sysfs_... |
219 220 221 |
struct sysfs_dirent *parent_sd; repeat: |
3007e997d sysfs: use sysfs_... |
222 223 224 |
/* Moving/renaming is always done while holding reference. * sd->s_parent won't change beneath us. */ |
13b3086d2 sysfs: add sysfs_... |
225 |
parent_sd = sd->s_parent; |
b402d72cf sysfs: rename sys... |
226 |
if (sysfs_type(sd) == SYSFS_KOBJ_LINK) |
b1fc3d614 sysfs: make s_ele... |
227 |
sysfs_put(sd->s_symlink.target_sd); |
b402d72cf sysfs: rename sys... |
228 |
if (sysfs_type(sd) & SYSFS_COPY_NAME) |
0c096b507 sysfs: add sysfs_... |
229 |
kfree(sd->s_name); |
4c3da2209 sysfs: Don't leak... |
230 231 232 |
if (sd->s_iattr && sd->s_iattr->ia_secdata) security_release_secctx(sd->s_iattr->ia_secdata, sd->s_iattr->ia_secdata_len); |
fa7f912ad sysfs: move relea... |
233 |
kfree(sd->s_iattr); |
2b611bb7a sysfs: allocate i... |
234 |
sysfs_free_ino(sd->s_ino); |
fa7f912ad sysfs: move relea... |
235 |
kmem_cache_free(sysfs_dir_cachep, sd); |
13b3086d2 sysfs: add sysfs_... |
236 237 238 239 |
sd = parent_sd; if (sd && atomic_dec_and_test(&sd->s_count)) goto repeat; |
fa7f912ad sysfs: move relea... |
240 |
} |
fe15ce446 fs: change d_dele... |
241 |
static int sysfs_dentry_delete(const struct dentry *dentry) |
e8f077c88 sysfs: Use dentry... |
242 243 244 245 246 247 248 |
{ struct sysfs_dirent *sd = dentry->d_fsdata; return !!(sd->s_flags & SYSFS_FLAG_REMOVED); } static int sysfs_dentry_revalidate(struct dentry *dentry, struct nameidata *nd) { |
34286d666 fs: rcu-walk awar... |
249 |
struct sysfs_dirent *sd; |
e8f077c88 sysfs: Use dentry... |
250 |
int is_dir; |
34286d666 fs: rcu-walk awar... |
251 252 253 254 |
if (nd->flags & LOOKUP_RCU) return -ECHILD; sd = dentry->d_fsdata; |
e8f077c88 sysfs: Use dentry... |
255 256 257 258 259 |
mutex_lock(&sysfs_mutex); /* The sysfs dirent has been deleted */ if (sd->s_flags & SYSFS_FLAG_REMOVED) goto out_bad; |
832b6af19 sysfs: Propagate ... |
260 261 262 263 264 265 266 |
/* The sysfs dirent has been moved? */ if (dentry->d_parent->d_fsdata != sd->s_parent) goto out_bad; /* The sysfs dirent has been renamed */ if (strcmp(dentry->d_name.name, sd->s_name) != 0) goto out_bad; |
e8f077c88 sysfs: Use dentry... |
267 268 269 270 271 272 273 |
mutex_unlock(&sysfs_mutex); out_valid: return 1; out_bad: /* Remove the dentry from the dcache hashes. * If this is a deleted dentry we use d_drop instead of d_delete * so sysfs doesn't need to cope with negative dentries. |
832b6af19 sysfs: Propagate ... |
274 275 276 277 278 279 |
* * If this is a dentry that has simply been renamed we * use d_drop to remove it from the dcache lookup on its * old parent. If this dentry persists later when a lookup * is performed at its new name the dentry will be readded * to the dcache hashes. |
e8f077c88 sysfs: Use dentry... |
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
*/ is_dir = (sysfs_type(sd) == SYSFS_DIR); mutex_unlock(&sysfs_mutex); if (is_dir) { /* If we have submounts we must allow the vfs caches * to lie about the state of the filesystem to prevent * leaks and other nasty things. */ if (have_submounts(dentry)) goto out_valid; shrink_dcache_parent(dentry); } d_drop(dentry); return 0; } |
28a027cfc sysfs: Rename sys... |
295 |
static void sysfs_dentry_iput(struct dentry *dentry, struct inode *inode) |
1da177e4c Linux-2.6.12-rc2 |
296 297 |
{ struct sysfs_dirent * sd = dentry->d_fsdata; |
5a26b79c4 sysfs: Remove s_d... |
298 |
sysfs_put(sd); |
1da177e4c Linux-2.6.12-rc2 |
299 300 |
iput(inode); } |
ee1ec3290 constify dentry_o... |
301 |
static const struct dentry_operations sysfs_dentry_ops = { |
e8f077c88 sysfs: Use dentry... |
302 303 |
.d_revalidate = sysfs_dentry_revalidate, .d_delete = sysfs_dentry_delete, |
28a027cfc sysfs: Rename sys... |
304 |
.d_iput = sysfs_dentry_iput, |
1da177e4c Linux-2.6.12-rc2 |
305 |
}; |
3e5190380 sysfs: make sysfs... |
306 |
struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) |
1da177e4c Linux-2.6.12-rc2 |
307 |
{ |
0c096b507 sysfs: add sysfs_... |
308 |
char *dup_name = NULL; |
01da2425f sysfs: avoid kmem... |
309 |
struct sysfs_dirent *sd; |
0c096b507 sysfs: add sysfs_... |
310 311 312 313 |
if (type & SYSFS_COPY_NAME) { name = dup_name = kstrdup(name, GFP_KERNEL); if (!name) |
01da2425f sysfs: avoid kmem... |
314 |
return NULL; |
0c096b507 sysfs: add sysfs_... |
315 |
} |
1da177e4c Linux-2.6.12-rc2 |
316 |
|
c37622296 [PATCH] Transform... |
317 |
sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
318 |
if (!sd) |
01da2425f sysfs: avoid kmem... |
319 |
goto err_out1; |
1da177e4c Linux-2.6.12-rc2 |
320 |
|
0c096b507 sysfs: add sysfs_... |
321 |
if (sysfs_alloc_ino(&sd->s_ino)) |
01da2425f sysfs: avoid kmem... |
322 |
goto err_out2; |
2b611bb7a sysfs: allocate i... |
323 |
|
1da177e4c Linux-2.6.12-rc2 |
324 |
atomic_set(&sd->s_count, 1); |
8619f9798 sysfs: slim down ... |
325 |
atomic_set(&sd->s_active, 0); |
a26cd7226 sysfs: consolidat... |
326 |
|
0c096b507 sysfs: add sysfs_... |
327 |
sd->s_name = name; |
a26cd7226 sysfs: consolidat... |
328 |
sd->s_mode = mode; |
b402d72cf sysfs: rename sys... |
329 |
sd->s_flags = type; |
1da177e4c Linux-2.6.12-rc2 |
330 331 |
return sd; |
0c096b507 sysfs: add sysfs_... |
332 |
|
01da2425f sysfs: avoid kmem... |
333 |
err_out2: |
0c096b507 sysfs: add sysfs_... |
334 |
kmem_cache_free(sysfs_dir_cachep, sd); |
01da2425f sysfs: avoid kmem... |
335 336 |
err_out1: kfree(dup_name); |
0c096b507 sysfs: add sysfs_... |
337 |
return NULL; |
1da177e4c Linux-2.6.12-rc2 |
338 |
} |
3007e997d sysfs: use sysfs_... |
339 |
/** |
fb6896da3 sysfs: restructur... |
340 341 342 |
* sysfs_addrm_start - prepare for sysfs_dirent add/remove * @acxt: pointer to sysfs_addrm_cxt to be used * @parent_sd: parent sysfs_dirent |
3007e997d sysfs: use sysfs_... |
343 |
* |
fb6896da3 sysfs: restructur... |
344 345 |
* This function is called when the caller is about to add or * remove sysfs_dirent under @parent_sd. This function acquires |
a16bbc343 sysfs: Gut sysfs_... |
346 |
* sysfs_mutex. @acxt is used to keep and pass context to |
fb6896da3 sysfs: restructur... |
347 |
* other addrm functions. |
3007e997d sysfs: use sysfs_... |
348 349 |
* * LOCKING: |
fb6896da3 sysfs: restructur... |
350 |
* Kernel thread context (may sleep). sysfs_mutex is locked on |
a16bbc343 sysfs: Gut sysfs_... |
351 |
* return. |
3007e997d sysfs: use sysfs_... |
352 |
*/ |
fb6896da3 sysfs: restructur... |
353 354 |
void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *parent_sd) |
b592fcfe7 sysfs: Shadow dir... |
355 |
{ |
fb6896da3 sysfs: restructur... |
356 357 |
memset(acxt, 0, sizeof(*acxt)); acxt->parent_sd = parent_sd; |
fb6896da3 sysfs: restructur... |
358 |
mutex_lock(&sysfs_mutex); |
fb6896da3 sysfs: restructur... |
359 360 361 |
} /** |
36ce6dad6 driver core: Supp... |
362 |
* __sysfs_add_one - add sysfs_dirent to parent without warning |
fb6896da3 sysfs: restructur... |
363 364 365 366 |
* @acxt: addrm context to use * @sd: sysfs_dirent to be added * * Get @acxt->parent_sd and set sd->s_parent to it and increment |
181b2e4be sysfs: fix commen... |
367 368 |
* nlink of parent inode if @sd is a directory and link into the * children list of the parent. |
fb6896da3 sysfs: restructur... |
369 370 371 372 373 374 375 |
* * This function should be called between calls to * sysfs_addrm_start() and sysfs_addrm_finish() and should be * passed the same @acxt as passed to sysfs_addrm_start(). * * LOCKING: * Determined by sysfs_addrm_start(). |
23dc27995 sysfs: make sysfs... |
376 377 378 379 |
* * RETURNS: * 0 on success, -EEXIST if entry with the given name already * exists. |
fb6896da3 sysfs: restructur... |
380 |
*/ |
36ce6dad6 driver core: Supp... |
381 |
int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) |
fb6896da3 sysfs: restructur... |
382 |
{ |
6b0bfe938 sysfs: Update s_i... |
383 |
struct sysfs_inode_attrs *ps_iattr; |
903e21e2e sysfs: Reject wit... |
384 385 386 387 388 389 390 |
if (!!sysfs_ns_type(acxt->parent_sd) != !!sd->s_ns) { WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s' ", sysfs_ns_type(acxt->parent_sd)? "required": "invalid", acxt->parent_sd->s_name, sd->s_name); return -EINVAL; } |
3ff195b01 sysfs: Implement ... |
391 |
if (sysfs_find_dirent(acxt->parent_sd, sd->s_ns, sd->s_name)) |
23dc27995 sysfs: make sysfs... |
392 |
return -EEXIST; |
fb6896da3 sysfs: restructur... |
393 |
sd->s_parent = sysfs_get(acxt->parent_sd); |
41fc1c274 sysfs: make sysfs... |
394 |
sysfs_link_sibling(sd); |
23dc27995 sysfs: make sysfs... |
395 |
|
6b0bfe938 sysfs: Update s_i... |
396 397 398 399 400 401 |
/* Update timestamps on the parent */ ps_iattr = acxt->parent_sd->s_iattr; if (ps_iattr) { struct iattr *ps_iattrs = &ps_iattr->ia_iattr; ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME; } |
23dc27995 sysfs: make sysfs... |
402 |
return 0; |
fb6896da3 sysfs: restructur... |
403 404 405 |
} /** |
425cb0291 sysfs: sysfs_add_... |
406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 |
* sysfs_pathname - return full path to sysfs dirent * @sd: sysfs_dirent whose path we want * @path: caller allocated buffer * * Gives the name "/" to the sysfs_root entry; any path returned * is relative to wherever sysfs is mounted. * * XXX: does no error checking on @path size */ static char *sysfs_pathname(struct sysfs_dirent *sd, char *path) { if (sd->s_parent) { sysfs_pathname(sd->s_parent, path); strcat(path, "/"); } strcat(path, sd->s_name); return path; } /** |
36ce6dad6 driver core: Supp... |
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 |
* sysfs_add_one - add sysfs_dirent to parent * @acxt: addrm context to use * @sd: sysfs_dirent to be added * * Get @acxt->parent_sd and set sd->s_parent to it and increment * nlink of parent inode if @sd is a directory and link into the * children list of the parent. * * This function should be called between calls to * sysfs_addrm_start() and sysfs_addrm_finish() and should be * passed the same @acxt as passed to sysfs_addrm_start(). * * LOCKING: * Determined by sysfs_addrm_start(). * * RETURNS: * 0 on success, -EEXIST if entry with the given name already * exists. */ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) { int ret; ret = __sysfs_add_one(acxt, sd); |
425cb0291 sysfs: sysfs_add_... |
450 451 452 453 454 455 456 457 458 459 |
if (ret == -EEXIST) { char *path = kzalloc(PATH_MAX, GFP_KERNEL); WARN(1, KERN_WARNING "sysfs: cannot create duplicate filename '%s' ", (path == NULL) ? sd->s_name : strcat(strcat(sysfs_pathname(acxt->parent_sd, path), "/"), sd->s_name)); kfree(path); } |
36ce6dad6 driver core: Supp... |
460 461 462 463 |
return ret; } /** |
fb6896da3 sysfs: restructur... |
464 465 |
* sysfs_remove_one - remove sysfs_dirent from parent * @acxt: addrm context to use |
9fd5b1c90 sysfs: Fix a copy... |
466 |
* @sd: sysfs_dirent to be removed |
fb6896da3 sysfs: restructur... |
467 468 |
* * Mark @sd removed and drop nlink of parent inode if @sd is a |
181b2e4be sysfs: fix commen... |
469 |
* directory. @sd is unlinked from the children list. |
fb6896da3 sysfs: restructur... |
470 471 472 473 474 475 476 477 478 479 |
* * This function should be called between calls to * sysfs_addrm_start() and sysfs_addrm_finish() and should be * passed the same @acxt as passed to sysfs_addrm_start(). * * LOCKING: * Determined by sysfs_addrm_start(). */ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) { |
6b0bfe938 sysfs: Update s_i... |
480 |
struct sysfs_inode_attrs *ps_iattr; |
41fc1c274 sysfs: make sysfs... |
481 482 483 |
BUG_ON(sd->s_flags & SYSFS_FLAG_REMOVED); sysfs_unlink_sibling(sd); |
fb6896da3 sysfs: restructur... |
484 |
|
6b0bfe938 sysfs: Update s_i... |
485 486 487 488 489 490 |
/* Update timestamps on the parent */ ps_iattr = acxt->parent_sd->s_iattr; if (ps_iattr) { struct iattr *ps_iattrs = &ps_iattr->ia_iattr; ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME; } |
fb6896da3 sysfs: restructur... |
491 |
sd->s_flags |= SYSFS_FLAG_REMOVED; |
58f2a4c79 sysfs: remove s_s... |
492 |
sd->u.removed_list = acxt->removed; |
fb6896da3 sysfs: restructur... |
493 |
acxt->removed = sd; |
a0edd7c84 sysfs: move sysfs... |
494 495 496 |
} /** |
fb6896da3 sysfs: restructur... |
497 498 499 500 501 |
* sysfs_addrm_finish - finish up sysfs_dirent add/remove * @acxt: addrm context to finish up * * Finish up sysfs_dirent add/remove. Resources acquired by * sysfs_addrm_start() are released and removed sysfs_dirents are |
a16bbc343 sysfs: Gut sysfs_... |
502 |
* cleaned up. |
fb6896da3 sysfs: restructur... |
503 504 |
* * LOCKING: |
a16bbc343 sysfs: Gut sysfs_... |
505 |
* sysfs_mutex is released. |
fb6896da3 sysfs: restructur... |
506 |
*/ |
990e53f88 sysfs: make sysfs... |
507 |
void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) |
fb6896da3 sysfs: restructur... |
508 509 510 |
{ /* release resources acquired by sysfs_addrm_start() */ mutex_unlock(&sysfs_mutex); |
fb6896da3 sysfs: restructur... |
511 512 513 514 |
/* kill removed sysfs_dirents */ while (acxt->removed) { struct sysfs_dirent *sd = acxt->removed; |
58f2a4c79 sysfs: remove s_s... |
515 |
acxt->removed = sd->u.removed_list; |
fb6896da3 sysfs: restructur... |
516 |
|
fb6896da3 sysfs: restructur... |
517 |
sysfs_deactivate(sd); |
e0edd3c65 sysfs: don't bloc... |
518 |
unmap_bin_file(sd); |
fb6896da3 sysfs: restructur... |
519 |
sysfs_put(sd); |
13b3086d2 sysfs: add sysfs_... |
520 |
} |
b592fcfe7 sysfs: Shadow dir... |
521 |
} |
f0b0af479 sysfs: implement ... |
522 523 524 525 526 527 |
/** * sysfs_find_dirent - find sysfs_dirent with the given name * @parent_sd: sysfs_dirent to search under * @name: name to look for * * Look for sysfs_dirent with name @name under @parent_sd. |
c516865cf [PATCH] sysfs: fi... |
528 |
* |
f0b0af479 sysfs: implement ... |
529 |
* LOCKING: |
3007e997d sysfs: use sysfs_... |
530 |
* mutex_lock(sysfs_mutex) |
c516865cf [PATCH] sysfs: fi... |
531 |
* |
f0b0af479 sysfs: implement ... |
532 533 |
* RETURNS: * Pointer to sysfs_dirent if found, NULL if not. |
c516865cf [PATCH] sysfs: fi... |
534 |
*/ |
f0b0af479 sysfs: implement ... |
535 |
struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, |
3ff195b01 sysfs: Implement ... |
536 |
const void *ns, |
f0b0af479 sysfs: implement ... |
537 |
const unsigned char *name) |
c516865cf [PATCH] sysfs: fi... |
538 |
{ |
4f72c0cab sysfs: use rb-tre... |
539 540 |
struct rb_node *p = parent_sd->s_dir.name_tree.rb_node; struct sysfs_dirent *found = NULL; |
903e21e2e sysfs: Reject wit... |
541 542 543 544 545 546 547 |
if (!!sysfs_ns_type(parent_sd) != !!ns) { WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s' ", sysfs_ns_type(parent_sd)? "required": "invalid", parent_sd->s_name, name); return NULL; } |
4f72c0cab sysfs: use rb-tre... |
548 549 550 551 552 553 554 555 556 557 558 559 560 561 |
while (p) { int c; #define node rb_entry(p, struct sysfs_dirent, name_node) c = strcmp(name, node->s_name); if (c < 0) { p = node->name_node.rb_left; } else if (c > 0) { p = node->name_node.rb_right; } else { found = node; p = node->name_node.rb_left; } #undef node } |
f0b0af479 sysfs: implement ... |
562 |
|
b9e2780d5 sysfs: Remove sup... |
563 564 |
if (found) { while (found->s_ns != ns) { |
4f72c0cab sysfs: use rb-tre... |
565 566 567 568 569 570 571 |
p = rb_next(&found->name_node); if (!p) return NULL; found = rb_entry(p, struct sysfs_dirent, name_node); if (strcmp(name, found->s_name)) return NULL; } |
3ff195b01 sysfs: Implement ... |
572 |
} |
4f72c0cab sysfs: use rb-tre... |
573 574 |
return found; |
f0b0af479 sysfs: implement ... |
575 |
} |
c516865cf [PATCH] sysfs: fi... |
576 |
|
f0b0af479 sysfs: implement ... |
577 578 579 580 581 582 583 584 585 |
/** * sysfs_get_dirent - find and get sysfs_dirent with the given name * @parent_sd: sysfs_dirent to search under * @name: name to look for * * Look for sysfs_dirent with name @name under @parent_sd and get * it if found. * * LOCKING: |
3007e997d sysfs: use sysfs_... |
586 |
* Kernel thread context (may sleep). Grabs sysfs_mutex. |
f0b0af479 sysfs: implement ... |
587 588 589 590 591 |
* * RETURNS: * Pointer to sysfs_dirent if found, NULL if not. */ struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, |
3ff195b01 sysfs: Implement ... |
592 |
const void *ns, |
f0b0af479 sysfs: implement ... |
593 594 595 |
const unsigned char *name) { struct sysfs_dirent *sd; |
3007e997d sysfs: use sysfs_... |
596 |
mutex_lock(&sysfs_mutex); |
3ff195b01 sysfs: Implement ... |
597 |
sd = sysfs_find_dirent(parent_sd, ns, name); |
f0b0af479 sysfs: implement ... |
598 |
sysfs_get(sd); |
3007e997d sysfs: use sysfs_... |
599 |
mutex_unlock(&sysfs_mutex); |
f0b0af479 sysfs: implement ... |
600 601 |
return sd; |
c516865cf [PATCH] sysfs: fi... |
602 |
} |
f1282c844 sysfs: Support sy... |
603 |
EXPORT_SYMBOL_GPL(sysfs_get_dirent); |
c516865cf [PATCH] sysfs: fi... |
604 |
|
608e266a2 sysfs: make kobj ... |
605 |
static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, |
3ff195b01 sysfs: Implement ... |
606 607 |
enum kobj_ns_type type, const void *ns, const char *name, struct sysfs_dirent **p_sd) |
1da177e4c Linux-2.6.12-rc2 |
608 |
{ |
1da177e4c Linux-2.6.12-rc2 |
609 |
umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; |
51225039f sysfs: make direc... |
610 |
struct sysfs_addrm_cxt acxt; |
dfeb9fb03 sysfs: flatten cl... |
611 |
struct sysfs_dirent *sd; |
23dc27995 sysfs: make sysfs... |
612 |
int rc; |
1da177e4c Linux-2.6.12-rc2 |
613 |
|
fc9f54b99 sysfs: reorganize... |
614 |
/* allocate */ |
3e5190380 sysfs: make sysfs... |
615 |
sd = sysfs_new_dirent(name, mode, SYSFS_DIR); |
a26cd7226 sysfs: consolidat... |
616 |
if (!sd) |
51225039f sysfs: make direc... |
617 |
return -ENOMEM; |
3ff195b01 sysfs: Implement ... |
618 619 620 |
sd->s_flags |= (type << SYSFS_NS_TYPE_SHIFT); sd->s_ns = ns; |
b1fc3d614 sysfs: make s_ele... |
621 |
sd->s_dir.kobj = kobj; |
dfeb9fb03 sysfs: flatten cl... |
622 |
|
fc9f54b99 sysfs: reorganize... |
623 |
/* link in */ |
51225039f sysfs: make direc... |
624 |
sysfs_addrm_start(&acxt, parent_sd); |
23dc27995 sysfs: make sysfs... |
625 626 |
rc = sysfs_add_one(&acxt, sd); sysfs_addrm_finish(&acxt); |
967e35dcc sysfs: cosmetic c... |
627 |
|
23dc27995 sysfs: make sysfs... |
628 629 630 |
if (rc == 0) *p_sd = sd; else |
967e35dcc sysfs: cosmetic c... |
631 |
sysfs_put(sd); |
dfeb9fb03 sysfs: flatten cl... |
632 |
|
23dc27995 sysfs: make sysfs... |
633 |
return rc; |
1da177e4c Linux-2.6.12-rc2 |
634 |
} |
608e266a2 sysfs: make kobj ... |
635 636 |
int sysfs_create_subdir(struct kobject *kobj, const char *name, struct sysfs_dirent **p_sd) |
1da177e4c Linux-2.6.12-rc2 |
637 |
{ |
3ff195b01 sysfs: Implement ... |
638 639 640 |
return create_dir(kobj, kobj->sd, KOBJ_NS_TYPE_NONE, NULL, name, p_sd); } |
be867b194 sysfs: Comment sy... |
641 642 643 644 645 646 647 648 |
/** * sysfs_read_ns_type: return associated ns_type * @kobj: the kobject being queried * * Each kobject can be tagged with exactly one namespace type * (i.e. network or user). Return the ns_type associated with * this object if any */ |
3ff195b01 sysfs: Implement ... |
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 |
static enum kobj_ns_type sysfs_read_ns_type(struct kobject *kobj) { const struct kobj_ns_type_operations *ops; enum kobj_ns_type type; ops = kobj_child_ns_ops(kobj); if (!ops) return KOBJ_NS_TYPE_NONE; type = ops->type; BUG_ON(type <= KOBJ_NS_TYPE_NONE); BUG_ON(type >= KOBJ_NS_TYPES); BUG_ON(!kobj_ns_type_registered(type)); return type; |
1da177e4c Linux-2.6.12-rc2 |
664 665 666 667 |
} /** * sysfs_create_dir - create a directory for an object. |
1da177e4c Linux-2.6.12-rc2 |
668 669 |
* @kobj: object we're creating directory for. */ |
90bc61359 sysfs: Remove fir... |
670 |
int sysfs_create_dir(struct kobject * kobj) |
1da177e4c Linux-2.6.12-rc2 |
671 |
{ |
3ff195b01 sysfs: Implement ... |
672 |
enum kobj_ns_type type; |
608e266a2 sysfs: make kobj ... |
673 |
struct sysfs_dirent *parent_sd, *sd; |
3ff195b01 sysfs: Implement ... |
674 |
const void *ns = NULL; |
1da177e4c Linux-2.6.12-rc2 |
675 676 677 |
int error = 0; BUG_ON(!kobj); |
90bc61359 sysfs: Remove fir... |
678 |
if (kobj->parent) |
608e266a2 sysfs: make kobj ... |
679 |
parent_sd = kobj->parent->sd; |
1da177e4c Linux-2.6.12-rc2 |
680 |
else |
7d0c7d676 sysfs: Make sysfs... |
681 |
parent_sd = &sysfs_root; |
1da177e4c Linux-2.6.12-rc2 |
682 |
|
3ff195b01 sysfs: Implement ... |
683 684 685 686 687 |
if (sysfs_ns_type(parent_sd)) ns = kobj->ktype->namespace(kobj); type = sysfs_read_ns_type(kobj); error = create_dir(kobj, parent_sd, type, ns, kobject_name(kobj), &sd); |
1da177e4c Linux-2.6.12-rc2 |
688 |
if (!error) |
608e266a2 sysfs: make kobj ... |
689 |
kobj->sd = sd; |
1da177e4c Linux-2.6.12-rc2 |
690 691 |
return error; } |
1da177e4c Linux-2.6.12-rc2 |
692 693 694 |
static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { |
6cb52147b sysfs: fix lockin... |
695 |
struct dentry *ret = NULL; |
3ff195b01 sysfs: Implement ... |
696 697 |
struct dentry *parent = dentry->d_parent; struct sysfs_dirent *parent_sd = parent->d_fsdata; |
a7a047549 sysfs: cosmetic c... |
698 |
struct sysfs_dirent *sd; |
fc9f54b99 sysfs: reorganize... |
699 |
struct inode *inode; |
3ff195b01 sysfs: Implement ... |
700 701 |
enum kobj_ns_type type; const void *ns; |
1da177e4c Linux-2.6.12-rc2 |
702 |
|
6cb52147b sysfs: fix lockin... |
703 |
mutex_lock(&sysfs_mutex); |
3ff195b01 sysfs: Implement ... |
704 705 706 707 |
type = sysfs_ns_type(parent_sd); ns = sysfs_info(dir->i_sb)->ns[type]; sd = sysfs_find_dirent(parent_sd, ns, dentry->d_name.name); |
1da177e4c Linux-2.6.12-rc2 |
708 |
|
fc9f54b99 sysfs: reorganize... |
709 |
/* no such entry */ |
e49452c67 sysfs: make sysfs... |
710 711 |
if (!sd) { ret = ERR_PTR(-ENOENT); |
6cb52147b sysfs: fix lockin... |
712 |
goto out_unlock; |
e49452c67 sysfs: make sysfs... |
713 |
} |
fc9f54b99 sysfs: reorganize... |
714 715 |
/* attach dentry and inode */ |
fac2622bb sysfs: Pass super... |
716 |
inode = sysfs_get_inode(dir->i_sb, sd); |
6cb52147b sysfs: fix lockin... |
717 718 719 720 |
if (!inode) { ret = ERR_PTR(-ENOMEM); goto out_unlock; } |
3007e997d sysfs: use sysfs_... |
721 |
|
d6b4fd2fa sysfs: open code ... |
722 |
/* instantiate and hash dentry */ |
832b6af19 sysfs: Propagate ... |
723 724 |
ret = d_find_alias(inode); if (!ret) { |
fb045adb9 fs: dcache reduce... |
725 |
d_set_d_op(dentry, &sysfs_dentry_ops); |
832b6af19 sysfs: Propagate ... |
726 727 728 729 730 731 |
dentry->d_fsdata = sysfs_get(sd); d_add(dentry, inode); } else { d_move(ret, dentry); iput(inode); } |
fc9f54b99 sysfs: reorganize... |
732 |
|
6cb52147b sysfs: fix lockin... |
733 |
out_unlock: |
3007e997d sysfs: use sysfs_... |
734 |
mutex_unlock(&sysfs_mutex); |
6cb52147b sysfs: fix lockin... |
735 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
736 |
} |
c5ef1c42c [PATCH] mark stru... |
737 |
const struct inode_operations sysfs_dir_inode_operations = { |
1da177e4c Linux-2.6.12-rc2 |
738 |
.lookup = sysfs_lookup, |
e61ab4ae4 sysfs: Implement ... |
739 |
.permission = sysfs_permission, |
988d186de [PATCH] sysfs-iat... |
740 |
.setattr = sysfs_setattr, |
e61ab4ae4 sysfs: Implement ... |
741 |
.getattr = sysfs_getattr, |
ddd29ec65 sysfs: Add labeli... |
742 |
.setxattr = sysfs_setxattr, |
1da177e4c Linux-2.6.12-rc2 |
743 |
}; |
608e266a2 sysfs: make kobj ... |
744 |
static void remove_dir(struct sysfs_dirent *sd) |
1da177e4c Linux-2.6.12-rc2 |
745 |
{ |
fb6896da3 sysfs: restructur... |
746 |
struct sysfs_addrm_cxt acxt; |
1da177e4c Linux-2.6.12-rc2 |
747 |
|
fb6896da3 sysfs: restructur... |
748 |
sysfs_addrm_start(&acxt, sd->s_parent); |
fb6896da3 sysfs: restructur... |
749 750 |
sysfs_remove_one(&acxt, sd); sysfs_addrm_finish(&acxt); |
1da177e4c Linux-2.6.12-rc2 |
751 |
} |
608e266a2 sysfs: make kobj ... |
752 |
void sysfs_remove_subdir(struct sysfs_dirent *sd) |
1da177e4c Linux-2.6.12-rc2 |
753 |
{ |
608e266a2 sysfs: make kobj ... |
754 |
remove_dir(sd); |
1da177e4c Linux-2.6.12-rc2 |
755 |
} |
608e266a2 sysfs: make kobj ... |
756 |
static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd) |
1da177e4c Linux-2.6.12-rc2 |
757 |
{ |
fb6896da3 sysfs: restructur... |
758 |
struct sysfs_addrm_cxt acxt; |
a406f7584 sysfs: use rb-tre... |
759 |
struct rb_node *pos; |
1da177e4c Linux-2.6.12-rc2 |
760 |
|
608e266a2 sysfs: make kobj ... |
761 |
if (!dir_sd) |
1da177e4c Linux-2.6.12-rc2 |
762 |
return; |
608e266a2 sysfs: make kobj ... |
763 764 |
pr_debug("sysfs %s: removing dir ", dir_sd->s_name); |
fb6896da3 sysfs: restructur... |
765 |
sysfs_addrm_start(&acxt, dir_sd); |
a406f7584 sysfs: use rb-tre... |
766 767 768 769 |
pos = rb_first(&dir_sd->s_dir.inode_tree); while (pos) { struct sysfs_dirent *sd = rb_entry(pos, struct sysfs_dirent, inode_node); pos = rb_next(pos); |
3efa65b92 sysfs: Simplify r... |
770 |
if (sysfs_type(sd) != SYSFS_DIR) |
fb6896da3 sysfs: restructur... |
771 |
sysfs_remove_one(&acxt, sd); |
1da177e4c Linux-2.6.12-rc2 |
772 |
} |
fb6896da3 sysfs: restructur... |
773 |
sysfs_addrm_finish(&acxt); |
0ab66088c sysfs: implement ... |
774 |
|
608e266a2 sysfs: make kobj ... |
775 |
remove_dir(dir_sd); |
b592fcfe7 sysfs: Shadow dir... |
776 777 778 779 780 781 782 783 784 785 786 787 788 |
} /** * sysfs_remove_dir - remove an object's directory. * @kobj: object. * * The only thing special about this is that we remove any files in * the directory before we remove the directory, and we've inlined * what used to be sysfs_rmdir() below, instead of calling separately. */ void sysfs_remove_dir(struct kobject * kobj) { |
608e266a2 sysfs: make kobj ... |
789 |
struct sysfs_dirent *sd = kobj->sd; |
aecdcedaa sysfs: implement ... |
790 |
|
5f9953237 sysfs: consolidat... |
791 |
spin_lock(&sysfs_assoc_lock); |
608e266a2 sysfs: make kobj ... |
792 |
kobj->sd = NULL; |
5f9953237 sysfs: consolidat... |
793 |
spin_unlock(&sysfs_assoc_lock); |
aecdcedaa sysfs: implement ... |
794 |
|
608e266a2 sysfs: make kobj ... |
795 |
__sysfs_remove_dir(sd); |
1da177e4c Linux-2.6.12-rc2 |
796 |
} |
ca1bab381 sysfs: Factor out... |
797 |
int sysfs_rename(struct sysfs_dirent *sd, |
3ff195b01 sysfs: Implement ... |
798 799 |
struct sysfs_dirent *new_parent_sd, const void *new_ns, const char *new_name) |
1da177e4c Linux-2.6.12-rc2 |
800 |
{ |
51225039f sysfs: make direc... |
801 |
const char *dup_name = NULL; |
996b73764 sysfs: flatten an... |
802 |
int error; |
1da177e4c Linux-2.6.12-rc2 |
803 |
|
832b6af19 sysfs: Propagate ... |
804 |
mutex_lock(&sysfs_mutex); |
932ea2e37 sysfs: Introduce ... |
805 |
|
9918f9a48 sysfs: Rewrite re... |
806 |
error = 0; |
3ff195b01 sysfs: Implement ... |
807 |
if ((sd->s_parent == new_parent_sd) && (sd->s_ns == new_ns) && |
ca1bab381 sysfs: Factor out... |
808 |
(strcmp(sd->s_name, new_name) == 0)) |
9918f9a48 sysfs: Rewrite re... |
809 |
goto out; /* nothing to rename */ |
9918f9a48 sysfs: Rewrite re... |
810 |
error = -EEXIST; |
3ff195b01 sysfs: Implement ... |
811 |
if (sysfs_find_dirent(new_parent_sd, new_ns, new_name)) |
832b6af19 sysfs: Propagate ... |
812 |
goto out; |
996b73764 sysfs: flatten an... |
813 |
|
0b4a4fea2 kobject: Cleanup ... |
814 |
/* rename sysfs_dirent */ |
ca1bab381 sysfs: Factor out... |
815 816 817 818 819 820 821 822 823 |
if (strcmp(sd->s_name, new_name) != 0) { error = -ENOMEM; new_name = dup_name = kstrdup(new_name, GFP_KERNEL); if (!new_name) goto out; dup_name = sd->s_name; sd->s_name = new_name; } |
0c096b507 sysfs: add sysfs_... |
824 |
|
f6d90b4f9 sysfs: Make sysfs... |
825 826 827 828 |
/* Move to the appropriate place in the appropriate directories rbtree. */ sysfs_unlink_sibling(sd); sysfs_get(new_parent_sd); sysfs_put(sd->s_parent); |
3ff195b01 sysfs: Implement ... |
829 |
sd->s_ns = new_ns; |
f6d90b4f9 sysfs: Make sysfs... |
830 831 |
sd->s_parent = new_parent_sd; sysfs_link_sibling(sd); |
0c096b507 sysfs: add sysfs_... |
832 |
|
996b73764 sysfs: flatten an... |
833 |
error = 0; |
832b6af19 sysfs: Propagate ... |
834 |
out: |
9918f9a48 sysfs: Rewrite re... |
835 |
mutex_unlock(&sysfs_mutex); |
51225039f sysfs: make direc... |
836 |
kfree(dup_name); |
1da177e4c Linux-2.6.12-rc2 |
837 838 |
return error; } |
ca1bab381 sysfs: Factor out... |
839 840 |
int sysfs_rename_dir(struct kobject *kobj, const char *new_name) { |
3ff195b01 sysfs: Implement ... |
841 842 843 844 845 846 847 |
struct sysfs_dirent *parent_sd = kobj->sd->s_parent; const void *new_ns = NULL; if (sysfs_ns_type(parent_sd)) new_ns = kobj->ktype->namespace(kobj); return sysfs_rename(kobj->sd, parent_sd, new_ns, new_name); |
ca1bab381 sysfs: Factor out... |
848 |
} |
51225039f sysfs: make direc... |
849 |
int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) |
8a82472f8 driver core: Intr... |
850 |
{ |
51225039f sysfs: make direc... |
851 852 |
struct sysfs_dirent *sd = kobj->sd; struct sysfs_dirent *new_parent_sd; |
3ff195b01 sysfs: Implement ... |
853 |
const void *new_ns = NULL; |
8a82472f8 driver core: Intr... |
854 |
|
51225039f sysfs: make direc... |
855 |
BUG_ON(!sd->s_parent); |
3ff195b01 sysfs: Implement ... |
856 857 |
if (sysfs_ns_type(sd->s_parent)) new_ns = kobj->ktype->namespace(kobj); |
ca1bab381 sysfs: Factor out... |
858 |
new_parent_sd = new_parent_kobj && new_parent_kobj->sd ? |
a6a835778 sysfs: Allow sysf... |
859 |
new_parent_kobj->sd : &sysfs_root; |
51225039f sysfs: make direc... |
860 |
|
3ff195b01 sysfs: Implement ... |
861 |
return sysfs_rename(sd, new_parent_sd, new_ns, sd->s_name); |
8a82472f8 driver core: Intr... |
862 |
} |
1da177e4c Linux-2.6.12-rc2 |
863 864 865 866 867 |
/* Relationship between s_mode and the DT_xxx types */ static inline unsigned char dt_type(struct sysfs_dirent *sd) { return (sd->s_mode >> 12) & 15; } |
1e5289c97 sysfs: Cache the ... |
868 869 870 871 872 |
static int sysfs_dir_release(struct inode *inode, struct file *filp) { sysfs_put(filp->private_data); return 0; } |
3ff195b01 sysfs: Implement ... |
873 874 |
static struct sysfs_dirent *sysfs_dir_pos(const void *ns, struct sysfs_dirent *parent_sd, ino_t ino, struct sysfs_dirent *pos) |
1e5289c97 sysfs: Cache the ... |
875 876 877 878 879 880 |
{ if (pos) { int valid = !(pos->s_flags & SYSFS_FLAG_REMOVED) && pos->s_parent == parent_sd && ino == pos->s_ino; sysfs_put(pos); |
3ff195b01 sysfs: Implement ... |
881 882 |
if (!valid) pos = NULL; |
1e5289c97 sysfs: Cache the ... |
883 |
} |
3ff195b01 sysfs: Implement ... |
884 |
if (!pos && (ino > 1) && (ino < INT_MAX)) { |
a406f7584 sysfs: use rb-tre... |
885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 |
struct rb_node *p = parent_sd->s_dir.inode_tree.rb_node; while (p) { #define node rb_entry(p, struct sysfs_dirent, inode_node) if (ino < node->s_ino) { pos = node; p = node->inode_node.rb_left; } else if (ino > node->s_ino) { p = node->inode_node.rb_right; } else { pos = node; break; } #undef node } } |
b9e2780d5 sysfs: Remove sup... |
900 |
while (pos && pos->s_ns != ns) { |
a406f7584 sysfs: use rb-tre... |
901 902 903 904 905 |
struct rb_node *p = rb_next(&pos->inode_node); if (!p) pos = NULL; else pos = rb_entry(p, struct sysfs_dirent, inode_node); |
1e5289c97 sysfs: Cache the ... |
906 907 908 |
} return pos; } |
3ff195b01 sysfs: Implement ... |
909 910 |
static struct sysfs_dirent *sysfs_dir_next_pos(const void *ns, struct sysfs_dirent *parent_sd, ino_t ino, struct sysfs_dirent *pos) |
1e5289c97 sysfs: Cache the ... |
911 |
{ |
3ff195b01 sysfs: Implement ... |
912 |
pos = sysfs_dir_pos(ns, parent_sd, ino, pos); |
a406f7584 sysfs: use rb-tre... |
913 914 915 916 917 918 |
if (pos) do { struct rb_node *p = rb_next(&pos->inode_node); if (!p) pos = NULL; else pos = rb_entry(p, struct sysfs_dirent, inode_node); |
b9e2780d5 sysfs: Remove sup... |
919 |
} while (pos && pos->s_ns != ns); |
1e5289c97 sysfs: Cache the ... |
920 921 |
return pos; } |
1da177e4c Linux-2.6.12-rc2 |
922 923 |
static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) { |
f427f5d5d [PATCH] sysfs: ch... |
924 |
struct dentry *dentry = filp->f_path.dentry; |
1da177e4c Linux-2.6.12-rc2 |
925 |
struct sysfs_dirent * parent_sd = dentry->d_fsdata; |
1e5289c97 sysfs: Cache the ... |
926 |
struct sysfs_dirent *pos = filp->private_data; |
3ff195b01 sysfs: Implement ... |
927 928 |
enum kobj_ns_type type; const void *ns; |
1da177e4c Linux-2.6.12-rc2 |
929 |
ino_t ino; |
1da177e4c Linux-2.6.12-rc2 |
930 |
|
3ff195b01 sysfs: Implement ... |
931 932 |
type = sysfs_ns_type(parent_sd); ns = sysfs_info(dentry->d_sb)->ns[type]; |
3efa65b92 sysfs: Simplify r... |
933 934 935 |
if (filp->f_pos == 0) { ino = parent_sd->s_ino; if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) == 0) |
1da177e4c Linux-2.6.12-rc2 |
936 |
filp->f_pos++; |
3efa65b92 sysfs: Simplify r... |
937 938 939 940 941 942 943 |
} if (filp->f_pos == 1) { if (parent_sd->s_parent) ino = parent_sd->s_parent->s_ino; else ino = parent_sd->s_ino; if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) == 0) |
1da177e4c Linux-2.6.12-rc2 |
944 |
filp->f_pos++; |
3efa65b92 sysfs: Simplify r... |
945 |
} |
1e5289c97 sysfs: Cache the ... |
946 |
mutex_lock(&sysfs_mutex); |
3ff195b01 sysfs: Implement ... |
947 |
for (pos = sysfs_dir_pos(ns, parent_sd, filp->f_pos, pos); |
1e5289c97 sysfs: Cache the ... |
948 |
pos; |
3ff195b01 sysfs: Implement ... |
949 |
pos = sysfs_dir_next_pos(ns, parent_sd, filp->f_pos, pos)) { |
1e5289c97 sysfs: Cache the ... |
950 951 952 953 954 955 956 957 958 959 |
const char * name; unsigned int type; int len, ret; name = pos->s_name; len = strlen(name); ino = pos->s_ino; type = dt_type(pos); filp->f_pos = ino; filp->private_data = sysfs_get(pos); |
1da177e4c Linux-2.6.12-rc2 |
960 |
|
3007e997d sysfs: use sysfs_... |
961 |
mutex_unlock(&sysfs_mutex); |
1e5289c97 sysfs: Cache the ... |
962 963 964 965 966 967 968 969 970 |
ret = filldir(dirent, name, len, filp->f_pos, ino, type); mutex_lock(&sysfs_mutex); if (ret < 0) break; } mutex_unlock(&sysfs_mutex); if ((filp->f_pos > 1) && !pos) { /* EOF */ filp->f_pos = INT_MAX; filp->private_data = NULL; |
1da177e4c Linux-2.6.12-rc2 |
971 |
} |
3efa65b92 sysfs: Simplify r... |
972 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
973 |
} |
3efa65b92 sysfs: Simplify r... |
974 |
|
4b6f5d20b [PATCH] Make most... |
975 |
const struct file_operations sysfs_dir_operations = { |
1da177e4c Linux-2.6.12-rc2 |
976 977 |
.read = generic_read_dir, .readdir = sysfs_readdir, |
1e5289c97 sysfs: Cache the ... |
978 |
.release = sysfs_dir_release, |
3222a3e55 [PATCH] fix ->lls... |
979 |
.llseek = generic_file_llseek, |
1da177e4c Linux-2.6.12-rc2 |
980 |
}; |