aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/autofs4/autofs_i.h5
-rw-r--r--fs/autofs4/root.c10
-rw-r--r--fs/autofs4/waitq.c77
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)
327static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) 327static 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
192static struct autofs_wait_queue *
193autofs4_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
192int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, 207int 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 */