[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