Commit 8ef9c292 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull vfs fixes from Al Viro.

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  vfs: add missing check for __O_TMPFILE in fcntl_init()
  fs: Allow unprivileged linkat(..., AT_EMPTY_PATH) aka flink
  fs: Fix file mode for O_TMPFILE
  reiserfs: fix deadlock in umount
parents e4ef108f 3d62c45b
...@@ -730,14 +730,14 @@ static int __init fcntl_init(void) ...@@ -730,14 +730,14 @@ static int __init fcntl_init(void)
* Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY
* is defined as O_NONBLOCK on some platforms and not on others. * is defined as O_NONBLOCK on some platforms and not on others.
*/ */
BUILD_BUG_ON(19 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32( BUILD_BUG_ON(20 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32(
O_RDONLY | O_WRONLY | O_RDWR | O_RDONLY | O_WRONLY | O_RDWR |
O_CREAT | O_EXCL | O_NOCTTY | O_CREAT | O_EXCL | O_NOCTTY |
O_TRUNC | O_APPEND | /* O_NONBLOCK | */ O_TRUNC | O_APPEND | /* O_NONBLOCK | */
__O_SYNC | O_DSYNC | FASYNC | __O_SYNC | O_DSYNC | FASYNC |
O_DIRECT | O_LARGEFILE | O_DIRECTORY | O_DIRECT | O_LARGEFILE | O_DIRECTORY |
O_NOFOLLOW | O_NOATIME | O_CLOEXEC | O_NOFOLLOW | O_NOATIME | O_CLOEXEC |
__FMODE_EXEC | O_PATH __FMODE_EXEC | O_PATH | __O_TMPFILE
)); ));
fasync_cache = kmem_cache_create("fasync_cache", fasync_cache = kmem_cache_create("fasync_cache",
......
...@@ -3671,15 +3671,11 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname, ...@@ -3671,15 +3671,11 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0) if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0)
return -EINVAL; return -EINVAL;
/* /*
* To use null names we require CAP_DAC_READ_SEARCH * Using empty names is equivalent to using AT_SYMLINK_FOLLOW
* This ensures that not everyone will be able to create * on /proc/self/fd/<fd>.
* handlink using the passed filedescriptor.
*/ */
if (flags & AT_EMPTY_PATH) { if (flags & AT_EMPTY_PATH)
if (!capable(CAP_DAC_READ_SEARCH))
return -ENOENT;
how = LOOKUP_EMPTY; how = LOOKUP_EMPTY;
}
if (flags & AT_SYMLINK_FOLLOW) if (flags & AT_SYMLINK_FOLLOW)
how |= LOOKUP_FOLLOW; how |= LOOKUP_FOLLOW;
......
...@@ -823,7 +823,7 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o ...@@ -823,7 +823,7 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
int lookup_flags = 0; int lookup_flags = 0;
int acc_mode; int acc_mode;
if (flags & O_CREAT) if (flags & (O_CREAT | __O_TMPFILE))
op->mode = (mode & S_IALLUGO) | S_IFREG; op->mode = (mode & S_IALLUGO) | S_IFREG;
else else
op->mode = 0; op->mode = 0;
......
...@@ -19,12 +19,13 @@ ...@@ -19,12 +19,13 @@
/* /*
* LOCKING: * LOCKING:
* *
* We rely on new Alexander Viro's super-block locking. * These guys are evicted from procfs as the very first step in ->kill_sb().
* *
*/ */
static int show_version(struct seq_file *m, struct super_block *sb) static int show_version(struct seq_file *m, void *unused)
{ {
struct super_block *sb = m->private;
char *format; char *format;
if (REISERFS_SB(sb)->s_properties & (1 << REISERFS_3_6)) { if (REISERFS_SB(sb)->s_properties & (1 << REISERFS_3_6)) {
...@@ -66,8 +67,9 @@ static int show_version(struct seq_file *m, struct super_block *sb) ...@@ -66,8 +67,9 @@ static int show_version(struct seq_file *m, struct super_block *sb)
#define DJP( x ) le32_to_cpu( jp -> x ) #define DJP( x ) le32_to_cpu( jp -> x )
#define JF( x ) ( r -> s_journal -> x ) #define JF( x ) ( r -> s_journal -> x )
static int show_super(struct seq_file *m, struct super_block *sb) static int show_super(struct seq_file *m, void *unused)
{ {
struct super_block *sb = m->private;
struct reiserfs_sb_info *r = REISERFS_SB(sb); struct reiserfs_sb_info *r = REISERFS_SB(sb);
seq_printf(m, "state: \t%s\n" seq_printf(m, "state: \t%s\n"
...@@ -128,8 +130,9 @@ static int show_super(struct seq_file *m, struct super_block *sb) ...@@ -128,8 +130,9 @@ static int show_super(struct seq_file *m, struct super_block *sb)
return 0; return 0;
} }
static int show_per_level(struct seq_file *m, struct super_block *sb) static int show_per_level(struct seq_file *m, void *unused)
{ {
struct super_block *sb = m->private;
struct reiserfs_sb_info *r = REISERFS_SB(sb); struct reiserfs_sb_info *r = REISERFS_SB(sb);
int level; int level;
...@@ -186,8 +189,9 @@ static int show_per_level(struct seq_file *m, struct super_block *sb) ...@@ -186,8 +189,9 @@ static int show_per_level(struct seq_file *m, struct super_block *sb)
return 0; return 0;
} }
static int show_bitmap(struct seq_file *m, struct super_block *sb) static int show_bitmap(struct seq_file *m, void *unused)
{ {
struct super_block *sb = m->private;
struct reiserfs_sb_info *r = REISERFS_SB(sb); struct reiserfs_sb_info *r = REISERFS_SB(sb);
seq_printf(m, "free_block: %lu\n" seq_printf(m, "free_block: %lu\n"
...@@ -218,8 +222,9 @@ static int show_bitmap(struct seq_file *m, struct super_block *sb) ...@@ -218,8 +222,9 @@ static int show_bitmap(struct seq_file *m, struct super_block *sb)
return 0; return 0;
} }
static int show_on_disk_super(struct seq_file *m, struct super_block *sb) static int show_on_disk_super(struct seq_file *m, void *unused)
{ {
struct super_block *sb = m->private;
struct reiserfs_sb_info *sb_info = REISERFS_SB(sb); struct reiserfs_sb_info *sb_info = REISERFS_SB(sb);
struct reiserfs_super_block *rs = sb_info->s_rs; struct reiserfs_super_block *rs = sb_info->s_rs;
int hash_code = DFL(s_hash_function_code); int hash_code = DFL(s_hash_function_code);
...@@ -261,8 +266,9 @@ static int show_on_disk_super(struct seq_file *m, struct super_block *sb) ...@@ -261,8 +266,9 @@ static int show_on_disk_super(struct seq_file *m, struct super_block *sb)
return 0; return 0;
} }
static int show_oidmap(struct seq_file *m, struct super_block *sb) static int show_oidmap(struct seq_file *m, void *unused)
{ {
struct super_block *sb = m->private;
struct reiserfs_sb_info *sb_info = REISERFS_SB(sb); struct reiserfs_sb_info *sb_info = REISERFS_SB(sb);
struct reiserfs_super_block *rs = sb_info->s_rs; struct reiserfs_super_block *rs = sb_info->s_rs;
unsigned int mapsize = le16_to_cpu(rs->s_v1.s_oid_cursize); unsigned int mapsize = le16_to_cpu(rs->s_v1.s_oid_cursize);
...@@ -291,8 +297,9 @@ static int show_oidmap(struct seq_file *m, struct super_block *sb) ...@@ -291,8 +297,9 @@ static int show_oidmap(struct seq_file *m, struct super_block *sb)
return 0; return 0;
} }
static int show_journal(struct seq_file *m, struct super_block *sb) static int show_journal(struct seq_file *m, void *unused)
{ {
struct super_block *sb = m->private;
struct reiserfs_sb_info *r = REISERFS_SB(sb); struct reiserfs_sb_info *r = REISERFS_SB(sb);
struct reiserfs_super_block *rs = r->s_rs; struct reiserfs_super_block *rs = r->s_rs;
struct journal_params *jp = &rs->s_v1.s_journal; struct journal_params *jp = &rs->s_v1.s_journal;
...@@ -383,92 +390,24 @@ static int show_journal(struct seq_file *m, struct super_block *sb) ...@@ -383,92 +390,24 @@ static int show_journal(struct seq_file *m, struct super_block *sb)
return 0; return 0;
} }
/* iterator */
static int test_sb(struct super_block *sb, void *data)
{
return data == sb;
}
static int set_sb(struct super_block *sb, void *data)
{
return -ENOENT;
}
struct reiserfs_seq_private {
struct super_block *sb;
int (*show) (struct seq_file *, struct super_block *);
};
static void *r_start(struct seq_file *m, loff_t * pos)
{
struct reiserfs_seq_private *priv = m->private;
loff_t l = *pos;
if (l)
return NULL;
if (IS_ERR(sget(&reiserfs_fs_type, test_sb, set_sb, 0, priv->sb)))
return NULL;
up_write(&priv->sb->s_umount);
return priv->sb;
}
static void *r_next(struct seq_file *m, void *v, loff_t * pos)
{
++*pos;
if (v)
deactivate_super(v);
return NULL;
}
static void r_stop(struct seq_file *m, void *v)
{
if (v)
deactivate_super(v);
}
static int r_show(struct seq_file *m, void *v)
{
struct reiserfs_seq_private *priv = m->private;
return priv->show(m, v);
}
static const struct seq_operations r_ops = {
.start = r_start,
.next = r_next,
.stop = r_stop,
.show = r_show,
};
static int r_open(struct inode *inode, struct file *file) static int r_open(struct inode *inode, struct file *file)
{ {
struct reiserfs_seq_private *priv; return single_open(file, PDE_DATA(inode),
int ret = seq_open_private(file, &r_ops, proc_get_parent_data(inode));
sizeof(struct reiserfs_seq_private));
if (!ret) {
struct seq_file *m = file->private_data;
priv = m->private;
priv->sb = proc_get_parent_data(inode);
priv->show = PDE_DATA(inode);
}
return ret;
} }
static const struct file_operations r_file_operations = { static const struct file_operations r_file_operations = {
.open = r_open, .open = r_open,
.read = seq_read, .read = seq_read,
.llseek = seq_lseek, .llseek = seq_lseek,
.release = seq_release_private, .release = single_release,
.owner = THIS_MODULE,
}; };
static struct proc_dir_entry *proc_info_root = NULL; static struct proc_dir_entry *proc_info_root = NULL;
static const char proc_info_root_name[] = "fs/reiserfs"; static const char proc_info_root_name[] = "fs/reiserfs";
static void add_file(struct super_block *sb, char *name, static void add_file(struct super_block *sb, char *name,
int (*func) (struct seq_file *, struct super_block *)) int (*func) (struct seq_file *, void *))
{ {
proc_create_data(name, 0, REISERFS_SB(sb)->procdir, proc_create_data(name, 0, REISERFS_SB(sb)->procdir,
&r_file_operations, func); &r_file_operations, func);
......
...@@ -499,6 +499,7 @@ int remove_save_link(struct inode *inode, int truncate) ...@@ -499,6 +499,7 @@ int remove_save_link(struct inode *inode, int truncate)
static void reiserfs_kill_sb(struct super_block *s) static void reiserfs_kill_sb(struct super_block *s)
{ {
if (REISERFS_SB(s)) { if (REISERFS_SB(s)) {
reiserfs_proc_info_done(s);
/* /*
* Force any pending inode evictions to occur now. Any * Force any pending inode evictions to occur now. Any
* inodes to be removed that have extended attributes * inodes to be removed that have extended attributes
...@@ -554,8 +555,6 @@ static void reiserfs_put_super(struct super_block *s) ...@@ -554,8 +555,6 @@ static void reiserfs_put_super(struct super_block *s)
REISERFS_SB(s)->reserved_blocks); REISERFS_SB(s)->reserved_blocks);
} }
reiserfs_proc_info_done(s);
reiserfs_write_unlock(s); reiserfs_write_unlock(s);
mutex_destroy(&REISERFS_SB(s)->lock); mutex_destroy(&REISERFS_SB(s)->lock);
kfree(s->s_fs_info); kfree(s->s_fs_info);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment