[SSI] openssi/kernel/cluster/ssi/util rmtfb.c,1.34,1.35
Roger Tsang <[email protected]> Mon, 17 Jan 2011 07:05:47 +0000
| Newsgroups | gmane.linux.cluster.ssic.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/util
In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv2164/cluster/ssi/util
Modified Files:
Tag: OPENSSI-FC
rmtfb.c
Log Message:
cluster/ssi/util/rmtfb.c (#ifdef RMTFB_HASH_LOCKLESS)
- rmtfb_getcli_id: remove retry of __rmtfb_getcli_id(). SMP-safe.
- rmtfb_newcli: no longer do early check for an existing rmtfb_cli struct with same rfb_id. caller already checked. in one possible code path we were doing total of three checks.
- rmtfb_newcli: remove retry of __rmtfb_getcli_id(). SMP-safe.
- rmtfb_newcli: move rmtfb_setcli_re/open() till after we've added the rmtfb_cli structure to the hashed chained linked list to avoid racing with rmtfb_rclose(). fix -ERFB_TRYAGAIN error when rmtfb_rclose() lost the race.
- rmtfb_newcli: add comment before function about circular reference between file struct and rmtfb_cli struct.
- __rmtfb_getcli_id: no need to return -ERFB_RELEASE error. just return NULL since there is nothing for caller to do.
- __rmtfb_getcli_id: wait for rmtfb_setcli_re/open() completion. return -EREMOTE on failure.
cluster/ssi/util/rmtfb.c (#ifdef REOP_EXPORT_PATH_SVRNODE)
- rmtfb_getcli_id: indicate to compiler unlikely branch direction.
Index: rmtfb.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/util/rmtfb.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -d -r1.34 -r1.35
--- rmtfb.c 17 Jan 2011 06:33:53 -0000 1.34
+++ rmtfb.c 17 Jan 2011 07:05:45 -0000 1.35
@@ -50,9 +50,10 @@
#include <cluster/gen/ics_rmtfb_macros_gen.h>
#include <cluster/gen/ics_rmtfb_protos_gen.h>
+#ifndef RMTFB_HASH_LOCKLESS
#define ERFB_RELEASE 700
-
#define rmtfb_maxloops HZ
+#endif
#ifdef RFBDEBUG
#define RMTFB_MAGIC 0xDEAD2A9E
@@ -964,22 +965,42 @@
#ifdef RMTFB_HASH_LOCKLESS
static struct rmtfb_cli *
-__rmtfb_getcli_id(unsigned long id)
+__rmtfb_getcli_id(unsigned long id, struct semaphore *sem)
{
struct rmtfb_cli *rfb;
+ task_t *curtask;
+ sigset_t oldmask;
- rfb = (struct rmtfb_cli *) rmtfb_getcmn(
- &rmtfb_clitbl[rfbhash(id)],
- rmtfb_test_id,
- (void *)&id);
+#ifdef RFBDEBUG
+ SSI_ASSERT(!sem || sem_owned(sem));
+#endif
+ rfb = (typeof(rfb)) rmtfb_getcmn(&rmtfb_clitbl[rfbhash(id)],
+ rmtfb_test_id, (void *)&id);
if (!rfb)
return NULL;
-
/* Do implicit get_file() */
if (!atomic_test_and_add(1, &rfb->common.rfb_file->f_count)) {
/* Lost race with final fput() */
rmtfb_putcli(rfb);
- return ERR_PTR(-ERFB_RELEASE);
+ return NULL;
+ }
+ /* Got a valid rmtfb_cli structure */
+ if (sem)
+ up(sem);
+
+ if (!atomic_read(&rfb->rfb_state)) {
+ curtask = current;
+ ssi_block_signals(curtask, &oldmask);
+ /* Wait for rmtfb_setcli_re/open() */
+ wait_event_interruptible(rfb->rfb_wait,
+ atomic_read(&rfb->rfb_state));
+ ssi_unblock_signals(curtask, &oldmask);
+ }
+ if (unlikely(atomic_read(&rfb->rfb_state) == 2)) {
+ /* rmtfb_setcli_re/open() failed */
+ fput(rfb->common.rfb_file);
+ rmtfb_putcli(rfb);
+ return ERR_PTR(-EREMOTE);
}
return rfb;
}
@@ -1040,11 +1061,13 @@
{
struct rmtfb_cli *rfb;
struct file *file;
- int loop;
+#ifndef RMTFB_HASH_LOCKLESS
+ int loop = 0;
+#endif
#ifdef REOP_EXPORT_PATH_SVRNODE
int svr = 0;
- if (!path || !(svr = path->svrnode) || inval(id,svr)) {
+ if (unlikely(!path || !(svr = path->svrnode) || inval(id,svr))) {
#else
if (!path || !svr || inval(id,svr)) {
#endif
@@ -1056,25 +1079,11 @@
return ERR_PTR(-EINVAL);
}
- loop = 0;
#ifdef RMTFB_HASH_LOCKLESS
- for (;;) {
- rfb = __rmtfb_getcli_id(id);
- if (!rfb)
- break;
- if (PTR_ERR(rfb) != -ERFB_RELEASE)
- goto out;
- /* Avoids a race where clrcli and setcli could
- * be received out of order at the server,
- * leaving it unaware that this node is its
- * client again.
- */
- if (++loop > rmtfb_maxloops) {
- printk(KERN_INFO "rmtfb_getcli_id: looping\n");
- loop = 0;
- }
- yield();
- }
+ /* See if another import made one already */
+ rfb = __rmtfb_getcli_id(id, NULL);
+ if (rfb || IS_ERR(rfb))
+ goto out;
#else /* RMTFB_HASH_LOCKLESS */
repeat:
LOCK_SHR_RW_LOCK(&rmtfb_clitbl_lock);
@@ -1202,6 +1211,10 @@
rfb->rfb_magic = RMTFB_MAGIC;
#endif
rfb->rfb_server = svr;
+#ifdef RMTFB_HASH_LOCKLESS
+ atomic_set(&rfb->rfb_state, 0);
+ init_waitqueue_head(&rfb->rfb_wait);
+#endif
}
return rfb;
}
@@ -1405,33 +1418,27 @@
*
* NOTE! fput() is called on @file before returning to caller if there is an
* existing rmtfb_cli structure with the same rfb_id.
+ *
+ * Also get_file() is not invoked on @file to increment f_count because of the
+ * circular reference file->private_data = rfb and rfb->common.rfb_file = file.
+ * The file structure has the active reference to rmtfb_cli structure but not
+ * the other way around.
*/
struct rmtfb_cli *
rmtfb_newcli(struct file *file, unsigned long id,
clusternode_t svr, char noremote)
{
static DECLARE_MUTEX(rmtfb_newcli_lock);
- struct rmtfb_cli *rfb;
+ struct rmtfb_cli *rfb, *old;
unsigned long hash;
int error;
char import;
- if (id) {
- /* Fast check: see if another import didn't make one already */
- rfb = __rmtfb_getcli_id(id);
- if (rfb && !IS_ERR(rfb)) {
- /* BUG: ssi_sockfs_make_cli() expects no race */
- BUG_ON(noremote);
- fput(file); /* rfb->common.rfb_file != file */
- return rfb;
- }
- }
-
if (unlikely(file->private_data)) {
printk(KERN_ERR "%s: non-exportable filesystem (%s)\n",
__FUNCTION__, file->f_vfsmnt->mnt_sb->s_type->name);
error = -EOPNOTSUPP;
- goto out;
+ goto out_bad;
}
SSI_ASSERT(svr && !inval(1,svr));
@@ -1439,61 +1446,28 @@
rfb = rmtfb_cli_alloc(file, id, svr);
if (!rfb) {
error = -ENOMEM;
- goto out;
+ goto out_bad;
}
import = !!id;
if (!id)
id = rfb->common.rfb_id;
- if (!noremote) {
- if (import)
- error = rmtfb_setcli_reopen(rfb);
- else
- error = rmtfb_setcli_open(rfb);
- SSI_ASSERT(error != -EINVAL);
- if (unlikely(error)) {
- rmtfb_freecli(rfb);
- goto out;
- }
- } else
- error = 0;
-
hash = rfbhash(id);
-
down(&rmtfb_newcli_lock);
-
if (import) {
- struct rmtfb_cli *old;
- int loop = 0;
-
/* Make sure another import didn't make one already */
- for (;;) {
- old = __rmtfb_getcli_id(id);
- if (!old || PTR_ERR(old) != -ERFB_RELEASE)
- break;
- up(&rmtfb_newcli_lock);
- /* Avoids a race where clrcli and setcli could
- * be received out of order at the server,
- * leaving it unaware that this node is its
- * client again.
- */
- if (++loop > rmtfb_maxloops) {
- printk(KERN_INFO "rmtfb_newcli: looping\n");
- loop = 0;
- }
- yield();
- down(&rmtfb_newcli_lock);
- }
- if (unlikely(old)) {
- up(&rmtfb_newcli_lock);
- /* NB: No need to undo rmtfb_setcli_re/open() */
+ old = __rmtfb_getcli_id(id, &rmtfb_newcli_lock);
+ if (old) {
+ /* rmtfb_newcli_lock released */
rmtfb_freecli(rfb);
- rfb = old;
- if (!IS_ERR(rfb)) {
- /* BUG: ssi_sockfs_make_cli() expects no race */
- BUG_ON(noremote);
- fput(file); /* rfb->common.rfb_file != file */
+ if (IS_ERR(old)) {
+ error = PTR_ERR(old);
+ goto out_bad;
}
+ rfb = old;
+ /* BUG: ssi_sockfs_make_cli() expects no race */
+ BUG_ON(noremote);
+ fput(file); /* rfb->common.rfb_file != file */
goto out;
}
}
@@ -1516,19 +1490,39 @@
hlist_add_head_rcu(&rfb->common.rfb_hash, &rmtfb_clitbl[hash]);
spin_unlock(&rmtfb_clitbl_lock);
up(&rmtfb_newcli_lock);
-out:
- if (error) {
-#ifdef RFBDEBUG
- printk(KERN_DEBUG "rmtfb_newcli: fail error=%d ino=%lu name=%s",
- error, ftoi(file)->i_ino, file->f_dentry->d_name.name);
-#endif
- return ERR_PTR(error);
+
+ if (!noremote) {
+ /* We save this part for last to ensure there is no other
+ * rmtfb_cli struct with the same rfb_id. We avoid racing with
+ * rmtfb_rclose(). If we won the race the next rmtfb_rclose()
+ * could see -ERFB_TRYAGAIN from the server.
+ */
+ if (import) {
+ error = rmtfb_setcli_reopen(rfb);
+ } else
+ error = rmtfb_setcli_open(rfb);
+ if (unlikely(error)) {
+ SSI_ASSERT(error != -EINVAL);
+ atomic_set(&rfb->rfb_state, 2); /* stale */
+ wake_up(&rfb->rfb_wait);
+ rmtfb_putcli(rfb);
+ goto out_bad;
+ }
}
+ atomic_set(&rfb->rfb_state, 1); /* ready */
+ wake_up(&rfb->rfb_wait);
+out:
#ifdef RFBDEBUG
printk(KERN_DEBUG "rfb_server=%u ", svr);
rmtfb_cli_debug("rmtfb_newcli:",rfb);
#endif
return rfb;
+out_bad:
+#ifdef RFBDEBUG
+ printk(KERN_DEBUG "rmtfb_newcli: fail error=%d ino=%lu name=%s",
+ error, ftoi(file)->i_ino, file->f_dentry->d_name.name);
+#endif
+ return ERR_PTR(error);
}
#else /* RMTFB_HASH_LOCKLESS */
struct rmtfb_cli *
------------------------------------------------------------------------------
Protect Your Site and Customers from Malware Attacks
Learn about various malware tactics and how to avoid them. Understand
malware threats, the impact they can have on your business, and how you
can protect your company and customers by using code signing.
http://p.sf.net/sfu/oracle-sfdevnl