diff options
| author | Jeff Garzik <jeff@garzik.org> | 2006-05-20 00:36:08 -0400 |
|---|---|---|
| committer | Jeff Garzik <jeff@garzik.org> | 2006-05-20 00:36:08 -0400 |
| commit | 3d71b3b0b634b1a5ba8632fd9ec998e0e4aedfdb (patch) | |
| tree | addbc37a278a126a19e03edd8270e577c75a8829 /fs/autofs4 | |
| parent | 8d4ee71ff6de5255ebfdf44fb83419d27bd06368 (diff) | |
| parent | e2a7f77a7b4ab298a38c8d1f624628456069bdb0 (diff) | |
Merge branch 'upstream-fixes' into upstream
Conflicts:
drivers/scsi/libata-core.c
Diffstat (limited to 'fs/autofs4')
| -rw-r--r-- | fs/autofs4/autofs_i.h | 5 | ||||
| -rw-r--r-- | fs/autofs4/root.c | 10 | ||||
| -rw-r--r-- | fs/autofs4/waitq.c | 77 |
3 files changed, 58 insertions, 34 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index 57c4903614e5..d6603d02304c 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h | |||
| @@ -74,8 +74,8 @@ struct autofs_wait_queue { | |||
| 74 | struct autofs_wait_queue *next; | 74 | struct autofs_wait_queue *next; |
| 75 | autofs_wqt_t wait_queue_token; | 75 | autofs_wqt_t wait_queue_token; |
| 76 | /* We use the following to see what we are waiting for */ | 76 | /* We use the following to see what we are waiting for */ |
| 77 | int hash; | 77 | unsigned int hash; |
| 78 | int len; | 78 | unsigned int len; |
| 79 | char *name; | 79 | char *name; |
| 80 | u32 dev; | 80 | u32 dev; |
| 81 | u64 ino; | 81 | u64 ino; |
| @@ -85,7 +85,6 @@ struct autofs_wait_queue { | |||
| 85 | pid_t tgid; | 85 | pid_t tgid; |
| 86 | /* This is for status reporting upon return */ | 86 | /* This is for status reporting upon return */ |
| 87 | int status; | 87 | int status; |
| 88 | atomic_t notify; | ||
| 89 | atomic_t wait_ctr; | 88 | atomic_t wait_ctr; |
| 90 | }; | 89 | }; |
| 91 | 90 | ||
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 84e030c8ddd0..5100f984783f 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
| @@ -327,6 +327,7 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags) | |||
| 327 | static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) | 327 | static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) |
| 328 | { | 328 | { |
| 329 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | 329 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); |
| 330 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | ||
| 330 | int oz_mode = autofs4_oz_mode(sbi); | 331 | int oz_mode = autofs4_oz_mode(sbi); |
| 331 | unsigned int lookup_type; | 332 | unsigned int lookup_type; |
| 332 | int status; | 333 | int status; |
| @@ -340,13 +341,8 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
| 340 | if (oz_mode || !lookup_type) | 341 | if (oz_mode || !lookup_type) |
| 341 | goto done; | 342 | goto done; |
| 342 | 343 | ||
| 343 | /* | 344 | /* If an expire request is pending wait for it. */ |
| 344 | * If a request is pending wait for it. | 345 | if (ino && (ino->flags & AUTOFS_INF_EXPIRING)) { |
| 345 | * If it's a mount then it won't be expired till at least | ||
| 346 | * a liitle later and if it's an expire then we might need | ||
| 347 | * to mount it again. | ||
| 348 | */ | ||
| 349 | if (autofs4_ispending(dentry)) { | ||
| 350 | DPRINTK("waiting for active request %p name=%.*s", | 346 | DPRINTK("waiting for active request %p name=%.*s", |
| 351 | dentry, dentry->d_name.len, dentry->d_name.name); | 347 | dentry, dentry->d_name.len, dentry->d_name.name); |
| 352 | 348 | ||
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index 142ab6aa2aa1..ce103e7b0bc3 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c | |||
| @@ -189,14 +189,30 @@ static int autofs4_getpath(struct autofs_sb_info *sbi, | |||
| 189 | return len; | 189 | return len; |
| 190 | } | 190 | } |
| 191 | 191 | ||
| 192 | static struct autofs_wait_queue * | ||
| 193 | autofs4_find_wait(struct autofs_sb_info *sbi, | ||
| 194 | char *name, unsigned int hash, unsigned int len) | ||
| 195 | { | ||
| 196 | struct autofs_wait_queue *wq; | ||
| 197 | |||
| 198 | for (wq = sbi->queues; wq; wq = wq->next) { | ||
| 199 | if (wq->hash == hash && | ||
| 200 | wq->len == len && | ||
| 201 | wq->name && !memcmp(wq->name, name, len)) | ||
| 202 | break; | ||
| 203 | } | ||
| 204 | return wq; | ||
| 205 | } | ||
| 206 | |||
| 192 | int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | 207 | int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, |
| 193 | enum autofs_notify notify) | 208 | enum autofs_notify notify) |
| 194 | { | 209 | { |
| 210 | struct autofs_info *ino; | ||
| 195 | struct autofs_wait_queue *wq; | 211 | struct autofs_wait_queue *wq; |
| 196 | char *name; | 212 | char *name; |
| 197 | unsigned int len = 0; | 213 | unsigned int len = 0; |
| 198 | unsigned int hash = 0; | 214 | unsigned int hash = 0; |
| 199 | int status; | 215 | int status, type; |
| 200 | 216 | ||
| 201 | /* In catatonic mode, we don't wait for nobody */ | 217 | /* In catatonic mode, we don't wait for nobody */ |
| 202 | if (sbi->catatonic) | 218 | if (sbi->catatonic) |
| @@ -223,21 +239,41 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
| 223 | return -EINTR; | 239 | return -EINTR; |
| 224 | } | 240 | } |
| 225 | 241 | ||
| 226 | for (wq = sbi->queues ; wq ; wq = wq->next) { | 242 | wq = autofs4_find_wait(sbi, name, hash, len); |
| 227 | if (wq->hash == dentry->d_name.hash && | 243 | ino = autofs4_dentry_ino(dentry); |
| 228 | wq->len == len && | 244 | if (!wq && ino && notify == NFY_NONE) { |
| 229 | wq->name && !memcmp(wq->name, name, len)) | 245 | /* |
| 230 | break; | 246 | * Either we've betean the pending expire to post it's |
| 231 | } | 247 | * wait or it finished while we waited on the mutex. |
| 248 | * So we need to wait till either, the wait appears | ||
| 249 | * or the expire finishes. | ||
| 250 | */ | ||
| 251 | |||
| 252 | while (ino->flags & AUTOFS_INF_EXPIRING) { | ||
| 253 | mutex_unlock(&sbi->wq_mutex); | ||
| 254 | schedule_timeout_interruptible(HZ/10); | ||
| 255 | if (mutex_lock_interruptible(&sbi->wq_mutex)) { | ||
| 256 | kfree(name); | ||
| 257 | return -EINTR; | ||
| 258 | } | ||
| 259 | wq = autofs4_find_wait(sbi, name, hash, len); | ||
| 260 | if (wq) | ||
| 261 | break; | ||
| 262 | } | ||
| 232 | 263 | ||
| 233 | if (!wq) { | 264 | /* |
| 234 | /* Can't wait for an expire if there's no mount */ | 265 | * Not ideal but the status has already gone. Of the two |
| 235 | if (notify == NFY_NONE && !d_mountpoint(dentry)) { | 266 | * cases where we wait on NFY_NONE neither depend on the |
| 267 | * return status of the wait. | ||
| 268 | */ | ||
| 269 | if (!wq) { | ||
| 236 | kfree(name); | 270 | kfree(name); |
| 237 | mutex_unlock(&sbi->wq_mutex); | 271 | mutex_unlock(&sbi->wq_mutex); |
| 238 | return -ENOENT; | 272 | return 0; |
| 239 | } | 273 | } |
| 274 | } | ||
| 240 | 275 | ||
| 276 | if (!wq) { | ||
| 241 | /* Create a new wait queue */ | 277 | /* Create a new wait queue */ |
| 242 | wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL); | 278 | wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL); |
| 243 | if (!wq) { | 279 | if (!wq) { |
| @@ -263,20 +299,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
| 263 | wq->tgid = current->tgid; | 299 | wq->tgid = current->tgid; |
| 264 | wq->status = -EINTR; /* Status return if interrupted */ | 300 | wq->status = -EINTR; /* Status return if interrupted */ |
| 265 | atomic_set(&wq->wait_ctr, 2); | 301 | atomic_set(&wq->wait_ctr, 2); |
| 266 | atomic_set(&wq->notify, 1); | ||
| 267 | mutex_unlock(&sbi->wq_mutex); | ||
| 268 | } else { | ||
| 269 | atomic_inc(&wq->wait_ctr); | ||
| 270 | mutex_unlock(&sbi->wq_mutex); | 302 | mutex_unlock(&sbi->wq_mutex); |
| 271 | kfree(name); | ||
| 272 | DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d", | ||
| 273 | (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify); | ||
| 274 | } | ||
| 275 | |||
| 276 | if (notify != NFY_NONE && atomic_read(&wq->notify)) { | ||
| 277 | int type; | ||
| 278 | |||
| 279 | atomic_dec(&wq->notify); | ||
| 280 | 303 | ||
| 281 | if (sbi->version < 5) { | 304 | if (sbi->version < 5) { |
| 282 | if (notify == NFY_MOUNT) | 305 | if (notify == NFY_MOUNT) |
| @@ -299,6 +322,12 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
| 299 | 322 | ||
| 300 | /* autofs4_notify_daemon() may block */ | 323 | /* autofs4_notify_daemon() may block */ |
| 301 | autofs4_notify_daemon(sbi, wq, type); | 324 | autofs4_notify_daemon(sbi, wq, type); |
| 325 | } else { | ||
| 326 | atomic_inc(&wq->wait_ctr); | ||
| 327 | mutex_unlock(&sbi->wq_mutex); | ||
| 328 | kfree(name); | ||
| 329 | DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d", | ||
| 330 | (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify); | ||
| 302 | } | 331 | } |
| 303 | 332 | ||
| 304 | /* wq->name is NULL if and only if the lock is already released */ | 333 | /* wq->name is NULL if and only if the lock is already released */ |
