aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorAndy Adamson <andros@netapp.com>2009-04-01 09:22:15 -0400
committerBenny Halevy <bhalevy@panasas.com>2009-06-17 13:46:39 -0400
commitfbcd4abcb3841f85578985c09c6df85aa41b0ae8 (patch)
treefd1744248ab503dad083e0fb54c938315adef92f /fs/nfs
parent510b81756f18922a4c5b555e8145f4fed5beb569 (diff)
nfs41: setup_sequence method
Allocate a slot in the session slot table and set the sequence op arguments. Called at the rpc prepare stage. Add a status to nfs41_sequence_res, initialize it to one so that we catch rpc level failures which do not go through decode_sequence which sets the new status field. Note that upon an rpc level failure, we don't know if the server processed the sequence operation or not. Proceed as if the server did process the sequence operation. Signed-off-by: Rahul Iyer <iyer@netapp.com> [nfs41: sequence args use slotid] [nfs41: find slot return slotid] Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> [nfs41: remove SEQ4_STATUS_USE_TK_STATUS] As per 11-14-08 review [move extern declaration from nfs41: sequence setup/done support] [removed sa_session definition, changed sa_cache_this into a u8 to reduce footprint] Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> [nfs41: rpc_sleep_on slot_tbl_waitq must be called under slot_tbl_lock] Otherwise there's a race (we've hit) with nfs4_free_slot where nfs41_setup_sequence sees a full slot table, unlocks slot_tbl_lock, nfs4_free_slots happen concurrently and call rpc_wake_up_next where there's nobody to wake up yet, context goes back to nfs41_setup_sequence which goes to sleep when the slot table is actually empty now and there's no-one to wake it up anymore. Signed-off-by: Benny Halevy <bhalevy@panasas.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4_fs.h10
-rw-r--r--fs/nfs/nfs4proc.c34
2 files changed, 42 insertions, 2 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index acac6f8c3d39..eccf4e93e7d7 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -203,8 +203,18 @@ extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
203extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops; 203extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
204extern struct nfs4_state_recovery_ops nfs4_nograce_recovery_ops; 204extern struct nfs4_state_recovery_ops nfs4_nograce_recovery_ops;
205#if defined(CONFIG_NFS_V4_1) 205#if defined(CONFIG_NFS_V4_1)
206extern int nfs4_setup_sequence(struct nfs_client *clp,
207 struct nfs4_sequence_args *args, struct nfs4_sequence_res *res,
208 int cache_reply, struct rpc_task *task);
206extern void nfs4_destroy_session(struct nfs4_session *session); 209extern void nfs4_destroy_session(struct nfs4_session *session);
207extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp); 210extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp);
211#else /* CONFIG_NFS_v4_1 */
212static inline int nfs4_setup_sequence(struct nfs_client *clp,
213 struct nfs4_sequence_args *args, struct nfs4_sequence_res *res,
214 int cache_reply, struct rpc_task *task)
215{
216 return 0;
217}
208#endif /* CONFIG_NFS_V4_1 */ 218#endif /* CONFIG_NFS_V4_1 */
209 219
210extern const u32 nfs4_fattr_bitmap[2]; 220extern const u32 nfs4_fattr_bitmap[2];
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index a0946a0d116e..c9618080317e 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -280,6 +280,8 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp
280 * If found, we mark the slot as used, update the highest_used_slotid, 280 * If found, we mark the slot as used, update the highest_used_slotid,
281 * and respectively set up the sequence operation args. 281 * and respectively set up the sequence operation args.
282 * The slot number is returned if found, or NFS4_MAX_SLOT_TABLE otherwise. 282 * The slot number is returned if found, or NFS4_MAX_SLOT_TABLE otherwise.
283 *
284 * Note: must be called with under the slot_tbl_lock.
283 */ 285 */
284static u8 286static u8
285nfs4_find_slot(struct nfs4_slot_table *tbl, struct rpc_task *task) 287nfs4_find_slot(struct nfs4_slot_table *tbl, struct rpc_task *task)
@@ -288,7 +290,6 @@ nfs4_find_slot(struct nfs4_slot_table *tbl, struct rpc_task *task)
288 u8 ret_id = NFS4_MAX_SLOT_TABLE; 290 u8 ret_id = NFS4_MAX_SLOT_TABLE;
289 BUILD_BUG_ON((u8)NFS4_MAX_SLOT_TABLE != (int)NFS4_MAX_SLOT_TABLE); 291 BUILD_BUG_ON((u8)NFS4_MAX_SLOT_TABLE != (int)NFS4_MAX_SLOT_TABLE);
290 292
291 spin_lock(&tbl->slot_tbl_lock);
292 dprintk("--> %s used_slots=%04lx highest_used=%d max_slots=%d\n", 293 dprintk("--> %s used_slots=%04lx highest_used=%d max_slots=%d\n",
293 __func__, tbl->used_slots[0], tbl->highest_used_slotid, 294 __func__, tbl->used_slots[0], tbl->highest_used_slotid,
294 tbl->max_slots); 295 tbl->max_slots);
@@ -302,7 +303,6 @@ nfs4_find_slot(struct nfs4_slot_table *tbl, struct rpc_task *task)
302out: 303out:
303 dprintk("<-- %s used_slots=%04lx highest_used=%d slotid=%d \n", 304 dprintk("<-- %s used_slots=%04lx highest_used=%d slotid=%d \n",
304 __func__, tbl->used_slots[0], tbl->highest_used_slotid, ret_id); 305 __func__, tbl->used_slots[0], tbl->highest_used_slotid, ret_id);
305 spin_unlock(&tbl->slot_tbl_lock);
306 return ret_id; 306 return ret_id;
307} 307}
308 308
@@ -312,12 +312,42 @@ static int nfs41_setup_sequence(struct nfs4_session *session,
312 int cache_reply, 312 int cache_reply,
313 struct rpc_task *task) 313 struct rpc_task *task)
314{ 314{
315 struct nfs4_slot *slot;
316 struct nfs4_slot_table *tbl;
317 u8 slotid;
318
319 dprintk("--> %s\n", __func__);
315 /* slot already allocated? */ 320 /* slot already allocated? */
316 if (res->sr_slotid != NFS4_MAX_SLOT_TABLE) 321 if (res->sr_slotid != NFS4_MAX_SLOT_TABLE)
317 return 0; 322 return 0;
318 323
319 memset(res, 0, sizeof(*res)); 324 memset(res, 0, sizeof(*res));
320 res->sr_slotid = NFS4_MAX_SLOT_TABLE; 325 res->sr_slotid = NFS4_MAX_SLOT_TABLE;
326 tbl = &session->fc_slot_table;
327
328 spin_lock(&tbl->slot_tbl_lock);
329 slotid = nfs4_find_slot(tbl, task);
330 if (slotid == NFS4_MAX_SLOT_TABLE) {
331 rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
332 spin_unlock(&tbl->slot_tbl_lock);
333 dprintk("<-- %s: no free slots\n", __func__);
334 return -EAGAIN;
335 }
336 spin_unlock(&tbl->slot_tbl_lock);
337
338 slot = tbl->slots + slotid;
339 args->sa_slotid = slotid;
340 args->sa_cache_this = cache_reply;
341
342 dprintk("<-- %s slotid=%d seqid=%d\n", __func__, slotid, slot->seq_nr);
343
344 res->sr_slotid = slotid;
345 res->sr_renewal_time = jiffies;
346 /*
347 * sr_status is only set in decode_sequence, and so will remain
348 * set to 1 if an rpc level failure occurs.
349 */
350 res->sr_status = 1;
321 return 0; 351 return 0;
322} 352}
323 353