aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/CHANGES7
-rw-r--r--fs/cifs/README25
-rw-r--r--fs/cifs/cifs_debug.c8
-rw-r--r--fs/cifs/cifs_dfs_ref.c12
-rw-r--r--fs/cifs/cifs_unicode.c2
-rw-r--r--fs/cifs/cifsfs.c4
-rw-r--r--fs/cifs/cifsglob.h2
-rw-r--r--fs/cifs/cifssmb.c5
-rw-r--r--fs/cifs/connect.c64
-rw-r--r--fs/cifs/inode.c9
10 files changed, 97 insertions, 41 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 92888aa90749..e85b1e4389e0 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,10 @@
1Version 1.60
2-------------
3Fix memory leak in reconnect. Fix oops in DFS mount error path.
4Set s_maxbytes to smaller (the max that vfs can handle) so that
5sendfile will now work over cifs mounts again. Add noforcegid
6and noforceuid mount parameters.
7
1Version 1.59 8Version 1.59
2------------ 9------------
3Client uses server inode numbers (which are persistent) rather than 10Client uses server inode numbers (which are persistent) rather than
diff --git a/fs/cifs/README b/fs/cifs/README
index ad92921dbde4..79c1a93400be 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -262,11 +262,11 @@ A partial list of the supported mount options follows:
262 mount. 262 mount.
263 domain Set the SMB/CIFS workgroup name prepended to the 263 domain Set the SMB/CIFS workgroup name prepended to the
264 username during CIFS session establishment 264 username during CIFS session establishment
265 forceuid Set the default uid for inodes based on the uid 265 forceuid Set the default uid for inodes to the uid
266 passed in. For mounts to servers 266 passed in on mount. For mounts to servers
267 which do support the CIFS Unix extensions, such as a 267 which do support the CIFS Unix extensions, such as a
268 properly configured Samba server, the server provides 268 properly configured Samba server, the server provides
269 the uid, gid and mode so this parameter should not be 269 the uid, gid and mode so this parameter should not be
270 specified unless the server and clients uid and gid 270 specified unless the server and clients uid and gid
271 numbering differ. If the server and client are in the 271 numbering differ. If the server and client are in the
272 same domain (e.g. running winbind or nss_ldap) and 272 same domain (e.g. running winbind or nss_ldap) and
@@ -278,11 +278,7 @@ A partial list of the supported mount options follows:
278 of existing files will be the uid (gid) of the person 278 of existing files will be the uid (gid) of the person
279 who executed the mount (root, except when mount.cifs 279 who executed the mount (root, except when mount.cifs
280 is configured setuid for user mounts) unless the "uid=" 280 is configured setuid for user mounts) unless the "uid="
281 (gid) mount option is specified. For the uid (gid) of newly 281 (gid) mount option is specified. Also note that permission
282 created files and directories, ie files created since
283 the last mount of the server share, the expected uid
284 (gid) is cached as long as the inode remains in
285 memory on the client. Also note that permission
286 checks (authorization checks) on accesses to a file occur 282 checks (authorization checks) on accesses to a file occur
287 at the server, but there are cases in which an administrator 283 at the server, but there are cases in which an administrator
288 may want to restrict at the client as well. For those 284 may want to restrict at the client as well. For those
@@ -290,12 +286,15 @@ A partial list of the supported mount options follows:
290 (such as Windows), permissions can also be checked at the 286 (such as Windows), permissions can also be checked at the
291 client, and a crude form of client side permission checking 287 client, and a crude form of client side permission checking
292 can be enabled by specifying file_mode and dir_mode on 288 can be enabled by specifying file_mode and dir_mode on
293 the client. Note that the mount.cifs helper must be 289 the client. (default)
294 at version 1.10 or higher to support specifying the uid 290 forcegid (similar to above but for the groupid instead of uid) (default)
295 (or gid) in non-numeric form. 291 noforceuid Fill in file owner information (uid) by requesting it from
296 forcegid (similar to above but for the groupid instead of uid) 292 the server if possible. With this option, the value given in
293 the uid= option (on mount) will only be used if the server
294 can not support returning uids on inodes.
295 noforcegid (similar to above but for the group owner, gid, instead of uid)
297 uid Set the default uid for inodes, and indicate to the 296 uid Set the default uid for inodes, and indicate to the
298 cifs kernel driver which local user mounted . If the server 297 cifs kernel driver which local user mounted. If the server
299 supports the unix extensions the default uid is 298 supports the unix extensions the default uid is
300 not used to fill in the owner fields of inodes (files) 299 not used to fill in the owner fields of inodes (files)
301 unless the "forceuid" parameter is specified. 300 unless the "forceuid" parameter is specified.
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 7f19fefd3d45..42cec2a7c0cf 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -261,6 +261,8 @@ static ssize_t cifs_stats_proc_write(struct file *file,
261 atomic_set(&tcon->num_reads, 0); 261 atomic_set(&tcon->num_reads, 0);
262 atomic_set(&tcon->num_oplock_brks, 0); 262 atomic_set(&tcon->num_oplock_brks, 0);
263 atomic_set(&tcon->num_opens, 0); 263 atomic_set(&tcon->num_opens, 0);
264 atomic_set(&tcon->num_posixopens, 0);
265 atomic_set(&tcon->num_posixmkdirs, 0);
264 atomic_set(&tcon->num_closes, 0); 266 atomic_set(&tcon->num_closes, 0);
265 atomic_set(&tcon->num_deletes, 0); 267 atomic_set(&tcon->num_deletes, 0);
266 atomic_set(&tcon->num_mkdirs, 0); 268 atomic_set(&tcon->num_mkdirs, 0);
@@ -347,11 +349,15 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v)
347 atomic_read(&tcon->num_locks), 349 atomic_read(&tcon->num_locks),
348 atomic_read(&tcon->num_hardlinks), 350 atomic_read(&tcon->num_hardlinks),
349 atomic_read(&tcon->num_symlinks)); 351 atomic_read(&tcon->num_symlinks));
350 seq_printf(m, "\nOpens: %d Closes: %d" 352 seq_printf(m, "\nOpens: %d Closes: %d "
351 "Deletes: %d", 353 "Deletes: %d",
352 atomic_read(&tcon->num_opens), 354 atomic_read(&tcon->num_opens),
353 atomic_read(&tcon->num_closes), 355 atomic_read(&tcon->num_closes),
354 atomic_read(&tcon->num_deletes)); 356 atomic_read(&tcon->num_deletes));
357 seq_printf(m, "\nPosix Opens: %d "
358 "Posix Mkdirs: %d",
359 atomic_read(&tcon->num_posixopens),
360 atomic_read(&tcon->num_posixmkdirs));
355 seq_printf(m, "\nMkdirs: %d Rmdirs: %d", 361 seq_printf(m, "\nMkdirs: %d Rmdirs: %d",
356 atomic_read(&tcon->num_mkdirs), 362 atomic_read(&tcon->num_mkdirs),
357 atomic_read(&tcon->num_rmdirs)); 363 atomic_read(&tcon->num_rmdirs));
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index 3bb11be8b6a8..606912d8f2a8 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -55,7 +55,7 @@ void cifs_dfs_release_automount_timer(void)
55 * i.e. strips from UNC trailing path that is not part of share 55 * i.e. strips from UNC trailing path that is not part of share
56 * name and fixup missing '\' in the begining of DFS node refferal 56 * name and fixup missing '\' in the begining of DFS node refferal
57 * if neccessary. 57 * if neccessary.
58 * Returns pointer to share name on success or NULL on error. 58 * Returns pointer to share name on success or ERR_PTR on error.
59 * Caller is responsible for freeing returned string. 59 * Caller is responsible for freeing returned string.
60 */ 60 */
61static char *cifs_get_share_name(const char *node_name) 61static char *cifs_get_share_name(const char *node_name)
@@ -68,7 +68,7 @@ static char *cifs_get_share_name(const char *node_name)
68 UNC = kmalloc(len+2 /*for term null and additional \ if it's missed */, 68 UNC = kmalloc(len+2 /*for term null and additional \ if it's missed */,
69 GFP_KERNEL); 69 GFP_KERNEL);
70 if (!UNC) 70 if (!UNC)
71 return NULL; 71 return ERR_PTR(-ENOMEM);
72 72
73 /* get share name and server name */ 73 /* get share name and server name */
74 if (node_name[1] != '\\') { 74 if (node_name[1] != '\\') {
@@ -87,7 +87,7 @@ static char *cifs_get_share_name(const char *node_name)
87 cERROR(1, ("%s: no server name end in node name: %s", 87 cERROR(1, ("%s: no server name end in node name: %s",
88 __func__, node_name)); 88 __func__, node_name));
89 kfree(UNC); 89 kfree(UNC);
90 return NULL; 90 return ERR_PTR(-EINVAL);
91 } 91 }
92 92
93 /* find sharename end */ 93 /* find sharename end */
@@ -133,6 +133,12 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
133 return ERR_PTR(-EINVAL); 133 return ERR_PTR(-EINVAL);
134 134
135 *devname = cifs_get_share_name(ref->node_name); 135 *devname = cifs_get_share_name(ref->node_name);
136 if (IS_ERR(*devname)) {
137 rc = PTR_ERR(*devname);
138 *devname = NULL;
139 goto compose_mount_options_err;
140 }
141
136 rc = dns_resolve_server_name_to_ip(*devname, &srvIP); 142 rc = dns_resolve_server_name_to_ip(*devname, &srvIP);
137 if (rc != 0) { 143 if (rc != 0) {
138 cERROR(1, ("%s: Failed to resolve server part of %s to IP: %d", 144 cERROR(1, ("%s: Failed to resolve server part of %s to IP: %d",
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 60e3c4253de0..714a542cbafc 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -44,7 +44,7 @@ cifs_ucs2_bytes(const __le16 *from, int maxbytes,
44 int maxwords = maxbytes / 2; 44 int maxwords = maxbytes / 2;
45 char tmp[NLS_MAX_CHARSET_SIZE]; 45 char tmp[NLS_MAX_CHARSET_SIZE];
46 46
47 for (i = 0; from[i] && i < maxwords; i++) { 47 for (i = 0; i < maxwords && from[i]; i++) {
48 charlen = codepage->uni2char(le16_to_cpu(from[i]), tmp, 48 charlen = codepage->uni2char(le16_to_cpu(from[i]), tmp,
49 NLS_MAX_CHARSET_SIZE); 49 NLS_MAX_CHARSET_SIZE);
50 if (charlen > 0) 50 if (charlen > 0)
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 44f30504b82d..84b75253b05a 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -376,10 +376,14 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
376 seq_printf(s, ",uid=%d", cifs_sb->mnt_uid); 376 seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
377 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) 377 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
378 seq_printf(s, ",forceuid"); 378 seq_printf(s, ",forceuid");
379 else
380 seq_printf(s, ",noforceuid");
379 381
380 seq_printf(s, ",gid=%d", cifs_sb->mnt_gid); 382 seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
381 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) 383 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
382 seq_printf(s, ",forcegid"); 384 seq_printf(s, ",forcegid");
385 else
386 seq_printf(s, ",noforcegid");
383 387
384 cifs_show_address(s, tcon->ses->server); 388 cifs_show_address(s, tcon->ses->server);
385 389
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 63f6cdfa5638..6084d6379c03 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -260,6 +260,8 @@ struct cifsTconInfo {
260 atomic_t num_closes; 260 atomic_t num_closes;
261 atomic_t num_deletes; 261 atomic_t num_deletes;
262 atomic_t num_mkdirs; 262 atomic_t num_mkdirs;
263 atomic_t num_posixopens;
264 atomic_t num_posixmkdirs;
263 atomic_t num_rmdirs; 265 atomic_t num_rmdirs;
264 atomic_t num_renames; 266 atomic_t num_renames;
265 atomic_t num_t2renames; 267 atomic_t num_t2renames;
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 922f5fe2084c..1866bc2927d4 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1113,7 +1113,10 @@ PsxCreat:
1113psx_create_err: 1113psx_create_err:
1114 cifs_buf_release(pSMB); 1114 cifs_buf_release(pSMB);
1115 1115
1116 cifs_stats_inc(&tcon->num_mkdirs); 1116 if (posix_flags & SMB_O_DIRECTORY)
1117 cifs_stats_inc(&tcon->num_posixmkdirs);
1118 else
1119 cifs_stats_inc(&tcon->num_posixopens);
1117 1120
1118 if (rc == -EAGAIN) 1121 if (rc == -EAGAIN)
1119 goto PsxCreat; 1122 goto PsxCreat;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index e16d7592116a..1f3345d7fa79 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -803,6 +803,10 @@ cifs_parse_mount_options(char *options, const char *devname,
803 char *data; 803 char *data;
804 unsigned int temp_len, i, j; 804 unsigned int temp_len, i, j;
805 char separator[2]; 805 char separator[2];
806 short int override_uid = -1;
807 short int override_gid = -1;
808 bool uid_specified = false;
809 bool gid_specified = false;
806 810
807 separator[0] = ','; 811 separator[0] = ',';
808 separator[1] = 0; 812 separator[1] = 0;
@@ -1093,18 +1097,20 @@ cifs_parse_mount_options(char *options, const char *devname,
1093 "too long.\n"); 1097 "too long.\n");
1094 return 1; 1098 return 1;
1095 } 1099 }
1096 } else if (strnicmp(data, "uid", 3) == 0) { 1100 } else if (!strnicmp(data, "uid", 3) && value && *value) {
1097 if (value && *value) 1101 vol->linux_uid = simple_strtoul(value, &value, 0);
1098 vol->linux_uid = 1102 uid_specified = true;
1099 simple_strtoul(value, &value, 0); 1103 } else if (!strnicmp(data, "forceuid", 8)) {
1100 } else if (strnicmp(data, "forceuid", 8) == 0) { 1104 override_uid = 1;
1101 vol->override_uid = 1; 1105 } else if (!strnicmp(data, "noforceuid", 10)) {
1102 } else if (strnicmp(data, "gid", 3) == 0) { 1106 override_uid = 0;
1103 if (value && *value) 1107 } else if (!strnicmp(data, "gid", 3) && value && *value) {
1104 vol->linux_gid = 1108 vol->linux_gid = simple_strtoul(value, &value, 0);
1105 simple_strtoul(value, &value, 0); 1109 gid_specified = true;
1106 } else if (strnicmp(data, "forcegid", 8) == 0) { 1110 } else if (!strnicmp(data, "forcegid", 8)) {
1107 vol->override_gid = 1; 1111 override_gid = 1;
1112 } else if (!strnicmp(data, "noforcegid", 10)) {
1113 override_gid = 0;
1108 } else if (strnicmp(data, "file_mode", 4) == 0) { 1114 } else if (strnicmp(data, "file_mode", 4) == 0) {
1109 if (value && *value) { 1115 if (value && *value) {
1110 vol->file_mode = 1116 vol->file_mode =
@@ -1355,6 +1361,18 @@ cifs_parse_mount_options(char *options, const char *devname,
1355 if (vol->UNCip == NULL) 1361 if (vol->UNCip == NULL)
1356 vol->UNCip = &vol->UNC[2]; 1362 vol->UNCip = &vol->UNC[2];
1357 1363
1364 if (uid_specified)
1365 vol->override_uid = override_uid;
1366 else if (override_uid == 1)
1367 printk(KERN_NOTICE "CIFS: ignoring forceuid mount option "
1368 "specified with no uid= option.\n");
1369
1370 if (gid_specified)
1371 vol->override_gid = override_gid;
1372 else if (override_gid == 1)
1373 printk(KERN_NOTICE "CIFS: ignoring forcegid mount option "
1374 "specified with no gid= option.\n");
1375
1358 return 0; 1376 return 0;
1359} 1377}
1360 1378
@@ -2452,10 +2470,10 @@ try_mount_again:
2452 tcon->local_lease = volume_info->local_lease; 2470 tcon->local_lease = volume_info->local_lease;
2453 } 2471 }
2454 if (pSesInfo) { 2472 if (pSesInfo) {
2455 if (pSesInfo->capabilities & CAP_LARGE_FILES) { 2473 if (pSesInfo->capabilities & CAP_LARGE_FILES)
2456 sb->s_maxbytes = (u64) 1 << 63; 2474 sb->s_maxbytes = MAX_LFS_FILESIZE;
2457 } else 2475 else
2458 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */ 2476 sb->s_maxbytes = MAX_NON_LFS;
2459 } 2477 }
2460 2478
2461 /* BB FIXME fix time_gran to be larger for LANMAN sessions */ 2479 /* BB FIXME fix time_gran to be larger for LANMAN sessions */
@@ -2544,11 +2562,20 @@ remote_path_check:
2544 2562
2545 if (mount_data != mount_data_global) 2563 if (mount_data != mount_data_global)
2546 kfree(mount_data); 2564 kfree(mount_data);
2565
2547 mount_data = cifs_compose_mount_options( 2566 mount_data = cifs_compose_mount_options(
2548 cifs_sb->mountdata, full_path + 1, 2567 cifs_sb->mountdata, full_path + 1,
2549 referrals, &fake_devname); 2568 referrals, &fake_devname);
2550 kfree(fake_devname); 2569
2551 free_dfs_info_array(referrals, num_referrals); 2570 free_dfs_info_array(referrals, num_referrals);
2571 kfree(fake_devname);
2572 kfree(full_path);
2573
2574 if (IS_ERR(mount_data)) {
2575 rc = PTR_ERR(mount_data);
2576 mount_data = NULL;
2577 goto mount_fail_check;
2578 }
2552 2579
2553 if (tcon) 2580 if (tcon)
2554 cifs_put_tcon(tcon); 2581 cifs_put_tcon(tcon);
@@ -2556,8 +2583,6 @@ remote_path_check:
2556 cifs_put_smb_ses(pSesInfo); 2583 cifs_put_smb_ses(pSesInfo);
2557 2584
2558 cleanup_volume_info(&volume_info); 2585 cleanup_volume_info(&volume_info);
2559 FreeXid(xid);
2560 kfree(full_path);
2561 referral_walks_count++; 2586 referral_walks_count++;
2562 goto try_mount_again; 2587 goto try_mount_again;
2563 } 2588 }
@@ -2726,6 +2751,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
2726 strncpy(tcon->treeName, tree, MAX_TREE_SIZE); 2751 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
2727 2752
2728 /* mostly informational -- no need to fail on error here */ 2753 /* mostly informational -- no need to fail on error here */
2754 kfree(tcon->nativeFileSystem);
2729 tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr, 2755 tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr,
2730 bytes_left, is_unicode, 2756 bytes_left, is_unicode,
2731 nls_codepage); 2757 nls_codepage);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 18afe57b2461..82d83839655e 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -212,7 +212,7 @@ cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
212 * junction to the new submount (ie to setup the fake directory 212 * junction to the new submount (ie to setup the fake directory
213 * which represents a DFS referral). 213 * which represents a DFS referral).
214 */ 214 */
215void 215static void
216cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb) 216cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
217{ 217{
218 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 218 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
@@ -388,7 +388,7 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
388} 388}
389 389
390/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */ 390/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
391void 391static void
392cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, 392cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
393 struct cifs_sb_info *cifs_sb, bool adjust_tz) 393 struct cifs_sb_info *cifs_sb, bool adjust_tz)
394{ 394{
@@ -513,9 +513,12 @@ int cifs_get_inode_info(struct inode **pinode,
513 cifs_sb->mnt_cifs_flags & 513 cifs_sb->mnt_cifs_flags &
514 CIFS_MOUNT_MAP_SPECIAL_CHR); 514 CIFS_MOUNT_MAP_SPECIAL_CHR);
515 if (rc1) { 515 if (rc1) {
516 /* BB EOPNOSUPP disable SERVER_INUM? */
517 cFYI(1, ("GetSrvInodeNum rc %d", rc1)); 516 cFYI(1, ("GetSrvInodeNum rc %d", rc1));
518 fattr.cf_uniqueid = iunique(sb, ROOT_I); 517 fattr.cf_uniqueid = iunique(sb, ROOT_I);
518 /* disable serverino if call not supported */
519 if (rc1 == -EINVAL)
520 cifs_sb->mnt_cifs_flags &=
521 ~CIFS_MOUNT_SERVER_INUM;
519 } 522 }
520 } else { 523 } else {
521 fattr.cf_uniqueid = iunique(sb, ROOT_I); 524 fattr.cf_uniqueid = iunique(sb, ROOT_I);