diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 123 |
1 files changed, 108 insertions, 15 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 0a07e353a961..1d84e7088af9 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -85,6 +85,9 @@ static int nfs4_map_errors(int err) | |||
85 | switch (err) { | 85 | switch (err) { |
86 | case -NFS4ERR_RESOURCE: | 86 | case -NFS4ERR_RESOURCE: |
87 | return -EREMOTEIO; | 87 | return -EREMOTEIO; |
88 | case -NFS4ERR_BADOWNER: | ||
89 | case -NFS4ERR_BADNAME: | ||
90 | return -EINVAL; | ||
88 | default: | 91 | default: |
89 | dprintk("%s could not handle NFSv4 error %d\n", | 92 | dprintk("%s could not handle NFSv4 error %d\n", |
90 | __func__, -err); | 93 | __func__, -err); |
@@ -241,7 +244,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) | |||
241 | /* This is the error handling routine for processes that are allowed | 244 | /* This is the error handling routine for processes that are allowed |
242 | * to sleep. | 245 | * to sleep. |
243 | */ | 246 | */ |
244 | static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception) | 247 | static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception) |
245 | { | 248 | { |
246 | struct nfs_client *clp = server->nfs_client; | 249 | struct nfs_client *clp = server->nfs_client; |
247 | struct nfs4_state *state = exception->state; | 250 | struct nfs4_state *state = exception->state; |
@@ -293,6 +296,19 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, | |||
293 | break; | 296 | break; |
294 | case -NFS4ERR_OLD_STATEID: | 297 | case -NFS4ERR_OLD_STATEID: |
295 | exception->retry = 1; | 298 | exception->retry = 1; |
299 | break; | ||
300 | case -NFS4ERR_BADOWNER: | ||
301 | /* The following works around a Linux server bug! */ | ||
302 | case -NFS4ERR_BADNAME: | ||
303 | if (server->caps & NFS_CAP_UIDGID_NOMAP) { | ||
304 | server->caps &= ~NFS_CAP_UIDGID_NOMAP; | ||
305 | exception->retry = 1; | ||
306 | printk(KERN_WARNING "NFS: v4 server %s " | ||
307 | "does not accept raw " | ||
308 | "uid/gids. " | ||
309 | "Reenabling the idmapper.\n", | ||
310 | server->nfs_client->cl_hostname); | ||
311 | } | ||
296 | } | 312 | } |
297 | /* We failed to handle the error */ | 313 | /* We failed to handle the error */ |
298 | return nfs4_map_errors(ret); | 314 | return nfs4_map_errors(ret); |
@@ -505,7 +521,7 @@ out: | |||
505 | return ret_id; | 521 | return ret_id; |
506 | } | 522 | } |
507 | 523 | ||
508 | static int nfs41_setup_sequence(struct nfs4_session *session, | 524 | int nfs41_setup_sequence(struct nfs4_session *session, |
509 | struct nfs4_sequence_args *args, | 525 | struct nfs4_sequence_args *args, |
510 | struct nfs4_sequence_res *res, | 526 | struct nfs4_sequence_res *res, |
511 | int cache_reply, | 527 | int cache_reply, |
@@ -571,6 +587,7 @@ static int nfs41_setup_sequence(struct nfs4_session *session, | |||
571 | res->sr_status = 1; | 587 | res->sr_status = 1; |
572 | return 0; | 588 | return 0; |
573 | } | 589 | } |
590 | EXPORT_SYMBOL_GPL(nfs41_setup_sequence); | ||
574 | 591 | ||
575 | int nfs4_setup_sequence(const struct nfs_server *server, | 592 | int nfs4_setup_sequence(const struct nfs_server *server, |
576 | struct nfs4_sequence_args *args, | 593 | struct nfs4_sequence_args *args, |
@@ -1573,9 +1590,8 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) | |||
1573 | return 0; | 1590 | return 0; |
1574 | } | 1591 | } |
1575 | 1592 | ||
1576 | static int nfs4_recover_expired_lease(struct nfs_server *server) | 1593 | static int nfs4_client_recover_expired_lease(struct nfs_client *clp) |
1577 | { | 1594 | { |
1578 | struct nfs_client *clp = server->nfs_client; | ||
1579 | unsigned int loop; | 1595 | unsigned int loop; |
1580 | int ret; | 1596 | int ret; |
1581 | 1597 | ||
@@ -1592,6 +1608,11 @@ static int nfs4_recover_expired_lease(struct nfs_server *server) | |||
1592 | return ret; | 1608 | return ret; |
1593 | } | 1609 | } |
1594 | 1610 | ||
1611 | static int nfs4_recover_expired_lease(struct nfs_server *server) | ||
1612 | { | ||
1613 | return nfs4_client_recover_expired_lease(server->nfs_client); | ||
1614 | } | ||
1615 | |||
1595 | /* | 1616 | /* |
1596 | * OPEN_EXPIRED: | 1617 | * OPEN_EXPIRED: |
1597 | * reclaim state on the server after a network partition. | 1618 | * reclaim state on the server after a network partition. |
@@ -3069,15 +3090,10 @@ static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, | |||
3069 | return err; | 3090 | return err; |
3070 | } | 3091 | } |
3071 | 3092 | ||
3072 | static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data) | 3093 | static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_read_data *data) |
3073 | { | 3094 | { |
3074 | struct nfs_server *server = NFS_SERVER(data->inode); | 3095 | struct nfs_server *server = NFS_SERVER(data->inode); |
3075 | 3096 | ||
3076 | dprintk("--> %s\n", __func__); | ||
3077 | |||
3078 | if (!nfs4_sequence_done(task, &data->res.seq_res)) | ||
3079 | return -EAGAIN; | ||
3080 | |||
3081 | if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { | 3097 | if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { |
3082 | nfs_restart_rpc(task, server->nfs_client); | 3098 | nfs_restart_rpc(task, server->nfs_client); |
3083 | return -EAGAIN; | 3099 | return -EAGAIN; |
@@ -3089,19 +3105,44 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data) | |||
3089 | return 0; | 3105 | return 0; |
3090 | } | 3106 | } |
3091 | 3107 | ||
3108 | static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data) | ||
3109 | { | ||
3110 | |||
3111 | dprintk("--> %s\n", __func__); | ||
3112 | |||
3113 | if (!nfs4_sequence_done(task, &data->res.seq_res)) | ||
3114 | return -EAGAIN; | ||
3115 | |||
3116 | return data->read_done_cb(task, data); | ||
3117 | } | ||
3118 | |||
3092 | static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg) | 3119 | static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg) |
3093 | { | 3120 | { |
3094 | data->timestamp = jiffies; | 3121 | data->timestamp = jiffies; |
3122 | data->read_done_cb = nfs4_read_done_cb; | ||
3095 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ]; | 3123 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ]; |
3096 | } | 3124 | } |
3097 | 3125 | ||
3098 | static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) | 3126 | /* Reset the the nfs_read_data to send the read to the MDS. */ |
3127 | void nfs4_reset_read(struct rpc_task *task, struct nfs_read_data *data) | ||
3128 | { | ||
3129 | dprintk("%s Reset task for i/o through\n", __func__); | ||
3130 | put_lseg(data->lseg); | ||
3131 | data->lseg = NULL; | ||
3132 | /* offsets will differ in the dense stripe case */ | ||
3133 | data->args.offset = data->mds_offset; | ||
3134 | data->ds_clp = NULL; | ||
3135 | data->args.fh = NFS_FH(data->inode); | ||
3136 | data->read_done_cb = nfs4_read_done_cb; | ||
3137 | task->tk_ops = data->mds_ops; | ||
3138 | rpc_task_reset_client(task, NFS_CLIENT(data->inode)); | ||
3139 | } | ||
3140 | EXPORT_SYMBOL_GPL(nfs4_reset_read); | ||
3141 | |||
3142 | static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data) | ||
3099 | { | 3143 | { |
3100 | struct inode *inode = data->inode; | 3144 | struct inode *inode = data->inode; |
3101 | 3145 | ||
3102 | if (!nfs4_sequence_done(task, &data->res.seq_res)) | ||
3103 | return -EAGAIN; | ||
3104 | |||
3105 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) { | 3146 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) { |
3106 | nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client); | 3147 | nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client); |
3107 | return -EAGAIN; | 3148 | return -EAGAIN; |
@@ -3113,11 +3154,41 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) | |||
3113 | return 0; | 3154 | return 0; |
3114 | } | 3155 | } |
3115 | 3156 | ||
3157 | static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) | ||
3158 | { | ||
3159 | if (!nfs4_sequence_done(task, &data->res.seq_res)) | ||
3160 | return -EAGAIN; | ||
3161 | return data->write_done_cb(task, data); | ||
3162 | } | ||
3163 | |||
3164 | /* Reset the the nfs_write_data to send the write to the MDS. */ | ||
3165 | void nfs4_reset_write(struct rpc_task *task, struct nfs_write_data *data) | ||
3166 | { | ||
3167 | dprintk("%s Reset task for i/o through\n", __func__); | ||
3168 | put_lseg(data->lseg); | ||
3169 | data->lseg = NULL; | ||
3170 | data->ds_clp = NULL; | ||
3171 | data->write_done_cb = nfs4_write_done_cb; | ||
3172 | data->args.fh = NFS_FH(data->inode); | ||
3173 | data->args.bitmask = data->res.server->cache_consistency_bitmask; | ||
3174 | data->args.offset = data->mds_offset; | ||
3175 | data->res.fattr = &data->fattr; | ||
3176 | task->tk_ops = data->mds_ops; | ||
3177 | rpc_task_reset_client(task, NFS_CLIENT(data->inode)); | ||
3178 | } | ||
3179 | EXPORT_SYMBOL_GPL(nfs4_reset_write); | ||
3180 | |||
3116 | static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg) | 3181 | static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg) |
3117 | { | 3182 | { |
3118 | struct nfs_server *server = NFS_SERVER(data->inode); | 3183 | struct nfs_server *server = NFS_SERVER(data->inode); |
3119 | 3184 | ||
3120 | data->args.bitmask = server->cache_consistency_bitmask; | 3185 | if (data->lseg) { |
3186 | data->args.bitmask = NULL; | ||
3187 | data->res.fattr = NULL; | ||
3188 | } else | ||
3189 | data->args.bitmask = server->cache_consistency_bitmask; | ||
3190 | if (!data->write_done_cb) | ||
3191 | data->write_done_cb = nfs4_write_done_cb; | ||
3121 | data->res.server = server; | 3192 | data->res.server = server; |
3122 | data->timestamp = jiffies; | 3193 | data->timestamp = jiffies; |
3123 | 3194 | ||
@@ -5118,6 +5189,27 @@ int nfs4_init_session(struct nfs_server *server) | |||
5118 | return ret; | 5189 | return ret; |
5119 | } | 5190 | } |
5120 | 5191 | ||
5192 | int nfs4_init_ds_session(struct nfs_client *clp) | ||
5193 | { | ||
5194 | struct nfs4_session *session = clp->cl_session; | ||
5195 | int ret; | ||
5196 | |||
5197 | if (!test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) | ||
5198 | return 0; | ||
5199 | |||
5200 | ret = nfs4_client_recover_expired_lease(clp); | ||
5201 | if (!ret) | ||
5202 | /* Test for the DS role */ | ||
5203 | if (!is_ds_client(clp)) | ||
5204 | ret = -ENODEV; | ||
5205 | if (!ret) | ||
5206 | ret = nfs4_check_client_ready(clp); | ||
5207 | return ret; | ||
5208 | |||
5209 | } | ||
5210 | EXPORT_SYMBOL_GPL(nfs4_init_ds_session); | ||
5211 | |||
5212 | |||
5121 | /* | 5213 | /* |
5122 | * Renew the cl_session lease. | 5214 | * Renew the cl_session lease. |
5123 | */ | 5215 | */ |
@@ -5648,6 +5740,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = { | |||
5648 | .clear_acl_cache = nfs4_zap_acl_attr, | 5740 | .clear_acl_cache = nfs4_zap_acl_attr, |
5649 | .close_context = nfs4_close_context, | 5741 | .close_context = nfs4_close_context, |
5650 | .open_context = nfs4_atomic_open, | 5742 | .open_context = nfs4_atomic_open, |
5743 | .init_client = nfs4_init_client, | ||
5651 | }; | 5744 | }; |
5652 | 5745 | ||
5653 | static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { | 5746 | static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { |