Skip to content

Commit 36231d2

Browse files
committed
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
2 parents 19bf1c2 + 24924a2 commit 36231d2

File tree

4 files changed

+15
-18
lines changed

4 files changed

+15
-18
lines changed

fs/open.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,8 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
844844
if ((flags & O_TMPFILE_MASK) != O_TMPFILE)
845845
return -EINVAL;
846846
acc_mode = MAY_OPEN | ACC_MODE(flags);
847+
if (!(acc_mode & MAY_WRITE))
848+
return -EINVAL;
847849
} else if (flags & O_PATH) {
848850
/*
849851
* If we have O_PATH in the open flag. Then we

fs/super.c

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -336,19 +336,19 @@ EXPORT_SYMBOL(deactivate_super);
336336
* and want to turn it into a full-blown active reference. grab_super()
337337
* is called with sb_lock held and drops it. Returns 1 in case of
338338
* 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.
340342
*/
341343
static int grab_super(struct super_block *s) __releases(sb_lock)
342344
{
343-
if (atomic_inc_not_zero(&s->s_active)) {
344-
spin_unlock(&sb_lock);
345-
return 1;
346-
}
347-
/* it's going away */
348345
s->s_count++;
349346
spin_unlock(&sb_lock);
350-
/* wait for it to die */
351347
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+
}
352352
up_write(&s->s_umount);
353353
put_super(s);
354354
return 0;
@@ -463,11 +463,6 @@ struct super_block *sget(struct file_system_type *type,
463463
destroy_super(s);
464464
s = NULL;
465465
}
466-
down_write(&old->s_umount);
467-
if (unlikely(!(old->s_flags & MS_BORN))) {
468-
deactivate_locked_super(old);
469-
goto retry;
470-
}
471466
return old;
472467
}
473468
}
@@ -660,10 +655,10 @@ struct super_block *get_active_super(struct block_device *bdev)
660655
if (hlist_unhashed(&sb->s_instances))
661656
continue;
662657
if (sb->s_bdev == bdev) {
663-
if (grab_super(sb)) /* drops sb_lock */
664-
return sb;
665-
else
658+
if (!grab_super(sb))
666659
goto restart;
660+
up_write(&sb->s_umount);
661+
return sb;
667662
}
668663
}
669664
spin_unlock(&sb_lock);

include/linux/dcache.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ static inline int __d_rcu_to_refcount(struct dentry *dentry, unsigned seq)
324324
return ret;
325325
}
326326

327-
static inline unsigned d_count(struct dentry *dentry)
327+
static inline unsigned d_count(const struct dentry *dentry)
328328
{
329329
return dentry->d_count;
330330
}

include/uapi/asm-generic/fcntl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@
8989
#endif
9090

9191
/* 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)
9494

9595
#ifndef O_NDELAY
9696
#define O_NDELAY O_NONBLOCK

0 commit comments

Comments
 (0)