diff options
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index eb24653612bc..7ae03283bd61 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -3485,6 +3485,44 @@ cifs_get_volume_info(char *mount_data, const char *devname) | |||
3485 | return volume_info; | 3485 | return volume_info; |
3486 | } | 3486 | } |
3487 | 3487 | ||
3488 | static int | ||
3489 | cifs_are_all_path_components_accessible(struct TCP_Server_Info *server, | ||
3490 | unsigned int xid, | ||
3491 | struct cifs_tcon *tcon, | ||
3492 | struct cifs_sb_info *cifs_sb, | ||
3493 | char *full_path) | ||
3494 | { | ||
3495 | int rc; | ||
3496 | char *s; | ||
3497 | char sep, tmp; | ||
3498 | |||
3499 | sep = CIFS_DIR_SEP(cifs_sb); | ||
3500 | s = full_path; | ||
3501 | |||
3502 | rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, ""); | ||
3503 | while (rc == 0) { | ||
3504 | /* skip separators */ | ||
3505 | while (*s == sep) | ||
3506 | s++; | ||
3507 | if (!*s) | ||
3508 | break; | ||
3509 | /* next separator */ | ||
3510 | while (*s && *s != sep) | ||
3511 | s++; | ||
3512 | |||
3513 | /* | ||
3514 | * temporarily null-terminate the path at the end of | ||
3515 | * the current component | ||
3516 | */ | ||
3517 | tmp = *s; | ||
3518 | *s = 0; | ||
3519 | rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, | ||
3520 | full_path); | ||
3521 | *s = tmp; | ||
3522 | } | ||
3523 | return rc; | ||
3524 | } | ||
3525 | |||
3488 | int | 3526 | int |
3489 | cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info) | 3527 | cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info) |
3490 | { | 3528 | { |
@@ -3622,6 +3660,16 @@ remote_path_check: | |||
3622 | kfree(full_path); | 3660 | kfree(full_path); |
3623 | goto mount_fail_check; | 3661 | goto mount_fail_check; |
3624 | } | 3662 | } |
3663 | |||
3664 | rc = cifs_are_all_path_components_accessible(server, | ||
3665 | xid, tcon, cifs_sb, | ||
3666 | full_path); | ||
3667 | if (rc != 0) { | ||
3668 | cifs_dbg(VFS, "cannot query dirs between root and final path, " | ||
3669 | "enabling CIFS_MOUNT_USE_PREFIX_PATH\n"); | ||
3670 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; | ||
3671 | rc = 0; | ||
3672 | } | ||
3625 | kfree(full_path); | 3673 | kfree(full_path); |
3626 | } | 3674 | } |
3627 | 3675 | ||
@@ -3891,6 +3939,7 @@ cifs_umount(struct cifs_sb_info *cifs_sb) | |||
3891 | 3939 | ||
3892 | bdi_destroy(&cifs_sb->bdi); | 3940 | bdi_destroy(&cifs_sb->bdi); |
3893 | kfree(cifs_sb->mountdata); | 3941 | kfree(cifs_sb->mountdata); |
3942 | kfree(cifs_sb->prepath); | ||
3894 | call_rcu(&cifs_sb->rcu, delayed_free); | 3943 | call_rcu(&cifs_sb->rcu, delayed_free); |
3895 | } | 3944 | } |
3896 | 3945 | ||