[pnfs] (no subject)

iyer at netapp.com iyer at netapp.com
Fri Mar 16 18:16:50 EDT 2007


From: iyer <iyer at netapp.com>
Date: Wed, 14 Mar 2007 18:30:01 -0800
Subject: [PATCH 3/8] Slot Table Implementation

Added code to implement a slot table.

Signed-off-by: iyer <iyer at netapp.com>
---

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 167ff4a..28513a1 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -49,6 +49,7 @@
 #include <linux/namei.h>
 #include <linux/mount.h>
 #include <linux/module.h>
+#include <linux/bitops.h>
 
 #include "nfs4_fs.h"
 #include "delegation.h"
@@ -221,8 +222,10 @@ static int nfs41_proc_sequence_done(struct nfs4_session *session, struct nfs41_s
 	unsigned long timestamp;
 	struct nfs4_client *clp;
 
-	if (!session || !(clp = session->client))
-		return 0;
+	if (!session || !(clp = session->client)) {
+		printk(KERN_EMERG "%s is NULL!!!\n", (!session)?"session":"clp");
+		BUG();
+	}
 
 	if (!status) {
 		timestamp = jiffies;
@@ -233,17 +236,131 @@ static int nfs41_proc_sequence_done(struct nfs4_session *session, struct nfs41_s
 		spin_unlock(&clp->cl_lock);
 	}
 
+	/* Clear the 'busy' bit on the slot that was used */
+	smp_mb__before_clear_bit();
+	clear_bit(NFS4_SLOT_BUSY, &res->slot->flags);
+	smp_mb__after_clear_bit();
+
+	printk(KERN_EMERG "waking up waiters on slot %d\n", res->slot->slot_nr);
+
+	/* Wake up the threads waiting on this slot */
+	wake_up_bit(&res->slot->flags, NFS4_SLOT_BUSY);
+
 	return status;
 }
 
+static int nfs4_wait_bit_interruptible(void *word)
+{
+	if (signal_pending(current))
+		return -ERESTARTSYS;
+	schedule();
+	return 0;
+}
+
+/* Find the lowest numbered slot or sleep on the least loaded slot */
+struct nfs4_slot *nfs4_find_slot(struct nfs4_channel *channel)
+{
+	struct nfs4_slot_table *tbl;
+	struct nfs4_slot *slot;
+	struct nfs4_slot *target_slot;
+	u32 max_slots;
+	u32 min_waiters;
+	int i;
+	int need_to_sleep;
+	
+	might_sleep();
+
+	tbl = &channel->slot_table;
+	min_waiters = tbl->slots[0].nr_waiters;
+	target_slot = &tbl->slots[0];
+
+	spin_lock(&tbl->slot_tbl_lock);
+	/* Make a local copy of max slots so we don't need to hold it through
+	 * out. 
+	 * XXX Will need to revalidate this if slots are reclaimed
+	 */
+	max_slots = tbl->max_slots;
+	spin_unlock(&tbl->slot_tbl_lock);
+
+	do {
+		need_to_sleep = 1;
+		for (i = 0; i <  max_slots; ++i) {
+			slot = &tbl->slots[i];
+			if (!test_and_set_bit(NFS4_SLOT_BUSY, &slot->flags)){
+				/* We found an empty slot */
+				target_slot = slot;
+				need_to_sleep = 0;
+				break;
+			}
+
+			spin_lock(&slot->slot_lock);
+			if (min_waiters > slot->nr_waiters) {
+				min_waiters = slot->nr_waiters;
+				target_slot = slot;
+			}
+			spin_unlock(&slot->slot_lock);
+			printk(KERN_EMERG "slot %d has busy bit %s and nr_waiters is %u\n"
+					, slot->slot_nr, 
+					(need_to_sleep)?"set":"unset", 
+					slot->nr_waiters);
+		}
+	
+		/* Check whether we need to sleep. If so, sleep on the BUSY bit 
+		 * Increment the nr_waiters before sleeping and decrement it 
+		 * when woken up
+		 */
+		if (need_to_sleep) {
+			printk(KERN_EMERG "sleeping on slot %d; seq_nr: %d\n",
+					target_slot->slot_nr, 
+					target_slot->seq_nr);
+			spin_lock(&target_slot->slot_lock);
+			++target_slot->nr_waiters;
+			spin_unlock(&target_slot->slot_lock);
+	
+			/* XXX: We need to check the return value of
+			 * eait_on_bit so that we can check if it's
+			 * interrupted.
+			 */
+			wait_on_bit(&target_slot->flags, NFS4_SLOT_BUSY, 
+					nfs4_wait_bit_interruptible,
+					TASK_INTERRUPTIBLE);
+
+			spin_lock(&target_slot->slot_lock);
+			--target_slot->nr_waiters;
+			spin_unlock(&target_slot->slot_lock);
+		}
+		else
+			break;
+	}while (test_and_set_bit(NFS4_SLOT_BUSY, &target_slot->flags));
+
+	printk(KERN_EMERG "slot id: %u\nseqid: %u\n max_slots: %u\n", 
+			target_slot->slot_nr, target_slot->seq_nr, 
+				max_slots);
+	
+	return target_slot;
+}
+	
 static int _nfs41_proc_setup_sequence(struct nfs4_session *session, struct nfs41_sequence_args *args, struct nfs41_sequence_res *res)
 {
 	u32 *ptr;
-
+	struct nfs4_slot *slot;
+	
 	ptr = (u32 *)session->sess_id;
 	dprintk("%s: %u:%u:%u:%u\n", __FUNCTION__, ptr[0], ptr[1], ptr[2], ptr[3]);
 
-	memcpy(args->sessionid, (unsigned char *)session->sess_id, NFS4_MAX_SESSIONID_LEN);
+	memcpy(args->sessionid, (unsigned char *)session->sess_id, 
+					NFS4_MAX_SESSIONID_LEN);
+
+       slot = nfs4_find_slot(&session->fore_channel);
+
+       /* XXX: Do we always increment this? Are there any errors for which we
+	* don't increment the sequence number?
+	*/
+       args->seqid = slot->seq_nr++;
+       args->slotid = slot->slot_nr;
+       args->maxslots = session->fore_channel.slot_table.max_slots;
+      
+       res->slot = slot;
 
 	return 0;
 }


More information about the pNFS mailing list