diff options
Diffstat (limited to 'drivers/base/devtmpfs.c')
-rw-r--r-- | drivers/base/devtmpfs.c | 107 |
1 files changed, 43 insertions, 64 deletions
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 765c3a28077a..deb4a456cf83 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c | |||
@@ -156,9 +156,7 @@ static int dev_mkdir(const char *name, umode_t mode) | |||
156 | if (!err) | 156 | if (!err) |
157 | /* mark as kernel-created inode */ | 157 | /* mark as kernel-created inode */ |
158 | dentry->d_inode->i_private = &thread; | 158 | dentry->d_inode->i_private = &thread; |
159 | dput(dentry); | 159 | done_path_create(&path, dentry); |
160 | mutex_unlock(&path.dentry->d_inode->i_mutex); | ||
161 | path_put(&path); | ||
162 | return err; | 160 | return err; |
163 | } | 161 | } |
164 | 162 | ||
@@ -218,42 +216,30 @@ static int handle_create(const char *nodename, umode_t mode, struct device *dev) | |||
218 | /* mark as kernel-created inode */ | 216 | /* mark as kernel-created inode */ |
219 | dentry->d_inode->i_private = &thread; | 217 | dentry->d_inode->i_private = &thread; |
220 | } | 218 | } |
221 | dput(dentry); | 219 | done_path_create(&path, dentry); |
222 | |||
223 | mutex_unlock(&path.dentry->d_inode->i_mutex); | ||
224 | path_put(&path); | ||
225 | return err; | 220 | return err; |
226 | } | 221 | } |
227 | 222 | ||
228 | static int dev_rmdir(const char *name) | 223 | static int dev_rmdir(const char *name) |
229 | { | 224 | { |
230 | struct nameidata nd; | 225 | struct path parent; |
231 | struct dentry *dentry; | 226 | struct dentry *dentry; |
232 | int err; | 227 | int err; |
233 | 228 | ||
234 | err = kern_path_parent(name, &nd); | 229 | dentry = kern_path_locked(name, &parent); |
235 | if (err) | 230 | if (IS_ERR(dentry)) |
236 | return err; | 231 | return PTR_ERR(dentry); |
237 | 232 | if (dentry->d_inode) { | |
238 | mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); | 233 | if (dentry->d_inode->i_private == &thread) |
239 | dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len); | 234 | err = vfs_rmdir(parent.dentry->d_inode, dentry); |
240 | if (!IS_ERR(dentry)) { | 235 | else |
241 | if (dentry->d_inode) { | 236 | err = -EPERM; |
242 | if (dentry->d_inode->i_private == &thread) | ||
243 | err = vfs_rmdir(nd.path.dentry->d_inode, | ||
244 | dentry); | ||
245 | else | ||
246 | err = -EPERM; | ||
247 | } else { | ||
248 | err = -ENOENT; | ||
249 | } | ||
250 | dput(dentry); | ||
251 | } else { | 237 | } else { |
252 | err = PTR_ERR(dentry); | 238 | err = -ENOENT; |
253 | } | 239 | } |
254 | 240 | dput(dentry); | |
255 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 241 | mutex_unlock(&parent.dentry->d_inode->i_mutex); |
256 | path_put(&nd.path); | 242 | path_put(&parent); |
257 | return err; | 243 | return err; |
258 | } | 244 | } |
259 | 245 | ||
@@ -305,50 +291,43 @@ static int dev_mynode(struct device *dev, struct inode *inode, struct kstat *sta | |||
305 | 291 | ||
306 | static int handle_remove(const char *nodename, struct device *dev) | 292 | static int handle_remove(const char *nodename, struct device *dev) |
307 | { | 293 | { |
308 | struct nameidata nd; | 294 | struct path parent; |
309 | struct dentry *dentry; | 295 | struct dentry *dentry; |
310 | struct kstat stat; | ||
311 | int deleted = 1; | 296 | int deleted = 1; |
312 | int err; | 297 | int err; |
313 | 298 | ||
314 | err = kern_path_parent(nodename, &nd); | 299 | dentry = kern_path_locked(nodename, &parent); |
315 | if (err) | 300 | if (IS_ERR(dentry)) |
316 | return err; | 301 | return PTR_ERR(dentry); |
317 | 302 | ||
318 | mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); | 303 | if (dentry->d_inode) { |
319 | dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len); | 304 | struct kstat stat; |
320 | if (!IS_ERR(dentry)) { | 305 | err = vfs_getattr(parent.mnt, dentry, &stat); |
321 | if (dentry->d_inode) { | 306 | if (!err && dev_mynode(dev, dentry->d_inode, &stat)) { |
322 | err = vfs_getattr(nd.path.mnt, dentry, &stat); | 307 | struct iattr newattrs; |
323 | if (!err && dev_mynode(dev, dentry->d_inode, &stat)) { | 308 | /* |
324 | struct iattr newattrs; | 309 | * before unlinking this node, reset permissions |
325 | /* | 310 | * of possible references like hardlinks |
326 | * before unlinking this node, reset permissions | 311 | */ |
327 | * of possible references like hardlinks | 312 | newattrs.ia_uid = 0; |
328 | */ | 313 | newattrs.ia_gid = 0; |
329 | newattrs.ia_uid = 0; | 314 | newattrs.ia_mode = stat.mode & ~0777; |
330 | newattrs.ia_gid = 0; | 315 | newattrs.ia_valid = |
331 | newattrs.ia_mode = stat.mode & ~0777; | 316 | ATTR_UID|ATTR_GID|ATTR_MODE; |
332 | newattrs.ia_valid = | 317 | mutex_lock(&dentry->d_inode->i_mutex); |
333 | ATTR_UID|ATTR_GID|ATTR_MODE; | 318 | notify_change(dentry, &newattrs); |
334 | mutex_lock(&dentry->d_inode->i_mutex); | 319 | mutex_unlock(&dentry->d_inode->i_mutex); |
335 | notify_change(dentry, &newattrs); | 320 | err = vfs_unlink(parent.dentry->d_inode, dentry); |
336 | mutex_unlock(&dentry->d_inode->i_mutex); | 321 | if (!err || err == -ENOENT) |
337 | err = vfs_unlink(nd.path.dentry->d_inode, | 322 | deleted = 1; |
338 | dentry); | ||
339 | if (!err || err == -ENOENT) | ||
340 | deleted = 1; | ||
341 | } | ||
342 | } else { | ||
343 | err = -ENOENT; | ||
344 | } | 323 | } |
345 | dput(dentry); | ||
346 | } else { | 324 | } else { |
347 | err = PTR_ERR(dentry); | 325 | err = -ENOENT; |
348 | } | 326 | } |
349 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 327 | dput(dentry); |
328 | mutex_unlock(&parent.dentry->d_inode->i_mutex); | ||
350 | 329 | ||
351 | path_put(&nd.path); | 330 | path_put(&parent); |
352 | if (deleted && strchr(nodename, '/')) | 331 | if (deleted && strchr(nodename, '/')) |
353 | delete_path(nodename); | 332 | delete_path(nodename); |
354 | return err; | 333 | return err; |