Skip to content

Commit 0cf21c6

Browse files
committed
Merge tag 'nfs-for-4.8-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client bugfixes from Trond Myklebust: "Highlights include: Stable patches: - Fix a refcount leak in nfs_callback_up_net - Fix an Oopsable condition when the flexfile pNFS driver connection to the DS fails - Fix an Oopsable condition in NFSv4.1 server callback races - Ensure pNFS clients stop doing I/O to the DS if their lease has expired, as required by the NFSv4.1 protocol Bugfixes: - Fix potential looping in the NFSv4.x migration code - Patch series to close callback races for OPEN, LAYOUTGET and LAYOUTRETURN - Silence WARN_ON when NFSv4.1 over RDMA is in use - Fix a LAYOUTCOMMIT race in the pNFS/blocks client - Fix pNFS timeout issues when the DS fails" * tag 'nfs-for-4.8-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: NFSv4.x: Fix a refcount leak in nfs_callback_up_net NFS4: Avoid migration loops pNFS/flexfiles: Fix an Oopsable condition when connection to the DS fails NFSv4.1: Remove obsolete and incorrrect assignment in nfs4_callback_sequence NFSv4.1: Close callback races for OPEN, LAYOUTGET and LAYOUTRETURN NFSv4.1: Defer bumping the slot sequence number until we free the slot NFSv4.1: Delay callback processing when there are referring triples NFSv4.1: Fix Oopsable condition in server callback races SUNRPC: Silence WARN_ON when NFSv4.1 over RDMA is in use pnfs/blocklayout: update last_write_offset atomically with extents pNFS: The client must not do I/O to the DS if it's lease has expired pNFS: Handle NFS4ERR_OLD_STATEID correctly in LAYOUTSTAT calls pNFS/flexfiles: Set reasonable default retrans values for the data channel NFS: Allow the mount option retrans=0 pNFS/flexfiles: Fix layoutstat periodic reporting
2 parents 0d025d2 + 98b0f80 commit 0cf21c6

File tree

18 files changed

+244
-78
lines changed

18 files changed

+244
-78
lines changed

fs/nfs/blocklayout/blocklayout.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ static void bl_write_cleanup(struct work_struct *work)
346346
PAGE_SIZE - 1) & (loff_t)PAGE_MASK;
347347

348348
ext_tree_mark_written(bl, start >> SECTOR_SHIFT,
349-
(end - start) >> SECTOR_SHIFT);
349+
(end - start) >> SECTOR_SHIFT, end);
350350
}
351351

352352
pnfs_ld_write_done(hdr);

fs/nfs/blocklayout/blocklayout.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ struct pnfs_block_layout {
141141
struct rb_root bl_ext_ro;
142142
spinlock_t bl_ext_lock; /* Protects list manipulation */
143143
bool bl_scsi_layout;
144+
u64 bl_lwb;
144145
};
145146

146147
static inline struct pnfs_block_layout *
@@ -182,7 +183,7 @@ int ext_tree_insert(struct pnfs_block_layout *bl,
182183
int ext_tree_remove(struct pnfs_block_layout *bl, bool rw, sector_t start,
183184
sector_t end);
184185
int ext_tree_mark_written(struct pnfs_block_layout *bl, sector_t start,
185-
sector_t len);
186+
sector_t len, u64 lwb);
186187
bool ext_tree_lookup(struct pnfs_block_layout *bl, sector_t isect,
187188
struct pnfs_block_extent *ret, bool rw);
188189
int ext_tree_prepare_commit(struct nfs4_layoutcommit_args *arg);

fs/nfs/blocklayout/extent_tree.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ ext_tree_split(struct rb_root *root, struct pnfs_block_extent *be,
402402

403403
int
404404
ext_tree_mark_written(struct pnfs_block_layout *bl, sector_t start,
405-
sector_t len)
405+
sector_t len, u64 lwb)
406406
{
407407
struct rb_root *root = &bl->bl_ext_rw;
408408
sector_t end = start + len;
@@ -471,6 +471,8 @@ ext_tree_mark_written(struct pnfs_block_layout *bl, sector_t start,
471471
}
472472
}
473473
out:
474+
if (bl->bl_lwb < lwb)
475+
bl->bl_lwb = lwb;
474476
spin_unlock(&bl->bl_ext_lock);
475477

476478
__ext_put_deviceids(&tmp);
@@ -518,7 +520,7 @@ static __be32 *encode_scsi_range(struct pnfs_block_extent *be, __be32 *p)
518520
}
519521

