diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2009-04-07 11:08:56 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2009-06-11 21:35:58 -0400 |
commit | 4e44b6852e03c915618ca6776b6697b436246b00 (patch) | |
tree | 264db0cf8dde04a604740508dbe5f5b929605467 /fs/autofs4/dev-ioctl.c | |
parent | 73422811d290c628b4ddbf6830e5cd6fa42e84f1 (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.c | 195 |
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 | /* | 195 | static 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) |
199 | static 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 | } |
232 | out: | 218 | path_put(&path); |
233 | return err; | 219 | return err; |
234 | } | 220 | } |
235 | 221 | ||
236 | /* | 222 | static 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 | */ | ||
240 | static 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 */ | 227 | static 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 | } | ||
264 | out: | ||
265 | return err; | ||
266 | } | 231 | } |
267 | 232 | ||
268 | static void autofs_dev_ioctl_fd_install(unsigned int fd, struct file *file) | 233 | static 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 | */ |
286 | static int autofs_dev_ioctl_open_mountpoint(const char *path, dev_t devid) | 251 | static 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); | |
512 | out_release: | ||
513 | path_put(&nd.path); | ||
514 | out: | 464 | out: |
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); | |
646 | out_release: | ||
647 | path_put(&nd.path); | ||
648 | out: | 573 | out: |
649 | return err; | 574 | return err; |
650 | } | 575 | } |