Skip to content

Commit 045d2a6

Browse files
committed
NFSv4.1: Delay callback processing when there are referring triples
If CB_SEQUENCE tells us that the processing of this request depends on the completion of one or more referring triples (see RFC 5661 Section 2.10.6.3), delay the callback processing until after the RPC requests being referred to have completed. If we end up delaying for more than 1/2 second, then fall back to returning NFS4ERR_DELAY in reply to the callback. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
1 parent e09c978 commit 045d2a6

File tree

4 files changed

+29
-4
lines changed

4 files changed

+29
-4
lines changed

fs/nfs/callback_proc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -454,8 +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-
status = nfs4_slot_seqid_in_use(tbl, ref->rc_slotid,
458-
ref->rc_sequenceid);
457+
status = nfs4_slot_wait_on_seqid(tbl, ref->rc_slotid,
458+
ref->rc_sequenceid, HZ >> 1) < 0;
459459
if (status)
460460
goto out;
461461
}

fs/nfs/nfs4proc.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,8 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
686686
res->sr_slot = NULL;
687687
if (send_new_highest_used_slotid)
688688
nfs41_notify_server(session->clp);
689+
if (waitqueue_active(&tbl->slot_waitq))
690+
wake_up_all(&tbl->slot_waitq);
689691
}
690692

691693
int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)

fs/nfs/nfs4session.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ static void nfs4_init_slot_table(struct nfs4_slot_table *tbl, const char *queue)
2828
tbl->highest_used_slotid = NFS4_NO_SLOT;
2929
spin_lock_init(&tbl->slot_tbl_lock);
3030
rpc_init_priority_wait_queue(&tbl->slot_tbl_waitq, queue);
31+
init_waitqueue_head(&tbl->slot_waitq);
3132
init_completion(&tbl->complete);
3233
}
3334

@@ -192,7 +193,8 @@ static int nfs4_slot_get_seqid(struct nfs4_slot_table *tbl, u32 slotid,
192193
* RPC call in question is still in flight. This function is mainly
193194
* intended for use by the callback channel.
194195
*/
195-
bool nfs4_slot_seqid_in_use(struct nfs4_slot_table *tbl, u32 slotid, u32 seq_nr)
196+
static bool nfs4_slot_seqid_in_use(struct nfs4_slot_table *tbl,
197+
u32 slotid, u32 seq_nr)
196198
{
197199
u32 cur_seq;
198200
bool ret = false;
@@ -205,6 +207,24 @@ bool nfs4_slot_seqid_in_use(struct nfs4_slot_table *tbl, u32 slotid, u32 seq_nr)
205207
return ret;
206208
}
207209

210+
/*
211+
* nfs4_slot_wait_on_seqid - wait until a slot sequence id is complete
212+
*
213+
* Given a slot table, slot id and sequence number, wait until the
214+
* corresponding RPC call completes. This function is mainly
215+
* intended for use by the callback channel.
216+
*/
217+
int nfs4_slot_wait_on_seqid(struct nfs4_slot_table *tbl,
218+
u32 slotid, u32 seq_nr,
219+
unsigned long timeout)
220+
{
221+
if (wait_event_timeout(tbl->slot_waitq,
222+
!nfs4_slot_seqid_in_use(tbl, slotid, seq_nr),
223+
timeout) == 0)
224+
return -ETIMEDOUT;
225+
return 0;
226+
}
227+
208228
/*
209229
* nfs4_alloc_slot - efficiently look for a free slot
210230
*

fs/nfs/nfs4session.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ struct nfs4_slot_table {
3636
unsigned long used_slots[SLOT_TABLE_SZ]; /* used/unused bitmap */
3737
spinlock_t slot_tbl_lock;
3838
struct rpc_wait_queue slot_tbl_waitq; /* allocators may wait here */
39+
wait_queue_head_t slot_waitq; /* Completion wait on slot */
3940
u32 max_slots; /* # slots in table */
4041
u32 max_slotid; /* Max allowed slotid value */
4142
u32 highest_used_slotid; /* sent to server on each SEQ.
@@ -78,7 +79,9 @@ extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl,
7879
extern void nfs4_shutdown_slot_table(struct nfs4_slot_table *tbl);
7980
extern struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl);
8081
extern struct nfs4_slot *nfs4_lookup_slot(struct nfs4_slot_table *tbl, u32 slotid);
81-
extern bool nfs4_slot_seqid_in_use(struct nfs4_slot_table *tbl, u32 slotid, u32 seq_nr);
82+
extern int nfs4_slot_wait_on_seqid(struct nfs4_slot_table *tbl,
83+
u32 slotid, u32 seq_nr,
84+
unsigned long timeout);
8285
extern bool nfs4_try_to_lock_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot);
8386
extern void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot);
8487
extern void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl);

0 commit comments

Comments
 (0)