diff options
| -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 | ||||
| -rw-r--r-- | include/linux/nfs_fs.h | 7 | ||||
| -rw-r--r-- | include/linux/nfs_fs_sb.h | 2 | ||||
| -rw-r--r-- | net/sunrpc/backchannel_rqst.c | 6 | ||||
| -rw-r--r-- | net/sunrpc/clnt.c | 5 | ||||
| -rw-r--r-- | net/sunrpc/xprtsock.c | 25 |
15 files changed, 189 insertions, 103 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); |
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index f91b5ade30c9..874b77228fb9 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
| @@ -292,9 +292,12 @@ static inline void nfs_mark_for_revalidate(struct inode *inode) | |||
| 292 | struct nfs_inode *nfsi = NFS_I(inode); | 292 | struct nfs_inode *nfsi = NFS_I(inode); |
| 293 | 293 | ||
| 294 | spin_lock(&inode->i_lock); | 294 | spin_lock(&inode->i_lock); |
| 295 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS; | 295 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | |
| 296 | NFS_INO_REVAL_PAGECACHE | | ||
| 297 | NFS_INO_INVALID_ACCESS | | ||
| 298 | NFS_INO_INVALID_ACL; | ||
| 296 | if (S_ISDIR(inode->i_mode)) | 299 | if (S_ISDIR(inode->i_mode)) |
| 297 | nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA; | 300 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; |
| 298 | spin_unlock(&inode->i_lock); | 301 | spin_unlock(&inode->i_lock); |
| 299 | } | 302 | } |
| 300 | 303 | ||
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index a2ea1491d3df..20bc8e51b161 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h | |||
| @@ -220,7 +220,7 @@ struct nfs_server { | |||
| 220 | #define NFS_CAP_SYMLINKS (1U << 2) | 220 | #define NFS_CAP_SYMLINKS (1U << 2) |
| 221 | #define NFS_CAP_ACLS (1U << 3) | 221 | #define NFS_CAP_ACLS (1U << 3) |
| 222 | #define NFS_CAP_ATOMIC_OPEN (1U << 4) | 222 | #define NFS_CAP_ATOMIC_OPEN (1U << 4) |
| 223 | #define NFS_CAP_CHANGE_ATTR (1U << 5) | 223 | /* #define NFS_CAP_CHANGE_ATTR (1U << 5) */ |
| 224 | #define NFS_CAP_FILEID (1U << 6) | 224 | #define NFS_CAP_FILEID (1U << 6) |
| 225 | #define NFS_CAP_MODE (1U << 7) | 225 | #define NFS_CAP_MODE (1U << 7) |
| 226 | #define NFS_CAP_NLINK (1U << 8) | 226 | #define NFS_CAP_NLINK (1U << 8) |
diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c index 9825ff0f91d6..6255d141133b 100644 --- a/net/sunrpc/backchannel_rqst.c +++ b/net/sunrpc/backchannel_rqst.c | |||
| @@ -240,8 +240,8 @@ static struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt, __be32 xid) | |||
| 240 | req = xprt_alloc_bc_req(xprt, GFP_ATOMIC); | 240 | req = xprt_alloc_bc_req(xprt, GFP_ATOMIC); |
| 241 | if (!req) | 241 | if (!req) |
| 242 | goto not_found; | 242 | goto not_found; |
| 243 | /* Note: this 'free' request adds it to xprt->bc_pa_list */ | 243 | list_add_tail(&req->rq_bc_pa_list, &xprt->bc_pa_list); |
| 244 | xprt_free_bc_request(req); | 244 | xprt->bc_alloc_count++; |
| 245 | } | 245 | } |
| 246 | req = list_first_entry(&xprt->bc_pa_list, struct rpc_rqst, | 246 | req = list_first_entry(&xprt->bc_pa_list, struct rpc_rqst, |
| 247 | rq_bc_pa_list); | 247 | rq_bc_pa_list); |
| @@ -336,7 +336,7 @@ void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied) | |||
| 336 | 336 | ||
| 337 | spin_lock(&xprt->bc_pa_lock); | 337 | spin_lock(&xprt->bc_pa_lock); |
| 338 | list_del(&req->rq_bc_pa_list); | 338 | list_del(&req->rq_bc_pa_list); |
| 339 | xprt->bc_alloc_count--; | 339 | xprt_dec_alloc_count(xprt, 1); |
| 340 | spin_unlock(&xprt->bc_pa_lock); | 340 | spin_unlock(&xprt->bc_pa_lock); |
| 341 | 341 | ||
| 342 | req->rq_private_buf.len = copied; | 342 | req->rq_private_buf.len = copied; |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index cbc6af923dd1..23608eb0ded2 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
| @@ -1902,6 +1902,7 @@ call_transmit_status(struct rpc_task *task) | |||
| 1902 | 1902 | ||
| 1903 | switch (task->tk_status) { | 1903 | switch (task->tk_status) { |
| 1904 | case -EAGAIN: | 1904 | case -EAGAIN: |
| 1905 | case -ENOBUFS: | ||
| 1905 | break; | 1906 | break; |
| 1906 | default: | 1907 | default: |
| 1907 | dprint_status(task); | 1908 | dprint_status(task); |
| @@ -1928,7 +1929,6 @@ call_transmit_status(struct rpc_task *task) | |||
| 1928 | case -ECONNABORTED: | 1929 | case -ECONNABORTED: |
| 1929 | case -EADDRINUSE: | 1930 | case -EADDRINUSE: |
| 1930 | case -ENOTCONN: | 1931 | case -ENOTCONN: |
| 1931 | case -ENOBUFS: | ||
| 1932 | case -EPIPE: | 1932 | case -EPIPE: |
| 1933 | rpc_task_force_reencode(task); | 1933 | rpc_task_force_reencode(task); |
| 1934 | } | 1934 | } |
| @@ -2057,12 +2057,13 @@ call_status(struct rpc_task *task) | |||
| 2057 | case -ECONNABORTED: | 2057 | case -ECONNABORTED: |
| 2058 | rpc_force_rebind(clnt); | 2058 | rpc_force_rebind(clnt); |
| 2059 | case -EADDRINUSE: | 2059 | case -EADDRINUSE: |
| 2060 | case -ENOBUFS: | ||
| 2061 | rpc_delay(task, 3*HZ); | 2060 | rpc_delay(task, 3*HZ); |
| 2062 | case -EPIPE: | 2061 | case -EPIPE: |
| 2063 | case -ENOTCONN: | 2062 | case -ENOTCONN: |
| 2064 | task->tk_action = call_bind; | 2063 | task->tk_action = call_bind; |
| 2065 | break; | 2064 | break; |
| 2065 | case -ENOBUFS: | ||
| 2066 | rpc_delay(task, HZ>>2); | ||
| 2066 | case -EAGAIN: | 2067 | case -EAGAIN: |
| 2067 | task->tk_action = call_transmit; | 2068 | task->tk_action = call_transmit; |
| 2068 | break; | 2069 | break; |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index e193c2b5476b..0030376327b7 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
| @@ -527,6 +527,10 @@ static int xs_local_send_request(struct rpc_task *task) | |||
| 527 | true, &sent); | 527 | true, &sent); |
| 528 | dprintk("RPC: %s(%u) = %d\n", | 528 | dprintk("RPC: %s(%u) = %d\n", |
| 529 | __func__, xdr->len - req->rq_bytes_sent, status); | 529 | __func__, xdr->len - req->rq_bytes_sent, status); |
| 530 | |||
| 531 | if (status == -EAGAIN && sock_writeable(transport->inet)) | ||
| 532 | status = -ENOBUFS; | ||
| 533 | |||
| 530 | if (likely(sent > 0) || status == 0) { | 534 | if (likely(sent > 0) || status == 0) { |
| 531 | req->rq_bytes_sent += sent; | 535 | req->rq_bytes_sent += sent; |
| 532 | req->rq_xmit_bytes_sent += sent; | 536 | req->rq_xmit_bytes_sent += sent; |
| @@ -539,6 +543,7 @@ static int xs_local_send_request(struct rpc_task *task) | |||
| 539 | 543 | ||
| 540 | switch (status) { | 544 | switch (status) { |
| 541 | case -ENOBUFS: | 545 | case -ENOBUFS: |
| 546 | break; | ||
| 542 | case -EAGAIN: | 547 | case -EAGAIN: |
| 543 | status = xs_nospace(task); | 548 | status = xs_nospace(task); |
| 544 | break; | 549 | break; |
| @@ -589,6 +594,9 @@ static int xs_udp_send_request(struct rpc_task *task) | |||
| 589 | if (status == -EPERM) | 594 | if (status == -EPERM) |
| 590 | goto process_status; | 595 | goto process_status; |
| 591 | 596 | ||
| 597 | if (status == -EAGAIN && sock_writeable(transport->inet)) | ||
| 598 | status = -ENOBUFS; | ||
| 599 | |||
| 592 | if (sent > 0 || status == 0) { | 600 | if (sent > 0 || status == 0) { |
| 593 | req->rq_xmit_bytes_sent += sent; | 601 | req->rq_xmit_bytes_sent += sent; |
| 594 | if (sent >= req->rq_slen) | 602 | if (sent >= req->rq_slen) |
| @@ -669,9 +677,6 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
| 669 | dprintk("RPC: xs_tcp_send_request(%u) = %d\n", | 677 | dprintk("RPC: xs_tcp_send_request(%u) = %d\n", |
| 670 | xdr->len - req->rq_bytes_sent, status); | 678 | xdr->len - req->rq_bytes_sent, status); |
| 671 | 679 | ||
| 672 | if (unlikely(sent == 0 && status < 0)) | ||
| 673 | break; | ||
| 674 | |||
| 675 | /* If we've sent the entire packet, immediately | 680 | /* If we've sent the entire packet, immediately |
| 676 | * reset the count of bytes sent. */ | 681 | * reset the count of bytes sent. */ |
| 677 | req->rq_bytes_sent += sent; | 682 | req->rq_bytes_sent += sent; |
| @@ -681,18 +686,21 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
| 681 | return 0; | 686 | return 0; |
| 682 | } | 687 | } |
| 683 | 688 | ||
| 684 | if (sent != 0) | 689 | if (status < 0) |
| 685 | continue; | 690 | break; |
| 686 | status = -EAGAIN; | 691 | if (sent == 0) { |
| 687 | break; | 692 | status = -EAGAIN; |
| 693 | break; | ||
| 694 | } | ||
| 688 | } | 695 | } |
| 696 | if (status == -EAGAIN && sk_stream_is_writeable(transport->inet)) | ||
| 697 | status = -ENOBUFS; | ||
| 689 | 698 | ||
| 690 | switch (status) { | 699 | switch (status) { |
| 691 | case -ENOTSOCK: | 700 | case -ENOTSOCK: |
| 692 | status = -ENOTCONN; | 701 | status = -ENOTCONN; |
| 693 | /* Should we call xs_close() here? */ | 702 | /* Should we call xs_close() here? */ |
| 694 | break; | 703 | break; |
| 695 | case -ENOBUFS: | ||
| 696 | case -EAGAIN: | 704 | case -EAGAIN: |
| 697 | status = xs_nospace(task); | 705 | status = xs_nospace(task); |
| 698 | break; | 706 | break; |
| @@ -703,6 +711,7 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
| 703 | case -ECONNREFUSED: | 711 | case -ECONNREFUSED: |
| 704 | case -ENOTCONN: | 712 | case -ENOTCONN: |
| 705 | case -EADDRINUSE: | 713 | case -EADDRINUSE: |
| 714 | case -ENOBUFS: | ||
| 706 | case -EPIPE: | 715 | case -EPIPE: |
| 707 | clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); | 716 | clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); |
| 708 | } | 717 | } |
