aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c186
1 files changed, 139 insertions, 47 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f82bde005a82..99650aaf8937 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -838,7 +838,8 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
838 p->o_arg.open_flags = flags; 838 p->o_arg.open_flags = flags;
839 p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE); 839 p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE);
840 p->o_arg.clientid = server->nfs_client->cl_clientid; 840 p->o_arg.clientid = server->nfs_client->cl_clientid;
841 p->o_arg.id = sp->so_seqid.owner_id; 841 p->o_arg.id.create_time = ktime_to_ns(sp->so_seqid.create_time);
842 p->o_arg.id.uniquifier = sp->so_seqid.owner_id;
842 p->o_arg.name = &dentry->d_name; 843 p->o_arg.name = &dentry->d_name;
843 p->o_arg.server = server; 844 p->o_arg.server = server;
844 p->o_arg.bitmask = server->attr_bitmask; 845 p->o_arg.bitmask = server->attr_bitmask;
@@ -1466,8 +1467,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
1466 goto unlock_no_action; 1467 goto unlock_no_action;
1467 rcu_read_unlock(); 1468 rcu_read_unlock();
1468 } 1469 }
1469 /* Update sequence id. */ 1470 /* Update client id. */
1470 data->o_arg.id = sp->so_seqid.owner_id;
1471 data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid; 1471 data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid;
1472 if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) { 1472 if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) {
1473 task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; 1473 task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
@@ -1954,10 +1954,19 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
1954 }; 1954 };
1955 int err; 1955 int err;
1956 do { 1956 do {
1957 err = nfs4_handle_exception(server, 1957 err = _nfs4_do_setattr(inode, cred, fattr, sattr, state);
1958 _nfs4_do_setattr(inode, cred, fattr, sattr, state), 1958 switch (err) {
1959 &exception); 1959 case -NFS4ERR_OPENMODE:
1960 if (state && !(state->state & FMODE_WRITE)) {
1961 err = -EBADF;
1962 if (sattr->ia_valid & ATTR_OPEN)
1963 err = -EACCES;
1964 goto out;
1965 }
1966 }
1967 err = nfs4_handle_exception(server, err, &exception);
1960 } while (exception.retry); 1968 } while (exception.retry);
1969out:
1961 return err; 1970 return err;
1962} 1971}
1963 1972
@@ -2368,8 +2377,9 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
2368 * Note that we'll actually follow the referral later when 2377 * Note that we'll actually follow the referral later when
2369 * we detect fsid mismatch in inode revalidation 2378 * we detect fsid mismatch in inode revalidation
2370 */ 2379 */
2371static int nfs4_get_referral(struct inode *dir, const struct qstr *name, 2380static int nfs4_get_referral(struct rpc_clnt *client, struct inode *dir,
2372 struct nfs_fattr *fattr, struct nfs_fh *fhandle) 2381 const struct qstr *name, struct nfs_fattr *fattr,
2382 struct nfs_fh *fhandle)
2373{ 2383{
2374 int status = -ENOMEM; 2384 int status = -ENOMEM;
2375 struct page *page = NULL; 2385 struct page *page = NULL;
@@ -2382,7 +2392,7 @@ static int nfs4_get_referral(struct inode *dir, const struct qstr *name,
2382 if (locations == NULL) 2392 if (locations == NULL)
2383 goto out; 2393 goto out;
2384 2394
2385 status = nfs4_proc_fs_locations(dir, name, locations, page); 2395 status = nfs4_proc_fs_locations(client, dir, name, locations, page);
2386 if (status != 0) 2396 if (status != 0)
2387 goto out; 2397 goto out;
2388 /* Make sure server returned a different fsid for the referral */ 2398 /* Make sure server returned a different fsid for the referral */
@@ -2519,39 +2529,84 @@ static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir,
2519 return status; 2529 return status;
2520} 2530}
2521 2531
2522void nfs_fixup_secinfo_attributes(struct nfs_fattr *fattr, struct nfs_fh *fh) 2532static void nfs_fixup_secinfo_attributes(struct nfs_fattr *fattr)
2523{ 2533{
2524 memset(fh, 0, sizeof(struct nfs_fh));
2525 fattr->fsid.major = 1;
2526 fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE | 2534 fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE |
2527 NFS_ATTR_FATTR_NLINK | NFS_ATTR_FATTR_FSID | NFS_ATTR_FATTR_MOUNTPOINT; 2535 NFS_ATTR_FATTR_NLINK | NFS_ATTR_FATTR_MOUNTPOINT;
2528 fattr->mode = S_IFDIR | S_IRUGO | S_IXUGO; 2536 fattr->mode = S_IFDIR | S_IRUGO | S_IXUGO;
2529 fattr->nlink = 2; 2537 fattr->nlink = 2;
2530} 2538}
2531 2539
2532static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name, 2540static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir,
2533 struct nfs_fh *fhandle, struct nfs_fattr *fattr) 2541 struct qstr *name, struct nfs_fh *fhandle,
2542 struct nfs_fattr *fattr)
2534{ 2543{
2535 struct nfs4_exception exception = { }; 2544 struct nfs4_exception exception = { };
2545 struct rpc_clnt *client = *clnt;
2536 int err; 2546 int err;
2537 do { 2547 do {
2538 int status; 2548 err = _nfs4_proc_lookup(client, dir, name, fhandle, fattr);
2539 2549 switch (err) {
2540 status = _nfs4_proc_lookup(clnt, dir, name, fhandle, fattr);
2541 switch (status) {
2542 case -NFS4ERR_BADNAME: 2550 case -NFS4ERR_BADNAME:
2543 return -ENOENT; 2551 err = -ENOENT;
2552 goto out;
2544 case -NFS4ERR_MOVED: 2553 case -NFS4ERR_MOVED:
2545 return nfs4_get_referral(dir, name, fattr, fhandle); 2554 err = nfs4_get_referral(client, dir, name, fattr, fhandle);
2555 goto out;
2546 case -NFS4ERR_WRONGSEC: 2556 case -NFS4ERR_WRONGSEC:
2547 nfs_fixup_secinfo_attributes(fattr, fhandle); 2557 err = -EPERM;
2558 if (client != *clnt)
2559 goto out;
2560
2561 client = nfs4_create_sec_client(client, dir, name);
2562 if (IS_ERR(client))
2563 return PTR_ERR(client);
2564
2565 exception.retry = 1;
2566 break;
2567 default:
2568 err = nfs4_handle_exception(NFS_SERVER(dir), err, &exception);
2548 } 2569 }
2549 err = nfs4_handle_exception(NFS_SERVER(dir),
2550 status, &exception);
2551 } while (exception.retry); 2570 } while (exception.retry);
2571
2572out:
2573 if (err == 0)
2574 *clnt = client;
2575 else if (client != *clnt)
2576 rpc_shutdown_client(client);
2577
2552 return err; 2578 return err;
2553} 2579}
2554 2580
2581static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name,
2582 struct nfs_fh *fhandle, struct nfs_fattr *fattr)
2583{
2584 int status;
2585 struct rpc_clnt *client = NFS_CLIENT(dir);
2586
2587 status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr);
2588 if (client != NFS_CLIENT(dir)) {
2589 rpc_shutdown_client(client);
2590 nfs_fixup_secinfo_attributes(fattr);
2591 }
2592 return status;
2593}
2594
2595struct rpc_clnt *
2596nfs4_proc_lookup_mountpoint(struct inode *dir, struct qstr *name,
2597 struct nfs_fh *fhandle, struct nfs_fattr *fattr)
2598{
2599 int status;
2600 struct rpc_clnt *client = rpc_clone_client(NFS_CLIENT(dir));
2601
2602 status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr);
2603 if (status < 0) {
2604 rpc_shutdown_client(client);
2605 return ERR_PTR(status);
2606 }
2607 return client;
2608}
2609
2555static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) 2610static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
2556{ 2611{
2557 struct nfs_server *server = NFS_SERVER(inode); 2612 struct nfs_server *server = NFS_SERVER(inode);
@@ -3619,16 +3674,16 @@ out:
3619 return ret; 3674 return ret;
3620} 3675}
3621 3676
3622static void nfs4_write_cached_acl(struct inode *inode, const char *buf, size_t acl_len) 3677static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size_t pgbase, size_t acl_len)
3623{ 3678{
3624 struct nfs4_cached_acl *acl; 3679 struct nfs4_cached_acl *acl;
3625 3680
3626 if (buf && acl_len <= PAGE_SIZE) { 3681 if (pages && acl_len <= PAGE_SIZE) {
3627 acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL); 3682 acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL);
3628 if (acl == NULL) 3683 if (acl == NULL)
3629 goto out; 3684 goto out;
3630 acl->cached = 1; 3685 acl->cached = 1;
3631 memcpy(acl->data, buf, acl_len); 3686 _copy_from_pages(acl->data, pages, pgbase, acl_len);
3632 } else { 3687 } else {
3633 acl = kmalloc(sizeof(*acl), GFP_KERNEL); 3688 acl = kmalloc(sizeof(*acl), GFP_KERNEL);
3634 if (acl == NULL) 3689 if (acl == NULL)
@@ -3661,7 +3716,6 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
3661 struct nfs_getaclres res = { 3716 struct nfs_getaclres res = {
3662 .acl_len = buflen, 3717 .acl_len = buflen,
3663 }; 3718 };
3664 void *resp_buf;
3665 struct rpc_message msg = { 3719 struct rpc_message msg = {
3666 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL], 3720 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL],
3667 .rpc_argp = &args, 3721 .rpc_argp = &args,
@@ -3675,24 +3729,27 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
3675 if (npages == 0) 3729 if (npages == 0)
3676 npages = 1; 3730 npages = 1;
3677 3731
3732 /* Add an extra page to handle the bitmap returned */
3733 npages++;
3734
3678 for (i = 0; i < npages; i++) { 3735 for (i = 0; i < npages; i++) {
3679 pages[i] = alloc_page(GFP_KERNEL); 3736 pages[i] = alloc_page(GFP_KERNEL);
3680 if (!pages[i]) 3737 if (!pages[i])
3681 goto out_free; 3738 goto out_free;
3682 } 3739 }
3683 if (npages > 1) { 3740
3684 /* for decoding across pages */ 3741 /* for decoding across pages */
3685 res.acl_scratch = alloc_page(GFP_KERNEL); 3742 res.acl_scratch = alloc_page(GFP_KERNEL);
3686 if (!res.acl_scratch) 3743 if (!res.acl_scratch)
3687 goto out_free; 3744 goto out_free;
3688 } 3745
3689 args.acl_len = npages * PAGE_SIZE; 3746 args.acl_len = npages * PAGE_SIZE;
3690 args.acl_pgbase = 0; 3747 args.acl_pgbase = 0;
3748
3691 /* Let decode_getfacl know not to fail if the ACL data is larger than 3749 /* Let decode_getfacl know not to fail if the ACL data is larger than
3692 * the page we send as a guess */ 3750 * the page we send as a guess */
3693 if (buf == NULL) 3751 if (buf == NULL)
3694 res.acl_flags |= NFS4_ACL_LEN_REQUEST; 3752 res.acl_flags |= NFS4_ACL_LEN_REQUEST;
3695 resp_buf = page_address(pages[0]);
3696 3753
3697 dprintk("%s buf %p buflen %zu npages %d args.acl_len %zu\n", 3754 dprintk("%s buf %p buflen %zu npages %d args.acl_len %zu\n",
3698 __func__, buf, buflen, npages, args.acl_len); 3755 __func__, buf, buflen, npages, args.acl_len);
@@ -3703,9 +3760,9 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
3703 3760
3704 acl_len = res.acl_len - res.acl_data_offset; 3761 acl_len = res.acl_len - res.acl_data_offset;
3705 if (acl_len > args.acl_len) 3762 if (acl_len > args.acl_len)
3706 nfs4_write_cached_acl(inode, NULL, acl_len); 3763 nfs4_write_cached_acl(inode, NULL, 0, acl_len);
3707 else 3764 else
3708 nfs4_write_cached_acl(inode, resp_buf + res.acl_data_offset, 3765 nfs4_write_cached_acl(inode, pages, res.acl_data_offset,
3709 acl_len); 3766 acl_len);
3710 if (buf) { 3767 if (buf) {
3711 ret = -ERANGE; 3768 ret = -ERANGE;
@@ -4558,7 +4615,9 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
4558static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request) 4615static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
4559{ 4616{
4560 struct nfs_server *server = NFS_SERVER(state->inode); 4617 struct nfs_server *server = NFS_SERVER(state->inode);
4561 struct nfs4_exception exception = { }; 4618 struct nfs4_exception exception = {
4619 .inode = state->inode,
4620 };
4562 int err; 4621 int err;
4563 4622
4564 do { 4623 do {
@@ -4576,7 +4635,9 @@ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request
4576static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request) 4635static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request)
4577{ 4636{
4578 struct nfs_server *server = NFS_SERVER(state->inode); 4637 struct nfs_server *server = NFS_SERVER(state->inode);
4579 struct nfs4_exception exception = { }; 4638 struct nfs4_exception exception = {
4639 .inode = state->inode,
4640 };
4580 int err; 4641 int err;
4581 4642
4582 err = nfs4_set_lock_state(state, request); 4643 err = nfs4_set_lock_state(state, request);
@@ -4676,6 +4737,7 @@ static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *
4676{ 4737{
4677 struct nfs4_exception exception = { 4738 struct nfs4_exception exception = {
4678 .state = state, 4739 .state = state,
4740 .inode = state->inode,
4679 }; 4741 };
4680 int err; 4742 int err;
4681 4743
@@ -4721,6 +4783,20 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
4721 4783
4722 if (state == NULL) 4784 if (state == NULL)
4723 return -ENOLCK; 4785 return -ENOLCK;
4786 /*
4787 * Don't rely on the VFS having checked the file open mode,
4788 * since it won't do this for flock() locks.
4789 */
4790 switch (request->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) {
4791 case F_RDLCK:
4792 if (!(filp->f_mode & FMODE_READ))
4793 return -EBADF;
4794 break;
4795 case F_WRLCK:
4796 if (!(filp->f_mode & FMODE_WRITE))
4797 return -EBADF;
4798 }
4799
4724 do { 4800 do {
4725 status = nfs4_proc_setlk(state, cmd, request); 4801 status = nfs4_proc_setlk(state, cmd, request);
4726 if ((status != -EAGAIN) || IS_SETLK(cmd)) 4802 if ((status != -EAGAIN) || IS_SETLK(cmd))
@@ -4891,8 +4967,10 @@ static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr)
4891 fattr->nlink = 2; 4967 fattr->nlink = 2;
4892} 4968}
4893 4969
4894int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, 4970static int _nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir,
4895 struct nfs4_fs_locations *fs_locations, struct page *page) 4971 const struct qstr *name,
4972 struct nfs4_fs_locations *fs_locations,
4973 struct page *page)
4896{ 4974{
4897 struct nfs_server *server = NFS_SERVER(dir); 4975 struct nfs_server *server = NFS_SERVER(dir);
4898 u32 bitmask[2] = { 4976 u32 bitmask[2] = {
@@ -4926,11 +5004,26 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
4926 nfs_fattr_init(&fs_locations->fattr); 5004 nfs_fattr_init(&fs_locations->fattr);
4927 fs_locations->server = server; 5005 fs_locations->server = server;
4928 fs_locations->nlocations = 0; 5006 fs_locations->nlocations = 0;
4929 status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); 5007 status = nfs4_call_sync(client, server, &msg, &args.seq_args, &res.seq_res, 0);
4930 dprintk("%s: returned status = %d\n", __func__, status); 5008 dprintk("%s: returned status = %d\n", __func__, status);
4931 return status; 5009 return status;
4932} 5010}
4933 5011
5012int nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir,
5013 const struct qstr *name,
5014 struct nfs4_fs_locations *fs_locations,
5015 struct page *page)
5016{
5017 struct nfs4_exception exception = { };
5018 int err;
5019 do {
5020 err = nfs4_handle_exception(NFS_SERVER(dir),
5021 _nfs4_proc_fs_locations(client, dir, name, fs_locations, page),
5022 &exception);
5023 } while (exception.retry);
5024 return err;
5025}
5026
4934static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors) 5027static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors)
4935{ 5028{
4936 int status; 5029 int status;
@@ -4953,8 +5046,8 @@ static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct
4953 return status; 5046 return status;
4954} 5047}
4955 5048
4956static int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, 5049int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name,
4957 struct nfs4_secinfo_flavors *flavors) 5050 struct nfs4_secinfo_flavors *flavors)
4958{ 5051{
4959 struct nfs4_exception exception = { }; 5052 struct nfs4_exception exception = { };
4960 int err; 5053 int err;
@@ -5029,10 +5122,9 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
5029 nfs4_construct_boot_verifier(clp, &verifier); 5122 nfs4_construct_boot_verifier(clp, &verifier);
5030 5123
5031 args.id_len = scnprintf(args.id, sizeof(args.id), 5124 args.id_len = scnprintf(args.id, sizeof(args.id),
5032 "%s/%s.%s/%u", 5125 "%s/%s/%u",
5033 clp->cl_ipaddr, 5126 clp->cl_ipaddr,
5034 init_utsname()->nodename, 5127 clp->cl_rpcclient->cl_nodename,
5035 init_utsname()->domainname,
5036 clp->cl_rpcclient->cl_auth->au_flavor); 5128 clp->cl_rpcclient->cl_auth->au_flavor);
5037 5129
5038 res.server_scope = kzalloc(sizeof(struct server_scope), GFP_KERNEL); 5130 res.server_scope = kzalloc(sizeof(struct server_scope), GFP_KERNEL);