Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 105463
b: refs/heads/master
c: a1362fe
h: refs/heads/master
i:
  105461: b963978
  105459: b901932
  105455: 42df4ee
v: v3
  • Loading branch information
Ian Kent authored and Linus Torvalds committed Jul 24, 2008
1 parent 6d14ee5 commit 760684a
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 39 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5a11d4d0ee1ff284271f7265929d07ea4a1168a6
refs/heads/master: a1362fe92f1bde687b3a9e93d6b8d105d0a84f74
135 changes: 97 additions & 38 deletions trunk/fs/autofs4/waitq.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,19 +215,106 @@ autofs4_find_wait(struct autofs_sb_info *sbi, struct qstr *qstr)
return wq;
}

/*
* Check if we have a valid request.
* Returns
* 1 if the request should continue.
* In this case we can return an autofs_wait_queue entry if one is
* found or NULL to idicate a new wait needs to be created.
* 0 or a negative errno if the request shouldn't continue.
*/
static int validate_request(struct autofs_wait_queue **wait,
struct autofs_sb_info *sbi,
struct qstr *qstr,
struct dentry*dentry, enum autofs_notify notify)
{
struct autofs_wait_queue *wq;
struct autofs_info *ino;

/* Wait in progress, continue; */
wq = autofs4_find_wait(sbi, qstr);
if (wq) {
*wait = wq;
return 1;
}

*wait = NULL;

/* If we don't yet have any info this is a new request */
ino = autofs4_dentry_ino(dentry);
if (!ino)
return 1;

/*
* If we've been asked to wait on an existing expire (NFY_NONE)
* but there is no wait in the queue ...
*/
if (notify == NFY_NONE) {
/*
* Either we've betean the pending expire to post it's
* wait or it finished while we waited on the mutex.
* So we need to wait till either, the wait appears
* or the expire finishes.
*/

while (ino->flags & AUTOFS_INF_EXPIRING) {
mutex_unlock(&sbi->wq_mutex);
schedule_timeout_interruptible(HZ/10);
if (mutex_lock_interruptible(&sbi->wq_mutex))
return -EINTR;

wq = autofs4_find_wait(sbi, qstr);
if (wq) {
*wait = wq;
return 1;
}
}

/*
* Not ideal but the status has already gone. Of the two
* cases where we wait on NFY_NONE neither depend on the
* return status of the wait.
*/
return 0;
}

/*
* If we've been asked to trigger a mount and the request
* completed while we waited on the mutex ...
*/
if (notify == NFY_MOUNT) {
/*
* If the dentry isn't hashed just go ahead and try the
* mount again with a new wait (not much else we can do).
*/
if (!d_unhashed(dentry)) {
/*
* But if the dentry is hashed, that means that we
* got here through the revalidate path. Thus, we
* need to check if the dentry has been mounted
* while we waited on the wq_mutex. If it has,
* simply return success.
*/
if (d_mountpoint(dentry))
return 0;
}
}

return 1;
}

int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
enum autofs_notify notify)
{
struct autofs_info *ino;
struct autofs_wait_queue *wq;
struct qstr qstr;
char *name;
int status, type;
int status, ret, type;

/* In catatonic mode, we don't wait for nobody */
if (sbi->catatonic)
return -ENOENT;

name = kmalloc(NAME_MAX + 1, GFP_KERNEL);
if (!name)
return -ENOMEM;
Expand All @@ -245,43 +332,15 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
qstr.name = name;
qstr.hash = full_name_hash(name, qstr.len);

if (mutex_lock_interruptible(&sbi->wq_mutex)) {
kfree(qstr.name);
if (mutex_lock_interruptible(&sbi->wq_mutex))
return -EINTR;
}

wq = autofs4_find_wait(sbi, &qstr);
ino = autofs4_dentry_ino(dentry);
if (!wq && ino && notify == NFY_NONE) {
/*
* Either we've betean the pending expire to post it's
* wait or it finished while we waited on the mutex.
* So we need to wait till either, the wait appears
* or the expire finishes.
*/

while (ino->flags & AUTOFS_INF_EXPIRING) {
mutex_unlock(&sbi->wq_mutex);
schedule_timeout_interruptible(HZ/10);
if (mutex_lock_interruptible(&sbi->wq_mutex)) {
kfree(qstr.name);
return -EINTR;
}
wq = autofs4_find_wait(sbi, &qstr);
if (wq)
break;
}

/*
* Not ideal but the status has already gone. Of the two
* cases where we wait on NFY_NONE neither depend on the
* return status of the wait.
*/
if (!wq) {
kfree(qstr.name);
ret = validate_request(&wq, sbi, &qstr, dentry, notify);
if (ret <= 0) {
if (ret == 0)
mutex_unlock(&sbi->wq_mutex);
return 0;
}
kfree(qstr.name);
return ret;
}

if (!wq) {
Expand Down Expand Up @@ -392,9 +451,9 @@ int autofs4_wait_release(struct autofs_sb_info *sbi, autofs_wqt_t wait_queue_tok
}

*wql = wq->next; /* Unlink from chain */
mutex_unlock(&sbi->wq_mutex);
kfree(wq->name.name);
wq->name.name = NULL; /* Do not wait on this queue */
mutex_unlock(&sbi->wq_mutex);

wq->status = status;

Expand Down

0 comments on commit 760684a

Please sign in to comment.