diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index d54a141a89b3..d86702e604f9 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c @@ -859,7 +859,8 @@ bl_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) if (pgio->pg_lseg && test_bit(NFS_LSEG_UNAVAILABLE, &pgio->pg_lseg->pls_flags)) { - pnfs_error_mark_layout_for_return(pgio->pg_inode, pgio->pg_lseg); + pnfs_error_mark_layout_for_return(pgio->pg_inode, pgio->pg_lseg, + NULL); pnfs_set_lo_fail(pgio->pg_lseg); nfs_pageio_reset_read_mds(pgio); } @@ -921,7 +922,8 @@ bl_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) if (pgio->pg_lseg && test_bit(NFS_LSEG_UNAVAILABLE, &pgio->pg_lseg->pls_flags)) { - pnfs_error_mark_layout_for_return(pgio->pg_inode, pgio->pg_lseg); + pnfs_error_mark_layout_for_return(pgio->pg_inode, pgio->pg_lseg, + NULL); pnfs_set_lo_fail(pgio->pg_lseg); nfs_pageio_reset_write_mds(pgio); } diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index c9b71dbae9ea..9d836cb72e78 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c @@ -292,7 +292,7 @@ static u32 initiate_file_draining(struct nfs_client *clp, switch (pnfs_mark_matching_lsegs_return(lo, &free_me_list, &args->cbl_range, be32_to_cpu(args->cbl_stateid.seqid), - args->cbl_layoutchanged)) { + args->cbl_layoutchanged, NULL)) { case 0: case -EBUSY: /* There are layout segments that need to be returned */ diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c index 0d53277f972e..d1c08d529e02 100644 --- a/fs/nfs/filelayout/filelayout.c +++ b/fs/nfs/filelayout/filelayout.c @@ -186,7 +186,7 @@ static int filelayout_async_handle_error(struct rpc_task *task, dprintk("%s DS connection error %d\n", __func__, task->tk_status); nfs4_mark_deviceid_unavailable(devid); - pnfs_error_mark_layout_for_return(inode, lseg); + pnfs_error_mark_layout_for_return(inode, lseg, NULL); pnfs_set_lo_fail(lseg); rpc_wake_up(&tbl->slot_tbl_waitq); fallthrough; @@ -856,7 +856,7 @@ fl_pnfs_update_layout(struct inode *ino, status = filelayout_check_deviceid(lo, fl, gfp_flags); if (status) { - pnfs_error_mark_layout_for_return(ino, lseg); + pnfs_error_mark_layout_for_return(ino, lseg, NULL); pnfs_set_lo_fail(lseg); pnfs_put_lseg(lseg); lseg = NULL; diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index 6fa6aa82d509..d27e0adb2709 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c @@ -1281,7 +1281,7 @@ static void ff_layout_resend_pnfs_read(struct nfs_pgio_header *hdr) mirror_ds = ff_layout_choose_any_ds_for_read(hdr->lseg, idx, &new_idx, hdr->args.offset, &dss_id); if (IS_ERR(mirror_ds)) { - pnfs_error_mark_layout_for_return(hdr->inode, hdr->lseg); + pnfs_error_mark_layout_for_return(hdr->inode, hdr->lseg, NULL); } else { nfs4_ff_layout_put_deviceid(mirror_ds); ff_layout_send_layouterror(hdr->lseg); @@ -1294,7 +1294,7 @@ static void ff_layout_reset_read(struct nfs_pgio_header *hdr) struct rpc_task *task = &hdr->task; pnfs_layoutcommit_inode(hdr->inode, false); - pnfs_error_mark_layout_for_return(hdr->inode, hdr->lseg); + pnfs_error_mark_layout_for_return(hdr->inode, hdr->lseg, NULL); if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) { dprintk("%s Reset task %5u for i/o through MDS " @@ -1594,7 +1594,7 @@ static void ff_layout_io_track_ds_error(struct pnfs_layout_segment *lseg, fallthrough; default: pnfs_error_mark_layout_for_return(lseg->pls_layout->plh_inode, - lseg); + lseg, NULL); } out: @@ -2256,7 +2256,7 @@ ff_layout_read_pagelist(struct nfs_pgio_header *hdr) * FF_FLAGS_NO_IO_THRU_MDS: force fresh LAYOUTGET, * never fall through to MDS I/O. */ - pnfs_error_mark_layout_for_return(hdr->inode, lseg); + pnfs_error_mark_layout_for_return(hdr->inode, lseg, NULL); return PNFS_TRY_AGAIN; } trace_pnfs_mds_fallback_read_pagelist(hdr->inode, @@ -2359,7 +2359,7 @@ ff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync) * FF_FLAGS_NO_IO_THRU_MDS: force fresh LAYOUTGET, * never fall through to MDS I/O. */ - pnfs_error_mark_layout_for_return(hdr->inode, lseg); + pnfs_error_mark_layout_for_return(hdr->inode, lseg, NULL); return PNFS_TRY_AGAIN; } trace_pnfs_mds_fallback_write_pagelist(hdr->inode, @@ -2490,7 +2490,8 @@ static bool ff_layout_match_io(const struct rpc_task *task, const void *data) return false; } -static void ff_layout_cancel_io(struct pnfs_layout_segment *lseg) +static void ff_layout_cancel_io(struct pnfs_layout_segment *lseg, + const struct nfs4_deviceid *devid) { struct nfs4_ff_layout_segment *flseg = FF_LAYOUT_LSEG(lseg); struct nfs4_ff_layout_mirror *mirror; @@ -2503,6 +2504,9 @@ static void ff_layout_cancel_io(struct pnfs_layout_segment *lseg) for (idx = 0; idx < flseg->mirror_array_cnt; idx++) { mirror = flseg->mirror_array[idx]; for (dss_id = 0; dss_id < mirror->dss_count; dss_id++) { + if (devid && memcmp(&mirror->dss[dss_id].devid, devid, + sizeof(*devid)) != 0) + continue; rcu_read_lock(); mirror_ds = rcu_dereference(mirror->dss[dss_id].mirror_ds); if (IS_ERR_OR_NULL(mirror_ds) || diff --git a/fs/nfs/flexfilelayout/flexfilelayoutdev.c b/fs/nfs/flexfilelayout/flexfilelayoutdev.c index bc95628a811f..7bb0f2094e9d 100644 --- a/fs/nfs/flexfilelayout/flexfilelayoutdev.c +++ b/fs/nfs/flexfilelayout/flexfilelayoutdev.c @@ -453,7 +453,7 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, opnum, GFP_NOIO); ff_layout_send_layouterror(lseg); if (opnum != OP_READ || !ff_layout_has_available_ds(lseg)) - pnfs_error_mark_layout_for_return(ino, lseg); + pnfs_error_mark_layout_for_return(ino, lseg, NULL); ds = ERR_PTR(status); out: return ds; diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 79f671355e5b..93a0852e1e8a 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -433,7 +433,7 @@ bool nfs4_layout_refresh_old_stateid(nfs4_stateid *dst, } /* Try to update the seqid to the most recent */ err = pnfs_mark_matching_lsegs_return(lo, &head, &range, 0, - true); + true, NULL); if (err != -EBUSY) { dst->seqid = lo->plh_stateid.seqid; *dst_range = range; @@ -487,7 +487,8 @@ static int pnfs_mark_layout_stateid_return(struct pnfs_layout_hdr *lo, .length = NFS4_MAX_UINT64, }; - return pnfs_mark_matching_lsegs_return(lo, lseg_list, &range, seq, true); + return pnfs_mark_matching_lsegs_return(lo, lseg_list, &range, seq, true, + NULL); } static int @@ -525,7 +526,7 @@ pnfs_layout_io_set_failed(struct pnfs_layout_hdr *lo, u32 iomode) spin_lock(&inode->i_lock); pnfs_layout_set_fail_bit(lo, pnfs_iomode_to_fail_bit(iomode)); - pnfs_mark_matching_lsegs_return(lo, &head, &range, 0, true); + pnfs_mark_matching_lsegs_return(lo, &head, &range, 0, true, NULL); spin_unlock(&inode->i_lock); pnfs_free_lseg_list(&head); dprintk("%s Setting layout IOMODE_%s fail bit\n", __func__, @@ -740,7 +741,7 @@ pnfs_mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo, if (mark_lseg_invalid(lseg, tmp_list)) continue; remaining++; - pnfs_lseg_cancel_io(server, lseg); + pnfs_lseg_cancel_io(server, lseg, NULL); } dprintk("%s:Return %i\n", __func__, remaining); return remaining; @@ -1476,7 +1477,7 @@ _pnfs_return_layout(struct inode *ino) } valid_layout = pnfs_layout_is_valid(lo); pnfs_clear_layoutcommit(ino, &tmp_list); - pnfs_mark_matching_lsegs_return(lo, &tmp_list, &range, 0, true); + pnfs_mark_matching_lsegs_return(lo, &tmp_list, &range, 0, true, NULL); /* Don't send a LAYOUTRETURN if list was initially empty */ @@ -2658,7 +2659,8 @@ pnfs_layout_process(struct nfs4_layoutget *lgp) .iomode = IOMODE_ANY, .length = NFS4_MAX_UINT64, }; - pnfs_mark_matching_lsegs_return(lo, &free_me, &range, 0, true); + pnfs_mark_matching_lsegs_return(lo, &free_me, &range, 0, true, + NULL); goto out_forget; } else { /* We have a completely new layout */ @@ -2691,6 +2693,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp) * @return_range: describe layout segment ranges to be returned * @seq: stateid seqid to match * @cancel_io: signal io be cancelled + * @devid: only cancel io directed at this device (all devices if NULL) * * This function is mainly intended for use by layoutrecall. It attempts * to free the layout segment immediately, or else to mark it for return @@ -2705,7 +2708,8 @@ int pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo, struct list_head *tmp_list, const struct pnfs_layout_range *return_range, - u32 seq, bool cancel_io) + u32 seq, bool cancel_io, + const struct nfs4_deviceid *devid) { struct pnfs_layout_segment *lseg, *next; struct nfs_server *server = NFS_SERVER(lo->plh_inode); @@ -2732,7 +2736,7 @@ pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo, remaining++; set_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags); if (cancel_io) - pnfs_lseg_cancel_io(server, lseg); + pnfs_lseg_cancel_io(server, lseg, devid); } if (remaining) { @@ -2750,7 +2754,8 @@ pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo, static void pnfs_mark_layout_for_return(struct inode *inode, - const struct pnfs_layout_range *range) + const struct pnfs_layout_range *range, + const struct nfs4_deviceid *devid) { struct pnfs_layout_hdr *lo; bool return_now = false; @@ -2768,7 +2773,7 @@ pnfs_mark_layout_for_return(struct inode *inode, * for how it works. */ if (pnfs_mark_matching_lsegs_return(lo, &lo->plh_return_segs, range, 0, - true) != -EBUSY) { + true, devid) != -EBUSY) { const struct cred *cred; nfs4_stateid stateid; enum pnfs_iomode iomode; @@ -2785,7 +2790,8 @@ pnfs_mark_layout_for_return(struct inode *inode, } void pnfs_error_mark_layout_for_return(struct inode *inode, - struct pnfs_layout_segment *lseg) + struct pnfs_layout_segment *lseg, + const struct nfs4_deviceid *devid) { struct pnfs_layout_range range = { .iomode = lseg->pls_range.iomode, @@ -2793,7 +2799,7 @@ void pnfs_error_mark_layout_for_return(struct inode *inode, .length = NFS4_MAX_UINT64, }; - pnfs_mark_layout_for_return(inode, &range); + pnfs_mark_layout_for_return(inode, &range, devid); } EXPORT_SYMBOL_GPL(pnfs_error_mark_layout_for_return); @@ -2883,7 +2889,7 @@ static int pnfs_layout_return_unused_byserver(struct nfs_server *server, pnfs_get_layout_hdr(lo); pnfs_set_plh_return_info(lo, range->iomode, 0); if (pnfs_mark_matching_lsegs_return(lo, &lo->plh_return_segs, - range, 0, true) != 0 || + range, 0, true, NULL) != 0 || !pnfs_prepare_layoutreturn(lo, &stateid, &cred, &iomode)) { spin_unlock(&inode->i_lock); rcu_read_unlock(); diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 5cde5db63d29..2774d4adf4c3 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h @@ -197,7 +197,8 @@ struct pnfs_layoutdriver_type { int (*prepare_layoutcommit) (struct nfs4_layoutcommit_args *args); int (*prepare_layoutstats) (struct nfs42_layoutstat_args *args); - void (*cancel_io)(struct pnfs_layout_segment *lseg); + void (*cancel_io)(struct pnfs_layout_segment *lseg, + const struct nfs4_deviceid *devid); }; struct pnfs_commit_ops { @@ -320,7 +321,8 @@ int pnfs_mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo, int pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo, struct list_head *tmp_list, const struct pnfs_layout_range *recall_range, - u32 seq, bool cancel_io); + u32 seq, bool cancel_io, + const struct nfs4_deviceid *devid); int pnfs_mark_layout_stateid_invalid(struct pnfs_layout_hdr *lo, struct list_head *lseg_list); bool pnfs_roc(struct inode *ino, struct nfs4_layoutreturn_args *args, @@ -370,7 +372,8 @@ int pnfs_read_done_resend_to_mds(struct nfs_pgio_header *); int pnfs_write_done_resend_to_mds(struct nfs_pgio_header *); struct nfs4_threshold *pnfs_mdsthreshold_alloc(void); void pnfs_error_mark_layout_for_return(struct inode *inode, - struct pnfs_layout_segment *lseg); + struct pnfs_layout_segment *lseg, + const struct nfs4_deviceid *devid); void pnfs_layout_return_unused_byclid(struct nfs_client *clp, enum pnfs_iomode iomode); void pnfs_layout_reresolve_deviceid_byclid(struct nfs_client *clp, @@ -774,10 +777,11 @@ pnfs_lseg_request_intersecting(struct pnfs_layout_segment *lseg, struct nfs_page } static inline void pnfs_lseg_cancel_io(struct nfs_server *server, - struct pnfs_layout_segment *lseg) + struct pnfs_layout_segment *lseg, + const struct nfs4_deviceid *devid) { if (server->pnfs_curr_ld->cancel_io) - server->pnfs_curr_ld->cancel_io(lseg); + server->pnfs_curr_ld->cancel_io(lseg, devid); } extern unsigned int layoutstats_timer;