diff options
author | Dave Airlie <airlied@redhat.com> | 2015-08-17 00:13:53 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2015-08-17 00:13:53 -0400 |
commit | 4eebf60b7452fbd551fd7dece855ba7825a49cbc (patch) | |
tree | 490b4d194ba09c90e10201ab7fc084a0bda0ed27 /fs/nfs | |
parent | 8f9cb50789e76f3e224e8861adf650e55c747af4 (diff) | |
parent | 2c6625cd545bdd66acff14f3394865d43920a5c7 (diff) |
Merge tag 'v4.2-rc7' into drm-next
Linux 4.2-rc7
Backmerge master for i915 fixes
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/client.c | 2 | ||||
-rw-r--r-- | fs/nfs/flexfilelayout/flexfilelayout.c | 2 | ||||
-rw-r--r-- | fs/nfs/inode.c | 15 | ||||
-rw-r--r-- | fs/nfs/internal.h | 21 | ||||
-rw-r--r-- | fs/nfs/nfs42proc.c | 19 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 36 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 29 | ||||
-rw-r--r-- | fs/nfs/pagelist.c | 7 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 101 | ||||
-rw-r--r-- | fs/nfs/write.c | 15 |
10 files changed, 160 insertions, 87 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index ecebb406cc1a..4a90c9bb3135 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -775,7 +775,7 @@ static int nfs_init_server(struct nfs_server *server, | |||
775 | server->options = data->options; | 775 | server->options = data->options; |
776 | server->caps |= NFS_CAP_HARDLINKS|NFS_CAP_SYMLINKS|NFS_CAP_FILEID| | 776 | server->caps |= NFS_CAP_HARDLINKS|NFS_CAP_SYMLINKS|NFS_CAP_FILEID| |
777 | NFS_CAP_MODE|NFS_CAP_NLINK|NFS_CAP_OWNER|NFS_CAP_OWNER_GROUP| | 777 | NFS_CAP_MODE|NFS_CAP_NLINK|NFS_CAP_OWNER|NFS_CAP_OWNER_GROUP| |
778 | NFS_CAP_ATIME|NFS_CAP_CTIME|NFS_CAP_MTIME|NFS_CAP_CHANGE_ATTR; | 778 | NFS_CAP_ATIME|NFS_CAP_CTIME|NFS_CAP_MTIME; |
779 | 779 | ||
780 | if (data->rsize) | 780 | if (data->rsize) |
781 | server->rsize = nfs_block_size(data->rsize, NULL); | 781 | server->rsize = nfs_block_size(data->rsize, NULL); |
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index c12951b9551e..b3289d701eea 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c | |||
@@ -1852,7 +1852,7 @@ ff_layout_mirror_prepare_stats(struct nfs42_layoutstat_args *args, | |||
1852 | struct nfs42_layoutstat_devinfo *devinfo; | 1852 | struct nfs42_layoutstat_devinfo *devinfo; |
1853 | int i; | 1853 | int i; |
1854 | 1854 | ||
1855 | for (i = 0; i <= FF_LAYOUT_MIRROR_COUNT(pls); i++) { | 1855 | for (i = 0; i < FF_LAYOUT_MIRROR_COUNT(pls); i++) { |
1856 | if (*dev_count >= dev_limit) | 1856 | if (*dev_count >= dev_limit) |
1857 | break; | 1857 | break; |
1858 | mirror = FF_LAYOUT_COMP(pls, i); | 1858 | mirror = FF_LAYOUT_COMP(pls, i); |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index b77b328a06d7..0adc7d245b3d 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -442,8 +442,9 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st | |||
442 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR); | 442 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR); |
443 | if (fattr->valid & NFS_ATTR_FATTR_CHANGE) | 443 | if (fattr->valid & NFS_ATTR_FATTR_CHANGE) |
444 | inode->i_version = fattr->change_attr; | 444 | inode->i_version = fattr->change_attr; |
445 | else if (nfs_server_capable(inode, NFS_CAP_CHANGE_ATTR)) | 445 | else |
446 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR); | 446 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR |
447 | | NFS_INO_REVAL_PAGECACHE); | ||
447 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) | 448 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) |
448 | inode->i_size = nfs_size_to_loff_t(fattr->size); | 449 | inode->i_size = nfs_size_to_loff_t(fattr->size); |
449 | else | 450 | else |
@@ -1244,9 +1245,11 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
1244 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) { | 1245 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) { |
1245 | cur_size = i_size_read(inode); | 1246 | cur_size = i_size_read(inode); |
1246 | new_isize = nfs_size_to_loff_t(fattr->size); | 1247 | new_isize = nfs_size_to_loff_t(fattr->size); |
1247 | if (cur_size != new_isize && nfsi->nrequests == 0) | 1248 | if (cur_size != new_isize) |
1248 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 1249 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; |
1249 | } | 1250 | } |
1251 | if (nfsi->nrequests != 0) | ||
1252 | invalid &= ~NFS_INO_REVAL_PAGECACHE; | ||
1250 | 1253 | ||
1251 | /* Have any file permissions changed? */ | 1254 | /* Have any file permissions changed? */ |
1252 | if ((fattr->valid & NFS_ATTR_FATTR_MODE) && (inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)) | 1255 | if ((fattr->valid & NFS_ATTR_FATTR_MODE) && (inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)) |
@@ -1684,13 +1687,12 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1684 | invalid |= NFS_INO_INVALID_ATTR | 1687 | invalid |= NFS_INO_INVALID_ATTR |
1685 | | NFS_INO_INVALID_DATA | 1688 | | NFS_INO_INVALID_DATA |
1686 | | NFS_INO_INVALID_ACCESS | 1689 | | NFS_INO_INVALID_ACCESS |
1687 | | NFS_INO_INVALID_ACL | 1690 | | NFS_INO_INVALID_ACL; |
1688 | | NFS_INO_REVAL_PAGECACHE; | ||
1689 | if (S_ISDIR(inode->i_mode)) | 1691 | if (S_ISDIR(inode->i_mode)) |
1690 | nfs_force_lookup_revalidate(inode); | 1692 | nfs_force_lookup_revalidate(inode); |
1691 | inode->i_version = fattr->change_attr; | 1693 | inode->i_version = fattr->change_attr; |
1692 | } | 1694 | } |
1693 | } else if (server->caps & NFS_CAP_CHANGE_ATTR) | 1695 | } else |
1694 | nfsi->cache_validity |= save_cache_validity; | 1696 | nfsi->cache_validity |= save_cache_validity; |
1695 | 1697 | ||
1696 | if (fattr->valid & NFS_ATTR_FATTR_MTIME) { | 1698 | if (fattr->valid & NFS_ATTR_FATTR_MTIME) { |
@@ -1717,7 +1719,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1717 | if ((nfsi->nrequests == 0) || new_isize > cur_isize) { | 1719 | if ((nfsi->nrequests == 0) || new_isize > cur_isize) { |
1718 | i_size_write(inode, new_isize); | 1720 | i_size_write(inode, new_isize); |
1719 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1721 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
1720 | invalid &= ~NFS_INO_REVAL_PAGECACHE; | ||
1721 | } | 1722 | } |
1722 | dprintk("NFS: isize change on server for file %s/%ld " | 1723 | dprintk("NFS: isize change on server for file %s/%ld " |
1723 | "(%Ld to %Ld)\n", | 1724 | "(%Ld to %Ld)\n", |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 7e3c4604bea8..9b372b845f6a 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -296,6 +296,22 @@ extern struct rpc_procinfo nfs4_procedures[]; | |||
296 | 296 | ||
297 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | 297 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL |
298 | extern struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags); | 298 | extern struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags); |
299 | static inline struct nfs4_label * | ||
300 | nfs4_label_copy(struct nfs4_label *dst, struct nfs4_label *src) | ||
301 | { | ||
302 | if (!dst || !src) | ||
303 | return NULL; | ||
304 | |||
305 | if (src->len > NFS4_MAXLABELLEN) | ||
306 | return NULL; | ||
307 | |||
308 | dst->lfs = src->lfs; | ||
309 | dst->pi = src->pi; | ||
310 | dst->len = src->len; | ||
311 | memcpy(dst->label, src->label, src->len); | ||
312 | |||
313 | return dst; | ||
314 | } | ||
299 | static inline void nfs4_label_free(struct nfs4_label *label) | 315 | static inline void nfs4_label_free(struct nfs4_label *label) |
300 | { | 316 | { |
301 | if (label) { | 317 | if (label) { |
@@ -316,6 +332,11 @@ static inline void nfs4_label_free(void *label) {} | |||
316 | static inline void nfs_zap_label_cache_locked(struct nfs_inode *nfsi) | 332 | static inline void nfs_zap_label_cache_locked(struct nfs_inode *nfsi) |
317 | { | 333 | { |
318 | } | 334 | } |
335 | static inline struct nfs4_label * | ||
336 | nfs4_label_copy(struct nfs4_label *dst, struct nfs4_label *src) | ||
337 | { | ||
338 | return NULL; | ||
339 | } | ||
319 | #endif /* CONFIG_NFS_V4_SECURITY_LABEL */ | 340 | #endif /* CONFIG_NFS_V4_SECURITY_LABEL */ |
320 | 341 | ||
321 | /* proc.c */ | 342 | /* proc.c */ |
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c index f486b80f927a..d731bbf974aa 100644 --- a/fs/nfs/nfs42proc.c +++ b/fs/nfs/nfs42proc.c | |||
@@ -135,7 +135,7 @@ int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len) | |||
135 | return err; | 135 | return err; |
136 | } | 136 | } |
137 | 137 | ||
138 | loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence) | 138 | static loff_t _nfs42_proc_llseek(struct file *filep, loff_t offset, int whence) |
139 | { | 139 | { |
140 | struct inode *inode = file_inode(filep); | 140 | struct inode *inode = file_inode(filep); |
141 | struct nfs42_seek_args args = { | 141 | struct nfs42_seek_args args = { |
@@ -171,6 +171,23 @@ loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence) | |||
171 | return vfs_setpos(filep, res.sr_offset, inode->i_sb->s_maxbytes); | 171 | return vfs_setpos(filep, res.sr_offset, inode->i_sb->s_maxbytes); |
172 | } | 172 | } |
173 | 173 | ||
174 | loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence) | ||
175 | { | ||
176 | struct nfs_server *server = NFS_SERVER(file_inode(filep)); | ||
177 | struct nfs4_exception exception = { }; | ||
178 | int err; | ||
179 | |||
180 | do { | ||
181 | err = _nfs42_proc_llseek(filep, offset, whence); | ||
182 | if (err == -ENOTSUPP) | ||
183 | return -EOPNOTSUPP; | ||
184 | err = nfs4_handle_exception(server, err, &exception); | ||
185 | } while (exception.retry); | ||
186 | |||
187 | return err; | ||
188 | } | ||
189 | |||
190 | |||
174 | static void | 191 | static void |
175 | nfs42_layoutstat_prepare(struct rpc_task *task, void *calldata) | 192 | nfs42_layoutstat_prepare(struct rpc_task *task, void *calldata) |
176 | { | 193 | { |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 8bee93469617..3acb1eb72930 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -467,7 +467,10 @@ static void do_renew_lease(struct nfs_client *clp, unsigned long timestamp) | |||
467 | 467 | ||
468 | static void renew_lease(const struct nfs_server *server, unsigned long timestamp) | 468 | static void renew_lease(const struct nfs_server *server, unsigned long timestamp) |
469 | { | 469 | { |
470 | do_renew_lease(server->nfs_client, timestamp); | 470 | struct nfs_client *clp = server->nfs_client; |
471 | |||
472 | if (!nfs4_has_session(clp)) | ||
473 | do_renew_lease(clp, timestamp); | ||
471 | } | 474 | } |
472 | 475 | ||
473 | struct nfs4_call_sync_data { | 476 | struct nfs4_call_sync_data { |
@@ -616,8 +619,7 @@ int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res) | |||
616 | clp = session->clp; | 619 | clp = session->clp; |
617 | do_renew_lease(clp, res->sr_timestamp); | 620 | do_renew_lease(clp, res->sr_timestamp); |
618 | /* Check sequence flags */ | 621 | /* Check sequence flags */ |
619 | if (res->sr_status_flags != 0) | 622 | nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags); |
620 | nfs4_schedule_lease_recovery(clp); | ||
621 | nfs41_update_target_slotid(slot->table, slot, res); | 623 | nfs41_update_target_slotid(slot->table, slot, res); |
622 | break; | 624 | break; |
623 | case 1: | 625 | case 1: |
@@ -910,6 +912,7 @@ struct nfs4_opendata { | |||
910 | struct nfs_open_confirmres c_res; | 912 | struct nfs_open_confirmres c_res; |
911 | struct nfs4_string owner_name; | 913 | struct nfs4_string owner_name; |
912 | struct nfs4_string group_name; | 914 | struct nfs4_string group_name; |
915 | struct nfs4_label *a_label; | ||
913 | struct nfs_fattr f_attr; | 916 | struct nfs_fattr f_attr; |
914 | struct nfs4_label *f_label; | 917 | struct nfs4_label *f_label; |
915 | struct dentry *dir; | 918 | struct dentry *dir; |
@@ -1013,6 +1016,10 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | |||
1013 | if (IS_ERR(p->f_label)) | 1016 | if (IS_ERR(p->f_label)) |
1014 | goto err_free_p; | 1017 | goto err_free_p; |
1015 | 1018 | ||
1019 | p->a_label = nfs4_label_alloc(server, gfp_mask); | ||
1020 | if (IS_ERR(p->a_label)) | ||
1021 | goto err_free_f; | ||
1022 | |||
1016 | alloc_seqid = server->nfs_client->cl_mvops->alloc_seqid; | 1023 | alloc_seqid = server->nfs_client->cl_mvops->alloc_seqid; |
1017 | p->o_arg.seqid = alloc_seqid(&sp->so_seqid, gfp_mask); | 1024 | p->o_arg.seqid = alloc_seqid(&sp->so_seqid, gfp_mask); |
1018 | if (IS_ERR(p->o_arg.seqid)) | 1025 | if (IS_ERR(p->o_arg.seqid)) |
@@ -1041,7 +1048,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | |||
1041 | p->o_arg.server = server; | 1048 | p->o_arg.server = server; |
1042 | p->o_arg.bitmask = nfs4_bitmask(server, label); | 1049 | p->o_arg.bitmask = nfs4_bitmask(server, label); |
1043 | p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0]; | 1050 | p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0]; |
1044 | p->o_arg.label = label; | 1051 | p->o_arg.label = nfs4_label_copy(p->a_label, label); |
1045 | p->o_arg.claim = nfs4_map_atomic_open_claim(server, claim); | 1052 | p->o_arg.claim = nfs4_map_atomic_open_claim(server, claim); |
1046 | switch (p->o_arg.claim) { | 1053 | switch (p->o_arg.claim) { |
1047 | case NFS4_OPEN_CLAIM_NULL: | 1054 | case NFS4_OPEN_CLAIM_NULL: |
@@ -1074,6 +1081,8 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | |||
1074 | return p; | 1081 | return p; |
1075 | 1082 | ||
1076 | err_free_label: | 1083 | err_free_label: |
1084 | nfs4_label_free(p->a_label); | ||
1085 | err_free_f: | ||
1077 | nfs4_label_free(p->f_label); | 1086 | nfs4_label_free(p->f_label); |
1078 | err_free_p: | 1087 | err_free_p: |
1079 | kfree(p); | 1088 | kfree(p); |
@@ -1093,6 +1102,7 @@ static void nfs4_opendata_free(struct kref *kref) | |||
1093 | nfs4_put_open_state(p->state); | 1102 | nfs4_put_open_state(p->state); |
1094 | nfs4_put_state_owner(p->owner); | 1103 | nfs4_put_state_owner(p->owner); |
1095 | 1104 | ||
1105 | nfs4_label_free(p->a_label); | ||
1096 | nfs4_label_free(p->f_label); | 1106 | nfs4_label_free(p->f_label); |
1097 | 1107 | ||
1098 | dput(p->dir); | 1108 | dput(p->dir); |
@@ -1198,12 +1208,15 @@ static bool nfs_need_update_open_stateid(struct nfs4_state *state, | |||
1198 | 1208 | ||
1199 | static void nfs_resync_open_stateid_locked(struct nfs4_state *state) | 1209 | static void nfs_resync_open_stateid_locked(struct nfs4_state *state) |
1200 | { | 1210 | { |
1211 | if (!(state->n_wronly || state->n_rdonly || state->n_rdwr)) | ||
1212 | return; | ||
1201 | if (state->n_wronly) | 1213 | if (state->n_wronly) |
1202 | set_bit(NFS_O_WRONLY_STATE, &state->flags); | 1214 | set_bit(NFS_O_WRONLY_STATE, &state->flags); |
1203 | if (state->n_rdonly) | 1215 | if (state->n_rdonly) |
1204 | set_bit(NFS_O_RDONLY_STATE, &state->flags); | 1216 | set_bit(NFS_O_RDONLY_STATE, &state->flags); |
1205 | if (state->n_rdwr) | 1217 | if (state->n_rdwr) |
1206 | set_bit(NFS_O_RDWR_STATE, &state->flags); | 1218 | set_bit(NFS_O_RDWR_STATE, &state->flags); |
1219 | set_bit(NFS_OPEN_STATE, &state->flags); | ||
1207 | } | 1220 | } |
1208 | 1221 | ||
1209 | static void nfs_clear_open_stateid_locked(struct nfs4_state *state, | 1222 | static void nfs_clear_open_stateid_locked(struct nfs4_state *state, |
@@ -7571,13 +7584,8 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) | |||
7571 | goto out; | 7584 | goto out; |
7572 | } | 7585 | } |
7573 | ret = rpc_wait_for_completion_task(task); | 7586 | ret = rpc_wait_for_completion_task(task); |
7574 | if (!ret) { | 7587 | if (!ret) |
7575 | struct nfs4_sequence_res *res = task->tk_msg.rpc_resp; | ||
7576 | |||
7577 | if (task->tk_status == 0) | ||
7578 | nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags); | ||
7579 | ret = task->tk_status; | 7588 | ret = task->tk_status; |
7580 | } | ||
7581 | rpc_put_task(task); | 7589 | rpc_put_task(task); |
7582 | out: | 7590 | out: |
7583 | dprintk("<-- %s status=%d\n", __func__, ret); | 7591 | dprintk("<-- %s status=%d\n", __func__, ret); |
@@ -7965,16 +7973,17 @@ static void nfs4_layoutreturn_release(void *calldata) | |||
7965 | { | 7973 | { |
7966 | struct nfs4_layoutreturn *lrp = calldata; | 7974 | struct nfs4_layoutreturn *lrp = calldata; |
7967 | struct pnfs_layout_hdr *lo = lrp->args.layout; | 7975 | struct pnfs_layout_hdr *lo = lrp->args.layout; |
7976 | LIST_HEAD(freeme); | ||
7968 | 7977 | ||
7969 | dprintk("--> %s\n", __func__); | 7978 | dprintk("--> %s\n", __func__); |
7970 | spin_lock(&lo->plh_inode->i_lock); | 7979 | spin_lock(&lo->plh_inode->i_lock); |
7971 | if (lrp->res.lrs_present) | 7980 | if (lrp->res.lrs_present) |
7972 | pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); | 7981 | pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); |
7982 | pnfs_mark_matching_lsegs_invalid(lo, &freeme, &lrp->args.range); | ||
7973 | pnfs_clear_layoutreturn_waitbit(lo); | 7983 | pnfs_clear_layoutreturn_waitbit(lo); |
7974 | clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, &lo->plh_flags); | ||
7975 | rpc_wake_up(&NFS_SERVER(lo->plh_inode)->roc_rpcwaitq); | ||
7976 | lo->plh_block_lgets--; | 7984 | lo->plh_block_lgets--; |
7977 | spin_unlock(&lo->plh_inode->i_lock); | 7985 | spin_unlock(&lo->plh_inode->i_lock); |
7986 | pnfs_free_lseg_list(&freeme); | ||
7978 | pnfs_put_layout_hdr(lrp->args.layout); | 7987 | pnfs_put_layout_hdr(lrp->args.layout); |
7979 | nfs_iput_and_deactive(lrp->inode); | 7988 | nfs_iput_and_deactive(lrp->inode); |
7980 | kfree(calldata); | 7989 | kfree(calldata); |
@@ -8588,7 +8597,6 @@ static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = { | |||
8588 | .minor_version = 0, | 8597 | .minor_version = 0, |
8589 | .init_caps = NFS_CAP_READDIRPLUS | 8598 | .init_caps = NFS_CAP_READDIRPLUS |
8590 | | NFS_CAP_ATOMIC_OPEN | 8599 | | NFS_CAP_ATOMIC_OPEN |
8591 | | NFS_CAP_CHANGE_ATTR | ||
8592 | | NFS_CAP_POSIX_LOCK, | 8600 | | NFS_CAP_POSIX_LOCK, |
8593 | .init_client = nfs40_init_client, | 8601 | .init_client = nfs40_init_client, |
8594 | .shutdown_client = nfs40_shutdown_client, | 8602 | .shutdown_client = nfs40_shutdown_client, |
@@ -8614,7 +8622,6 @@ static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = { | |||
8614 | .minor_version = 1, | 8622 | .minor_version = 1, |
8615 | .init_caps = NFS_CAP_READDIRPLUS | 8623 | .init_caps = NFS_CAP_READDIRPLUS |
8616 | | NFS_CAP_ATOMIC_OPEN | 8624 | | NFS_CAP_ATOMIC_OPEN |
8617 | | NFS_CAP_CHANGE_ATTR | ||
8618 | | NFS_CAP_POSIX_LOCK | 8625 | | NFS_CAP_POSIX_LOCK |
8619 | | NFS_CAP_STATEID_NFSV41 | 8626 | | NFS_CAP_STATEID_NFSV41 |
8620 | | NFS_CAP_ATOMIC_OPEN_V1, | 8627 | | NFS_CAP_ATOMIC_OPEN_V1, |
@@ -8637,7 +8644,6 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = { | |||
8637 | .minor_version = 2, | 8644 | .minor_version = 2, |
8638 | .init_caps = NFS_CAP_READDIRPLUS | 8645 | .init_caps = NFS_CAP_READDIRPLUS |
8639 | | NFS_CAP_ATOMIC_OPEN | 8646 | | NFS_CAP_ATOMIC_OPEN |
8640 | | NFS_CAP_CHANGE_ATTR | ||
8641 | | NFS_CAP_POSIX_LOCK | 8647 | | NFS_CAP_POSIX_LOCK |
8642 | | NFS_CAP_STATEID_NFSV41 | 8648 | | NFS_CAP_STATEID_NFSV41 |
8643 | | NFS_CAP_ATOMIC_OPEN_V1 | 8649 | | NFS_CAP_ATOMIC_OPEN_V1 |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 605840dc89cf..f2e2ad894461 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -2191,25 +2191,35 @@ static void nfs41_handle_server_reboot(struct nfs_client *clp) | |||
2191 | } | 2191 | } |
2192 | } | 2192 | } |
2193 | 2193 | ||
2194 | static void nfs41_handle_state_revoked(struct nfs_client *clp) | 2194 | static void nfs41_handle_all_state_revoked(struct nfs_client *clp) |
2195 | { | 2195 | { |
2196 | nfs4_reset_all_state(clp); | 2196 | nfs4_reset_all_state(clp); |
2197 | dprintk("%s: state revoked on server %s\n", __func__, clp->cl_hostname); | 2197 | dprintk("%s: state revoked on server %s\n", __func__, clp->cl_hostname); |
2198 | } | 2198 | } |
2199 | 2199 | ||
2200 | static void nfs41_handle_some_state_revoked(struct nfs_client *clp) | ||
2201 | { | ||
2202 | nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce); | ||
2203 | nfs4_schedule_state_manager(clp); | ||
2204 | |||
2205 | dprintk("%s: state revoked on server %s\n", __func__, clp->cl_hostname); | ||
2206 | } | ||
2207 | |||
2200 | static void nfs41_handle_recallable_state_revoked(struct nfs_client *clp) | 2208 | static void nfs41_handle_recallable_state_revoked(struct nfs_client *clp) |
2201 | { | 2209 | { |
2202 | /* This will need to handle layouts too */ | 2210 | /* FIXME: For now, we destroy all layouts. */ |
2203 | nfs_expire_all_delegations(clp); | 2211 | pnfs_destroy_all_layouts(clp); |
2212 | /* FIXME: For now, we test all delegations+open state+locks. */ | ||
2213 | nfs41_handle_some_state_revoked(clp); | ||
2204 | dprintk("%s: Recallable state revoked on server %s!\n", __func__, | 2214 | dprintk("%s: Recallable state revoked on server %s!\n", __func__, |
2205 | clp->cl_hostname); | 2215 | clp->cl_hostname); |
2206 | } | 2216 | } |
2207 | 2217 | ||
2208 | static void nfs41_handle_backchannel_fault(struct nfs_client *clp) | 2218 | static void nfs41_handle_backchannel_fault(struct nfs_client *clp) |
2209 | { | 2219 | { |
2210 | nfs_expire_all_delegations(clp); | 2220 | set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); |
2211 | if (test_and_set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) == 0) | 2221 | nfs4_schedule_state_manager(clp); |
2212 | nfs4_schedule_state_manager(clp); | 2222 | |
2213 | dprintk("%s: server %s declared a backchannel fault\n", __func__, | 2223 | dprintk("%s: server %s declared a backchannel fault\n", __func__, |
2214 | clp->cl_hostname); | 2224 | clp->cl_hostname); |
2215 | } | 2225 | } |
@@ -2231,10 +2241,11 @@ void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags) | |||
2231 | 2241 | ||
2232 | if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED) | 2242 | if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED) |
2233 | nfs41_handle_server_reboot(clp); | 2243 | nfs41_handle_server_reboot(clp); |
2234 | if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED | | 2244 | if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED)) |
2235 | SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED | | 2245 | nfs41_handle_all_state_revoked(clp); |
2246 | if (flags & (SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED | | ||
2236 | SEQ4_STATUS_ADMIN_STATE_REVOKED)) | 2247 | SEQ4_STATUS_ADMIN_STATE_REVOKED)) |
2237 | nfs41_handle_state_revoked(clp); | 2248 | nfs41_handle_some_state_revoked(clp); |
2238 | if (flags & SEQ4_STATUS_LEASE_MOVED) | 2249 | if (flags & SEQ4_STATUS_LEASE_MOVED) |
2239 | nfs4_schedule_lease_moved_recovery(clp); | 2250 | nfs4_schedule_lease_moved_recovery(clp); |
2240 | if (flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED) | 2251 | if (flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED) |
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 1da68d3b1eda..4984bbe55ff1 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -1100,8 +1100,6 @@ static int nfs_do_recoalesce(struct nfs_pageio_descriptor *desc) | |||
1100 | mirror->pg_base = 0; | 1100 | mirror->pg_base = 0; |
1101 | mirror->pg_recoalesce = 0; | 1101 | mirror->pg_recoalesce = 0; |
1102 | 1102 | ||
1103 | desc->pg_moreio = 0; | ||
1104 | |||
1105 | while (!list_empty(&head)) { | 1103 | while (!list_empty(&head)) { |
1106 | struct nfs_page *req; | 1104 | struct nfs_page *req; |
1107 | 1105 | ||
@@ -1109,8 +1107,11 @@ static int nfs_do_recoalesce(struct nfs_pageio_descriptor *desc) | |||
1109 | nfs_list_remove_request(req); | 1107 | nfs_list_remove_request(req); |
1110 | if (__nfs_pageio_add_request(desc, req)) | 1108 | if (__nfs_pageio_add_request(desc, req)) |
1111 | continue; | 1109 | continue; |
1112 | if (desc->pg_error < 0) | 1110 | if (desc->pg_error < 0) { |
1111 | list_splice_tail(&head, &mirror->pg_list); | ||
1112 | mirror->pg_recoalesce = 1; | ||
1113 | return 0; | 1113 | return 0; |
1114 | } | ||
1114 | break; | 1115 | break; |
1115 | } | 1116 | } |
1116 | } while (mirror->pg_recoalesce); | 1117 | } while (mirror->pg_recoalesce); |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 0ba9a02c9566..70bf706b1090 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -352,7 +352,7 @@ pnfs_layout_need_return(struct pnfs_layout_hdr *lo, | |||
352 | { | 352 | { |
353 | struct pnfs_layout_segment *s; | 353 | struct pnfs_layout_segment *s; |
354 | 354 | ||
355 | if (!test_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags)) | 355 | if (!test_and_clear_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags)) |
356 | return false; | 356 | return false; |
357 | 357 | ||
358 | list_for_each_entry(s, &lo->plh_segs, pls_list) | 358 | list_for_each_entry(s, &lo->plh_segs, pls_list) |
@@ -362,6 +362,18 @@ pnfs_layout_need_return(struct pnfs_layout_hdr *lo, | |||
362 | return true; | 362 | return true; |
363 | } | 363 | } |
364 | 364 | ||
365 | static bool | ||
366 | pnfs_prepare_layoutreturn(struct pnfs_layout_hdr *lo) | ||
367 | { | ||
368 | if (test_and_set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) | ||
369 | return false; | ||
370 | lo->plh_return_iomode = 0; | ||
371 | lo->plh_block_lgets++; | ||
372 | pnfs_get_layout_hdr(lo); | ||
373 | clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, &lo->plh_flags); | ||
374 | return true; | ||
375 | } | ||
376 | |||
365 | static void pnfs_layoutreturn_before_put_lseg(struct pnfs_layout_segment *lseg, | 377 | static void pnfs_layoutreturn_before_put_lseg(struct pnfs_layout_segment *lseg, |
366 | struct pnfs_layout_hdr *lo, struct inode *inode) | 378 | struct pnfs_layout_hdr *lo, struct inode *inode) |
367 | { | 379 | { |
@@ -372,17 +384,16 @@ static void pnfs_layoutreturn_before_put_lseg(struct pnfs_layout_segment *lseg, | |||
372 | if (pnfs_layout_need_return(lo, lseg)) { | 384 | if (pnfs_layout_need_return(lo, lseg)) { |
373 | nfs4_stateid stateid; | 385 | nfs4_stateid stateid; |
374 | enum pnfs_iomode iomode; | 386 | enum pnfs_iomode iomode; |
387 | bool send; | ||
375 | 388 | ||
376 | stateid = lo->plh_stateid; | 389 | stateid = lo->plh_stateid; |
377 | iomode = lo->plh_return_iomode; | 390 | iomode = lo->plh_return_iomode; |
378 | /* decreased in pnfs_send_layoutreturn() */ | 391 | send = pnfs_prepare_layoutreturn(lo); |
379 | lo->plh_block_lgets++; | ||
380 | lo->plh_return_iomode = 0; | ||
381 | spin_unlock(&inode->i_lock); | 392 | spin_unlock(&inode->i_lock); |
382 | pnfs_get_layout_hdr(lo); | 393 | if (send) { |
383 | 394 | /* Send an async layoutreturn so we dont deadlock */ | |
384 | /* Send an async layoutreturn so we dont deadlock */ | 395 | pnfs_send_layoutreturn(lo, stateid, iomode, false); |
385 | pnfs_send_layoutreturn(lo, stateid, iomode, false); | 396 | } |
386 | } else | 397 | } else |
387 | spin_unlock(&inode->i_lock); | 398 | spin_unlock(&inode->i_lock); |
388 | } | 399 | } |
@@ -411,6 +422,10 @@ pnfs_put_lseg(struct pnfs_layout_segment *lseg) | |||
411 | pnfs_layoutreturn_before_put_lseg(lseg, lo, inode); | 422 | pnfs_layoutreturn_before_put_lseg(lseg, lo, inode); |
412 | 423 | ||
413 | if (atomic_dec_and_lock(&lseg->pls_refcount, &inode->i_lock)) { | 424 | if (atomic_dec_and_lock(&lseg->pls_refcount, &inode->i_lock)) { |
425 | if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags)) { | ||
426 | spin_unlock(&inode->i_lock); | ||
427 | return; | ||
428 | } | ||
414 | pnfs_get_layout_hdr(lo); | 429 | pnfs_get_layout_hdr(lo); |
415 | pnfs_layout_remove_lseg(lo, lseg); | 430 | pnfs_layout_remove_lseg(lo, lseg); |
416 | spin_unlock(&inode->i_lock); | 431 | spin_unlock(&inode->i_lock); |
@@ -451,6 +466,8 @@ pnfs_put_lseg_locked(struct pnfs_layout_segment *lseg) | |||
451 | test_bit(NFS_LSEG_VALID, &lseg->pls_flags)); | 466 | test_bit(NFS_LSEG_VALID, &lseg->pls_flags)); |
452 | if (atomic_dec_and_test(&lseg->pls_refcount)) { | 467 | if (atomic_dec_and_test(&lseg->pls_refcount)) { |
453 | struct pnfs_layout_hdr *lo = lseg->pls_layout; | 468 | struct pnfs_layout_hdr *lo = lseg->pls_layout; |
469 | if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags)) | ||
470 | return; | ||
454 | pnfs_get_layout_hdr(lo); | 471 | pnfs_get_layout_hdr(lo); |
455 | pnfs_layout_remove_lseg(lo, lseg); | 472 | pnfs_layout_remove_lseg(lo, lseg); |
456 | pnfs_free_lseg_async(lseg); | 473 | pnfs_free_lseg_async(lseg); |
@@ -924,6 +941,7 @@ void pnfs_clear_layoutreturn_waitbit(struct pnfs_layout_hdr *lo) | |||
924 | clear_bit_unlock(NFS_LAYOUT_RETURN, &lo->plh_flags); | 941 | clear_bit_unlock(NFS_LAYOUT_RETURN, &lo->plh_flags); |
925 | smp_mb__after_atomic(); | 942 | smp_mb__after_atomic(); |
926 | wake_up_bit(&lo->plh_flags, NFS_LAYOUT_RETURN); | 943 | wake_up_bit(&lo->plh_flags, NFS_LAYOUT_RETURN); |
944 | rpc_wake_up(&NFS_SERVER(lo->plh_inode)->roc_rpcwaitq); | ||
927 | } | 945 | } |
928 | 946 | ||
929 | static int | 947 | static int |
@@ -978,6 +996,7 @@ _pnfs_return_layout(struct inode *ino) | |||
978 | LIST_HEAD(tmp_list); | 996 | LIST_HEAD(tmp_list); |
979 | nfs4_stateid stateid; | 997 | nfs4_stateid stateid; |
980 | int status = 0, empty; | 998 | int status = 0, empty; |
999 | bool send; | ||
981 | 1000 | ||
982 | dprintk("NFS: %s for inode %lu\n", __func__, ino->i_ino); | 1001 | dprintk("NFS: %s for inode %lu\n", __func__, ino->i_ino); |
983 | 1002 | ||
@@ -1007,17 +1026,18 @@ _pnfs_return_layout(struct inode *ino) | |||
1007 | /* Don't send a LAYOUTRETURN if list was initially empty */ | 1026 | /* Don't send a LAYOUTRETURN if list was initially empty */ |
1008 | if (empty) { | 1027 | if (empty) { |
1009 | spin_unlock(&ino->i_lock); | 1028 | spin_unlock(&ino->i_lock); |
1010 | pnfs_put_layout_hdr(lo); | ||
1011 | dprintk("NFS: %s no layout segments to return\n", __func__); | 1029 | dprintk("NFS: %s no layout segments to return\n", __func__); |
1012 | goto out; | 1030 | goto out_put_layout_hdr; |
1013 | } | 1031 | } |
1014 | 1032 | ||
1015 | set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); | 1033 | set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); |
1016 | lo->plh_block_lgets++; | 1034 | send = pnfs_prepare_layoutreturn(lo); |
1017 | spin_unlock(&ino->i_lock); | 1035 | spin_unlock(&ino->i_lock); |
1018 | pnfs_free_lseg_list(&tmp_list); | 1036 | pnfs_free_lseg_list(&tmp_list); |
1019 | 1037 | if (send) | |
1020 | status = pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, true); | 1038 | status = pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, true); |
1039 | out_put_layout_hdr: | ||
1040 | pnfs_put_layout_hdr(lo); | ||
1021 | out: | 1041 | out: |
1022 | dprintk("<-- %s status: %d\n", __func__, status); | 1042 | dprintk("<-- %s status: %d\n", __func__, status); |
1023 | return status; | 1043 | return status; |
@@ -1097,13 +1117,9 @@ bool pnfs_roc(struct inode *ino) | |||
1097 | out_noroc: | 1117 | out_noroc: |
1098 | if (lo) { | 1118 | if (lo) { |
1099 | stateid = lo->plh_stateid; | 1119 | stateid = lo->plh_stateid; |
1100 | layoutreturn = | 1120 | if (test_and_clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, |
1101 | test_and_clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, | 1121 | &lo->plh_flags)) |
1102 | &lo->plh_flags); | 1122 | layoutreturn = pnfs_prepare_layoutreturn(lo); |
1103 | if (layoutreturn) { | ||
1104 | lo->plh_block_lgets++; | ||
1105 | pnfs_get_layout_hdr(lo); | ||
1106 | } | ||
1107 | } | 1123 | } |
1108 | spin_unlock(&ino->i_lock); | 1124 | spin_unlock(&ino->i_lock); |
1109 | if (layoutreturn) { | 1125 | if (layoutreturn) { |
@@ -1146,15 +1162,18 @@ bool pnfs_roc_drain(struct inode *ino, u32 *barrier, struct rpc_task *task) | |||
1146 | struct pnfs_layout_segment *lseg; | 1162 | struct pnfs_layout_segment *lseg; |
1147 | nfs4_stateid stateid; | 1163 | nfs4_stateid stateid; |
1148 | u32 current_seqid; | 1164 | u32 current_seqid; |
1149 | bool found = false, layoutreturn = false; | 1165 | bool layoutreturn = false; |
1150 | 1166 | ||
1151 | spin_lock(&ino->i_lock); | 1167 | spin_lock(&ino->i_lock); |
1152 | list_for_each_entry(lseg, &nfsi->layout->plh_segs, pls_list) | 1168 | list_for_each_entry(lseg, &nfsi->layout->plh_segs, pls_list) { |
1153 | if (test_bit(NFS_LSEG_ROC, &lseg->pls_flags)) { | 1169 | if (!test_bit(NFS_LSEG_ROC, &lseg->pls_flags)) |
1154 | rpc_sleep_on(&NFS_SERVER(ino)->roc_rpcwaitq, task, NULL); | 1170 | continue; |
1155 | found = true; | 1171 | if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags)) |
1156 | goto out; | 1172 | continue; |
1157 | } | 1173 | rpc_sleep_on(&NFS_SERVER(ino)->roc_rpcwaitq, task, NULL); |
1174 | spin_unlock(&ino->i_lock); | ||
1175 | return true; | ||
1176 | } | ||
1158 | lo = nfsi->layout; | 1177 | lo = nfsi->layout; |
1159 | current_seqid = be32_to_cpu(lo->plh_stateid.seqid); | 1178 | current_seqid = be32_to_cpu(lo->plh_stateid.seqid); |
1160 | 1179 | ||
@@ -1162,23 +1181,19 @@ bool pnfs_roc_drain(struct inode *ino, u32 *barrier, struct rpc_task *task) | |||
1162 | * a barrier, we choose the worst-case barrier. | 1181 | * a barrier, we choose the worst-case barrier. |
1163 | */ | 1182 | */ |
1164 | *barrier = current_seqid + atomic_read(&lo->plh_outstanding); | 1183 | *barrier = current_seqid + atomic_read(&lo->plh_outstanding); |
1165 | out: | 1184 | stateid = lo->plh_stateid; |
1166 | if (!found) { | 1185 | if (test_and_clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, |
1167 | stateid = lo->plh_stateid; | 1186 | &lo->plh_flags)) |
1168 | layoutreturn = | 1187 | layoutreturn = pnfs_prepare_layoutreturn(lo); |
1169 | test_and_clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, | 1188 | if (test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) |
1170 | &lo->plh_flags); | 1189 | rpc_sleep_on(&NFS_SERVER(ino)->roc_rpcwaitq, task, NULL); |
1171 | if (layoutreturn) { | 1190 | |
1172 | lo->plh_block_lgets++; | ||
1173 | pnfs_get_layout_hdr(lo); | ||
1174 | } | ||
1175 | } | ||
1176 | spin_unlock(&ino->i_lock); | 1191 | spin_unlock(&ino->i_lock); |
1177 | if (layoutreturn) { | 1192 | if (layoutreturn) { |
1178 | rpc_sleep_on(&NFS_SERVER(ino)->roc_rpcwaitq, task, NULL); | ||
1179 | pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, false); | 1193 | pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, false); |
1194 | return true; | ||
1180 | } | 1195 | } |
1181 | return found; | 1196 | return false; |
1182 | } | 1197 | } |
1183 | 1198 | ||
1184 | /* | 1199 | /* |
@@ -1695,7 +1710,6 @@ void pnfs_error_mark_layout_for_return(struct inode *inode, | |||
1695 | spin_lock(&inode->i_lock); | 1710 | spin_lock(&inode->i_lock); |
1696 | /* set failure bit so that pnfs path will be retried later */ | 1711 | /* set failure bit so that pnfs path will be retried later */ |
1697 | pnfs_layout_set_fail_bit(lo, iomode); | 1712 | pnfs_layout_set_fail_bit(lo, iomode); |
1698 | set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags); | ||
1699 | if (lo->plh_return_iomode == 0) | 1713 | if (lo->plh_return_iomode == 0) |
1700 | lo->plh_return_iomode = range.iomode; | 1714 | lo->plh_return_iomode = range.iomode; |
1701 | else if (lo->plh_return_iomode != range.iomode) | 1715 | else if (lo->plh_return_iomode != range.iomode) |
@@ -2207,13 +2221,12 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync) | |||
2207 | if (ld->prepare_layoutcommit) { | 2221 | if (ld->prepare_layoutcommit) { |
2208 | status = ld->prepare_layoutcommit(&data->args); | 2222 | status = ld->prepare_layoutcommit(&data->args); |
2209 | if (status) { | 2223 | if (status) { |
2224 | put_rpccred(data->cred); | ||
2210 | spin_lock(&inode->i_lock); | 2225 | spin_lock(&inode->i_lock); |
2211 | set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags); | 2226 | set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags); |
2212 | if (end_pos > nfsi->layout->plh_lwb) | 2227 | if (end_pos > nfsi->layout->plh_lwb) |
2213 | nfsi->layout->plh_lwb = end_pos; | 2228 | nfsi->layout->plh_lwb = end_pos; |
2214 | spin_unlock(&inode->i_lock); | 2229 | goto out_unlock; |
2215 | put_rpccred(data->cred); | ||
2216 | goto clear_layoutcommitting; | ||
2217 | } | 2230 | } |
2218 | } | 2231 | } |
2219 | 2232 | ||
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 65869ca9c851..75a35a1afa79 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -1379,24 +1379,27 @@ static void nfs_writeback_check_extend(struct nfs_pgio_header *hdr, | |||
1379 | { | 1379 | { |
1380 | struct nfs_pgio_args *argp = &hdr->args; | 1380 | struct nfs_pgio_args *argp = &hdr->args; |
1381 | struct nfs_pgio_res *resp = &hdr->res; | 1381 | struct nfs_pgio_res *resp = &hdr->res; |
1382 | u64 size = argp->offset + resp->count; | ||
1382 | 1383 | ||
1383 | if (!(fattr->valid & NFS_ATTR_FATTR_SIZE)) | 1384 | if (!(fattr->valid & NFS_ATTR_FATTR_SIZE)) |
1385 | fattr->size = size; | ||
1386 | if (nfs_size_to_loff_t(fattr->size) < i_size_read(hdr->inode)) { | ||
1387 | fattr->valid &= ~NFS_ATTR_FATTR_SIZE; | ||
1384 | return; | 1388 | return; |
1385 | if (argp->offset + resp->count != fattr->size) | 1389 | } |
1386 | return; | 1390 | if (size != fattr->size) |
1387 | if (nfs_size_to_loff_t(fattr->size) < i_size_read(hdr->inode)) | ||
1388 | return; | 1391 | return; |
1389 | /* Set attribute barrier */ | 1392 | /* Set attribute barrier */ |
1390 | nfs_fattr_set_barrier(fattr); | 1393 | nfs_fattr_set_barrier(fattr); |
1394 | /* ...and update size */ | ||
1395 | fattr->valid |= NFS_ATTR_FATTR_SIZE; | ||
1391 | } | 1396 | } |
1392 | 1397 | ||
1393 | void nfs_writeback_update_inode(struct nfs_pgio_header *hdr) | 1398 | void nfs_writeback_update_inode(struct nfs_pgio_header *hdr) |
1394 | { | 1399 | { |
1395 | struct nfs_fattr *fattr = hdr->res.fattr; | 1400 | struct nfs_fattr *fattr = &hdr->fattr; |
1396 | struct inode *inode = hdr->inode; | 1401 | struct inode *inode = hdr->inode; |
1397 | 1402 | ||
1398 | if (fattr == NULL) | ||
1399 | return; | ||
1400 | spin_lock(&inode->i_lock); | 1403 | spin_lock(&inode->i_lock); |
1401 | nfs_writeback_check_extend(hdr, fattr); | 1404 | nfs_writeback_check_extend(hdr, fattr); |
1402 | nfs_post_op_update_inode_force_wcc_locked(inode, fattr); | 1405 | nfs_post_op_update_inode_force_wcc_locked(inode, fattr); |