Commit ca5b857c authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull misc vfs updates from Al Viro:
 "Assorted stuff, really no common topic here"

* 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  vfs: grab the lock instead of blocking in __fd_install during resizing
  vfs: stop clearing close on exec when closing a fd
  include/linux/fs.h: fix comment about struct address_space
  fs: make fiemap work from compat_ioctl
  coda: fix 'kernel memory exposure attempt' in fsync
  pstore: remove unneeded unlikely()
  vfs: remove unneeded unlikely()
  stubs for mount_bdev() and kill_block_super() in !CONFIG_BLOCK case
  make vfs_ustat() static
  do_handle_open() should be static
  elf_fdpic: fix unused variable warning
  fold destroy_super() into __put_super()
  new helper: destroy_unused_super()
  fix address space warnings in ipc/
  acct.h: get rid of detritus
parents a0e136e5 c02b1a9b
...@@ -501,10 +501,6 @@ in your dentry operations instead. ...@@ -501,10 +501,6 @@ in your dentry operations instead.
is non-NULL. Note that link body isn't available anymore, so if you need it, is non-NULL. Note that link body isn't available anymore, so if you need it,
store it as cookie. store it as cookie.
-- --
[mandatory]
__fd_install() & fd_install() can now sleep. Callers should not
hold a spinlock or other resources that do not allow a schedule.
--
[mandatory] [mandatory]
any symlink that might use page_follow_link_light/page_put_link() must any symlink that might use page_follow_link_light/page_put_link() must
have inode_nohighmem(inode) called before anything might start playing with have inode_nohighmem(inode) called before anything might start playing with
......
...@@ -1498,7 +1498,9 @@ static bool elf_fdpic_dump_segments(struct coredump_params *cprm) ...@@ -1498,7 +1498,9 @@ static bool elf_fdpic_dump_segments(struct coredump_params *cprm)
struct vm_area_struct *vma; struct vm_area_struct *vma;
for (vma = current->mm->mmap; vma; vma = vma->vm_next) { for (vma = current->mm->mmap; vma; vma = vma->vm_next) {
#ifdef CONFIG_MMU
unsigned long addr; unsigned long addr;
#endif
if (!maydump(vma, cprm->mm_flags)) if (!maydump(vma, cprm->mm_flags))
continue; continue;
......
...@@ -447,8 +447,7 @@ int venus_fsync(struct super_block *sb, struct CodaFid *fid) ...@@ -447,8 +447,7 @@ int venus_fsync(struct super_block *sb, struct CodaFid *fid)
UPARG(CODA_FSYNC); UPARG(CODA_FSYNC);
inp->coda_fsync.VFid = *fid; inp->coda_fsync.VFid = *fid;
error = coda_upcall(coda_vcp(sb), sizeof(union inputArgs), error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
&outsize, inp);
CODA_FREE(inp, insize); CODA_FREE(inp, insize);
return error; return error;
......
...@@ -1458,6 +1458,7 @@ COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, ...@@ -1458,6 +1458,7 @@ COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd,
case FICLONE: case FICLONE:
case FICLONERANGE: case FICLONERANGE:
case FIDEDUPERANGE: case FIDEDUPERANGE:
case FS_IOC_FIEMAP:
goto do_ioctl; goto do_ioctl;
case FIBMAP: case FIBMAP:
......
...@@ -213,8 +213,8 @@ static int handle_to_path(int mountdirfd, struct file_handle __user *ufh, ...@@ -213,8 +213,8 @@ static int handle_to_path(int mountdirfd, struct file_handle __user *ufh,
return retval; return retval;
} }
long do_handle_open(int mountdirfd, static long do_handle_open(int mountdirfd, struct file_handle __user *ufh,
struct file_handle __user *ufh, int open_flag) int open_flag)
{ {
long retval = 0; long retval = 0;
struct path path; struct path path;
......
...@@ -593,13 +593,16 @@ void __fd_install(struct files_struct *files, unsigned int fd, ...@@ -593,13 +593,16 @@ void __fd_install(struct files_struct *files, unsigned int fd,
{ {
struct fdtable *fdt; struct fdtable *fdt;
might_sleep();
rcu_read_lock_sched(); rcu_read_lock_sched();
while (unlikely(files->resize_in_progress)) { if (unlikely(files->resize_in_progress)) {
rcu_read_unlock_sched(); rcu_read_unlock_sched();
wait_event(files->resize_wait, !files->resize_in_progress); spin_lock(&files->file_lock);
rcu_read_lock_sched(); fdt = files_fdtable(files);
BUG_ON(fdt->fd[fd] != NULL);
rcu_assign_pointer(fdt->fd[fd], file);
spin_unlock(&files->file_lock);
return;
} }
/* coupled with smp_wmb() in expand_fdtable() */ /* coupled with smp_wmb() in expand_fdtable() */
smp_rmb(); smp_rmb();
...@@ -632,7 +635,6 @@ int __close_fd(struct files_struct *files, unsigned fd) ...@@ -632,7 +635,6 @@ int __close_fd(struct files_struct *files, unsigned fd)
if (!file) if (!file)
goto out_unlock; goto out_unlock;
rcu_assign_pointer(fdt->fd[fd], NULL); rcu_assign_pointer(fdt->fd[fd], NULL);
__clear_close_on_exec(fd, fdt);
__put_unused_fd(files, fd); __put_unused_fd(files, fd);
spin_unlock(&files->file_lock); spin_unlock(&files->file_lock);
return filp_close(file, files); return filp_close(file, files);
......
...@@ -3459,7 +3459,7 @@ static int do_tmpfile(struct nameidata *nd, unsigned flags, ...@@ -3459,7 +3459,7 @@ static int do_tmpfile(struct nameidata *nd, unsigned flags,
goto out; goto out;
child = vfs_tmpfile(path.dentry, op->mode, op->open_flag); child = vfs_tmpfile(path.dentry, op->mode, op->open_flag);
error = PTR_ERR(child); error = PTR_ERR(child);
if (unlikely(IS_ERR(child))) if (IS_ERR(child))
goto out2; goto out2;
dput(path.dentry); dput(path.dentry);
path.dentry = child; path.dentry = child;
......
...@@ -651,7 +651,7 @@ static int pstore_write_user_compat(struct pstore_record *record, ...@@ -651,7 +651,7 @@ static int pstore_write_user_compat(struct pstore_record *record,
return -EINVAL; return -EINVAL;
record->buf = memdup_user(buf, record->size); record->buf = memdup_user(buf, record->size);
if (unlikely(IS_ERR(record->buf))) { if (IS_ERR(record->buf)) {
ret = PTR_ERR(record->buf); ret = PTR_ERR(record->buf);
goto out; goto out;
} }
......
...@@ -217,7 +217,7 @@ SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user ...@@ -217,7 +217,7 @@ SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user
return error; return error;
} }
int vfs_ustat(dev_t dev, struct kstatfs *sbuf) static int vfs_ustat(dev_t dev, struct kstatfs *sbuf)
{ {
struct super_block *s = user_get_super(dev); struct super_block *s = user_get_super(dev);
int err; int err;
......
...@@ -155,21 +155,19 @@ static void destroy_super_rcu(struct rcu_head *head) ...@@ -155,21 +155,19 @@ static void destroy_super_rcu(struct rcu_head *head)
schedule_work(&s->destroy_work); schedule_work(&s->destroy_work);
} }
/** /* Free a superblock that has never been seen by anyone */
* destroy_super - frees a superblock static void destroy_unused_super(struct super_block *s)
* @s: superblock to free
*
* Frees a superblock.
*/
static void destroy_super(struct super_block *s)
{ {
if (!s)
return;
up_write(&s->s_umount);
list_lru_destroy(&s->s_dentry_lru); list_lru_destroy(&s->s_dentry_lru);
list_lru_destroy(&s->s_inode_lru); list_lru_destroy(&s->s_inode_lru);
security_sb_free(s); security_sb_free(s);
WARN_ON(!list_empty(&s->s_mounts));
put_user_ns(s->s_user_ns); put_user_ns(s->s_user_ns);
kfree(s->s_subtype); kfree(s->s_subtype);
call_rcu(&s->rcu, destroy_super_rcu); /* no delays needed */
destroy_super_work(&s->destroy_work);
} }
/** /**
...@@ -257,7 +255,7 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags, ...@@ -257,7 +255,7 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags,
return s; return s;
fail: fail:
destroy_super(s); destroy_unused_super(s);
return NULL; return NULL;
} }
...@@ -266,11 +264,17 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags, ...@@ -266,11 +264,17 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags,
/* /*
* Drop a superblock's refcount. The caller must hold sb_lock. * Drop a superblock's refcount. The caller must hold sb_lock.
*/ */
static void __put_super(struct super_block *sb) static void __put_super(struct super_block *s)
{ {
if (!--sb->s_count) { if (!--s->s_count) {
list_del_init(&sb->s_list); list_del_init(&s->s_list);
destroy_super(sb); WARN_ON(s->s_dentry_lru.node);
WARN_ON(s->s_inode_lru.node);
WARN_ON(!list_empty(&s->s_mounts));
security_sb_free(s);
put_user_ns(s->s_user_ns);
kfree(s->s_subtype);
call_rcu(&s->rcu, destroy_super_rcu);
} }
} }
...@@ -485,19 +489,12 @@ struct super_block *sget_userns(struct file_system_type *type, ...@@ -485,19 +489,12 @@ struct super_block *sget_userns(struct file_system_type *type,
continue; continue;
if (user_ns != old->s_user_ns) { if (user_ns != old->s_user_ns) {
spin_unlock(&sb_lock); spin_unlock(&sb_lock);
if (s) { destroy_unused_super(s);
up_write(&s->s_umount);
destroy_super(s);
}
return ERR_PTR(-EBUSY); return ERR_PTR(-EBUSY);
} }
if (!grab_super(old)) if (!grab_super(old))
goto retry; goto retry;
if (s) { destroy_unused_super(s);
up_write(&s->s_umount);
destroy_super(s);
s = NULL;
}
return old; return old;
} }
} }
...@@ -512,8 +509,7 @@ struct super_block *sget_userns(struct file_system_type *type, ...@@ -512,8 +509,7 @@ struct super_block *sget_userns(struct file_system_type *type,
err = set(s, data); err = set(s, data);
if (err) { if (err) {
spin_unlock(&sb_lock); spin_unlock(&sb_lock);
up_write(&s->s_umount); destroy_unused_super(s);
destroy_super(s);
return ERR_PTR(err); return ERR_PTR(err);
} }
s->s_type = type; s->s_type = type;
......
...@@ -20,9 +20,6 @@ ...@@ -20,9 +20,6 @@
#ifdef CONFIG_BSD_PROCESS_ACCT #ifdef CONFIG_BSD_PROCESS_ACCT
struct vfsmount;
struct super_block;
struct pacct_struct;
struct pid_namespace; struct pid_namespace;
extern int acct_parm[]; /* for sysctl */ extern int acct_parm[]; /* for sysctl */
extern void acct_collect(long exitcode, int group_dead); extern void acct_collect(long exitcode, int group_dead);
......
...@@ -2098,9 +2098,18 @@ struct file_system_type { ...@@ -2098,9 +2098,18 @@ struct file_system_type {
extern struct dentry *mount_ns(struct file_system_type *fs_type, extern struct dentry *mount_ns(struct file_system_type *fs_type,
int flags, void *data, void *ns, struct user_namespace *user_ns, int flags, void *data, void *ns, struct user_namespace *user_ns,
int (*fill_super)(struct super_block *, void *, int)); int (*fill_super)(struct super_block *, void *, int));
#ifdef CONFIG_BLOCK
extern struct dentry *mount_bdev(struct file_system_type *fs_type, extern struct dentry *mount_bdev(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data, int flags, const char *dev_name, void *data,
int (*fill_super)(struct super_block *, void *, int)); int (*fill_super)(struct super_block *, void *, int));
#else
static inline struct dentry *mount_bdev(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data,
int (*fill_super)(struct super_block *, void *, int))
{
return ERR_PTR(-ENODEV);
}
#endif
extern struct dentry *mount_single(struct file_system_type *fs_type, extern struct dentry *mount_single(struct file_system_type *fs_type,
int flags, void *data, int flags, void *data,
int (*fill_super)(struct super_block *, void *, int)); int (*fill_super)(struct super_block *, void *, int));
...@@ -2109,7 +2118,14 @@ extern struct dentry *mount_nodev(struct file_system_type *fs_type, ...@@ -2109,7 +2118,14 @@ extern struct dentry *mount_nodev(struct file_system_type *fs_type,
int (*fill_super)(struct super_block *, void *, int)); int (*fill_super)(struct super_block *, void *, int));
extern struct dentry *mount_subtree(struct vfsmount *mnt, const char *path); extern struct dentry *mount_subtree(struct vfsmount *mnt, const char *path);
void generic_shutdown_super(struct super_block *sb); void generic_shutdown_super(struct super_block *sb);
#ifdef CONFIG_BLOCK
void kill_block_super(struct super_block *sb); void kill_block_super(struct super_block *sb);
#else
static inline void kill_block_super(struct super_block *sb)
{
BUG();
}
#endif
void kill_anon_super(struct super_block *sb); void kill_anon_super(struct super_block *sb);
void kill_litter_super(struct super_block *sb); void kill_litter_super(struct super_block *sb);
void deactivate_super(struct super_block *sb); void deactivate_super(struct super_block *sb);
...@@ -2173,7 +2189,6 @@ extern int iterate_mounts(int (*)(struct vfsmount *, void *), void *, ...@@ -2173,7 +2189,6 @@ extern int iterate_mounts(int (*)(struct vfsmount *, void *), void *,
extern int vfs_statfs(const struct path *, struct kstatfs *); extern int vfs_statfs(const struct path *, struct kstatfs *);
extern int user_statfs(const char __user *, struct kstatfs *); extern int user_statfs(const char __user *, struct kstatfs *);
extern int fd_statfs(int, struct kstatfs *); extern int fd_statfs(int, struct kstatfs *);
extern int vfs_ustat(dev_t, struct kstatfs *);
extern int freeze_super(struct super_block *super); extern int freeze_super(struct super_block *super);
extern int thaw_super(struct super_block *super); extern int thaw_super(struct super_block *super);
extern bool our_mnt(struct vfsmount *mnt); extern bool our_mnt(struct vfsmount *mnt);
......
...@@ -591,13 +591,13 @@ static int copy_compat_msqid_from_user(struct msqid64_ds *out, void __user *buf, ...@@ -591,13 +591,13 @@ static int copy_compat_msqid_from_user(struct msqid64_ds *out, void __user *buf,
{ {
memset(out, 0, sizeof(*out)); memset(out, 0, sizeof(*out));
if (version == IPC_64) { if (version == IPC_64) {
struct compat_msqid64_ds *p = buf; struct compat_msqid64_ds __user *p = buf;
if (get_compat_ipc64_perm(&out->msg_perm, &p->msg_perm)) if (get_compat_ipc64_perm(&out->msg_perm, &p->msg_perm))
return -EFAULT; return -EFAULT;
if (get_user(out->msg_qbytes, &p->msg_qbytes)) if (get_user(out->msg_qbytes, &p->msg_qbytes))
return -EFAULT; return -EFAULT;
} else { } else {
struct compat_msqid_ds *p = buf; struct compat_msqid_ds __user *p = buf;
if (get_compat_ipc_perm(&out->msg_perm, &p->msg_perm)) if (get_compat_ipc_perm(&out->msg_perm, &p->msg_perm))
return -EFAULT; return -EFAULT;
if (get_user(out->msg_qbytes, &p->msg_qbytes)) if (get_user(out->msg_qbytes, &p->msg_qbytes))
......
...@@ -1637,10 +1637,10 @@ static int copy_compat_semid_from_user(struct semid64_ds *out, void __user *buf, ...@@ -1637,10 +1637,10 @@ static int copy_compat_semid_from_user(struct semid64_ds *out, void __user *buf,
{ {
memset(out, 0, sizeof(*out)); memset(out, 0, sizeof(*out));
if (version == IPC_64) { if (version == IPC_64) {
struct compat_semid64_ds *p = buf; struct compat_semid64_ds __user *p = buf;
return get_compat_ipc64_perm(&out->sem_perm, &p->sem_perm); return get_compat_ipc64_perm(&out->sem_perm, &p->sem_perm);
} else { } else {
struct compat_semid_ds *p = buf; struct compat_semid_ds __user *p = buf;
return get_compat_ipc_perm(&out->sem_perm, &p->sem_perm); return get_compat_ipc_perm(&out->sem_perm, &p->sem_perm);
} }
} }
......
...@@ -1194,10 +1194,10 @@ static int copy_compat_shmid_from_user(struct shmid64_ds *out, void __user *buf, ...@@ -1194,10 +1194,10 @@ static int copy_compat_shmid_from_user(struct shmid64_ds *out, void __user *buf,
{ {
memset(out, 0, sizeof(*out)); memset(out, 0, sizeof(*out));
if (version == IPC_64) { if (version == IPC_64) {
struct compat_shmid64_ds *p = buf; struct compat_shmid64_ds __user *p = buf;
return get_compat_ipc64_perm(&out->shm_perm, &p->shm_perm); return get_compat_ipc64_perm(&out->shm_perm, &p->shm_perm);
} else { } else {
struct compat_shmid_ds *p = buf; struct compat_shmid_ds __user *p = buf;
return get_compat_ipc_perm(&out->shm_perm, &p->shm_perm); return get_compat_ipc_perm(&out->shm_perm, &p->shm_perm);
} }
} }
......
...@@ -172,7 +172,7 @@ COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second, ...@@ -172,7 +172,7 @@ COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second,
COMPAT_SHMLBA); COMPAT_SHMLBA);
if (err < 0) if (err < 0)
return err; return err;
return put_user(raddr, (compat_ulong_t *)compat_ptr(third)); return put_user(raddr, (compat_ulong_t __user *)compat_ptr(third));
} }
case SHMDT: case SHMDT:
return sys_shmdt(compat_ptr(ptr)); return sys_shmdt(compat_ptr(ptr));
......
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