diff options
Diffstat (limited to 'fs/sysfs')
-rw-r--r-- | fs/sysfs/dir.c | 88 | ||||
-rw-r--r-- | fs/sysfs/sysfs.h | 94 |
2 files changed, 94 insertions, 88 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 06dff2c30c9b..f5f0b936f181 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -20,6 +20,94 @@ spinlock_t kobj_sysfs_assoc_lock = SPIN_LOCK_UNLOCKED; | |||
20 | static spinlock_t sysfs_ino_lock = SPIN_LOCK_UNLOCKED; | 20 | static spinlock_t sysfs_ino_lock = SPIN_LOCK_UNLOCKED; |
21 | static DEFINE_IDA(sysfs_ino_ida); | 21 | static DEFINE_IDA(sysfs_ino_ida); |
22 | 22 | ||
23 | /** | ||
24 | * sysfs_get_active - get an active reference to sysfs_dirent | ||
25 | * @sd: sysfs_dirent to get an active reference to | ||
26 | * | ||
27 | * Get an active reference of @sd. This function is noop if @sd | ||
28 | * is NULL. | ||
29 | * | ||
30 | * RETURNS: | ||
31 | * Pointer to @sd on success, NULL on failure. | ||
32 | */ | ||
33 | struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) | ||
34 | { | ||
35 | if (sd) { | ||
36 | if (unlikely(!down_read_trylock(&sd->s_active))) | ||
37 | sd = NULL; | ||
38 | } | ||
39 | return sd; | ||
40 | } | ||
41 | |||
42 | /** | ||
43 | * sysfs_put_active - put an active reference to sysfs_dirent | ||
44 | * @sd: sysfs_dirent to put an active reference to | ||
45 | * | ||
46 | * Put an active reference to @sd. This function is noop if @sd | ||
47 | * is NULL. | ||
48 | */ | ||
49 | void sysfs_put_active(struct sysfs_dirent *sd) | ||
50 | { | ||
51 | if (sd) | ||
52 | up_read(&sd->s_active); | ||
53 | } | ||
54 | |||
55 | /** | ||
56 | * sysfs_get_active_two - get active references to sysfs_dirent and parent | ||
57 | * @sd: sysfs_dirent of interest | ||
58 | * | ||
59 | * Get active reference to @sd and its parent. Parent's active | ||
60 | * reference is grabbed first. This function is noop if @sd is | ||
61 | * NULL. | ||
62 | * | ||
63 | * RETURNS: | ||
64 | * Pointer to @sd on success, NULL on failure. | ||
65 | */ | ||
66 | struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd) | ||
67 | { | ||
68 | if (sd) { | ||
69 | if (sd->s_parent && unlikely(!sysfs_get_active(sd->s_parent))) | ||
70 | return NULL; | ||
71 | if (unlikely(!sysfs_get_active(sd))) { | ||
72 | sysfs_put_active(sd->s_parent); | ||
73 | return NULL; | ||
74 | } | ||
75 | } | ||
76 | return sd; | ||
77 | } | ||
78 | |||
79 | /** | ||
80 | * sysfs_put_active_two - put active references to sysfs_dirent and parent | ||
81 | * @sd: sysfs_dirent of interest | ||
82 | * | ||
83 | * Put active references to @sd and its parent. This function is | ||
84 | * noop if @sd is NULL. | ||
85 | */ | ||
86 | void sysfs_put_active_two(struct sysfs_dirent *sd) | ||
87 | { | ||
88 | if (sd) { | ||
89 | sysfs_put_active(sd); | ||
90 | sysfs_put_active(sd->s_parent); | ||
91 | } | ||
92 | } | ||
93 | |||
94 | /** | ||
95 | * sysfs_deactivate - deactivate sysfs_dirent | ||
96 | * @sd: sysfs_dirent to deactivate | ||
97 | * | ||
98 | * Deny new active references and drain existing ones. s_active | ||
99 | * will be unlocked when the sysfs_dirent is released. | ||
100 | */ | ||
101 | void sysfs_deactivate(struct sysfs_dirent *sd) | ||
102 | { | ||
103 | down_write_nested(&sd->s_active, SYSFS_S_ACTIVE_DEACTIVATE); | ||
104 | |||
105 | /* s_active will be unlocked by the thread doing the final put | ||
106 | * on @sd. Lie to lockdep. | ||
107 | */ | ||
108 | rwsem_release(&sd->s_active.dep_map, 1, _RET_IP_); | ||
109 | } | ||
110 | |||
23 | static int sysfs_alloc_ino(ino_t *pino) | 111 | static int sysfs_alloc_ino(ino_t *pino) |
24 | { | 112 | { |
25 | int ino, rc; | 113 | int ino, rc; |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 627bf3940dfa..f8779eaa53ff 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
@@ -56,6 +56,12 @@ enum sysfs_s_active_class | |||
56 | extern struct vfsmount * sysfs_mount; | 56 | extern struct vfsmount * sysfs_mount; |
57 | extern struct kmem_cache *sysfs_dir_cachep; | 57 | extern struct kmem_cache *sysfs_dir_cachep; |
58 | 58 | ||
59 | extern struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd); | ||
60 | extern void sysfs_put_active(struct sysfs_dirent *sd); | ||
61 | extern struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd); | ||
62 | extern void sysfs_put_active_two(struct sysfs_dirent *sd); | ||
63 | extern void sysfs_deactivate(struct sysfs_dirent *sd); | ||
64 | |||
59 | extern void sysfs_delete_inode(struct inode *inode); | 65 | extern void sysfs_delete_inode(struct inode *inode); |
60 | extern void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode); | 66 | extern void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode); |
61 | extern struct inode * sysfs_get_inode(struct sysfs_dirent *sd); | 67 | extern struct inode * sysfs_get_inode(struct sysfs_dirent *sd); |
@@ -104,94 +110,6 @@ static inline void sysfs_put(struct sysfs_dirent * sd) | |||
104 | release_sysfs_dirent(sd); | 110 | release_sysfs_dirent(sd); |
105 | } | 111 | } |
106 | 112 | ||
107 | /** | ||
108 | * sysfs_get_active - get an active reference to sysfs_dirent | ||
109 | * @sd: sysfs_dirent to get an active reference to | ||
110 | * | ||
111 | * Get an active reference of @sd. This function is noop if @sd | ||
112 | * is NULL. | ||
113 | * | ||
114 | * RETURNS: | ||
115 | * Pointer to @sd on success, NULL on failure. | ||
116 | */ | ||
117 | static inline struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) | ||
118 | { | ||
119 | if (sd) { | ||
120 | if (unlikely(!down_read_trylock(&sd->s_active))) | ||
121 | sd = NULL; | ||
122 | } | ||
123 | return sd; | ||
124 | } | ||
125 | |||
126 | /** | ||
127 | * sysfs_put_active - put an active reference to sysfs_dirent | ||
128 | * @sd: sysfs_dirent to put an active reference to | ||
129 | * | ||
130 | * Put an active reference to @sd. This function is noop if @sd | ||
131 | * is NULL. | ||
132 | */ | ||
133 | static inline void sysfs_put_active(struct sysfs_dirent *sd) | ||
134 | { | ||
135 | if (sd) | ||
136 | up_read(&sd->s_active); | ||
137 | } | ||
138 | |||
139 | /** | ||
140 | * sysfs_get_active_two - get active references to sysfs_dirent and parent | ||
141 | * @sd: sysfs_dirent of interest | ||
142 | * | ||
143 | * Get active reference to @sd and its parent. Parent's active | ||
144 | * reference is grabbed first. This function is noop if @sd is | ||
145 | * NULL. | ||
146 | * | ||
147 | * RETURNS: | ||
148 | * Pointer to @sd on success, NULL on failure. | ||
149 | */ | ||
150 | static inline struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd) | ||
151 | { | ||
152 | if (sd) { | ||
153 | if (sd->s_parent && unlikely(!sysfs_get_active(sd->s_parent))) | ||
154 | return NULL; | ||
155 | if (unlikely(!sysfs_get_active(sd))) { | ||
156 | sysfs_put_active(sd->s_parent); | ||
157 | return NULL; | ||
158 | } | ||
159 | } | ||
160 | return sd; | ||
161 | } | ||
162 | |||
163 | /** | ||
164 | * sysfs_put_active_two - put active references to sysfs_dirent and parent | ||
165 | * @sd: sysfs_dirent of interest | ||
166 | * | ||
167 | * Put active references to @sd and its parent. This function is | ||
168 | * noop if @sd is NULL. | ||
169 | */ | ||
170 | static inline void sysfs_put_active_two(struct sysfs_dirent *sd) | ||
171 | { | ||
172 | if (sd) { | ||
173 | sysfs_put_active(sd); | ||
174 | sysfs_put_active(sd->s_parent); | ||
175 | } | ||
176 | } | ||
177 | |||
178 | /** | ||
179 | * sysfs_deactivate - deactivate sysfs_dirent | ||
180 | * @sd: sysfs_dirent to deactivate | ||
181 | * | ||
182 | * Deny new active references and drain existing ones. s_active | ||
183 | * will be unlocked when the sysfs_dirent is released. | ||
184 | */ | ||
185 | static inline void sysfs_deactivate(struct sysfs_dirent *sd) | ||
186 | { | ||
187 | down_write_nested(&sd->s_active, SYSFS_S_ACTIVE_DEACTIVATE); | ||
188 | |||
189 | /* s_active will be unlocked by the thread doing the final put | ||
190 | * on @sd. Lie to lockdep. | ||
191 | */ | ||
192 | rwsem_release(&sd->s_active.dep_map, 1, _RET_IP_); | ||
193 | } | ||
194 | |||
195 | static inline int sysfs_is_shadowed_inode(struct inode *inode) | 113 | static inline int sysfs_is_shadowed_inode(struct inode *inode) |
196 | { | 114 | { |
197 | return S_ISDIR(inode->i_mode) && inode->i_op->follow_link; | 115 | return S_ISDIR(inode->i_mode) && inode->i_op->follow_link; |