520522
static int ext_tree_encode_commit(struct pnfs_block_layout *bl, __be32 *p,
521-
size_t buffer_size, size_t *count)
523+
size_t buffer_size, size_t *count, __u64 *lastbyte)
522524
{
523525
struct pnfs_block_extent *be;
524526
int ret = 0;
@@ -542,6 +544,8 @@ static int ext_tree_encode_commit(struct pnfs_block_layout *bl, __be32 *p,
542544
p = encode_block_extent(be, p);
543545
be->be_tag = EXTENT_COMMITTING;
544546
}
547+
*lastbyte = bl->bl_lwb - 1;
548+
bl->bl_lwb = 0;
545549
spin_unlock(&bl->bl_ext_lock);
546550

547551
return ret;
@@ -564,7 +568,7 @@ ext_tree_prepare_commit(struct nfs4_layoutcommit_args *arg)
564568
arg->layoutupdate_pages = &arg->layoutupdate_page;
565569

566570
retry:
567-
ret = ext_tree_encode_commit(bl, start_p + 1, buffer_size, &count);
571+
ret = ext_tree_encode_commit(bl, start_p + 1, buffer_size, &count, &arg->lastbytewritten);
568572
if (unlikely(ret)) {
569573
ext_tree_free_commitdata(arg, buffer_size);
570574

fs/nfs/callback.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ static int nfs_callback_up_net(int minorversion, struct svc_serv *serv,
275275
err_socks:
276276
svc_rpcb_cleanup(serv, net);
277277
err_bind:
278+
nn->cb_users[minorversion]--;
278279
dprintk("NFS: Couldn't create callback socket: err = %d; "
279280
"net = %p\n", ret, net);
280281
return ret;

fs/nfs/callback_proc.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -454,11 +454,8 @@ static bool referring_call_exists(struct nfs_client *clp,
454454
((u32 *)&rclist->rcl_sessionid.data)[3],
455455
ref->rc_sequenceid, ref->rc_slotid);
456456

457-
spin_lock(&tbl->slot_tbl_lock);
458-
status = (test_bit(ref->rc_slotid, tbl->used_slots) &&
459-
tbl->slots[ref->rc_slotid].seq_nr ==
460-
ref->rc_sequenceid);
461-
spin_unlock(&tbl->slot_tbl_lock);
457+
status = nfs4_slot_wait_on_seqid(tbl, ref->rc_slotid,
458+
ref->rc_sequenceid, HZ >> 1) < 0;
462459
if (status)
463460
goto out;
464461
}
@@ -487,7 +484,6 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
487484
goto out;
488485

489486
tbl = &clp->cl_session->bc_slot_table;
490-
slot = tbl->slots + args->csa_slotid;
491487

492488
/* Set up res before grabbing the spinlock */
493489
memcpy(&res->csr_sessionid, &args->csa_sessionid,

fs/nfs/client.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -426,17 +426,17 @@ EXPORT_SYMBOL_GPL(nfs_mark_client_ready);
426426
* Initialise the timeout values for a connection
427427
*/
428428
void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
429-
unsigned int timeo, unsigned int retrans)
429+
int timeo, int retrans)
430430
{
431431
to->to_initval = timeo * HZ / 10;
432432
to->to_retries = retrans;
433433

434434
switch (proto) {
435435
case XPRT_TRANSPORT_TCP:
436436
case XPRT_TRANSPORT_RDMA:
437-
if (to->to_retries == 0)
437+
if (retrans == NFS_UNSPEC_RETRANS)
438438
to->to_retries = NFS_DEF_TCP_RETRANS;
439-
if (to->to_initval == 0)
439+
if (timeo == NFS_UNSPEC_TIMEO || to->to_retries == 0)
440440
to->to_initval = NFS_DEF_TCP_TIMEO * HZ / 10;
441441
if (to->to_initval > NFS_MAX_TCP_TIMEOUT)
442442
to->to_initval = NFS_MAX_TCP_TIMEOUT;
@@ -449,9 +449,9 @@ void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
449449
to->to_exponential = 0;
450450
break;
451451
case XPRT_TRANSPORT_UDP:
452-
if (to->to_retries == 0)
452+
if (retrans == NFS_UNSPEC_RETRANS)
453453
to->to_retries = NFS_DEF_UDP_RETRANS;
454-
if (!to->to_initval)
454+
if (timeo == NFS_UNSPEC_TIMEO || to->to_initval == 0)
455455
to->to_initval = NFS_DEF_UDP_TIMEO * HZ / 10;
456456
if (to->to_initval > NFS_MAX_UDP_TIMEOUT)
457457
to->to_initval = NFS_MAX_UDP_TIMEOUT;

fs/nfs/flexfilelayout/flexfilelayout.c

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ ff_layout_alloc_layout_hdr(struct inode *inode, gfp_t gfp_flags)
3737
if (ffl) {
3838
INIT_LIST_HEAD(&ffl->error_list);
3939
INIT_LIST_HEAD(&ffl->mirrors);
40+
ffl->last_report_time = ktime_get();
4041
return &ffl->generic_hdr;
4142
} else
4243
return NULL;
@@ -640,19 +641,18 @@ nfs4_ff_layoutstat_start_io(struct nfs4_ff_layout_mirror *mirror,
640641
{
641642
static const ktime_t notime = {0};
642643
s64 report_interval = FF_LAYOUTSTATS_REPORT_INTERVAL;
644+
struct nfs4_flexfile_layout *ffl = FF_LAYOUT_FROM_HDR(mirror->layout);
643645

644646
nfs4_ff_start_busy_timer(&layoutstat->busy_timer, now);
645647
if (ktime_equal(mirror->start_time, notime))
646648
mirror->start_time = now;
647-
if (ktime_equal(mirror->last_report_time, notime))
648-
mirror->last_report_time = now;
649649
if (mirror->report_interval != 0)
650650
report_interval = (s64)mirror->report_interval * 1000LL;
651651
else if (layoutstats_timer != 0)
652652
report_interval = (s64)layoutstats_timer * 1000LL;
653-
if (ktime_to_ms(ktime_sub(now, mirror->last_report_time)) >=
653+
if (ktime_to_ms(ktime_sub(now, ffl->last_report_time)) >=
654654
report_interval) {
655-
mirror->last_report_time = now;
655+
ffl->last_report_time = now;
656656
return true;
657657
}
658658

@@ -806,11 +806,14 @@ ff_layout_choose_best_ds_for_read(struct pnfs_layout_segment *lseg,
806806
{
807807
struct nfs4_ff_layout_segment *fls = FF_LAYOUT_LSEG(lseg);
808808
struct nfs4_pnfs_ds *ds;
809+
bool fail_return = false;
809810
int idx;
810811

811812
/* mirrors are sorted by efficiency */
812813
for (idx = start_idx; idx < fls->mirror_array_cnt; idx++) {
813-
ds = nfs4_ff_layout_prepare_ds(lseg, idx, false);
814+
if (idx+1 == fls->mirror_array_cnt)
815+
fail_return = true;
816+
ds = nfs4_ff_layout_prepare_ds(lseg, idx, fail_return);
814817
if (ds) {
815818
*best_idx = idx;
816819
return ds;
@@ -859,6 +862,7 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
859862
struct nfs4_pnfs_ds *ds;
860863
int ds_idx;
861864

865+
retry:
862866
/* Use full layout for now */
863867
if (!pgio->pg_lseg)
864868
ff_layout_pg_get_read(pgio, req, false);
@@ -871,10 +875,13 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
871875

872876
ds = ff_layout_choose_best_ds_for_read(pgio->pg_lseg, 0, &ds_idx);
873877
if (!ds) {
874-
if (ff_layout_no_fallback_to_mds(pgio->pg_lseg))
875-
goto out_pnfs;
876-
else
878+
if (!ff_layout_no_fallback_to_mds(pgio->pg_lseg))
877879
goto out_mds;
880+
pnfs_put_lseg(pgio->pg_lseg);
881+
pgio->pg_lseg = NULL;
882+
/* Sleep for 1 second before retrying */
883+
ssleep(1);
884+
goto retry;
878885
}
879886

880887
mirror = FF_LAYOUT_COMP(pgio->pg_lseg, ds_idx);
@@ -890,12 +897,6 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
890897
pnfs_put_lseg(pgio->pg_lseg);
891898
pgio->pg_lseg = NULL;
892899
nfs_pageio_reset_read_mds(pgio);
893-
return;
894-
895-
out_pnfs:
896-
pnfs_set_lo_fail(pgio->pg_lseg);
897-
pnfs_put_lseg(pgio->pg_lseg);
898-
pgio->pg_lseg = NULL;
899900
}
900901

901902
static void
@@ -909,6 +910,7 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio,
909910
int i;
910911
int status;
911912

913+
retry:
912914
if (!pgio->pg_lseg) {
913915
pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
914916
req->wb_context,
@@ -940,10 +942,13 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio,
940942
for (i = 0; i < pgio->pg_mirror_count; i++) {
941943
ds = nfs4_ff_layout_prepare_ds(pgio->pg_lseg, i, true);
942944
if (!ds) {
943-
if (ff_layout_no_fallback_to_mds(pgio->pg_lseg))
944-
goto out_pnfs;
945-
else
945+
if (!ff_layout_no_fallback_to_mds(pgio->pg_lseg))
946946
goto out_mds;
947+
pnfs_put_lseg(pgio->pg_lseg);
948+
pgio->pg_lseg = NULL;
949+
/* Sleep for 1 second before retrying */
950+
ssleep(1);
951+
goto retry;
947952
}
948953
pgm = &pgio->pg_mirrors[i];
949954
mirror = FF_LAYOUT_COMP(pgio->pg_lseg, i);
@@ -956,12 +961,6 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio,
956961
pnfs_put_lseg(pgio->pg_lseg);
957962
pgio->pg_lseg = NULL;
958963
nfs_pageio_reset_write_mds(pgio);
959-
return;
960-
961-
out_pnfs:
962-
pnfs_set_lo_fail(pgio->pg_lseg);
963-
pnfs_put_lseg(pgio->pg_lseg);
964-
pgio->pg_lseg = NULL;
965964
}
966965

967966
static unsigned int

fs/nfs/flexfilelayout/flexfilelayout.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ struct nfs4_ff_layout_mirror {
8484
struct nfs4_ff_layoutstat read_stat;
8585
struct nfs4_ff_layoutstat write_stat;
8686
ktime_t start_time;
87-
ktime_t last_report_time;
8887
u32 report_interval;
8988
};
9089

@@ -101,6 +100,7 @@ struct nfs4_flexfile_layout {
101100
struct pnfs_ds_commit_info commit_info;
102101
struct list_head mirrors;
103102
struct list_head error_list; /* nfs4_ff_layout_ds_err */
103+
ktime_t last_report_time; /* Layoutstat report times */
104104
};
105105

106106
static inline struct nfs4_flexfile_layout *

fs/nfs/flexfilelayout/flexfilelayoutdev.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717

1818
#define NFSDBG_FACILITY NFSDBG_PNFS_LD
1919

20-
static unsigned int dataserver_timeo = NFS4_DEF_DS_TIMEO;
21-
static unsigned int dataserver_retrans = NFS4_DEF_DS_RETRANS;
20+
static unsigned int dataserver_timeo = NFS_DEF_TCP_RETRANS;
21+
static unsigned int dataserver_retrans;
2222

2323
void nfs4_ff_layout_put_deviceid(struct nfs4_ff_layout_ds *mirror_ds)
2424
{
@@ -379,7 +379,7 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx,
379379

380380
devid = &mirror->mirror_ds->id_node;
381381
if (ff_layout_test_devid_unavailable(devid))
382-
goto out;
382+
goto out_fail;
383383

384384
ds = mirror->mirror_ds->ds;
385385
/* matching smp_wmb() in _nfs4_pnfs_v3/4_ds_connect */
@@ -405,15 +405,16 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx,
405405
mirror->mirror_ds->ds_versions[0].rsize = max_payload;
406406
if (mirror->mirror_ds->ds_versions[0].wsize > max_payload)
407407
mirror->mirror_ds->ds_versions[0].wsize = max_payload;
408-
} else {
409-
ff_layout_track_ds_error(FF_LAYOUT_FROM_HDR(lseg->pls_layout),
410-
mirror, lseg->pls_range.offset,
411-
lseg->pls_range.length, NFS4ERR_NXIO,
412-
OP_ILLEGAL, GFP_NOIO);
413-
if (fail_return || !ff_layout_has_available_ds(lseg))
414-
pnfs_error_mark_layout_for_return(ino, lseg);
415-
ds = NULL;
408+
goto out;
416409
}
410+
ff_layout_track_ds_error(FF_LAYOUT_FROM_HDR(lseg->pls_layout),
411+
mirror, lseg->pls_range.offset,
412+
lseg->pls_range.length, NFS4ERR_NXIO,
413+
OP_ILLEGAL, GFP_NOIO);
414+
out_fail:
415+
if (fail_return || !ff_layout_has_available_ds(lseg))
416+
pnfs_error_mark_layout_for_return(ino, lseg);
417+
ds = NULL;
417418
out:
418419
return ds;
419420
}

fs/nfs/internal.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ struct nfs_clone_mount {
5858
*/
5959
#define NFS_UNSPEC_PORT (-1)
6060

61+
#define NFS_UNSPEC_RETRANS (UINT_MAX)
62+
#define NFS_UNSPEC_TIMEO (UINT_MAX)
63+
6164
/*
6265
* Maximum number of pages that readdir can use for creating
6366
* a vmapped array of pages.
@@ -156,7 +159,7 @@ struct nfs_client *nfs_get_client(const struct nfs_client_initdata *,
156159
int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *, struct nfs_fattr *);
157160
void nfs_server_insert_lists(struct nfs_server *);
158161
void nfs_server_remove_lists(struct nfs_server *);
159-
void nfs_init_timeout_values(struct rpc_timeout *, int, unsigned int, unsigned int);
162+
void nfs_init_timeout_values(struct rpc_timeout *to, int proto, int timeo, int retrans);
160163
int nfs_init_server_rpcclient(struct nfs_server *, const struct rpc_timeout *t,
161164
rpc_authflavor_t);
162165
struct nfs_server *nfs_alloc_server(void);

0 commit comments

Comments
 (0)