diff options
Diffstat (limited to 'fs/autofs4')
-rw-r--r-- | fs/autofs4/autofs_i.h | 6 | ||||
-rw-r--r-- | fs/autofs4/dev-ioctl.c | 195 | ||||
-rw-r--r-- | fs/autofs4/expire.c | 15 | ||||
-rw-r--r-- | fs/autofs4/root.c | 7 |
4 files changed, 73 insertions, 150 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index b7ff33c63101..8f7cdde41733 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h | |||
@@ -223,12 +223,12 @@ int autofs4_wait(struct autofs_sb_info *,struct dentry *, enum autofs_notify); | |||
223 | int autofs4_wait_release(struct autofs_sb_info *,autofs_wqt_t,int); | 223 | int autofs4_wait_release(struct autofs_sb_info *,autofs_wqt_t,int); |
224 | void autofs4_catatonic_mode(struct autofs_sb_info *); | 224 | void autofs4_catatonic_mode(struct autofs_sb_info *); |
225 | 225 | ||
226 | static inline int autofs4_follow_mount(struct vfsmount **mnt, struct dentry **dentry) | 226 | static inline int autofs4_follow_mount(struct path *path) |
227 | { | 227 | { |
228 | int res = 0; | 228 | int res = 0; |
229 | 229 | ||
230 | while (d_mountpoint(*dentry)) { | 230 | while (d_mountpoint(path->dentry)) { |
231 | int followed = follow_down(mnt, dentry); | 231 | int followed = follow_down(path); |
232 | if (!followed) | 232 | if (!followed) |
233 | break; | 233 | break; |
234 | res = 1; | 234 | res = 1; |
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c index 84168c0dcc2d..f3da2eb51f56 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)) | ||
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)) |
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 | } |
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index 3077d8f16523..aa39ae83f019 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c | |||
@@ -48,19 +48,19 @@ static inline int autofs4_can_expire(struct dentry *dentry, | |||
48 | static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry) | 48 | static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry) |
49 | { | 49 | { |
50 | struct dentry *top = dentry; | 50 | struct dentry *top = dentry; |
51 | struct path path = {.mnt = mnt, .dentry = dentry}; | ||
51 | int status = 1; | 52 | int status = 1; |
52 | 53 | ||
53 | DPRINTK("dentry %p %.*s", | 54 | DPRINTK("dentry %p %.*s", |
54 | dentry, (int)dentry->d_name.len, dentry->d_name.name); | 55 | dentry, (int)dentry->d_name.len, dentry->d_name.name); |
55 | 56 | ||
56 | mntget(mnt); | 57 | path_get(&path); |
57 | dget(dentry); | ||
58 | 58 | ||
59 | if (!follow_down(&mnt, &dentry)) | 59 | if (!follow_down(&path)) |
60 | goto done; | 60 | goto done; |
61 | 61 | ||
62 | if (is_autofs4_dentry(dentry)) { | 62 | if (is_autofs4_dentry(path.dentry)) { |
63 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | 63 | struct autofs_sb_info *sbi = autofs4_sbi(path.dentry->d_sb); |
64 | 64 | ||
65 | /* This is an autofs submount, we can't expire it */ | 65 | /* This is an autofs submount, we can't expire it */ |
66 | if (autofs_type_indirect(sbi->type)) | 66 | if (autofs_type_indirect(sbi->type)) |
@@ -70,7 +70,7 @@ static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry) | |||
70 | * Otherwise it's an offset mount and we need to check | 70 | * Otherwise it's an offset mount and we need to check |
71 | * if we can umount its mount, if there is one. | 71 | * if we can umount its mount, if there is one. |
72 | */ | 72 | */ |
73 | if (!d_mountpoint(dentry)) { | 73 | if (!d_mountpoint(path.dentry)) { |
74 | status = 0; | 74 | status = 0; |
75 | goto done; | 75 | goto done; |
76 | } | 76 | } |
@@ -86,8 +86,7 @@ static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry) | |||
86 | status = 0; | 86 | status = 0; |
87 | done: | 87 | done: |
88 | DPRINTK("returning = %d", status); | 88 | DPRINTK("returning = %d", status); |
89 | dput(dentry); | 89 | path_put(&path); |
90 | mntput(mnt); | ||
91 | return status; | 90 | return status; |
92 | } | 91 | } |
93 | 92 | ||
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index e383bf0334f1..b96a3c57359d 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -181,7 +181,7 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
181 | nd->flags); | 181 | nd->flags); |
182 | /* | 182 | /* |
183 | * For an expire of a covered direct or offset mount we need | 183 | * For an expire of a covered direct or offset mount we need |
184 | * to beeak out of follow_down() at the autofs mount trigger | 184 | * to break out of follow_down() at the autofs mount trigger |
185 | * (d_mounted--), so we can see the expiring flag, and manage | 185 | * (d_mounted--), so we can see the expiring flag, and manage |
186 | * the blocking and following here until the expire is completed. | 186 | * the blocking and following here until the expire is completed. |
187 | */ | 187 | */ |
@@ -190,7 +190,7 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
190 | if (ino->flags & AUTOFS_INF_EXPIRING) { | 190 | if (ino->flags & AUTOFS_INF_EXPIRING) { |
191 | spin_unlock(&sbi->fs_lock); | 191 | spin_unlock(&sbi->fs_lock); |
192 | /* Follow down to our covering mount. */ | 192 | /* Follow down to our covering mount. */ |
193 | if (!follow_down(&nd->path.mnt, &nd->path.dentry)) | 193 | if (!follow_down(&nd->path)) |
194 | goto done; | 194 | goto done; |
195 | goto follow; | 195 | goto follow; |
196 | } | 196 | } |
@@ -230,8 +230,7 @@ follow: | |||
230 | * to follow it. | 230 | * to follow it. |
231 | */ | 231 | */ |
232 | if (d_mountpoint(dentry)) { | 232 | if (d_mountpoint(dentry)) { |
233 | if (!autofs4_follow_mount(&nd->path.mnt, | 233 | if (!autofs4_follow_mount(&nd->path)) { |
234 | &nd->path.dentry)) { | ||
235 | status = -ENOENT; | 234 | status = -ENOENT; |
236 | goto out_error; | 235 | goto out_error; |
237 | } | 236 | } |