X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=fs%2Fafs%2Fvlocation.c;h=09e3ad0fc7cc2163684a97cbe54b4f1eb51cf6b9;hb=ecd27b92fbb41f779d857632a69bd45dbaf0f915;hp=7d9815e9ae0f03091716ddf7f060891a5ad8db51;hpb=00d3b7a4533e367b0dc2812a706db8f9f071c27f;p=linux-2.6 diff --git a/fs/afs/vlocation.c b/fs/afs/vlocation.c index 7d9815e9ae..09e3ad0fc7 100644 --- a/fs/afs/vlocation.c +++ b/fs/afs/vlocation.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "internal.h" unsigned afs_vlocation_timeout = 10; /* volume location timeout in seconds */ @@ -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); } @@ -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");