diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-06-21 21:20:55 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-06-21 21:20:55 -0400 |
commit | 2992c4bd5742b31a0ee00a76eee9c1c284507418 (patch) | |
tree | b2af7d776ec6a4ae69b5f245ee0586359a99eabd /fs | |
parent | e08f6d4131ab964420f0bcabecc68d75fb49df79 (diff) | |
parent | 1650add23578b5ca35c1f1e863987180a8c03779 (diff) |
Merge branch 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
* 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6:
NFS: Fix decode_secinfo_maxsz
NFSv4.1: Fix an off-by-one error in pnfs_generic_pg_test
NFSv4.1: Fix some issues with pnfs_generic_pg_test
NFSv4.1: file layout must consider pg_bsize for coalescing
pnfs-obj: No longer needed to take an extra ref at add_device
SUNRPC: Ensure the RPC client only quits on fatal signals
NFSv4: Fix a readdir regression
nfs4.1: mark layout as bad on error path in _pnfs_return_layout
nfs4.1: prevent race that allowed use of freed layout in _pnfs_return_layout
NFSv4.1: need to put_layout_hdr on _pnfs_return_layout error path
NFS: (d)printks should use %zd for ssize_t arguments
NFSv4.1: fix break condition in pnfs_find_lseg
nfs4.1: fix several problems with _pnfs_return_layout
NFSv4.1: allow zero fh array in filelayout decode layout
NFSv4.1: allow nfs_fhget to succeed with mounted on fileid
NFSv4.1: Fix a refcounting issue in the pNFS device id cache
NFSv4.1: deprecate headerpadsz in CREATE_SESSION
NFS41: do not update isize if inode needs layoutcommit
NLM: Don't hang forever on NLM unlock requests
NFS: fix umount of pnfs filesystems
Diffstat (limited to 'fs')
-rw-r--r-- | fs/lockd/clntproc.c | 8 | ||||
-rw-r--r-- | fs/nfs/inode.c | 6 | ||||
-rw-r--r-- | fs/nfs/internal.h | 11 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayout.c | 21 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 45 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 26 | ||||
-rw-r--r-- | fs/nfs/objlayout/objio_osd.c | 4 | ||||
-rw-r--r-- | fs/nfs/objlayout/objlayout.c | 2 | ||||
-rw-r--r-- | fs/nfs/pagelist.c | 3 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 44 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 1 | ||||
-rw-r--r-- | fs/nfs/pnfs_dev.c | 17 |
12 files changed, 127 insertions, 61 deletions
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index adb45ec9038c..e374050a911c 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c | |||
@@ -708,7 +708,13 @@ static void nlmclnt_unlock_callback(struct rpc_task *task, void *data) | |||
708 | 708 | ||
709 | if (task->tk_status < 0) { | 709 | if (task->tk_status < 0) { |
710 | dprintk("lockd: unlock failed (err = %d)\n", -task->tk_status); | 710 | dprintk("lockd: unlock failed (err = %d)\n", -task->tk_status); |
711 | goto retry_rebind; | 711 | switch (task->tk_status) { |
712 | case -EACCES: | ||
713 | case -EIO: | ||
714 | goto die; | ||
715 | default: | ||
716 | goto retry_rebind; | ||
717 | } | ||
712 | } | 718 | } |
713 | if (status == NLM_LCK_DENIED_GRACE_PERIOD) { | 719 | if (status == NLM_LCK_DENIED_GRACE_PERIOD) { |
714 | rpc_delay(task, NLMCLNT_GRACE_WAIT); | 720 | rpc_delay(task, NLMCLNT_GRACE_WAIT); |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 144f2a3c7185..6f4850deb272 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -256,7 +256,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
256 | 256 | ||
257 | nfs_attr_check_mountpoint(sb, fattr); | 257 | nfs_attr_check_mountpoint(sb, fattr); |
258 | 258 | ||
259 | if ((fattr->valid & NFS_ATTR_FATTR_FILEID) == 0 && (fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT) == 0) | 259 | if (((fattr->valid & NFS_ATTR_FATTR_FILEID) == 0) && |
260 | !nfs_attr_use_mounted_on_fileid(fattr)) | ||
260 | goto out_no_inode; | 261 | goto out_no_inode; |
261 | if ((fattr->valid & NFS_ATTR_FATTR_TYPE) == 0) | 262 | if ((fattr->valid & NFS_ATTR_FATTR_TYPE) == 0) |
262 | goto out_no_inode; | 263 | goto out_no_inode; |
@@ -1294,7 +1295,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1294 | if (new_isize != cur_isize) { | 1295 | if (new_isize != cur_isize) { |
1295 | /* Do we perhaps have any outstanding writes, or has | 1296 | /* Do we perhaps have any outstanding writes, or has |
1296 | * the file grown beyond our last write? */ | 1297 | * the file grown beyond our last write? */ |
1297 | if (nfsi->npages == 0 || new_isize > cur_isize) { | 1298 | if ((nfsi->npages == 0 && !test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) || |
1299 | new_isize > cur_isize) { | ||
1298 | i_size_write(inode, new_isize); | 1300 | i_size_write(inode, new_isize); |
1299 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1301 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
1300 | } | 1302 | } |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index b9056cbe68d6..2a55347a2daa 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -45,6 +45,17 @@ static inline void nfs_attr_check_mountpoint(struct super_block *parent, struct | |||
45 | fattr->valid |= NFS_ATTR_FATTR_MOUNTPOINT; | 45 | fattr->valid |= NFS_ATTR_FATTR_MOUNTPOINT; |
46 | } | 46 | } |
47 | 47 | ||
48 | static inline int nfs_attr_use_mounted_on_fileid(struct nfs_fattr *fattr) | ||
49 | { | ||
50 | if (((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) == 0) || | ||
51 | (((fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT) == 0) && | ||
52 | ((fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) == 0))) | ||
53 | return 0; | ||
54 | |||
55 | fattr->fileid = fattr->mounted_on_fileid; | ||
56 | return 1; | ||
57 | } | ||
58 | |||
48 | struct nfs_clone_mount { | 59 | struct nfs_clone_mount { |
49 | const struct super_block *sb; | 60 | const struct super_block *sb; |
50 | const struct dentry *dentry; | 61 | const struct dentry *dentry; |
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 426908809c97..0bafcc91c27f 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
@@ -30,6 +30,7 @@ | |||
30 | */ | 30 | */ |
31 | 31 | ||
32 | #include <linux/nfs_fs.h> | 32 | #include <linux/nfs_fs.h> |
33 | #include <linux/nfs_page.h> | ||
33 | 34 | ||
34 | #include "internal.h" | 35 | #include "internal.h" |
35 | #include "nfs4filelayout.h" | 36 | #include "nfs4filelayout.h" |
@@ -552,13 +553,18 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo, | |||
552 | __func__, nfl_util, fl->num_fh, fl->first_stripe_index, | 553 | __func__, nfl_util, fl->num_fh, fl->first_stripe_index, |
553 | fl->pattern_offset); | 554 | fl->pattern_offset); |
554 | 555 | ||
555 | if (!fl->num_fh) | 556 | /* Note that a zero value for num_fh is legal for STRIPE_SPARSE. |
557 | * Futher checking is done in filelayout_check_layout */ | ||
558 | if (fl->num_fh < 0 || fl->num_fh > | ||
559 | max(NFS4_PNFS_MAX_STRIPE_CNT, NFS4_PNFS_MAX_MULTI_CNT)) | ||
556 | goto out_err; | 560 | goto out_err; |
557 | 561 | ||
558 | fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *), | 562 | if (fl->num_fh > 0) { |
559 | gfp_flags); | 563 | fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *), |
560 | if (!fl->fh_array) | 564 | gfp_flags); |
561 | goto out_err; | 565 | if (!fl->fh_array) |
566 | goto out_err; | ||
567 | } | ||
562 | 568 | ||
563 | for (i = 0; i < fl->num_fh; i++) { | 569 | for (i = 0; i < fl->num_fh; i++) { |
564 | /* Do we want to use a mempool here? */ | 570 | /* Do we want to use a mempool here? */ |
@@ -661,8 +667,9 @@ filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, | |||
661 | u64 p_stripe, r_stripe; | 667 | u64 p_stripe, r_stripe; |
662 | u32 stripe_unit; | 668 | u32 stripe_unit; |
663 | 669 | ||
664 | if (!pnfs_generic_pg_test(pgio, prev, req)) | 670 | if (!pnfs_generic_pg_test(pgio, prev, req) || |
665 | return 0; | 671 | !nfs_generic_pg_test(pgio, prev, req)) |
672 | return false; | ||
666 | 673 | ||
667 | if (!pgio->pg_lseg) | 674 | if (!pgio->pg_lseg) |
668 | return 1; | 675 | return 1; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index d2c4b59c896d..5879b23e0c99 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -2265,12 +2265,14 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2265 | return nfs4_map_errors(status); | 2265 | return nfs4_map_errors(status); |
2266 | } | 2266 | } |
2267 | 2267 | ||
2268 | static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr); | ||
2268 | /* | 2269 | /* |
2269 | * Get locations and (maybe) other attributes of a referral. | 2270 | * Get locations and (maybe) other attributes of a referral. |
2270 | * Note that we'll actually follow the referral later when | 2271 | * Note that we'll actually follow the referral later when |
2271 | * we detect fsid mismatch in inode revalidation | 2272 | * we detect fsid mismatch in inode revalidation |
2272 | */ | 2273 | */ |
2273 | static int nfs4_get_referral(struct inode *dir, const struct qstr *name, struct nfs_fattr *fattr, struct nfs_fh *fhandle) | 2274 | static int nfs4_get_referral(struct inode *dir, const struct qstr *name, |
2275 | struct nfs_fattr *fattr, struct nfs_fh *fhandle) | ||
2274 | { | 2276 | { |
2275 | int status = -ENOMEM; | 2277 | int status = -ENOMEM; |
2276 | struct page *page = NULL; | 2278 | struct page *page = NULL; |
@@ -2288,15 +2290,16 @@ static int nfs4_get_referral(struct inode *dir, const struct qstr *name, struct | |||
2288 | goto out; | 2290 | goto out; |
2289 | /* Make sure server returned a different fsid for the referral */ | 2291 | /* Make sure server returned a different fsid for the referral */ |
2290 | if (nfs_fsid_equal(&NFS_SERVER(dir)->fsid, &locations->fattr.fsid)) { | 2292 | if (nfs_fsid_equal(&NFS_SERVER(dir)->fsid, &locations->fattr.fsid)) { |
2291 | dprintk("%s: server did not return a different fsid for a referral at %s\n", __func__, name->name); | 2293 | dprintk("%s: server did not return a different fsid for" |
2294 | " a referral at %s\n", __func__, name->name); | ||
2292 | status = -EIO; | 2295 | status = -EIO; |
2293 | goto out; | 2296 | goto out; |
2294 | } | 2297 | } |
2298 | /* Fixup attributes for the nfs_lookup() call to nfs_fhget() */ | ||
2299 | nfs_fixup_referral_attributes(&locations->fattr); | ||
2295 | 2300 | ||
2301 | /* replace the lookup nfs_fattr with the locations nfs_fattr */ | ||
2296 | memcpy(fattr, &locations->fattr, sizeof(struct nfs_fattr)); | 2302 | memcpy(fattr, &locations->fattr, sizeof(struct nfs_fattr)); |
2297 | fattr->valid |= NFS_ATTR_FATTR_V4_REFERRAL; | ||
2298 | if (!fattr->mode) | ||
2299 | fattr->mode = S_IFDIR; | ||
2300 | memset(fhandle, 0, sizeof(struct nfs_fh)); | 2303 | memset(fhandle, 0, sizeof(struct nfs_fh)); |
2301 | out: | 2304 | out: |
2302 | if (page) | 2305 | if (page) |
@@ -4667,11 +4670,15 @@ static size_t nfs4_xattr_list_nfs4_acl(struct dentry *dentry, char *list, | |||
4667 | return len; | 4670 | return len; |
4668 | } | 4671 | } |
4669 | 4672 | ||
4673 | /* | ||
4674 | * nfs_fhget will use either the mounted_on_fileid or the fileid | ||
4675 | */ | ||
4670 | static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr) | 4676 | static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr) |
4671 | { | 4677 | { |
4672 | if (!((fattr->valid & NFS_ATTR_FATTR_FILEID) && | 4678 | if (!(((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) || |
4673 | (fattr->valid & NFS_ATTR_FATTR_FSID) && | 4679 | (fattr->valid & NFS_ATTR_FATTR_FILEID)) && |
4674 | (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL))) | 4680 | (fattr->valid & NFS_ATTR_FATTR_FSID) && |
4681 | (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL))) | ||
4675 | return; | 4682 | return; |
4676 | 4683 | ||
4677 | fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE | | 4684 | fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE | |
@@ -4686,7 +4693,6 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, | |||
4686 | struct nfs_server *server = NFS_SERVER(dir); | 4693 | struct nfs_server *server = NFS_SERVER(dir); |
4687 | u32 bitmask[2] = { | 4694 | u32 bitmask[2] = { |
4688 | [0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS, | 4695 | [0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS, |
4689 | [1] = FATTR4_WORD1_MOUNTED_ON_FILEID, | ||
4690 | }; | 4696 | }; |
4691 | struct nfs4_fs_locations_arg args = { | 4697 | struct nfs4_fs_locations_arg args = { |
4692 | .dir_fh = NFS_FH(dir), | 4698 | .dir_fh = NFS_FH(dir), |
@@ -4705,11 +4711,18 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, | |||
4705 | int status; | 4711 | int status; |
4706 | 4712 | ||
4707 | dprintk("%s: start\n", __func__); | 4713 | dprintk("%s: start\n", __func__); |
4714 | |||
4715 | /* Ask for the fileid of the absent filesystem if mounted_on_fileid | ||
4716 | * is not supported */ | ||
4717 | if (NFS_SERVER(dir)->attr_bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID) | ||
4718 | bitmask[1] |= FATTR4_WORD1_MOUNTED_ON_FILEID; | ||
4719 | else | ||
4720 | bitmask[0] |= FATTR4_WORD0_FILEID; | ||
4721 | |||
4708 | nfs_fattr_init(&fs_locations->fattr); | 4722 | nfs_fattr_init(&fs_locations->fattr); |
4709 | fs_locations->server = server; | 4723 | fs_locations->server = server; |
4710 | fs_locations->nlocations = 0; | 4724 | fs_locations->nlocations = 0; |
4711 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); | 4725 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); |
4712 | nfs_fixup_referral_attributes(&fs_locations->fattr); | ||
4713 | dprintk("%s: returned status = %d\n", __func__, status); | 4726 | dprintk("%s: returned status = %d\n", __func__, status); |
4714 | return status; | 4727 | return status; |
4715 | } | 4728 | } |
@@ -5098,7 +5111,6 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args) | |||
5098 | if (mxresp_sz == 0) | 5111 | if (mxresp_sz == 0) |
5099 | mxresp_sz = NFS_MAX_FILE_IO_SIZE; | 5112 | mxresp_sz = NFS_MAX_FILE_IO_SIZE; |
5100 | /* Fore channel attributes */ | 5113 | /* Fore channel attributes */ |
5101 | args->fc_attrs.headerpadsz = 0; | ||
5102 | args->fc_attrs.max_rqst_sz = mxrqst_sz; | 5114 | args->fc_attrs.max_rqst_sz = mxrqst_sz; |
5103 | args->fc_attrs.max_resp_sz = mxresp_sz; | 5115 | args->fc_attrs.max_resp_sz = mxresp_sz; |
5104 | args->fc_attrs.max_ops = NFS4_MAX_OPS; | 5116 | args->fc_attrs.max_ops = NFS4_MAX_OPS; |
@@ -5111,7 +5123,6 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args) | |||
5111 | args->fc_attrs.max_ops, args->fc_attrs.max_reqs); | 5123 | args->fc_attrs.max_ops, args->fc_attrs.max_reqs); |
5112 | 5124 | ||
5113 | /* Back channel attributes */ | 5125 | /* Back channel attributes */ |
5114 | args->bc_attrs.headerpadsz = 0; | ||
5115 | args->bc_attrs.max_rqst_sz = PAGE_SIZE; | 5126 | args->bc_attrs.max_rqst_sz = PAGE_SIZE; |
5116 | args->bc_attrs.max_resp_sz = PAGE_SIZE; | 5127 | args->bc_attrs.max_resp_sz = PAGE_SIZE; |
5117 | args->bc_attrs.max_resp_sz_cached = 0; | 5128 | args->bc_attrs.max_resp_sz_cached = 0; |
@@ -5131,8 +5142,6 @@ static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args | |||
5131 | struct nfs4_channel_attrs *sent = &args->fc_attrs; | 5142 | struct nfs4_channel_attrs *sent = &args->fc_attrs; |
5132 | struct nfs4_channel_attrs *rcvd = &session->fc_attrs; | 5143 | struct nfs4_channel_attrs *rcvd = &session->fc_attrs; |
5133 | 5144 | ||
5134 | if (rcvd->headerpadsz > sent->headerpadsz) | ||
5135 | return -EINVAL; | ||
5136 | if (rcvd->max_resp_sz > sent->max_resp_sz) | 5145 | if (rcvd->max_resp_sz > sent->max_resp_sz) |
5137 | return -EINVAL; | 5146 | return -EINVAL; |
5138 | /* | 5147 | /* |
@@ -5697,6 +5706,7 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) | |||
5697 | { | 5706 | { |
5698 | struct nfs4_layoutreturn *lrp = calldata; | 5707 | struct nfs4_layoutreturn *lrp = calldata; |
5699 | struct nfs_server *server; | 5708 | struct nfs_server *server; |
5709 | struct pnfs_layout_hdr *lo = NFS_I(lrp->args.inode)->layout; | ||
5700 | 5710 | ||
5701 | dprintk("--> %s\n", __func__); | 5711 | dprintk("--> %s\n", __func__); |
5702 | 5712 | ||
@@ -5708,16 +5718,15 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) | |||
5708 | nfs_restart_rpc(task, lrp->clp); | 5718 | nfs_restart_rpc(task, lrp->clp); |
5709 | return; | 5719 | return; |
5710 | } | 5720 | } |
5721 | spin_lock(&lo->plh_inode->i_lock); | ||
5711 | if (task->tk_status == 0) { | 5722 | if (task->tk_status == 0) { |
5712 | struct pnfs_layout_hdr *lo = NFS_I(lrp->args.inode)->layout; | ||
5713 | |||
5714 | if (lrp->res.lrs_present) { | 5723 | if (lrp->res.lrs_present) { |
5715 | spin_lock(&lo->plh_inode->i_lock); | ||
5716 | pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); | 5724 | pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); |
5717 | spin_unlock(&lo->plh_inode->i_lock); | ||
5718 | } else | 5725 | } else |
5719 | BUG_ON(!list_empty(&lo->plh_segs)); | 5726 | BUG_ON(!list_empty(&lo->plh_segs)); |
5720 | } | 5727 | } |
5728 | lo->plh_block_lgets--; | ||
5729 | spin_unlock(&lo->plh_inode->i_lock); | ||
5721 | dprintk("<-- %s\n", __func__); | 5730 | dprintk("<-- %s\n", __func__); |
5722 | } | 5731 | } |
5723 | 5732 | ||
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index d869a5e5464b..6870bc61ceec 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -255,7 +255,7 @@ static int nfs4_stat_to_errno(int); | |||
255 | #define decode_fs_locations_maxsz \ | 255 | #define decode_fs_locations_maxsz \ |
256 | (0) | 256 | (0) |
257 | #define encode_secinfo_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) | 257 | #define encode_secinfo_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) |
258 | #define decode_secinfo_maxsz (op_decode_hdr_maxsz + 4 + (NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN))) | 258 | #define decode_secinfo_maxsz (op_decode_hdr_maxsz + 1 + ((NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN)) / 4)) |
259 | 259 | ||
260 | #if defined(CONFIG_NFS_V4_1) | 260 | #if defined(CONFIG_NFS_V4_1) |
261 | #define NFS4_MAX_MACHINE_NAME_LEN (64) | 261 | #define NFS4_MAX_MACHINE_NAME_LEN (64) |
@@ -1725,7 +1725,7 @@ static void encode_create_session(struct xdr_stream *xdr, | |||
1725 | *p++ = cpu_to_be32(args->flags); /*flags */ | 1725 | *p++ = cpu_to_be32(args->flags); /*flags */ |
1726 | 1726 | ||
1727 | /* Fore Channel */ | 1727 | /* Fore Channel */ |
1728 | *p++ = cpu_to_be32(args->fc_attrs.headerpadsz); /* header padding size */ | 1728 | *p++ = cpu_to_be32(0); /* header padding size */ |
1729 | *p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz); /* max req size */ | 1729 | *p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz); /* max req size */ |
1730 | *p++ = cpu_to_be32(args->fc_attrs.max_resp_sz); /* max resp size */ | 1730 | *p++ = cpu_to_be32(args->fc_attrs.max_resp_sz); /* max resp size */ |
1731 | *p++ = cpu_to_be32(max_resp_sz_cached); /* Max resp sz cached */ | 1731 | *p++ = cpu_to_be32(max_resp_sz_cached); /* Max resp sz cached */ |
@@ -1734,7 +1734,7 @@ static void encode_create_session(struct xdr_stream *xdr, | |||
1734 | *p++ = cpu_to_be32(0); /* rdmachannel_attrs */ | 1734 | *p++ = cpu_to_be32(0); /* rdmachannel_attrs */ |
1735 | 1735 | ||
1736 | /* Back Channel */ | 1736 | /* Back Channel */ |
1737 | *p++ = cpu_to_be32(args->fc_attrs.headerpadsz); /* header padding size */ | 1737 | *p++ = cpu_to_be32(0); /* header padding size */ |
1738 | *p++ = cpu_to_be32(args->bc_attrs.max_rqst_sz); /* max req size */ | 1738 | *p++ = cpu_to_be32(args->bc_attrs.max_rqst_sz); /* max req size */ |
1739 | *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz); /* max resp size */ | 1739 | *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz); /* max resp size */ |
1740 | *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz_cached); /* Max resp sz cached */ | 1740 | *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz_cached); /* Max resp sz cached */ |
@@ -3098,7 +3098,7 @@ out_overflow: | |||
3098 | return -EIO; | 3098 | return -EIO; |
3099 | } | 3099 | } |
3100 | 3100 | ||
3101 | static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap) | 3101 | static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap, int32_t *res) |
3102 | { | 3102 | { |
3103 | __be32 *p; | 3103 | __be32 *p; |
3104 | 3104 | ||
@@ -3109,7 +3109,7 @@ static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap) | |||
3109 | if (unlikely(!p)) | 3109 | if (unlikely(!p)) |
3110 | goto out_overflow; | 3110 | goto out_overflow; |
3111 | bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; | 3111 | bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; |
3112 | return -be32_to_cpup(p); | 3112 | *res = -be32_to_cpup(p); |
3113 | } | 3113 | } |
3114 | return 0; | 3114 | return 0; |
3115 | out_overflow: | 3115 | out_overflow: |
@@ -4070,6 +4070,7 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4070 | int status; | 4070 | int status; |
4071 | umode_t fmode = 0; | 4071 | umode_t fmode = 0; |
4072 | uint32_t type; | 4072 | uint32_t type; |
4073 | int32_t err; | ||
4073 | 4074 | ||
4074 | status = decode_attr_type(xdr, bitmap, &type); | 4075 | status = decode_attr_type(xdr, bitmap, &type); |
4075 | if (status < 0) | 4076 | if (status < 0) |
@@ -4095,13 +4096,12 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4095 | goto xdr_error; | 4096 | goto xdr_error; |
4096 | fattr->valid |= status; | 4097 | fattr->valid |= status; |
4097 | 4098 | ||
4098 | status = decode_attr_error(xdr, bitmap); | 4099 | err = 0; |
4099 | if (status == -NFS4ERR_WRONGSEC) { | 4100 | status = decode_attr_error(xdr, bitmap, &err); |
4100 | nfs_fixup_secinfo_attributes(fattr, fh); | ||
4101 | status = 0; | ||
4102 | } | ||
4103 | if (status < 0) | 4101 | if (status < 0) |
4104 | goto xdr_error; | 4102 | goto xdr_error; |
4103 | if (err == -NFS4ERR_WRONGSEC) | ||
4104 | nfs_fixup_secinfo_attributes(fattr, fh); | ||
4105 | 4105 | ||
4106 | status = decode_attr_filehandle(xdr, bitmap, fh); | 4106 | status = decode_attr_filehandle(xdr, bitmap, fh); |
4107 | if (status < 0) | 4107 | if (status < 0) |
@@ -4997,12 +4997,14 @@ static int decode_chan_attrs(struct xdr_stream *xdr, | |||
4997 | struct nfs4_channel_attrs *attrs) | 4997 | struct nfs4_channel_attrs *attrs) |
4998 | { | 4998 | { |
4999 | __be32 *p; | 4999 | __be32 *p; |
5000 | u32 nr_attrs; | 5000 | u32 nr_attrs, val; |
5001 | 5001 | ||
5002 | p = xdr_inline_decode(xdr, 28); | 5002 | p = xdr_inline_decode(xdr, 28); |
5003 | if (unlikely(!p)) | 5003 | if (unlikely(!p)) |
5004 | goto out_overflow; | 5004 | goto out_overflow; |
5005 | attrs->headerpadsz = be32_to_cpup(p++); | 5005 | val = be32_to_cpup(p++); /* headerpadsz */ |
5006 | if (val) | ||
5007 | return -EINVAL; /* no support for header padding yet */ | ||
5006 | attrs->max_rqst_sz = be32_to_cpup(p++); | 5008 | attrs->max_rqst_sz = be32_to_cpup(p++); |
5007 | attrs->max_resp_sz = be32_to_cpup(p++); | 5009 | attrs->max_resp_sz = be32_to_cpup(p++); |
5008 | attrs->max_resp_sz_cached = be32_to_cpup(p++); | 5010 | attrs->max_resp_sz_cached = be32_to_cpup(p++); |
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index 9cf208df1f25..8ff2ea3f10ef 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c | |||
@@ -108,7 +108,6 @@ _dev_list_add(const struct nfs_server *nfss, | |||
108 | de = n; | 108 | de = n; |
109 | } | 109 | } |
110 | 110 | ||
111 | atomic_inc(&de->id_node.ref); | ||
112 | return de; | 111 | return de; |
113 | } | 112 | } |
114 | 113 | ||
@@ -1001,6 +1000,9 @@ static bool objio_pg_test(struct nfs_pageio_descriptor *pgio, | |||
1001 | if (!pnfs_generic_pg_test(pgio, prev, req)) | 1000 | if (!pnfs_generic_pg_test(pgio, prev, req)) |
1002 | return false; | 1001 | return false; |
1003 | 1002 | ||
1003 | if (pgio->pg_lseg == NULL) | ||
1004 | return true; | ||
1005 | |||
1004 | return pgio->pg_count + req->wb_bytes <= | 1006 | return pgio->pg_count + req->wb_bytes <= |
1005 | OBJIO_LSEG(pgio->pg_lseg)->max_io_size; | 1007 | OBJIO_LSEG(pgio->pg_lseg)->max_io_size; |
1006 | } | 1008 | } |
diff --git a/fs/nfs/objlayout/objlayout.c b/fs/nfs/objlayout/objlayout.c index dc3956c0de80..1d06f8e2adea 100644 --- a/fs/nfs/objlayout/objlayout.c +++ b/fs/nfs/objlayout/objlayout.c | |||
@@ -291,7 +291,7 @@ objlayout_read_done(struct objlayout_io_state *state, ssize_t status, bool sync) | |||
291 | struct nfs_read_data *rdata; | 291 | struct nfs_read_data *rdata; |
292 | 292 | ||
293 | state->status = status; | 293 | state->status = status; |
294 | dprintk("%s: Begin status=%ld eof=%d\n", __func__, status, eof); | 294 | dprintk("%s: Begin status=%zd eof=%d\n", __func__, status, eof); |
295 | rdata = state->rpcdata; | 295 | rdata = state->rpcdata; |
296 | rdata->task.tk_status = status; | 296 | rdata->task.tk_status = status; |
297 | if (status >= 0) { | 297 | if (status >= 0) { |
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 7913961aff22..009855716286 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -204,7 +204,7 @@ nfs_wait_on_request(struct nfs_page *req) | |||
204 | TASK_UNINTERRUPTIBLE); | 204 | TASK_UNINTERRUPTIBLE); |
205 | } | 205 | } |
206 | 206 | ||
207 | static bool nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, struct nfs_page *prev, struct nfs_page *req) | 207 | bool nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, struct nfs_page *prev, struct nfs_page *req) |
208 | { | 208 | { |
209 | /* | 209 | /* |
210 | * FIXME: ideally we should be able to coalesce all requests | 210 | * FIXME: ideally we should be able to coalesce all requests |
@@ -218,6 +218,7 @@ static bool nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, struct nfs_p | |||
218 | 218 | ||
219 | return desc->pg_count + req->wb_bytes <= desc->pg_bsize; | 219 | return desc->pg_count + req->wb_bytes <= desc->pg_bsize; |
220 | } | 220 | } |
221 | EXPORT_SYMBOL_GPL(nfs_generic_pg_test); | ||
221 | 222 | ||
222 | /** | 223 | /** |
223 | * nfs_pageio_init - initialise a page io descriptor | 224 | * nfs_pageio_init - initialise a page io descriptor |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 8c1309d852a6..29c0ca7fc347 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -634,14 +634,16 @@ _pnfs_return_layout(struct inode *ino) | |||
634 | 634 | ||
635 | spin_lock(&ino->i_lock); | 635 | spin_lock(&ino->i_lock); |
636 | lo = nfsi->layout; | 636 | lo = nfsi->layout; |
637 | if (!lo || !mark_matching_lsegs_invalid(lo, &tmp_list, NULL)) { | 637 | if (!lo) { |
638 | spin_unlock(&ino->i_lock); | 638 | spin_unlock(&ino->i_lock); |
639 | dprintk("%s: no layout segments to return\n", __func__); | 639 | dprintk("%s: no layout to return\n", __func__); |
640 | goto out; | 640 | return status; |
641 | } | 641 | } |
642 | stateid = nfsi->layout->plh_stateid; | 642 | stateid = nfsi->layout->plh_stateid; |
643 | /* Reference matched in nfs4_layoutreturn_release */ | 643 | /* Reference matched in nfs4_layoutreturn_release */ |
644 | get_layout_hdr(lo); | 644 | get_layout_hdr(lo); |
645 | mark_matching_lsegs_invalid(lo, &tmp_list, NULL); | ||
646 | lo->plh_block_lgets++; | ||
645 | spin_unlock(&ino->i_lock); | 647 | spin_unlock(&ino->i_lock); |
646 | pnfs_free_lseg_list(&tmp_list); | 648 | pnfs_free_lseg_list(&tmp_list); |
647 | 649 | ||
@@ -650,6 +652,9 @@ _pnfs_return_layout(struct inode *ino) | |||
650 | lrp = kzalloc(sizeof(*lrp), GFP_KERNEL); | 652 | lrp = kzalloc(sizeof(*lrp), GFP_KERNEL); |
651 | if (unlikely(lrp == NULL)) { | 653 | if (unlikely(lrp == NULL)) { |
652 | status = -ENOMEM; | 654 | status = -ENOMEM; |
655 | set_bit(NFS_LAYOUT_RW_FAILED, &lo->plh_flags); | ||
656 | set_bit(NFS_LAYOUT_RO_FAILED, &lo->plh_flags); | ||
657 | put_layout_hdr(lo); | ||
653 | goto out; | 658 | goto out; |
654 | } | 659 | } |
655 | 660 | ||
@@ -887,7 +892,7 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo, | |||
887 | ret = get_lseg(lseg); | 892 | ret = get_lseg(lseg); |
888 | break; | 893 | break; |
889 | } | 894 | } |
890 | if (cmp_layout(range, &lseg->pls_range) > 0) | 895 | if (lseg->pls_range.offset > range->offset) |
891 | break; | 896 | break; |
892 | } | 897 | } |
893 | 898 | ||
@@ -1059,23 +1064,36 @@ pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, | |||
1059 | gfp_flags = GFP_NOFS; | 1064 | gfp_flags = GFP_NOFS; |
1060 | } | 1065 | } |
1061 | 1066 | ||
1062 | if (pgio->pg_count == prev->wb_bytes) { | 1067 | if (pgio->pg_lseg == NULL) { |
1068 | if (pgio->pg_count != prev->wb_bytes) | ||
1069 | return true; | ||
1063 | /* This is first coelesce call for a series of nfs_pages */ | 1070 | /* This is first coelesce call for a series of nfs_pages */ |
1064 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | 1071 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, |
1065 | prev->wb_context, | 1072 | prev->wb_context, |
1066 | req_offset(req), | 1073 | req_offset(prev), |
1067 | pgio->pg_count, | 1074 | pgio->pg_count, |
1068 | access_type, | 1075 | access_type, |
1069 | gfp_flags); | 1076 | gfp_flags); |
1070 | return true; | 1077 | if (pgio->pg_lseg == NULL) |
1078 | return true; | ||
1071 | } | 1079 | } |
1072 | 1080 | ||
1073 | if (pgio->pg_lseg && | 1081 | /* |
1074 | req_offset(req) > end_offset(pgio->pg_lseg->pls_range.offset, | 1082 | * Test if a nfs_page is fully contained in the pnfs_layout_range. |
1075 | pgio->pg_lseg->pls_range.length)) | 1083 | * Note that this test makes several assumptions: |
1076 | return false; | 1084 | * - that the previous nfs_page in the struct nfs_pageio_descriptor |
1077 | 1085 | * is known to lie within the range. | |
1078 | return true; | 1086 | * - that the nfs_page being tested is known to be contiguous with the |
1087 | * previous nfs_page. | ||
1088 | * - Layout ranges are page aligned, so we only have to test the | ||
1089 | * start offset of the request. | ||
1090 | * | ||
1091 | * Please also note that 'end_offset' is actually the offset of the | ||
1092 | * first byte that lies outside the pnfs_layout_range. FIXME? | ||
1093 | * | ||
1094 | */ | ||
1095 | return req_offset(req) < end_offset(pgio->pg_lseg->pls_range.offset, | ||
1096 | pgio->pg_lseg->pls_range.length); | ||
1079 | } | 1097 | } |
1080 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_test); | 1098 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_test); |
1081 | 1099 | ||
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 48d0a8e4d062..96bf4e6f45be 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -186,6 +186,7 @@ int pnfs_ld_read_done(struct nfs_read_data *); | |||
186 | /* pnfs_dev.c */ | 186 | /* pnfs_dev.c */ |
187 | struct nfs4_deviceid_node { | 187 | struct nfs4_deviceid_node { |
188 | struct hlist_node node; | 188 | struct hlist_node node; |
189 | struct hlist_node tmpnode; | ||
189 | const struct pnfs_layoutdriver_type *ld; | 190 | const struct pnfs_layoutdriver_type *ld; |
190 | const struct nfs_client *nfs_client; | 191 | const struct nfs_client *nfs_client; |
191 | struct nfs4_deviceid deviceid; | 192 | struct nfs4_deviceid deviceid; |
diff --git a/fs/nfs/pnfs_dev.c b/fs/nfs/pnfs_dev.c index c65e133ce9c0..f0f8e1e22f6c 100644 --- a/fs/nfs/pnfs_dev.c +++ b/fs/nfs/pnfs_dev.c | |||
@@ -174,6 +174,7 @@ nfs4_init_deviceid_node(struct nfs4_deviceid_node *d, | |||
174 | const struct nfs4_deviceid *id) | 174 | const struct nfs4_deviceid *id) |
175 | { | 175 | { |
176 | INIT_HLIST_NODE(&d->node); | 176 | INIT_HLIST_NODE(&d->node); |
177 | INIT_HLIST_NODE(&d->tmpnode); | ||
177 | d->ld = ld; | 178 | d->ld = ld; |
178 | d->nfs_client = nfs_client; | 179 | d->nfs_client = nfs_client; |
179 | d->deviceid = *id; | 180 | d->deviceid = *id; |
@@ -208,6 +209,7 @@ nfs4_insert_deviceid_node(struct nfs4_deviceid_node *new) | |||
208 | 209 | ||
209 | hlist_add_head_rcu(&new->node, &nfs4_deviceid_cache[hash]); | 210 | hlist_add_head_rcu(&new->node, &nfs4_deviceid_cache[hash]); |
210 | spin_unlock(&nfs4_deviceid_lock); | 211 | spin_unlock(&nfs4_deviceid_lock); |
212 | atomic_inc(&new->ref); | ||
211 | 213 | ||
212 | return new; | 214 | return new; |
213 | } | 215 | } |
@@ -238,24 +240,29 @@ static void | |||
238 | _deviceid_purge_client(const struct nfs_client *clp, long hash) | 240 | _deviceid_purge_client(const struct nfs_client *clp, long hash) |
239 | { | 241 | { |
240 | struct nfs4_deviceid_node *d; | 242 | struct nfs4_deviceid_node *d; |
241 | struct hlist_node *n, *next; | 243 | struct hlist_node *n; |
242 | HLIST_HEAD(tmp); | 244 | HLIST_HEAD(tmp); |
243 | 245 | ||
246 | spin_lock(&nfs4_deviceid_lock); | ||
244 | rcu_read_lock(); | 247 | rcu_read_lock(); |
245 | hlist_for_each_entry_rcu(d, n, &nfs4_deviceid_cache[hash], node) | 248 | hlist_for_each_entry_rcu(d, n, &nfs4_deviceid_cache[hash], node) |
246 | if (d->nfs_client == clp && atomic_read(&d->ref)) { | 249 | if (d->nfs_client == clp && atomic_read(&d->ref)) { |
247 | hlist_del_init_rcu(&d->node); | 250 | hlist_del_init_rcu(&d->node); |
248 | hlist_add_head(&d->node, &tmp); | 251 | hlist_add_head(&d->tmpnode, &tmp); |
249 | } | 252 | } |
250 | rcu_read_unlock(); | 253 | rcu_read_unlock(); |
254 | spin_unlock(&nfs4_deviceid_lock); | ||
251 | 255 | ||
252 | if (hlist_empty(&tmp)) | 256 | if (hlist_empty(&tmp)) |
253 | return; | 257 | return; |
254 | 258 | ||
255 | synchronize_rcu(); | 259 | synchronize_rcu(); |
256 | hlist_for_each_entry_safe(d, n, next, &tmp, node) | 260 | while (!hlist_empty(&tmp)) { |
261 | d = hlist_entry(tmp.first, struct nfs4_deviceid_node, tmpnode); | ||
262 | hlist_del(&d->tmpnode); | ||
257 | if (atomic_dec_and_test(&d->ref)) | 263 | if (atomic_dec_and_test(&d->ref)) |
258 | d->ld->free_deviceid_node(d); | 264 | d->ld->free_deviceid_node(d); |
265 | } | ||
259 | } | 266 | } |
260 | 267 | ||
261 | void | 268 | void |
@@ -263,8 +270,8 @@ nfs4_deviceid_purge_client(const struct nfs_client *clp) | |||
263 | { | 270 | { |
264 | long h; | 271 | long h; |
265 | 272 | ||
266 | spin_lock(&nfs4_deviceid_lock); | 273 | if (!(clp->cl_exchange_flags & EXCHGID4_FLAG_USE_PNFS_MDS)) |
274 | return; | ||
267 | for (h = 0; h < NFS4_DEVICE_ID_HASH_SIZE; h++) | 275 | for (h = 0; h < NFS4_DEVICE_ID_HASH_SIZE; h++) |
268 | _deviceid_purge_client(clp, h); | 276 | _deviceid_purge_client(clp, h); |
269 | spin_unlock(&nfs4_deviceid_lock); | ||
270 | } | 277 | } |