diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2011-06-17 09:05:48 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-06-24 18:39:41 -0400 |
commit | 2c6292ae4be00454882246d07f38cdf15a823c2a (patch) | |
tree | 40bfa681a0f94f6df2b3f8140452f0eab7809b1c /fs | |
parent | ca171baaad1420a29cca98be5bdf5596cd70b294 (diff) |
cifs: don't pass superblock to cifs_mount()
To close sget() races we'll need to be able to set cifs_sb up before
we get the superblock, so we'll want to be able to do cifs_mount()
earlier. Fortunately, it's easy to do - setting ->s_maxbytes can
be done in cifs_read_super(), ditto for ->s_time_gran and as for
putting MS_POSIXACL into ->s_flags, we can mirror it in ->mnt_cifs_flags
until cifs_read_super() is called. Kill unused 'devname' argument,
while we are at it...
Acked-by: Pavel Shilovsky <piastryyy@gmail.com>
Reviewed-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/cifs_fs_sb.h | 1 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 13 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 6 | ||||
-rw-r--r-- | fs/cifs/connect.c | 28 |
4 files changed, 26 insertions, 22 deletions
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index ffb1459dc6ec..7260e11e21f8 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h | |||
@@ -42,6 +42,7 @@ | |||
42 | #define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */ | 42 | #define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */ |
43 | #define CIFS_MOUNT_STRICT_IO 0x40000 /* strict cache mode */ | 43 | #define CIFS_MOUNT_STRICT_IO 0x40000 /* strict cache mode */ |
44 | #define CIFS_MOUNT_RWPIDFORWARD 0x80000 /* use pid forwarding for rw */ | 44 | #define CIFS_MOUNT_RWPIDFORWARD 0x80000 /* use pid forwarding for rw */ |
45 | #define CIFS_MOUNT_POSIXACL 0x100000 /* mirror of MS_POSIXACL in mnt_cifs_flags */ | ||
45 | 46 | ||
46 | struct cifs_sb_info { | 47 | struct cifs_sb_info { |
47 | struct rb_root tlink_tree; | 48 | struct rb_root tlink_tree; |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index bfab2bc83726..8f7451f3c8e6 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -116,7 +116,7 @@ cifs_read_super(struct super_block *sb, struct smb_vol *volume_info, | |||
116 | spin_lock_init(&cifs_sb->tlink_tree_lock); | 116 | spin_lock_init(&cifs_sb->tlink_tree_lock); |
117 | cifs_sb->tlink_tree = RB_ROOT; | 117 | cifs_sb->tlink_tree = RB_ROOT; |
118 | 118 | ||
119 | rc = cifs_mount(sb, cifs_sb, volume_info, devname); | 119 | rc = cifs_mount(cifs_sb, volume_info); |
120 | 120 | ||
121 | if (rc) { | 121 | if (rc) { |
122 | if (!silent) | 122 | if (!silent) |
@@ -124,6 +124,17 @@ cifs_read_super(struct super_block *sb, struct smb_vol *volume_info, | |||
124 | return rc; | 124 | return rc; |
125 | } | 125 | } |
126 | 126 | ||
127 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL) | ||
128 | sb->s_flags |= MS_POSIXACL; | ||
129 | |||
130 | if (cifs_sb_master_tcon(cifs_sb)->ses->capabilities & CAP_LARGE_FILES) | ||
131 | sb->s_maxbytes = MAX_LFS_FILESIZE; | ||
132 | else | ||
133 | sb->s_maxbytes = MAX_NON_LFS; | ||
134 | |||
135 | /* BB FIXME fix time_gran to be larger for LANMAN sessions */ | ||
136 | sb->s_time_gran = 100; | ||
137 | |||
127 | sb->s_magic = CIFS_MAGIC_NUMBER; | 138 | sb->s_magic = CIFS_MAGIC_NUMBER; |
128 | sb->s_op = &cifs_super_ops; | 139 | sb->s_op = &cifs_super_ops; |
129 | sb->s_bdi = &cifs_sb->bdi; | 140 | sb->s_bdi = &cifs_sb->bdi; |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 953f84413c77..5814fe543f95 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -157,8 +157,7 @@ extern int cifs_match_super(struct super_block *, void *); | |||
157 | extern void cifs_cleanup_volume_info(struct smb_vol **pvolume_info); | 157 | extern void cifs_cleanup_volume_info(struct smb_vol **pvolume_info); |
158 | extern int cifs_setup_volume_info(struct smb_vol **pvolume_info, | 158 | extern int cifs_setup_volume_info(struct smb_vol **pvolume_info, |
159 | char *mount_data, const char *devname); | 159 | char *mount_data, const char *devname); |
160 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, | 160 | extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *); |
161 | struct smb_vol *, const char *); | ||
162 | extern int cifs_umount(struct super_block *, struct cifs_sb_info *); | 161 | extern int cifs_umount(struct super_block *, struct cifs_sb_info *); |
163 | extern void cifs_dfs_release_automount_timer(void); | 162 | extern void cifs_dfs_release_automount_timer(void); |
164 | void cifs_proc_init(void); | 163 | void cifs_proc_init(void); |
@@ -218,7 +217,8 @@ extern int get_dfs_path(int xid, struct cifs_ses *pSesInfo, | |||
218 | struct dfs_info3_param **preferrals, | 217 | struct dfs_info3_param **preferrals, |
219 | int remap); | 218 | int remap); |
220 | extern void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon, | 219 | extern void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon, |
221 | struct super_block *sb, struct smb_vol *vol); | 220 | struct cifs_sb_info *cifs_sb, |
221 | struct smb_vol *vol); | ||
222 | extern int CIFSSMBQFSInfo(const int xid, struct cifs_tcon *tcon, | 222 | extern int CIFSSMBQFSInfo(const int xid, struct cifs_tcon *tcon, |
223 | struct kstatfs *FSData); | 223 | struct kstatfs *FSData); |
224 | extern int SMBOldQFSInfo(const int xid, struct cifs_tcon *tcon, | 224 | extern int SMBOldQFSInfo(const int xid, struct cifs_tcon *tcon, |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 78fd7557e35d..3011ac8c9249 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -2546,7 +2546,7 @@ ip_connect(struct TCP_Server_Info *server) | |||
2546 | } | 2546 | } |
2547 | 2547 | ||
2548 | void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon, | 2548 | void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon, |
2549 | struct super_block *sb, struct smb_vol *vol_info) | 2549 | struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info) |
2550 | { | 2550 | { |
2551 | /* if we are reconnecting then should we check to see if | 2551 | /* if we are reconnecting then should we check to see if |
2552 | * any requested capabilities changed locally e.g. via | 2552 | * any requested capabilities changed locally e.g. via |
@@ -2600,22 +2600,23 @@ void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon, | |||
2600 | cap &= ~CIFS_UNIX_POSIX_ACL_CAP; | 2600 | cap &= ~CIFS_UNIX_POSIX_ACL_CAP; |
2601 | else if (CIFS_UNIX_POSIX_ACL_CAP & cap) { | 2601 | else if (CIFS_UNIX_POSIX_ACL_CAP & cap) { |
2602 | cFYI(1, "negotiated posix acl support"); | 2602 | cFYI(1, "negotiated posix acl support"); |
2603 | if (sb) | 2603 | if (cifs_sb) |
2604 | sb->s_flags |= MS_POSIXACL; | 2604 | cifs_sb->mnt_cifs_flags |= |
2605 | CIFS_MOUNT_POSIXACL; | ||
2605 | } | 2606 | } |
2606 | 2607 | ||
2607 | if (vol_info && vol_info->posix_paths == 0) | 2608 | if (vol_info && vol_info->posix_paths == 0) |
2608 | cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP; | 2609 | cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP; |
2609 | else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) { | 2610 | else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) { |
2610 | cFYI(1, "negotiate posix pathnames"); | 2611 | cFYI(1, "negotiate posix pathnames"); |
2611 | if (sb) | 2612 | if (cifs_sb) |
2612 | CIFS_SB(sb)->mnt_cifs_flags |= | 2613 | cifs_sb->mnt_cifs_flags |= |
2613 | CIFS_MOUNT_POSIX_PATHS; | 2614 | CIFS_MOUNT_POSIX_PATHS; |
2614 | } | 2615 | } |
2615 | 2616 | ||
2616 | if (sb && (CIFS_SB(sb)->rsize > 127 * 1024)) { | 2617 | if (cifs_sb && (cifs_sb->rsize > 127 * 1024)) { |
2617 | if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) { | 2618 | if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) { |
2618 | CIFS_SB(sb)->rsize = 127 * 1024; | 2619 | cifs_sb->rsize = 127 * 1024; |
2619 | cFYI(DBG2, "larger reads not supported by srv"); | 2620 | cFYI(DBG2, "larger reads not supported by srv"); |
2620 | } | 2621 | } |
2621 | } | 2622 | } |
@@ -2971,8 +2972,7 @@ out: | |||
2971 | } | 2972 | } |
2972 | 2973 | ||
2973 | int | 2974 | int |
2974 | cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | 2975 | cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info) |
2975 | struct smb_vol *volume_info, const char *devname) | ||
2976 | { | 2976 | { |
2977 | int rc = 0; | 2977 | int rc = 0; |
2978 | int xid; | 2978 | int xid; |
@@ -3026,14 +3026,6 @@ try_mount_again: | |||
3026 | goto mount_fail_check; | 3026 | goto mount_fail_check; |
3027 | } | 3027 | } |
3028 | 3028 | ||
3029 | if (pSesInfo->capabilities & CAP_LARGE_FILES) | ||
3030 | sb->s_maxbytes = MAX_LFS_FILESIZE; | ||
3031 | else | ||
3032 | sb->s_maxbytes = MAX_NON_LFS; | ||
3033 | |||
3034 | /* BB FIXME fix time_gran to be larger for LANMAN sessions */ | ||
3035 | sb->s_time_gran = 100; | ||
3036 | |||
3037 | /* search for existing tcon to this server share */ | 3029 | /* search for existing tcon to this server share */ |
3038 | tcon = cifs_get_tcon(pSesInfo, volume_info); | 3030 | tcon = cifs_get_tcon(pSesInfo, volume_info); |
3039 | if (IS_ERR(tcon)) { | 3031 | if (IS_ERR(tcon)) { |
@@ -3046,7 +3038,7 @@ try_mount_again: | |||
3046 | if (tcon->ses->capabilities & CAP_UNIX) { | 3038 | if (tcon->ses->capabilities & CAP_UNIX) { |
3047 | /* reset of caps checks mount to see if unix extensions | 3039 | /* reset of caps checks mount to see if unix extensions |
3048 | disabled for just this mount */ | 3040 | disabled for just this mount */ |
3049 | reset_cifs_unix_caps(xid, tcon, sb, volume_info); | 3041 | reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info); |
3050 | if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) && | 3042 | if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) && |
3051 | (le64_to_cpu(tcon->fsUnixInfo.Capability) & | 3043 | (le64_to_cpu(tcon->fsUnixInfo.Capability) & |
3052 | CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) { | 3044 | CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) { |