diff options
Diffstat (limited to 'fs/autofs4/waitq.c')
-rw-r--r-- | fs/autofs4/waitq.c | 86 |
1 files changed, 74 insertions, 12 deletions
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index b0bb9d43bcd9..12da2c977b0a 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * linux/fs/autofs/waitq.c | 3 | * linux/fs/autofs/waitq.c |
4 | * | 4 | * |
5 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved | 5 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved |
6 | * Copyright 2001-2003 Ian Kent <raven@themaw.net> | 6 | * Copyright 2001-2006 Ian Kent <raven@themaw.net> |
7 | * | 7 | * |
8 | * This file is part of the Linux kernel and is made available under | 8 | * This file is part of the Linux kernel and is made available under |
9 | * the terms of the GNU General Public License, version 2, or at your | 9 | * the terms of the GNU General Public License, version 2, or at your |
@@ -97,7 +97,10 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, | |||
97 | 97 | ||
98 | pkt.hdr.proto_version = sbi->version; | 98 | pkt.hdr.proto_version = sbi->version; |
99 | pkt.hdr.type = type; | 99 | pkt.hdr.type = type; |
100 | if (type == autofs_ptype_missing) { | 100 | switch (type) { |
101 | /* Kernel protocol v4 missing and expire packets */ | ||
102 | case autofs_ptype_missing: | ||
103 | { | ||
101 | struct autofs_packet_missing *mp = &pkt.missing; | 104 | struct autofs_packet_missing *mp = &pkt.missing; |
102 | 105 | ||
103 | pktsz = sizeof(*mp); | 106 | pktsz = sizeof(*mp); |
@@ -106,7 +109,10 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, | |||
106 | mp->len = wq->len; | 109 | mp->len = wq->len; |
107 | memcpy(mp->name, wq->name, wq->len); | 110 | memcpy(mp->name, wq->name, wq->len); |
108 | mp->name[wq->len] = '\0'; | 111 | mp->name[wq->len] = '\0'; |
109 | } else if (type == autofs_ptype_expire_multi) { | 112 | break; |
113 | } | ||
114 | case autofs_ptype_expire_multi: | ||
115 | { | ||
110 | struct autofs_packet_expire_multi *ep = &pkt.expire_multi; | 116 | struct autofs_packet_expire_multi *ep = &pkt.expire_multi; |
111 | 117 | ||
112 | pktsz = sizeof(*ep); | 118 | pktsz = sizeof(*ep); |
@@ -115,7 +121,34 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, | |||
115 | ep->len = wq->len; | 121 | ep->len = wq->len; |
116 | memcpy(ep->name, wq->name, wq->len); | 122 | memcpy(ep->name, wq->name, wq->len); |
117 | ep->name[wq->len] = '\0'; | 123 | ep->name[wq->len] = '\0'; |
118 | } else { | 124 | break; |
125 | } | ||
126 | /* | ||
127 | * Kernel protocol v5 packet for handling indirect and direct | ||
128 | * mount missing and expire requests | ||
129 | */ | ||
130 | case autofs_ptype_missing_indirect: | ||
131 | case autofs_ptype_expire_indirect: | ||
132 | case autofs_ptype_missing_direct: | ||
133 | case autofs_ptype_expire_direct: | ||
134 | { | ||
135 | struct autofs_v5_packet *packet = &pkt.v5_packet; | ||
136 | |||
137 | pktsz = sizeof(*packet); | ||
138 | |||
139 | packet->wait_queue_token = wq->wait_queue_token; | ||
140 | packet->len = wq->len; | ||
141 | memcpy(packet->name, wq->name, wq->len); | ||
142 | packet->name[wq->len] = '\0'; | ||
143 | packet->dev = wq->dev; | ||
144 | packet->ino = wq->ino; | ||
145 | packet->uid = wq->uid; | ||
146 | packet->gid = wq->gid; | ||
147 | packet->pid = wq->pid; | ||
148 | packet->tgid = wq->tgid; | ||
149 | break; | ||
150 | } | ||
151 | default: | ||
119 | printk("autofs4_notify_daemon: bad type %d!\n", type); | 152 | printk("autofs4_notify_daemon: bad type %d!\n", type); |
120 | return; | 153 | return; |
121 | } | 154 | } |
@@ -161,7 +194,9 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
161 | { | 194 | { |
162 | struct autofs_wait_queue *wq; | 195 | struct autofs_wait_queue *wq; |
163 | char *name; | 196 | char *name; |
164 | int len, status; | 197 | unsigned int len = 0; |
198 | unsigned int hash = 0; | ||
199 | int status; | ||
165 | 200 | ||
166 | /* In catatonic mode, we don't wait for nobody */ | 201 | /* In catatonic mode, we don't wait for nobody */ |
167 | if (sbi->catatonic) | 202 | if (sbi->catatonic) |
@@ -171,11 +206,17 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
171 | if (!name) | 206 | if (!name) |
172 | return -ENOMEM; | 207 | return -ENOMEM; |
173 | 208 | ||
174 | len = autofs4_getpath(sbi, dentry, &name); | 209 | /* If this is a direct mount request create a dummy name */ |
175 | if (!len) { | 210 | if (IS_ROOT(dentry) && (sbi->type & AUTOFS_TYP_DIRECT)) |
176 | kfree(name); | 211 | len = sprintf(name, "%p", dentry); |
177 | return -ENOENT; | 212 | else { |
213 | len = autofs4_getpath(sbi, dentry, &name); | ||
214 | if (!len) { | ||
215 | kfree(name); | ||
216 | return -ENOENT; | ||
217 | } | ||
178 | } | 218 | } |
219 | hash = full_name_hash(name, len); | ||
179 | 220 | ||
180 | if (mutex_lock_interruptible(&sbi->wq_mutex)) { | 221 | if (mutex_lock_interruptible(&sbi->wq_mutex)) { |
181 | kfree(name); | 222 | kfree(name); |
@@ -211,9 +252,15 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
211 | wq->next = sbi->queues; | 252 | wq->next = sbi->queues; |
212 | sbi->queues = wq; | 253 | sbi->queues = wq; |
213 | init_waitqueue_head(&wq->queue); | 254 | init_waitqueue_head(&wq->queue); |
214 | wq->hash = dentry->d_name.hash; | 255 | wq->hash = hash; |
215 | wq->name = name; | 256 | wq->name = name; |
216 | wq->len = len; | 257 | wq->len = len; |
258 | wq->dev = autofs4_get_dev(sbi); | ||
259 | wq->ino = autofs4_get_ino(sbi); | ||
260 | wq->uid = current->uid; | ||
261 | wq->gid = current->gid; | ||
262 | wq->pid = current->pid; | ||
263 | wq->tgid = current->tgid; | ||
217 | wq->status = -EINTR; /* Status return if interrupted */ | 264 | wq->status = -EINTR; /* Status return if interrupted */ |
218 | atomic_set(&wq->wait_ctr, 2); | 265 | atomic_set(&wq->wait_ctr, 2); |
219 | atomic_set(&wq->notified, 1); | 266 | atomic_set(&wq->notified, 1); |
@@ -227,8 +274,23 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
227 | } | 274 | } |
228 | 275 | ||
229 | if (notify != NFY_NONE && atomic_dec_and_test(&wq->notified)) { | 276 | if (notify != NFY_NONE && atomic_dec_and_test(&wq->notified)) { |
230 | int type = (notify == NFY_MOUNT ? | 277 | int type; |
231 | autofs_ptype_missing : autofs_ptype_expire_multi); | 278 | |
279 | if (sbi->version < 5) { | ||
280 | if (notify == NFY_MOUNT) | ||
281 | type = autofs_ptype_missing; | ||
282 | else | ||
283 | type = autofs_ptype_expire_multi; | ||
284 | } else { | ||
285 | if (notify == NFY_MOUNT) | ||
286 | type = (sbi->type & AUTOFS_TYP_DIRECT) ? | ||
287 | autofs_ptype_missing_direct : | ||
288 | autofs_ptype_missing_indirect; | ||
289 | else | ||
290 | type = (sbi->type & AUTOFS_TYP_DIRECT) ? | ||
291 | autofs_ptype_expire_direct : | ||
292 | autofs_ptype_expire_indirect; | ||
293 | } | ||
232 | 294 | ||
233 | DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d\n", | 295 | DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d\n", |
234 | (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify); | 296 | (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify); |