|
@@ -796,45 +796,18 @@ pnfs_layoutgets_blocked(const struct pnfs_layout_hdr *lo)
|
|
|
test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags);
|
|
|
}
|
|
|
|
|
|
-int
|
|
|
-pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,
|
|
|
- const struct pnfs_layout_range *range,
|
|
|
- struct nfs4_state *open_state)
|
|
|
-{
|
|
|
- int status = 0;
|
|
|
-
|
|
|
- dprintk("--> %s\n", __func__);
|
|
|
- spin_lock(&lo->plh_inode->i_lock);
|
|
|
- if (pnfs_layoutgets_blocked(lo)) {
|
|
|
- status = -EAGAIN;
|
|
|
- } else if (!nfs4_valid_open_stateid(open_state)) {
|
|
|
- status = -EBADF;
|
|
|
- } else if (list_empty(&lo->plh_segs) ||
|
|
|
- test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags)) {
|
|
|
- int seq;
|
|
|
-
|
|
|
- do {
|
|
|
- seq = read_seqbegin(&open_state->seqlock);
|
|
|
- nfs4_stateid_copy(dst, &open_state->stateid);
|
|
|
- } while (read_seqretry(&open_state->seqlock, seq));
|
|
|
- } else
|
|
|
- nfs4_stateid_copy(dst, &lo->plh_stateid);
|
|
|
- spin_unlock(&lo->plh_inode->i_lock);
|
|
|
- dprintk("<-- %s\n", __func__);
|
|
|
- return status;
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
-* Get layout from server.
|
|
|
-* for now, assume that whole file layouts are requested.
|
|
|
-* arg->offset: 0
|
|
|
-* arg->length: all ones
|
|
|
-*/
|
|
|
+ * Get layout from server.
|
|
|
+ * for now, assume that whole file layouts are requested.
|
|
|
+ * arg->offset: 0
|
|
|
+ * arg->length: all ones
|
|
|
+ */
|
|
|
static struct pnfs_layout_segment *
|
|
|
send_layoutget(struct pnfs_layout_hdr *lo,
|
|
|
struct nfs_open_context *ctx,
|
|
|
+ nfs4_stateid *stateid,
|
|
|
const struct pnfs_layout_range *range,
|
|
|
- gfp_t gfp_flags)
|
|
|
+ long *timeout, gfp_t gfp_flags)
|
|
|
{
|
|
|
struct inode *ino = lo->plh_inode;
|
|
|
struct nfs_server *server = NFS_SERVER(ino);
|
|
@@ -868,10 +841,11 @@ send_layoutget(struct pnfs_layout_hdr *lo,
|
|
|
lgp->args.type = server->pnfs_curr_ld->id;
|
|
|
lgp->args.inode = ino;
|
|
|
lgp->args.ctx = get_nfs_open_context(ctx);
|
|
|
+ nfs4_stateid_copy(&lgp->args.stateid, stateid);
|
|
|
lgp->gfp_flags = gfp_flags;
|
|
|
lgp->cred = lo->plh_lc_cred;
|
|
|
|
|
|
- return nfs4_proc_layoutget(lgp, gfp_flags);
|
|
|
+ return nfs4_proc_layoutget(lgp, timeout, gfp_flags);
|
|
|
}
|
|
|
|
|
|
static void pnfs_clear_layoutcommit(struct inode *inode,
|
|
@@ -1511,27 +1485,30 @@ pnfs_update_layout(struct inode *ino,
|
|
|
.offset = pos,
|
|
|
.length = count,
|
|
|
};
|
|
|
- unsigned pg_offset;
|
|
|
+ unsigned pg_offset, seq;
|
|
|
struct nfs_server *server = NFS_SERVER(ino);
|
|
|
struct nfs_client *clp = server->nfs_client;
|
|
|
- struct pnfs_layout_hdr *lo;
|
|
|
+ struct pnfs_layout_hdr *lo = NULL;
|
|
|
struct pnfs_layout_segment *lseg = NULL;
|
|
|
+ nfs4_stateid stateid;
|
|
|
+ long timeout = 0;
|
|
|
+ unsigned long giveup = jiffies + rpc_get_timeout(server->client);
|
|
|
bool first;
|
|
|
|
|
|
if (!pnfs_enabled_sb(NFS_SERVER(ino))) {
|
|
|
- trace_pnfs_update_layout(ino, pos, count, iomode, NULL,
|
|
|
+ trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
|
|
|
PNFS_UPDATE_LAYOUT_NO_PNFS);
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
if (iomode == IOMODE_READ && i_size_read(ino) == 0) {
|
|
|
- trace_pnfs_update_layout(ino, pos, count, iomode, NULL,
|
|
|
+ trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
|
|
|
PNFS_UPDATE_LAYOUT_RD_ZEROLEN);
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
if (pnfs_within_mdsthreshold(ctx, ino, iomode)) {
|
|
|
- trace_pnfs_update_layout(ino, pos, count, iomode, NULL,
|
|
|
+ trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
|
|
|
PNFS_UPDATE_LAYOUT_MDSTHRESH);
|
|
|
goto out;
|
|
|
}
|
|
@@ -1542,14 +1519,14 @@ lookup_again:
|
|
|
lo = pnfs_find_alloc_layout(ino, ctx, gfp_flags);
|
|
|
if (lo == NULL) {
|
|
|
spin_unlock(&ino->i_lock);
|
|
|
- trace_pnfs_update_layout(ino, pos, count, iomode, NULL,
|
|
|
+ trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
|
|
|
PNFS_UPDATE_LAYOUT_NOMEM);
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
/* Do we even need to bother with this? */
|
|
|
if (test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags)) {
|
|
|
- trace_pnfs_update_layout(ino, pos, count, iomode, lo,
|
|
|
+ trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
|
|
|
PNFS_UPDATE_LAYOUT_BULK_RECALL);
|
|
|
dprintk("%s matches recall, use MDS\n", __func__);
|
|
|
goto out_unlock;
|
|
@@ -1557,14 +1534,34 @@ lookup_again:
|
|
|
|
|
|
/* if LAYOUTGET already failed once we don't try again */
|
|
|
if (pnfs_layout_io_test_failed(lo, iomode)) {
|
|
|
- trace_pnfs_update_layout(ino, pos, count, iomode, lo,
|
|
|
+ trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
|
|
|
PNFS_UPDATE_LAYOUT_IO_TEST_FAIL);
|
|
|
goto out_unlock;
|
|
|
}
|
|
|
|
|
|
- first = list_empty(&lo->plh_segs);
|
|
|
- if (first) {
|
|
|
- /* The first layoutget for the file. Need to serialize per
|
|
|
+ lseg = pnfs_find_lseg(lo, &arg);
|
|
|
+ if (lseg) {
|
|
|
+ trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
|
|
|
+ PNFS_UPDATE_LAYOUT_FOUND_CACHED);
|
|
|
+ goto out_unlock;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!nfs4_valid_open_stateid(ctx->state)) {
|
|
|
+ trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
|
|
|
+ PNFS_UPDATE_LAYOUT_INVALID_OPEN);
|
|
|
+ goto out_unlock;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Choose a stateid for the LAYOUTGET. If we don't have a layout
|
|
|
+ * stateid, or it has been invalidated, then we must use the open
|
|
|
+ * stateid.
|
|
|
+ */
|
|
|
+ if (lo->plh_stateid.seqid == 0 ||
|
|
|
+ test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags)) {
|
|
|
+
|
|
|
+ /*
|
|
|
+ * The first layoutget for the file. Need to serialize per
|
|
|
* RFC 5661 Errata 3208.
|
|
|
*/
|
|
|
if (test_and_set_bit(NFS_LAYOUT_FIRST_LAYOUTGET,
|
|
@@ -1573,18 +1570,17 @@ lookup_again:
|
|
|
wait_on_bit(&lo->plh_flags, NFS_LAYOUT_FIRST_LAYOUTGET,
|
|
|
TASK_UNINTERRUPTIBLE);
|
|
|
pnfs_put_layout_hdr(lo);
|
|
|
+ dprintk("%s retrying\n", __func__);
|
|
|
goto lookup_again;
|
|
|
}
|
|
|
+
|
|
|
+ first = true;
|
|
|
+ do {
|
|
|
+ seq = read_seqbegin(&ctx->state->seqlock);
|
|
|
+ nfs4_stateid_copy(&stateid, &ctx->state->stateid);
|
|
|
+ } while (read_seqretry(&ctx->state->seqlock, seq));
|
|
|
} else {
|
|
|
- /* Check to see if the layout for the given range
|
|
|
- * already exists
|
|
|
- */
|
|
|
- lseg = pnfs_find_lseg(lo, &arg);
|
|
|
- if (lseg) {
|
|
|
- trace_pnfs_update_layout(ino, pos, count, iomode, lo,
|
|
|
- PNFS_UPDATE_LAYOUT_FOUND_CACHED);
|
|
|
- goto out_unlock;
|
|
|
- }
|
|
|
+ nfs4_stateid_copy(&stateid, &lo->plh_stateid);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -1599,15 +1595,17 @@ lookup_again:
|
|
|
pnfs_clear_first_layoutget(lo);
|
|
|
pnfs_put_layout_hdr(lo);
|
|
|
dprintk("%s retrying\n", __func__);
|
|
|
+ trace_pnfs_update_layout(ino, pos, count, iomode, lo,
|
|
|
+ lseg, PNFS_UPDATE_LAYOUT_RETRY);
|
|
|
goto lookup_again;
|
|
|
}
|
|
|
- trace_pnfs_update_layout(ino, pos, count, iomode, lo,
|
|
|
+ trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
|
|
|
PNFS_UPDATE_LAYOUT_RETURN);
|
|
|
goto out_put_layout_hdr;
|
|
|
}
|
|
|
|
|
|
if (pnfs_layoutgets_blocked(lo)) {
|
|
|
- trace_pnfs_update_layout(ino, pos, count, iomode, lo,
|
|
|
+ trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
|
|
|
PNFS_UPDATE_LAYOUT_BLOCKED);
|
|
|
goto out_unlock;
|
|
|
}
|
|
@@ -1632,26 +1630,36 @@ lookup_again:
|
|
|
if (arg.length != NFS4_MAX_UINT64)
|
|
|
arg.length = PAGE_ALIGN(arg.length);
|
|
|
|
|
|
- lseg = send_layoutget(lo, ctx, &arg, gfp_flags);
|
|
|
+ lseg = send_layoutget(lo, ctx, &stateid, &arg, &timeout, gfp_flags);
|
|
|
+ trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
|
|
|
+ PNFS_UPDATE_LAYOUT_SEND_LAYOUTGET);
|
|
|
if (IS_ERR(lseg)) {
|
|
|
- if (lseg == ERR_PTR(-EAGAIN)) {
|
|
|
+ switch(PTR_ERR(lseg)) {
|
|
|
+ case -ERECALLCONFLICT:
|
|
|
+ if (time_after(jiffies, giveup))
|
|
|
+ lseg = NULL;
|
|
|
+ /* Fallthrough */
|
|
|
+ case -EAGAIN:
|
|
|
+ pnfs_put_layout_hdr(lo);
|
|
|
if (first)
|
|
|
pnfs_clear_first_layoutget(lo);
|
|
|
- pnfs_put_layout_hdr(lo);
|
|
|
- goto lookup_again;
|
|
|
- }
|
|
|
-
|
|
|
- if (!nfs_error_is_fatal(PTR_ERR(lseg))) {
|
|
|
- pnfs_layout_clear_fail_bit(lo, pnfs_iomode_to_fail_bit(iomode));
|
|
|
- lseg = NULL;
|
|
|
+ if (lseg) {
|
|
|
+ trace_pnfs_update_layout(ino, pos, count,
|
|
|
+ iomode, lo, lseg, PNFS_UPDATE_LAYOUT_RETRY);
|
|
|
+ goto lookup_again;
|
|
|
+ }
|
|
|
+ /* Fallthrough */
|
|
|
+ default:
|
|
|
+ if (!nfs_error_is_fatal(PTR_ERR(lseg))) {
|
|
|
+ pnfs_layout_clear_fail_bit(lo, pnfs_iomode_to_fail_bit(iomode));
|
|
|
+ lseg = NULL;
|
|
|
+ }
|
|
|
}
|
|
|
} else {
|
|
|
pnfs_layout_clear_fail_bit(lo, pnfs_iomode_to_fail_bit(iomode));
|
|
|
}
|
|
|
|
|
|
atomic_dec(&lo->plh_outstanding);
|
|
|
- trace_pnfs_update_layout(ino, pos, count, iomode, lo,
|
|
|
- PNFS_UPDATE_LAYOUT_SEND_LAYOUTGET);
|
|
|
out_put_layout_hdr:
|
|
|
if (first)
|
|
|
pnfs_clear_first_layoutget(lo);
|