NFSv4/flexfiles: Abort I/O early if the layout segment was invalidated
[sfrench/cifs-2.6.git] / fs / nfs / flexfilelayout / flexfilelayout.c
index 63abe705f4cabe133d28e94236039e7a0c69887d..a8e9bdd978e74f5ea16a0618eb561f4cba95c67f 100644 (file)
@@ -410,7 +410,7 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh,
        for (i = 0; i < fls->mirror_array_cnt; i++) {
                struct nfs4_ff_layout_mirror *mirror;
                struct cred *kcred;
-               const struct cred *cred;
+               const struct cred __rcu *cred;
                kuid_t uid;
                kgid_t gid;
                u32 ds_count, fh_count, id;
@@ -501,7 +501,7 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh,
                        goto out_err_free;
                kcred->fsuid = uid;
                kcred->fsgid = gid;
-               cred = kcred;
+               cred = RCU_INITIALIZER(kcred);
 
                if (lgr->range.iomode == IOMODE_READ)
                        rcu_assign_pointer(fls->mirror_array[i]->ro_cred, cred);
@@ -1071,6 +1071,8 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task,
                break;
        case -NFS4ERR_RETRY_UNCACHED_REP:
                break;
+       case -EAGAIN:
+               return -NFS4ERR_RESET_TO_PNFS;
        /* Invalidate Layout errors */
        case -NFS4ERR_PNFS_NO_LAYOUT:
        case -ESTALE:           /* mapped NFS4ERR_STALE */
@@ -1131,6 +1133,7 @@ static int ff_layout_async_handle_error_v3(struct rpc_task *task,
        case -EBADHANDLE:
        case -ELOOP:
        case -ENOSPC:
+       case -EAGAIN:
                break;
        case -EJUKEBOX:
                nfs_inc_stats(lseg->pls_layout->plh_inode, NFSIOS_DELAY);
@@ -1369,6 +1372,16 @@ static void ff_layout_read_prepare_v4(struct rpc_task *task, void *data)
        ff_layout_read_prepare_common(task, hdr);
 }
 
+static void
+ff_layout_io_prepare_transmit(struct rpc_task *task,
+               void *data)
+{
+       struct nfs_pgio_header *hdr = data;
+
+       if (!pnfs_is_valid_lseg(hdr->lseg))
+               rpc_exit(task, -EAGAIN);
+}
+
 static void ff_layout_read_call_done(struct rpc_task *task, void *data)
 {
        struct nfs_pgio_header *hdr = data;
@@ -1657,6 +1670,7 @@ static void ff_layout_commit_release(void *data)
 
 static const struct rpc_call_ops ff_layout_read_call_ops_v3 = {
        .rpc_call_prepare = ff_layout_read_prepare_v3,
+       .rpc_call_prepare_transmit = ff_layout_io_prepare_transmit,
        .rpc_call_done = ff_layout_read_call_done,
        .rpc_count_stats = ff_layout_read_count_stats,
        .rpc_release = ff_layout_read_release,
@@ -1664,6 +1678,7 @@ static const struct rpc_call_ops ff_layout_read_call_ops_v3 = {
 
 static const struct rpc_call_ops ff_layout_read_call_ops_v4 = {
        .rpc_call_prepare = ff_layout_read_prepare_v4,
+       .rpc_call_prepare_transmit = ff_layout_io_prepare_transmit,
        .rpc_call_done = ff_layout_read_call_done,
        .rpc_count_stats = ff_layout_read_count_stats,
        .rpc_release = ff_layout_read_release,
@@ -1671,6 +1686,7 @@ static const struct rpc_call_ops ff_layout_read_call_ops_v4 = {
 
 static const struct rpc_call_ops ff_layout_write_call_ops_v3 = {
        .rpc_call_prepare = ff_layout_write_prepare_v3,
+       .rpc_call_prepare_transmit = ff_layout_io_prepare_transmit,
        .rpc_call_done = ff_layout_write_call_done,
        .rpc_count_stats = ff_layout_write_count_stats,
        .rpc_release = ff_layout_write_release,
@@ -1678,6 +1694,7 @@ static const struct rpc_call_ops ff_layout_write_call_ops_v3 = {
 
 static const struct rpc_call_ops ff_layout_write_call_ops_v4 = {
        .rpc_call_prepare = ff_layout_write_prepare_v4,
+       .rpc_call_prepare_transmit = ff_layout_io_prepare_transmit,
        .rpc_call_done = ff_layout_write_call_done,
        .rpc_count_stats = ff_layout_write_count_stats,
        .rpc_release = ff_layout_write_release,
@@ -2036,7 +2053,7 @@ ff_layout_encode_layoutreturn(struct xdr_stream *xdr,
 
        dprintk("%s: Begin\n", __func__);
 
-       xdr_init_encode(&tmp_xdr, &tmp_buf, NULL);
+       xdr_init_encode(&tmp_xdr, &tmp_buf, NULL, NULL);
 
        ff_layout_encode_ioerr(&tmp_xdr, args, ff_args);
        ff_layout_encode_iostats_array(&tmp_xdr, args, ff_args);