Commit 36231d255b8df9cb4698e9a3902c16067d5c1398
Exists in
master
and in
20 other branches
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs fixes from Al Viro: "The sget() one is a long-standing bug and will need to go into -stable (in fact, it had been originally caught in RHEL6), the other two are 3.11-only" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: vfs: constify dentry parameter in d_count() livelock avoidance in sget() allow O_TMPFILE to work with O_WRONLY
Showing 4 changed files Side-by-side Diff
fs/open.c
... | ... | @@ -844,6 +844,8 @@ |
844 | 844 | if ((flags & O_TMPFILE_MASK) != O_TMPFILE) |
845 | 845 | return -EINVAL; |
846 | 846 | acc_mode = MAY_OPEN | ACC_MODE(flags); |
847 | + if (!(acc_mode & MAY_WRITE)) | |
848 | + return -EINVAL; | |
847 | 849 | } else if (flags & O_PATH) { |
848 | 850 | /* |
849 | 851 | * If we have O_PATH in the open flag. Then we |
fs/super.c
... | ... | @@ -336,19 +336,19 @@ |
336 | 336 | * and want to turn it into a full-blown active reference. grab_super() |
337 | 337 | * is called with sb_lock held and drops it. Returns 1 in case of |
338 | 338 | * success, 0 if we had failed (superblock contents was already dead or |
339 | - * dying when grab_super() had been called). | |
339 | + * dying when grab_super() had been called). Note that this is only | |
340 | + * called for superblocks not in rundown mode (== ones still on ->fs_supers | |
341 | + * of their type), so increment of ->s_count is OK here. | |
340 | 342 | */ |
341 | 343 | static int grab_super(struct super_block *s) __releases(sb_lock) |
342 | 344 | { |
343 | - if (atomic_inc_not_zero(&s->s_active)) { | |
344 | - spin_unlock(&sb_lock); | |
345 | - return 1; | |
346 | - } | |
347 | - /* it's going away */ | |
348 | 345 | s->s_count++; |
349 | 346 | spin_unlock(&sb_lock); |
350 | - /* wait for it to die */ | |
351 | 347 | down_write(&s->s_umount); |
348 | + if ((s->s_flags & MS_BORN) && atomic_inc_not_zero(&s->s_active)) { | |
349 | + put_super(s); | |
350 | + return 1; | |
351 | + } | |
352 | 352 | up_write(&s->s_umount); |
353 | 353 | put_super(s); |
354 | 354 | return 0; |
... | ... | @@ -463,11 +463,6 @@ |
463 | 463 | destroy_super(s); |
464 | 464 | s = NULL; |
465 | 465 | } |
466 | - down_write(&old->s_umount); | |
467 | - if (unlikely(!(old->s_flags & MS_BORN))) { | |
468 | - deactivate_locked_super(old); | |
469 | - goto retry; | |
470 | - } | |
471 | 466 | return old; |
472 | 467 | } |
473 | 468 | } |
474 | 469 | |
... | ... | @@ -660,10 +655,10 @@ |
660 | 655 | if (hlist_unhashed(&sb->s_instances)) |
661 | 656 | continue; |
662 | 657 | if (sb->s_bdev == bdev) { |
663 | - if (grab_super(sb)) /* drops sb_lock */ | |
664 | - return sb; | |
665 | - else | |
658 | + if (!grab_super(sb)) | |
666 | 659 | goto restart; |
660 | + up_write(&sb->s_umount); | |
661 | + return sb; | |
667 | 662 | } |
668 | 663 | } |
669 | 664 | spin_unlock(&sb_lock); |
include/linux/dcache.h
include/uapi/asm-generic/fcntl.h
... | ... | @@ -89,8 +89,8 @@ |
89 | 89 | #endif |
90 | 90 | |
91 | 91 | /* a horrid kludge trying to make sure that this will fail on old kernels */ |
92 | -#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY | O_RDWR) | |
93 | -#define O_TMPFILE_MASK (__O_TMPFILE | O_DIRECTORY | O_CREAT | O_ACCMODE) | |
92 | +#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY) | |
93 | +#define O_TMPFILE_MASK (__O_TMPFILE | O_DIRECTORY | O_CREAT) | |
94 | 94 | |
95 | 95 | #ifndef O_NDELAY |
96 | 96 | #define O_NDELAY O_NONBLOCK |