]> Pileus Git - ~andy/linux/blobdiff - fs/cifs/connect.c
Merge branch 'akpm' (Fixups from Andrew)
[~andy/linux] / fs / cifs / connect.c
index 6df6fa14cba8e9f19fd5d686f17af6bdf928a48a..5c670b998ffbebb3e9743ab66c8125711ab8e421 100644 (file)
@@ -67,6 +67,7 @@ enum {
        /* Mount options that take no arguments */
        Opt_user_xattr, Opt_nouser_xattr,
        Opt_forceuid, Opt_noforceuid,
+       Opt_forcegid, Opt_noforcegid,
        Opt_noblocksend, Opt_noautotune,
        Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
        Opt_mapchars, Opt_nomapchars, Opt_sfu,
@@ -82,8 +83,7 @@ enum {
        Opt_serverino, Opt_noserverino,
        Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl,
        Opt_acl, Opt_noacl, Opt_locallease,
-       Opt_sign, Opt_seal, Opt_direct,
-       Opt_strictcache, Opt_noac,
+       Opt_sign, Opt_seal, Opt_noac,
        Opt_fsc, Opt_mfsymlinks,
        Opt_multiuser, Opt_sloppy,
 
@@ -118,6 +118,8 @@ static const match_table_t cifs_mount_option_tokens = {
        { Opt_nouser_xattr, "nouser_xattr" },
        { Opt_forceuid, "forceuid" },
        { Opt_noforceuid, "noforceuid" },
+       { Opt_forcegid, "forcegid" },
+       { Opt_noforcegid, "noforcegid" },
        { Opt_noblocksend, "noblocksend" },
        { Opt_noautotune, "noautotune" },
        { Opt_hard, "hard" },
@@ -160,10 +162,6 @@ static const match_table_t cifs_mount_option_tokens = {
        { Opt_locallease, "locallease" },
        { Opt_sign, "sign" },
        { Opt_seal, "seal" },
-       { Opt_direct, "direct" },
-       { Opt_direct, "directio" },
-       { Opt_direct, "forcedirectio" },
-       { Opt_strictcache, "strictcache" },
        { Opt_noac, "noac" },
        { Opt_fsc, "fsc" },
        { Opt_mfsymlinks, "mfsymlinks" },
@@ -277,6 +275,7 @@ static const match_table_t cifs_cacheflavor_tokens = {
 static const match_table_t cifs_smb_version_tokens = {
        { Smb_1, SMB1_VERSION_STRING },
        { Smb_21, SMB21_VERSION_STRING },
+       { Smb_30, SMB30_VERSION_STRING },
 };
 
 static int ip_connect(struct TCP_Server_Info *server);
@@ -819,6 +818,10 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
                cifs_dump_mem("Bad SMB: ", buf,
                        min_t(unsigned int, server->total_read, 48));
 
+       if (server->ops->is_status_pending &&
+           server->ops->is_status_pending(buf, server, length))
+               return -1;
+
        if (!mid)
                return length;
 
@@ -1075,6 +1078,10 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol)
                vol->ops = &smb21_operations;
                vol->vals = &smb21_values;
                break;
+       case Smb_30:
+               vol->ops = &smb21_operations; /* currently identical with 2.1 */
+               vol->vals = &smb30_values;
+               break;
 #endif
        default:
                cERROR(1, "Unknown vers= option specified: %s", value);
@@ -1101,8 +1108,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
        char *string = NULL;
        char *tmp_end, *value;
        char delim;
-       bool cache_specified = false;
-       static bool cache_warned = false;
 
        separator[0] = ',';
        separator[1] = 0;
@@ -1134,6 +1139,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
        /* default to using server inode numbers where available */
        vol->server_ino = 1;
 
+       /* default is to use strict cifs caching semantics */
+       vol->strict_io = true;
+
        vol->actimeo = CIFS_DEF_ACTIMEO;
 
        /* FIXME: add autonegotiation -- for now, SMB1 is default */
@@ -1190,6 +1198,12 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                case Opt_noforceuid:
                        override_uid = 0;
                        break;
+               case Opt_forcegid:
+                       override_gid = 1;
+                       break;
+               case Opt_noforcegid:
+                       override_gid = 0;
+                       break;
                case Opt_noblocksend:
                        vol->noblocksnd = 1;
                        break;
@@ -1317,22 +1331,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                         */
                        vol->seal = 1;
                        break;
-               case Opt_direct:
-                       cache_specified = true;
-                       vol->direct_io = true;
-                       vol->strict_io = false;
-                       cERROR(1, "The \"directio\" option will be removed in "
-                                 "3.7. Please switch to the \"cache=none\" "
-                                 "option.");
-                       break;
-               case Opt_strictcache:
-                       cache_specified = true;
-                       vol->direct_io = false;
-                       vol->strict_io = true;
-                       cERROR(1, "The \"strictcache\" option will be removed "
-                               "in 3.7. Please switch to the \"cache=strict\" "
-                               "option.");
-                       break;
                case Opt_noac:
                        printk(KERN_WARNING "CIFS: Mount option noac not "
                                "supported. Instead set "
@@ -1676,8 +1674,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                        if (string == NULL)
                                goto out_nomem;
 
-                       if (strnicmp(string, "TCP_NODELAY", 11) == 0)
+                       if (strnicmp(string, "TCP_NODELAY", 11) == 0) {
+                               printk(KERN_WARNING "CIFS: the "
+                                       "sockopt=TCP_NODELAY option has been "
+                                       "deprecated and will be removed "
+                                       "in 3.9\n");
                                vol->sockopt_tcp_nodelay = 1;
+                       }
                        break;
                case Opt_netbiosname:
                        string = match_strdup(args);
@@ -1762,7 +1765,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                                goto cifs_parse_mount_err;
                        break;
                case Opt_cache:
-                       cache_specified = true;
                        string = match_strdup(args);
                        if (string == NULL)
                                goto out_nomem;
@@ -1813,14 +1815,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                printk(KERN_NOTICE "CIFS: ignoring forcegid mount option "
                                   "specified with no gid= option.\n");
 
-       /* FIXME: remove this block in 3.7 */
-       if (!cache_specified && !cache_warned) {
-               cache_warned = true;
-               printk(KERN_NOTICE "CIFS: no cache= option specified, using "
-                                  "\"cache=loose\". This default will change "
-                                  "to \"cache=strict\" in 3.7.\n");
-       }
-
        kfree(mountdata_copy);
        return 0;
 
@@ -2636,6 +2630,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
        tcon->retry = volume_info->retry;
        tcon->nocase = volume_info->nocase;
        tcon->local_lease = volume_info->local_lease;
+       INIT_LIST_HEAD(&tcon->pending_opens);
 
        spin_lock(&cifs_tcp_ses_lock);
        list_add(&tcon->tcon_list, &ses->tcon_list);
@@ -3261,146 +3256,6 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
                           "mount option supported");
 }
 
-/*
- * When the server supports very large reads and writes via POSIX extensions,
- * we can allow up to 2^24-1, minus the size of a READ/WRITE_AND_X header, not
- * including the RFC1001 length.
- *
- * Note that this might make for "interesting" allocation problems during
- * writeback however as we have to allocate an array of pointers for the
- * pages. A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096.
- *
- * For reads, there is a similar problem as we need to allocate an array
- * of kvecs to handle the receive, though that should only need to be done
- * once.
- */
-#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4)
-#define CIFS_MAX_RSIZE ((1<<24) - sizeof(READ_RSP) + 4)
-
-/*
- * When the server doesn't allow large posix writes, only allow a rsize/wsize
- * of 2^17-1 minus the size of the call header. That allows for a read or
- * write up to the maximum size described by RFC1002.
- */
-#define CIFS_MAX_RFC1002_WSIZE ((1<<17) - 1 - sizeof(WRITE_REQ) + 4)
-#define CIFS_MAX_RFC1002_RSIZE ((1<<17) - 1 - sizeof(READ_RSP) + 4)
-
-/*
- * The default wsize is 1M. find_get_pages seems to return a maximum of 256
- * pages in a single call. With PAGE_CACHE_SIZE == 4k, this means we can fill
- * a single wsize request with a single call.
- */
-#define CIFS_DEFAULT_IOSIZE (1024 * 1024)
-
-/*
- * Windows only supports a max of 60kb reads and 65535 byte writes. Default to
- * those values when posix extensions aren't in force. In actuality here, we
- * use 65536 to allow for a write that is a multiple of 4k. Most servers seem
- * to be ok with the extra byte even though Windows doesn't send writes that
- * are that large.
- *
- * Citation:
- *
- * http://blogs.msdn.com/b/openspecification/archive/2009/04/10/smb-maximum-transmit-buffer-size-and-performance-tuning.aspx
- */
-#define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024)
-#define CIFS_DEFAULT_NON_POSIX_WSIZE (65536)
-
-/*
- * On hosts with high memory, we can't currently support wsize/rsize that are
- * larger than we can kmap at once. Cap the rsize/wsize at
- * LAST_PKMAP * PAGE_SIZE. We'll never be able to fill a read or write request
- * larger than that anyway.
- */
-#ifdef CONFIG_HIGHMEM
-#define CIFS_KMAP_SIZE_LIMIT   (LAST_PKMAP * PAGE_CACHE_SIZE)
-#else /* CONFIG_HIGHMEM */
-#define CIFS_KMAP_SIZE_LIMIT   (1<<24)
-#endif /* CONFIG_HIGHMEM */
-
-static unsigned int
-cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
-{
-       __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
-       struct TCP_Server_Info *server = tcon->ses->server;
-       unsigned int wsize;
-
-       /* start with specified wsize, or default */
-       if (pvolume_info->wsize)
-               wsize = pvolume_info->wsize;
-       else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
-               wsize = CIFS_DEFAULT_IOSIZE;
-       else
-               wsize = CIFS_DEFAULT_NON_POSIX_WSIZE;
-
-       /* can server support 24-bit write sizes? (via UNIX extensions) */
-       if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
-               wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE);
-
-       /*
-        * no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set?
-        * Limit it to max buffer offered by the server, minus the size of the
-        * WRITEX header, not including the 4 byte RFC1001 length.
-        */
-       if (!(server->capabilities & CAP_LARGE_WRITE_X) ||
-           (!(server->capabilities & CAP_UNIX) &&
-            (server->sec_mode & (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED))))
-               wsize = min_t(unsigned int, wsize,
-                               server->maxBuf - sizeof(WRITE_REQ) + 4);
-
-       /* limit to the amount that we can kmap at once */
-       wsize = min_t(unsigned int, wsize, CIFS_KMAP_SIZE_LIMIT);
-
-       /* hard limit of CIFS_MAX_WSIZE */
-       wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
-
-       return wsize;
-}
-
-static unsigned int
-cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
-{
-       __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
-       struct TCP_Server_Info *server = tcon->ses->server;
-       unsigned int rsize, defsize;
-
-       /*
-        * Set default value...
-        *
-        * HACK alert! Ancient servers have very small buffers. Even though
-        * MS-CIFS indicates that servers are only limited by the client's
-        * bufsize for reads, testing against win98se shows that it throws
-        * INVALID_PARAMETER errors if you try to request too large a read.
-        * OS/2 just sends back short reads.
-        *
-        * If the server doesn't advertise CAP_LARGE_READ_X, then assume that
-        * it can't handle a read request larger than its MaxBufferSize either.
-        */
-       if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_READ_CAP))
-               defsize = CIFS_DEFAULT_IOSIZE;
-       else if (server->capabilities & CAP_LARGE_READ_X)
-               defsize = CIFS_DEFAULT_NON_POSIX_RSIZE;
-       else
-               defsize = server->maxBuf - sizeof(READ_RSP);
-
-       rsize = pvolume_info->rsize ? pvolume_info->rsize : defsize;
-
-       /*
-        * no CAP_LARGE_READ_X? Then MS-CIFS states that we must limit this to
-        * the client's MaxBufferSize.
-        */
-       if (!(server->capabilities & CAP_LARGE_READ_X))
-               rsize = min_t(unsigned int, CIFSMaxBufSize, rsize);
-
-       /* limit to the amount that we can kmap at once */
-       rsize = min_t(unsigned int, rsize, CIFS_KMAP_SIZE_LIMIT);
-
-       /* hard limit of CIFS_MAX_RSIZE */
-       rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE);
-
-       return rsize;
-}
-
 static void
 cleanup_volume_info_contents(struct smb_vol *volume_info)
 {
@@ -3651,8 +3506,8 @@ try_mount_again:
        if (!tcon->ipc && server->ops->qfs_tcon)
                server->ops->qfs_tcon(xid, tcon);
 
-       cifs_sb->wsize = cifs_negotiate_wsize(tcon, volume_info);
-       cifs_sb->rsize = cifs_negotiate_rsize(tcon, volume_info);
+       cifs_sb->wsize = server->ops->negotiate_wsize(tcon, volume_info);
+       cifs_sb->rsize = server->ops->negotiate_rsize(tcon, volume_info);
 
        /* tune readahead according to rsize */
        cifs_sb->bdi.ra_pages = cifs_sb->rsize / PAGE_CACHE_SIZE;