aboutsummaryrefslogtreecommitdiffstats
path: root/fs/autofs4/dev-ioctl.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2009-04-07 11:08:56 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2009-06-11 21:35:58 -0400
commit4e44b6852e03c915618ca6776b6697b436246b00 (patch)
tree264db0cf8dde04a604740508dbe5f5b929605467 /fs/autofs4/dev-ioctl.c
parent73422811d290c628b4ddbf6830e5cd6fa42e84f1 (diff)
Get rid of path_lookup in autofs4
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/autofs4/dev-ioctl.c')
-rw-r--r--fs/autofs4/dev-ioctl.c195
1 files changed, 60 insertions, 135 deletions
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c
index 84168c0dcc2d..f71dac9986f0 100644
--- a/fs/autofs4/dev-ioctl.c
+++ b/fs/autofs4/dev-ioctl.c
@@ -192,77 +192,42 @@ static int autofs_dev_ioctl_protosubver(struct file *fp,
192 return 0; 192 return 0;
193} 193}
194 194
195/* 195static int find_autofs_mount(const char *pathname,
196 * Walk down the mount stack looking for an autofs mount that 196 struct path *res,
197 * has the requested device number (aka. new_encode_dev(sb->s_dev). 197 int test(struct path *path, void *data),
198 */ 198 void *data)
199static int autofs_dev_ioctl_find_super(struct nameidata *nd, dev_t devno)
200{ 199{
201 struct dentry *dentry; 200 struct path path;
202 struct inode *inode; 201 int err = kern_path(pathname, 0, &path);
203 struct super_block *sb; 202 if (err)
204 dev_t s_dev; 203 return err;
205 unsigned int err;
206
207 err = -ENOENT; 204 err = -ENOENT;
208 205 while (path.dentry == path.mnt->mnt_root) {
209 /* Lookup the dentry name at the base of our mount point */ 206 if (path.mnt->mnt_sb->s_magic == AUTOFS_SUPER_MAGIC) {
210 dentry = d_lookup(nd->path.dentry, &nd->last); 207 if (test(&path, data)) {
211 if (!dentry) 208 path_get(&path);
212 goto out; 209 if (!err) /* already found some */
213 210 path_put(res);
214 dput(nd->path.dentry); 211 *res = path;
215 nd->path.dentry = dentry;
216
217 /* And follow the mount stack looking for our autofs mount */
218 while (follow_down(&nd->path.mnt, &nd->path.dentry)) {
219 inode = nd->path.dentry->d_inode;
220 if (!inode)
221 break;
222
223 sb = inode->i_sb;
224 s_dev = new_encode_dev(sb->s_dev);
225 if (devno == s_dev) {
226 if (sb->s_magic == AUTOFS_SUPER_MAGIC) {
227 err = 0; 212 err = 0;
228 break;
229 } 213 }
230 } 214 }
215 if (!follow_up(&path.mnt, &path.dentry))
216 break;
231 } 217 }
232out: 218 path_put(&path);
233 return err; 219 return err;
234} 220}
235 221
236/* 222static int test_by_dev(struct path *path, void *p)
237 * Walk down the mount stack looking for an autofs mount that
238 * has the requested mount type (ie. indirect, direct or offset).
239 */
240static int autofs_dev_ioctl_find_sbi_type(struct nameidata *nd, unsigned int type)
241{ 223{
242 struct dentry *dentry; 224 return path->mnt->mnt_sb->s_dev == *(dev_t *)p;
243 struct autofs_info *ino; 225}
244 unsigned int err;
245
246 err = -ENOENT;
247
248 /* Lookup the dentry name at the base of our mount point */
249 dentry = d_lookup(nd->path.dentry, &nd->last);
250 if (!dentry)
251 goto out;
252
253 dput(nd->path.dentry);
254 nd->path.dentry = dentry;
255 226
256 /* And follow the mount stack looking for our autofs mount */ 227static int test_by_type(struct path *path, void *p)
257 while (follow_down(&nd->path.mnt, &nd->path.dentry)) { 228{
258 ino = autofs4_dentry_ino(nd->path.dentry); 229 struct autofs_info *ino = autofs4_dentry_ino(path->dentry);
259 if (ino && ino->sbi->type & type) { 230 return ino && ino->sbi->type & *(unsigned *)p;
260 err = 0;
261 break;
262 }
263 }
264out:
265 return err;
266} 231}
267 232
268static void autofs_dev_ioctl_fd_install(unsigned int fd, struct file *file) 233static void autofs_dev_ioctl_fd_install(unsigned int fd, struct file *file)
@@ -283,31 +248,25 @@ static void autofs_dev_ioctl_fd_install(unsigned int fd, struct file *file)
283 * Open a file descriptor on the autofs mount point corresponding 248 * Open a file descriptor on the autofs mount point corresponding
284 * to the given path and device number (aka. new_encode_dev(sb->s_dev)). 249 * to the given path and device number (aka. new_encode_dev(sb->s_dev)).
285 */ 250 */
286static int autofs_dev_ioctl_open_mountpoint(const char *path, dev_t devid) 251static int autofs_dev_ioctl_open_mountpoint(const char *name, dev_t devid)
287{ 252{
288 struct file *filp;
289 struct nameidata nd;
290 int err, fd; 253 int err, fd;
291 254
292 fd = get_unused_fd(); 255 fd = get_unused_fd();
293 if (likely(fd >= 0)) { 256 if (likely(fd >= 0)) {
294 /* Get nameidata of the parent directory */ 257 struct file *filp;
295 err = path_lookup(path, LOOKUP_PARENT, &nd); 258 struct path path;
259
260 err = find_autofs_mount(name, &path, test_by_dev, &devid);
296 if (err) 261 if (err)
297 goto out; 262 goto out;
298 263
299 /* 264 /*
300 * Search down, within the parent, looking for an 265 * Find autofs super block that has the device number
301 * autofs super block that has the device number
302 * corresponding to the autofs fs we want to open. 266 * corresponding to the autofs fs we want to open.
303 */ 267 */
304 err = autofs_dev_ioctl_find_super(&nd, devid);
305 if (err) {
306 path_put(&nd.path);
307 goto out;
308 }
309 268
310 filp = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY, 269 filp = dentry_open(path.dentry, path.mnt, O_RDONLY,
311 current_cred()); 270 current_cred());
312 if (IS_ERR(filp)) { 271 if (IS_ERR(filp)) {
313 err = PTR_ERR(filp); 272 err = PTR_ERR(filp);
@@ -340,7 +299,7 @@ static int autofs_dev_ioctl_openmount(struct file *fp,
340 param->ioctlfd = -1; 299 param->ioctlfd = -1;
341 300
342 path = param->path; 301 path = param->path;
343 devid = param->openmount.devid; 302 devid = new_decode_dev(param->openmount.devid);
344 303
345 err = 0; 304 err = 0;
346 fd = autofs_dev_ioctl_open_mountpoint(path, devid); 305 fd = autofs_dev_ioctl_open_mountpoint(path, devid);
@@ -475,8 +434,7 @@ static int autofs_dev_ioctl_requester(struct file *fp,
475 struct autofs_dev_ioctl *param) 434 struct autofs_dev_ioctl *param)
476{ 435{
477 struct autofs_info *ino; 436 struct autofs_info *ino;
478 struct nameidata nd; 437 struct path path;
479 const char *path;
480 dev_t devid; 438 dev_t devid;
481 int err = -ENOENT; 439 int err = -ENOENT;
482 440
@@ -485,32 +443,24 @@ static int autofs_dev_ioctl_requester(struct file *fp,
485 goto out; 443 goto out;
486 } 444 }
487 445
488 path = param->path; 446 devid = sbi->sb->s_dev;
489 devid = new_encode_dev(sbi->sb->s_dev);
490 447
491 param->requester.uid = param->requester.gid = -1; 448 param->requester.uid = param->requester.gid = -1;
492 449
493 /* Get nameidata of the parent directory */ 450 err = find_autofs_mount(param->path, &path, test_by_dev, &devid);
494 err = path_lookup(path, LOOKUP_PARENT, &nd);
495 if (err) 451 if (err)
496 goto out; 452 goto out;
497 453
498 err = autofs_dev_ioctl_find_super(&nd, devid); 454 ino = autofs4_dentry_ino(path.dentry);
499 if (err)
500 goto out_release;
501
502 ino = autofs4_dentry_ino(nd.path.dentry);
503 if (ino) { 455 if (ino) {
504 err = 0; 456 err = 0;
505 autofs4_expire_wait(nd.path.dentry); 457 autofs4_expire_wait(path.dentry);
506 spin_lock(&sbi->fs_lock); 458 spin_lock(&sbi->fs_lock);
507 param->requester.uid = ino->uid; 459 param->requester.uid = ino->uid;
508 param->requester.gid = ino->gid; 460 param->requester.gid = ino->gid;
509 spin_unlock(&sbi->fs_lock); 461 spin_unlock(&sbi->fs_lock);
510 } 462 }
511 463 path_put(&path);
512out_release:
513 path_put(&nd.path);
514out: 464out:
515 return err; 465 return err;
516} 466}
@@ -569,8 +519,8 @@ static int autofs_dev_ioctl_ismountpoint(struct file *fp,
569 struct autofs_sb_info *sbi, 519 struct autofs_sb_info *sbi,
570 struct autofs_dev_ioctl *param) 520 struct autofs_dev_ioctl *param)
571{ 521{
572 struct nameidata nd; 522 struct path path;
573 const char *path; 523 const char *name;
574 unsigned int type; 524 unsigned int type;
575 unsigned int devid, magic; 525 unsigned int devid, magic;
576 int err = -ENOENT; 526 int err = -ENOENT;
@@ -580,71 +530,46 @@ static int autofs_dev_ioctl_ismountpoint(struct file *fp,
580 goto out; 530 goto out;
581 } 531 }
582 532
583 path = param->path; 533 name = param->path;
584 type = param->ismountpoint.in.type; 534 type = param->ismountpoint.in.type;
585 535
586 param->ismountpoint.out.devid = devid = 0; 536 param->ismountpoint.out.devid = devid = 0;
587 param->ismountpoint.out.magic = magic = 0; 537 param->ismountpoint.out.magic = magic = 0;
588 538
589 if (!fp || param->ioctlfd == -1) { 539 if (!fp || param->ioctlfd == -1) {
590 if (autofs_type_any(type)) { 540 if (autofs_type_any(type))
591 struct super_block *sb; 541 err = kern_path(name, LOOKUP_FOLLOW, &path);
592 542 else
593 err = path_lookup(path, LOOKUP_FOLLOW, &nd); 543 err = find_autofs_mount(name, &path, test_by_type, &type);
594 if (err) 544 if (err)
595 goto out; 545 goto out;
596 546 devid = new_encode_dev(path.mnt->mnt_sb->s_dev);
597 sb = nd.path.dentry->d_sb;
598 devid = new_encode_dev(sb->s_dev);
599 } else {
600 struct autofs_info *ino;
601
602 err = path_lookup(path, LOOKUP_PARENT, &nd);
603 if (err)
604 goto out;
605
606 err = autofs_dev_ioctl_find_sbi_type(&nd, type);
607 if (err)
608 goto out_release;
609
610 ino = autofs4_dentry_ino(nd.path.dentry);
611 devid = autofs4_get_dev(ino->sbi);
612 }
613
614 err = 0; 547 err = 0;
615 if (nd.path.dentry->d_inode && 548 if (path.dentry->d_inode &&
616 nd.path.mnt->mnt_root == nd.path.dentry) { 549 path.mnt->mnt_root == path.dentry) {
617 err = 1; 550 err = 1;
618 magic = nd.path.dentry->d_inode->i_sb->s_magic; 551 magic = path.dentry->d_inode->i_sb->s_magic;
619 } 552 }
620 } else { 553 } else {
621 dev_t dev = autofs4_get_dev(sbi); 554 dev_t dev = sbi->sb->s_dev;
622 555
623 err = path_lookup(path, LOOKUP_PARENT, &nd); 556 err = find_autofs_mount(name, &path, test_by_dev, &dev);
624 if (err) 557 if (err)
625 goto out; 558 goto out;
626 559
627 err = autofs_dev_ioctl_find_super(&nd, dev); 560 devid = new_encode_dev(dev);
628 if (err)
629 goto out_release;
630
631 devid = dev;
632 561
633 err = have_submounts(nd.path.dentry); 562 err = have_submounts(path.dentry);
634 563
635 if (nd.path.mnt->mnt_mountpoint != nd.path.mnt->mnt_root) { 564 if (path.mnt->mnt_mountpoint != path.mnt->mnt_root) {
636 if (follow_down(&nd.path.mnt, &nd.path.dentry)) { 565 if (follow_down(&path.mnt, &path.dentry))
637 struct inode *inode = nd.path.dentry->d_inode; 566 magic = path.mnt->mnt_sb->s_magic;
638 magic = inode->i_sb->s_magic;
639 }
640 } 567 }
641 } 568 }
642 569
643 param->ismountpoint.out.devid = devid; 570 param->ismountpoint.out.devid = devid;
644 param->ismountpoint.out.magic = magic; 571 param->ismountpoint.out.magic = magic;
645 572 path_put(&path);
646out_release:
647 path_put(&nd.path);
648out: 573out:
649 return err; 574 return err;
650} 575}