Merge branch 'x86-kbuild-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.git] / fs / cifs / connect.c
index 97f4311..1f3345d 100644 (file)
@@ -70,7 +70,6 @@ struct smb_vol {
        mode_t file_mode;
        mode_t dir_mode;
        unsigned secFlg;
-       bool rw:1;
        bool retry:1;
        bool intr:1;
        bool setuids:1;
@@ -804,6 +803,10 @@ cifs_parse_mount_options(char *options, const char *devname,
        char *data;
        unsigned int  temp_len, i, j;
        char separator[2];
+       short int override_uid = -1;
+       short int override_gid = -1;
+       bool uid_specified = false;
+       bool gid_specified = false;
 
        separator[0] = ',';
        separator[1] = 0;
@@ -832,7 +835,6 @@ cifs_parse_mount_options(char *options, const char *devname,
        vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
 
        /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
-       vol->rw = true;
        /* default is always to request posix paths. */
        vol->posix_paths = 1;
        /* default to using server inode numbers where available */
@@ -1095,18 +1097,20 @@ cifs_parse_mount_options(char *options, const char *devname,
                                                    "too long.\n");
                                return 1;
                        }
-               } else if (strnicmp(data, "uid", 3) == 0) {
-                       if (value && *value)
-                               vol->linux_uid =
-                                       simple_strtoul(value, &value, 0);
-               } else if (strnicmp(data, "forceuid", 8) == 0) {
-                               vol->override_uid = 1;
-               } else if (strnicmp(data, "gid", 3) == 0) {
-                       if (value && *value)
-                               vol->linux_gid =
-                                       simple_strtoul(value, &value, 0);
-               } else if (strnicmp(data, "forcegid", 8) == 0) {
-                               vol->override_gid = 1;
+               } else if (!strnicmp(data, "uid", 3) && value && *value) {
+                       vol->linux_uid = simple_strtoul(value, &value, 0);
+                       uid_specified = true;
+               } else if (!strnicmp(data, "forceuid", 8)) {
+                       override_uid = 1;
+               } else if (!strnicmp(data, "noforceuid", 10)) {
+                       override_uid = 0;
+               } else if (!strnicmp(data, "gid", 3) && value && *value) {
+                       vol->linux_gid = simple_strtoul(value, &value, 0);
+                       gid_specified = true;
+               } else if (!strnicmp(data, "forcegid", 8)) {
+                       override_gid = 1;
+               } else if (!strnicmp(data, "noforcegid", 10)) {
+                       override_gid = 0;
                } else if (strnicmp(data, "file_mode", 4) == 0) {
                        if (value && *value) {
                                vol->file_mode =
@@ -1199,7 +1203,9 @@ cifs_parse_mount_options(char *options, const char *devname,
                } else if (strnicmp(data, "guest", 5) == 0) {
                        /* ignore */
                } else if (strnicmp(data, "rw", 2) == 0) {
-                       vol->rw = true;
+                       /* ignore */
+               } else if (strnicmp(data, "ro", 2) == 0) {
+                       /* ignore */
                } else if (strnicmp(data, "noblocksend", 11) == 0) {
                        vol->noblocksnd = 1;
                } else if (strnicmp(data, "noautotune", 10) == 0) {
@@ -1218,8 +1224,6 @@ cifs_parse_mount_options(char *options, const char *devname,
                            parse these options again and set anything and it
                            is ok to just ignore them */
                        continue;
-               } else if (strnicmp(data, "ro", 2) == 0) {
-                       vol->rw = false;
                } else if (strnicmp(data, "hard", 4) == 0) {
                        vol->retry = 1;
                } else if (strnicmp(data, "soft", 4) == 0) {
@@ -1357,6 +1361,18 @@ cifs_parse_mount_options(char *options, const char *devname,
        if (vol->UNCip == NULL)
                vol->UNCip = &vol->UNC[2];
 
+       if (uid_specified)
+               vol->override_uid = override_uid;
+       else if (override_uid == 1)
+               printk(KERN_NOTICE "CIFS: ignoring forceuid mount option "
+                                  "specified with no uid= option.\n");
+
+       if (gid_specified)
+               vol->override_gid = override_gid;
+       else if (override_gid == 1)
+               printk(KERN_NOTICE "CIFS: ignoring forcegid mount option "
+                                  "specified with no gid= option.\n");
+
        return 0;
 }
 
@@ -1386,8 +1402,10 @@ cifs_find_tcp_session(struct sockaddr_storage *addr)
                     server->addr.sockAddr.sin_addr.s_addr))
                        continue;
                else if (addr->ss_family == AF_INET6 &&
-                        !ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr,
-                                         &addr6->sin6_addr))
+                        (!ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr,
+                                          &addr6->sin6_addr) ||
+                         server->addr.sockAddr6.sin6_scope_id !=
+                                          addr6->sin6_scope_id))
                        continue;
 
                ++server->srv_count;
