diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-12-06 16:51:49 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-12-06 16:51:49 -0500 |
commit | d8cd93ea67af2391f8718cf06b4b8084d38a3428 (patch) | |
tree | 5fd2f7374e4fe069258e0d8b7f55141d96f01261 | |
parent | fb7b26e47ef932a21f0cac4cf04e8f51105d77d7 (diff) | |
parent | 2788cc47f4593cca2c3c73c7bb82cd32b88c8ef7 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs fixes from Al Viro:
"A couple of fixes (-stable fodder) + dead code removal after the
overlayfs fix.
I agree that it's better to separate from the fix part to make
backporting easier, but IMO it's not worth delaying said dead code
removal until the next window"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
Don't reset ->total_link_count on nested calls of vfs_path_lookup()
ovl: get rid of the dead code left from broken (and disabled) optimizations
ovl: fix permission checking for setattr
-rw-r--r-- | fs/namei.c | 1 | ||||
-rw-r--r-- | fs/overlayfs/copy_up.c | 23 | ||||
-rw-r--r-- | fs/overlayfs/inode.c | 19 | ||||
-rw-r--r-- | fs/overlayfs/overlayfs.h | 3 |
4 files changed, 15 insertions, 31 deletions
diff --git a/fs/namei.c b/fs/namei.c index d84d7c7515fc..0c3974cd3ecd 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1996,7 +1996,6 @@ static const char *path_init(struct nameidata *nd, unsigned flags) | |||
1996 | nd->last_type = LAST_ROOT; /* if there are only slashes... */ | 1996 | nd->last_type = LAST_ROOT; /* if there are only slashes... */ |
1997 | nd->flags = flags | LOOKUP_JUMPED | LOOKUP_PARENT; | 1997 | nd->flags = flags | LOOKUP_JUMPED | LOOKUP_PARENT; |
1998 | nd->depth = 0; | 1998 | nd->depth = 0; |
1999 | nd->total_link_count = 0; | ||
2000 | if (flags & LOOKUP_ROOT) { | 1999 | if (flags & LOOKUP_ROOT) { |
2001 | struct dentry *root = nd->root.dentry; | 2000 | struct dentry *root = nd->root.dentry; |
2002 | struct inode *inode = root->d_inode; | 2001 | struct inode *inode = root->d_inode; |
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index 871fcb67be97..0a8983492d91 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c | |||
@@ -195,8 +195,7 @@ int ovl_set_attr(struct dentry *upperdentry, struct kstat *stat) | |||
195 | 195 | ||
196 | static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, | 196 | static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, |
197 | struct dentry *dentry, struct path *lowerpath, | 197 | struct dentry *dentry, struct path *lowerpath, |
198 | struct kstat *stat, struct iattr *attr, | 198 | struct kstat *stat, const char *link) |
199 | const char *link) | ||
200 | { | 199 | { |
201 | struct inode *wdir = workdir->d_inode; | 200 | struct inode *wdir = workdir->d_inode; |
202 | struct inode *udir = upperdir->d_inode; | 201 | struct inode *udir = upperdir->d_inode; |
@@ -240,8 +239,6 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, | |||
240 | 239 | ||
241 | mutex_lock(&newdentry->d_inode->i_mutex); | 240 | mutex_lock(&newdentry->d_inode->i_mutex); |
242 | err = ovl_set_attr(newdentry, stat); | 241 | err = ovl_set_attr(newdentry, stat); |
243 | if (!err && attr) | ||
244 | err = notify_change(newdentry, attr, NULL); | ||
245 | mutex_unlock(&newdentry->d_inode->i_mutex); | 242 | mutex_unlock(&newdentry->d_inode->i_mutex); |
246 | if (err) | 243 | if (err) |
247 | goto out_cleanup; | 244 | goto out_cleanup; |
@@ -286,8 +283,7 @@ out_cleanup: | |||
286 | * that point the file will have already been copied up anyway. | 283 | * that point the file will have already been copied up anyway. |
287 | */ | 284 | */ |
288 | int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, | 285 | int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, |
289 | struct path *lowerpath, struct kstat *stat, | 286 | struct path *lowerpath, struct kstat *stat) |
290 | struct iattr *attr) | ||
291 | { | 287 | { |
292 | struct dentry *workdir = ovl_workdir(dentry); | 288 | struct dentry *workdir = ovl_workdir(dentry); |
293 | int err; | 289 | int err; |
@@ -345,26 +341,19 @@ int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, | |||
345 | } | 341 | } |
346 | upperdentry = ovl_dentry_upper(dentry); | 342 | upperdentry = ovl_dentry_upper(dentry); |
347 | if (upperdentry) { | 343 | if (upperdentry) { |
348 | unlock_rename(workdir, upperdir); | 344 | /* Raced with another copy-up? Nothing to do, then... */ |
349 | err = 0; | 345 | err = 0; |
350 | /* Raced with another copy-up? Do the setattr here */ | 346 | goto out_unlock; |
351 | if (attr) { | ||
352 | mutex_lock(&upperdentry->d_inode->i_mutex); | ||
353 | err = notify_change(upperdentry, attr, NULL); | ||
354 | mutex_unlock(&upperdentry->d_inode->i_mutex); | ||
355 | } | ||
356 | goto out_put_cred; | ||
357 | } | 347 | } |
358 | 348 | ||
359 | err = ovl_copy_up_locked(workdir, upperdir, dentry, lowerpath, | 349 | err = ovl_copy_up_locked(workdir, upperdir, dentry, lowerpath, |
360 | stat, attr, link); | 350 | stat, link); |
361 | if (!err) { | 351 | if (!err) { |
362 | /* Restore timestamps on parent (best effort) */ | 352 | /* Restore timestamps on parent (best effort) */ |
363 | ovl_set_timestamps(upperdir, &pstat); | 353 | ovl_set_timestamps(upperdir, &pstat); |
364 | } | 354 | } |
365 | out_unlock: | 355 | out_unlock: |
366 | unlock_rename(workdir, upperdir); | 356 | unlock_rename(workdir, upperdir); |
367 | out_put_cred: | ||
368 | revert_creds(old_cred); | 357 | revert_creds(old_cred); |
369 | put_cred(override_cred); | 358 | put_cred(override_cred); |
370 | 359 | ||
@@ -406,7 +395,7 @@ int ovl_copy_up(struct dentry *dentry) | |||
406 | ovl_path_lower(next, &lowerpath); | 395 | ovl_path_lower(next, &lowerpath); |
407 | err = vfs_getattr(&lowerpath, &stat); | 396 | err = vfs_getattr(&lowerpath, &stat); |
408 | if (!err) | 397 | if (!err) |
409 | err = ovl_copy_up_one(parent, next, &lowerpath, &stat, NULL); | 398 | err = ovl_copy_up_one(parent, next, &lowerpath, &stat); |
410 | 399 | ||
411 | dput(parent); | 400 | dput(parent); |
412 | dput(next); | 401 | dput(next); |
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index ec0c2a050043..4060ffde8722 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c | |||
@@ -12,8 +12,7 @@ | |||
12 | #include <linux/xattr.h> | 12 | #include <linux/xattr.h> |
13 | #include "overlayfs.h" | 13 | #include "overlayfs.h" |
14 | 14 | ||
15 | static int ovl_copy_up_last(struct dentry *dentry, struct iattr *attr, | 15 | static int ovl_copy_up_truncate(struct dentry *dentry) |
16 | bool no_data) | ||
17 | { | 16 | { |
18 | int err; | 17 | int err; |
19 | struct dentry *parent; | 18 | struct dentry *parent; |
@@ -30,10 +29,8 @@ static int ovl_copy_up_last(struct dentry *dentry, struct iattr *attr, | |||
30 | if (err) | 29 | if (err) |
31 | goto out_dput_parent; | 30 | goto out_dput_parent; |
32 | 31 | ||
33 | if (no_data) | 32 | stat.size = 0; |
34 | stat.size = 0; | 33 | err = ovl_copy_up_one(parent, dentry, &lowerpath, &stat); |
35 | |||
36 | err = ovl_copy_up_one(parent, dentry, &lowerpath, &stat, attr); | ||
37 | 34 | ||
38 | out_dput_parent: | 35 | out_dput_parent: |
39 | dput(parent); | 36 | dput(parent); |
@@ -49,13 +46,13 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr) | |||
49 | if (err) | 46 | if (err) |
50 | goto out; | 47 | goto out; |
51 | 48 | ||
52 | upperdentry = ovl_dentry_upper(dentry); | 49 | err = ovl_copy_up(dentry); |
53 | if (upperdentry) { | 50 | if (!err) { |
51 | upperdentry = ovl_dentry_upper(dentry); | ||
52 | |||
54 | mutex_lock(&upperdentry->d_inode->i_mutex); | 53 | mutex_lock(&upperdentry->d_inode->i_mutex); |
55 | err = notify_change(upperdentry, attr, NULL); | 54 | err = notify_change(upperdentry, attr, NULL); |
56 | mutex_unlock(&upperdentry->d_inode->i_mutex); | 55 | mutex_unlock(&upperdentry->d_inode->i_mutex); |
57 | } else { | ||
58 | err = ovl_copy_up_last(dentry, attr, false); | ||
59 | } | 56 | } |
60 | ovl_drop_write(dentry); | 57 | ovl_drop_write(dentry); |
61 | out: | 58 | out: |
@@ -353,7 +350,7 @@ struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags) | |||
353 | return ERR_PTR(err); | 350 | return ERR_PTR(err); |
354 | 351 | ||
355 | if (file_flags & O_TRUNC) | 352 | if (file_flags & O_TRUNC) |
356 | err = ovl_copy_up_last(dentry, NULL, true); | 353 | err = ovl_copy_up_truncate(dentry); |
357 | else | 354 | else |
358 | err = ovl_copy_up(dentry); | 355 | err = ovl_copy_up(dentry); |
359 | ovl_drop_write(dentry); | 356 | ovl_drop_write(dentry); |
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index ea5a40b06e3a..e17154aeaae4 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h | |||
@@ -194,7 +194,6 @@ void ovl_cleanup(struct inode *dir, struct dentry *dentry); | |||
194 | /* copy_up.c */ | 194 | /* copy_up.c */ |
195 | int ovl_copy_up(struct dentry *dentry); | 195 | int ovl_copy_up(struct dentry *dentry); |
196 | int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, | 196 | int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, |
197 | struct path *lowerpath, struct kstat *stat, | 197 | struct path *lowerpath, struct kstat *stat); |
198 | struct iattr *attr); | ||
199 | int ovl_copy_xattr(struct dentry *old, struct dentry *new); | 198 | int ovl_copy_xattr(struct dentry *old, struct dentry *new); |
200 | int ovl_set_attr(struct dentry *upper, struct kstat *stat); | 199 | int ovl_set_attr(struct dentry *upper, struct kstat *stat); |