diff options
Diffstat (limited to 'fs')
55 files changed, 579 insertions, 563 deletions
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 392c5dac1981..d934f04e7736 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c | |||
| @@ -184,10 +184,20 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts) | |||
| 184 | v9ses->afid = option; | 184 | v9ses->afid = option; |
| 185 | break; | 185 | break; |
| 186 | case Opt_uname: | 186 | case Opt_uname: |
| 187 | match_strlcpy(v9ses->uname, &args[0], PATH_MAX); | 187 | kfree(v9ses->uname); |
| 188 | v9ses->uname = match_strdup(&args[0]); | ||
| 189 | if (!v9ses->uname) { | ||
| 190 | ret = -ENOMEM; | ||
| 191 | goto free_and_return; | ||
| 192 | } | ||
| 188 | break; | 193 | break; |
| 189 | case Opt_remotename: | 194 | case Opt_remotename: |
| 190 | match_strlcpy(v9ses->aname, &args[0], PATH_MAX); | 195 | kfree(v9ses->aname); |
| 196 | v9ses->aname = match_strdup(&args[0]); | ||
| 197 | if (!v9ses->aname) { | ||
| 198 | ret = -ENOMEM; | ||
| 199 | goto free_and_return; | ||
| 200 | } | ||
| 191 | break; | 201 | break; |
| 192 | case Opt_nodevmap: | 202 | case Opt_nodevmap: |
| 193 | v9ses->nodev = 1; | 203 | v9ses->nodev = 1; |
| @@ -287,21 +297,21 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, | |||
| 287 | struct p9_fid *fid; | 297 | struct p9_fid *fid; |
| 288 | int rc; | 298 | int rc; |
| 289 | 299 | ||
| 290 | v9ses->uname = __getname(); | 300 | v9ses->uname = kstrdup(V9FS_DEFUSER, GFP_KERNEL); |
| 291 | if (!v9ses->uname) | 301 | if (!v9ses->uname) |
| 292 | return ERR_PTR(-ENOMEM); | 302 | return ERR_PTR(-ENOMEM); |
| 293 | 303 | ||
| 294 | v9ses->aname = __getname(); | 304 | v9ses->aname = kstrdup(V9FS_DEFANAME, GFP_KERNEL); |
| 295 | if (!v9ses->aname) { | 305 | if (!v9ses->aname) { |
| 296 | __putname(v9ses->uname); | 306 | kfree(v9ses->uname); |
| 297 | return ERR_PTR(-ENOMEM); | 307 | return ERR_PTR(-ENOMEM); |
| 298 | } | 308 | } |
| 299 | init_rwsem(&v9ses->rename_sem); | 309 | init_rwsem(&v9ses->rename_sem); |
| 300 | 310 | ||
| 301 | rc = bdi_setup_and_register(&v9ses->bdi, "9p", BDI_CAP_MAP_COPY); | 311 | rc = bdi_setup_and_register(&v9ses->bdi, "9p", BDI_CAP_MAP_COPY); |
| 302 | if (rc) { | 312 | if (rc) { |
| 303 | __putname(v9ses->aname); | 313 | kfree(v9ses->aname); |
| 304 | __putname(v9ses->uname); | 314 | kfree(v9ses->uname); |
| 305 | return ERR_PTR(rc); | 315 | return ERR_PTR(rc); |
| 306 | } | 316 | } |
| 307 | 317 | ||
| @@ -309,8 +319,6 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, | |||
| 309 | list_add(&v9ses->slist, &v9fs_sessionlist); | 319 | list_add(&v9ses->slist, &v9fs_sessionlist); |
| 310 | spin_unlock(&v9fs_sessionlist_lock); | 320 | spin_unlock(&v9fs_sessionlist_lock); |
| 311 | 321 | ||
| 312 | strcpy(v9ses->uname, V9FS_DEFUSER); | ||
| 313 | strcpy(v9ses->aname, V9FS_DEFANAME); | ||
| 314 | v9ses->uid = ~0; | 322 | v9ses->uid = ~0; |
| 315 | v9ses->dfltuid = V9FS_DEFUID; | 323 | v9ses->dfltuid = V9FS_DEFUID; |
| 316 | v9ses->dfltgid = V9FS_DEFGID; | 324 | v9ses->dfltgid = V9FS_DEFGID; |
| @@ -412,8 +420,8 @@ void v9fs_session_close(struct v9fs_session_info *v9ses) | |||
| 412 | kfree(v9ses->cachetag); | 420 | kfree(v9ses->cachetag); |
| 413 | } | 421 | } |
| 414 | #endif | 422 | #endif |
| 415 | __putname(v9ses->uname); | 423 | kfree(v9ses->uname); |
| 416 | __putname(v9ses->aname); | 424 | kfree(v9ses->aname); |
| 417 | 425 | ||
| 418 | bdi_destroy(&v9ses->bdi); | 426 | bdi_destroy(&v9ses->bdi); |
| 419 | 427 | ||
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index cbf9dbb1b2a2..890bed538f9b 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
| @@ -1276,12 +1276,12 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) | |||
| 1276 | } | 1276 | } |
| 1277 | 1277 | ||
| 1278 | /* copy extension buffer into buffer */ | 1278 | /* copy extension buffer into buffer */ |
| 1279 | strncpy(buffer, st->extension, buflen); | 1279 | retval = min(strlen(st->extension)+1, (size_t)buflen); |
| 1280 | memcpy(buffer, st->extension, retval); | ||
| 1280 | 1281 | ||
| 1281 | p9_debug(P9_DEBUG_VFS, "%s -> %s (%s)\n", | 1282 | p9_debug(P9_DEBUG_VFS, "%s -> %s (%.*s)\n", |
| 1282 | dentry->d_name.name, st->extension, buffer); | 1283 | dentry->d_name.name, st->extension, buflen, buffer); |
| 1283 | 1284 | ||
| 1284 | retval = strnlen(buffer, buflen); | ||
| 1285 | done: | 1285 | done: |
| 1286 | p9stat_free(st); | 1286 | p9stat_free(st); |
| 1287 | kfree(st); | 1287 | kfree(st); |
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index e7396cfdb109..91b11650722e 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
| @@ -392,10 +392,12 @@ static struct vfsmount *autofs4_d_automount(struct path *path) | |||
| 392 | ino->flags |= AUTOFS_INF_PENDING; | 392 | ino->flags |= AUTOFS_INF_PENDING; |
| 393 | spin_unlock(&sbi->fs_lock); | 393 | spin_unlock(&sbi->fs_lock); |
| 394 | status = autofs4_mount_wait(dentry); | 394 | status = autofs4_mount_wait(dentry); |
| 395 | if (status) | ||
| 396 | return ERR_PTR(status); | ||
| 397 | spin_lock(&sbi->fs_lock); | 395 | spin_lock(&sbi->fs_lock); |
| 398 | ino->flags &= ~AUTOFS_INF_PENDING; | 396 | ino->flags &= ~AUTOFS_INF_PENDING; |
| 397 | if (status) { | ||
| 398 | spin_unlock(&sbi->fs_lock); | ||
| 399 | return ERR_PTR(status); | ||
| 400 | } | ||
| 399 | } | 401 | } |
| 400 | done: | 402 | done: |
| 401 | if (!(ino->flags & AUTOFS_INF_EXPIRING)) { | 403 | if (!(ino->flags & AUTOFS_INF_EXPIRING)) { |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index e568c472f807..61168805f175 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -638,7 +638,7 @@ static int btrfs_may_delete(struct inode *dir,struct dentry *victim,int isdir) | |||
| 638 | return -ENOENT; | 638 | return -ENOENT; |
| 639 | 639 | ||
| 640 | BUG_ON(victim->d_parent->d_inode != dir); | 640 | BUG_ON(victim->d_parent->d_inode != dir); |
| 641 | audit_inode_child(victim, dir); | 641 | audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE); |
| 642 | 642 | ||
| 643 | error = inode_permission(dir, MAY_WRITE | MAY_EXEC); | 643 | error = inode_permission(dir, MAY_WRITE | MAY_EXEC); |
| 644 | if (error) | 644 | if (error) |
diff --git a/fs/ceph/export.c b/fs/ceph/export.c index 8e1b60e557b6..02ce90972d81 100644 --- a/fs/ceph/export.c +++ b/fs/ceph/export.c | |||
| @@ -99,7 +99,7 @@ static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len, | |||
| 99 | * FIXME: we should try harder by querying the mds for the ino. | 99 | * FIXME: we should try harder by querying the mds for the ino. |
| 100 | */ | 100 | */ |
| 101 | static struct dentry *__fh_to_dentry(struct super_block *sb, | 101 | static struct dentry *__fh_to_dentry(struct super_block *sb, |
| 102 | struct ceph_nfs_fh *fh) | 102 | struct ceph_nfs_fh *fh, int fh_len) |
| 103 | { | 103 | { |
| 104 | struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc; | 104 | struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc; |
| 105 | struct inode *inode; | 105 | struct inode *inode; |
| @@ -107,6 +107,9 @@ static struct dentry *__fh_to_dentry(struct super_block *sb, | |||
| 107 | struct ceph_vino vino; | 107 | struct ceph_vino vino; |
| 108 | int err; | 108 | int err; |
| 109 | 109 | ||
| 110 | if (fh_len < sizeof(*fh) / 4) | ||
| 111 | return ERR_PTR(-ESTALE); | ||
| 112 | |||
| 110 | dout("__fh_to_dentry %llx\n", fh->ino); | 113 | dout("__fh_to_dentry %llx\n", fh->ino); |
| 111 | vino.ino = fh->ino; | 114 | vino.ino = fh->ino; |
| 112 | vino.snap = CEPH_NOSNAP; | 115 | vino.snap = CEPH_NOSNAP; |
| @@ -150,7 +153,7 @@ static struct dentry *__fh_to_dentry(struct super_block *sb, | |||
| 150 | * convert connectable fh to dentry | 153 | * convert connectable fh to dentry |
| 151 | */ | 154 | */ |
| 152 | static struct dentry *__cfh_to_dentry(struct super_block *sb, | 155 | static struct dentry *__cfh_to_dentry(struct super_block *sb, |
| 153 | struct ceph_nfs_confh *cfh) | 156 | struct ceph_nfs_confh *cfh, int fh_len) |
| 154 | { | 157 | { |
| 155 | struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc; | 158 | struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc; |
| 156 | struct inode *inode; | 159 | struct inode *inode; |
| @@ -158,6 +161,9 @@ static struct dentry *__cfh_to_dentry(struct super_block *sb, | |||
| 158 | struct ceph_vino vino; | 161 | struct ceph_vino vino; |
| 159 | int err; | 162 | int err; |
| 160 | 163 | ||
| 164 | if (fh_len < sizeof(*cfh) / 4) | ||
| 165 | return ERR_PTR(-ESTALE); | ||
| 166 | |||
| 161 | dout("__cfh_to_dentry %llx (%llx/%x)\n", | 167 | dout("__cfh_to_dentry %llx (%llx/%x)\n", |
| 162 | cfh->ino, cfh->parent_ino, cfh->parent_name_hash); | 168 | cfh->ino, cfh->parent_ino, cfh->parent_name_hash); |
| 163 | 169 | ||
| @@ -207,9 +213,11 @@ static struct dentry *ceph_fh_to_dentry(struct super_block *sb, struct fid *fid, | |||
| 207 | int fh_len, int fh_type) | 213 | int fh_len, int fh_type) |
| 208 | { | 214 | { |
| 209 | if (fh_type == 1) | 215 | if (fh_type == 1) |
| 210 | return __fh_to_dentry(sb, (struct ceph_nfs_fh *)fid->raw); | 216 | return __fh_to_dentry(sb, (struct ceph_nfs_fh *)fid->raw, |
| 217 | fh_len); | ||
| 211 | else | 218 | else |
| 212 | return __cfh_to_dentry(sb, (struct ceph_nfs_confh *)fid->raw); | 219 | return __cfh_to_dentry(sb, (struct ceph_nfs_confh *)fid->raw, |
| 220 | fh_len); | ||
| 213 | } | 221 | } |
| 214 | 222 | ||
| 215 | /* | 223 | /* |
| @@ -230,6 +238,8 @@ static struct dentry *ceph_fh_to_parent(struct super_block *sb, | |||
| 230 | 238 | ||
| 231 | if (fh_type == 1) | 239 | if (fh_type == 1) |
| 232 | return ERR_PTR(-ESTALE); | 240 | return ERR_PTR(-ESTALE); |
| 241 | if (fh_len < sizeof(*cfh) / 4) | ||
| 242 | return ERR_PTR(-ESTALE); | ||
| 233 | 243 | ||
| 234 | pr_debug("fh_to_parent %llx/%d\n", cfh->parent_ino, | 244 | pr_debug("fh_to_parent %llx/%d\n", cfh->parent_ino, |
| 235 | cfh->parent_name_hash); | 245 | cfh->parent_name_hash); |
diff --git a/fs/compat.c b/fs/compat.c index b7a24d0ca30d..015e1e1f87c6 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
| @@ -776,16 +776,16 @@ asmlinkage long compat_sys_mount(const char __user * dev_name, | |||
| 776 | char *kernel_type; | 776 | char *kernel_type; |
| 777 | unsigned long data_page; | 777 | unsigned long data_page; |
| 778 | char *kernel_dev; | 778 | char *kernel_dev; |
| 779 | char *dir_page; | 779 | struct filename *dir; |
| 780 | int retval; | 780 | int retval; |
| 781 | 781 | ||
| 782 | retval = copy_mount_string(type, &kernel_type); | 782 | retval = copy_mount_string(type, &kernel_type); |
| 783 | if (retval < 0) | 783 | if (retval < 0) |
| 784 | goto out; | 784 | goto out; |
| 785 | 785 | ||
| 786 | dir_page = getname(dir_name); | 786 | dir = getname(dir_name); |
| 787 | retval = PTR_ERR(dir_page); | 787 | retval = PTR_ERR(dir); |
| 788 | if (IS_ERR(dir_page)) | 788 | if (IS_ERR(dir)) |
| 789 | goto out1; | 789 | goto out1; |
| 790 | 790 | ||
| 791 | retval = copy_mount_string(dev_name, &kernel_dev); | 791 | retval = copy_mount_string(dev_name, &kernel_dev); |
| @@ -807,7 +807,7 @@ asmlinkage long compat_sys_mount(const char __user * dev_name, | |||
| 807 | } | 807 | } |
| 808 | } | 808 | } |
| 809 | 809 | ||
| 810 | retval = do_mount(kernel_dev, dir_page, kernel_type, | 810 | retval = do_mount(kernel_dev, dir->name, kernel_type, |
| 811 | flags, (void*)data_page); | 811 | flags, (void*)data_page); |
| 812 | 812 | ||
| 813 | out4: | 813 | out4: |
| @@ -815,7 +815,7 @@ asmlinkage long compat_sys_mount(const char __user * dev_name, | |||
| 815 | out3: | 815 | out3: |
| 816 | kfree(kernel_dev); | 816 | kfree(kernel_dev); |
| 817 | out2: | 817 | out2: |
| 818 | putname(dir_page); | 818 | putname(dir); |
| 819 | out1: | 819 | out1: |
| 820 | kfree(kernel_type); | 820 | kfree(kernel_type); |
| 821 | out: | 821 | out: |
| @@ -105,7 +105,7 @@ static inline void put_binfmt(struct linux_binfmt * fmt) | |||
| 105 | SYSCALL_DEFINE1(uselib, const char __user *, library) | 105 | SYSCALL_DEFINE1(uselib, const char __user *, library) |
| 106 | { | 106 | { |
| 107 | struct file *file; | 107 | struct file *file; |
| 108 | char *tmp = getname(library); | 108 | struct filename *tmp = getname(library); |
| 109 | int error = PTR_ERR(tmp); | 109 | int error = PTR_ERR(tmp); |
| 110 | static const struct open_flags uselib_flags = { | 110 | static const struct open_flags uselib_flags = { |
| 111 | .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, | 111 | .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, |
| @@ -751,13 +751,14 @@ struct file *open_exec(const char *name) | |||
| 751 | { | 751 | { |
| 752 | struct file *file; | 752 | struct file *file; |
| 753 | int err; | 753 | int err; |
| 754 | struct filename tmp = { .name = name }; | ||
| 754 | static const struct open_flags open_exec_flags = { | 755 | static const struct open_flags open_exec_flags = { |
| 755 | .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, | 756 | .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, |
| 756 | .acc_mode = MAY_EXEC | MAY_OPEN, | 757 | .acc_mode = MAY_EXEC | MAY_OPEN, |
| 757 | .intent = LOOKUP_OPEN | 758 | .intent = LOOKUP_OPEN |
| 758 | }; | 759 | }; |
| 759 | 760 | ||
| 760 | file = do_filp_open(AT_FDCWD, name, &open_exec_flags, LOOKUP_FOLLOW); | 761 | file = do_filp_open(AT_FDCWD, &tmp, &open_exec_flags, LOOKUP_FOLLOW); |
| 761 | if (IS_ERR(file)) | 762 | if (IS_ERR(file)) |
| 762 | goto out; | 763 | goto out; |
| 763 | 764 | ||
| @@ -1664,10 +1665,10 @@ SYSCALL_DEFINE3(execve, | |||
| 1664 | const char __user *const __user *, argv, | 1665 | const char __user *const __user *, argv, |
| 1665 | const char __user *const __user *, envp) | 1666 | const char __user *const __user *, envp) |
| 1666 | { | 1667 | { |
| 1667 | const char *path = getname(filename); | 1668 | struct filename *path = getname(filename); |
| 1668 | int error = PTR_ERR(path); | 1669 | int error = PTR_ERR(path); |
| 1669 | if (!IS_ERR(path)) { | 1670 | if (!IS_ERR(path)) { |
| 1670 | error = do_execve(path, argv, envp, current_pt_regs()); | 1671 | error = do_execve(path->name, argv, envp, current_pt_regs()); |
| 1671 | putname(path); | 1672 | putname(path); |
| 1672 | } | 1673 | } |
| 1673 | return error; | 1674 | return error; |
| @@ -1677,10 +1678,11 @@ asmlinkage long compat_sys_execve(const char __user * filename, | |||
| 1677 | const compat_uptr_t __user * argv, | 1678 | const compat_uptr_t __user * argv, |
| 1678 | const compat_uptr_t __user * envp) | 1679 | const compat_uptr_t __user * envp) |
| 1679 | { | 1680 | { |
| 1680 | const char *path = getname(filename); | 1681 | struct filename *path = getname(filename); |
| 1681 | int error = PTR_ERR(path); | 1682 | int error = PTR_ERR(path); |
| 1682 | if (!IS_ERR(path)) { | 1683 | if (!IS_ERR(path)) { |
| 1683 | error = compat_do_execve(path, argv, envp, current_pt_regs()); | 1684 | error = compat_do_execve(path->name, argv, envp, |
| 1685 | current_pt_regs()); | ||
| 1684 | putname(path); | 1686 | putname(path); |
| 1685 | } | 1687 | } |
| 1686 | return error; | 1688 | return error; |
diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 59e3bbfac0b1..5e59280d42d7 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c | |||
| @@ -389,8 +389,6 @@ static int exofs_sync_fs(struct super_block *sb, int wait) | |||
| 389 | if (unlikely(ret)) | 389 | if (unlikely(ret)) |
| 390 | goto out; | 390 | goto out; |
| 391 | 391 | ||
| 392 | lock_super(sb); | ||
| 393 | |||
| 394 | ios->length = offsetof(struct exofs_fscb, s_dev_table_oid); | 392 | ios->length = offsetof(struct exofs_fscb, s_dev_table_oid); |
| 395 | memset(fscb, 0, ios->length); | 393 | memset(fscb, 0, ios->length); |
| 396 | fscb->s_nextid = cpu_to_le64(sbi->s_nextid); | 394 | fscb->s_nextid = cpu_to_le64(sbi->s_nextid); |
| @@ -406,8 +404,6 @@ static int exofs_sync_fs(struct super_block *sb, int wait) | |||
| 406 | if (unlikely(ret)) | 404 | if (unlikely(ret)) |
| 407 | EXOFS_ERR("%s: ore_write failed.\n", __func__); | 405 | EXOFS_ERR("%s: ore_write failed.\n", __func__); |
| 408 | 406 | ||
| 409 | |||
| 410 | unlock_super(sb); | ||
| 411 | out: | 407 | out: |
| 412 | EXOFS_DBGMSG("s_nextid=0x%llx ret=%d\n", _LLU(sbi->s_nextid), ret); | 408 | EXOFS_DBGMSG("s_nextid=0x%llx ret=%d\n", _LLU(sbi->s_nextid), ret); |
| 413 | ore_put_io_state(ios); | 409 | ore_put_io_state(ios); |
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 17ae5c83d234..29e79713c7eb 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
| @@ -2578,11 +2578,9 @@ out: | |||
| 2578 | static int ext3_unfreeze(struct super_block *sb) | 2578 | static int ext3_unfreeze(struct super_block *sb) |
| 2579 | { | 2579 | { |
| 2580 | if (!(sb->s_flags & MS_RDONLY)) { | 2580 | if (!(sb->s_flags & MS_RDONLY)) { |
| 2581 | lock_super(sb); | ||
| 2582 | /* Reser the needs_recovery flag before the fs is unlocked. */ | 2581 | /* Reser the needs_recovery flag before the fs is unlocked. */ |
| 2583 | EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); | 2582 | EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); |
| 2584 | ext3_commit_super(sb, EXT3_SB(sb)->s_es, 1); | 2583 | ext3_commit_super(sb, EXT3_SB(sb)->s_es, 1); |
| 2585 | unlock_super(sb); | ||
| 2586 | journal_unlock_updates(EXT3_SB(sb)->s_journal); | 2584 | journal_unlock_updates(EXT3_SB(sb)->s_journal); |
| 2587 | } | 2585 | } |
| 2588 | return 0; | 2586 | return 0; |
| @@ -2602,7 +2600,6 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data) | |||
| 2602 | #endif | 2600 | #endif |
| 2603 | 2601 | ||
| 2604 | /* Store the original options */ | 2602 | /* Store the original options */ |
| 2605 | lock_super(sb); | ||
| 2606 | old_sb_flags = sb->s_flags; | 2603 | old_sb_flags = sb->s_flags; |
| 2607 | old_opts.s_mount_opt = sbi->s_mount_opt; | 2604 | old_opts.s_mount_opt = sbi->s_mount_opt; |
| 2608 | old_opts.s_resuid = sbi->s_resuid; | 2605 | old_opts.s_resuid = sbi->s_resuid; |
| @@ -2708,8 +2705,6 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data) | |||
| 2708 | old_opts.s_qf_names[i] != sbi->s_qf_names[i]) | 2705 | old_opts.s_qf_names[i] != sbi->s_qf_names[i]) |
| 2709 | kfree(old_opts.s_qf_names[i]); | 2706 | kfree(old_opts.s_qf_names[i]); |
| 2710 | #endif | 2707 | #endif |
| 2711 | unlock_super(sb); | ||
| 2712 | |||
| 2713 | if (enable_quota) | 2708 | if (enable_quota) |
| 2714 | dquot_resume(sb, -1); | 2709 | dquot_resume(sb, -1); |
| 2715 | return 0; | 2710 | return 0; |
| @@ -2728,7 +2723,6 @@ restore_opts: | |||
| 2728 | sbi->s_qf_names[i] = old_opts.s_qf_names[i]; | 2723 | sbi->s_qf_names[i] = old_opts.s_qf_names[i]; |
| 2729 | } | 2724 | } |
| 2730 | #endif | 2725 | #endif |
| 2731 | unlock_super(sb); | ||
| 2732 | return err; | 2726 | return err; |
| 2733 | } | 2727 | } |
| 2734 | 2728 | ||
diff --git a/fs/fat/dir.c b/fs/fat/dir.c index bca6d0a1255e..2a182342442e 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c | |||
| @@ -571,7 +571,7 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent, | |||
| 571 | int short_len = 0, fill_len = 0; | 571 | int short_len = 0, fill_len = 0; |
| 572 | int ret = 0; | 572 | int ret = 0; |
| 573 | 573 | ||
| 574 | lock_super(sb); | 574 | mutex_lock(&sbi->s_lock); |
| 575 | 575 | ||
| 576 | cpos = filp->f_pos; | 576 | cpos = filp->f_pos; |
| 577 | /* Fake . and .. for the root directory. */ | 577 | /* Fake . and .. for the root directory. */ |
| @@ -693,7 +693,7 @@ fill_failed: | |||
| 693 | if (unicode) | 693 | if (unicode) |
| 694 | __putname(unicode); | 694 | __putname(unicode); |
| 695 | out: | 695 | out: |
| 696 | unlock_super(sb); | 696 | mutex_unlock(&sbi->s_lock); |
| 697 | return ret; | 697 | return ret; |
| 698 | } | 698 | } |
| 699 | 699 | ||
diff --git a/fs/fat/fat.h b/fs/fat/fat.h index ca7e8f8bad7c..623f36f0423b 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h | |||
| @@ -71,8 +71,9 @@ struct msdos_sb_info { | |||
| 71 | unsigned long root_cluster; /* first cluster of the root directory */ | 71 | unsigned long root_cluster; /* first cluster of the root directory */ |
| 72 | unsigned long fsinfo_sector; /* sector number of FAT32 fsinfo */ | 72 | unsigned long fsinfo_sector; /* sector number of FAT32 fsinfo */ |
| 73 | struct mutex fat_lock; | 73 | struct mutex fat_lock; |
| 74 | unsigned int prev_free; /* previously allocated cluster number */ | 74 | struct mutex s_lock; |
| 75 | unsigned int free_clusters; /* -1 if undefined */ | 75 | unsigned int prev_free; /* previously allocated cluster number */ |
| 76 | unsigned int free_clusters; /* -1 if undefined */ | ||
| 76 | unsigned int free_clus_valid; /* is free_clusters valid? */ | 77 | unsigned int free_clus_valid; /* is free_clusters valid? */ |
| 77 | struct fat_mount_options options; | 78 | struct fat_mount_options options; |
| 78 | struct nls_table *nls_disk; /* Codepage used on disk */ | 79 | struct nls_table *nls_disk; /* Codepage used on disk */ |
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 76f60c642c06..5bafaad00530 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
| @@ -673,9 +673,9 @@ static int fat_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
| 673 | if (inode->i_ino == MSDOS_FSINFO_INO) { | 673 | if (inode->i_ino == MSDOS_FSINFO_INO) { |
| 674 | struct super_block *sb = inode->i_sb; | 674 | struct super_block *sb = inode->i_sb; |
| 675 | 675 | ||
| 676 | lock_super(sb); | 676 | mutex_lock(&MSDOS_SB(sb)->s_lock); |
| 677 | err = fat_clusters_flush(sb); | 677 | err = fat_clusters_flush(sb); |
| 678 | unlock_super(sb); | 678 | mutex_unlock(&MSDOS_SB(sb)->s_lock); |
| 679 | } else | 679 | } else |
| 680 | err = __fat_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL); | 680 | err = __fat_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL); |
| 681 | 681 | ||
| @@ -1268,6 +1268,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, | |||
| 1268 | b = (struct fat_boot_sector *) bh->b_data; | 1268 | b = (struct fat_boot_sector *) bh->b_data; |
| 1269 | } | 1269 | } |
| 1270 | 1270 | ||
| 1271 | mutex_init(&sbi->s_lock); | ||
| 1271 | sbi->cluster_size = sb->s_blocksize * sbi->sec_per_clus; | 1272 | sbi->cluster_size = sb->s_blocksize * sbi->sec_per_clus; |
| 1272 | sbi->cluster_bits = ffs(sbi->cluster_size) - 1; | 1273 | sbi->cluster_bits = ffs(sbi->cluster_size) - 1; |
| 1273 | sbi->fats = b->fats; | 1274 | sbi->fats = b->fats; |
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c index c1055e778fff..e2cfda94a28d 100644 --- a/fs/fat/namei_msdos.c +++ b/fs/fat/namei_msdos.c | |||
| @@ -208,7 +208,7 @@ static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry, | |||
| 208 | struct inode *inode; | 208 | struct inode *inode; |
| 209 | int err; | 209 | int err; |
| 210 | 210 | ||
| 211 | lock_super(sb); | 211 | mutex_lock(&MSDOS_SB(sb)->s_lock); |
| 212 | err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo); | 212 | err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo); |
| 213 | switch (err) { | 213 | switch (err) { |
| 214 | case -ENOENT: | 214 | case -ENOENT: |
| @@ -221,7 +221,7 @@ static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry, | |||
| 221 | default: | 221 | default: |
| 222 | inode = ERR_PTR(err); | 222 | inode = ERR_PTR(err); |
| 223 | } | 223 | } |
| 224 | unlock_super(sb); | 224 | mutex_unlock(&MSDOS_SB(sb)->s_lock); |
| 225 | return d_splice_alias(inode, dentry); | 225 | return d_splice_alias(inode, dentry); |
| 226 | } | 226 | } |
| 227 | 227 | ||
| @@ -273,7 +273,7 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
| 273 | unsigned char msdos_name[MSDOS_NAME]; | 273 | unsigned char msdos_name[MSDOS_NAME]; |
| 274 | int err, is_hid; | 274 | int err, is_hid; |
| 275 | 275 | ||
| 276 | lock_super(sb); | 276 | mutex_lock(&MSDOS_SB(sb)->s_lock); |
| 277 | 277 | ||
| 278 | err = msdos_format_name(dentry->d_name.name, dentry->d_name.len, | 278 | err = msdos_format_name(dentry->d_name.name, dentry->d_name.len, |
| 279 | msdos_name, &MSDOS_SB(sb)->options); | 279 | msdos_name, &MSDOS_SB(sb)->options); |
| @@ -302,7 +302,7 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
| 302 | 302 | ||
| 303 | d_instantiate(dentry, inode); | 303 | d_instantiate(dentry, inode); |
| 304 | out: | 304 | out: |
| 305 | unlock_super(sb); | 305 | mutex_unlock(&MSDOS_SB(sb)->s_lock); |
| 306 | if (!err) | 306 | if (!err) |
| 307 | err = fat_flush_inodes(sb, dir, inode); | 307 | err = fat_flush_inodes(sb, dir, inode); |
| 308 | return err; | 308 | return err; |
| @@ -316,7 +316,7 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 316 | struct fat_slot_info sinfo; | 316 | struct fat_slot_info sinfo; |
| 317 | int err; | 317 | int err; |
| 318 | 318 | ||
| 319 | lock_super(sb); | 319 | mutex_lock(&MSDOS_SB(sb)->s_lock); |
| 320 | /* | 320 | /* |
| 321 | * Check whether the directory is not in use, then check | 321 | * Check whether the directory is not in use, then check |
| 322 | * whether it is empty. | 322 | * whether it is empty. |
| @@ -337,7 +337,7 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 337 | inode->i_ctime = CURRENT_TIME_SEC; | 337 | inode->i_ctime = CURRENT_TIME_SEC; |
| 338 | fat_detach(inode); | 338 | fat_detach(inode); |
| 339 | out: | 339 | out: |
| 340 | unlock_super(sb); | 340 | mutex_unlock(&MSDOS_SB(sb)->s_lock); |
| 341 | if (!err) | 341 | if (!err) |
| 342 | err = fat_flush_inodes(sb, dir, inode); | 342 | err = fat_flush_inodes(sb, dir, inode); |
| 343 | 343 | ||
| @@ -354,7 +354,7 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
| 354 | struct timespec ts; | 354 | struct timespec ts; |
| 355 | int err, is_hid, cluster; | 355 | int err, is_hid, cluster; |
| 356 | 356 | ||
| 357 | lock_super(sb); | 357 | mutex_lock(&MSDOS_SB(sb)->s_lock); |
| 358 | 358 | ||
| 359 | err = msdos_format_name(dentry->d_name.name, dentry->d_name.len, | 359 | err = msdos_format_name(dentry->d_name.name, dentry->d_name.len, |
| 360 | msdos_name, &MSDOS_SB(sb)->options); | 360 | msdos_name, &MSDOS_SB(sb)->options); |
| @@ -392,14 +392,14 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
| 392 | 392 | ||
| 393 | d_instantiate(dentry, inode); | 393 | d_instantiate(dentry, inode); |
| 394 | 394 | ||
| 395 | unlock_super(sb); | 395 | mutex_unlock(&MSDOS_SB(sb)->s_lock); |
| 396 | fat_flush_inodes(sb, dir, inode); | 396 | fat_flush_inodes(sb, dir, inode); |
| 397 | return 0; | 397 | return 0; |
| 398 | 398 | ||
| 399 | out_free: | 399 | out_free: |
| 400 | fat_free_clusters(dir, cluster); | 400 | fat_free_clusters(dir, cluster); |
| 401 | out: | 401 | out: |
| 402 | unlock_super(sb); | 402 | mutex_unlock(&MSDOS_SB(sb)->s_lock); |
| 403 | return err; | 403 | return err; |
| 404 | } | 404 | } |
| 405 | 405 | ||
| @@ -411,7 +411,7 @@ static int msdos_unlink(struct inode *dir, struct dentry *dentry) | |||
| 411 | struct fat_slot_info sinfo; | 411 | struct fat_slot_info sinfo; |
| 412 | int err; | 412 | int err; |
| 413 | 413 | ||
| 414 | lock_super(sb); | 414 | mutex_lock(&MSDOS_SB(sb)->s_lock); |
| 415 | err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo); | 415 | err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo); |
| 416 | if (err) | 416 | if (err) |
| 417 | goto out; | 417 | goto out; |
| @@ -423,7 +423,7 @@ static int msdos_unlink(struct inode *dir, struct dentry *dentry) | |||
| 423 | inode->i_ctime = CURRENT_TIME_SEC; | 423 | inode->i_ctime = CURRENT_TIME_SEC; |
| 424 | fat_detach(inode); | 424 | fat_detach(inode); |
| 425 | out: | 425 | out: |
| 426 | unlock_super(sb); | 426 | mutex_unlock(&MSDOS_SB(sb)->s_lock); |
| 427 | if (!err) | 427 | if (!err) |
| 428 | err = fat_flush_inodes(sb, dir, inode); | 428 | err = fat_flush_inodes(sb, dir, inode); |
| 429 | 429 | ||
| @@ -606,7 +606,7 @@ static int msdos_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 606 | unsigned char old_msdos_name[MSDOS_NAME], new_msdos_name[MSDOS_NAME]; | 606 | unsigned char old_msdos_name[MSDOS_NAME], new_msdos_name[MSDOS_NAME]; |
| 607 | int err, is_hid; | 607 | int err, is_hid; |
| 608 | 608 | ||
| 609 | lock_super(sb); | 609 | mutex_lock(&MSDOS_SB(sb)->s_lock); |
| 610 | 610 | ||
| 611 | err = msdos_format_name(old_dentry->d_name.name, | 611 | err = msdos_format_name(old_dentry->d_name.name, |
| 612 | old_dentry->d_name.len, old_msdos_name, | 612 | old_dentry->d_name.len, old_msdos_name, |
| @@ -625,7 +625,7 @@ static int msdos_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 625 | err = do_msdos_rename(old_dir, old_msdos_name, old_dentry, | 625 | err = do_msdos_rename(old_dir, old_msdos_name, old_dentry, |
| 626 | new_dir, new_msdos_name, new_dentry, is_hid); | 626 | new_dir, new_msdos_name, new_dentry, is_hid); |
| 627 | out: | 627 | out: |
| 628 | unlock_super(sb); | 628 | mutex_unlock(&MSDOS_SB(sb)->s_lock); |
| 629 | if (!err) | 629 | if (!err) |
| 630 | err = fat_flush_inodes(sb, old_dir, new_dir); | 630 | err = fat_flush_inodes(sb, old_dir, new_dir); |
| 631 | return err; | 631 | return err; |
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index e535dd75b986..ac959d655e7d 100644 --- a/fs/fat/namei_vfat.c +++ b/fs/fat/namei_vfat.c | |||
| @@ -721,7 +721,7 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry, | |||
| 721 | struct dentry *alias; | 721 | struct dentry *alias; |
| 722 | int err; | 722 | int err; |
| 723 | 723 | ||
| 724 | lock_super(sb); | 724 | mutex_lock(&MSDOS_SB(sb)->s_lock); |
| 725 | 725 | ||
| 726 | err = vfat_find(dir, &dentry->d_name, &sinfo); | 726 | err = vfat_find(dir, &dentry->d_name, &sinfo); |
| 727 | if (err) { | 727 | if (err) { |
| @@ -752,13 +752,13 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry, | |||
| 752 | if (!S_ISDIR(inode->i_mode)) | 752 | if (!S_ISDIR(inode->i_mode)) |
| 753 | d_move(alias, dentry); | 753 | d_move(alias, dentry); |
| 754 | iput(inode); | 754 | iput(inode); |
| 755 | unlock_super(sb); | 755 | mutex_unlock(&MSDOS_SB(sb)->s_lock); |
| 756 | return alias; | 756 | return alias; |
| 757 | } else | 757 | } else |
| 758 | dput(alias); | 758 | dput(alias); |
| 759 | 759 | ||
| 760 | out: | 760 | out: |
| 761 | unlock_super(sb); | 761 | mutex_unlock(&MSDOS_SB(sb)->s_lock); |
| 762 | dentry->d_time = dentry->d_parent->d_inode->i_version; | 762 | dentry->d_time = dentry->d_parent->d_inode->i_version; |
| 763 | dentry = d_splice_alias(inode, dentry); | 763 | dentry = d_splice_alias(inode, dentry); |
| 764 | if (dentry) | 764 | if (dentry) |
| @@ -766,7 +766,7 @@ out: | |||
| 766 | return dentry; | 766 | return dentry; |
| 767 | 767 | ||
| 768 | error: | 768 | error: |
| 769 | unlock_super(sb); | 769 | mutex_unlock(&MSDOS_SB(sb)->s_lock); |
| 770 | return ERR_PTR(err); | 770 | return ERR_PTR(err); |
| 771 | } | 771 | } |
| 772 | 772 | ||
| @@ -779,7 +779,7 @@ static int vfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
| 779 | struct timespec ts; | 779 | struct timespec ts; |
| 780 | int err; | 780 | int err; |
| 781 | 781 | ||
| 782 | lock_super(sb); | 782 | mutex_lock(&MSDOS_SB(sb)->s_lock); |
| 783 | 783 | ||
| 784 | ts = CURRENT_TIME_SEC; | 784 | ts = CURRENT_TIME_SEC; |
| 785 | err = vfat_add_entry(dir, &dentry->d_name, 0, 0, &ts, &sinfo); | 785 | err = vfat_add_entry(dir, &dentry->d_name, 0, 0, &ts, &sinfo); |
| @@ -800,7 +800,7 @@ static int vfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
| 800 | dentry->d_time = dentry->d_parent->d_inode->i_version; | 800 | dentry->d_time = dentry->d_parent->d_inode->i_version; |
| 801 | d_instantiate(dentry, inode); | 801 | d_instantiate(dentry, inode); |
| 802 | out: | 802 | out: |
| 803 | unlock_super(sb); | 803 | mutex_unlock(&MSDOS_SB(sb)->s_lock); |
| 804 | return err; | 804 | return err; |
| 805 | } | 805 | } |
| 806 | 806 | ||
| @@ -811,7 +811,7 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 811 | struct fat_slot_info sinfo; | 811 | struct fat_slot_info sinfo; |
| 812 | int err; | 812 | int err; |
| 813 | 813 | ||
| 814 | lock_super(sb); | 814 | mutex_lock(&MSDOS_SB(sb)->s_lock); |
| 815 | 815 | ||
| 816 | err = fat_dir_empty(inode); | 816 | err = fat_dir_empty(inode); |
| 817 | if (err) | 817 | if (err) |
| @@ -829,7 +829,7 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 829 | inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC; | 829 | inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC; |
| 830 | fat_detach(inode); | 830 | fat_detach(inode); |
| 831 | out: | 831 | out: |
| 832 | unlock_super(sb); | 832 | mutex_unlock(&MSDOS_SB(sb)->s_lock); |
| 833 | 833 | ||
| 834 | return err; | 834 | return err; |
| 835 | } | 835 | } |
| @@ -841,7 +841,7 @@ static int vfat_unlink(struct inode *dir, struct dentry *dentry) | |||
| 841 | struct fat_slot_info sinfo; | 841 | struct fat_slot_info sinfo; |
| 842 | int err; | 842 | int err; |
| 843 | 843 | ||
| 844 | lock_super(sb); | 844 | mutex_lock(&MSDOS_SB(sb)->s_lock); |
| 845 | 845 | ||
| 846 | err = vfat_find(dir, &dentry->d_name, &sinfo); | 846 | err = vfat_find(dir, &dentry->d_name, &sinfo); |
| 847 | if (err) | 847 | if (err) |
| @@ -854,7 +854,7 @@ static int vfat_unlink(struct inode *dir, struct dentry *dentry) | |||
| 854 | inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC; | 854 | inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC; |
| 855 | fat_detach(inode); | 855 | fat_detach(inode); |
| 856 | out: | 856 | out: |
| 857 | unlock_super(sb); | 857 | mutex_unlock(&MSDOS_SB(sb)->s_lock); |
| 858 | 858 | ||
| 859 | return err; | 859 | return err; |
| 860 | } | 860 | } |
| @@ -867,7 +867,7 @@ static int vfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
| 867 | struct timespec ts; | 867 | struct timespec ts; |
| 868 | int err, cluster; | 868 | int err, cluster; |
| 869 | 869 | ||
| 870 | lock_super(sb); | 870 | mutex_lock(&MSDOS_SB(sb)->s_lock); |
| 871 | 871 | ||
| 872 | ts = CURRENT_TIME_SEC; | 872 | ts = CURRENT_TIME_SEC; |
| 873 | cluster = fat_alloc_new_dir(dir, &ts); | 873 | cluster = fat_alloc_new_dir(dir, &ts); |
| @@ -896,13 +896,13 @@ static int vfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
| 896 | dentry->d_time = dentry->d_parent->d_inode->i_version; | 896 | dentry->d_time = dentry->d_parent->d_inode->i_version; |
| 897 | d_instantiate(dentry, inode); | 897 | d_instantiate(dentry, inode); |
| 898 | 898 | ||
| 899 | unlock_super(sb); | 899 | mutex_unlock(&MSDOS_SB(sb)->s_lock); |
| 900 | return 0; | 900 | return 0; |
| 901 | 901 | ||
| 902 | out_free: | 902 | out_free: |
| 903 | fat_free_clusters(dir, cluster); | 903 | fat_free_clusters(dir, cluster); |
| 904 | out: | 904 | out: |
| 905 | unlock_super(sb); | 905 | mutex_unlock(&MSDOS_SB(sb)->s_lock); |
| 906 | return err; | 906 | return err; |
| 907 | } | 907 | } |
| 908 | 908 | ||
| @@ -921,7 +921,7 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 921 | old_sinfo.bh = sinfo.bh = dotdot_bh = NULL; | 921 | old_sinfo.bh = sinfo.bh = dotdot_bh = NULL; |
| 922 | old_inode = old_dentry->d_inode; | 922 | old_inode = old_dentry->d_inode; |
| 923 | new_inode = new_dentry->d_inode; | 923 | new_inode = new_dentry->d_inode; |
| 924 | lock_super(sb); | 924 | mutex_lock(&MSDOS_SB(sb)->s_lock); |
| 925 | err = vfat_find(old_dir, &old_dentry->d_name, &old_sinfo); | 925 | err = vfat_find(old_dir, &old_dentry->d_name, &old_sinfo); |
| 926 | if (err) | 926 | if (err) |
| 927 | goto out; | 927 | goto out; |
| @@ -996,7 +996,7 @@ out: | |||
| 996 | brelse(sinfo.bh); | 996 | brelse(sinfo.bh); |
| 997 | brelse(dotdot_bh); | 997 | brelse(dotdot_bh); |
| 998 | brelse(old_sinfo.bh); | 998 | brelse(old_sinfo.bh); |
| 999 | unlock_super(sb); | 999 | mutex_unlock(&MSDOS_SB(sb)->s_lock); |
| 1000 | 1000 | ||
| 1001 | return err; | 1001 | return err; |
| 1002 | 1002 | ||
| @@ -922,6 +922,9 @@ SYSCALL_DEFINE3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags) | |||
| 922 | if ((flags & ~O_CLOEXEC) != 0) | 922 | if ((flags & ~O_CLOEXEC) != 0) |
| 923 | return -EINVAL; | 923 | return -EINVAL; |
| 924 | 924 | ||
| 925 | if (unlikely(oldfd == newfd)) | ||
| 926 | return -EINVAL; | ||
| 927 | |||
| 925 | if (newfd >= rlimit(RLIMIT_NOFILE)) | 928 | if (newfd >= rlimit(RLIMIT_NOFILE)) |
| 926 | return -EMFILE; | 929 | return -EMFILE; |
| 927 | 930 | ||
diff --git a/fs/file_table.c b/fs/file_table.c index dac67923330f..a72bf9ddd0d2 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
| @@ -36,7 +36,7 @@ struct files_stat_struct files_stat = { | |||
| 36 | .max_files = NR_FILE | 36 | .max_files = NR_FILE |
| 37 | }; | 37 | }; |
| 38 | 38 | ||
| 39 | DEFINE_LGLOCK(files_lglock); | 39 | DEFINE_STATIC_LGLOCK(files_lglock); |
| 40 | 40 | ||
| 41 | /* SLAB cache for file structures */ | 41 | /* SLAB cache for file structures */ |
| 42 | static struct kmem_cache *filp_cachep __read_mostly; | 42 | static struct kmem_cache *filp_cachep __read_mostly; |
diff --git a/fs/filesystems.c b/fs/filesystems.c index 96f24286667a..da165f6adcbf 100644 --- a/fs/filesystems.c +++ b/fs/filesystems.c | |||
| @@ -124,7 +124,7 @@ EXPORT_SYMBOL(unregister_filesystem); | |||
| 124 | static int fs_index(const char __user * __name) | 124 | static int fs_index(const char __user * __name) |
| 125 | { | 125 | { |
| 126 | struct file_system_type * tmp; | 126 | struct file_system_type * tmp; |
| 127 | char * name; | 127 | struct filename *name; |
| 128 | int err, index; | 128 | int err, index; |
| 129 | 129 | ||
| 130 | name = getname(__name); | 130 | name = getname(__name); |
| @@ -135,7 +135,7 @@ static int fs_index(const char __user * __name) | |||
| 135 | err = -EINVAL; | 135 | err = -EINVAL; |
| 136 | read_lock(&file_systems_lock); | 136 | read_lock(&file_systems_lock); |
| 137 | for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) { | 137 | for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) { |
| 138 | if (strcmp(tmp->name,name) == 0) { | 138 | if (strcmp(tmp->name, name->name) == 0) { |
| 139 | err = index; | 139 | err = index; |
| 140 | break; | 140 | break; |
| 141 | } | 141 | } |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 401b6c6248ae..51ea267d444c 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
| @@ -249,7 +249,7 @@ static bool inode_dirtied_after(struct inode *inode, unsigned long t) | |||
| 249 | } | 249 | } |
| 250 | 250 | ||
| 251 | /* | 251 | /* |
| 252 | * Move expired (dirtied after work->older_than_this) dirty inodes from | 252 | * Move expired (dirtied before work->older_than_this) dirty inodes from |
| 253 | * @delaying_queue to @dispatch_queue. | 253 | * @delaying_queue to @dispatch_queue. |
| 254 | */ | 254 | */ |
| 255 | static int move_expired_inodes(struct list_head *delaying_queue, | 255 | static int move_expired_inodes(struct list_head *delaying_queue, |
diff --git a/fs/gfs2/export.c b/fs/gfs2/export.c index e8ed6d4a6181..4767774a5f3e 100644 --- a/fs/gfs2/export.c +++ b/fs/gfs2/export.c | |||
| @@ -161,6 +161,8 @@ static struct dentry *gfs2_fh_to_dentry(struct super_block *sb, struct fid *fid, | |||
| 161 | case GFS2_SMALL_FH_SIZE: | 161 | case GFS2_SMALL_FH_SIZE: |
| 162 | case GFS2_LARGE_FH_SIZE: | 162 | case GFS2_LARGE_FH_SIZE: |
| 163 | case GFS2_OLD_FH_SIZE: | 163 | case GFS2_OLD_FH_SIZE: |
| 164 | if (fh_len < GFS2_SMALL_FH_SIZE) | ||
| 165 | return NULL; | ||
| 164 | this.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32; | 166 | this.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32; |
| 165 | this.no_formal_ino |= be32_to_cpu(fh[1]); | 167 | this.no_formal_ino |= be32_to_cpu(fh[1]); |
| 166 | this.no_addr = ((u64)be32_to_cpu(fh[2])) << 32; | 168 | this.no_addr = ((u64)be32_to_cpu(fh[2])) << 32; |
| @@ -180,6 +182,8 @@ static struct dentry *gfs2_fh_to_parent(struct super_block *sb, struct fid *fid, | |||
| 180 | switch (fh_type) { | 182 | switch (fh_type) { |
| 181 | case GFS2_LARGE_FH_SIZE: | 183 | case GFS2_LARGE_FH_SIZE: |
| 182 | case GFS2_OLD_FH_SIZE: | 184 | case GFS2_OLD_FH_SIZE: |
| 185 | if (fh_len < GFS2_LARGE_FH_SIZE) | ||
| 186 | return NULL; | ||
| 183 | parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32; | 187 | parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32; |
| 184 | parent.no_formal_ino |= be32_to_cpu(fh[5]); | 188 | parent.no_formal_ino |= be32_to_cpu(fh[5]); |
| 185 | parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32; | 189 | parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32; |
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index bc28bf077a6a..a3076228523d 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c | |||
| @@ -398,7 +398,6 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data) | |||
| 398 | *flags |= MS_NOATIME; | 398 | *flags |= MS_NOATIME; |
| 399 | 399 | ||
| 400 | hpfs_lock(s); | 400 | hpfs_lock(s); |
| 401 | lock_super(s); | ||
| 402 | uid = sbi->sb_uid; gid = sbi->sb_gid; | 401 | uid = sbi->sb_uid; gid = sbi->sb_gid; |
| 403 | umask = 0777 & ~sbi->sb_mode; | 402 | umask = 0777 & ~sbi->sb_mode; |
| 404 | lowercase = sbi->sb_lowercase; | 403 | lowercase = sbi->sb_lowercase; |
| @@ -431,12 +430,10 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data) | |||
| 431 | 430 | ||
| 432 | replace_mount_options(s, new_opts); | 431 | replace_mount_options(s, new_opts); |
| 433 | 432 | ||
| 434 | unlock_super(s); | ||
| 435 | hpfs_unlock(s); | 433 | hpfs_unlock(s); |
| 436 | return 0; | 434 | return 0; |
| 437 | 435 | ||
| 438 | out_err: | 436 | out_err: |
| 439 | unlock_super(s); | ||
| 440 | hpfs_unlock(s); | 437 | hpfs_unlock(s); |
| 441 | kfree(new_opts); | 438 | kfree(new_opts); |
| 442 | return -EINVAL; | 439 | return -EINVAL; |
diff --git a/fs/internal.h b/fs/internal.h index 371bcc4b1697..916b7cbf3e3e 100644 --- a/fs/internal.h +++ b/fs/internal.h | |||
| @@ -97,8 +97,8 @@ struct open_flags { | |||
| 97 | int acc_mode; | 97 | int acc_mode; |
| 98 | int intent; | 98 | int intent; |
| 99 | }; | 99 | }; |
| 100 | extern struct file *do_filp_open(int dfd, const char *pathname, | 100 | extern struct file *do_filp_open(int dfd, struct filename *pathname, |
| 101 | const struct open_flags *op, int lookup_flags); | 101 | const struct open_flags *op, int flags); |
| 102 | extern struct file *do_file_open_root(struct dentry *, struct vfsmount *, | 102 | extern struct file *do_file_open_root(struct dentry *, struct vfsmount *, |
| 103 | const char *, const struct open_flags *, int lookup_flags); | 103 | const char *, const struct open_flags *, int lookup_flags); |
| 104 | 104 | ||
diff --git a/fs/isofs/export.c b/fs/isofs/export.c index 1d3804492aa7..2b4f2358eadb 100644 --- a/fs/isofs/export.c +++ b/fs/isofs/export.c | |||
| @@ -175,7 +175,7 @@ static struct dentry *isofs_fh_to_parent(struct super_block *sb, | |||
| 175 | { | 175 | { |
| 176 | struct isofs_fid *ifid = (struct isofs_fid *)fid; | 176 | struct isofs_fid *ifid = (struct isofs_fid *)fid; |
| 177 | 177 | ||
| 178 | if (fh_type != 2) | 178 | if (fh_len < 2 || fh_type != 2) |
| 179 | return NULL; | 179 | return NULL; |
| 180 | 180 | ||
| 181 | return isofs_export_iget(sb, | 181 | return isofs_export_iget(sb, |
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 7e355870d519..a2aa97d45670 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c | |||
| @@ -126,7 +126,7 @@ static void restart_grace(void) | |||
| 126 | static int | 126 | static int |
| 127 | lockd(void *vrqstp) | 127 | lockd(void *vrqstp) |
| 128 | { | 128 | { |
| 129 | int err = 0, preverr = 0; | 129 | int err = 0; |
| 130 | struct svc_rqst *rqstp = vrqstp; | 130 | struct svc_rqst *rqstp = vrqstp; |
| 131 | 131 | ||
| 132 | /* try_to_freeze() is called from svc_recv() */ | 132 | /* try_to_freeze() is called from svc_recv() */ |
| @@ -165,21 +165,8 @@ lockd(void *vrqstp) | |||
| 165 | * recvfrom routine. | 165 | * recvfrom routine. |
| 166 | */ | 166 | */ |
| 167 | err = svc_recv(rqstp, timeout); | 167 | err = svc_recv(rqstp, timeout); |
| 168 | if (err == -EAGAIN || err == -EINTR) { | 168 | if (err == -EAGAIN || err == -EINTR) |
| 169 | preverr = err; | ||
| 170 | continue; | 169 | continue; |
| 171 | } | ||
| 172 | if (err < 0) { | ||
| 173 | if (err != preverr) { | ||
| 174 | printk(KERN_WARNING "%s: unexpected error " | ||
| 175 | "from svc_recv (%d)\n", __func__, err); | ||
| 176 | preverr = err; | ||
| 177 | } | ||
| 178 | schedule_timeout_interruptible(HZ); | ||
| 179 | continue; | ||
| 180 | } | ||
| 181 | preverr = err; | ||
| 182 | |||
| 183 | dprintk("lockd: request from %s\n", | 170 | dprintk("lockd: request from %s\n", |
| 184 | svc_print_addr(rqstp, buf, sizeof(buf))); | 171 | svc_print_addr(rqstp, buf, sizeof(buf))); |
| 185 | 172 | ||
diff --git a/fs/locks.c b/fs/locks.c index abc7dc6c490b..a94e331a52a2 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
| @@ -1289,7 +1289,7 @@ EXPORT_SYMBOL(__break_lease); | |||
| 1289 | void lease_get_mtime(struct inode *inode, struct timespec *time) | 1289 | void lease_get_mtime(struct inode *inode, struct timespec *time) |
| 1290 | { | 1290 | { |
| 1291 | struct file_lock *flock = inode->i_flock; | 1291 | struct file_lock *flock = inode->i_flock; |
| 1292 | if (flock && IS_LEASE(flock) && (flock->fl_type & F_WRLCK)) | 1292 | if (flock && IS_LEASE(flock) && (flock->fl_type == F_WRLCK)) |
| 1293 | *time = current_fs_time(inode->i_sb); | 1293 | *time = current_fs_time(inode->i_sb); |
| 1294 | else | 1294 | else |
| 1295 | *time = inode->i_mtime; | 1295 | *time = inode->i_mtime; |
| @@ -2185,8 +2185,8 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl, | |||
| 2185 | } else { | 2185 | } else { |
| 2186 | seq_printf(f, "%s ", | 2186 | seq_printf(f, "%s ", |
| 2187 | (lease_breaking(fl)) | 2187 | (lease_breaking(fl)) |
| 2188 | ? (fl->fl_type & F_UNLCK) ? "UNLCK" : "READ " | 2188 | ? (fl->fl_type == F_UNLCK) ? "UNLCK" : "READ " |
| 2189 | : (fl->fl_type & F_WRLCK) ? "WRITE" : "READ "); | 2189 | : (fl->fl_type == F_WRLCK) ? "WRITE" : "READ "); |
| 2190 | } | 2190 | } |
| 2191 | if (inode) { | 2191 | if (inode) { |
| 2192 | #ifdef WE_CAN_BREAK_LSLK_NOW | 2192 | #ifdef WE_CAN_BREAK_LSLK_NOW |
diff --git a/fs/namei.c b/fs/namei.c index aa30d19e9edd..d1895f308156 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -117,18 +117,70 @@ | |||
| 117 | * POSIX.1 2.4: an empty pathname is invalid (ENOENT). | 117 | * POSIX.1 2.4: an empty pathname is invalid (ENOENT). |
| 118 | * PATH_MAX includes the nul terminator --RR. | 118 | * PATH_MAX includes the nul terminator --RR. |
| 119 | */ | 119 | */ |
| 120 | static char *getname_flags(const char __user *filename, int flags, int *empty) | 120 | void final_putname(struct filename *name) |
| 121 | { | 121 | { |
| 122 | char *result = __getname(), *err; | 122 | if (name->separate) { |
| 123 | __putname(name->name); | ||
| 124 | kfree(name); | ||
| 125 | } else { | ||
| 126 | __putname(name); | ||
| 127 | } | ||
| 128 | } | ||
| 129 | |||
| 130 | #define EMBEDDED_NAME_MAX (PATH_MAX - sizeof(struct filename)) | ||
| 131 | |||
| 132 | static struct filename * | ||
| 133 | getname_flags(const char __user *filename, int flags, int *empty) | ||
| 134 | { | ||
| 135 | struct filename *result, *err; | ||
| 123 | int len; | 136 | int len; |
| 137 | long max; | ||
| 138 | char *kname; | ||
| 124 | 139 | ||
| 140 | result = audit_reusename(filename); | ||
| 141 | if (result) | ||
| 142 | return result; | ||
| 143 | |||
| 144 | result = __getname(); | ||
| 125 | if (unlikely(!result)) | 145 | if (unlikely(!result)) |
| 126 | return ERR_PTR(-ENOMEM); | 146 | return ERR_PTR(-ENOMEM); |
| 127 | 147 | ||
| 128 | len = strncpy_from_user(result, filename, PATH_MAX); | 148 | /* |
| 129 | err = ERR_PTR(len); | 149 | * First, try to embed the struct filename inside the names_cache |
| 130 | if (unlikely(len < 0)) | 150 | * allocation |
| 151 | */ | ||
| 152 | kname = (char *)result + sizeof(*result); | ||
| 153 | result->name = kname; | ||
| 154 | result->separate = false; | ||
| 155 | max = EMBEDDED_NAME_MAX; | ||
| 156 | |||
| 157 | recopy: | ||
| 158 | len = strncpy_from_user(kname, filename, max); | ||
| 159 | if (unlikely(len < 0)) { | ||
| 160 | err = ERR_PTR(len); | ||
| 131 | goto error; | 161 | goto error; |
| 162 | } | ||
| 163 | |||
| 164 | /* | ||
| 165 | * Uh-oh. We have a name that's approaching PATH_MAX. Allocate a | ||
| 166 | * separate struct filename so we can dedicate the entire | ||
| 167 | * names_cache allocation for the pathname, and re-do the copy from | ||
| 168 | * userland. | ||
| 169 | */ | ||
| 170 | if (len == EMBEDDED_NAME_MAX && max == EMBEDDED_NAME_MAX) { | ||
| 171 | kname = (char *)result; | ||
| 172 | |||
| 173 | result = kzalloc(sizeof(*result), GFP_KERNEL); | ||
| 174 | if (!result) { | ||
| 175 | err = ERR_PTR(-ENOMEM); | ||
| 176 | result = (struct filename *)kname; | ||
| 177 | goto error; | ||
| 178 | } | ||
| 179 | result->name = kname; | ||
| 180 | result->separate = true; | ||
| 181 | max = PATH_MAX; | ||
| 182 | goto recopy; | ||
| 183 | } | ||
| 132 | 184 | ||
| 133 | /* The empty path is special. */ | 185 | /* The empty path is special. */ |
| 134 | if (unlikely(!len)) { | 186 | if (unlikely(!len)) { |
| @@ -140,30 +192,32 @@ static char *getname_flags(const char __user *filename, int flags, int *empty) | |||
| 140 | } | 192 | } |
| 141 | 193 | ||
| 142 | err = ERR_PTR(-ENAMETOOLONG); | 194 | err = ERR_PTR(-ENAMETOOLONG); |
| 143 | if (likely(len < PATH_MAX)) { | 195 | if (unlikely(len >= PATH_MAX)) |
| 144 | audit_getname(result); | 196 | goto error; |
| 145 | return result; | 197 | |
| 146 | } | 198 | result->uptr = filename; |
| 199 | audit_getname(result); | ||
| 200 | return result; | ||
| 147 | 201 | ||
| 148 | error: | 202 | error: |
| 149 | __putname(result); | 203 | final_putname(result); |
| 150 | return err; | 204 | return err; |
| 151 | } | 205 | } |
| 152 | 206 | ||
| 153 | char *getname(const char __user * filename) | 207 | struct filename * |
| 208 | getname(const char __user * filename) | ||
| 154 | { | 209 | { |
| 155 | return getname_flags(filename, 0, NULL); | 210 | return getname_flags(filename, 0, NULL); |
| 156 | } | 211 | } |
| 212 | EXPORT_SYMBOL(getname); | ||
| 157 | 213 | ||
| 158 | #ifdef CONFIG_AUDITSYSCALL | 214 | #ifdef CONFIG_AUDITSYSCALL |
| 159 | void putname(const char *name) | 215 | void putname(struct filename *name) |
| 160 | { | 216 | { |
| 161 | if (unlikely(!audit_dummy_context())) | 217 | if (unlikely(!audit_dummy_context())) |
| 162 | audit_putname(name); | 218 | return audit_putname(name); |
| 163 | else | 219 | final_putname(name); |
| 164 | __putname(name); | ||
| 165 | } | 220 | } |
| 166 | EXPORT_SYMBOL(putname); | ||
| 167 | #endif | 221 | #endif |
| 168 | 222 | ||
| 169 | static int check_acl(struct inode *inode, int mask) | 223 | static int check_acl(struct inode *inode, int mask) |
| @@ -692,9 +746,9 @@ static inline int may_follow_link(struct path *link, struct nameidata *nd) | |||
| 692 | if (uid_eq(parent->i_uid, inode->i_uid)) | 746 | if (uid_eq(parent->i_uid, inode->i_uid)) |
| 693 | return 0; | 747 | return 0; |
| 694 | 748 | ||
| 749 | audit_log_link_denied("follow_link", link); | ||
| 695 | path_put_conditional(link, nd); | 750 | path_put_conditional(link, nd); |
| 696 | path_put(&nd->path); | 751 | path_put(&nd->path); |
| 697 | audit_log_link_denied("follow_link", link); | ||
| 698 | return -EACCES; | 752 | return -EACCES; |
| 699 | } | 753 | } |
| 700 | 754 | ||
| @@ -810,6 +864,7 @@ follow_link(struct path *link, struct nameidata *nd, void **p) | |||
| 810 | return error; | 864 | return error; |
| 811 | 865 | ||
| 812 | out_put_nd_path: | 866 | out_put_nd_path: |
| 867 | *p = NULL; | ||
| 813 | path_put(&nd->path); | 868 | path_put(&nd->path); |
| 814 | path_put(link); | 869 | path_put(link); |
| 815 | return error; | 870 | return error; |
| @@ -1962,24 +2017,29 @@ static int path_lookupat(int dfd, const char *name, | |||
| 1962 | return err; | 2017 | return err; |
| 1963 | } | 2018 | } |
| 1964 | 2019 | ||
| 1965 | static int do_path_lookup(int dfd, const char *name, | 2020 | static int filename_lookup(int dfd, struct filename *name, |
| 1966 | unsigned int flags, struct nameidata *nd) | 2021 | unsigned int flags, struct nameidata *nd) |
| 1967 | { | 2022 | { |
| 1968 | int retval = path_lookupat(dfd, name, flags | LOOKUP_RCU, nd); | 2023 | int retval = path_lookupat(dfd, name->name, flags | LOOKUP_RCU, nd); |
| 1969 | if (unlikely(retval == -ECHILD)) | 2024 | if (unlikely(retval == -ECHILD)) |
| 1970 | retval = path_lookupat(dfd, name, flags, nd); | 2025 | retval = path_lookupat(dfd, name->name, flags, nd); |
| 1971 | if (unlikely(retval == -ESTALE)) | 2026 | if (unlikely(retval == -ESTALE)) |
| 1972 | retval = path_lookupat(dfd, name, flags | LOOKUP_REVAL, nd); | 2027 | retval = path_lookupat(dfd, name->name, |
| 2028 | flags | LOOKUP_REVAL, nd); | ||
| 1973 | 2029 | ||
| 1974 | if (likely(!retval)) { | 2030 | if (likely(!retval)) |
| 1975 | if (unlikely(!audit_dummy_context())) { | 2031 | audit_inode(name, nd->path.dentry, flags & LOOKUP_PARENT); |
| 1976 | if (nd->path.dentry && nd->inode) | ||
| 1977 | audit_inode(name, nd->path.dentry); | ||
| 1978 | } | ||
| 1979 | } | ||
| 1980 | return retval; | 2032 | return retval; |
| 1981 | } | 2033 | } |
| 1982 | 2034 | ||
| 2035 | static int do_path_lookup(int dfd, const char *name, | ||
| 2036 | unsigned int flags, struct nameidata *nd) | ||
| 2037 | { | ||
| 2038 | struct filename filename = { .name = name }; | ||
| 2039 | |||
| 2040 | return filename_lookup(dfd, &filename, flags, nd); | ||
| 2041 | } | ||
| 2042 | |||
| 1983 | /* does lookup, returns the object with parent locked */ | 2043 | /* does lookup, returns the object with parent locked */ |
| 1984 | struct dentry *kern_path_locked(const char *name, struct path *path) | 2044 | struct dentry *kern_path_locked(const char *name, struct path *path) |
| 1985 | { | 2045 | { |
| @@ -2097,13 +2157,13 @@ int user_path_at_empty(int dfd, const char __user *name, unsigned flags, | |||
| 2097 | struct path *path, int *empty) | 2157 | struct path *path, int *empty) |
| 2098 | { | 2158 | { |
| 2099 | struct nameidata nd; | 2159 | struct nameidata nd; |
| 2100 | char *tmp = getname_flags(name, flags, empty); | 2160 | struct filename *tmp = getname_flags(name, flags, empty); |
| 2101 | int err = PTR_ERR(tmp); | 2161 | int err = PTR_ERR(tmp); |
| 2102 | if (!IS_ERR(tmp)) { | 2162 | if (!IS_ERR(tmp)) { |
| 2103 | 2163 | ||
| 2104 | BUG_ON(flags & LOOKUP_PARENT); | 2164 | BUG_ON(flags & LOOKUP_PARENT); |
| 2105 | 2165 | ||
| 2106 | err = do_path_lookup(dfd, tmp, flags, &nd); | 2166 | err = filename_lookup(dfd, tmp, flags, &nd); |
| 2107 | putname(tmp); | 2167 | putname(tmp); |
| 2108 | if (!err) | 2168 | if (!err) |
| 2109 | *path = nd.path; | 2169 | *path = nd.path; |
| @@ -2117,22 +2177,28 @@ int user_path_at(int dfd, const char __user *name, unsigned flags, | |||
| 2117 | return user_path_at_empty(dfd, name, flags, path, NULL); | 2177 | return user_path_at_empty(dfd, name, flags, path, NULL); |
| 2118 | } | 2178 | } |
| 2119 | 2179 | ||
| 2120 | static int user_path_parent(int dfd, const char __user *path, | 2180 | /* |
| 2121 | struct nameidata *nd, char **name) | 2181 | * NB: most callers don't do anything directly with the reference to the |
| 2182 | * to struct filename, but the nd->last pointer points into the name string | ||
| 2183 | * allocated by getname. So we must hold the reference to it until all | ||
| 2184 | * path-walking is complete. | ||
| 2185 | */ | ||
| 2186 | static struct filename * | ||
| 2187 | user_path_parent(int dfd, const char __user *path, struct nameidata *nd) | ||
| 2122 | { | 2188 | { |
| 2123 | char *s = getname(path); | 2189 | struct filename *s = getname(path); |
| 2124 | int error; | 2190 | int error; |
| 2125 | 2191 | ||
| 2126 | if (IS_ERR(s)) | 2192 | if (IS_ERR(s)) |
| 2127 | return PTR_ERR(s); | 2193 | return s; |
| 2128 | 2194 | ||
| 2129 | error = do_path_lookup(dfd, s, LOOKUP_PARENT, nd); | 2195 | error = filename_lookup(dfd, s, LOOKUP_PARENT, nd); |
| 2130 | if (error) | 2196 | if (error) { |
| 2131 | putname(s); | 2197 | putname(s); |
| 2132 | else | 2198 | return ERR_PTR(error); |
| 2133 | *name = s; | 2199 | } |
| 2134 | 2200 | ||
| 2135 | return error; | 2201 | return s; |
| 2136 | } | 2202 | } |
| 2137 | 2203 | ||
| 2138 | /* | 2204 | /* |
| @@ -2179,7 +2245,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir) | |||
| 2179 | return -ENOENT; | 2245 | return -ENOENT; |
| 2180 | 2246 | ||
| 2181 | BUG_ON(victim->d_parent->d_inode != dir); | 2247 | BUG_ON(victim->d_parent->d_inode != dir); |
| 2182 | audit_inode_child(victim, dir); | 2248 | audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE); |
| 2183 | 2249 | ||
| 2184 | error = inode_permission(dir, MAY_WRITE | MAY_EXEC); | 2250 | error = inode_permission(dir, MAY_WRITE | MAY_EXEC); |
| 2185 | if (error) | 2251 | if (error) |
| @@ -2624,7 +2690,7 @@ out_dput: | |||
| 2624 | */ | 2690 | */ |
| 2625 | static int do_last(struct nameidata *nd, struct path *path, | 2691 | static int do_last(struct nameidata *nd, struct path *path, |
| 2626 | struct file *file, const struct open_flags *op, | 2692 | struct file *file, const struct open_flags *op, |
| 2627 | int *opened, const char *pathname) | 2693 | int *opened, struct filename *name) |
| 2628 | { | 2694 | { |
| 2629 | struct dentry *dir = nd->path.dentry; | 2695 | struct dentry *dir = nd->path.dentry; |
| 2630 | int open_flag = op->open_flag; | 2696 | int open_flag = op->open_flag; |
| @@ -2651,7 +2717,7 @@ static int do_last(struct nameidata *nd, struct path *path, | |||
| 2651 | error = complete_walk(nd); | 2717 | error = complete_walk(nd); |
| 2652 | if (error) | 2718 | if (error) |
| 2653 | return error; | 2719 | return error; |
| 2654 | audit_inode(pathname, nd->path.dentry); | 2720 | audit_inode(name, nd->path.dentry, 0); |
| 2655 | if (open_flag & O_CREAT) { | 2721 | if (open_flag & O_CREAT) { |
| 2656 | error = -EISDIR; | 2722 | error = -EISDIR; |
| 2657 | goto out; | 2723 | goto out; |
| @@ -2661,7 +2727,7 @@ static int do_last(struct nameidata *nd, struct path *path, | |||
| 2661 | error = complete_walk(nd); | 2727 | error = complete_walk(nd); |
| 2662 | if (error) | 2728 | if (error) |
| 2663 | return error; | 2729 | return error; |
| 2664 | audit_inode(pathname, dir); | 2730 | audit_inode(name, dir, 0); |
| 2665 | goto finish_open; | 2731 | goto finish_open; |
| 2666 | } | 2732 | } |
| 2667 | 2733 | ||
| @@ -2690,7 +2756,7 @@ static int do_last(struct nameidata *nd, struct path *path, | |||
| 2690 | if (error) | 2756 | if (error) |
| 2691 | return error; | 2757 | return error; |
| 2692 | 2758 | ||
| 2693 | audit_inode(pathname, dir); | 2759 | audit_inode(name, dir, 0); |
| 2694 | error = -EISDIR; | 2760 | error = -EISDIR; |
| 2695 | /* trailing slashes? */ | 2761 | /* trailing slashes? */ |
| 2696 | if (nd->last.name[nd->last.len]) | 2762 | if (nd->last.name[nd->last.len]) |
| @@ -2720,7 +2786,7 @@ retry_lookup: | |||
| 2720 | !S_ISREG(file->f_path.dentry->d_inode->i_mode)) | 2786 | !S_ISREG(file->f_path.dentry->d_inode->i_mode)) |
| 2721 | will_truncate = false; | 2787 | will_truncate = false; |
| 2722 | 2788 | ||
| 2723 | audit_inode(pathname, file->f_path.dentry); | 2789 | audit_inode(name, file->f_path.dentry, 0); |
| 2724 | goto opened; | 2790 | goto opened; |
| 2725 | } | 2791 | } |
| 2726 | 2792 | ||
| @@ -2737,7 +2803,7 @@ retry_lookup: | |||
| 2737 | * create/update audit record if it already exists. | 2803 | * create/update audit record if it already exists. |
| 2738 | */ | 2804 | */ |
| 2739 | if (path->dentry->d_inode) | 2805 | if (path->dentry->d_inode) |
| 2740 | audit_inode(pathname, path->dentry); | 2806 | audit_inode(name, path->dentry, 0); |
| 2741 | 2807 | ||
| 2742 | /* | 2808 | /* |
| 2743 | * If atomic_open() acquired write access it is dropped now due to | 2809 | * If atomic_open() acquired write access it is dropped now due to |
| @@ -2802,7 +2868,7 @@ finish_lookup: | |||
| 2802 | error = -ENOTDIR; | 2868 | error = -ENOTDIR; |
| 2803 | if ((nd->flags & LOOKUP_DIRECTORY) && !nd->inode->i_op->lookup) | 2869 | if ((nd->flags & LOOKUP_DIRECTORY) && !nd->inode->i_op->lookup) |
| 2804 | goto out; | 2870 | goto out; |
| 2805 | audit_inode(pathname, nd->path.dentry); | 2871 | audit_inode(name, nd->path.dentry, 0); |
| 2806 | finish_open: | 2872 | finish_open: |
| 2807 | if (!S_ISREG(nd->inode->i_mode)) | 2873 | if (!S_ISREG(nd->inode->i_mode)) |
| 2808 | will_truncate = false; | 2874 | will_truncate = false; |
| @@ -2870,7 +2936,7 @@ stale_open: | |||
| 2870 | goto retry_lookup; | 2936 | goto retry_lookup; |
| 2871 | } | 2937 | } |
| 2872 | 2938 | ||
| 2873 | static struct file *path_openat(int dfd, const char *pathname, | 2939 | static struct file *path_openat(int dfd, struct filename *pathname, |
| 2874 | struct nameidata *nd, const struct open_flags *op, int flags) | 2940 | struct nameidata *nd, const struct open_flags *op, int flags) |
| 2875 | { | 2941 | { |
| 2876 | struct file *base = NULL; | 2942 | struct file *base = NULL; |
| @@ -2885,12 +2951,12 @@ static struct file *path_openat(int dfd, const char *pathname, | |||
| 2885 | 2951 | ||
| 2886 | file->f_flags = op->open_flag; | 2952 | file->f_flags = op->open_flag; |
| 2887 | 2953 | ||
| 2888 | error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base); | 2954 | error = path_init(dfd, pathname->name, flags | LOOKUP_PARENT, nd, &base); |
| 2889 | if (unlikely(error)) | 2955 | if (unlikely(error)) |
| 2890 | goto out; | 2956 | goto out; |
| 2891 | 2957 | ||
| 2892 | current->total_link_count = 0; | 2958 | current->total_link_count = 0; |
| 2893 | error = link_path_walk(pathname, nd); | 2959 | error = link_path_walk(pathname->name, nd); |
| 2894 | if (unlikely(error)) | 2960 | if (unlikely(error)) |
| 2895 | goto out; | 2961 | goto out; |
| 2896 | 2962 | ||
| @@ -2936,7 +3002,7 @@ out: | |||
| 2936 | return file; | 3002 | return file; |
| 2937 | } | 3003 | } |
| 2938 | 3004 | ||
| 2939 | struct file *do_filp_open(int dfd, const char *pathname, | 3005 | struct file *do_filp_open(int dfd, struct filename *pathname, |
| 2940 | const struct open_flags *op, int flags) | 3006 | const struct open_flags *op, int flags) |
| 2941 | { | 3007 | { |
| 2942 | struct nameidata nd; | 3008 | struct nameidata nd; |
| @@ -2955,6 +3021,7 @@ struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt, | |||
| 2955 | { | 3021 | { |
| 2956 | struct nameidata nd; | 3022 | struct nameidata nd; |
| 2957 | struct file *file; | 3023 | struct file *file; |
| 3024 | struct filename filename = { .name = name }; | ||
| 2958 | 3025 | ||
| 2959 | nd.root.mnt = mnt; | 3026 | nd.root.mnt = mnt; |
| 2960 | nd.root.dentry = dentry; | 3027 | nd.root.dentry = dentry; |
| @@ -2964,11 +3031,11 @@ struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt, | |||
| 2964 | if (dentry->d_inode->i_op->follow_link && op->intent & LOOKUP_OPEN) | 3031 | if (dentry->d_inode->i_op->follow_link && op->intent & LOOKUP_OPEN) |
| 2965 | return ERR_PTR(-ELOOP); | 3032 | return ERR_PTR(-ELOOP); |
| 2966 | 3033 | ||
| 2967 | file = path_openat(-1, name, &nd, op, flags | LOOKUP_RCU); | 3034 | file = path_openat(-1, &filename, &nd, op, flags | LOOKUP_RCU); |
| 2968 | if (unlikely(file == ERR_PTR(-ECHILD))) | 3035 | if (unlikely(file == ERR_PTR(-ECHILD))) |
| 2969 | file = path_openat(-1, name, &nd, op, flags); | 3036 | file = path_openat(-1, &filename, &nd, op, flags); |
| 2970 | if (unlikely(file == ERR_PTR(-ESTALE))) | 3037 | if (unlikely(file == ERR_PTR(-ESTALE))) |
| 2971 | file = path_openat(-1, name, &nd, op, flags | LOOKUP_REVAL); | 3038 | file = path_openat(-1, &filename, &nd, op, flags | LOOKUP_REVAL); |
| 2972 | return file; | 3039 | return file; |
| 2973 | } | 3040 | } |
| 2974 | 3041 | ||
| @@ -3043,11 +3110,11 @@ EXPORT_SYMBOL(done_path_create); | |||
| 3043 | 3110 | ||
| 3044 | struct dentry *user_path_create(int dfd, const char __user *pathname, struct path *path, int is_dir) | 3111 | struct dentry *user_path_create(int dfd, const char __user *pathname, struct path *path, int is_dir) |
| 3045 | { | 3112 | { |
| 3046 | char *tmp = getname(pathname); | 3113 | struct filename *tmp = getname(pathname); |
| 3047 | struct dentry *res; | 3114 | struct dentry *res; |
| 3048 | if (IS_ERR(tmp)) | 3115 | if (IS_ERR(tmp)) |
| 3049 | return ERR_CAST(tmp); | 3116 | return ERR_CAST(tmp); |
| 3050 | res = kern_path_create(dfd, tmp, path, is_dir); | 3117 | res = kern_path_create(dfd, tmp->name, path, is_dir); |
| 3051 | putname(tmp); | 3118 | putname(tmp); |
| 3052 | return res; | 3119 | return res; |
| 3053 | } | 3120 | } |
| @@ -3252,13 +3319,13 @@ out: | |||
| 3252 | static long do_rmdir(int dfd, const char __user *pathname) | 3319 | static long do_rmdir(int dfd, const char __user *pathname) |
| 3253 | { | 3320 | { |
| 3254 | int error = 0; | 3321 | int error = 0; |
| 3255 | char * name; | 3322 | struct filename *name; |
| 3256 | struct dentry *dentry; | 3323 | struct dentry *dentry; |
| 3257 | struct nameidata nd; | 3324 | struct nameidata nd; |
| 3258 | 3325 | ||
| 3259 | error = user_path_parent(dfd, pathname, &nd, &name); | 3326 | name = user_path_parent(dfd, pathname, &nd); |
| 3260 | if (error) | 3327 | if (IS_ERR(name)) |
| 3261 | return error; | 3328 | return PTR_ERR(name); |
| 3262 | 3329 | ||
| 3263 | switch(nd.last_type) { | 3330 | switch(nd.last_type) { |
| 3264 | case LAST_DOTDOT: | 3331 | case LAST_DOTDOT: |
| @@ -3347,14 +3414,14 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) | |||
| 3347 | static long do_unlinkat(int dfd, const char __user *pathname) | 3414 | static long do_unlinkat(int dfd, const char __user *pathname) |
| 3348 | { | 3415 | { |
| 3349 | int error; | 3416 | int error; |
| 3350 | char *name; | 3417 | struct filename *name; |
| 3351 | struct dentry *dentry; | 3418 | struct dentry *dentry; |
| 3352 | struct nameidata nd; | 3419 | struct nameidata nd; |
| 3353 | struct inode *inode = NULL; | 3420 | struct inode *inode = NULL; |
| 3354 | 3421 | ||
| 3355 | error = user_path_parent(dfd, pathname, &nd, &name); | 3422 | name = user_path_parent(dfd, pathname, &nd); |
| 3356 | if (error) | 3423 | if (IS_ERR(name)) |
| 3357 | return error; | 3424 | return PTR_ERR(name); |
| 3358 | 3425 | ||
| 3359 | error = -EISDIR; | 3426 | error = -EISDIR; |
| 3360 | if (nd.last_type != LAST_NORM) | 3427 | if (nd.last_type != LAST_NORM) |
| @@ -3438,7 +3505,7 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname, | |||
| 3438 | int, newdfd, const char __user *, newname) | 3505 | int, newdfd, const char __user *, newname) |
| 3439 | { | 3506 | { |
| 3440 | int error; | 3507 | int error; |
| 3441 | char *from; | 3508 | struct filename *from; |
| 3442 | struct dentry *dentry; | 3509 | struct dentry *dentry; |
| 3443 | struct path path; | 3510 | struct path path; |
| 3444 | 3511 | ||
| @@ -3451,9 +3518,9 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname, | |||
| 3451 | if (IS_ERR(dentry)) | 3518 | if (IS_ERR(dentry)) |
| 3452 | goto out_putname; | 3519 | goto out_putname; |
| 3453 | 3520 | ||
| 3454 | error = security_path_symlink(&path, dentry, from); | 3521 | error = security_path_symlink(&path, dentry, from->name); |
| 3455 | if (!error) | 3522 | if (!error) |
| 3456 | error = vfs_symlink(path.dentry->d_inode, dentry, from); | 3523 | error = vfs_symlink(path.dentry->d_inode, dentry, from->name); |
| 3457 | done_path_create(&path, dentry); | 3524 | done_path_create(&path, dentry); |
| 3458 | out_putname: | 3525 | out_putname: |
| 3459 | putname(from); | 3526 | putname(from); |
| @@ -3733,17 +3800,21 @@ SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, | |||
| 3733 | struct dentry *old_dentry, *new_dentry; | 3800 | struct dentry *old_dentry, *new_dentry; |
| 3734 | struct dentry *trap; | 3801 | struct dentry *trap; |
| 3735 | struct nameidata oldnd, newnd; | 3802 | struct nameidata oldnd, newnd; |
| 3736 | char *from; | 3803 | struct filename *from; |
| 3737 | char *to; | 3804 | struct filename *to; |
| 3738 | int error; | 3805 | int error; |
| 3739 | 3806 | ||
| 3740 | error = user_path_parent(olddfd, oldname, &oldnd, &from); | 3807 | from = user_path_parent(olddfd, oldname, &oldnd); |
| 3741 | if (error) | 3808 | if (IS_ERR(from)) { |
| 3809 | error = PTR_ERR(from); | ||
| 3742 | goto exit; | 3810 | goto exit; |
| 3811 | } | ||
| 3743 | 3812 | ||
| 3744 | error = user_path_parent(newdfd, newname, &newnd, &to); | 3813 | to = user_path_parent(newdfd, newname, &newnd); |
| 3745 | if (error) | 3814 | if (IS_ERR(to)) { |
| 3815 | error = PTR_ERR(to); | ||
| 3746 | goto exit1; | 3816 | goto exit1; |
| 3817 | } | ||
| 3747 | 3818 | ||
| 3748 | error = -EXDEV; | 3819 | error = -EXDEV; |
| 3749 | if (oldnd.path.mnt != newnd.path.mnt) | 3820 | if (oldnd.path.mnt != newnd.path.mnt) |
| @@ -3967,7 +4038,6 @@ EXPORT_SYMBOL(follow_down_one); | |||
| 3967 | EXPORT_SYMBOL(follow_down); | 4038 | EXPORT_SYMBOL(follow_down); |
| 3968 | EXPORT_SYMBOL(follow_up); | 4039 | EXPORT_SYMBOL(follow_up); |
| 3969 | EXPORT_SYMBOL(get_write_access); /* nfsd */ | 4040 | EXPORT_SYMBOL(get_write_access); /* nfsd */ |
| 3970 | EXPORT_SYMBOL(getname); | ||
| 3971 | EXPORT_SYMBOL(lock_rename); | 4041 | EXPORT_SYMBOL(lock_rename); |
| 3972 | EXPORT_SYMBOL(lookup_one_len); | 4042 | EXPORT_SYMBOL(lookup_one_len); |
| 3973 | EXPORT_SYMBOL(page_follow_link_light); | 4043 | EXPORT_SYMBOL(page_follow_link_light); |
diff --git a/fs/namespace.c b/fs/namespace.c index 7bdf7907413f..24960626bb6b 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
| @@ -1640,7 +1640,7 @@ static int do_change_type(struct path *path, int flag) | |||
| 1640 | /* | 1640 | /* |
| 1641 | * do loopback mount. | 1641 | * do loopback mount. |
| 1642 | */ | 1642 | */ |
| 1643 | static int do_loopback(struct path *path, char *old_name, | 1643 | static int do_loopback(struct path *path, const char *old_name, |
| 1644 | int recurse) | 1644 | int recurse) |
| 1645 | { | 1645 | { |
| 1646 | LIST_HEAD(umount_list); | 1646 | LIST_HEAD(umount_list); |
| @@ -1764,7 +1764,7 @@ static inline int tree_contains_unbindable(struct mount *mnt) | |||
| 1764 | return 0; | 1764 | return 0; |
| 1765 | } | 1765 | } |
| 1766 | 1766 | ||
| 1767 | static int do_move_mount(struct path *path, char *old_name) | 1767 | static int do_move_mount(struct path *path, const char *old_name) |
| 1768 | { | 1768 | { |
| 1769 | struct path old_path, parent_path; | 1769 | struct path old_path, parent_path; |
| 1770 | struct mount *p; | 1770 | struct mount *p; |
| @@ -1917,8 +1917,8 @@ unlock: | |||
| 1917 | * create a new mount for userspace and request it to be added into the | 1917 | * create a new mount for userspace and request it to be added into the |
| 1918 | * namespace's tree | 1918 | * namespace's tree |
| 1919 | */ | 1919 | */ |
| 1920 | static int do_new_mount(struct path *path, char *type, int flags, | 1920 | static int do_new_mount(struct path *path, const char *type, int flags, |
| 1921 | int mnt_flags, char *name, void *data) | 1921 | int mnt_flags, const char *name, void *data) |
| 1922 | { | 1922 | { |
| 1923 | struct vfsmount *mnt; | 1923 | struct vfsmount *mnt; |
| 1924 | int err; | 1924 | int err; |
| @@ -2191,8 +2191,8 @@ int copy_mount_string(const void __user *data, char **where) | |||
| 2191 | * Therefore, if this magic number is present, it carries no information | 2191 | * Therefore, if this magic number is present, it carries no information |
| 2192 | * and must be discarded. | 2192 | * and must be discarded. |
| 2193 | */ | 2193 | */ |
| 2194 | long do_mount(char *dev_name, char *dir_name, char *type_page, | 2194 | long do_mount(const char *dev_name, const char *dir_name, |
| 2195 | unsigned long flags, void *data_page) | 2195 | const char *type_page, unsigned long flags, void *data_page) |
| 2196 | { | 2196 | { |
| 2197 | struct path path; | 2197 | struct path path; |
| 2198 | int retval = 0; | 2198 | int retval = 0; |
| @@ -2408,7 +2408,7 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, | |||
| 2408 | { | 2408 | { |
| 2409 | int ret; | 2409 | int ret; |
| 2410 | char *kernel_type; | 2410 | char *kernel_type; |
| 2411 | char *kernel_dir; | 2411 | struct filename *kernel_dir; |
| 2412 | char *kernel_dev; | 2412 | char *kernel_dev; |
| 2413 | unsigned long data_page; | 2413 | unsigned long data_page; |
| 2414 | 2414 | ||
| @@ -2430,7 +2430,7 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, | |||
| 2430 | if (ret < 0) | 2430 | if (ret < 0) |
| 2431 | goto out_data; | 2431 | goto out_data; |
| 2432 | 2432 | ||
| 2433 | ret = do_mount(kernel_dev, kernel_dir, kernel_type, flags, | 2433 | ret = do_mount(kernel_dev, kernel_dir->name, kernel_type, flags, |
| 2434 | (void *) data_page); | 2434 | (void *) data_page); |
| 2435 | 2435 | ||
| 2436 | free_page(data_page); | 2436 | free_page(data_page); |
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 2245bef50f37..9a521fb39869 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c | |||
| @@ -72,7 +72,7 @@ out_err: | |||
| 72 | static int | 72 | static int |
| 73 | nfs4_callback_svc(void *vrqstp) | 73 | nfs4_callback_svc(void *vrqstp) |
| 74 | { | 74 | { |
| 75 | int err, preverr = 0; | 75 | int err; |
| 76 | struct svc_rqst *rqstp = vrqstp; | 76 | struct svc_rqst *rqstp = vrqstp; |
| 77 | 77 | ||
| 78 | set_freezable(); | 78 | set_freezable(); |
| @@ -82,20 +82,8 @@ nfs4_callback_svc(void *vrqstp) | |||
| 82 | * Listen for a request on the socket | 82 | * Listen for a request on the socket |
| 83 | */ | 83 | */ |
| 84 | err = svc_recv(rqstp, MAX_SCHEDULE_TIMEOUT); | 84 | err = svc_recv(rqstp, MAX_SCHEDULE_TIMEOUT); |
| 85 | if (err == -EAGAIN || err == -EINTR) { | 85 | if (err == -EAGAIN || err == -EINTR) |
| 86 | preverr = err; | ||
| 87 | continue; | 86 | continue; |
| 88 | } | ||
| 89 | if (err < 0) { | ||
| 90 | if (err != preverr) { | ||
| 91 | printk(KERN_WARNING "NFS: %s: unexpected error " | ||
| 92 | "from svc_recv (%d)\n", __func__, err); | ||
| 93 | preverr = err; | ||
| 94 | } | ||
| 95 | schedule_timeout_uninterruptible(HZ); | ||
| 96 | continue; | ||
| 97 | } | ||
| 98 | preverr = err; | ||
| 99 | svc_process(rqstp); | 87 | svc_process(rqstp); |
| 100 | } | 88 | } |
| 101 | return 0; | 89 | return 0; |
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c index 6aa5590c3679..b314888825d5 100644 --- a/fs/nfsd/nfs2acl.c +++ b/fs/nfsd/nfs2acl.c | |||
| @@ -218,8 +218,7 @@ static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p, | |||
| 218 | * There must be an encoding function for void results so svc_process | 218 | * There must be an encoding function for void results so svc_process |
| 219 | * will work properly. | 219 | * will work properly. |
| 220 | */ | 220 | */ |
| 221 | int | 221 | static int nfsaclsvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy) |
| 222 | nfsaclsvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy) | ||
| 223 | { | 222 | { |
| 224 | return xdr_ressize_check(rqstp, p); | 223 | return xdr_ressize_check(rqstp, p); |
| 225 | } | 224 | } |
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c index 9095f3c21df9..97d90d1c8608 100644 --- a/fs/nfsd/nfs3proc.c +++ b/fs/nfsd/nfs3proc.c | |||
| @@ -247,7 +247,7 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp, | |||
| 247 | /* Now create the file and set attributes */ | 247 | /* Now create the file and set attributes */ |
| 248 | nfserr = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len, | 248 | nfserr = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len, |
| 249 | attr, newfhp, | 249 | attr, newfhp, |
| 250 | argp->createmode, argp->verf, NULL, NULL); | 250 | argp->createmode, (u32 *)argp->verf, NULL, NULL); |
| 251 | 251 | ||
| 252 | RETURN_STATUS(nfserr); | 252 | RETURN_STATUS(nfserr); |
| 253 | } | 253 | } |
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index 4c7bd35b1876..bdf29c96e4cd 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c | |||
| @@ -1028,7 +1028,6 @@ void nfsd4_cb_recall(struct nfs4_delegation *dp) | |||
| 1028 | cb->cb_msg.rpc_cred = callback_cred; | 1028 | cb->cb_msg.rpc_cred = callback_cred; |
| 1029 | 1029 | ||
| 1030 | cb->cb_ops = &nfsd4_cb_recall_ops; | 1030 | cb->cb_ops = &nfsd4_cb_recall_ops; |
| 1031 | dp->dl_retries = 1; | ||
| 1032 | 1031 | ||
| 1033 | INIT_LIST_HEAD(&cb->cb_per_client); | 1032 | INIT_LIST_HEAD(&cb->cb_per_client); |
| 1034 | cb->cb_done = true; | 1033 | cb->cb_done = true; |
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index fdc91a6fc9c4..a1f10c0a6255 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c | |||
| @@ -478,7 +478,7 @@ nfsd_idmap_init(struct net *net) | |||
| 478 | goto destroy_idtoname_cache; | 478 | goto destroy_idtoname_cache; |
| 479 | nn->nametoid_cache = cache_create_net(&nametoid_cache_template, net); | 479 | nn->nametoid_cache = cache_create_net(&nametoid_cache_template, net); |
| 480 | if (IS_ERR(nn->nametoid_cache)) { | 480 | if (IS_ERR(nn->nametoid_cache)) { |
| 481 | rv = PTR_ERR(nn->idtoname_cache); | 481 | rv = PTR_ERR(nn->nametoid_cache); |
| 482 | goto unregister_idtoname_cache; | 482 | goto unregister_idtoname_cache; |
| 483 | } | 483 | } |
| 484 | rv = cache_register_net(nn->nametoid_cache, net); | 484 | rv = cache_register_net(nn->nametoid_cache, net); |
| @@ -598,7 +598,7 @@ numeric_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namel | |||
| 598 | /* Just to make sure it's null-terminated: */ | 598 | /* Just to make sure it's null-terminated: */ |
| 599 | memcpy(buf, name, namelen); | 599 | memcpy(buf, name, namelen); |
| 600 | buf[namelen] = '\0'; | 600 | buf[namelen] = '\0'; |
| 601 | ret = kstrtouint(name, 10, id); | 601 | ret = kstrtouint(buf, 10, id); |
| 602 | return ret == 0; | 602 | return ret == 0; |
| 603 | } | 603 | } |
| 604 | 604 | ||
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index c9c1c0a25417..6c9a4b291dba 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
| @@ -370,7 +370,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 370 | break; | 370 | break; |
| 371 | case NFS4_OPEN_CLAIM_PREVIOUS: | 371 | case NFS4_OPEN_CLAIM_PREVIOUS: |
| 372 | open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; | 372 | open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; |
| 373 | status = nfs4_check_open_reclaim(&open->op_clientid); | 373 | status = nfs4_check_open_reclaim(&open->op_clientid, cstate->minorversion); |
| 374 | if (status) | 374 | if (status) |
| 375 | goto out; | 375 | goto out; |
| 376 | case NFS4_OPEN_CLAIM_FH: | 376 | case NFS4_OPEN_CLAIM_FH: |
| @@ -1054,8 +1054,8 @@ struct nfsd4_operation { | |||
| 1054 | char *op_name; | 1054 | char *op_name; |
| 1055 | /* Try to get response size before operation */ | 1055 | /* Try to get response size before operation */ |
| 1056 | nfsd4op_rsize op_rsize_bop; | 1056 | nfsd4op_rsize op_rsize_bop; |
| 1057 | stateid_setter op_get_currentstateid; | 1057 | stateid_getter op_get_currentstateid; |
| 1058 | stateid_getter op_set_currentstateid; | 1058 | stateid_setter op_set_currentstateid; |
| 1059 | }; | 1059 | }; |
| 1060 | 1060 | ||
| 1061 | static struct nfsd4_operation nfsd4_ops[]; | 1061 | static struct nfsd4_operation nfsd4_ops[]; |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 48a1bad37334..d0237f872cc4 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
| @@ -758,7 +758,7 @@ static void nfsd4_put_drc_mem(int slotsize, int num) | |||
| 758 | spin_unlock(&nfsd_drc_lock); | 758 | spin_unlock(&nfsd_drc_lock); |
| 759 | } | 759 | } |
| 760 | 760 | ||
| 761 | static struct nfsd4_session *alloc_session(int slotsize, int numslots) | 761 | static struct nfsd4_session *__alloc_session(int slotsize, int numslots) |
| 762 | { | 762 | { |
| 763 | struct nfsd4_session *new; | 763 | struct nfsd4_session *new; |
| 764 | int mem, i; | 764 | int mem, i; |
| @@ -852,35 +852,28 @@ static int nfsd4_register_conn(struct nfsd4_conn *conn) | |||
| 852 | return register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user); | 852 | return register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user); |
| 853 | } | 853 | } |
| 854 | 854 | ||
| 855 | static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses, u32 dir) | 855 | static void nfsd4_init_conn(struct svc_rqst *rqstp, struct nfsd4_conn *conn, struct nfsd4_session *ses) |
| 856 | { | 856 | { |
| 857 | struct nfsd4_conn *conn; | ||
| 858 | int ret; | 857 | int ret; |
| 859 | 858 | ||
| 860 | conn = alloc_conn(rqstp, dir); | ||
| 861 | if (!conn) | ||
| 862 | return nfserr_jukebox; | ||
| 863 | nfsd4_hash_conn(conn, ses); | 859 | nfsd4_hash_conn(conn, ses); |
| 864 | ret = nfsd4_register_conn(conn); | 860 | ret = nfsd4_register_conn(conn); |
| 865 | if (ret) | 861 | if (ret) |
| 866 | /* oops; xprt is already down: */ | 862 | /* oops; xprt is already down: */ |
| 867 | nfsd4_conn_lost(&conn->cn_xpt_user); | 863 | nfsd4_conn_lost(&conn->cn_xpt_user); |
| 868 | if (ses->se_client->cl_cb_state == NFSD4_CB_DOWN && | 864 | if (conn->cn_flags & NFS4_CDFC4_BACK) { |
| 869 | dir & NFS4_CDFC4_BACK) { | ||
| 870 | /* callback channel may be back up */ | 865 | /* callback channel may be back up */ |
| 871 | nfsd4_probe_callback(ses->se_client); | 866 | nfsd4_probe_callback(ses->se_client); |
| 872 | } | 867 | } |
| 873 | return nfs_ok; | ||
| 874 | } | 868 | } |
| 875 | 869 | ||
| 876 | static __be32 nfsd4_new_conn_from_crses(struct svc_rqst *rqstp, struct nfsd4_session *ses) | 870 | static struct nfsd4_conn *alloc_conn_from_crses(struct svc_rqst *rqstp, struct nfsd4_create_session *cses) |
| 877 | { | 871 | { |
| 878 | u32 dir = NFS4_CDFC4_FORE; | 872 | u32 dir = NFS4_CDFC4_FORE; |
| 879 | 873 | ||
| 880 | if (ses->se_flags & SESSION4_BACK_CHAN) | 874 | if (cses->flags & SESSION4_BACK_CHAN) |
| 881 | dir |= NFS4_CDFC4_BACK; | 875 | dir |= NFS4_CDFC4_BACK; |
| 882 | 876 | return alloc_conn(rqstp, dir); | |
| 883 | return nfsd4_new_conn(rqstp, ses, dir); | ||
| 884 | } | 877 | } |
| 885 | 878 | ||
| 886 | /* must be called under client_lock */ | 879 | /* must be called under client_lock */ |
| @@ -903,20 +896,21 @@ static void nfsd4_del_conns(struct nfsd4_session *s) | |||
| 903 | spin_unlock(&clp->cl_lock); | 896 | spin_unlock(&clp->cl_lock); |
| 904 | } | 897 | } |
| 905 | 898 | ||
| 899 | static void __free_session(struct nfsd4_session *ses) | ||
| 900 | { | ||
| 901 | nfsd4_put_drc_mem(slot_bytes(&ses->se_fchannel), ses->se_fchannel.maxreqs); | ||
| 902 | free_session_slots(ses); | ||
| 903 | kfree(ses); | ||
| 904 | } | ||
| 905 | |||
| 906 | static void free_session(struct kref *kref) | 906 | static void free_session(struct kref *kref) |
| 907 | { | 907 | { |
| 908 | struct nfsd4_session *ses; | 908 | struct nfsd4_session *ses; |
| 909 | int mem; | ||
| 910 | 909 | ||
| 911 | lockdep_assert_held(&client_lock); | 910 | lockdep_assert_held(&client_lock); |
| 912 | ses = container_of(kref, struct nfsd4_session, se_ref); | 911 | ses = container_of(kref, struct nfsd4_session, se_ref); |
| 913 | nfsd4_del_conns(ses); | 912 | nfsd4_del_conns(ses); |
| 914 | spin_lock(&nfsd_drc_lock); | 913 | __free_session(ses); |
| 915 | mem = ses->se_fchannel.maxreqs * slot_bytes(&ses->se_fchannel); | ||
| 916 | nfsd_drc_mem_used -= mem; | ||
| 917 | spin_unlock(&nfsd_drc_lock); | ||
| 918 | free_session_slots(ses); | ||
| 919 | kfree(ses); | ||
| 920 | } | 914 | } |
| 921 | 915 | ||
| 922 | void nfsd4_put_session(struct nfsd4_session *ses) | 916 | void nfsd4_put_session(struct nfsd4_session *ses) |
| @@ -926,14 +920,10 @@ void nfsd4_put_session(struct nfsd4_session *ses) | |||
| 926 | spin_unlock(&client_lock); | 920 | spin_unlock(&client_lock); |
| 927 | } | 921 | } |
| 928 | 922 | ||
| 929 | static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, struct nfsd4_create_session *cses) | 923 | static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan) |
| 930 | { | 924 | { |
| 931 | struct nfsd4_session *new; | 925 | struct nfsd4_session *new; |
| 932 | struct nfsd4_channel_attrs *fchan = &cses->fore_channel; | ||
| 933 | int numslots, slotsize; | 926 | int numslots, slotsize; |
| 934 | __be32 status; | ||
| 935 | int idx; | ||
| 936 | |||
| 937 | /* | 927 | /* |
| 938 | * Note decreasing slot size below client's request may | 928 | * Note decreasing slot size below client's request may |
| 939 | * make it difficult for client to function correctly, whereas | 929 | * make it difficult for client to function correctly, whereas |
| @@ -946,12 +936,18 @@ static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct n | |||
| 946 | if (numslots < 1) | 936 | if (numslots < 1) |
| 947 | return NULL; | 937 | return NULL; |
| 948 | 938 | ||
| 949 | new = alloc_session(slotsize, numslots); | 939 | new = __alloc_session(slotsize, numslots); |
| 950 | if (!new) { | 940 | if (!new) { |
| 951 | nfsd4_put_drc_mem(slotsize, fchan->maxreqs); | 941 | nfsd4_put_drc_mem(slotsize, fchan->maxreqs); |
| 952 | return NULL; | 942 | return NULL; |
| 953 | } | 943 | } |
| 954 | init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize); | 944 | init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize); |
| 945 | return new; | ||
| 946 | } | ||
| 947 | |||
| 948 | static struct nfsd4_session *init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, struct nfs4_client *clp, struct nfsd4_create_session *cses) | ||
| 949 | { | ||
| 950 | int idx; | ||
| 955 | 951 | ||
| 956 | new->se_client = clp; | 952 | new->se_client = clp; |
| 957 | gen_sessionid(new); | 953 | gen_sessionid(new); |
| @@ -970,14 +966,6 @@ static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct n | |||
| 970 | spin_unlock(&clp->cl_lock); | 966 | spin_unlock(&clp->cl_lock); |
| 971 | spin_unlock(&client_lock); | 967 | spin_unlock(&client_lock); |
| 972 | 968 | ||
| 973 | status = nfsd4_new_conn_from_crses(rqstp, new); | ||
| 974 | /* whoops: benny points out, status is ignored! (err, or bogus) */ | ||
| 975 | if (status) { | ||
| 976 | spin_lock(&client_lock); | ||
| 977 | free_session(&new->se_ref); | ||
| 978 | spin_unlock(&client_lock); | ||
| 979 | return NULL; | ||
| 980 | } | ||
| 981 | if (cses->flags & SESSION4_BACK_CHAN) { | 969 | if (cses->flags & SESSION4_BACK_CHAN) { |
| 982 | struct sockaddr *sa = svc_addr(rqstp); | 970 | struct sockaddr *sa = svc_addr(rqstp); |
| 983 | /* | 971 | /* |
| @@ -990,7 +978,6 @@ static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct n | |||
| 990 | rpc_copy_addr((struct sockaddr *)&clp->cl_cb_conn.cb_addr, sa); | 978 | rpc_copy_addr((struct sockaddr *)&clp->cl_cb_conn.cb_addr, sa); |
| 991 | clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa); | 979 | clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa); |
| 992 | } | 980 | } |
| 993 | nfsd4_probe_callback(clp); | ||
| 994 | return new; | 981 | return new; |
| 995 | } | 982 | } |
| 996 | 983 | ||
| @@ -1131,7 +1118,7 @@ unhash_client_locked(struct nfs4_client *clp) | |||
| 1131 | } | 1118 | } |
| 1132 | 1119 | ||
| 1133 | static void | 1120 | static void |
| 1134 | expire_client(struct nfs4_client *clp) | 1121 | destroy_client(struct nfs4_client *clp) |
| 1135 | { | 1122 | { |
| 1136 | struct nfs4_openowner *oo; | 1123 | struct nfs4_openowner *oo; |
| 1137 | struct nfs4_delegation *dp; | 1124 | struct nfs4_delegation *dp; |
| @@ -1165,6 +1152,12 @@ expire_client(struct nfs4_client *clp) | |||
| 1165 | spin_unlock(&client_lock); | 1152 | spin_unlock(&client_lock); |
| 1166 | } | 1153 | } |
| 1167 | 1154 | ||
| 1155 | static void expire_client(struct nfs4_client *clp) | ||
| 1156 | { | ||
| 1157 | nfsd4_client_record_remove(clp); | ||
| 1158 | destroy_client(clp); | ||
| 1159 | } | ||
| 1160 | |||
| 1168 | static void copy_verf(struct nfs4_client *target, nfs4_verifier *source) | 1161 | static void copy_verf(struct nfs4_client *target, nfs4_verifier *source) |
| 1169 | { | 1162 | { |
| 1170 | memcpy(target->cl_verifier.data, source->data, | 1163 | memcpy(target->cl_verifier.data, source->data, |
| @@ -1223,10 +1216,26 @@ static bool groups_equal(struct group_info *g1, struct group_info *g2) | |||
| 1223 | return true; | 1216 | return true; |
| 1224 | } | 1217 | } |
| 1225 | 1218 | ||
| 1219 | /* | ||
| 1220 | * RFC 3530 language requires clid_inuse be returned when the | ||
| 1221 | * "principal" associated with a requests differs from that previously | ||
| 1222 | * used. We use uid, gid's, and gss principal string as our best | ||
| 1223 | * approximation. We also don't want to allow non-gss use of a client | ||
| 1224 | * established using gss: in theory cr_principal should catch that | ||
| 1225 | * change, but in practice cr_principal can be null even in the gss case | ||
| 1226 | * since gssd doesn't always pass down a principal string. | ||
| 1227 | */ | ||
| 1228 | static bool is_gss_cred(struct svc_cred *cr) | ||
| 1229 | { | ||
| 1230 | /* Is cr_flavor one of the gss "pseudoflavors"?: */ | ||
| 1231 | return (cr->cr_flavor > RPC_AUTH_MAXFLAVOR); | ||
| 1232 | } | ||
| 1233 | |||
| 1234 | |||
| 1226 | static bool | 1235 | static bool |
| 1227 | same_creds(struct svc_cred *cr1, struct svc_cred *cr2) | 1236 | same_creds(struct svc_cred *cr1, struct svc_cred *cr2) |
| 1228 | { | 1237 | { |
| 1229 | if ((cr1->cr_flavor != cr2->cr_flavor) | 1238 | if ((is_gss_cred(cr1) != is_gss_cred(cr2)) |
| 1230 | || (cr1->cr_uid != cr2->cr_uid) | 1239 | || (cr1->cr_uid != cr2->cr_uid) |
| 1231 | || (cr1->cr_gid != cr2->cr_gid) | 1240 | || (cr1->cr_gid != cr2->cr_gid) |
| 1232 | || !groups_equal(cr1->cr_group_info, cr2->cr_group_info)) | 1241 | || !groups_equal(cr1->cr_group_info, cr2->cr_group_info)) |
| @@ -1340,13 +1349,15 @@ move_to_confirmed(struct nfs4_client *clp) | |||
| 1340 | } | 1349 | } |
| 1341 | 1350 | ||
| 1342 | static struct nfs4_client * | 1351 | static struct nfs4_client * |
| 1343 | find_confirmed_client(clientid_t *clid) | 1352 | find_confirmed_client(clientid_t *clid, bool sessions) |
| 1344 | { | 1353 | { |
| 1345 | struct nfs4_client *clp; | 1354 | struct nfs4_client *clp; |
| 1346 | unsigned int idhashval = clientid_hashval(clid->cl_id); | 1355 | unsigned int idhashval = clientid_hashval(clid->cl_id); |
| 1347 | 1356 | ||
| 1348 | list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) { | 1357 | list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) { |
| 1349 | if (same_clid(&clp->cl_clientid, clid)) { | 1358 | if (same_clid(&clp->cl_clientid, clid)) { |
| 1359 | if ((bool)clp->cl_minorversion != sessions) | ||
| 1360 | return NULL; | ||
| 1350 | renew_client(clp); | 1361 | renew_client(clp); |
| 1351 | return clp; | 1362 | return clp; |
| 1352 | } | 1363 | } |
| @@ -1355,14 +1366,17 @@ find_confirmed_client(clientid_t *clid) | |||
| 1355 | } | 1366 | } |
| 1356 | 1367 | ||
| 1357 | static struct nfs4_client * | 1368 | static struct nfs4_client * |
| 1358 | find_unconfirmed_client(clientid_t *clid) | 1369 | find_unconfirmed_client(clientid_t *clid, bool sessions) |
| 1359 | { | 1370 | { |
| 1360 | struct nfs4_client *clp; | 1371 | struct nfs4_client *clp; |
| 1361 | unsigned int idhashval = clientid_hashval(clid->cl_id); | 1372 | unsigned int idhashval = clientid_hashval(clid->cl_id); |
| 1362 | 1373 | ||
| 1363 | list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) { | 1374 | list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) { |
| 1364 | if (same_clid(&clp->cl_clientid, clid)) | 1375 | if (same_clid(&clp->cl_clientid, clid)) { |
| 1376 | if ((bool)clp->cl_minorversion != sessions) | ||
| 1377 | return NULL; | ||
| 1365 | return clp; | 1378 | return clp; |
| 1379 | } | ||
| 1366 | } | 1380 | } |
| 1367 | return NULL; | 1381 | return NULL; |
| 1368 | } | 1382 | } |
| @@ -1651,6 +1665,7 @@ out_new: | |||
| 1651 | status = nfserr_jukebox; | 1665 | status = nfserr_jukebox; |
| 1652 | goto out; | 1666 | goto out; |
| 1653 | } | 1667 | } |
| 1668 | new->cl_minorversion = 1; | ||
| 1654 | 1669 | ||
| 1655 | gen_clid(new); | 1670 | gen_clid(new); |
| 1656 | add_to_unconfirmed(new, strhashval); | 1671 | add_to_unconfirmed(new, strhashval); |
| @@ -1743,67 +1758,71 @@ nfsd4_create_session(struct svc_rqst *rqstp, | |||
| 1743 | struct sockaddr *sa = svc_addr(rqstp); | 1758 | struct sockaddr *sa = svc_addr(rqstp); |
| 1744 | struct nfs4_client *conf, *unconf; | 1759 | struct nfs4_client *conf, *unconf; |
| 1745 | struct nfsd4_session *new; | 1760 | struct nfsd4_session *new; |
| 1761 | struct nfsd4_conn *conn; | ||
| 1746 | struct nfsd4_clid_slot *cs_slot = NULL; | 1762 | struct nfsd4_clid_slot *cs_slot = NULL; |
| 1747 | bool confirm_me = false; | ||
| 1748 | __be32 status = 0; | 1763 | __be32 status = 0; |
| 1749 | 1764 | ||
| 1750 | if (cr_ses->flags & ~SESSION4_FLAG_MASK_A) | 1765 | if (cr_ses->flags & ~SESSION4_FLAG_MASK_A) |
| 1751 | return nfserr_inval; | 1766 | return nfserr_inval; |
| 1767 | if (check_forechannel_attrs(cr_ses->fore_channel)) | ||
| 1768 | return nfserr_toosmall; | ||
| 1769 | new = alloc_session(&cr_ses->fore_channel); | ||
| 1770 | if (!new) | ||
| 1771 | return nfserr_jukebox; | ||
| 1772 | status = nfserr_jukebox; | ||
| 1773 | conn = alloc_conn_from_crses(rqstp, cr_ses); | ||
| 1774 | if (!conn) | ||
| 1775 | goto out_free_session; | ||
| 1752 | 1776 | ||
| 1753 | nfs4_lock_state(); | 1777 | nfs4_lock_state(); |
| 1754 | unconf = find_unconfirmed_client(&cr_ses->clientid); | 1778 | unconf = find_unconfirmed_client(&cr_ses->clientid, true); |
| 1755 | conf = find_confirmed_client(&cr_ses->clientid); | 1779 | conf = find_confirmed_client(&cr_ses->clientid, true); |
| 1756 | 1780 | ||
| 1757 | if (conf) { | 1781 | if (conf) { |
| 1758 | cs_slot = &conf->cl_cs_slot; | 1782 | cs_slot = &conf->cl_cs_slot; |
| 1759 | status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0); | 1783 | status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0); |
| 1760 | if (status == nfserr_replay_cache) { | 1784 | if (status == nfserr_replay_cache) { |
| 1761 | status = nfsd4_replay_create_session(cr_ses, cs_slot); | 1785 | status = nfsd4_replay_create_session(cr_ses, cs_slot); |
| 1762 | goto out; | 1786 | goto out_free_conn; |
| 1763 | } else if (cr_ses->seqid != cs_slot->sl_seqid + 1) { | 1787 | } else if (cr_ses->seqid != cs_slot->sl_seqid + 1) { |
| 1764 | status = nfserr_seq_misordered; | 1788 | status = nfserr_seq_misordered; |
| 1765 | goto out; | 1789 | goto out_free_conn; |
| 1766 | } | 1790 | } |
| 1767 | } else if (unconf) { | 1791 | } else if (unconf) { |
| 1792 | unsigned int hash; | ||
| 1793 | struct nfs4_client *old; | ||
| 1768 | if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) || | 1794 | if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) || |
| 1769 | !rpc_cmp_addr(sa, (struct sockaddr *) &unconf->cl_addr)) { | 1795 | !rpc_cmp_addr(sa, (struct sockaddr *) &unconf->cl_addr)) { |
| 1770 | status = nfserr_clid_inuse; | 1796 | status = nfserr_clid_inuse; |
| 1771 | goto out; | 1797 | goto out_free_conn; |
| 1772 | } | 1798 | } |
| 1773 | cs_slot = &unconf->cl_cs_slot; | 1799 | cs_slot = &unconf->cl_cs_slot; |
| 1774 | status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0); | 1800 | status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0); |
| 1775 | if (status) { | 1801 | if (status) { |
| 1776 | /* an unconfirmed replay returns misordered */ | 1802 | /* an unconfirmed replay returns misordered */ |
| 1777 | status = nfserr_seq_misordered; | 1803 | status = nfserr_seq_misordered; |
| 1778 | goto out; | 1804 | goto out_free_conn; |
| 1779 | } | 1805 | } |
| 1780 | confirm_me = true; | 1806 | hash = clientstr_hashval(unconf->cl_recdir); |
| 1807 | old = find_confirmed_client_by_str(unconf->cl_recdir, hash); | ||
| 1808 | if (old) | ||
| 1809 | expire_client(old); | ||
| 1810 | move_to_confirmed(unconf); | ||
| 1781 | conf = unconf; | 1811 | conf = unconf; |
| 1782 | } else { | 1812 | } else { |
| 1783 | status = nfserr_stale_clientid; | 1813 | status = nfserr_stale_clientid; |
| 1784 | goto out; | 1814 | goto out_free_conn; |
| 1785 | } | 1815 | } |
| 1786 | 1816 | status = nfs_ok; | |
| 1787 | /* | ||
| 1788 | * XXX: we should probably set this at creation time, and check | ||
| 1789 | * for consistent minorversion use throughout: | ||
| 1790 | */ | ||
| 1791 | conf->cl_minorversion = 1; | ||
| 1792 | /* | 1817 | /* |
| 1793 | * We do not support RDMA or persistent sessions | 1818 | * We do not support RDMA or persistent sessions |
| 1794 | */ | 1819 | */ |
| 1795 | cr_ses->flags &= ~SESSION4_PERSIST; | 1820 | cr_ses->flags &= ~SESSION4_PERSIST; |
| 1796 | cr_ses->flags &= ~SESSION4_RDMA; | 1821 | cr_ses->flags &= ~SESSION4_RDMA; |
| 1797 | 1822 | ||
| 1798 | status = nfserr_toosmall; | 1823 | init_session(rqstp, new, conf, cr_ses); |
| 1799 | if (check_forechannel_attrs(cr_ses->fore_channel)) | 1824 | nfsd4_init_conn(rqstp, conn, new); |
| 1800 | goto out; | ||
| 1801 | 1825 | ||
| 1802 | status = nfserr_jukebox; | ||
| 1803 | new = alloc_init_session(rqstp, conf, cr_ses); | ||
| 1804 | if (!new) | ||
| 1805 | goto out; | ||
| 1806 | status = nfs_ok; | ||
| 1807 | memcpy(cr_ses->sessionid.data, new->se_sessionid.data, | 1826 | memcpy(cr_ses->sessionid.data, new->se_sessionid.data, |
| 1808 | NFS4_MAX_SESSIONID_LEN); | 1827 | NFS4_MAX_SESSIONID_LEN); |
| 1809 | memcpy(&cr_ses->fore_channel, &new->se_fchannel, | 1828 | memcpy(&cr_ses->fore_channel, &new->se_fchannel, |
| @@ -1813,18 +1832,15 @@ nfsd4_create_session(struct svc_rqst *rqstp, | |||
| 1813 | 1832 | ||
| 1814 | /* cache solo and embedded create sessions under the state lock */ | 1833 | /* cache solo and embedded create sessions under the state lock */ |
| 1815 | nfsd4_cache_create_session(cr_ses, cs_slot, status); | 1834 | nfsd4_cache_create_session(cr_ses, cs_slot, status); |
| 1816 | if (confirm_me) { | ||
| 1817 | unsigned int hash = clientstr_hashval(unconf->cl_recdir); | ||
| 1818 | struct nfs4_client *old = | ||
| 1819 | find_confirmed_client_by_str(conf->cl_recdir, hash); | ||
| 1820 | if (old) | ||
| 1821 | expire_client(old); | ||
| 1822 | move_to_confirmed(conf); | ||
| 1823 | } | ||
| 1824 | out: | 1835 | out: |
| 1825 | nfs4_unlock_state(); | 1836 | nfs4_unlock_state(); |
| 1826 | dprintk("%s returns %d\n", __func__, ntohl(status)); | 1837 | dprintk("%s returns %d\n", __func__, ntohl(status)); |
| 1827 | return status; | 1838 | return status; |
| 1839 | out_free_conn: | ||
| 1840 | free_conn(conn); | ||
| 1841 | out_free_session: | ||
| 1842 | __free_session(new); | ||
| 1843 | goto out; | ||
| 1828 | } | 1844 | } |
| 1829 | 1845 | ||
| 1830 | static bool nfsd4_last_compound_op(struct svc_rqst *rqstp) | 1846 | static bool nfsd4_last_compound_op(struct svc_rqst *rqstp) |
| @@ -1854,6 +1870,7 @@ __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp, | |||
| 1854 | struct nfsd4_bind_conn_to_session *bcts) | 1870 | struct nfsd4_bind_conn_to_session *bcts) |
| 1855 | { | 1871 | { |
| 1856 | __be32 status; | 1872 | __be32 status; |
| 1873 | struct nfsd4_conn *conn; | ||
| 1857 | 1874 | ||
| 1858 | if (!nfsd4_last_compound_op(rqstp)) | 1875 | if (!nfsd4_last_compound_op(rqstp)) |
| 1859 | return nfserr_not_only_op; | 1876 | return nfserr_not_only_op; |
| @@ -1870,9 +1887,13 @@ __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp, | |||
| 1870 | return nfserr_badsession; | 1887 | return nfserr_badsession; |
| 1871 | 1888 | ||
| 1872 | status = nfsd4_map_bcts_dir(&bcts->dir); | 1889 | status = nfsd4_map_bcts_dir(&bcts->dir); |
| 1873 | if (!status) | 1890 | if (status) |
| 1874 | nfsd4_new_conn(rqstp, cstate->session, bcts->dir); | 1891 | return status; |
| 1875 | return status; | 1892 | conn = alloc_conn(rqstp, bcts->dir); |
| 1893 | if (!conn) | ||
| 1894 | return nfserr_jukebox; | ||
| 1895 | nfsd4_init_conn(rqstp, conn, cstate->session); | ||
| 1896 | return nfs_ok; | ||
| 1876 | } | 1897 | } |
| 1877 | 1898 | ||
| 1878 | static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid) | 1899 | static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid) |
| @@ -2085,8 +2106,8 @@ nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta | |||
| 2085 | __be32 status = 0; | 2106 | __be32 status = 0; |
| 2086 | 2107 | ||
| 2087 | nfs4_lock_state(); | 2108 | nfs4_lock_state(); |
| 2088 | unconf = find_unconfirmed_client(&dc->clientid); | 2109 | unconf = find_unconfirmed_client(&dc->clientid, true); |
| 2089 | conf = find_confirmed_client(&dc->clientid); | 2110 | conf = find_confirmed_client(&dc->clientid, true); |
| 2090 | 2111 | ||
| 2091 | if (conf) { | 2112 | if (conf) { |
| 2092 | clp = conf; | 2113 | clp = conf; |
| @@ -2200,10 +2221,6 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 2200 | copy_clid(new, conf); | 2221 | copy_clid(new, conf); |
| 2201 | else /* case 4 (new client) or cases 2, 3 (client reboot): */ | 2222 | else /* case 4 (new client) or cases 2, 3 (client reboot): */ |
| 2202 | gen_clid(new); | 2223 | gen_clid(new); |
| 2203 | /* | ||
| 2204 | * XXX: we should probably set this at creation time, and check | ||
| 2205 | * for consistent minorversion use throughout: | ||
| 2206 | */ | ||
| 2207 | new->cl_minorversion = 0; | 2224 | new->cl_minorversion = 0; |
| 2208 | gen_callback(new, setclid, rqstp); | 2225 | gen_callback(new, setclid, rqstp); |
| 2209 | add_to_unconfirmed(new, strhashval); | 2226 | add_to_unconfirmed(new, strhashval); |
| @@ -2232,8 +2249,8 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
| 2232 | return nfserr_stale_clientid; | 2249 | return nfserr_stale_clientid; |
| 2233 | nfs4_lock_state(); | 2250 | nfs4_lock_state(); |
| 2234 | 2251 | ||
| 2235 | conf = find_confirmed_client(clid); | 2252 | conf = find_confirmed_client(clid, false); |
| 2236 | unconf = find_unconfirmed_client(clid); | 2253 | unconf = find_unconfirmed_client(clid, false); |
| 2237 | /* | 2254 | /* |
| 2238 | * We try hard to give out unique clientid's, so if we get an | 2255 | * We try hard to give out unique clientid's, so if we get an |
| 2239 | * attempt to confirm the same clientid with a different cred, | 2256 | * attempt to confirm the same clientid with a different cred, |
| @@ -2262,10 +2279,8 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
| 2262 | unsigned int hash = clientstr_hashval(unconf->cl_recdir); | 2279 | unsigned int hash = clientstr_hashval(unconf->cl_recdir); |
| 2263 | 2280 | ||
| 2264 | conf = find_confirmed_client_by_str(unconf->cl_recdir, hash); | 2281 | conf = find_confirmed_client_by_str(unconf->cl_recdir, hash); |
| 2265 | if (conf) { | 2282 | if (conf) |
| 2266 | nfsd4_client_record_remove(conf); | ||
| 2267 | expire_client(conf); | 2283 | expire_client(conf); |
| 2268 | } | ||
| 2269 | move_to_confirmed(unconf); | 2284 | move_to_confirmed(unconf); |
| 2270 | nfsd4_probe_callback(unconf); | 2285 | nfsd4_probe_callback(unconf); |
| 2271 | } | 2286 | } |
| @@ -2447,16 +2462,20 @@ same_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, | |||
| 2447 | } | 2462 | } |
| 2448 | 2463 | ||
| 2449 | static struct nfs4_openowner * | 2464 | static struct nfs4_openowner * |
| 2450 | find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open) | 2465 | find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open, bool sessions) |
| 2451 | { | 2466 | { |
| 2452 | struct nfs4_stateowner *so; | 2467 | struct nfs4_stateowner *so; |
| 2453 | struct nfs4_openowner *oo; | 2468 | struct nfs4_openowner *oo; |
| 2469 | struct nfs4_client *clp; | ||
| 2454 | 2470 | ||
| 2455 | list_for_each_entry(so, &ownerstr_hashtbl[hashval], so_strhash) { | 2471 | list_for_each_entry(so, &ownerstr_hashtbl[hashval], so_strhash) { |
| 2456 | if (!so->so_is_open_owner) | 2472 | if (!so->so_is_open_owner) |
| 2457 | continue; | 2473 | continue; |
| 2458 | if (same_owner_str(so, &open->op_owner, &open->op_clientid)) { | 2474 | if (same_owner_str(so, &open->op_owner, &open->op_clientid)) { |
| 2459 | oo = openowner(so); | 2475 | oo = openowner(so); |
| 2476 | clp = oo->oo_owner.so_client; | ||
| 2477 | if ((bool)clp->cl_minorversion != sessions) | ||
| 2478 | return NULL; | ||
| 2460 | renew_client(oo->oo_owner.so_client); | 2479 | renew_client(oo->oo_owner.so_client); |
| 2461 | return oo; | 2480 | return oo; |
| 2462 | } | 2481 | } |
| @@ -2600,10 +2619,10 @@ nfsd4_process_open1(struct nfsd4_compound_state *cstate, | |||
| 2600 | return nfserr_jukebox; | 2619 | return nfserr_jukebox; |
| 2601 | 2620 | ||
| 2602 | strhashval = ownerstr_hashval(clientid->cl_id, &open->op_owner); | 2621 | strhashval = ownerstr_hashval(clientid->cl_id, &open->op_owner); |
| 2603 | oo = find_openstateowner_str(strhashval, open); | 2622 | oo = find_openstateowner_str(strhashval, open, cstate->minorversion); |
| 2604 | open->op_openowner = oo; | 2623 | open->op_openowner = oo; |
| 2605 | if (!oo) { | 2624 | if (!oo) { |
| 2606 | clp = find_confirmed_client(clientid); | 2625 | clp = find_confirmed_client(clientid, cstate->minorversion); |
| 2607 | if (clp == NULL) | 2626 | if (clp == NULL) |
| 2608 | return nfserr_expired; | 2627 | return nfserr_expired; |
| 2609 | goto new_owner; | 2628 | goto new_owner; |
| @@ -2705,11 +2724,6 @@ nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_ol_st | |||
| 2705 | return nfs_ok; | 2724 | return nfs_ok; |
| 2706 | } | 2725 | } |
| 2707 | 2726 | ||
| 2708 | static void nfs4_free_stateid(struct nfs4_ol_stateid *s) | ||
| 2709 | { | ||
| 2710 | kmem_cache_free(stateid_slab, s); | ||
| 2711 | } | ||
| 2712 | |||
| 2713 | static inline int nfs4_access_to_access(u32 nfs4_access) | 2727 | static inline int nfs4_access_to_access(u32 nfs4_access) |
| 2714 | { | 2728 | { |
| 2715 | int flags = 0; | 2729 | int flags = 0; |
| @@ -3087,7 +3101,7 @@ void nfsd4_cleanup_open_state(struct nfsd4_open *open, __be32 status) | |||
| 3087 | if (open->op_file) | 3101 | if (open->op_file) |
| 3088 | nfsd4_free_file(open->op_file); | 3102 | nfsd4_free_file(open->op_file); |
| 3089 | if (open->op_stp) | 3103 | if (open->op_stp) |
| 3090 | nfs4_free_stateid(open->op_stp); | 3104 | free_generic_stateid(open->op_stp); |
| 3091 | } | 3105 | } |
| 3092 | 3106 | ||
| 3093 | __be32 | 3107 | __be32 |
| @@ -3104,7 +3118,7 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 3104 | status = nfserr_stale_clientid; | 3118 | status = nfserr_stale_clientid; |
| 3105 | if (STALE_CLIENTID(clid, nn)) | 3119 | if (STALE_CLIENTID(clid, nn)) |
| 3106 | goto out; | 3120 | goto out; |
| 3107 | clp = find_confirmed_client(clid); | 3121 | clp = find_confirmed_client(clid, cstate->minorversion); |
| 3108 | status = nfserr_expired; | 3122 | status = nfserr_expired; |
| 3109 | if (clp == NULL) { | 3123 | if (clp == NULL) { |
| 3110 | /* We assume the client took too long to RENEW. */ | 3124 | /* We assume the client took too long to RENEW. */ |
| @@ -3180,7 +3194,6 @@ nfs4_laundromat(void) | |||
| 3180 | clp = list_entry(pos, struct nfs4_client, cl_lru); | 3194 | clp = list_entry(pos, struct nfs4_client, cl_lru); |
| 3181 | dprintk("NFSD: purging unused client (clientid %08x)\n", | 3195 | dprintk("NFSD: purging unused client (clientid %08x)\n", |
| 3182 | clp->cl_clientid.cl_id); | 3196 | clp->cl_clientid.cl_id); |
| 3183 | nfsd4_client_record_remove(clp); | ||
| 3184 | expire_client(clp); | 3197 | expire_client(clp); |
| 3185 | } | 3198 | } |
| 3186 | spin_lock(&recall_lock); | 3199 | spin_lock(&recall_lock); |
| @@ -3372,7 +3385,7 @@ static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid) | |||
| 3372 | return nfs_ok; | 3385 | return nfs_ok; |
| 3373 | } | 3386 | } |
| 3374 | 3387 | ||
| 3375 | static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s) | 3388 | static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s, bool sessions) |
| 3376 | { | 3389 | { |
| 3377 | struct nfs4_client *cl; | 3390 | struct nfs4_client *cl; |
| 3378 | struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); | 3391 | struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); |
| @@ -3381,7 +3394,7 @@ static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, s | |||
| 3381 | return nfserr_bad_stateid; | 3394 | return nfserr_bad_stateid; |
| 3382 | if (STALE_STATEID(stateid, nn)) | 3395 | if (STALE_STATEID(stateid, nn)) |
| 3383 | return nfserr_stale_stateid; | 3396 | return nfserr_stale_stateid; |
| 3384 | cl = find_confirmed_client(&stateid->si_opaque.so_clid); | 3397 | cl = find_confirmed_client(&stateid->si_opaque.so_clid, sessions); |
| 3385 | if (!cl) | 3398 | if (!cl) |
| 3386 | return nfserr_expired; | 3399 | return nfserr_expired; |
| 3387 | *s = find_stateid_by_type(cl, stateid, typemask); | 3400 | *s = find_stateid_by_type(cl, stateid, typemask); |
| @@ -3414,7 +3427,7 @@ nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate, | |||
| 3414 | if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) | 3427 | if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) |
| 3415 | return check_special_stateids(net, current_fh, stateid, flags); | 3428 | return check_special_stateids(net, current_fh, stateid, flags); |
| 3416 | 3429 | ||
| 3417 | status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, &s); | 3430 | status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, &s, cstate->minorversion); |
| 3418 | if (status) | 3431 | if (status) |
| 3419 | return status; | 3432 | return status; |
| 3420 | status = check_stateid_generation(stateid, &s->sc_stateid, nfsd4_has_session(cstate)); | 3433 | status = check_stateid_generation(stateid, &s->sc_stateid, nfsd4_has_session(cstate)); |
| @@ -3564,7 +3577,7 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid, | |||
| 3564 | seqid, STATEID_VAL(stateid)); | 3577 | seqid, STATEID_VAL(stateid)); |
| 3565 | 3578 | ||
| 3566 | *stpp = NULL; | 3579 | *stpp = NULL; |
| 3567 | status = nfsd4_lookup_stateid(stateid, typemask, &s); | 3580 | status = nfsd4_lookup_stateid(stateid, typemask, &s, cstate->minorversion); |
| 3568 | if (status) | 3581 | if (status) |
| 3569 | return status; | 3582 | return status; |
| 3570 | *stpp = openlockstateid(s); | 3583 | *stpp = openlockstateid(s); |
| @@ -3765,6 +3778,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 3765 | memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); | 3778 | memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); |
| 3766 | 3779 | ||
| 3767 | nfsd4_close_open_stateid(stp); | 3780 | nfsd4_close_open_stateid(stp); |
| 3781 | release_last_closed_stateid(oo); | ||
| 3768 | oo->oo_last_closed_stid = stp; | 3782 | oo->oo_last_closed_stid = stp; |
| 3769 | 3783 | ||
| 3770 | if (list_empty(&oo->oo_owner.so_stateids)) { | 3784 | if (list_empty(&oo->oo_owner.so_stateids)) { |
| @@ -3801,7 +3815,7 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 3801 | inode = cstate->current_fh.fh_dentry->d_inode; | 3815 | inode = cstate->current_fh.fh_dentry->d_inode; |
| 3802 | 3816 | ||
| 3803 | nfs4_lock_state(); | 3817 | nfs4_lock_state(); |
| 3804 | status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID, &s); | 3818 | status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID, &s, cstate->minorversion); |
| 3805 | if (status) | 3819 | if (status) |
| 3806 | goto out; | 3820 | goto out; |
| 3807 | dp = delegstateid(s); | 3821 | dp = delegstateid(s); |
| @@ -4045,8 +4059,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 4045 | struct nfs4_lockowner *lock_sop = NULL; | 4059 | struct nfs4_lockowner *lock_sop = NULL; |
| 4046 | struct nfs4_ol_stateid *lock_stp; | 4060 | struct nfs4_ol_stateid *lock_stp; |
| 4047 | struct file *filp = NULL; | 4061 | struct file *filp = NULL; |
| 4048 | struct file_lock file_lock; | 4062 | struct file_lock *file_lock = NULL; |
| 4049 | struct file_lock conflock; | 4063 | struct file_lock *conflock = NULL; |
| 4050 | __be32 status = 0; | 4064 | __be32 status = 0; |
| 4051 | bool new_state = false; | 4065 | bool new_state = false; |
| 4052 | int lkflg; | 4066 | int lkflg; |
| @@ -4116,21 +4130,28 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 4116 | if (!locks_in_grace(SVC_NET(rqstp)) && lock->lk_reclaim) | 4130 | if (!locks_in_grace(SVC_NET(rqstp)) && lock->lk_reclaim) |
| 4117 | goto out; | 4131 | goto out; |
| 4118 | 4132 | ||
| 4119 | locks_init_lock(&file_lock); | 4133 | file_lock = locks_alloc_lock(); |
| 4134 | if (!file_lock) { | ||
| 4135 | dprintk("NFSD: %s: unable to allocate lock!\n", __func__); | ||
| 4136 | status = nfserr_jukebox; | ||
| 4137 | goto out; | ||
| 4138 | } | ||
| 4139 | |||
| 4140 | locks_init_lock(file_lock); | ||
| 4120 | switch (lock->lk_type) { | 4141 | switch (lock->lk_type) { |
| 4121 | case NFS4_READ_LT: | 4142 | case NFS4_READ_LT: |
| 4122 | case NFS4_READW_LT: | 4143 | case NFS4_READW_LT: |
| 4123 | filp = find_readable_file(lock_stp->st_file); | 4144 | filp = find_readable_file(lock_stp->st_file); |
| 4124 | if (filp) | 4145 | if (filp) |
| 4125 | get_lock_access(lock_stp, NFS4_SHARE_ACCESS_READ); | 4146 | get_lock_access(lock_stp, NFS4_SHARE_ACCESS_READ); |
| 4126 | file_lock.fl_type = F_RDLCK; | 4147 | file_lock->fl_type = F_RDLCK; |
| 4127 | break; | 4148 | break; |
| 4128 | case NFS4_WRITE_LT: | 4149 | case NFS4_WRITE_LT: |
| 4129 | case NFS4_WRITEW_LT: | 4150 | case NFS4_WRITEW_LT: |
| 4130 | filp = find_writeable_file(lock_stp->st_file); | 4151 | filp = find_writeable_file(lock_stp->st_file); |
| 4131 | if (filp) | 4152 | if (filp) |
| 4132 | get_lock_access(lock_stp, NFS4_SHARE_ACCESS_WRITE); | 4153 | get_lock_access(lock_stp, NFS4_SHARE_ACCESS_WRITE); |
| 4133 | file_lock.fl_type = F_WRLCK; | 4154 | file_lock->fl_type = F_WRLCK; |
| 4134 | break; | 4155 | break; |
| 4135 | default: | 4156 | default: |
| 4136 | status = nfserr_inval; | 4157 | status = nfserr_inval; |
| @@ -4140,22 +4161,23 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 4140 | status = nfserr_openmode; | 4161 | status = nfserr_openmode; |
| 4141 | goto out; | 4162 | goto out; |
| 4142 | } | 4163 | } |
| 4143 | file_lock.fl_owner = (fl_owner_t)lock_sop; | 4164 | file_lock->fl_owner = (fl_owner_t)lock_sop; |
| 4144 | file_lock.fl_pid = current->tgid; | 4165 | file_lock->fl_pid = current->tgid; |
| 4145 | file_lock.fl_file = filp; | 4166 | file_lock->fl_file = filp; |
| 4146 | file_lock.fl_flags = FL_POSIX; | 4167 | file_lock->fl_flags = FL_POSIX; |
| 4147 | file_lock.fl_lmops = &nfsd_posix_mng_ops; | 4168 | file_lock->fl_lmops = &nfsd_posix_mng_ops; |
| 4148 | 4169 | file_lock->fl_start = lock->lk_offset; | |
| 4149 | file_lock.fl_start = lock->lk_offset; | 4170 | file_lock->fl_end = last_byte_offset(lock->lk_offset, lock->lk_length); |
| 4150 | file_lock.fl_end = last_byte_offset(lock->lk_offset, lock->lk_length); | 4171 | nfs4_transform_lock_offset(file_lock); |
| 4151 | nfs4_transform_lock_offset(&file_lock); | 4172 | |
| 4152 | 4173 | conflock = locks_alloc_lock(); | |
| 4153 | /* | 4174 | if (!conflock) { |
| 4154 | * Try to lock the file in the VFS. | 4175 | dprintk("NFSD: %s: unable to allocate lock!\n", __func__); |
| 4155 | * Note: locks.c uses the BKL to protect the inode's lock list. | 4176 | status = nfserr_jukebox; |
| 4156 | */ | 4177 | goto out; |
| 4178 | } | ||
| 4157 | 4179 | ||
| 4158 | err = vfs_lock_file(filp, F_SETLK, &file_lock, &conflock); | 4180 | err = vfs_lock_file(filp, F_SETLK, file_lock, conflock); |
| 4159 | switch (-err) { | 4181 | switch (-err) { |
| 4160 | case 0: /* success! */ | 4182 | case 0: /* success! */ |
| 4161 | update_stateid(&lock_stp->st_stid.sc_stateid); | 4183 | update_stateid(&lock_stp->st_stid.sc_stateid); |
| @@ -4166,7 +4188,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 4166 | case (EAGAIN): /* conflock holds conflicting lock */ | 4188 | case (EAGAIN): /* conflock holds conflicting lock */ |
| 4167 | status = nfserr_denied; | 4189 | status = nfserr_denied; |
| 4168 | dprintk("NFSD: nfsd4_lock: conflicting lock found!\n"); | 4190 | dprintk("NFSD: nfsd4_lock: conflicting lock found!\n"); |
| 4169 | nfs4_set_lock_denied(&conflock, &lock->lk_denied); | 4191 | nfs4_set_lock_denied(conflock, &lock->lk_denied); |
| 4170 | break; | 4192 | break; |
| 4171 | case (EDEADLK): | 4193 | case (EDEADLK): |
| 4172 | status = nfserr_deadlock; | 4194 | status = nfserr_deadlock; |
| @@ -4181,6 +4203,10 @@ out: | |||
| 4181 | release_lockowner(lock_sop); | 4203 | release_lockowner(lock_sop); |
| 4182 | if (!cstate->replay_owner) | 4204 | if (!cstate->replay_owner) |
| 4183 | nfs4_unlock_state(); | 4205 | nfs4_unlock_state(); |
| 4206 | if (file_lock) | ||
| 4207 | locks_free_lock(file_lock); | ||
| 4208 | if (conflock) | ||
| 4209 | locks_free_lock(conflock); | ||
| 4184 | return status; | 4210 | return status; |
| 4185 | } | 4211 | } |
| 4186 | 4212 | ||
| @@ -4209,7 +4235,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 4209 | struct nfsd4_lockt *lockt) | 4235 | struct nfsd4_lockt *lockt) |
| 4210 | { | 4236 | { |
| 4211 | struct inode *inode; | 4237 | struct inode *inode; |
| 4212 | struct file_lock file_lock; | 4238 | struct file_lock *file_lock = NULL; |
| 4213 | struct nfs4_lockowner *lo; | 4239 | struct nfs4_lockowner *lo; |
| 4214 | __be32 status; | 4240 | __be32 status; |
| 4215 | struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); | 4241 | struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); |
| @@ -4230,15 +4256,21 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 4230 | goto out; | 4256 | goto out; |
| 4231 | 4257 | ||
| 4232 | inode = cstate->current_fh.fh_dentry->d_inode; | 4258 | inode = cstate->current_fh.fh_dentry->d_inode; |
| 4233 | locks_init_lock(&file_lock); | 4259 | file_lock = locks_alloc_lock(); |
| 4260 | if (!file_lock) { | ||
| 4261 | dprintk("NFSD: %s: unable to allocate lock!\n", __func__); | ||
| 4262 | status = nfserr_jukebox; | ||
| 4263 | goto out; | ||
| 4264 | } | ||
| 4265 | locks_init_lock(file_lock); | ||
| 4234 | switch (lockt->lt_type) { | 4266 | switch (lockt->lt_type) { |
| 4235 | case NFS4_READ_LT: | 4267 | case NFS4_READ_LT: |
| 4236 | case NFS4_READW_LT: | 4268 | case NFS4_READW_LT: |
| 4237 | file_lock.fl_type = F_RDLCK; | 4269 | file_lock->fl_type = F_RDLCK; |
| 4238 | break; | 4270 | break; |
| 4239 | case NFS4_WRITE_LT: | 4271 | case NFS4_WRITE_LT: |
| 4240 | case NFS4_WRITEW_LT: | 4272 | case NFS4_WRITEW_LT: |
| 4241 | file_lock.fl_type = F_WRLCK; | 4273 | file_lock->fl_type = F_WRLCK; |
| 4242 | break; | 4274 | break; |
| 4243 | default: | 4275 | default: |
| 4244 | dprintk("NFSD: nfs4_lockt: bad lock type!\n"); | 4276 | dprintk("NFSD: nfs4_lockt: bad lock type!\n"); |
| @@ -4248,25 +4280,27 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 4248 | 4280 | ||
| 4249 | lo = find_lockowner_str(inode, &lockt->lt_clientid, &lockt->lt_owner); | 4281 | lo = find_lockowner_str(inode, &lockt->lt_clientid, &lockt->lt_owner); |
| 4250 | if (lo) | 4282 | if (lo) |
| 4251 | file_lock.fl_owner = (fl_owner_t)lo; | 4283 | file_lock->fl_owner = (fl_owner_t)lo; |
| 4252 | file_lock.fl_pid = current->tgid; | 4284 | file_lock->fl_pid = current->tgid; |
| 4253 | file_lock.fl_flags = FL_POSIX; | 4285 | file_lock->fl_flags = FL_POSIX; |
| 4254 | 4286 | ||
| 4255 | file_lock.fl_start = lockt->lt_offset; | 4287 | file_lock->fl_start = lockt->lt_offset; |
| 4256 | file_lock.fl_end = last_byte_offset(lockt->lt_offset, lockt->lt_length); | 4288 | file_lock->fl_end = last_byte_offset(lockt->lt_offset, lockt->lt_length); |
| 4257 | 4289 | ||
| 4258 | nfs4_transform_lock_offset(&file_lock); | 4290 | nfs4_transform_lock_offset(file_lock); |
| 4259 | 4291 | ||
| 4260 | status = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock); | 4292 | status = nfsd_test_lock(rqstp, &cstate->current_fh, file_lock); |
| 4261 | if (status) | 4293 | if (status) |
| 4262 | goto out; | 4294 | goto out; |
| 4263 | 4295 | ||
| 4264 | if (file_lock.fl_type != F_UNLCK) { | 4296 | if (file_lock->fl_type != F_UNLCK) { |
| 4265 | status = nfserr_denied; | 4297 | status = nfserr_denied; |
| 4266 | nfs4_set_lock_denied(&file_lock, &lockt->lt_denied); | 4298 | nfs4_set_lock_denied(file_lock, &lockt->lt_denied); |
| 4267 | } | 4299 | } |
| 4268 | out: | 4300 | out: |
| 4269 | nfs4_unlock_state(); | 4301 | nfs4_unlock_state(); |
| 4302 | if (file_lock) | ||
| 4303 | locks_free_lock(file_lock); | ||
| 4270 | return status; | 4304 | return status; |
| 4271 | } | 4305 | } |
| 4272 | 4306 | ||
| @@ -4276,7 +4310,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 4276 | { | 4310 | { |
| 4277 | struct nfs4_ol_stateid *stp; | 4311 | struct nfs4_ol_stateid *stp; |
| 4278 | struct file *filp = NULL; | 4312 | struct file *filp = NULL; |
| 4279 | struct file_lock file_lock; | 4313 | struct file_lock *file_lock = NULL; |
| 4280 | __be32 status; | 4314 | __be32 status; |
| 4281 | int err; | 4315 | int err; |
| 4282 | 4316 | ||
| @@ -4298,23 +4332,29 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 4298 | status = nfserr_lock_range; | 4332 | status = nfserr_lock_range; |
| 4299 | goto out; | 4333 | goto out; |
| 4300 | } | 4334 | } |
| 4301 | BUG_ON(!filp); | 4335 | file_lock = locks_alloc_lock(); |
| 4302 | locks_init_lock(&file_lock); | 4336 | if (!file_lock) { |
| 4303 | file_lock.fl_type = F_UNLCK; | 4337 | dprintk("NFSD: %s: unable to allocate lock!\n", __func__); |
| 4304 | file_lock.fl_owner = (fl_owner_t)lockowner(stp->st_stateowner); | 4338 | status = nfserr_jukebox; |
| 4305 | file_lock.fl_pid = current->tgid; | 4339 | goto out; |
| 4306 | file_lock.fl_file = filp; | 4340 | } |
| 4307 | file_lock.fl_flags = FL_POSIX; | 4341 | locks_init_lock(file_lock); |
| 4308 | file_lock.fl_lmops = &nfsd_posix_mng_ops; | 4342 | file_lock->fl_type = F_UNLCK; |
| 4309 | file_lock.fl_start = locku->lu_offset; | 4343 | file_lock->fl_owner = (fl_owner_t)lockowner(stp->st_stateowner); |
| 4310 | 4344 | file_lock->fl_pid = current->tgid; | |
| 4311 | file_lock.fl_end = last_byte_offset(locku->lu_offset, locku->lu_length); | 4345 | file_lock->fl_file = filp; |
| 4312 | nfs4_transform_lock_offset(&file_lock); | 4346 | file_lock->fl_flags = FL_POSIX; |
| 4347 | file_lock->fl_lmops = &nfsd_posix_mng_ops; | ||
| 4348 | file_lock->fl_start = locku->lu_offset; | ||
| 4349 | |||
| 4350 | file_lock->fl_end = last_byte_offset(locku->lu_offset, | ||
| 4351 | locku->lu_length); | ||
| 4352 | nfs4_transform_lock_offset(file_lock); | ||
| 4313 | 4353 | ||
| 4314 | /* | 4354 | /* |
| 4315 | * Try to unlock the file in the VFS. | 4355 | * Try to unlock the file in the VFS. |
| 4316 | */ | 4356 | */ |
| 4317 | err = vfs_lock_file(filp, F_SETLK, &file_lock, NULL); | 4357 | err = vfs_lock_file(filp, F_SETLK, file_lock, NULL); |
| 4318 | if (err) { | 4358 | if (err) { |
| 4319 | dprintk("NFSD: nfs4_locku: vfs_lock_file failed!\n"); | 4359 | dprintk("NFSD: nfs4_locku: vfs_lock_file failed!\n"); |
| 4320 | goto out_nfserr; | 4360 | goto out_nfserr; |
| @@ -4328,6 +4368,8 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 4328 | out: | 4368 | out: |
| 4329 | if (!cstate->replay_owner) | 4369 | if (!cstate->replay_owner) |
| 4330 | nfs4_unlock_state(); | 4370 | nfs4_unlock_state(); |
| 4371 | if (file_lock) | ||
| 4372 | locks_free_lock(file_lock); | ||
| 4331 | return status; | 4373 | return status; |
| 4332 | 4374 | ||
| 4333 | out_nfserr: | 4375 | out_nfserr: |
| @@ -4501,12 +4543,12 @@ nfsd4_find_reclaim_client(struct nfs4_client *clp) | |||
| 4501 | * Called from OPEN. Look for clientid in reclaim list. | 4543 | * Called from OPEN. Look for clientid in reclaim list. |
| 4502 | */ | 4544 | */ |
| 4503 | __be32 | 4545 | __be32 |
| 4504 | nfs4_check_open_reclaim(clientid_t *clid) | 4546 | nfs4_check_open_reclaim(clientid_t *clid, bool sessions) |
| 4505 | { | 4547 | { |
| 4506 | struct nfs4_client *clp; | 4548 | struct nfs4_client *clp; |
| 4507 | 4549 | ||
| 4508 | /* find clientid in conf_id_hashtbl */ | 4550 | /* find clientid in conf_id_hashtbl */ |
| 4509 | clp = find_confirmed_client(clid); | 4551 | clp = find_confirmed_client(clid, sessions); |
| 4510 | if (clp == NULL) | 4552 | if (clp == NULL) |
| 4511 | return nfserr_reclaim_bad; | 4553 | return nfserr_reclaim_bad; |
| 4512 | 4554 | ||
| @@ -4522,7 +4564,6 @@ void nfsd_forget_clients(u64 num) | |||
| 4522 | 4564 | ||
| 4523 | nfs4_lock_state(); | 4565 | nfs4_lock_state(); |
| 4524 | list_for_each_entry_safe(clp, next, &client_lru, cl_lru) { | 4566 | list_for_each_entry_safe(clp, next, &client_lru, cl_lru) { |
| 4525 | nfsd4_client_record_remove(clp); | ||
| 4526 | expire_client(clp); | 4567 | expire_client(clp); |
| 4527 | if (++count == num) | 4568 | if (++count == num) |
| 4528 | break; | 4569 | break; |
| @@ -4582,7 +4623,7 @@ void nfsd_forget_openowners(u64 num) | |||
| 4582 | printk(KERN_INFO "NFSD: Forgot %d open owners", count); | 4623 | printk(KERN_INFO "NFSD: Forgot %d open owners", count); |
| 4583 | } | 4624 | } |
| 4584 | 4625 | ||
| 4585 | int nfsd_process_n_delegations(u64 num, struct list_head *list) | 4626 | static int nfsd_process_n_delegations(u64 num, struct list_head *list) |
| 4586 | { | 4627 | { |
| 4587 | int i, count = 0; | 4628 | int i, count = 0; |
| 4588 | struct nfs4_file *fp, *fnext; | 4629 | struct nfs4_file *fp, *fnext; |
| @@ -4747,11 +4788,11 @@ __nfs4_state_shutdown(void) | |||
| 4747 | for (i = 0; i < CLIENT_HASH_SIZE; i++) { | 4788 | for (i = 0; i < CLIENT_HASH_SIZE; i++) { |
| 4748 | while (!list_empty(&conf_id_hashtbl[i])) { | 4789 | while (!list_empty(&conf_id_hashtbl[i])) { |
| 4749 | clp = list_entry(conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash); | 4790 | clp = list_entry(conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash); |
| 4750 | expire_client(clp); | 4791 | destroy_client(clp); |
| 4751 | } | 4792 | } |
| 4752 | while (!list_empty(&unconf_str_hashtbl[i])) { | 4793 | while (!list_empty(&unconf_str_hashtbl[i])) { |
| 4753 | clp = list_entry(unconf_str_hashtbl[i].next, struct nfs4_client, cl_strhash); | 4794 | clp = list_entry(unconf_str_hashtbl[i].next, struct nfs4_client, cl_strhash); |
| 4754 | expire_client(clp); | 4795 | destroy_client(clp); |
| 4755 | } | 4796 | } |
| 4756 | } | 4797 | } |
| 4757 | INIT_LIST_HEAD(&reaplist); | 4798 | INIT_LIST_HEAD(&reaplist); |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 6322df36031f..fd548d155088 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
| @@ -2659,7 +2659,7 @@ static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp, | |||
| 2659 | RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 8); | 2659 | RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 8); |
| 2660 | WRITEMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN); | 2660 | WRITEMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN); |
| 2661 | WRITE32(bcts->dir); | 2661 | WRITE32(bcts->dir); |
| 2662 | /* XXX: ? */ | 2662 | /* Sorry, we do not yet support RDMA over 4.1: */ |
| 2663 | WRITE32(0); | 2663 | WRITE32(0); |
| 2664 | ADJUST_ARGS(); | 2664 | ADJUST_ARGS(); |
| 2665 | } | 2665 | } |
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index fa49cff5ee65..dab350dfc376 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
| @@ -406,7 +406,7 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size) | |||
| 406 | return rv; | 406 | return rv; |
| 407 | if (newthreads < 0) | 407 | if (newthreads < 0) |
| 408 | return -EINVAL; | 408 | return -EINVAL; |
| 409 | rv = nfsd_svc(NFS_PORT, newthreads); | 409 | rv = nfsd_svc(newthreads); |
| 410 | if (rv < 0) | 410 | if (rv < 0) |
| 411 | return rv; | 411 | return rv; |
| 412 | } else | 412 | } else |
| @@ -683,25 +683,6 @@ static ssize_t __write_ports_addfd(char *buf) | |||
| 683 | } | 683 | } |
| 684 | 684 | ||
| 685 | /* | 685 | /* |
| 686 | * A '-' followed by the 'name' of a socket means we close the socket. | ||
| 687 | */ | ||
| 688 | static ssize_t __write_ports_delfd(char *buf) | ||
| 689 | { | ||
| 690 | char *toclose; | ||
| 691 | int len = 0; | ||
| 692 | |||
| 693 | toclose = kstrdup(buf + 1, GFP_KERNEL); | ||
| 694 | if (toclose == NULL) | ||
| 695 | return -ENOMEM; | ||
| 696 | |||
| 697 | if (nfsd_serv != NULL) | ||
| 698 | len = svc_sock_names(nfsd_serv, buf, | ||
| 699 | SIMPLE_TRANSACTION_LIMIT, toclose); | ||
| 700 | kfree(toclose); | ||
| 701 | return len; | ||
| 702 | } | ||
| 703 | |||
| 704 | /* | ||
| 705 | * A transport listener is added by writing it's transport name and | 686 | * A transport listener is added by writing it's transport name and |
| 706 | * a port number. | 687 | * a port number. |
| 707 | */ | 688 | */ |
| @@ -712,7 +693,7 @@ static ssize_t __write_ports_addxprt(char *buf) | |||
| 712 | int port, err; | 693 | int port, err; |
| 713 | struct net *net = &init_net; | 694 | struct net *net = &init_net; |
| 714 | 695 | ||
| 715 | if (sscanf(buf, "%15s %4u", transport, &port) != 2) | 696 | if (sscanf(buf, "%15s %5u", transport, &port) != 2) |
| 716 | return -EINVAL; | 697 | return -EINVAL; |
| 717 | 698 | ||
| 718 | if (port < 1 || port > USHRT_MAX) | 699 | if (port < 1 || port > USHRT_MAX) |
| @@ -746,31 +727,6 @@ out_err: | |||
| 746 | return err; | 727 | return err; |
| 747 | } | 728 | } |
| 748 | 729 | ||
| 749 | /* | ||
| 750 | * A transport listener is removed by writing a "-", it's transport | ||
| 751 | * name, and it's port number. | ||
| 752 | */ | ||
| 753 | static ssize_t __write_ports_delxprt(char *buf) | ||
| 754 | { | ||
| 755 | struct svc_xprt *xprt; | ||
| 756 | char transport[16]; | ||
| 757 | int port; | ||
| 758 | |||
| 759 | if (sscanf(&buf[1], "%15s %4u", transport, &port) != 2) | ||
| 760 | return -EINVAL; | ||
| 761 | |||
| 762 | if (port < 1 || port > USHRT_MAX || nfsd_serv == NULL) | ||
| 763 | return -EINVAL; | ||
| 764 | |||
| 765 | xprt = svc_find_xprt(nfsd_serv, transport, &init_net, AF_UNSPEC, port); | ||
| 766 | if (xprt == NULL) | ||
| 767 | return -ENOTCONN; | ||
| 768 | |||
| 769 | svc_close_xprt(xprt); | ||
| 770 | svc_xprt_put(xprt); | ||
| 771 | return 0; | ||
| 772 | } | ||
| 773 | |||
| 774 | static ssize_t __write_ports(struct file *file, char *buf, size_t size) | 730 | static ssize_t __write_ports(struct file *file, char *buf, size_t size) |
| 775 | { | 731 | { |
| 776 | if (size == 0) | 732 | if (size == 0) |
| @@ -779,15 +735,9 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size) | |||
| 779 | if (isdigit(buf[0])) | 735 | if (isdigit(buf[0])) |
| 780 | return __write_ports_addfd(buf); | 736 | return __write_ports_addfd(buf); |
| 781 | 737 | ||
| 782 | if (buf[0] == '-' && isdigit(buf[1])) | ||
| 783 | return __write_ports_delfd(buf); | ||
| 784 | |||
| 785 | if (isalpha(buf[0])) | 738 | if (isalpha(buf[0])) |
| 786 | return __write_ports_addxprt(buf); | 739 | return __write_ports_addxprt(buf); |
| 787 | 740 | ||
| 788 | if (buf[0] == '-' && isalpha(buf[1])) | ||
| 789 | return __write_ports_delxprt(buf); | ||
| 790 | |||
| 791 | return -EINVAL; | 741 | return -EINVAL; |
| 792 | } | 742 | } |
| 793 | 743 | ||
| @@ -825,21 +775,6 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size) | |||
| 825 | * OR | 775 | * OR |
| 826 | * | 776 | * |
| 827 | * Input: | 777 | * Input: |
| 828 | * buf: C string containing a "-" followed | ||
| 829 | * by an integer value representing a | ||
| 830 | * previously passed in socket file | ||
| 831 | * descriptor | ||
| 832 | * size: non-zero length of C string in @buf | ||
| 833 | * Output: | ||
| 834 | * On success: NFS service no longer listens on that socket; | ||
| 835 | * passed-in buffer filled with a '\n'-terminated C | ||
| 836 | * string containing a unique name of the listener; | ||
| 837 | * return code is the size in bytes of the string | ||
| 838 | * On error: return code is a negative errno value | ||
| 839 | * | ||
| 840 | * OR | ||
| 841 | * | ||
| 842 | * Input: | ||
| 843 | * buf: C string containing a transport | 778 | * buf: C string containing a transport |
| 844 | * name and an unsigned integer value | 779 | * name and an unsigned integer value |
| 845 | * representing the port to listen on, | 780 | * representing the port to listen on, |
| @@ -848,19 +783,6 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size) | |||
| 848 | * Output: | 783 | * Output: |
| 849 | * On success: returns zero; NFS service is started | 784 | * On success: returns zero; NFS service is started |
| 850 | * On error: return code is a negative errno value | 785 | * On error: return code is a negative errno value |
| 851 | * | ||
| 852 | * OR | ||
| 853 | * | ||
| 854 | * Input: | ||
| 855 | * buf: C string containing a "-" followed | ||
| 856 | * by a transport name and an unsigned | ||
| 857 | * integer value representing the port | ||
| 858 | * to listen on, separated by whitespace | ||
| 859 | * size: non-zero length of C string in @buf | ||
| 860 | * Output: | ||
| 861 | * On success: returns zero; NFS service no longer listens | ||
| 862 | * on that transport | ||
| 863 | * On error: return code is a negative errno value | ||
| 864 | */ | 786 | */ |
| 865 | static ssize_t write_ports(struct file *file, char *buf, size_t size) | 787 | static ssize_t write_ports(struct file *file, char *buf, size_t size) |
| 866 | { | 788 | { |
| @@ -1008,8 +930,6 @@ static ssize_t write_gracetime(struct file *file, char *buf, size_t size) | |||
| 1008 | return nfsd4_write_time(file, buf, size, &nfsd4_grace); | 930 | return nfsd4_write_time(file, buf, size, &nfsd4_grace); |
| 1009 | } | 931 | } |
| 1010 | 932 | ||
| 1011 | extern char *nfs4_recoverydir(void); | ||
| 1012 | |||
| 1013 | static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size) | 933 | static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size) |
| 1014 | { | 934 | { |
| 1015 | char *mesg = buf; | 935 | char *mesg = buf; |
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 2244222368ab..80d5ce40aadb 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h | |||
| @@ -65,7 +65,7 @@ extern const struct seq_operations nfs_exports_op; | |||
| 65 | /* | 65 | /* |
| 66 | * Function prototypes. | 66 | * Function prototypes. |
| 67 | */ | 67 | */ |
| 68 | int nfsd_svc(unsigned short port, int nrservs); | 68 | int nfsd_svc(int nrservs); |
| 69 | int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp); | 69 | int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp); |
| 70 | 70 | ||
| 71 | int nfsd_nrthreads(void); | 71 | int nfsd_nrthreads(void); |
| @@ -124,6 +124,7 @@ int nfs4_state_start(void); | |||
| 124 | void nfs4_state_shutdown(void); | 124 | void nfs4_state_shutdown(void); |
| 125 | void nfs4_reset_lease(time_t leasetime); | 125 | void nfs4_reset_lease(time_t leasetime); |
| 126 | int nfs4_reset_recoverydir(char *recdir); | 126 | int nfs4_reset_recoverydir(char *recdir); |
| 127 | char * nfs4_recoverydir(void); | ||
| 127 | #else | 128 | #else |
| 128 | static inline void nfs4_state_init(void) { } | 129 | static inline void nfs4_state_init(void) { } |
| 129 | static inline int nfsd4_init_slabs(void) { return 0; } | 130 | static inline int nfsd4_init_slabs(void) { return 0; } |
| @@ -132,6 +133,7 @@ static inline int nfs4_state_start(void) { return 0; } | |||
| 132 | static inline void nfs4_state_shutdown(void) { } | 133 | static inline void nfs4_state_shutdown(void) { } |
| 133 | static inline void nfs4_reset_lease(time_t leasetime) { } | 134 | static inline void nfs4_reset_lease(time_t leasetime) { } |
| 134 | static inline int nfs4_reset_recoverydir(char *recdir) { return 0; } | 135 | static inline int nfs4_reset_recoverydir(char *recdir) { return 0; } |
| 136 | static inline char * nfs4_recoverydir(void) {return NULL; } | ||
| 135 | #endif | 137 | #endif |
| 136 | 138 | ||
| 137 | /* | 139 | /* |
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 240473cb708f..2013aa001dab 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c | |||
| @@ -183,18 +183,18 @@ int nfsd_nrthreads(void) | |||
| 183 | return rv; | 183 | return rv; |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | static int nfsd_init_socks(int port) | 186 | static int nfsd_init_socks(void) |
| 187 | { | 187 | { |
| 188 | int error; | 188 | int error; |
| 189 | if (!list_empty(&nfsd_serv->sv_permsocks)) | 189 | if (!list_empty(&nfsd_serv->sv_permsocks)) |
| 190 | return 0; | 190 | return 0; |
| 191 | 191 | ||
| 192 | error = svc_create_xprt(nfsd_serv, "udp", &init_net, PF_INET, port, | 192 | error = svc_create_xprt(nfsd_serv, "udp", &init_net, PF_INET, NFS_PORT, |
| 193 | SVC_SOCK_DEFAULTS); | 193 | SVC_SOCK_DEFAULTS); |
| 194 | if (error < 0) | 194 | if (error < 0) |
| 195 | return error; | 195 | return error; |
| 196 | 196 | ||
| 197 | error = svc_create_xprt(nfsd_serv, "tcp", &init_net, PF_INET, port, | 197 | error = svc_create_xprt(nfsd_serv, "tcp", &init_net, PF_INET, NFS_PORT, |
| 198 | SVC_SOCK_DEFAULTS); | 198 | SVC_SOCK_DEFAULTS); |
| 199 | if (error < 0) | 199 | if (error < 0) |
| 200 | return error; | 200 | return error; |
| @@ -204,7 +204,7 @@ static int nfsd_init_socks(int port) | |||
| 204 | 204 | ||
| 205 | static bool nfsd_up = false; | 205 | static bool nfsd_up = false; |
| 206 | 206 | ||
| 207 | static int nfsd_startup(unsigned short port, int nrservs) | 207 | static int nfsd_startup(int nrservs) |
| 208 | { | 208 | { |
| 209 | int ret; | 209 | int ret; |
| 210 | 210 | ||
| @@ -218,7 +218,7 @@ static int nfsd_startup(unsigned short port, int nrservs) | |||
| 218 | ret = nfsd_racache_init(2*nrservs); | 218 | ret = nfsd_racache_init(2*nrservs); |
| 219 | if (ret) | 219 | if (ret) |
| 220 | return ret; | 220 | return ret; |
| 221 | ret = nfsd_init_socks(port); | 221 | ret = nfsd_init_socks(); |
| 222 | if (ret) | 222 | if (ret) |
| 223 | goto out_racache; | 223 | goto out_racache; |
| 224 | ret = lockd_up(&init_net); | 224 | ret = lockd_up(&init_net); |
| @@ -436,7 +436,7 @@ int nfsd_set_nrthreads(int n, int *nthreads) | |||
| 436 | * this is the first time nrservs is nonzero. | 436 | * this is the first time nrservs is nonzero. |
| 437 | */ | 437 | */ |
| 438 | int | 438 | int |
| 439 | nfsd_svc(unsigned short port, int nrservs) | 439 | nfsd_svc(int nrservs) |
| 440 | { | 440 | { |
| 441 | int error; | 441 | int error; |
| 442 | bool nfsd_up_before; | 442 | bool nfsd_up_before; |
| @@ -458,7 +458,7 @@ nfsd_svc(unsigned short port, int nrservs) | |||
| 458 | 458 | ||
| 459 | nfsd_up_before = nfsd_up; | 459 | nfsd_up_before = nfsd_up; |
| 460 | 460 | ||
| 461 | error = nfsd_startup(port, nrservs); | 461 | error = nfsd_startup(nrservs); |
| 462 | if (error) | 462 | if (error) |
| 463 | goto out_destroy; | 463 | goto out_destroy; |
| 464 | error = svc_set_num_threads(nfsd_serv, NULL, nrservs); | 464 | error = svc_set_num_threads(nfsd_serv, NULL, nrservs); |
| @@ -487,7 +487,7 @@ static int | |||
| 487 | nfsd(void *vrqstp) | 487 | nfsd(void *vrqstp) |
| 488 | { | 488 | { |
| 489 | struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp; | 489 | struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp; |
| 490 | int err, preverr = 0; | 490 | int err; |
| 491 | 491 | ||
| 492 | /* Lock module and set up kernel thread */ | 492 | /* Lock module and set up kernel thread */ |
| 493 | mutex_lock(&nfsd_mutex); | 493 | mutex_lock(&nfsd_mutex); |
| @@ -534,16 +534,6 @@ nfsd(void *vrqstp) | |||
| 534 | ; | 534 | ; |
| 535 | if (err == -EINTR) | 535 | if (err == -EINTR) |
| 536 | break; | 536 | break; |
| 537 | else if (err < 0) { | ||
| 538 | if (err != preverr) { | ||
| 539 | printk(KERN_WARNING "%s: unexpected error " | ||
| 540 | "from svc_recv (%d)\n", __func__, -err); | ||
| 541 | preverr = err; | ||
| 542 | } | ||
| 543 | schedule_timeout_uninterruptible(HZ); | ||
| 544 | continue; | ||
| 545 | } | ||
| 546 | |||
| 547 | validate_process_creds(); | 537 | validate_process_creds(); |
| 548 | svc_process(rqstp); | 538 | svc_process(rqstp); |
| 549 | validate_process_creds(); | 539 | validate_process_creds(); |
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 22bd0a66c356..e036894bce57 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h | |||
| @@ -373,11 +373,7 @@ static inline struct nfs4_lockowner * lockowner(struct nfs4_stateowner *so) | |||
| 373 | return container_of(so, struct nfs4_lockowner, lo_owner); | 373 | return container_of(so, struct nfs4_lockowner, lo_owner); |
| 374 | } | 374 | } |
| 375 | 375 | ||
| 376 | /* | 376 | /* nfs4_file: a file opened by some number of (open) nfs4_stateowners. */ |
| 377 | * nfs4_file: a file opened by some number of (open) nfs4_stateowners. | ||
| 378 | * o fi_perfile list is used to search for conflicting | ||
| 379 | * share_acces, share_deny on the file. | ||
| 380 | */ | ||
| 381 | struct nfs4_file { | 377 | struct nfs4_file { |
| 382 | atomic_t fi_ref; | 378 | atomic_t fi_ref; |
| 383 | struct list_head fi_hash; /* hash by "struct inode *" */ | 379 | struct list_head fi_hash; /* hash by "struct inode *" */ |
| @@ -459,7 +455,7 @@ extern void nfs4_unlock_state(void); | |||
| 459 | extern int nfs4_in_grace(void); | 455 | extern int nfs4_in_grace(void); |
| 460 | extern void nfs4_release_reclaim(void); | 456 | extern void nfs4_release_reclaim(void); |
| 461 | extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct nfs4_client *crp); | 457 | extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct nfs4_client *crp); |
| 462 | extern __be32 nfs4_check_open_reclaim(clientid_t *clid); | 458 | extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions); |
| 463 | extern void nfs4_free_openowner(struct nfs4_openowner *); | 459 | extern void nfs4_free_openowner(struct nfs4_openowner *); |
| 464 | extern void nfs4_free_lockowner(struct nfs4_lockowner *); | 460 | extern void nfs4_free_lockowner(struct nfs4_lockowner *); |
| 465 | extern int set_callback_cred(void); | 461 | extern int set_callback_cred(void); |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 3f67b8e12251..c120b48ec305 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
| @@ -1581,7 +1581,7 @@ nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp) | |||
| 1581 | */ | 1581 | */ |
| 1582 | 1582 | ||
| 1583 | oldfs = get_fs(); set_fs(KERNEL_DS); | 1583 | oldfs = get_fs(); set_fs(KERNEL_DS); |
| 1584 | host_err = inode->i_op->readlink(path.dentry, buf, *lenp); | 1584 | host_err = inode->i_op->readlink(path.dentry, (char __user *)buf, *lenp); |
| 1585 | set_fs(oldfs); | 1585 | set_fs(oldfs); |
| 1586 | 1586 | ||
| 1587 | if (host_err < 0) | 1587 | if (host_err < 0) |
| @@ -478,7 +478,7 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd, umode_t, mode) | |||
| 478 | 478 | ||
| 479 | file = fget(fd); | 479 | file = fget(fd); |
| 480 | if (file) { | 480 | if (file) { |
| 481 | audit_inode(NULL, file->f_path.dentry); | 481 | audit_inode(NULL, file->f_path.dentry, 0); |
| 482 | err = chmod_common(&file->f_path, mode); | 482 | err = chmod_common(&file->f_path, mode); |
| 483 | fput(file); | 483 | fput(file); |
| 484 | } | 484 | } |
| @@ -588,7 +588,7 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group) | |||
| 588 | error = mnt_want_write_file(f.file); | 588 | error = mnt_want_write_file(f.file); |
| 589 | if (error) | 589 | if (error) |
| 590 | goto out_fput; | 590 | goto out_fput; |
| 591 | audit_inode(NULL, f.file->f_path.dentry); | 591 | audit_inode(NULL, f.file->f_path.dentry, 0); |
| 592 | error = chown_common(&f.file->f_path, user, group); | 592 | error = chown_common(&f.file->f_path, user, group); |
| 593 | mnt_drop_write_file(f.file); | 593 | mnt_drop_write_file(f.file); |
| 594 | out_fput: | 594 | out_fput: |
| @@ -859,6 +859,24 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o | |||
| 859 | } | 859 | } |
| 860 | 860 | ||
| 861 | /** | 861 | /** |
| 862 | * file_open_name - open file and return file pointer | ||
| 863 | * | ||
| 864 | * @name: struct filename containing path to open | ||
| 865 | * @flags: open flags as per the open(2) second argument | ||
| 866 | * @mode: mode for the new file if O_CREAT is set, else ignored | ||
| 867 | * | ||
| 868 | * This is the helper to open a file from kernelspace if you really | ||
| 869 | * have to. But in generally you should not do this, so please move | ||
| 870 | * along, nothing to see here.. | ||
| 871 | */ | ||
| 872 | struct file *file_open_name(struct filename *name, int flags, umode_t mode) | ||
| 873 | { | ||
| 874 | struct open_flags op; | ||
| 875 | int lookup = build_open_flags(flags, mode, &op); | ||
| 876 | return do_filp_open(AT_FDCWD, name, &op, lookup); | ||
| 877 | } | ||
| 878 | |||
| 879 | /** | ||
| 862 | * filp_open - open file and return file pointer | 880 | * filp_open - open file and return file pointer |
| 863 | * | 881 | * |
| 864 | * @filename: path to open | 882 | * @filename: path to open |
| @@ -871,9 +889,8 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o | |||
| 871 | */ | 889 | */ |
| 872 | struct file *filp_open(const char *filename, int flags, umode_t mode) | 890 | struct file *filp_open(const char *filename, int flags, umode_t mode) |
| 873 | { | 891 | { |
| 874 | struct open_flags op; | 892 | struct filename name = {.name = filename}; |
| 875 | int lookup = build_open_flags(flags, mode, &op); | 893 | return file_open_name(&name, flags, mode); |
| 876 | return do_filp_open(AT_FDCWD, filename, &op, lookup); | ||
| 877 | } | 894 | } |
| 878 | EXPORT_SYMBOL(filp_open); | 895 | EXPORT_SYMBOL(filp_open); |
| 879 | 896 | ||
| @@ -895,7 +912,7 @@ long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) | |||
| 895 | { | 912 | { |
| 896 | struct open_flags op; | 913 | struct open_flags op; |
| 897 | int lookup = build_open_flags(flags, mode, &op); | 914 | int lookup = build_open_flags(flags, mode, &op); |
| 898 | char *tmp = getname(filename); | 915 | struct filename *tmp = getname(filename); |
| 899 | int fd = PTR_ERR(tmp); | 916 | int fd = PTR_ERR(tmp); |
| 900 | 917 | ||
| 901 | if (!IS_ERR(tmp)) { | 918 | if (!IS_ERR(tmp)) { |
diff --git a/fs/proc/base.c b/fs/proc/base.c index ef5c84be66f9..144a96732dd7 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -2258,7 +2258,8 @@ static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
| 2258 | pid_t tgid = task_tgid_nr_ns(current, ns); | 2258 | pid_t tgid = task_tgid_nr_ns(current, ns); |
| 2259 | char *name = ERR_PTR(-ENOENT); | 2259 | char *name = ERR_PTR(-ENOENT); |
| 2260 | if (tgid) { | 2260 | if (tgid) { |
| 2261 | name = __getname(); | 2261 | /* 11 for max length of signed int in decimal + NULL term */ |
| 2262 | name = kmalloc(12, GFP_KERNEL); | ||
| 2262 | if (!name) | 2263 | if (!name) |
| 2263 | name = ERR_PTR(-ENOMEM); | 2264 | name = ERR_PTR(-ENOMEM); |
| 2264 | else | 2265 | else |
| @@ -2273,7 +2274,7 @@ static void proc_self_put_link(struct dentry *dentry, struct nameidata *nd, | |||
| 2273 | { | 2274 | { |
| 2274 | char *s = nd_get_link(nd); | 2275 | char *s = nd_get_link(nd); |
| 2275 | if (!IS_ERR(s)) | 2276 | if (!IS_ERR(s)) |
| 2276 | __putname(s); | 2277 | kfree(s); |
| 2277 | } | 2278 | } |
| 2278 | 2279 | ||
| 2279 | static const struct inode_operations proc_self_inode_operations = { | 2280 | static const struct inode_operations proc_self_inode_operations = { |
diff --git a/fs/quota/quota.c b/fs/quota/quota.c index ff0135d6bc51..af1661f7a54f 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c | |||
| @@ -331,11 +331,11 @@ static struct super_block *quotactl_block(const char __user *special, int cmd) | |||
| 331 | #ifdef CONFIG_BLOCK | 331 | #ifdef CONFIG_BLOCK |
| 332 | struct block_device *bdev; | 332 | struct block_device *bdev; |
| 333 | struct super_block *sb; | 333 | struct super_block *sb; |
| 334 | char *tmp = getname(special); | 334 | struct filename *tmp = getname(special); |
| 335 | 335 | ||
| 336 | if (IS_ERR(tmp)) | 336 | if (IS_ERR(tmp)) |
| 337 | return ERR_CAST(tmp); | 337 | return ERR_CAST(tmp); |
| 338 | bdev = lookup_bdev(tmp); | 338 | bdev = lookup_bdev(tmp->name); |
| 339 | putname(tmp); | 339 | putname(tmp); |
| 340 | if (IS_ERR(bdev)) | 340 | if (IS_ERR(bdev)) |
| 341 | return ERR_CAST(bdev); | 341 | return ERR_CAST(bdev); |
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 46485557cdc6..f27f01a98aa2 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
| @@ -1573,8 +1573,10 @@ struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid, | |||
| 1573 | reiserfs_warning(sb, "reiserfs-13077", | 1573 | reiserfs_warning(sb, "reiserfs-13077", |
| 1574 | "nfsd/reiserfs, fhtype=%d, len=%d - odd", | 1574 | "nfsd/reiserfs, fhtype=%d, len=%d - odd", |
| 1575 | fh_type, fh_len); | 1575 | fh_type, fh_len); |
| 1576 | fh_type = 5; | 1576 | fh_type = fh_len; |
| 1577 | } | 1577 | } |
| 1578 | if (fh_len < 2) | ||
| 1579 | return NULL; | ||
| 1578 | 1580 | ||
| 1579 | return reiserfs_get_dentry(sb, fid->raw[0], fid->raw[1], | 1581 | return reiserfs_get_dentry(sb, fid->raw[0], fid->raw[1], |
| 1580 | (fh_type == 3 || fh_type >= 5) ? fid->raw[2] : 0); | 1582 | (fh_type == 3 || fh_type >= 5) ? fid->raw[2] : 0); |
| @@ -1583,6 +1585,8 @@ struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid, | |||
| 1583 | struct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid, | 1585 | struct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid, |
| 1584 | int fh_len, int fh_type) | 1586 | int fh_len, int fh_type) |
| 1585 | { | 1587 | { |
| 1588 | if (fh_type > fh_len) | ||
| 1589 | fh_type = fh_len; | ||
| 1586 | if (fh_type < 4) | 1590 | if (fh_type < 4) |
| 1587 | return NULL; | 1591 | return NULL; |
| 1588 | 1592 | ||
diff --git a/fs/super.c b/fs/super.c index a3bc935069d9..12f123712161 100644 --- a/fs/super.c +++ b/fs/super.c | |||
| @@ -186,15 +186,8 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags) | |||
| 186 | spin_lock_init(&s->s_inode_lru_lock); | 186 | spin_lock_init(&s->s_inode_lru_lock); |
| 187 | INIT_LIST_HEAD(&s->s_mounts); | 187 | INIT_LIST_HEAD(&s->s_mounts); |
| 188 | init_rwsem(&s->s_umount); | 188 | init_rwsem(&s->s_umount); |
| 189 | mutex_init(&s->s_lock); | ||
| 190 | lockdep_set_class(&s->s_umount, &type->s_umount_key); | 189 | lockdep_set_class(&s->s_umount, &type->s_umount_key); |
| 191 | /* | 190 | /* |
| 192 | * The locking rules for s_lock are up to the | ||
| 193 | * filesystem. For example ext3fs has different | ||
| 194 | * lock ordering than usbfs: | ||
| 195 | */ | ||
| 196 | lockdep_set_class(&s->s_lock, &type->s_lock_key); | ||
| 197 | /* | ||
| 198 | * sget() can have s_umount recursion. | 191 | * sget() can have s_umount recursion. |
| 199 | * | 192 | * |
| 200 | * When it cannot find a suitable sb, it allocates a new | 193 | * When it cannot find a suitable sb, it allocates a new |
| @@ -394,22 +387,6 @@ bool grab_super_passive(struct super_block *sb) | |||
| 394 | return false; | 387 | return false; |
| 395 | } | 388 | } |
| 396 | 389 | ||
| 397 | /* | ||
| 398 | * Superblock locking. We really ought to get rid of these two. | ||
| 399 | */ | ||
| 400 | void lock_super(struct super_block * sb) | ||
| 401 | { | ||
| 402 | mutex_lock(&sb->s_lock); | ||
| 403 | } | ||
| 404 | |||
| 405 | void unlock_super(struct super_block * sb) | ||
| 406 | { | ||
| 407 | mutex_unlock(&sb->s_lock); | ||
| 408 | } | ||
| 409 | |||
| 410 | EXPORT_SYMBOL(lock_super); | ||
| 411 | EXPORT_SYMBOL(unlock_super); | ||
| 412 | |||
| 413 | /** | 390 | /** |
| 414 | * generic_shutdown_super - common helper for ->kill_sb() | 391 | * generic_shutdown_super - common helper for ->kill_sb() |
| 415 | * @sb: superblock to kill | 392 | * @sb: superblock to kill |
diff --git a/fs/sysv/balloc.c b/fs/sysv/balloc.c index 9a6ad96acf27..921c053fc052 100644 --- a/fs/sysv/balloc.c +++ b/fs/sysv/balloc.c | |||
| @@ -60,12 +60,12 @@ void sysv_free_block(struct super_block * sb, sysv_zone_t nr) | |||
| 60 | return; | 60 | return; |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | lock_super(sb); | 63 | mutex_lock(&sbi->s_lock); |
| 64 | count = fs16_to_cpu(sbi, *sbi->s_bcache_count); | 64 | count = fs16_to_cpu(sbi, *sbi->s_bcache_count); |
| 65 | 65 | ||
| 66 | if (count > sbi->s_flc_size) { | 66 | if (count > sbi->s_flc_size) { |
| 67 | printk("sysv_free_block: flc_count > flc_size\n"); | 67 | printk("sysv_free_block: flc_count > flc_size\n"); |
| 68 | unlock_super(sb); | 68 | mutex_unlock(&sbi->s_lock); |
| 69 | return; | 69 | return; |
| 70 | } | 70 | } |
| 71 | /* If the free list head in super-block is full, it is copied | 71 | /* If the free list head in super-block is full, it is copied |
| @@ -77,7 +77,7 @@ void sysv_free_block(struct super_block * sb, sysv_zone_t nr) | |||
| 77 | bh = sb_getblk(sb, block); | 77 | bh = sb_getblk(sb, block); |
| 78 | if (!bh) { | 78 | if (!bh) { |
| 79 | printk("sysv_free_block: getblk() failed\n"); | 79 | printk("sysv_free_block: getblk() failed\n"); |
| 80 | unlock_super(sb); | 80 | mutex_unlock(&sbi->s_lock); |
| 81 | return; | 81 | return; |
| 82 | } | 82 | } |
| 83 | memset(bh->b_data, 0, sb->s_blocksize); | 83 | memset(bh->b_data, 0, sb->s_blocksize); |
| @@ -93,7 +93,7 @@ void sysv_free_block(struct super_block * sb, sysv_zone_t nr) | |||
| 93 | *sbi->s_bcache_count = cpu_to_fs16(sbi, count); | 93 | *sbi->s_bcache_count = cpu_to_fs16(sbi, count); |
| 94 | fs32_add(sbi, sbi->s_free_blocks, 1); | 94 | fs32_add(sbi, sbi->s_free_blocks, 1); |
| 95 | dirty_sb(sb); | 95 | dirty_sb(sb); |
| 96 | unlock_super(sb); | 96 | mutex_unlock(&sbi->s_lock); |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | sysv_zone_t sysv_new_block(struct super_block * sb) | 99 | sysv_zone_t sysv_new_block(struct super_block * sb) |
| @@ -104,7 +104,7 @@ sysv_zone_t sysv_new_block(struct super_block * sb) | |||
| 104 | struct buffer_head * bh; | 104 | struct buffer_head * bh; |
| 105 | unsigned count; | 105 | unsigned count; |
| 106 | 106 | ||
| 107 | lock_super(sb); | 107 | mutex_lock(&sbi->s_lock); |
| 108 | count = fs16_to_cpu(sbi, *sbi->s_bcache_count); | 108 | count = fs16_to_cpu(sbi, *sbi->s_bcache_count); |
| 109 | 109 | ||
| 110 | if (count == 0) /* Applies only to Coherent FS */ | 110 | if (count == 0) /* Applies only to Coherent FS */ |
| @@ -147,11 +147,11 @@ sysv_zone_t sysv_new_block(struct super_block * sb) | |||
| 147 | /* Now the free list head in the superblock is valid again. */ | 147 | /* Now the free list head in the superblock is valid again. */ |
| 148 | fs32_add(sbi, sbi->s_free_blocks, -1); | 148 | fs32_add(sbi, sbi->s_free_blocks, -1); |
| 149 | dirty_sb(sb); | 149 | dirty_sb(sb); |
| 150 | unlock_super(sb); | 150 | mutex_unlock(&sbi->s_lock); |
| 151 | return nr; | 151 | return nr; |
| 152 | 152 | ||
| 153 | Enospc: | 153 | Enospc: |
| 154 | unlock_super(sb); | 154 | mutex_unlock(&sbi->s_lock); |
| 155 | return 0; | 155 | return 0; |
| 156 | } | 156 | } |
| 157 | 157 | ||
| @@ -173,7 +173,7 @@ unsigned long sysv_count_free_blocks(struct super_block * sb) | |||
| 173 | if (sbi->s_type == FSTYPE_AFS) | 173 | if (sbi->s_type == FSTYPE_AFS) |
| 174 | return 0; | 174 | return 0; |
| 175 | 175 | ||
| 176 | lock_super(sb); | 176 | mutex_lock(&sbi->s_lock); |
| 177 | sb_count = fs32_to_cpu(sbi, *sbi->s_free_blocks); | 177 | sb_count = fs32_to_cpu(sbi, *sbi->s_free_blocks); |
| 178 | 178 | ||
| 179 | if (0) | 179 | if (0) |
| @@ -211,7 +211,7 @@ unsigned long sysv_count_free_blocks(struct super_block * sb) | |||
| 211 | if (count != sb_count) | 211 | if (count != sb_count) |
| 212 | goto Ecount; | 212 | goto Ecount; |
| 213 | done: | 213 | done: |
| 214 | unlock_super(sb); | 214 | mutex_unlock(&sbi->s_lock); |
| 215 | return count; | 215 | return count; |
| 216 | 216 | ||
| 217 | Einval: | 217 | Einval: |
diff --git a/fs/sysv/ialloc.c b/fs/sysv/ialloc.c index 8233b02eccae..f9db4eb31db4 100644 --- a/fs/sysv/ialloc.c +++ b/fs/sysv/ialloc.c | |||
| @@ -118,7 +118,7 @@ void sysv_free_inode(struct inode * inode) | |||
| 118 | "%s\n", inode->i_sb->s_id); | 118 | "%s\n", inode->i_sb->s_id); |
| 119 | return; | 119 | return; |
| 120 | } | 120 | } |
| 121 | lock_super(sb); | 121 | mutex_lock(&sbi->s_lock); |
| 122 | count = fs16_to_cpu(sbi, *sbi->s_sb_fic_count); | 122 | count = fs16_to_cpu(sbi, *sbi->s_sb_fic_count); |
| 123 | if (count < sbi->s_fic_size) { | 123 | if (count < sbi->s_fic_size) { |
| 124 | *sv_sb_fic_inode(sb,count++) = cpu_to_fs16(sbi, ino); | 124 | *sv_sb_fic_inode(sb,count++) = cpu_to_fs16(sbi, ino); |
| @@ -128,7 +128,7 @@ void sysv_free_inode(struct inode * inode) | |||
| 128 | dirty_sb(sb); | 128 | dirty_sb(sb); |
| 129 | memset(raw_inode, 0, sizeof(struct sysv_inode)); | 129 | memset(raw_inode, 0, sizeof(struct sysv_inode)); |
| 130 | mark_buffer_dirty(bh); | 130 | mark_buffer_dirty(bh); |
| 131 | unlock_super(sb); | 131 | mutex_unlock(&sbi->s_lock); |
| 132 | brelse(bh); | 132 | brelse(bh); |
| 133 | } | 133 | } |
| 134 | 134 | ||
| @@ -147,13 +147,13 @@ struct inode * sysv_new_inode(const struct inode * dir, umode_t mode) | |||
| 147 | if (!inode) | 147 | if (!inode) |
| 148 | return ERR_PTR(-ENOMEM); | 148 | return ERR_PTR(-ENOMEM); |
| 149 | 149 | ||
| 150 | lock_super(sb); | 150 | mutex_lock(&sbi->s_lock); |
| 151 | count = fs16_to_cpu(sbi, *sbi->s_sb_fic_count); | 151 | count = fs16_to_cpu(sbi, *sbi->s_sb_fic_count); |
| 152 | if (count == 0 || (*sv_sb_fic_inode(sb,count-1) == 0)) { | 152 | if (count == 0 || (*sv_sb_fic_inode(sb,count-1) == 0)) { |
| 153 | count = refill_free_cache(sb); | 153 | count = refill_free_cache(sb); |
| 154 | if (count == 0) { | 154 | if (count == 0) { |
| 155 | iput(inode); | 155 | iput(inode); |
| 156 | unlock_super(sb); | 156 | mutex_unlock(&sbi->s_lock); |
| 157 | return ERR_PTR(-ENOSPC); | 157 | return ERR_PTR(-ENOSPC); |
| 158 | } | 158 | } |
| 159 | } | 159 | } |
| @@ -174,7 +174,7 @@ struct inode * sysv_new_inode(const struct inode * dir, umode_t mode) | |||
| 174 | sysv_write_inode(inode, &wbc); /* ensure inode not allocated again */ | 174 | sysv_write_inode(inode, &wbc); /* ensure inode not allocated again */ |
| 175 | mark_inode_dirty(inode); /* cleared by sysv_write_inode() */ | 175 | mark_inode_dirty(inode); /* cleared by sysv_write_inode() */ |
| 176 | /* That's it. */ | 176 | /* That's it. */ |
| 177 | unlock_super(sb); | 177 | mutex_unlock(&sbi->s_lock); |
| 178 | return inode; | 178 | return inode; |
| 179 | } | 179 | } |
| 180 | 180 | ||
| @@ -185,7 +185,7 @@ unsigned long sysv_count_free_inodes(struct super_block * sb) | |||
| 185 | struct sysv_inode * raw_inode; | 185 | struct sysv_inode * raw_inode; |
| 186 | int ino, count, sb_count; | 186 | int ino, count, sb_count; |
| 187 | 187 | ||
| 188 | lock_super(sb); | 188 | mutex_lock(&sbi->s_lock); |
| 189 | 189 | ||
| 190 | sb_count = fs16_to_cpu(sbi, *sbi->s_sb_total_free_inodes); | 190 | sb_count = fs16_to_cpu(sbi, *sbi->s_sb_total_free_inodes); |
| 191 | 191 | ||
| @@ -213,7 +213,7 @@ unsigned long sysv_count_free_inodes(struct super_block * sb) | |||
| 213 | if (count != sb_count) | 213 | if (count != sb_count) |
| 214 | goto Einval; | 214 | goto Einval; |
| 215 | out: | 215 | out: |
| 216 | unlock_super(sb); | 216 | mutex_unlock(&sbi->s_lock); |
| 217 | return count; | 217 | return count; |
| 218 | 218 | ||
| 219 | Einval: | 219 | Einval: |
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index d33e506c1eac..c327d4ee1235 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c | |||
| @@ -36,7 +36,7 @@ static int sysv_sync_fs(struct super_block *sb, int wait) | |||
| 36 | struct sysv_sb_info *sbi = SYSV_SB(sb); | 36 | struct sysv_sb_info *sbi = SYSV_SB(sb); |
| 37 | unsigned long time = get_seconds(), old_time; | 37 | unsigned long time = get_seconds(), old_time; |
| 38 | 38 | ||
| 39 | lock_super(sb); | 39 | mutex_lock(&sbi->s_lock); |
| 40 | 40 | ||
| 41 | /* | 41 | /* |
| 42 | * If we are going to write out the super block, | 42 | * If we are going to write out the super block, |
| @@ -51,7 +51,7 @@ static int sysv_sync_fs(struct super_block *sb, int wait) | |||
| 51 | mark_buffer_dirty(sbi->s_bh2); | 51 | mark_buffer_dirty(sbi->s_bh2); |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | unlock_super(sb); | 54 | mutex_unlock(&sbi->s_lock); |
| 55 | 55 | ||
| 56 | return 0; | 56 | return 0; |
| 57 | } | 57 | } |
diff --git a/fs/sysv/super.c b/fs/sysv/super.c index 7491c33b6468..a38e87bdd78d 100644 --- a/fs/sysv/super.c +++ b/fs/sysv/super.c | |||
| @@ -368,6 +368,7 @@ static int sysv_fill_super(struct super_block *sb, void *data, int silent) | |||
| 368 | 368 | ||
| 369 | sbi->s_sb = sb; | 369 | sbi->s_sb = sb; |
| 370 | sbi->s_block_base = 0; | 370 | sbi->s_block_base = 0; |
| 371 | mutex_init(&sbi->s_lock); | ||
| 371 | sb->s_fs_info = sbi; | 372 | sb->s_fs_info = sbi; |
| 372 | 373 | ||
| 373 | sb_set_blocksize(sb, BLOCK_SIZE); | 374 | sb_set_blocksize(sb, BLOCK_SIZE); |
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h index 0bc35fdc58e2..69d488986cce 100644 --- a/fs/sysv/sysv.h +++ b/fs/sysv/sysv.h | |||
| @@ -58,6 +58,7 @@ struct sysv_sb_info { | |||
| 58 | u32 s_nzones; /* same as s_sbd->s_fsize */ | 58 | u32 s_nzones; /* same as s_sbd->s_fsize */ |
| 59 | u16 s_namelen; /* max length of dir entry */ | 59 | u16 s_namelen; /* max length of dir entry */ |
| 60 | int s_forced_ro; | 60 | int s_forced_ro; |
| 61 | struct mutex s_lock; | ||
| 61 | }; | 62 | }; |
| 62 | 63 | ||
| 63 | /* | 64 | /* |
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index 1b3e410bf334..a7ea492ae660 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c | |||
| @@ -54,7 +54,7 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count) | |||
| 54 | if (ufs_fragnum(fragment) + count > uspi->s_fpg) | 54 | if (ufs_fragnum(fragment) + count > uspi->s_fpg) |
| 55 | ufs_error (sb, "ufs_free_fragments", "internal error"); | 55 | ufs_error (sb, "ufs_free_fragments", "internal error"); |
| 56 | 56 | ||
| 57 | lock_super(sb); | 57 | mutex_lock(&UFS_SB(sb)->s_lock); |
| 58 | 58 | ||
| 59 | cgno = ufs_dtog(uspi, fragment); | 59 | cgno = ufs_dtog(uspi, fragment); |
| 60 | bit = ufs_dtogd(uspi, fragment); | 60 | bit = ufs_dtogd(uspi, fragment); |
| @@ -118,12 +118,12 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count) | |||
| 118 | ubh_sync_block(UCPI_UBH(ucpi)); | 118 | ubh_sync_block(UCPI_UBH(ucpi)); |
| 119 | ufs_mark_sb_dirty(sb); | 119 | ufs_mark_sb_dirty(sb); |
| 120 | 120 | ||
| 121 | unlock_super (sb); | 121 | mutex_unlock(&UFS_SB(sb)->s_lock); |
| 122 | UFSD("EXIT\n"); | 122 | UFSD("EXIT\n"); |
| 123 | return; | 123 | return; |
| 124 | 124 | ||
| 125 | failed: | 125 | failed: |
| 126 | unlock_super (sb); | 126 | mutex_unlock(&UFS_SB(sb)->s_lock); |
| 127 | UFSD("EXIT (FAILED)\n"); | 127 | UFSD("EXIT (FAILED)\n"); |
| 128 | return; | 128 | return; |
| 129 | } | 129 | } |
| @@ -155,7 +155,7 @@ void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count) | |||
| 155 | goto failed; | 155 | goto failed; |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | lock_super(sb); | 158 | mutex_lock(&UFS_SB(sb)->s_lock); |
| 159 | 159 | ||
| 160 | do_more: | 160 | do_more: |
| 161 | overflow = 0; | 161 | overflow = 0; |
| @@ -215,12 +215,12 @@ do_more: | |||
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | ufs_mark_sb_dirty(sb); | 217 | ufs_mark_sb_dirty(sb); |
| 218 | unlock_super (sb); | 218 | mutex_unlock(&UFS_SB(sb)->s_lock); |
| 219 | UFSD("EXIT\n"); | 219 | UFSD("EXIT\n"); |
| 220 | return; | 220 | return; |
| 221 | 221 | ||
| 222 | failed_unlock: | 222 | failed_unlock: |
| 223 | unlock_super (sb); | 223 | mutex_unlock(&UFS_SB(sb)->s_lock); |
| 224 | failed: | 224 | failed: |
| 225 | UFSD("EXIT (FAILED)\n"); | 225 | UFSD("EXIT (FAILED)\n"); |
| 226 | return; | 226 | return; |
| @@ -361,7 +361,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, | |||
| 361 | usb1 = ubh_get_usb_first(uspi); | 361 | usb1 = ubh_get_usb_first(uspi); |
| 362 | *err = -ENOSPC; | 362 | *err = -ENOSPC; |
| 363 | 363 | ||
| 364 | lock_super (sb); | 364 | mutex_lock(&UFS_SB(sb)->s_lock); |
| 365 | tmp = ufs_data_ptr_to_cpu(sb, p); | 365 | tmp = ufs_data_ptr_to_cpu(sb, p); |
| 366 | 366 | ||
| 367 | if (count + ufs_fragnum(fragment) > uspi->s_fpb) { | 367 | if (count + ufs_fragnum(fragment) > uspi->s_fpb) { |
| @@ -382,19 +382,19 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, | |||
| 382 | "fragment %llu, tmp %llu\n", | 382 | "fragment %llu, tmp %llu\n", |
| 383 | (unsigned long long)fragment, | 383 | (unsigned long long)fragment, |
| 384 | (unsigned long long)tmp); | 384 | (unsigned long long)tmp); |
| 385 | unlock_super(sb); | 385 | mutex_unlock(&UFS_SB(sb)->s_lock); |
| 386 | return INVBLOCK; | 386 | return INVBLOCK; |
| 387 | } | 387 | } |
| 388 | if (fragment < UFS_I(inode)->i_lastfrag) { | 388 | if (fragment < UFS_I(inode)->i_lastfrag) { |
| 389 | UFSD("EXIT (ALREADY ALLOCATED)\n"); | 389 | UFSD("EXIT (ALREADY ALLOCATED)\n"); |
| 390 | unlock_super (sb); | 390 | mutex_unlock(&UFS_SB(sb)->s_lock); |
| 391 | return 0; | 391 | return 0; |
| 392 | } | 392 | } |
| 393 | } | 393 | } |
| 394 | else { | 394 | else { |
| 395 | if (tmp) { | 395 | if (tmp) { |
| 396 | UFSD("EXIT (ALREADY ALLOCATED)\n"); | 396 | UFSD("EXIT (ALREADY ALLOCATED)\n"); |
| 397 | unlock_super(sb); | 397 | mutex_unlock(&UFS_SB(sb)->s_lock); |
| 398 | return 0; | 398 | return 0; |
| 399 | } | 399 | } |
| 400 | } | 400 | } |
| @@ -403,7 +403,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, | |||
| 403 | * There is not enough space for user on the device | 403 | * There is not enough space for user on the device |
| 404 | */ | 404 | */ |
| 405 | if (!capable(CAP_SYS_RESOURCE) && ufs_freespace(uspi, UFS_MINFREE) <= 0) { | 405 | if (!capable(CAP_SYS_RESOURCE) && ufs_freespace(uspi, UFS_MINFREE) <= 0) { |
| 406 | unlock_super (sb); | 406 | mutex_unlock(&UFS_SB(sb)->s_lock); |
| 407 | UFSD("EXIT (FAILED)\n"); | 407 | UFSD("EXIT (FAILED)\n"); |
| 408 | return 0; | 408 | return 0; |
| 409 | } | 409 | } |
| @@ -428,7 +428,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, | |||
| 428 | ufs_clear_frags(inode, result + oldcount, | 428 | ufs_clear_frags(inode, result + oldcount, |
| 429 | newcount - oldcount, locked_page != NULL); | 429 | newcount - oldcount, locked_page != NULL); |
| 430 | } | 430 | } |
| 431 | unlock_super(sb); | 431 | mutex_unlock(&UFS_SB(sb)->s_lock); |
| 432 | UFSD("EXIT, result %llu\n", (unsigned long long)result); | 432 | UFSD("EXIT, result %llu\n", (unsigned long long)result); |
| 433 | return result; | 433 | return result; |
| 434 | } | 434 | } |
| @@ -443,7 +443,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, | |||
| 443 | fragment + count); | 443 | fragment + count); |
| 444 | ufs_clear_frags(inode, result + oldcount, newcount - oldcount, | 444 | ufs_clear_frags(inode, result + oldcount, newcount - oldcount, |
| 445 | locked_page != NULL); | 445 | locked_page != NULL); |
| 446 | unlock_super(sb); | 446 | mutex_unlock(&UFS_SB(sb)->s_lock); |
| 447 | UFSD("EXIT, result %llu\n", (unsigned long long)result); | 447 | UFSD("EXIT, result %llu\n", (unsigned long long)result); |
| 448 | return result; | 448 | return result; |
| 449 | } | 449 | } |
| @@ -481,7 +481,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, | |||
| 481 | *err = 0; | 481 | *err = 0; |
| 482 | UFS_I(inode)->i_lastfrag = max(UFS_I(inode)->i_lastfrag, | 482 | UFS_I(inode)->i_lastfrag = max(UFS_I(inode)->i_lastfrag, |
| 483 | fragment + count); | 483 | fragment + count); |
| 484 | unlock_super(sb); | 484 | mutex_unlock(&UFS_SB(sb)->s_lock); |
| 485 | if (newcount < request) | 485 | if (newcount < request) |
| 486 | ufs_free_fragments (inode, result + newcount, request - newcount); | 486 | ufs_free_fragments (inode, result + newcount, request - newcount); |
| 487 | ufs_free_fragments (inode, tmp, oldcount); | 487 | ufs_free_fragments (inode, tmp, oldcount); |
| @@ -489,7 +489,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, | |||
| 489 | return result; | 489 | return result; |
| 490 | } | 490 | } |
| 491 | 491 | ||
| 492 | unlock_super(sb); | 492 | mutex_unlock(&UFS_SB(sb)->s_lock); |
| 493 | UFSD("EXIT (FAILED)\n"); | 493 | UFSD("EXIT (FAILED)\n"); |
| 494 | return 0; | 494 | return 0; |
| 495 | } | 495 | } |
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c index e84cbe21b986..d0426d74817b 100644 --- a/fs/ufs/ialloc.c +++ b/fs/ufs/ialloc.c | |||
| @@ -71,11 +71,11 @@ void ufs_free_inode (struct inode * inode) | |||
| 71 | 71 | ||
| 72 | ino = inode->i_ino; | 72 | ino = inode->i_ino; |
| 73 | 73 | ||
| 74 | lock_super (sb); | 74 | mutex_lock(&UFS_SB(sb)->s_lock); |
| 75 | 75 | ||
| 76 | if (!((ino > 1) && (ino < (uspi->s_ncg * uspi->s_ipg )))) { | 76 | if (!((ino > 1) && (ino < (uspi->s_ncg * uspi->s_ipg )))) { |
| 77 | ufs_warning(sb, "ufs_free_inode", "reserved inode or nonexistent inode %u\n", ino); | 77 | ufs_warning(sb, "ufs_free_inode", "reserved inode or nonexistent inode %u\n", ino); |
| 78 | unlock_super (sb); | 78 | mutex_unlock(&UFS_SB(sb)->s_lock); |
| 79 | return; | 79 | return; |
| 80 | } | 80 | } |
| 81 | 81 | ||
| @@ -83,7 +83,7 @@ void ufs_free_inode (struct inode * inode) | |||
| 83 | bit = ufs_inotocgoff (ino); | 83 | bit = ufs_inotocgoff (ino); |
| 84 | ucpi = ufs_load_cylinder (sb, cg); | 84 | ucpi = ufs_load_cylinder (sb, cg); |
| 85 | if (!ucpi) { | 85 | if (!ucpi) { |
| 86 | unlock_super (sb); | 86 | mutex_unlock(&UFS_SB(sb)->s_lock); |
| 87 | return; | 87 | return; |
| 88 | } | 88 | } |
| 89 | ucg = ubh_get_ucg(UCPI_UBH(ucpi)); | 89 | ucg = ubh_get_ucg(UCPI_UBH(ucpi)); |
| @@ -117,7 +117,7 @@ void ufs_free_inode (struct inode * inode) | |||
| 117 | ubh_sync_block(UCPI_UBH(ucpi)); | 117 | ubh_sync_block(UCPI_UBH(ucpi)); |
| 118 | 118 | ||
| 119 | ufs_mark_sb_dirty(sb); | 119 | ufs_mark_sb_dirty(sb); |
| 120 | unlock_super (sb); | 120 | mutex_unlock(&UFS_SB(sb)->s_lock); |
| 121 | UFSD("EXIT\n"); | 121 | UFSD("EXIT\n"); |
| 122 | } | 122 | } |
| 123 | 123 | ||
| @@ -197,7 +197,7 @@ struct inode *ufs_new_inode(struct inode *dir, umode_t mode) | |||
| 197 | uspi = sbi->s_uspi; | 197 | uspi = sbi->s_uspi; |
| 198 | usb1 = ubh_get_usb_first(uspi); | 198 | usb1 = ubh_get_usb_first(uspi); |
| 199 | 199 | ||
| 200 | lock_super (sb); | 200 | mutex_lock(&sbi->s_lock); |
| 201 | 201 | ||
| 202 | /* | 202 | /* |
| 203 | * Try to place the inode in its parent directory | 203 | * Try to place the inode in its parent directory |
| @@ -333,20 +333,20 @@ cg_found: | |||
| 333 | brelse(bh); | 333 | brelse(bh); |
| 334 | } | 334 | } |
| 335 | 335 | ||
| 336 | unlock_super (sb); | 336 | mutex_unlock(&sbi->s_lock); |
| 337 | 337 | ||
| 338 | UFSD("allocating inode %lu\n", inode->i_ino); | 338 | UFSD("allocating inode %lu\n", inode->i_ino); |
| 339 | UFSD("EXIT\n"); | 339 | UFSD("EXIT\n"); |
| 340 | return inode; | 340 | return inode; |
| 341 | 341 | ||
| 342 | fail_remove_inode: | 342 | fail_remove_inode: |
| 343 | unlock_super(sb); | 343 | mutex_unlock(&sbi->s_lock); |
| 344 | clear_nlink(inode); | 344 | clear_nlink(inode); |
| 345 | iput(inode); | 345 | iput(inode); |
| 346 | UFSD("EXIT (FAILED): err %d\n", err); | 346 | UFSD("EXIT (FAILED): err %d\n", err); |
| 347 | return ERR_PTR(err); | 347 | return ERR_PTR(err); |
| 348 | failed: | 348 | failed: |
| 349 | unlock_super (sb); | 349 | mutex_unlock(&sbi->s_lock); |
| 350 | make_bad_inode(inode); | 350 | make_bad_inode(inode); |
| 351 | iput (inode); | 351 | iput (inode); |
| 352 | UFSD("EXIT (FAILED): err %d\n", err); | 352 | UFSD("EXIT (FAILED): err %d\n", err); |
diff --git a/fs/ufs/super.c b/fs/ufs/super.c index f7cfecfe1cab..dc8e3a861d0f 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c | |||
| @@ -699,7 +699,7 @@ static int ufs_sync_fs(struct super_block *sb, int wait) | |||
| 699 | unsigned flags; | 699 | unsigned flags; |
| 700 | 700 | ||
| 701 | lock_ufs(sb); | 701 | lock_ufs(sb); |
| 702 | lock_super(sb); | 702 | mutex_lock(&UFS_SB(sb)->s_lock); |
| 703 | 703 | ||
| 704 | UFSD("ENTER\n"); | 704 | UFSD("ENTER\n"); |
| 705 | 705 | ||
| @@ -717,7 +717,7 @@ static int ufs_sync_fs(struct super_block *sb, int wait) | |||
| 717 | ufs_put_cstotal(sb); | 717 | ufs_put_cstotal(sb); |
| 718 | 718 | ||
| 719 | UFSD("EXIT\n"); | 719 | UFSD("EXIT\n"); |
| 720 | unlock_super(sb); | 720 | mutex_unlock(&UFS_SB(sb)->s_lock); |
| 721 | unlock_ufs(sb); | 721 | unlock_ufs(sb); |
| 722 | 722 | ||
| 723 | return 0; | 723 | return 0; |
| @@ -805,6 +805,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 805 | } | 805 | } |
| 806 | #endif | 806 | #endif |
| 807 | mutex_init(&sbi->mutex); | 807 | mutex_init(&sbi->mutex); |
| 808 | mutex_init(&sbi->s_lock); | ||
| 808 | spin_lock_init(&sbi->work_lock); | 809 | spin_lock_init(&sbi->work_lock); |
| 809 | INIT_DELAYED_WORK(&sbi->sync_work, delayed_sync_fs); | 810 | INIT_DELAYED_WORK(&sbi->sync_work, delayed_sync_fs); |
| 810 | /* | 811 | /* |
| @@ -1280,7 +1281,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) | |||
| 1280 | unsigned flags; | 1281 | unsigned flags; |
| 1281 | 1282 | ||
| 1282 | lock_ufs(sb); | 1283 | lock_ufs(sb); |
| 1283 | lock_super(sb); | 1284 | mutex_lock(&UFS_SB(sb)->s_lock); |
| 1284 | uspi = UFS_SB(sb)->s_uspi; | 1285 | uspi = UFS_SB(sb)->s_uspi; |
| 1285 | flags = UFS_SB(sb)->s_flags; | 1286 | flags = UFS_SB(sb)->s_flags; |
| 1286 | usb1 = ubh_get_usb_first(uspi); | 1287 | usb1 = ubh_get_usb_first(uspi); |
| @@ -1294,7 +1295,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) | |||
| 1294 | new_mount_opt = 0; | 1295 | new_mount_opt = 0; |
| 1295 | ufs_set_opt (new_mount_opt, ONERROR_LOCK); | 1296 | ufs_set_opt (new_mount_opt, ONERROR_LOCK); |
| 1296 | if (!ufs_parse_options (data, &new_mount_opt)) { | 1297 | if (!ufs_parse_options (data, &new_mount_opt)) { |
| 1297 | unlock_super(sb); | 1298 | mutex_unlock(&UFS_SB(sb)->s_lock); |
| 1298 | unlock_ufs(sb); | 1299 | unlock_ufs(sb); |
| 1299 | return -EINVAL; | 1300 | return -EINVAL; |
| 1300 | } | 1301 | } |
| @@ -1302,14 +1303,14 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) | |||
| 1302 | new_mount_opt |= ufstype; | 1303 | new_mount_opt |= ufstype; |
| 1303 | } else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) { | 1304 | } else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) { |
| 1304 | printk("ufstype can't be changed during remount\n"); | 1305 | printk("ufstype can't be changed during remount\n"); |
| 1305 | unlock_super(sb); | 1306 | mutex_unlock(&UFS_SB(sb)->s_lock); |
| 1306 | unlock_ufs(sb); | 1307 | unlock_ufs(sb); |
| 1307 | return -EINVAL; | 1308 | return -EINVAL; |
| 1308 | } | 1309 | } |
| 1309 | 1310 | ||
| 1310 | if ((*mount_flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) { | 1311 | if ((*mount_flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) { |
| 1311 | UFS_SB(sb)->s_mount_opt = new_mount_opt; | 1312 | UFS_SB(sb)->s_mount_opt = new_mount_opt; |
| 1312 | unlock_super(sb); | 1313 | mutex_unlock(&UFS_SB(sb)->s_lock); |
| 1313 | unlock_ufs(sb); | 1314 | unlock_ufs(sb); |
| 1314 | return 0; | 1315 | return 0; |
| 1315 | } | 1316 | } |
| @@ -1334,7 +1335,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) | |||
| 1334 | #ifndef CONFIG_UFS_FS_WRITE | 1335 | #ifndef CONFIG_UFS_FS_WRITE |
| 1335 | printk("ufs was compiled with read-only support, " | 1336 | printk("ufs was compiled with read-only support, " |
| 1336 | "can't be mounted as read-write\n"); | 1337 | "can't be mounted as read-write\n"); |
| 1337 | unlock_super(sb); | 1338 | mutex_unlock(&UFS_SB(sb)->s_lock); |
| 1338 | unlock_ufs(sb); | 1339 | unlock_ufs(sb); |
| 1339 | return -EINVAL; | 1340 | return -EINVAL; |
| 1340 | #else | 1341 | #else |
| @@ -1344,13 +1345,13 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) | |||
| 1344 | ufstype != UFS_MOUNT_UFSTYPE_SUNx86 && | 1345 | ufstype != UFS_MOUNT_UFSTYPE_SUNx86 && |
| 1345 | ufstype != UFS_MOUNT_UFSTYPE_UFS2) { | 1346 | ufstype != UFS_MOUNT_UFSTYPE_UFS2) { |
| 1346 | printk("this ufstype is read-only supported\n"); | 1347 | printk("this ufstype is read-only supported\n"); |
| 1347 | unlock_super(sb); | 1348 | mutex_unlock(&UFS_SB(sb)->s_lock); |
| 1348 | unlock_ufs(sb); | 1349 | unlock_ufs(sb); |
| 1349 | return -EINVAL; | 1350 | return -EINVAL; |
| 1350 | } | 1351 | } |
| 1351 | if (!ufs_read_cylinder_structures(sb)) { | 1352 | if (!ufs_read_cylinder_structures(sb)) { |
| 1352 | printk("failed during remounting\n"); | 1353 | printk("failed during remounting\n"); |
| 1353 | unlock_super(sb); | 1354 | mutex_unlock(&UFS_SB(sb)->s_lock); |
| 1354 | unlock_ufs(sb); | 1355 | unlock_ufs(sb); |
| 1355 | return -EPERM; | 1356 | return -EPERM; |
| 1356 | } | 1357 | } |
| @@ -1358,7 +1359,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) | |||
| 1358 | #endif | 1359 | #endif |
| 1359 | } | 1360 | } |
| 1360 | UFS_SB(sb)->s_mount_opt = new_mount_opt; | 1361 | UFS_SB(sb)->s_mount_opt = new_mount_opt; |
| 1361 | unlock_super(sb); | 1362 | mutex_unlock(&UFS_SB(sb)->s_lock); |
| 1362 | unlock_ufs(sb); | 1363 | unlock_ufs(sb); |
| 1363 | return 0; | 1364 | return 0; |
| 1364 | } | 1365 | } |
diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h index 343e6fc571e5..ff2c15ab81aa 100644 --- a/fs/ufs/ufs.h +++ b/fs/ufs/ufs.h | |||
| @@ -24,6 +24,7 @@ struct ufs_sb_info { | |||
| 24 | int work_queued; /* non-zero if the delayed work is queued */ | 24 | int work_queued; /* non-zero if the delayed work is queued */ |
| 25 | struct delayed_work sync_work; /* FS sync delayed work */ | 25 | struct delayed_work sync_work; /* FS sync delayed work */ |
| 26 | spinlock_t work_lock; /* protects sync_work and work_queued */ | 26 | spinlock_t work_lock; /* protects sync_work and work_queued */ |
| 27 | struct mutex s_lock; | ||
| 27 | }; | 28 | }; |
| 28 | 29 | ||
| 29 | struct ufs_inode_info { | 30 | struct ufs_inode_info { |
diff --git a/fs/xattr.c b/fs/xattr.c index 1780f062dbaf..e164dddb8e96 100644 --- a/fs/xattr.c +++ b/fs/xattr.c | |||
| @@ -412,7 +412,7 @@ SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name, | |||
| 412 | if (!f.file) | 412 | if (!f.file) |
| 413 | return error; | 413 | return error; |
| 414 | dentry = f.file->f_path.dentry; | 414 | dentry = f.file->f_path.dentry; |
| 415 | audit_inode(NULL, dentry); | 415 | audit_inode(NULL, dentry, 0); |
| 416 | error = mnt_want_write_file(f.file); | 416 | error = mnt_want_write_file(f.file); |
| 417 | if (!error) { | 417 | if (!error) { |
| 418 | error = setxattr(dentry, name, value, size, flags); | 418 | error = setxattr(dentry, name, value, size, flags); |
| @@ -507,7 +507,7 @@ SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name, | |||
| 507 | 507 | ||
| 508 | if (!f.file) | 508 | if (!f.file) |
| 509 | return error; | 509 | return error; |
| 510 | audit_inode(NULL, f.file->f_path.dentry); | 510 | audit_inode(NULL, f.file->f_path.dentry, 0); |
| 511 | error = getxattr(f.file->f_path.dentry, name, value, size); | 511 | error = getxattr(f.file->f_path.dentry, name, value, size); |
| 512 | fdput(f); | 512 | fdput(f); |
| 513 | return error; | 513 | return error; |
| @@ -586,7 +586,7 @@ SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size) | |||
| 586 | 586 | ||
| 587 | if (!f.file) | 587 | if (!f.file) |
| 588 | return error; | 588 | return error; |
| 589 | audit_inode(NULL, f.file->f_path.dentry); | 589 | audit_inode(NULL, f.file->f_path.dentry, 0); |
| 590 | error = listxattr(f.file->f_path.dentry, list, size); | 590 | error = listxattr(f.file->f_path.dentry, list, size); |
| 591 | fdput(f); | 591 | fdput(f); |
| 592 | return error; | 592 | return error; |
| @@ -655,7 +655,7 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name) | |||
| 655 | if (!f.file) | 655 | if (!f.file) |
| 656 | return error; | 656 | return error; |
| 657 | dentry = f.file->f_path.dentry; | 657 | dentry = f.file->f_path.dentry; |
| 658 | audit_inode(NULL, dentry); | 658 | audit_inode(NULL, dentry, 0); |
| 659 | error = mnt_want_write_file(f.file); | 659 | error = mnt_want_write_file(f.file); |
| 660 | if (!error) { | 660 | if (!error) { |
| 661 | error = removexattr(dentry, name); | 661 | error = removexattr(dentry, name); |
diff --git a/fs/xfs/xfs_export.c b/fs/xfs/xfs_export.c index 42679223a0fd..8c6d1d70278c 100644 --- a/fs/xfs/xfs_export.c +++ b/fs/xfs/xfs_export.c | |||
| @@ -189,6 +189,9 @@ xfs_fs_fh_to_parent(struct super_block *sb, struct fid *fid, | |||
| 189 | struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fid; | 189 | struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fid; |
| 190 | struct inode *inode = NULL; | 190 | struct inode *inode = NULL; |
| 191 | 191 | ||
| 192 | if (fh_len < xfs_fileid_length(fileid_type)) | ||
| 193 | return NULL; | ||
| 194 | |||
| 192 | switch (fileid_type) { | 195 | switch (fileid_type) { |
| 193 | case FILEID_INO32_GEN_PARENT: | 196 | case FILEID_INO32_GEN_PARENT: |
| 194 | inode = xfs_nfs_get_inode(sb, fid->i32.parent_ino, | 197 | inode = xfs_nfs_get_inode(sb, fid->i32.parent_ino, |
