diff options
| -rw-r--r-- | fs/nfs/internal.h | 1 | ||||
| -rw-r--r-- | fs/nfs/nfs4filelayout.c | 81 | ||||
| -rw-r--r-- | fs/nfs/nfs4proc.c | 35 | ||||
| -rw-r--r-- | fs/nfs/nfs4state.c | 1 | ||||
| -rw-r--r-- | fs/nfs/read.c | 1 | ||||
| -rw-r--r-- | include/linux/nfs_xdr.h | 1 | ||||
| -rw-r--r-- | include/linux/sunrpc/clnt.h | 1 | ||||
| -rw-r--r-- | net/sunrpc/clnt.c | 8 |
8 files changed, 123 insertions, 6 deletions
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 5e9df992cd73..1a3228e9ea22 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
| @@ -285,6 +285,7 @@ extern int nfs_migrate_page(struct address_space *, | |||
| 285 | #endif | 285 | #endif |
| 286 | 286 | ||
| 287 | /* nfs4proc.c */ | 287 | /* nfs4proc.c */ |
| 288 | extern void nfs4_reset_read(struct rpc_task *task, struct nfs_read_data *data); | ||
| 288 | extern int nfs4_init_client(struct nfs_client *clp, | 289 | extern int nfs4_init_client(struct nfs_client *clp, |
| 289 | const struct rpc_timeout *timeparms, | 290 | const struct rpc_timeout *timeparms, |
| 290 | const char *ip_addr, | 291 | const char *ip_addr, |
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 3608411653dc..6a424c19abea 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
| @@ -40,6 +40,8 @@ MODULE_LICENSE("GPL"); | |||
| 40 | MODULE_AUTHOR("Dean Hildebrand <dhildebz@umich.edu>"); | 40 | MODULE_AUTHOR("Dean Hildebrand <dhildebz@umich.edu>"); |
| 41 | MODULE_DESCRIPTION("The NFSv4 file layout driver"); | 41 | MODULE_DESCRIPTION("The NFSv4 file layout driver"); |
| 42 | 42 | ||
| 43 | #define FILELAYOUT_POLL_RETRY_MAX (15*HZ) | ||
| 44 | |||
| 43 | static int | 45 | static int |
| 44 | filelayout_set_layoutdriver(struct nfs_server *nfss) | 46 | filelayout_set_layoutdriver(struct nfs_server *nfss) |
| 45 | { | 47 | { |
| @@ -100,6 +102,83 @@ filelayout_get_dserver_offset(struct pnfs_layout_segment *lseg, loff_t offset) | |||
| 100 | BUG(); | 102 | BUG(); |
| 101 | } | 103 | } |
| 102 | 104 | ||
| 105 | /* For data server errors we don't recover from */ | ||
| 106 | static void | ||
| 107 | filelayout_set_lo_fail(struct pnfs_layout_segment *lseg) | ||
| 108 | { | ||
| 109 | if (lseg->pls_range.iomode == IOMODE_RW) { | ||
| 110 | dprintk("%s Setting layout IOMODE_RW fail bit\n", __func__); | ||
| 111 | set_bit(lo_fail_bit(IOMODE_RW), &lseg->pls_layout->plh_flags); | ||
| 112 | } else { | ||
| 113 | dprintk("%s Setting layout IOMODE_READ fail bit\n", __func__); | ||
| 114 | set_bit(lo_fail_bit(IOMODE_READ), &lseg->pls_layout->plh_flags); | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | static int filelayout_async_handle_error(struct rpc_task *task, | ||
| 119 | struct nfs4_state *state, | ||
| 120 | struct nfs_client *clp, | ||
| 121 | int *reset) | ||
| 122 | { | ||
| 123 | if (task->tk_status >= 0) | ||
| 124 | return 0; | ||
| 125 | |||
| 126 | *reset = 0; | ||
| 127 | |||
| 128 | switch (task->tk_status) { | ||
| 129 | case -NFS4ERR_BADSESSION: | ||
| 130 | case -NFS4ERR_BADSLOT: | ||
| 131 | case -NFS4ERR_BAD_HIGH_SLOT: | ||
| 132 | case -NFS4ERR_DEADSESSION: | ||
| 133 | case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: | ||
| 134 | case -NFS4ERR_SEQ_FALSE_RETRY: | ||
| 135 | case -NFS4ERR_SEQ_MISORDERED: | ||
| 136 | dprintk("%s ERROR %d, Reset session. Exchangeid " | ||
| 137 | "flags 0x%x\n", __func__, task->tk_status, | ||
| 138 | clp->cl_exchange_flags); | ||
| 139 | nfs4_schedule_session_recovery(clp->cl_session); | ||
| 140 | break; | ||
| 141 | case -NFS4ERR_DELAY: | ||
| 142 | case -NFS4ERR_GRACE: | ||
| 143 | case -EKEYEXPIRED: | ||
| 144 | rpc_delay(task, FILELAYOUT_POLL_RETRY_MAX); | ||
| 145 | break; | ||
| 146 | default: | ||
| 147 | dprintk("%s DS error. Retry through MDS %d\n", __func__, | ||
| 148 | task->tk_status); | ||
| 149 | *reset = 1; | ||
| 150 | break; | ||
| 151 | } | ||
| 152 | task->tk_status = 0; | ||
| 153 | return -EAGAIN; | ||
| 154 | } | ||
| 155 | |||
| 156 | /* NFS_PROTO call done callback routines */ | ||
| 157 | |||
| 158 | static int filelayout_read_done_cb(struct rpc_task *task, | ||
| 159 | struct nfs_read_data *data) | ||
| 160 | { | ||
| 161 | struct nfs_client *clp = data->ds_clp; | ||
| 162 | int reset = 0; | ||
| 163 | |||
| 164 | dprintk("%s DS read\n", __func__); | ||
| 165 | |||
| 166 | if (filelayout_async_handle_error(task, data->args.context->state, | ||
| 167 | data->ds_clp, &reset) == -EAGAIN) { | ||
| 168 | dprintk("%s calling restart ds_clp %p ds_clp->cl_session %p\n", | ||
| 169 | __func__, data->ds_clp, data->ds_clp->cl_session); | ||
| 170 | if (reset) { | ||
| 171 | filelayout_set_lo_fail(data->lseg); | ||
| 172 | nfs4_reset_read(task, data); | ||
| 173 | clp = NFS_SERVER(data->inode)->nfs_client; | ||
| 174 | } | ||
| 175 | nfs_restart_rpc(task, clp); | ||
| 176 | return -EAGAIN; | ||
| 177 | } | ||
| 178 | |||
| 179 | return 0; | ||
| 180 | } | ||
| 181 | |||
| 103 | /* | 182 | /* |
| 104 | * Call ops for the async read/write cases | 183 | * Call ops for the async read/write cases |
| 105 | * In the case of dense layouts, the offset needs to be reset to its | 184 | * In the case of dense layouts, the offset needs to be reset to its |
| @@ -109,6 +188,8 @@ static void filelayout_read_prepare(struct rpc_task *task, void *data) | |||
| 109 | { | 188 | { |
| 110 | struct nfs_read_data *rdata = (struct nfs_read_data *)data; | 189 | struct nfs_read_data *rdata = (struct nfs_read_data *)data; |
| 111 | 190 | ||
| 191 | rdata->read_done_cb = filelayout_read_done_cb; | ||
| 192 | |||
| 112 | if (nfs41_setup_sequence(rdata->ds_clp->cl_session, | 193 | if (nfs41_setup_sequence(rdata->ds_clp->cl_session, |
| 113 | &rdata->args.seq_args, &rdata->res.seq_res, | 194 | &rdata->args.seq_args, &rdata->res.seq_res, |
| 114 | 0, task)) | 195 | 0, task)) |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index d09623933302..1dc809039448 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -3074,15 +3074,10 @@ static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 3074 | return err; | 3074 | return err; |
| 3075 | } | 3075 | } |
| 3076 | 3076 | ||
| 3077 | static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data) | 3077 | static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_read_data *data) |
| 3078 | { | 3078 | { |
| 3079 | struct nfs_server *server = NFS_SERVER(data->inode); | 3079 | struct nfs_server *server = NFS_SERVER(data->inode); |
| 3080 | 3080 | ||
| 3081 | dprintk("--> %s\n", __func__); | ||
| 3082 | |||
| 3083 | if (!nfs4_sequence_done(task, &data->res.seq_res)) | ||
| 3084 | return -EAGAIN; | ||
| 3085 | |||
| 3086 | if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { | 3081 | if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { |
| 3087 | nfs_restart_rpc(task, server->nfs_client); | 3082 | nfs_restart_rpc(task, server->nfs_client); |
| 3088 | return -EAGAIN; | 3083 | return -EAGAIN; |
| @@ -3094,12 +3089,40 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data) | |||
| 3094 | return 0; | 3089 | return 0; |
| 3095 | } | 3090 | } |
| 3096 | 3091 | ||
| 3092 | static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data) | ||
| 3093 | { | ||
| 3094 | |||
| 3095 | dprintk("--> %s\n", __func__); | ||
| 3096 | |||
| 3097 | if (!nfs4_sequence_done(task, &data->res.seq_res)) | ||
| 3098 | return -EAGAIN; | ||
| 3099 | |||
| 3100 | return data->read_done_cb(task, data); | ||
| 3101 | } | ||
| 3102 | |||
| 3097 | static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg) | 3103 | static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg) |
| 3098 | { | 3104 | { |
| 3099 | data->timestamp = jiffies; | 3105 | data->timestamp = jiffies; |
| 3106 | data->read_done_cb = nfs4_read_done_cb; | ||
| 3100 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ]; | 3107 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ]; |
| 3101 | } | 3108 | } |
| 3102 | 3109 | ||
| 3110 | /* Reset the the nfs_read_data to send the read to the MDS. */ | ||
| 3111 | void nfs4_reset_read(struct rpc_task *task, struct nfs_read_data *data) | ||
| 3112 | { | ||
| 3113 | dprintk("%s Reset task for i/o through\n", __func__); | ||
| 3114 | put_lseg(data->lseg); | ||
| 3115 | data->lseg = NULL; | ||
| 3116 | /* offsets will differ in the dense stripe case */ | ||
| 3117 | data->args.offset = data->mds_offset; | ||
| 3118 | data->ds_clp = NULL; | ||
| 3119 | data->args.fh = NFS_FH(data->inode); | ||
| 3120 | data->read_done_cb = nfs4_read_done_cb; | ||
| 3121 | task->tk_ops = data->mds_ops; | ||
| 3122 | rpc_task_reset_client(task, NFS_CLIENT(data->inode)); | ||
| 3123 | } | ||
| 3124 | EXPORT_SYMBOL_GPL(nfs4_reset_read); | ||
| 3125 | |||
| 3103 | static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) | 3126 | static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) |
| 3104 | { | 3127 | { |
| 3105 | struct inode *inode = data->inode; | 3128 | struct inode *inode = data->inode; |
