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