Blame view

fs/autofs4/waitq.c 13.8 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
  /* -*- c -*- --------------------------------------------------------------- *
   *
   * linux/fs/autofs/waitq.c
   *
   *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
5c0a32fc2   Ian Kent   [PATCH] autofs4: ...
6
   *  Copyright 2001-2006 Ian Kent <raven@themaw.net>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
   *
   * This file is part of the Linux kernel and is made available under
   * the terms of the GNU General Public License, version 2, or at your
   * option, any later version, incorporated herein by reference.
   *
   * ------------------------------------------------------------------------- */
  
  #include <linux/slab.h>
  #include <linux/time.h>
  #include <linux/signal.h>
  #include <linux/file.h>
  #include "autofs_i.h"
  
  /* We make this a static variable rather than a part of the superblock; it
     is better if we don't reassign numbers easily even across filesystems */
  static autofs_wqt_t autofs4_next_wait_queue = 1;
  
  /* These are the signals we allow interrupting a pending mount */
  #define SHUTDOWN_SIGS	(sigmask(SIGKILL) | sigmask(SIGINT) | sigmask(SIGQUIT))
  
  void autofs4_catatonic_mode(struct autofs_sb_info *sbi)
  {
  	struct autofs_wait_queue *wq, *nwq;
5a11d4d0e   Ian Kent   autofs4: fix wait...
30
31
32
33
34
  	mutex_lock(&sbi->wq_mutex);
  	if (sbi->catatonic) {
  		mutex_unlock(&sbi->wq_mutex);
  		return;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
36
37
38
39
  	DPRINTK("entering catatonic mode");
  
  	sbi->catatonic = 1;
  	wq = sbi->queues;
  	sbi->queues = NULL;	/* Erase all wait queues */
e77fbddf7   Ian Kent   [PATCH] autofs4: ...
40
  	while (wq) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
  		nwq = wq->next;
  		wq->status = -ENOENT; /* Magic is gone - report failure */
70b52a0a5   Jeff Moyer   autofs4: use stru...
43
44
45
46
  		if (wq->name.name) {
  			kfree(wq->name.name);
  			wq->name.name = NULL;
  		}
296f7bf78   Ian Kent   autofs4: fix wait...
47
  		wq->wait_ctr--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
50
  		wake_up_interruptible(&wq->queue);
  		wq = nwq;
  	}
ba8df43c0   Ian Kent   [PATCH] autofs4: ...
51
52
  	fput(sbi->pipe);	/* Close the pipe */
  	sbi->pipe = NULL;
5a11d4d0e   Ian Kent   autofs4: fix wait...
53
54
  	sbi->pipefd = -1;
  	mutex_unlock(&sbi->wq_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
  }
d668dc566   Al Viro   autofs4: deal wit...
56
57
  static int autofs4_write(struct autofs_sb_info *sbi,
  			 struct file *file, const void *addr, int bytes)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
60
61
62
  {
  	unsigned long sigpipe, flags;
  	mm_segment_t fs;
  	const char *data = (const char *)addr;
  	ssize_t wr = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
64
65
66
67
  	sigpipe = sigismember(&current->pending.signal, SIGPIPE);
  
  	/* Save pointer to user space and point back to kernel space */
  	fs = get_fs();
  	set_fs(KERNEL_DS);
d668dc566   Al Viro   autofs4: deal wit...
68
  	mutex_lock(&sbi->pipe_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
71
72
73
  	while (bytes &&
  	       (wr = file->f_op->write(file,data,bytes,&file->f_pos)) > 0) {
  		data += wr;
  		bytes -= wr;
  	}
8638094e9   Ian Kent   autofs4 - fix dea...
74
  	mutex_unlock(&sbi->pipe_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
  
  	set_fs(fs);
  
  	/* Keep the currently executing process from receiving a
  	   SIGPIPE unless it was already supposed to get one */
  	if (wr == -EPIPE && !sigpipe) {
  		spin_lock_irqsave(&current->sighand->siglock, flags);
  		sigdelset(&current->pending.signal, SIGPIPE);
  		recalc_sigpending();
  		spin_unlock_irqrestore(&current->sighand->siglock, flags);
  	}
  
  	return (bytes > 0);
  }
  	
  static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
  				 struct autofs_wait_queue *wq,
  				 int type)
  {
e8514478f   Ian Kent   [PATCH] autofs4: ...
94
95
96
97
98
  	union {
  		struct autofs_packet_hdr hdr;
  		union autofs_packet_union v4_pkt;
  		union autofs_v5_packet_union v5_pkt;
  	} pkt;
e64be33cc   Ian Kent   autofs4: check ke...
99
  	struct file *pipe = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
102
  	size_t pktsz;
  
  	DPRINTK("wait id = 0x%08lx, name = %.*s, type=%d",
2f84dd709   Linus Torvalds   autofs4: fix debu...
103
  		(unsigned long) wq->wait_queue_token, wq->name.len, wq->name.name, type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
105
106
107
108
  
  	memset(&pkt,0,sizeof pkt); /* For security reasons */
  
  	pkt.hdr.proto_version = sbi->version;
  	pkt.hdr.type = type;
875333326   Al Viro   autofs4: catatoni...
109
110
111
112
113
114
115
  	mutex_lock(&sbi->wq_mutex);
  
  	/* Check if we have become catatonic */
  	if (sbi->catatonic) {
  		mutex_unlock(&sbi->wq_mutex);
  		return;
  	}
5c0a32fc2   Ian Kent   [PATCH] autofs4: ...
116
117
118
119
  	switch (type) {
  	/* Kernel protocol v4 missing and expire packets */
  	case autofs_ptype_missing:
  	{
e8514478f   Ian Kent   [PATCH] autofs4: ...
120
  		struct autofs_packet_missing *mp = &pkt.v4_pkt.missing;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
123
124
  
  		pktsz = sizeof(*mp);
  
  		mp->wait_queue_token = wq->wait_queue_token;
70b52a0a5   Jeff Moyer   autofs4: use stru...
125
126
127
  		mp->len = wq->name.len;
  		memcpy(mp->name, wq->name.name, wq->name.len);
  		mp->name[wq->name.len] = '\0';
5c0a32fc2   Ian Kent   [PATCH] autofs4: ...
128
129
130
131
  		break;
  	}
  	case autofs_ptype_expire_multi:
  	{
e8514478f   Ian Kent   [PATCH] autofs4: ...
132
  		struct autofs_packet_expire_multi *ep = &pkt.v4_pkt.expire_multi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133
134
135
136
  
  		pktsz = sizeof(*ep);
  
  		ep->wait_queue_token = wq->wait_queue_token;
70b52a0a5   Jeff Moyer   autofs4: use stru...
137
138
139
  		ep->len = wq->name.len;
  		memcpy(ep->name, wq->name.name, wq->name.len);
  		ep->name[wq->name.len] = '\0';
5c0a32fc2   Ian Kent   [PATCH] autofs4: ...
140
141
142
143
144
145
146
147
148
149
150
  		break;
  	}
  	/*
  	 * Kernel protocol v5 packet for handling indirect and direct
  	 * mount missing and expire requests
  	 */
  	case autofs_ptype_missing_indirect:
  	case autofs_ptype_expire_indirect:
  	case autofs_ptype_missing_direct:
  	case autofs_ptype_expire_direct:
  	{
e8514478f   Ian Kent   [PATCH] autofs4: ...
151
  		struct autofs_v5_packet *packet = &pkt.v5_pkt.v5_packet;
5c0a32fc2   Ian Kent   [PATCH] autofs4: ...
152
153
154
155
  
  		pktsz = sizeof(*packet);
  
  		packet->wait_queue_token = wq->wait_queue_token;
70b52a0a5   Jeff Moyer   autofs4: use stru...
156
157
158
  		packet->len = wq->name.len;
  		memcpy(packet->name, wq->name.name, wq->name.len);
  		packet->name[wq->name.len] = '\0';
5c0a32fc2   Ian Kent   [PATCH] autofs4: ...
159
160
161
162
163
164
165
166
167
  		packet->dev = wq->dev;
  		packet->ino = wq->ino;
  		packet->uid = wq->uid;
  		packet->gid = wq->gid;
  		packet->pid = wq->pid;
  		packet->tgid = wq->tgid;
  		break;
  	}
  	default:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
169
  		printk("autofs4_notify_daemon: bad type %d!
  ", type);
875333326   Al Viro   autofs4: catatoni...
170
  		mutex_unlock(&sbi->wq_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
172
  		return;
  	}
875333326   Al Viro   autofs4: catatoni...
173
174
  	pipe = sbi->pipe;
  	get_file(pipe);
e64be33cc   Ian Kent   autofs4: check ke...
175
  	mutex_unlock(&sbi->wq_mutex);
d668dc566   Al Viro   autofs4: deal wit...
176
  	if (autofs4_write(sbi, pipe, &pkt, pktsz))
875333326   Al Viro   autofs4: catatoni...
177
178
  		autofs4_catatonic_mode(sbi);
  	fput(pipe);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
180
181
182
183
184
185
  }
  
  static int autofs4_getpath(struct autofs_sb_info *sbi,
  			   struct dentry *dentry, char **name)
  {
  	struct dentry *root = sbi->sb->s_root;
  	struct dentry *tmp;
949854d02   Nick Piggin   fs: Use rename lo...
186
  	char *buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
  	char *p;
949854d02   Nick Piggin   fs: Use rename lo...
188
189
190
191
192
193
  	int len;
  	unsigned seq;
  
  rename_retry:
  	buf = *name;
  	len = 0;
b5c84bf6f   Nick Piggin   fs: dcache remove...
194

949854d02   Nick Piggin   fs: Use rename lo...
195
196
  	seq = read_seqbegin(&rename_lock);
  	rcu_read_lock();
e7854723d   Ian Kent   autofs4 - remove ...
197
  	spin_lock(&sbi->fs_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
199
  	for (tmp = dentry ; tmp != root ; tmp = tmp->d_parent)
  		len += tmp->d_name.len + 1;
cab0936aa   Ian Kent   autofs4: check fo...
200
  	if (!len || --len > NAME_MAX) {
e7854723d   Ian Kent   autofs4 - remove ...
201
  		spin_unlock(&sbi->fs_lock);
949854d02   Nick Piggin   fs: Use rename lo...
202
203
204
  		rcu_read_unlock();
  		if (read_seqretry(&rename_lock, seq))
  			goto rename_retry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205
206
207
208
209
210
211
212
213
214
215
216
  		return 0;
  	}
  
  	*(buf + len) = '\0';
  	p = buf + len - dentry->d_name.len;
  	strncpy(p, dentry->d_name.name, dentry->d_name.len);
  
  	for (tmp = dentry->d_parent; tmp != root ; tmp = tmp->d_parent) {
  		*(--p) = '/';
  		p -= tmp->d_name.len;
  		strncpy(p, tmp->d_name.name, tmp->d_name.len);
  	}
e7854723d   Ian Kent   autofs4 - remove ...
217
  	spin_unlock(&sbi->fs_lock);
949854d02   Nick Piggin   fs: Use rename lo...
218
219
220
  	rcu_read_unlock();
  	if (read_seqretry(&rename_lock, seq))
  		goto rename_retry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
222
223
  
  	return len;
  }
a53705539   Ian Kent   [PATCH] autofs4: ...
224
  static struct autofs_wait_queue *
70b52a0a5   Jeff Moyer   autofs4: use stru...
225
  autofs4_find_wait(struct autofs_sb_info *sbi, struct qstr *qstr)
a53705539   Ian Kent   [PATCH] autofs4: ...
226
227
228
229
  {
  	struct autofs_wait_queue *wq;
  
  	for (wq = sbi->queues; wq; wq = wq->next) {
70b52a0a5   Jeff Moyer   autofs4: use stru...
230
231
232
233
  		if (wq->name.hash == qstr->hash &&
  		    wq->name.len == qstr->len &&
  		    wq->name.name &&
  			 !memcmp(wq->name.name, qstr->name, qstr->len))
a53705539   Ian Kent   [PATCH] autofs4: ...
234
235
236
237
  			break;
  	}
  	return wq;
  }
a1362fe92   Ian Kent   autofs4: fix pend...
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
  /*
   * 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;
4041bcdc7   Al Viro   autofs4: autofs4_...
253
254
  	if (sbi->catatonic)
  		return -ENOENT;
a1362fe92   Ian Kent   autofs4: fix pend...
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
  	/* 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;
4041bcdc7   Al Viro   autofs4: autofs4_...
286
287
  			if (sbi->catatonic)
  				return -ENOENT;
a1362fe92   Ian Kent   autofs4: fix pend...
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
  			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) {
9e3fea16b   Ian Kent   autofs4: Fix wait...
308
309
  		struct dentry *new = NULL;
  		int valid = 1;
a1362fe92   Ian Kent   autofs4: fix pend...
310
  		/*
463aea1a1   Ian Kent   autofs4: remove h...
311
312
313
314
315
316
  		 * If the dentry was successfully mounted while we slept
  		 * on the wait queue mutex we can return success. If it
  		 * isn't mounted (doesn't have submounts for the case of
  		 * a multi-mount with no mount at it's base) we can
  		 * continue on and create a new request.
  		 */
9e3fea16b   Ian Kent   autofs4: Fix wait...
317
318
319
320
321
322
323
324
  		if (!IS_ROOT(dentry)) {
  			if (dentry->d_inode && d_unhashed(dentry)) {
  				struct dentry *parent = dentry->d_parent;
  				new = d_lookup(parent, &dentry->d_name);
  				if (new)
  					dentry = new;
  			}
  		}
463aea1a1   Ian Kent   autofs4: remove h...
325
  		if (have_submounts(dentry))
9e3fea16b   Ian Kent   autofs4: Fix wait...
326
327
328
329
330
  			valid = 0;
  
  		if (new)
  			dput(new);
  		return valid;
a1362fe92   Ian Kent   autofs4: fix pend...
331
332
333
334
  	}
  
  	return 1;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
336
337
338
  int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
  		enum autofs_notify notify)
  {
  	struct autofs_wait_queue *wq;
70b52a0a5   Jeff Moyer   autofs4: use stru...
339
  	struct qstr qstr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340
  	char *name;
a1362fe92   Ian Kent   autofs4: fix pend...
341
  	int status, ret, type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
342
343
  
  	/* In catatonic mode, we don't wait for nobody */
e77fbddf7   Ian Kent   [PATCH] autofs4: ...
344
  	if (sbi->catatonic)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
345
  		return -ENOENT;
a1362fe92   Ian Kent   autofs4: fix pend...
346

c72305b54   Ian Kent   autofs4: indirect...
347
348
349
350
351
352
353
354
355
  	if (!dentry->d_inode) {
  		/*
  		 * A wait for a negative dentry is invalid for certain
  		 * cases. A direct or offset mount "always" has its mount
  		 * point directory created and so the request dentry must
  		 * be positive or the map key doesn't exist. The situation
  		 * is very similar for indirect mounts except only dentrys
  		 * in the root of the autofs file system may be negative.
  		 */
a92daf6ba   Ian Kent   autofs4: make aut...
356
  		if (autofs_type_trigger(sbi->type))
c72305b54   Ian Kent   autofs4: indirect...
357
358
359
360
  			return -ENOENT;
  		else if (!IS_ROOT(dentry->d_parent))
  			return -ENOENT;
  	}
eb3b17679   Ian Kent   autofs4: detect i...
361

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
363
364
  	name = kmalloc(NAME_MAX + 1, GFP_KERNEL);
  	if (!name)
  		return -ENOMEM;
5c0a32fc2   Ian Kent   [PATCH] autofs4: ...
365
  	/* If this is a direct mount request create a dummy name */
a92daf6ba   Ian Kent   autofs4: make aut...
366
  	if (IS_ROOT(dentry) && autofs_type_trigger(sbi->type))
70b52a0a5   Jeff Moyer   autofs4: use stru...
367
  		qstr.len = sprintf(name, "%p", dentry);
5c0a32fc2   Ian Kent   [PATCH] autofs4: ...
368
  	else {
70b52a0a5   Jeff Moyer   autofs4: use stru...
369
370
  		qstr.len = autofs4_getpath(sbi, dentry, &name);
  		if (!qstr.len) {
5c0a32fc2   Ian Kent   [PATCH] autofs4: ...
371
372
373
  			kfree(name);
  			return -ENOENT;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374
  	}
70b52a0a5   Jeff Moyer   autofs4: use stru...
375
376
  	qstr.name = name;
  	qstr.hash = full_name_hash(name, qstr.len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377

f4c7da026   Ian Kent   autofs4: add miss...
378
379
  	if (mutex_lock_interruptible(&sbi->wq_mutex)) {
  		kfree(qstr.name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
380
  		return -EINTR;
f4c7da026   Ian Kent   autofs4: add miss...
381
  	}
a53705539   Ian Kent   [PATCH] autofs4: ...
382

a1362fe92   Ian Kent   autofs4: fix pend...
383
384
  	ret = validate_request(&wq, sbi, &qstr, dentry, notify);
  	if (ret <= 0) {
4041bcdc7   Al Viro   autofs4: autofs4_...
385
  		if (ret != -EINTR)
1d5599e39   Ingo Molnar   [PATCH] sem2mutex...
386
  			mutex_unlock(&sbi->wq_mutex);
a1362fe92   Ian Kent   autofs4: fix pend...
387
388
  		kfree(qstr.name);
  		return ret;
a53705539   Ian Kent   [PATCH] autofs4: ...
389
  	}
cc9acc885   Ian Kent   [PATCH] autofs4: ...
390

a53705539   Ian Kent   [PATCH] autofs4: ...
391
  	if (!wq) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
392
393
  		/* Create a new wait queue */
  		wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL);
e77fbddf7   Ian Kent   [PATCH] autofs4: ...
394
  		if (!wq) {
70b52a0a5   Jeff Moyer   autofs4: use stru...
395
  			kfree(qstr.name);
1d5599e39   Ingo Molnar   [PATCH] sem2mutex...
396
  			mutex_unlock(&sbi->wq_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
398
399
400
401
402
403
404
405
  			return -ENOMEM;
  		}
  
  		wq->wait_queue_token = autofs4_next_wait_queue;
  		if (++autofs4_next_wait_queue == 0)
  			autofs4_next_wait_queue = 1;
  		wq->next = sbi->queues;
  		sbi->queues = wq;
  		init_waitqueue_head(&wq->queue);
70b52a0a5   Jeff Moyer   autofs4: use stru...
406
  		memcpy(&wq->name, &qstr, sizeof(struct qstr));
5c0a32fc2   Ian Kent   [PATCH] autofs4: ...
407
408
  		wq->dev = autofs4_get_dev(sbi);
  		wq->ino = autofs4_get_ino(sbi);
0eb790e3a   David Howells   CRED: Wrap task c...
409
410
  		wq->uid = current_uid();
  		wq->gid = current_gid();
5c0a32fc2   Ian Kent   [PATCH] autofs4: ...
411
412
  		wq->pid = current->pid;
  		wq->tgid = current->tgid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413
  		wq->status = -EINTR; /* Status return if interrupted */
296f7bf78   Ian Kent   autofs4: fix wait...
414
  		wq->wait_ctr = 2;
1d5599e39   Ingo Molnar   [PATCH] sem2mutex...
415
  		mutex_unlock(&sbi->wq_mutex);
3e7b19198   Ian Kent   [PATCH] autofs4: ...
416

5c0a32fc2   Ian Kent   [PATCH] autofs4: ...
417
418
419
420
421
422
423
  		if (sbi->version < 5) {
  			if (notify == NFY_MOUNT)
  				type = autofs_ptype_missing;
  			else
  				type = autofs_ptype_expire_multi;
  		} else {
  			if (notify == NFY_MOUNT)
a92daf6ba   Ian Kent   autofs4: make aut...
424
  				type = autofs_type_trigger(sbi->type) ?
5c0a32fc2   Ian Kent   [PATCH] autofs4: ...
425
426
427
  					autofs_ptype_missing_direct :
  					 autofs_ptype_missing_indirect;
  			else
a92daf6ba   Ian Kent   autofs4: make aut...
428
  				type = autofs_type_trigger(sbi->type) ?
5c0a32fc2   Ian Kent   [PATCH] autofs4: ...
429
430
431
  					autofs_ptype_expire_direct :
  					autofs_ptype_expire_indirect;
  		}
4dcd00b18   Ian Kent   [PATCH] autofs4: ...
432

682d4fc93   Ian Kent   [PATCH] autofs4: ...
433
434
  		DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d
  ",
70b52a0a5   Jeff Moyer   autofs4: use stru...
435
436
  			(unsigned long) wq->wait_queue_token, wq->name.len,
  			wq->name.name, notify);
4dcd00b18   Ian Kent   [PATCH] autofs4: ...
437
438
439
  
  		/* autofs4_notify_daemon() may block */
  		autofs4_notify_daemon(sbi, wq, type);
a53705539   Ian Kent   [PATCH] autofs4: ...
440
  	} else {
296f7bf78   Ian Kent   autofs4: fix wait...
441
  		wq->wait_ctr++;
a53705539   Ian Kent   [PATCH] autofs4: ...
442
  		mutex_unlock(&sbi->wq_mutex);
70b52a0a5   Jeff Moyer   autofs4: use stru...
443
  		kfree(qstr.name);
a53705539   Ian Kent   [PATCH] autofs4: ...
444
  		DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d",
70b52a0a5   Jeff Moyer   autofs4: use stru...
445
446
  			(unsigned long) wq->wait_queue_token, wq->name.len,
  			wq->name.name, notify);
4dcd00b18   Ian Kent   [PATCH] autofs4: ...
447
  	}
5a11d4d0e   Ian Kent   autofs4: fix wait...
448
449
450
451
  	/*
  	 * wq->name.name is NULL iff the lock is already released
  	 * or the mount has been made catatonic.
  	 */
70b52a0a5   Jeff Moyer   autofs4: use stru...
452
  	if (wq->name.name) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
454
455
456
457
458
459
460
461
  		/* Block all but "shutdown" signals while waiting */
  		sigset_t oldset;
  		unsigned long irqflags;
  
  		spin_lock_irqsave(&current->sighand->siglock, irqflags);
  		oldset = current->blocked;
  		siginitsetinv(&current->blocked, SHUTDOWN_SIGS & ~oldset.sig[0]);
  		recalc_sigpending();
  		spin_unlock_irqrestore(&current->sighand->siglock, irqflags);
70b52a0a5   Jeff Moyer   autofs4: use stru...
462
  		wait_event_interruptible(wq->queue, wq->name.name == NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463
464
465
466
467
468
469
470
471
472
  
  		spin_lock_irqsave(&current->sighand->siglock, irqflags);
  		current->blocked = oldset;
  		recalc_sigpending();
  		spin_unlock_irqrestore(&current->sighand->siglock, irqflags);
  	} else {
  		DPRINTK("skipped sleeping");
  	}
  
  	status = wq->status;
c0f54d3e5   Ian Kent   autofs4: track ui...
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
  	/*
  	 * For direct and offset mounts we need to track the requester's
  	 * uid and gid in the dentry info struct. This is so it can be
  	 * supplied, on request, by the misc device ioctl interface.
  	 * This is needed during daemon resatart when reconnecting
  	 * to existing, active, autofs mounts. The uid and gid (and
  	 * related string values) may be used for macro substitution
  	 * in autofs mount maps.
  	 */
  	if (!status) {
  		struct autofs_info *ino;
  		struct dentry *de = NULL;
  
  		/* direct mount or browsable map */
  		ino = autofs4_dentry_ino(dentry);
  		if (!ino) {
  			/* If not lookup actual dentry used */
  			de = d_lookup(dentry->d_parent, &dentry->d_name);
  			if (de)
  				ino = autofs4_dentry_ino(de);
  		}
  
  		/* Set mount requester */
  		if (ino) {
  			spin_lock(&sbi->fs_lock);
  			ino->uid = wq->uid;
  			ino->gid = wq->gid;
  			spin_unlock(&sbi->fs_lock);
  		}
  
  		if (de)
  			dput(de);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
506
  	/* Are we the last process to need status? */
296f7bf78   Ian Kent   autofs4: fix wait...
507
508
  	mutex_lock(&sbi->wq_mutex);
  	if (!--wq->wait_ctr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
  		kfree(wq);
296f7bf78   Ian Kent   autofs4: fix wait...
510
  	mutex_unlock(&sbi->wq_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
512
513
514
515
516
517
518
  
  	return status;
  }
  
  
  int autofs4_wait_release(struct autofs_sb_info *sbi, autofs_wqt_t wait_queue_token, int status)
  {
  	struct autofs_wait_queue *wq, **wql;
1d5599e39   Ingo Molnar   [PATCH] sem2mutex...
519
  	mutex_lock(&sbi->wq_mutex);
c80544dc0   Stephen Hemminger   sparse pointer us...
520
  	for (wql = &sbi->queues; (wq = *wql) != NULL; wql = &wq->next) {
e77fbddf7   Ian Kent   [PATCH] autofs4: ...
521
  		if (wq->wait_queue_token == wait_queue_token)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522
523
  			break;
  	}
e77fbddf7   Ian Kent   [PATCH] autofs4: ...
524
  	if (!wq) {
1d5599e39   Ingo Molnar   [PATCH] sem2mutex...
525
  		mutex_unlock(&sbi->wq_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
526
527
528
529
  		return -EINVAL;
  	}
  
  	*wql = wq->next;	/* Unlink from chain */
70b52a0a5   Jeff Moyer   autofs4: use stru...
530
531
  	kfree(wq->name.name);
  	wq->name.name = NULL;	/* Do not wait on this queue */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
532
  	wq->status = status;
296f7bf78   Ian Kent   autofs4: fix wait...
533
534
  	wake_up_interruptible(&wq->queue);
  	if (!--wq->wait_ctr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
  		kfree(wq);
296f7bf78   Ian Kent   autofs4: fix wait...
536
  	mutex_unlock(&sbi->wq_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
537
538
539
  
  	return 0;
  }