ACPI: Kconfig: CONFIG_ACPI_PROCFS now defaults to N
[safe/jmp/linux-2.6] / fs / afs / vlocation.c
index 60cb2f4..09e3ad0 100644 (file)
@@ -12,6 +12,7 @@
 #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 */
@@ -33,6 +34,7 @@ static struct workqueue_struct *afs_vlocation_update_worker;
  * about the volume in question
  */
 static int afs_vlocation_access_vl_by_name(struct afs_vlocation *vl,
+                                          struct key *key,
                                           struct afs_cache_vlocation *vldb)
 {
        struct afs_cell *cell = vl->cell;
@@ -49,7 +51,7 @@ static int afs_vlocation_access_vl_by_name(struct afs_vlocation *vl,
                _debug("CellServ[%hu]: %08x", cell->vl_curr_svix, addr.s_addr);
 
                /* attempt to access the VL server */
-               ret = afs_vl_get_entry_by_name(&addr, vl->vldb.name, vldb,
+               ret = afs_vl_get_entry_by_name(&addr, key, vl->vldb.name, vldb,
                                               &afs_sync_call);
                switch (ret) {
                case 0:
@@ -86,6 +88,7 @@ out:
  * about the volume in question
  */
 static int afs_vlocation_access_vl_by_id(struct afs_vlocation *vl,
+                                        struct key *key,
                                         afs_volid_t volid,
                                         afs_voltype_t voltype,
                                         struct afs_cache_vlocation *vldb)
@@ -104,7 +107,7 @@ static int afs_vlocation_access_vl_by_id(struct afs_vlocation *vl,
                _debug("CellServ[%hu]: %08x", cell->vl_curr_svix, addr.s_addr);
 
                /* attempt to access the VL server */
-               ret = afs_vl_get_entry_by_id(&addr, volid, voltype, vldb,
+               ret = afs_vl_get_entry_by_id(&addr, key, volid, voltype, vldb,
                                             &afs_sync_call);
                switch (ret) {
                case 0:
@@ -176,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);
        }
 
@@ -188,6 +191,7 @@ static struct afs_vlocation *afs_vlocation_alloc(struct afs_cell *cell,
  * update record if we found it in the cache
  */
 static int afs_vlocation_update_record(struct afs_vlocation *vl,
+                                      struct key *key,
                                       struct afs_cache_vlocation *vldb)
 {
        afs_voltype_t voltype;
@@ -228,7 +232,7 @@ static int afs_vlocation_update_record(struct afs_vlocation *vl,
        /* contact the server to make sure the volume is still available
         * - TODO: need to handle disconnected operation here
         */
-       ret = afs_vlocation_access_vl_by_id(vl, vid, voltype, vldb);
+       ret = afs_vlocation_access_vl_by_id(vl, key, vid, voltype, vldb);
        switch (ret) {
                /* net error */
        default:
@@ -287,7 +291,8 @@ static void afs_vlocation_apply_update(struct afs_vlocation *vl,
  * fill in a volume location record, consulting the cache and the VL server
  * both
  */
-static int afs_vlocation_fill_in_record(struct afs_vlocation *vl)
+static int afs_vlocation_fill_in_record(struct afs_vlocation *vl,
+                                       struct key *key)
 {
        struct afs_cache_vlocation vldb;
        int ret;
@@ -310,11 +315,11 @@ static int afs_vlocation_fill_in_record(struct afs_vlocation *vl)
                /* try to update a known volume in the cell VL databases by
                 * ID as the name may have changed */
                _debug("found in cache");
-               ret = afs_vlocation_update_record(vl, &vldb);
+               ret = afs_vlocation_update_record(vl, key, &vldb);
        } else {
                /* try to look up an unknown volume in the cell VL databases by
                 * name */
-               ret = afs_vlocation_access_vl_by_name(vl, &vldb);
+               ret = afs_vlocation_access_vl_by_name(vl, key, &vldb);
                if (ret < 0) {
                        printk("kAFS: failed to locate '%s' in cell '%s'\n",
                               vl->vldb.name, vl->cell->name);
@@ -366,14 +371,16 @@ void afs_vlocation_queue_for_updates(struct afs_vlocation *vl)
  * - insert/update in the local cache if did get a VL response
  */
 struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *cell,
+                                          struct key *key,
                                           const char *name,
                                           size_t namesz)
 {
        struct afs_vlocation *vl;
        int ret;
 
-       _enter("{%s},%*.*s,%zu",
-              cell->name, (int) namesz, (int) namesz, name, namesz);
+       _enter("{%s},{%x},%*.*s,%zu",
+              cell->name, key_serial(key),
+              (int) namesz, (int) namesz, name, namesz);
 
        if (namesz > sizeof(vl->vldb.name)) {
                _leave(" = -ENAMETOOLONG");
@@ -405,10 +412,12 @@ struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *cell,
        up_write(&cell->vl_sem);
 
 fill_in_record:
-       ret = afs_vlocation_fill_in_record(vl);
+       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 */
@@ -428,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);
@@ -590,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;
 
@@ -656,7 +669,8 @@ static void afs_vlocation_updater(struct work_struct *work)
        vl->upd_rej_cnt = 0;
        vl->upd_busy_cnt = 0;
 
-       ret = afs_vlocation_update_record(vl, &vldb);
+       ret = afs_vlocation_update_record(vl, NULL, &vldb);
+       spin_lock(&vl->lock);
        switch (ret) {
        case 0:
                afs_vlocation_apply_update(vl, &vldb);
@@ -669,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");