sysfs: make sysfs_alloc_ino() static
[deliverable/linux.git] / fs / sysfs / dir.c
CommitLineData
1da177e4
LT
1/*
2 * dir.c - Operations for sysfs directories.
3 */
4
5#undef DEBUG
6
7#include <linux/fs.h>
8#include <linux/mount.h>
9#include <linux/module.h>
10#include <linux/kobject.h>
5f45f1a7 11#include <linux/namei.h>
2b611bb7 12#include <linux/idr.h>
94bebf4d 13#include <asm/semaphore.h>
1da177e4
LT
14#include "sysfs.h"
15
16DECLARE_RWSEM(sysfs_rename_sem);
dd14cbc9 17spinlock_t sysfs_lock = SPIN_LOCK_UNLOCKED;
aecdceda 18spinlock_t kobj_sysfs_assoc_lock = SPIN_LOCK_UNLOCKED;
1da177e4 19
2b611bb7
TH
20static spinlock_t sysfs_ino_lock = SPIN_LOCK_UNLOCKED;
21static DEFINE_IDA(sysfs_ino_ida);
22
42b37df6 23static int sysfs_alloc_ino(ino_t *pino)
2b611bb7
TH
24{
25 int ino, rc;
26
27 retry:
28 spin_lock(&sysfs_ino_lock);
29 rc = ida_get_new_above(&sysfs_ino_ida, 2, &ino);
30 spin_unlock(&sysfs_ino_lock);
31
32 if (rc == -EAGAIN) {
33 if (ida_pre_get(&sysfs_ino_ida, GFP_KERNEL))
34 goto retry;
35 rc = -ENOMEM;
36 }
37
38 *pino = ino;
39 return rc;
40}
41
42static void sysfs_free_ino(ino_t ino)
43{
44 spin_lock(&sysfs_ino_lock);
45 ida_remove(&sysfs_ino_ida, ino);
46 spin_unlock(&sysfs_ino_lock);
47}
48
fa7f912a
TH
49void release_sysfs_dirent(struct sysfs_dirent * sd)
50{
13b3086d
TH
51 struct sysfs_dirent *parent_sd;
52
53 repeat:
54 parent_sd = sd->s_parent;
55
0ab66088
TH
56 /* If @sd is being released after deletion, s_active is write
57 * locked. If @sd is cursor for directory walk or being
58 * released prematurely, s_active has no reader or writer.
59 *
60 * sysfs_deactivate() lies to lockdep that s_active is
61 * unlocked immediately. Lie one more time to cover the
62 * previous lie.
63 */
64 if (!down_write_trylock(&sd->s_active))
65 rwsem_acquire(&sd->s_active.dep_map,
66 SYSFS_S_ACTIVE_DEACTIVATE, 0, _RET_IP_);
67 up_write(&sd->s_active);
68
3e519038 69 if (sd->s_type & SYSFS_KOBJ_LINK)
2b29ac25 70 sysfs_put(sd->s_elem.symlink.target_sd);
0c096b50
TH
71 if (sd->s_type & SYSFS_COPY_NAME)
72 kfree(sd->s_name);
fa7f912a 73 kfree(sd->s_iattr);
2b611bb7 74 sysfs_free_ino(sd->s_ino);
fa7f912a 75 kmem_cache_free(sysfs_dir_cachep, sd);
13b3086d
TH
76
77 sd = parent_sd;
78 if (sd && atomic_dec_and_test(&sd->s_count))
79 goto repeat;
fa7f912a
TH
80}
81
1da177e4
LT
82static void sysfs_d_iput(struct dentry * dentry, struct inode * inode)
83{
84 struct sysfs_dirent * sd = dentry->d_fsdata;
85
86 if (sd) {
dd14cbc9
TH
87 /* sd->s_dentry is protected with sysfs_lock. This
88 * allows sysfs_drop_dentry() to dereference it.
89 */
90 spin_lock(&sysfs_lock);
91
92 /* The dentry might have been deleted or another
93 * lookup could have happened updating sd->s_dentry to
94 * point the new dentry. Ignore if it isn't pointing
95 * to this dentry.
96 */
97 if (sd->s_dentry == dentry)
98 sd->s_dentry = NULL;
99 spin_unlock(&sysfs_lock);
1da177e4
LT
100 sysfs_put(sd);
101 }
102 iput(inode);
103}
104
105static struct dentry_operations sysfs_dentry_ops = {
106 .d_iput = sysfs_d_iput,
107};
108
3e519038 109struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
1da177e4 110{
0c096b50
TH
111 char *dup_name = NULL;
112 struct sysfs_dirent *sd = NULL;
113
114 if (type & SYSFS_COPY_NAME) {
115 name = dup_name = kstrdup(name, GFP_KERNEL);
116 if (!name)
117 goto err_out;
118 }
1da177e4 119
c3762229 120 sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL);
1da177e4 121 if (!sd)
0c096b50 122 goto err_out;
1da177e4 123
0c096b50
TH
124 if (sysfs_alloc_ino(&sd->s_ino))
125 goto err_out;
2b611bb7 126
1da177e4 127 atomic_set(&sd->s_count, 1);