Skip to content

Commit

Permalink
[AFS]: Eliminate cmpxchg() usage in vlocation code.
Browse files Browse the repository at this point in the history
cmpxchg() is not available on every processor so can't
be used in generic code.

Replace with spinlock protection on the ->state changes,
wakeups, and wait loops.

Add what appears to be a missing wakeup on transition
to AFS_VL_VALID state in afs_vlocation_updater().

Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
David S. Miller committed Apr 27, 2007
1 parent 68c708f commit 39bf094
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 6 deletions.
2 changes: 1 addition & 1 deletion fs/afs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ struct afs_vlocation {
struct afs_volume *vols[3]; /* volume access record pointer (index by type) */
wait_queue_head_t waitq; /* status change waitqueue */
time_t update_at; /* time at which record should be updated */
rwlock_t lock; /* access lock */
spinlock_t lock; /* access lock */
afs_vlocation_state_t state; /* volume location state */
unsigned short upd_rej_cnt; /* ENOMEDIUM count during update */
unsigned short upd_busy_cnt; /* EBUSY count during update */
Expand Down
20 changes: 15 additions & 5 deletions fs/afs/vlocation.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,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);
}

Expand Down Expand Up @@ -414,8 +414,10 @@ struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *cell,
ret = afs_vlocation_fill_in_record(vl, key);
if (ret < 0)
goto error_abandon;
spin_lock(&vl->lock);
vl->state = AFS_VL_VALID;
wake_up(&vl->waitq);
spin_unlock(&vl->lock);

/* schedule for regular updates */
afs_vlocation_queue_for_updates(vl);
Expand All @@ -434,38 +436,43 @@ struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *cell,
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;
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");

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;
wake_up(&vl->waitq);
spin_unlock(&vl->lock);
error:
ASSERT(vl != NULL);
afs_put_vlocation(vl);
Expand Down Expand Up @@ -663,10 +670,12 @@ 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);
vl->state = AFS_VL_VALID;
wake_up(&vl->waitq);
break;
case -ENOMEDIUM:
vl->state = AFS_VL_VOLUME_DELETED;
Expand All @@ -675,6 +684,7 @@ static void afs_vlocation_updater(struct work_struct *work)
vl->state = AFS_VL_UNCERTAIN;
break;
}
spin_unlock(&vl->lock);

/* and then reschedule */
_debug("reschedule");
Expand Down

0 comments on commit 39bf094

Please sign in to comment.