@@ -1433,28 +1451,15 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
 
        memset(&addr, 0, sizeof(struct sockaddr_storage));
 
-       if (volume_info->UNCip && volume_info->UNC) {
-               rc = cifs_inet_pton(AF_INET, volume_info->UNCip,
-                                   &sin_server->sin_addr.s_addr);
-
-               if (rc <= 0) {
-                       /* not ipv4 address, try ipv6 */
-                       rc = cifs_inet_pton(AF_INET6, volume_info->UNCip,
-                                           &sin_server6->sin6_addr.in6_u);
-                       if (rc > 0)
-                               addr.ss_family = AF_INET6;
-               } else {
-                       addr.ss_family = AF_INET;
-               }
+       cFYI(1, ("UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip));
 
-               if (rc <= 0) {
+       if (volume_info->UNCip && volume_info->UNC) {
+               rc = cifs_convert_address(volume_info->UNCip, &addr);
+               if (!rc) {
                        /* we failed translating address */
                        rc = -EINVAL;
                        goto out_err;
                }
-
-               cFYI(1, ("UNC: %s ip: %s", volume_info->UNC,
-                        volume_info->UNCip));
        } else if (volume_info->UNCip) {
                /* BB using ip addr as tcp_ses name to connect to the
                   DFS root below */
@@ -1513,14 +1518,14 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
                cFYI(1, ("attempting ipv6 connect"));
                /* BB should we allow ipv6 on port 139? */
                /* other OS never observed in Wild doing 139 with v6 */
+               sin_server6->sin6_port = htons(volume_info->port);
                memcpy(&tcp_ses->addr.sockAddr6, sin_server6,
                        sizeof(struct sockaddr_in6));
-               sin_server6->sin6_port = htons(volume_info->port);
                rc = ipv6_connect(tcp_ses);
        } else {
+               sin_server->sin_port = htons(volume_info->port);
                memcpy(&tcp_ses->addr.sockAddr, sin_server,
                        sizeof(struct sockaddr_in));
-               sin_server->sin_port = htons(volume_info->port);
                rc = ipv4_connect(tcp_ses);
        }
        if (rc < 0) {
@@ -2465,10 +2470,10 @@ try_mount_again:
                tcon->local_lease = volume_info->local_lease;
        }
        if (pSesInfo) {
-               if (pSesInfo->capabilities & CAP_LARGE_FILES) {
-                       sb->s_maxbytes = (u64) 1 << 63;
-               else
-                       sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
+               if (pSesInfo->capabilities & CAP_LARGE_FILES)
+                       sb->s_maxbytes = MAX_LFS_FILESIZE;
+               else
+                       sb->s_maxbytes = MAX_NON_LFS;
        }
 
        /* BB FIXME fix time_gran to be larger for LANMAN sessions */
@@ -2557,11 +2562,20 @@ remote_path_check:
 
                        if (mount_data != mount_data_global)
                                kfree(mount_data);
+
                        mount_data = cifs_compose_mount_options(
                                        cifs_sb->mountdata, full_path + 1,
                                        referrals, &fake_devname);
-                       kfree(fake_devname);
+
                        free_dfs_info_array(referrals, num_referrals);
+                       kfree(fake_devname);
+                       kfree(full_path);
+
+                       if (IS_ERR(mount_data)) {
+                               rc = PTR_ERR(mount_data);
+                               mount_data = NULL;
+                               goto mount_fail_check;
+                       }
 
                        if (tcon)
                                cifs_put_tcon(tcon);
@@ -2569,8 +2583,6 @@ remote_path_check:
                                cifs_put_smb_ses(pSesInfo);
 
                        cleanup_volume_info(&volume_info);
-                       FreeXid(xid);
-                       kfree(full_path);
                        referral_walks_count++;
                        goto try_mount_again;
                }
@@ -2739,6 +2751,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
                strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
 
                /* mostly informational -- no need to fail on error here */
+               kfree(tcon->nativeFileSystem);
                tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr,
                                                      bytes_left, is_unicode,
                                                      nls_codepage);