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 | |
| 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')
| -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 | } |
