KVM: MMU: invalidate and flush on spte small->large page size change
[safe/jmp/linux-2.6] / fs / afs / vlocation.c
index 7d9815e..9ac260d 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/slab.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 *);
@@ -64,6 +66,8 @@ static int afs_vlocation_access_vl_by_name(struct afs_vlocation *vl,
                                goto out;
                        goto rotate;
                case -ENOMEDIUM:
+               case -EKEYREJECTED:
+               case -EKEYEXPIRED:
                        goto out;
                default:
                        ret = -EIO;
@@ -178,7 +182,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);
        }
 
@@ -280,9 +284,8 @@ static void afs_vlocation_apply_update(struct afs_vlocation *vl,
 
        vl->vldb = *vldb;
 
-#ifdef AFS_CACHING_SUPPORT
-       /* update volume entry in local cache */
-       cachefs_update_cookie(vl->cache);
+#ifdef CONFIG_AFS_FSCACHE
+       fscache_update_cookie(vl->cache);
 #endif
 }
 
@@ -303,11 +306,9 @@ static int afs_vlocation_fill_in_record(struct afs_vlocation *vl,
        memset(&vldb, 0, sizeof(vldb));
 
        /* see if we have an in-cache copy (will set vl->valid if there is) */
-#ifdef AFS_CACHING_SUPPORT
-       cachefs_acquire_cookie(cell->cache,
-                              &afs_volume_cache_index_def,
-                              vlocation,
-                              &vl->cache);
+#ifdef CONFIG_AFS_FSCACHE
+       vl->cache = fscache_acquire_cookie(vl->cell->cache,
+                                          &afs_vlocation_cache_index_def, vl);
 #endif
 
        if (vl->valid) {
@@ -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,9 +415,16 @@ 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);
 
+       /* update volume entry in local cache */
+#ifdef CONFIG_AFS_FSCACHE
+       fscache_update_cookie(vl->cache);
+#endif
+
        /* schedule for regular updates */
        afs_vlocation_queue_for_updates(vl);
        goto success;
@@ -434,37 +442,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);
+       _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);
@@ -516,10 +528,9 @@ static void afs_vlocation_destroy(struct afs_vlocation *vl)
 {
        _enter("%p", vl);
 
-#ifdef AFS_CACHING_SUPPORT
-       cachefs_relinquish_cookie(vl->cache, 0);
+#ifdef CONFIG_AFS_FSCACHE
+       fscache_relinquish_cookie(vl->cache, 0);
 #endif
-
        afs_put_cell(vl->cell);
        kfree(vl);
 }
@@ -596,7 +607,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 +674,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 +687,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");