]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/afs/vlocation.c
Btrfs: Make sure dir is non-null before doing S_ISGID checks
[linux-2.6-omap-h63xx.git] / fs / afs / vlocation.c
index 7d9815e9ae0f03091716ddf7f060891a5ad8db51..849fc3160cb5b372c2626545f926ce185c22762b 100644 (file)
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 #include "internal.h"
 
-unsigned afs_vlocation_timeout = 10;   /* volume location timeout in seconds */
-unsigned afs_vlocation_update_timeout = 10 * 60;
+static unsigned afs_vlocation_timeout = 10;    /* volume location timeout in seconds */
+static unsigned afs_vlocation_update_timeout = 10 * 60;
 
 static void afs_vlocation_reaper(struct work_struct *);
 static void afs_vlocation_updater(struct work_struct *);
@@ -178,7 +179,7 @@ static struct afs_vlocation *afs_vlocation_alloc(struct afs_cell *cell,
                INIT_LIST_HEAD(&vl->grave);
                INIT_LIST_HEAD(&vl->update);
                init_waitqueue_head(&vl->waitq);
-               rwlock_init(&vl->lock);
+               spin_lock_init(&vl->lock);
                memcpy(vl->vldb.name, name, namesz);
        }
 
@@ -334,7 +335,7 @@ static int afs_vlocation_fill_in_record(struct afs_vlocation *vl,
 /*
  * queue a vlocation record for updates
  */
-void afs_vlocation_queue_for_updates(struct afs_vlocation *vl)
+static void afs_vlocation_queue_for_updates(struct afs_vlocation *vl)
 {
        struct afs_vlocation *xvl;
 
@@ -381,7 +382,7 @@ struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *cell,
               cell->name, key_serial(key),
               (int) namesz, (int) namesz, name, namesz);
 
-       if (namesz > sizeof(vl->vldb.name)) {
+       if (namesz >= sizeof(vl->vldb.name)) {
                _leave(" = -ENAMETOOLONG");
                return ERR_PTR(-ENAMETOOLONG);
        }
@@ -414,7 +415,9 @@ fill_in_record:
        ret = afs_vlocation_fill_in_record(vl, key);
        if (ret < 0)
                goto error_abandon;
+       spin_lock(&vl->lock);
        vl->state = AFS_VL_VALID;
+       spin_unlock(&vl->lock);
        wake_up(&vl->waitq);
 
        /* schedule for regular updates */
@@ -434,37 +437,41 @@ found_in_memory:
        up_write(&cell->vl_sem);
 
        /* see if it was an abandoned record that we might try filling in */
+       spin_lock(&vl->lock);
        while (vl->state != AFS_VL_VALID) {
                afs_vlocation_state_t state = vl->state;
 
                _debug("invalid [state %d]", state);
 
-               if ((state == AFS_VL_NEW || state == AFS_VL_NO_VOLUME)) {
-                       if (cmpxchg(&vl->state, state, AFS_VL_CREATING) ==
-                           state)
-                               goto fill_in_record;
-                       continue;
+               if (state == AFS_VL_NEW || state == AFS_VL_NO_VOLUME) {
+                       vl->state = AFS_VL_CREATING;
+                       spin_unlock(&vl->lock);
+                       goto fill_in_record;
                }
 
                /* must now wait for creation or update by someone else to
                 * complete */
                _debug("wait");
 
-               ret = wait_event_interruptible(
-                       vl->waitq,
-                       vl->state == AFS_VL_NEW ||
-                       vl->state == AFS_VL_VALID ||
-                       vl->state == AFS_VL_NO_VOLUME);
+               spin_unlock(&vl->lock);
+               ret = wait_event_interruptible(vl->waitq,
+                                              vl->state == AFS_VL_NEW ||
+                                              vl->state == AFS_VL_VALID ||
+                                              vl->state == AFS_VL_NO_VOLUME);
                if (ret < 0)
                        goto error;
+               spin_lock(&vl->lock);
        }
+       spin_unlock(&vl->lock);
 
 success:
        _leave(" = %p",vl);
        return vl;
 
 error_abandon:
+       spin_lock(&vl->lock);
        vl->state = AFS_VL_NEW;
+       spin_unlock(&vl->lock);
        wake_up(&vl->waitq);
 error:
        ASSERT(vl != NULL);
@@ -596,7 +603,7 @@ int __init afs_vlocation_update_init(void)
 /*
  * discard all the volume location records for rmmod
  */
-void __exit afs_vlocation_purge(void)
+void afs_vlocation_purge(void)
 {
        afs_vlocation_timeout = 0;
 
@@ -663,6 +670,7 @@ static void afs_vlocation_updater(struct work_struct *work)
        vl->upd_busy_cnt = 0;
 
        ret = afs_vlocation_update_record(vl, NULL, &vldb);
+       spin_lock(&vl->lock);
        switch (ret) {
        case 0:
                afs_vlocation_apply_update(vl, &vldb);
@@ -675,6 +683,8 @@ static void afs_vlocation_updater(struct work_struct *work)
                vl->state = AFS_VL_UNCERTAIN;
                break;
        }
+       spin_unlock(&vl->lock);
+       wake_up(&vl->waitq);
 
        /* and then reschedule */
        _debug("reschedule");