Merge tag '5.4-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 19 Sep 2019 17:32:16 +0000 (10:32 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 19 Sep 2019 17:32:16 +0000 (10:32 -0700)
Pull cifs updates from Steve French:
 "Various cifs/smb3 fixes (including for share deleted cases) and
  features including improved encrypted read performance, and various
  debugging improvements.

  Note that since I am at a test event this week with the Samba team,
  and at the annual Storage Developer Conference/SMB3 Plugfest test
  event next week a higher than usual number of fixes is expected later
  next week as other features in progress get additional testing and
  review during these two events"

* tag '5.4-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6: (38 commits)
  cifs: update internal module version number
  cifs: modefromsid: write mode ACE first
  cifs: cifsroot: add more err checking
  smb3: add missing worker function for SMB3 change notify
  cifs: Add support for root file systems
  cifs: modefromsid: make room for 4 ACE
  smb3: fix potential null dereference in decrypt offload
  smb3: fix unmount hang in open_shroot
  smb3: allow disabling requesting leases
  smb3: improve handling of share deleted (and share recreated)
  smb3: display max smb3 requests in flight at any one time
  smb3: only offload decryption of read responses if multiple requests
  cifs: add a helper to find an existing readable handle to a file
  smb3: enable offload of decryption of large reads via mount option
  smb3: allow parallelizing decryption of reads
  cifs: add a debug macro that prints \\server\share for errors
  smb3: fix signing verification of large reads
  smb3: allow skipping signature verification for perf sensitive configurations
  smb3: add dynamic tracepoints for flush and close
  smb3: log warning if CSC policy conflicts with cache mount option
  ...

29 files changed:
Documentation/filesystems/cifs/cifsroot.txt [new file with mode: 0644]
fs/cifs/Kconfig
fs/cifs/Makefile
fs/cifs/cifs_debug.c
fs/cifs/cifs_debug.h
fs/cifs/cifs_fs_sb.h
fs/cifs/cifs_ioctl.h
fs/cifs/cifsacl.c
fs/cifs/cifsacl.h
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/cifsroot.c [new file with mode: 0644]
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/dir.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/smb2inode.c
fs/cifs/smb2maperror.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/smb2pdu.h
fs/cifs/smb2proto.h
fs/cifs/smb2transport.c
fs/cifs/trace.h
fs/cifs/transport.c
include/linux/root_dev.h

diff --git a/Documentation/filesystems/cifs/cifsroot.txt b/Documentation/filesystems/cifs/cifsroot.txt
new file mode 100644 (file)
index 0000000..0fa1a2c
--- /dev/null
@@ -0,0 +1,97 @@
+Mounting root file system via SMB (cifs.ko)
+===========================================
+
+Written 2019 by Paulo Alcantara <palcantara@suse.de>
+Written 2019 by Aurelien Aptel <aaptel@suse.com>
+
+The CONFIG_CIFS_ROOT option enables experimental root file system
+support over the SMB protocol via cifs.ko.
+
+It introduces a new kernel command-line option called 'cifsroot='
+which will tell the kernel to mount the root file system over the
+network by utilizing SMB or CIFS protocol.
+
+In order to mount, the network stack will also need to be set up by
+using 'ip=' config option. For more details, see
+Documentation/filesystems/nfs/nfsroot.txt.
+
+A CIFS root mount currently requires the use of SMB1+UNIX Extensions
+which is only supported by the Samba server. SMB1 is the older
+deprecated version of the protocol but it has been extended to support
+POSIX features (See [1]). The equivalent extensions for the newer
+recommended version of the protocol (SMB3) have not been fully
+implemented yet which means SMB3 doesn't support some required POSIX
+file system objects (e.g. block devices, pipes, sockets).
+
+As a result, a CIFS root will default to SMB1 for now but the version
+to use can nonetheless be changed via the 'vers=' mount option.  This
+default will change once the SMB3 POSIX extensions are fully
+implemented.
+
+Server configuration
+====================
+
+To enable SMB1+UNIX extensions you will need to set these global
+settings in Samba smb.conf:
+
+    [global]
+    server min protocol = NT1
+    unix extension = yes        # default
+
+Kernel command line
+===================
+
+root=/dev/cifs
+
+This is just a virtual device that basically tells the kernel to mount
+the root file system via SMB protocol.
+
+cifsroot=//<server-ip>/<share>[,options]
+
+Enables the kernel to mount the root file system via SMB that are
+located in the <server-ip> and <share> specified in this option.
+
+The default mount options are set in fs/cifs/cifsroot.c.
+
+server-ip
+       IPv4 address of the server.
+
+share
+       Path to SMB share (rootfs).
+
+options
+       Optional mount options. For more information, see mount.cifs(8).
+
+Examples
+========
+
+Export root file system as a Samba share in smb.conf file.
+
+...
+[linux]
+       path = /path/to/rootfs
+       read only = no
+       guest ok = yes
+       force user = root
+       force group = root
+       browseable = yes
+       writeable = yes
+       admin users = root
+       public = yes
+       create mask = 0777
+       directory mask = 0777
+...
+
+Restart smb service.
+
+# systemctl restart smb
+
+Test it under QEMU on a kernel built with CONFIG_CIFS_ROOT and
+CONFIG_IP_PNP options enabled.
+
+# qemu-system-x86_64 -enable-kvm -cpu host -m 1024 \
+  -kernel /path/to/linux/arch/x86/boot/bzImage -nographic \
+  -append "root=/dev/cifs rw ip=dhcp cifsroot=//10.0.2.2/linux,username=foo,password=bar console=ttyS0 3"
+
+
+1: https://wiki.samba.org/index.php/UNIX_Extensions
index 350bc3061656ebf83b4758ab77652d9fe5d9722f..22cf04fb32d359dbfa3fe197579db4cfe0ae9313 100644 (file)
@@ -211,3 +211,11 @@ config CIFS_FSCACHE
          Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data
          to be cached locally on disk through the general filesystem cache
          manager. If unsure, say N.
+
+config CIFS_ROOT
+       bool "SMB root file system (Experimental)"
+       depends on CIFS=y && IP_PNP
+       help
+         Enables root file system support over SMB protocol.
+
+         Most people say N here.
index 41332f20055b852bbac6453f6660cae371cba385..51bae9340842f0e3fc1f196f3a72bd527383f062 100644 (file)
@@ -21,3 +21,5 @@ cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o dfs_cache.o
 cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o
 
 cifs-$(CONFIG_CIFS_SMB_DIRECT) += smbdirect.o
+
+cifs-$(CONFIG_CIFS_ROOT) += cifsroot.o
index a38d796f5ffeee838d912fd3201a0fa83d424d2c..0b4eee3bed6600e9ff22c855fc3e3d1b37a9f045 100644 (file)
@@ -452,6 +452,7 @@ static ssize_t cifs_stats_proc_write(struct file *file,
                list_for_each(tmp1, &cifs_tcp_ses_list) {
                        server = list_entry(tmp1, struct TCP_Server_Info,
                                            tcp_ses_list);
+                       server->max_in_flight = 0;
 #ifdef CONFIG_CIFS_STATS2
                        for (i = 0; i < NUMBER_OF_SMB2_COMMANDS; i++) {
                                atomic_set(&server->num_cmds[i], 0);
@@ -526,6 +527,7 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v)
        list_for_each(tmp1, &cifs_tcp_ses_list) {
                server = list_entry(tmp1, struct TCP_Server_Info,
                                    tcp_ses_list);
+               seq_printf(m, "\nMax requests in flight: %d", server->max_in_flight);
 #ifdef CONFIG_CIFS_STATS2
                seq_puts(m, "\nTotal time spent processing by command. Time ");
                seq_printf(m, "units are jiffies (%d per second)\n", HZ);
index 3d392620a2f49ec11b75d14358527f3eaec9c7b3..100b0056a369fd4d373d59edb36ffece354adff6 100644 (file)
@@ -80,6 +80,60 @@ do {                                                 \
                        type, fmt, ##__VA_ARGS__);      \
 } while (0)
 
+#define cifs_server_dbg_func(ratefunc, type, fmt, ...)         \
+do {                                                           \
+       const char *sn = "";                                    \
+       if (server && server->hostname)                         \
+               sn = server->hostname;                          \
+       if ((type) & FYI && cifsFYI & CIFS_INFO) {              \
+               pr_debug_ ## ratefunc("%s: \\\\%s "     fmt,    \
+                       __FILE__, sn, ##__VA_ARGS__);           \
+       } else if ((type) & VFS) {                              \
+               pr_err_ ## ratefunc("CIFS VFS: \\\\%s " fmt,    \
+                       sn, ##__VA_ARGS__);                     \
+       } else if ((type) & NOISY && (NOISY != 0)) {            \
+               pr_debug_ ## ratefunc("\\\\%s " fmt,            \
+                       sn, ##__VA_ARGS__);                     \
+       }                                                       \
+} while (0)
+
+#define cifs_server_dbg(type, fmt, ...)                        \
+do {                                                   \
+       if ((type) & ONCE)                              \
+               cifs_server_dbg_func(once,              \
+                       type, fmt, ##__VA_ARGS__);      \
+       else                                            \
+               cifs_server_dbg_func(ratelimited,       \
+                       type, fmt, ##__VA_ARGS__);      \
+} while (0)
+
+#define cifs_tcon_dbg_func(ratefunc, type, fmt, ...)           \
+do {                                                           \
+       const char *tn = "";                                    \
+       if (tcon && tcon->treeName)                             \
+               tn = tcon->treeName;                            \
+       if ((type) & FYI && cifsFYI & CIFS_INFO) {              \
+               pr_debug_ ## ratefunc("%s: %s " fmt,            \
+                       __FILE__, tn, ##__VA_ARGS__);           \
+       } else if ((type) & VFS) {                              \
+               pr_err_ ## ratefunc("CIFS VFS: %s " fmt,        \
+                       tn, ##__VA_ARGS__);                     \
+       } else if ((type) & NOISY && (NOISY != 0)) {            \
+               pr_debug_ ## ratefunc("%s " fmt,                \
+                       tn, ##__VA_ARGS__);                     \
+       }                                                       \
+} while (0)
+
+#define cifs_tcon_dbg(type, fmt, ...)                  \
+do {                                                   \
+       if ((type) & ONCE)                              \
+               cifs_tcon_dbg_func(once,                \
+                       type, fmt, ##__VA_ARGS__);      \
+       else                                            \
+               cifs_tcon_dbg_func(ratelimited, \
+                       type, fmt, ##__VA_ARGS__);      \
+} while (0)
+
 /*
  *     debug OFF
  *     ---------
@@ -91,6 +145,19 @@ do {                                                                        \
                pr_debug(fmt, ##__VA_ARGS__);                           \
 } while (0)
 
+#define cifs_server_dbg(type, fmt, ...)                                        \
+do {                                                                   \
+       if (0)                                                          \
+               pr_debug("\\\\%s " fmt,                                 \
+                        server->hostname, ##__VA_ARGS__);              \
+} while (0)
+
+#define cifs_tcon_dbg(type, fmt, ...)                                  \
+do {                                                                   \
+       if (0)                                                          \
+               pr_debug("%s " fmt, tcon->treeName, ##__VA_ARGS__);     \
+} while (0)
+
 #define cifs_info(fmt, ...)                                            \
 do {                                                                   \
        pr_info("CIFS: "fmt, ##__VA_ARGS__);                            \
index b326d2ca3765784c95d7a54faf06b72365675923..6e7c4427369d878f008320e32e34f29af9e5cf8e 100644 (file)
@@ -53,6 +53,8 @@
 #define CIFS_MOUNT_NO_HANDLE_CACHE 0x4000000 /* disable caching dir handles */
 #define CIFS_MOUNT_NO_DFS 0x8000000 /* disable DFS resolving */
 #define CIFS_MOUNT_MODE_FROM_SID 0x10000000 /* retrieve mode from special ACE */
+#define CIFS_MOUNT_RO_CACHE    0x20000000  /* assumes share will not change */
+#define CIFS_MOUNT_RW_CACHE    0x40000000  /* assumes only client accessing */
 
 struct cifs_sb_info {
        struct rb_root tlink_tree;
index 086ddc5108af7d0147eddd523e591a00c2e445cc..6c3bd07868d7771baf62a02afb1ab514f7819ead 100644 (file)
@@ -46,6 +46,7 @@ struct smb_snapshot_array {
 /* query_info flags */
 #define PASSTHRU_QUERY_INFO    0x00000000
 #define PASSTHRU_FSCTL         0x00000001
+#define PASSTHRU_SET_INFO      0x00000002
 struct smb_query_info {
        __u32   info_type;
        __u32   file_info_class;
index 1d377b7f286055fa0b8c2117c89f843704fb9c3c..f842944a5c76a3cd905bd405bd463c4ae49c9af7 100644 (file)
@@ -701,10 +701,9 @@ static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
 }
 #endif
 
-
 static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
                       struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
-                      struct cifs_fattr *fattr)
+                      struct cifs_fattr *fattr, bool mode_from_special_sid)
 {
        int i;
        int num_aces = 0;
@@ -757,22 +756,34 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
 #ifdef CONFIG_CIFS_DEBUG2
                        dump_ace(ppace[i], end_of_acl);
 #endif
-                       if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
+                       if (mode_from_special_sid &&
+                           (compare_sids(&(ppace[i]->sid),
+                                         &sid_unix_NFS_mode) == 0)) {
+                               /*
+                                * Full permissions are:
+                                * 07777 = S_ISUID | S_ISGID | S_ISVTX |
+                                *         S_IRWXU | S_IRWXG | S_IRWXO
+                                */
+                               fattr->cf_mode &= ~07777;
+                               fattr->cf_mode |=
+                                       le32_to_cpu(ppace[i]->sid.sub_auth[2]);
+                               break;
+                       } else if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
                                access_flags_to_mode(ppace[i]->access_req,
                                                     ppace[i]->type,
                                                     &fattr->cf_mode,
                                                     &user_mask);
-                       if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
+                       else if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
                                access_flags_to_mode(ppace[i]->access_req,
                                                     ppace[i]->type,
                                                     &fattr->cf_mode,
                                                     &group_mask);
-                       if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
+                       else if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
                                access_flags_to_mode(ppace[i]->access_req,
                                                     ppace[i]->type,
                                                     &fattr->cf_mode,
                                                     &other_mask);
-                       if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
+                       else if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
                                access_flags_to_mode(ppace[i]->access_req,
                                                     ppace[i]->type,
                                                     &fattr->cf_mode,
@@ -795,22 +806,49 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
 
 
 static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
-                       struct cifs_sid *pgrpsid, __u64 nmode)
+                       struct cifs_sid *pgrpsid, __u64 nmode, bool modefromsid)
 {
        u16 size = 0;
+       u32 num_aces = 0;
        struct cifs_acl *pnndacl;
 
        pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
 
+       if (modefromsid) {
+               struct cifs_ace *pntace =
+                       (struct cifs_ace *)((char *)pnndacl + size);
+               int i;
+
+               pntace->type = ACCESS_ALLOWED;
+               pntace->flags = 0x0;
+               pntace->access_req = 0;
+               pntace->sid.num_subauth = 3;
+               pntace->sid.revision = 1;
+               for (i = 0; i < NUM_AUTHS; i++)
+                       pntace->sid.authority[i] =
+                               sid_unix_NFS_mode.authority[i];
+               pntace->sid.sub_auth[0] = sid_unix_NFS_mode.sub_auth[0];
+               pntace->sid.sub_auth[1] = sid_unix_NFS_mode.sub_auth[1];
+               pntace->sid.sub_auth[2] = cpu_to_le32(nmode & 07777);
+
+               /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
+               pntace->size = cpu_to_le16(28);
+               size += 28;
+               num_aces++;
+       }
+
        size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
                                        pownersid, nmode, S_IRWXU);
+       num_aces++;
        size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
                                        pgrpsid, nmode, S_IRWXG);
+       num_aces++;
        size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
                                         &sid_everyone, nmode, S_IRWXO);
+       num_aces++;
 
+       pndacl->num_aces = cpu_to_le32(num_aces);
        pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
-       pndacl->num_aces = cpu_to_le32(3);
 
        return 0;
 }
@@ -851,7 +889,8 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
 
 /* Convert CIFS ACL to POSIX form */
 static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
-               struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr)
+               struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr,
+               bool get_mode_from_special_sid)
 {
        int rc = 0;
        struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
@@ -900,7 +939,7 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
 
        if (dacloffset)
                parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
-                          group_sid_ptr, fattr);
+                          group_sid_ptr, fattr, get_mode_from_special_sid);
        else
                cifs_dbg(FYI, "no ACL\n"); /* BB grant all or default perms? */
 
@@ -909,7 +948,8 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
 
 /* Convert permission bits from mode to equivalent CIFS ACL */
 static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
-       __u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid, int *aclflag)
+       __u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid,
+       bool mode_from_sid, int *aclflag)
 {
        int rc = 0;
        __u32 dacloffset;
@@ -934,7 +974,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
                ndacl_ptr->num_aces = 0;
 
                rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr,
-                                       nmode);
+                                   nmode, mode_from_sid);
                sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
                /* copy sec desc control portion & owner and group sids */
                copy_sec_desc(pntsd, pnntsd, sidsoffset);
@@ -1128,8 +1168,8 @@ out:
 /* Translate the CIFS ACL (similar to NTFS ACL) for a file into mode bits */
 int
 cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
-                 struct inode *inode, const char *path,
-                 const struct cifs_fid *pfid)
+                 struct inode *inode, bool mode_from_special_sid,
+                 const char *path, const struct cifs_fid *pfid)
 {
        struct cifs_ntsd *pntsd = NULL;
        u32 acllen = 0;
@@ -1156,8 +1196,11 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
        if (IS_ERR(pntsd)) {
                rc = PTR_ERR(pntsd);
                cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
+       } else if (mode_from_special_sid) {
+               rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, true);
        } else {
-               rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr);
+               /* get approximated mode from ACL */
+               rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, false);
                kfree(pntsd);
                if (rc)
                        cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc);
@@ -1181,6 +1224,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
        struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
        struct smb_version_operations *ops;
+       bool mode_from_sid;
 
        if (IS_ERR(tlink))
                return PTR_ERR(tlink);
@@ -1218,8 +1262,13 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
                return -ENOMEM;
        }
 
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)
+               mode_from_sid = true;
+       else
+               mode_from_sid = false;
+
        rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
-                               &aclflag);
+                           mode_from_sid, &aclflag);
 
        cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);
 
index dd95a6fa24bf41f177e3f78a78a46acc58b8813a..eb428349f29a26904dc11bde943ed5aee24ba922 100644 (file)
@@ -45,7 +45,7 @@
  */
 #define DEFAULT_SEC_DESC_LEN (sizeof(struct cifs_ntsd) + \
                              sizeof(struct cifs_acl) + \
-                             (sizeof(struct cifs_ace) * 3))
+                             (sizeof(struct cifs_ace) * 4))
 
 /*
  * Maximum size of a string representation of a SID:
index e8afff702bb8e60bba9c43fbc593fd6f9e0a1b74..2e9c7f493f99ad649c659e2460d9e6ae4654cb66 100644 (file)
@@ -118,6 +118,7 @@ extern mempool_t *cifs_req_poolp;
 extern mempool_t *cifs_mid_poolp;
 
 struct workqueue_struct        *cifsiod_wq;
+struct workqueue_struct        *decrypt_wq;
 struct workqueue_struct        *cifsoplockd_wq;
 __u32 cifs_lock_secret;
 
@@ -422,6 +423,10 @@ cifs_show_cache_flavor(struct seq_file *s, struct cifs_sb_info *cifs_sb)
                seq_puts(s, "strict");
        else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
                seq_puts(s, "none");
+       else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE)
+               seq_puts(s, "singleclient"); /* assume only one client access */
+       else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE)
+               seq_puts(s, "ro"); /* read only caching assumed */
        else
                seq_puts(s, "loose");
 }
@@ -455,6 +460,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
        cifs_show_security(s, tcon->ses);
        cifs_show_cache_flavor(s, cifs_sb);
 
+       if (tcon->no_lease)
+               seq_puts(s, ",nolease");
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)
                seq_puts(s, ",multiuser");
        else if (tcon->ses->user_name)
@@ -576,6 +583,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
        seq_printf(s, ",rsize=%u", cifs_sb->rsize);
        seq_printf(s, ",wsize=%u", cifs_sb->wsize);
        seq_printf(s, ",bsize=%u", cifs_sb->bsize);
+       if (tcon->ses->server->min_offload)
+               seq_printf(s, ",esize=%u", tcon->ses->server->min_offload);
        seq_printf(s, ",echo_interval=%lu",
                        tcon->ses->server->echo_interval / HZ);
 
@@ -1517,11 +1526,25 @@ init_cifs(void)
                goto out_clean_proc;
        }
 
+       /*
+        * Consider in future setting limit!=0 maybe to min(num_of_cores - 1, 3)
+        * so that we don't launch too many worker threads but
+        * Documentation/workqueue.txt recommends setting it to 0
+        */
+
+       /* WQ_UNBOUND allows decrypt tasks to run on any CPU */
+       decrypt_wq = alloc_workqueue("smb3decryptd",
+                                    WQ_UNBOUND|WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
+       if (!decrypt_wq) {
+               rc = -ENOMEM;
+               goto out_destroy_cifsiod_wq;
+       }
+
        cifsoplockd_wq = alloc_workqueue("cifsoplockd",
                                         WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
        if (!cifsoplockd_wq) {
                rc = -ENOMEM;
-               goto out_destroy_cifsiod_wq;
+               goto out_destroy_decrypt_wq;
        }
 
        rc = cifs_fscache_register();
@@ -1587,6 +1610,8 @@ out_unreg_fscache:
        cifs_fscache_unregister();
 out_destroy_cifsoplockd_wq:
        destroy_workqueue(cifsoplockd_wq);
+out_destroy_decrypt_wq:
+       destroy_workqueue(decrypt_wq);
 out_destroy_cifsiod_wq:
        destroy_workqueue(cifsiod_wq);
 out_clean_proc:
@@ -1613,6 +1638,7 @@ exit_cifs(void)
        cifs_destroy_inodecache();
        cifs_fscache_unregister();
        destroy_workqueue(cifsoplockd_wq);
+       destroy_workqueue(decrypt_wq);
        destroy_workqueue(cifsiod_wq);
        cifs_proc_clean();
 }
index 99caf77df4a23edd9291e0f9336ca4a0d6df323e..bc4ca94137f2a678162472d41d5abb5b8a887e86 100644 (file)
@@ -152,5 +152,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
 extern const struct export_operations cifs_export_ops;
 #endif /* CONFIG_CIFS_NFSD_EXPORT */
 
-#define CIFS_VERSION   "2.22"
+#define CIFS_VERSION   "2.23"
 #endif                         /* _CIFSFS_H */
index fe610e7e3670ff3fd57ccbdbf6c396cc21a0610f..54e204589cb98be350bf9012b833987cca590774 100644 (file)
@@ -542,6 +542,7 @@ struct smb_vol {
        umode_t dir_mode;
        enum securityEnum sectype; /* sectype requested via mnt opts */
        bool sign; /* was signing requested via mnt opts? */
+       bool ignore_signature:1;
        bool retry:1;
        bool intr:1;
        bool setuids:1;
@@ -559,6 +560,8 @@ struct smb_vol {
        bool server_ino:1; /* use inode numbers from server ie UniqueId */
        bool direct_io:1;
        bool strict_io:1; /* strict cache behavior */
+       bool cache_ro:1;
+       bool cache_rw:1;
        bool remap:1;      /* set to remap seven reserved chars in filenames */
        bool sfu_remap:1;  /* remap seven reserved chars ala SFU */
        bool posix_paths:1; /* unset to not ask for posix pathnames. */
@@ -576,6 +579,7 @@ struct smb_vol {
        bool noblocksnd:1;
        bool noautotune:1;
        bool nostrictsync:1; /* do not force expensive SMBflush on every sync */
+       bool no_lease:1;     /* disable requesting leases */
        bool fsc:1;     /* enable fscache */
        bool mfsymlinks:1; /* use Minshall+French Symlinks */
        bool multiuser:1;
@@ -589,6 +593,7 @@ struct smb_vol {
        unsigned int bsize;
        unsigned int rsize;
        unsigned int wsize;
+       unsigned int min_offload;
        bool sockopt_tcp_nodelay:1;
        unsigned long actimeo; /* attribute cache timeout (jiffies) */
        struct smb_version_operations *ops;
@@ -602,6 +607,7 @@ struct smb_vol {
        __u32 handle_timeout; /* persistent and durable handle timeout in ms */
        unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */
        __u16 compression; /* compression algorithm 0xFFFF default 0=disabled */
+       bool rootfs:1; /* if it's a SMB root file system */
 };
 
 /**
@@ -620,7 +626,8 @@ struct smb_vol {
                         CIFS_MOUNT_MULTIUSER | CIFS_MOUNT_STRICT_IO | \
                         CIFS_MOUNT_CIFS_BACKUPUID | CIFS_MOUNT_CIFS_BACKUPGID | \
                         CIFS_MOUNT_UID_FROM_ACL | CIFS_MOUNT_NO_HANDLE_CACHE | \
-                        CIFS_MOUNT_NO_DFS | CIFS_MOUNT_MODE_FROM_SID)
+                        CIFS_MOUNT_NO_DFS | CIFS_MOUNT_MODE_FROM_SID | \
+                        CIFS_MOUNT_RO_CACHE | CIFS_MOUNT_RW_CACHE)
 
 /**
  * Generic VFS superblock mount flags (s_flags) to consider when
@@ -672,12 +679,14 @@ struct TCP_Server_Info {
        unsigned int credits;  /* send no more requests at once */
        unsigned int max_credits; /* can override large 32000 default at mnt */
        unsigned int in_flight;  /* number of requests on the wire to server */
+       unsigned int max_in_flight; /* max number of requests that were on wire */
        spinlock_t req_lock;  /* protect the two values above */
        struct mutex srv_mutex;
        struct task_struct *tsk;
        char server_GUID[16];
        __u16 sec_mode;
        bool sign; /* is signing enabled on this connection? */
+       bool ignore_signature:1; /* skip validation of signatures in SMB2/3 rsp */
        bool session_estab; /* mark when very first sess is established */
        int echo_credits;  /* echo reserved slots */
        int oplock_credits;  /* oplock break reserved slots */
@@ -740,6 +749,7 @@ struct TCP_Server_Info {
 #endif /* STATS2 */
        unsigned int    max_read;
        unsigned int    max_write;
+       unsigned int    min_offload;
        __le16  compress_algorithm;
        __le16  cipher_type;
         /* save initital negprot hash */
@@ -755,6 +765,7 @@ struct TCP_Server_Info {
         * reconnect.
         */
        int nr_targets;
+       bool noblockcnt; /* use non-blocking connect() */
 };
 
 struct cifs_credits {
@@ -1082,6 +1093,7 @@ struct cifs_tcon {
        bool need_reopen_files:1; /* need to reopen tcon file handles */
        bool use_resilient:1; /* use resilient instead of durable handles */
        bool use_persistent:1; /* use persistent instead of durable handles */
+       bool no_lease:1;    /* Do not request leases on files or directories */
        __le32 capabilities;
        __u32 share_flags;
        __u32 maximal_access;
@@ -1366,9 +1378,9 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file);
 #define CIFS_CACHE_RW_FLG      (CIFS_CACHE_READ_FLG | CIFS_CACHE_WRITE_FLG)
 #define CIFS_CACHE_RHW_FLG     (CIFS_CACHE_RW_FLG | CIFS_CACHE_HANDLE_FLG)
 
-#define CIFS_CACHE_READ(cinode) (cinode->oplock & CIFS_CACHE_READ_FLG)
+#define CIFS_CACHE_READ(cinode) ((cinode->oplock & CIFS_CACHE_READ_FLG) || (CIFS_SB(cinode->vfs_inode.i_sb)->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE))
 #define CIFS_CACHE_HANDLE(cinode) (cinode->oplock & CIFS_CACHE_HANDLE_FLG)
-#define CIFS_CACHE_WRITE(cinode) (cinode->oplock & CIFS_CACHE_WRITE_FLG)
+#define CIFS_CACHE_WRITE(cinode) ((cinode->oplock & CIFS_CACHE_WRITE_FLG) || (CIFS_SB(cinode->vfs_inode.i_sb)->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE))
 
 /*
  * One of these for each file inode
@@ -1887,6 +1899,7 @@ void cifs_queue_oplock_break(struct cifsFileInfo *cfile);
 
 extern const struct slow_work_ops cifs_oplock_break_ops;
 extern struct workqueue_struct *cifsiod_wq;
+extern struct workqueue_struct *decrypt_wq;
 extern struct workqueue_struct *cifsoplockd_wq;
 extern __u32 cifs_lock_secret;
 
index 592a6cea2b79f52df986bd9df7c1dcced837ccdd..99b1b1ef558ce7cdc49b6897090468f472792dcd 100644 (file)
@@ -137,7 +137,11 @@ extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool);
 extern int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,
                                  bool fsuid_only,
                                  struct cifsFileInfo **ret_file);
+extern int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,
+                                 struct cifsFileInfo **ret_file);
 extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool);
+extern int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
+                                 struct cifsFileInfo **ret_file);
 extern unsigned int smbCalcSize(void *buf, struct TCP_Server_Info *server);
 extern int decode_negTokenInit(unsigned char *security_blob, int length,
                        struct TCP_Server_Info *server);
@@ -197,6 +201,7 @@ extern int cifs_rename_pending_delete(const char *full_path,
                                      const unsigned int xid);
 extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
                              struct cifs_fattr *fattr, struct inode *inode,
+                             bool get_mode_from_special_sid,
                              const char *path, const struct cifs_fid *pfid);
 extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64,
                                        kuid_t, kgid_t);
diff --git a/fs/cifs/cifsroot.c b/fs/cifs/cifsroot.c
new file mode 100644 (file)
index 0000000..37edbfb
--- /dev/null
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SMB root file system support
+ *
+ * Copyright (c) 2019 Paulo Alcantara <palcantara@suse.de>
+ */
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/root_dev.h>
+#include <linux/kernel.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <net/ipconfig.h>
+
+#define DEFAULT_MNT_OPTS \
+       "vers=1.0,cifsacl,mfsymlinks,rsize=1048576,wsize=65536,uid=0,gid=0," \
+       "hard,rootfs"
+
+static char root_dev[2048] __initdata = "";
+static char root_opts[1024] __initdata = DEFAULT_MNT_OPTS;
+
+static __be32 __init parse_srvaddr(char *start, char *end)
+{
+       /* TODO: ipv6 support */
+       char addr[sizeof("aaa.bbb.ccc.ddd")];
+       int i = 0;
+
+       while (start < end && i < sizeof(addr) - 1) {
+               if (isdigit(*start) || *start == '.')
+                       addr[i++] = *start;
+               start++;
+       }
+       addr[i] = '\0';
+       return in_aton(addr);
+}
+
+/* cifsroot=//<server-ip>/<share>[,options] */
+static int __init cifs_root_setup(char *line)
+{
+       char *s;
+       int len;
+       __be32 srvaddr = htonl(INADDR_NONE);
+
+       ROOT_DEV = Root_CIFS;
+
+       if (strlen(line) > 3 && line[0] == '/' && line[1] == '/') {
+               s = strchr(&line[2], '/');
+               if (!s || s[1] == '\0')
+                       return 1;
+
+               /* make s point to ',' or '\0' at end of line */
+               s = strchrnul(s, ',');
+               /* len is strlen(unc) + '\0' */
+               len = s - line + 1;
+               if (len > sizeof(root_dev)) {
+                       printk(KERN_ERR "Root-CIFS: UNC path too long\n");
+                       return 1;
+               }
+               strlcpy(root_dev, line, len);
+               srvaddr = parse_srvaddr(&line[2], s);
+               if (*s) {
+                       int n = snprintf(root_opts,
+                                        sizeof(root_opts), "%s,%s",
+                                        DEFAULT_MNT_OPTS, s + 1);
+                       if (n >= sizeof(root_opts)) {
+                               printk(KERN_ERR "Root-CIFS: mount options string too long\n");
+                               root_opts[sizeof(root_opts)-1] = '\0';
+                               return 1;
+                       }
+               }
+       }
+
+       root_server_addr = srvaddr;
+
+       return 1;
+}
+
+__setup("cifsroot=", cifs_root_setup);
+
+int __init cifs_root_data(char **dev, char **opts)
+{
+       if (!root_dev[0] || root_server_addr == htonl(INADDR_NONE)) {
+               printk(KERN_ERR "Root-CIFS: no SMB server address\n");
+               return -1;
+       }
+
+       *dev = root_dev;
+       *opts = root_opts;
+
+       return 0;
+}
index 3907653e63c7784e8f70fb1f48da7bd3dcf68b73..dbee2132e419d03147fc2b3de8f864aca06a293f 100644 (file)
@@ -1393,7 +1393,7 @@ int
 CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
          FILE_ALL_INFO *buf)
 {
-       int rc = -EACCES;
+       int rc;
        OPEN_REQ *req = NULL;
        OPEN_RSP *rsp = NULL;
        int bytes_returned;
index 5299effa6f7d42d940a76057395fb7d9bd6ce99f..2850c3ce43919c4581be4818e29f905e45512b9a 100644 (file)
@@ -74,7 +74,7 @@ enum {
        Opt_user_xattr, Opt_nouser_xattr,
        Opt_forceuid, Opt_noforceuid,
        Opt_forcegid, Opt_noforcegid,
-       Opt_noblocksend, Opt_noautotune,
+       Opt_noblocksend, Opt_noautotune, Opt_nolease,
        Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
        Opt_mapposix, Opt_nomapposix,
        Opt_mapchars, Opt_nomapchars, Opt_sfu,
@@ -91,18 +91,19 @@ enum {
        Opt_serverino, Opt_noserverino,
        Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl,
        Opt_acl, Opt_noacl, Opt_locallease,
-       Opt_sign, Opt_seal, Opt_noac,
+       Opt_sign, Opt_ignore_signature, Opt_seal, Opt_noac,
        Opt_fsc, Opt_mfsymlinks,
        Opt_multiuser, Opt_sloppy, Opt_nosharesock,
        Opt_persistent, Opt_nopersistent,
        Opt_resilient, Opt_noresilient,
-       Opt_domainauto, Opt_rdma, Opt_modesid,
+       Opt_domainauto, Opt_rdma, Opt_modesid, Opt_rootfs,
        Opt_compress,
 
        /* Mount options which take numeric value */
        Opt_backupuid, Opt_backupgid, Opt_uid,
        Opt_cruid, Opt_gid, Opt_file_mode,
        Opt_dirmode, Opt_port,
+       Opt_min_enc_offload,
        Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo,
        Opt_echo_interval, Opt_max_credits, Opt_handletimeout,
        Opt_snapshot,
@@ -134,6 +135,7 @@ static const match_table_t cifs_mount_option_tokens = {
        { Opt_noforcegid, "noforcegid" },
        { Opt_noblocksend, "noblocksend" },
        { Opt_noautotune, "noautotune" },
+       { Opt_nolease, "nolease" },
        { Opt_hard, "hard" },
        { Opt_soft, "soft" },
        { Opt_perm, "perm" },
@@ -183,6 +185,7 @@ static const match_table_t cifs_mount_option_tokens = {
        { Opt_noacl, "noacl" },
        { Opt_locallease, "locallease" },
        { Opt_sign, "sign" },
+       { Opt_ignore_signature, "signloosely" },
        { Opt_seal, "seal" },
        { Opt_noac, "noac" },
        { Opt_fsc, "fsc" },
@@ -206,6 +209,7 @@ static const match_table_t cifs_mount_option_tokens = {
        { Opt_dirmode, "dirmode=%s" },
        { Opt_dirmode, "dir_mode=%s" },
        { Opt_port, "port=%s" },
+       { Opt_min_enc_offload, "esize=%s" },
        { Opt_blocksize, "bsize=%s" },
        { Opt_rsize, "rsize=%s" },
        { Opt_wsize, "wsize=%s" },
@@ -262,6 +266,7 @@ static const match_table_t cifs_mount_option_tokens = {
        { Opt_ignore, "nomand" },
        { Opt_ignore, "relatime" },
        { Opt_ignore, "_netdev" },
+       { Opt_rootfs, "rootfs" },
 
        { Opt_err, NULL }
 };
@@ -298,6 +303,8 @@ enum {
        Opt_cache_loose,
        Opt_cache_strict,
        Opt_cache_none,
+       Opt_cache_ro,
+       Opt_cache_rw,
        Opt_cache_err
 };
 
@@ -305,6 +312,8 @@ static const match_table_t cifs_cacheflavor_tokens = {
        { Opt_cache_loose, "loose" },
        { Opt_cache_strict, "strict" },
        { Opt_cache_none, "none" },
+       { Opt_cache_ro, "ro" },
+       { Opt_cache_rw, "singleclient" },
        { Opt_cache_err, NULL }
 };
 
@@ -489,7 +498,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
        } else {
                rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list, &tgt_it);
                if (rc && (rc != -EOPNOTSUPP)) {
-                       cifs_dbg(VFS, "%s: no target servers for DFS failover\n",
+                       cifs_server_dbg(VFS, "%s: no target servers for DFS failover\n",
                                 __func__);
                } else {
                        server->nr_targets = dfs_cache_get_nr_tgts(&tgt_list);
@@ -617,12 +626,12 @@ cifs_reconnect(struct TCP_Server_Info *server)
                rc = dfs_cache_noreq_update_tgthint(cifs_sb->origin_fullpath + 1,
                                                    tgt_it);
                if (rc) {
-                       cifs_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n",
+                       cifs_server_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n",
                                 __func__, rc);
                }
                rc = dfs_cache_update_vol(cifs_sb->origin_fullpath, server);
                if (rc) {
-                       cifs_dbg(VFS, "%s: failed to update vol info in DFS cache: rc = %d\n",
+                       cifs_server_dbg(VFS, "%s: failed to update vol info in DFS cache: rc = %d\n",
                                 __func__, rc);
                }
                dfs_cache_free_tgts(&tgt_list);
@@ -678,7 +687,7 @@ allocate_buffers(struct TCP_Server_Info *server)
        if (!server->bigbuf) {
                server->bigbuf = (char *)cifs_buf_get();
                if (!server->bigbuf) {
-                       cifs_dbg(VFS, "No memory for large SMB response\n");
+                       cifs_server_dbg(VFS, "No memory for large SMB response\n");
                        msleep(3000);
                        /* retry will check if exiting */
                        return false;
@@ -691,7 +700,7 @@ allocate_buffers(struct TCP_Server_Info *server)
        if (!server->smallbuf) {
                server->smallbuf = (char *)cifs_small_buf_get();
                if (!server->smallbuf) {
-                       cifs_dbg(VFS, "No memory for SMB response\n");
+                       cifs_server_dbg(VFS, "No memory for SMB response\n");
                        msleep(1000);
                        /* retry will check if exiting */
                        return false;
@@ -712,7 +721,7 @@ server_unresponsive(struct TCP_Server_Info *server)
         * We need to wait 3 echo intervals to make sure we handle such
         * situations right:
         * 1s  client sends a normal SMB request
-        * 3s  client gets a response
+        * 2s  client gets a response
         * 30s echo workqueue job pops, and decides we got a response recently
         *     and don't need to send another
         * ...
@@ -722,8 +731,8 @@ server_unresponsive(struct TCP_Server_Info *server)
        if ((server->tcpStatus == CifsGood ||
            server->tcpStatus == CifsNeedNegotiate) &&
            time_after(jiffies, server->lstrp + 3 * server->echo_interval)) {
-               cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n",
-                        server->hostname, (3 * server->echo_interval) / HZ);
+               cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n",
+                        (3 * server->echo_interval) / HZ);
                cifs_reconnect(server);
                wake_up(&server->response_q);
                return true;
@@ -861,7 +870,7 @@ is_smb_response(struct TCP_Server_Info *server, unsigned char type)
                wake_up(&server->response_q);
                break;
        default:
-               cifs_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
+               cifs_server_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
                cifs_reconnect(server);
        }
 
@@ -1008,7 +1017,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
        /* make sure this will fit in a large buffer */
        if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
                server->vals->header_preamble_size) {
-               cifs_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
+               cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
                cifs_reconnect(server);
                wake_up(&server->response_q);
                return -ECONNABORTED;
@@ -1149,7 +1158,7 @@ next_pdu:
                /* make sure we have enough to get to the MID */
                if (server->pdu_size < HEADER_SIZE(server) - 1 -
                    server->vals->header_preamble_size) {
-                       cifs_dbg(VFS, "SMB response too short (%u bytes)\n",
+                       cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n",
                                 server->pdu_size);
                        cifs_reconnect(server);
                        wake_up(&server->response_q);
@@ -1222,7 +1231,7 @@ next_pdu:
                                smb2_add_credits_from_hdr(bufs[i], server);
                                cifs_dbg(FYI, "Received oplock break\n");
                        } else {
-                               cifs_dbg(VFS, "No task to wake, unknown frame "
+                               cifs_server_dbg(VFS, "No task to wake, unknown frame "
                                         "received! NumMids %d\n",
                                         atomic_read(&midCount));
                                cifs_dump_mem("Received Data is: ", bufs[i],
@@ -1418,14 +1427,32 @@ cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
        case Opt_cache_loose:
                vol->direct_io = false;
                vol->strict_io = false;
+               vol->cache_ro = false;
+               vol->cache_rw = false;
                break;
        case Opt_cache_strict:
                vol->direct_io = false;
                vol->strict_io = true;
+               vol->cache_ro = false;
+               vol->cache_rw = false;
                break;
        case Opt_cache_none:
                vol->direct_io = true;
                vol->strict_io = false;
+               vol->cache_ro = false;
+               vol->cache_rw = false;
+               break;
+       case Opt_cache_ro:
+               vol->direct_io = false;
+               vol->strict_io = false;
+               vol->cache_ro = true;
+               vol->cache_rw = false;
+               break;
+       case Opt_cache_rw:
+               vol->direct_io = false;
+               vol->strict_io = false;
+               vol->cache_ro = false;
+               vol->cache_rw = true;
                break;
        default:
                cifs_dbg(VFS, "bad cache= option: %s\n", value);
@@ -1713,6 +1740,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                case Opt_noautotune:
                        vol->noautotune = 1;
                        break;
+               case Opt_nolease:
+                       vol->no_lease = 1;
+                       break;
                case Opt_hard:
                        vol->retry = 1;
                        break;
@@ -1748,6 +1778,11 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                case Opt_nodfs:
                        vol->nodfs = 1;
                        break;
+               case Opt_rootfs:
+#ifdef CONFIG_CIFS_ROOT
+                       vol->rootfs = true;
+#endif
+                       break;
                case Opt_posixpaths:
                        vol->posix_paths = 1;
                        break;
@@ -1855,6 +1890,10 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                case Opt_sign:
                        vol->sign = true;
                        break;
+               case Opt_ignore_signature:
+                       vol->sign = true;
+                       vol->ignore_signature = true;
+                       break;
                case Opt_seal:
                        /* we do not do the following in secFlags because seal
                         * is a per tree connection (mount) not a per socket
@@ -1989,6 +2028,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                        }
                        port = (unsigned short)option;
                        break;
+               case Opt_min_enc_offload:
+                       if (get_option_ul(args, &option)) {
+                               cifs_dbg(VFS, "Invalid minimum encrypted read offload size (esize)\n");
+                               goto cifs_parse_mount_err;
+                       }
+                       vol->min_offload = option;
+                       break;
                case Opt_blocksize:
                        if (get_option_ul(args, &option)) {
                                cifs_dbg(VFS, "%s: Invalid blocksize value\n",
@@ -2586,6 +2632,12 @@ static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
        if (server->rdma != vol->rdma)
                return 0;
 
+       if (server->ignore_signature != vol->ignore_signature)
+               return 0;
+
+       if (server->min_offload != vol->min_offload)
+               return 0;
+
        return 1;
 }
 
@@ -2681,11 +2733,13 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
                goto out_err_crypto_release;
        }
 
-       tcp_ses->noblocksnd = volume_info->noblocksnd;
+       tcp_ses->noblockcnt = volume_info->rootfs;
+       tcp_ses->noblocksnd = volume_info->noblocksnd || volume_info->rootfs;
        tcp_ses->noautotune = volume_info->noautotune;
        tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
        tcp_ses->rdma = volume_info->rdma;
        tcp_ses->in_flight = 0;
+       tcp_ses->max_in_flight = 0;
        tcp_ses->credits = 1;
        init_waitqueue_head(&tcp_ses->response_q);
        init_waitqueue_head(&tcp_ses->request_q);
@@ -2760,10 +2814,11 @@ smbd_connected:
                module_put(THIS_MODULE);
                goto out_err_crypto_release;
        }
+       tcp_ses->min_offload = volume_info->min_offload;
        tcp_ses->tcpStatus = CifsNeedNegotiate;
 
        tcp_ses->nr_targets = 1;
-
+       tcp_ses->ignore_signature = volume_info->ignore_signature;
        /* thread spawned, put it on the list */
        spin_lock(&cifs_tcp_ses_lock);
        list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
@@ -2840,16 +2895,17 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info)
        struct nls_table *nls_codepage;
        char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
        bool seal = false;
+       struct TCP_Server_Info *server = ses->server;
 
        /*
         * If the mount request that resulted in the creation of the
         * session requires encryption, force IPC to be encrypted too.
         */
        if (volume_info->seal) {
-               if (ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
+               if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
                        seal = true;
                else {
-                       cifs_dbg(VFS,
+                       cifs_server_dbg(VFS,
                                 "IPC: server doesn't support encryption\n");
                        return -EOPNOTSUPP;
                }
@@ -2859,7 +2915,7 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info)
        if (tcon == NULL)
                return -ENOMEM;
 
-       scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", ses->server->hostname);
+       scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname);
 
        /* cannot fail */
        nls_codepage = load_nls_default();
@@ -2868,11 +2924,11 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info)
        tcon->ses = ses;
        tcon->ipc = true;
        tcon->seal = seal;
-       rc = ses->server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage);
+       rc = server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage);
        free_xid(xid);
 
        if (rc) {
-               cifs_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
+               cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
                tconInfoFree(tcon);
                goto out;
        }
@@ -2958,7 +3014,7 @@ void cifs_put_smb_ses(struct cifs_ses *ses)
                xid = get_xid();
                rc = server->ops->logoff(xid, ses);
                if (rc)
-                       cifs_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
+                       cifs_server_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
                                __func__, rc);
                _free_xid(xid);
        }
@@ -3212,7 +3268,6 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
 
        ses->sectype = volume_info->sectype;
        ses->sign = volume_info->sign;
-
        mutex_lock(&ses->session_mutex);
        rc = cifs_negotiate_protocol(xid, ses);
        if (!rc)
@@ -3250,6 +3305,8 @@ static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
                return 0;
        if (tcon->handle_timeout != volume_info->handle_timeout)
                return 0;
+       if (tcon->no_lease != volume_info->no_lease)
+               return 0;
        return 1;
 }
 
@@ -3455,6 +3512,14 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
                tcon->use_resilient = true;
        }
 
+       /* If the user really knows what they are doing they can override */
+       if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) {
+               if (volume_info->cache_ro)
+                       cifs_dbg(VFS, "cache=ro requested on mount but NO_CACHING flag set on share\n");
+               else if (volume_info->cache_rw)
+                       cifs_dbg(VFS, "cache=singleclient requested on mount but NO_CACHING flag set on share\n");
+       }
+
        /*
         * We can have only one retry value for a connection to a share so for
         * resources mounted more than once to the same server share the last
@@ -3464,6 +3529,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
        tcon->nocase = volume_info->nocase;
        tcon->nohandlecache = volume_info->nohandlecache;
        tcon->local_lease = volume_info->local_lease;
+       tcon->no_lease = volume_info->no_lease;
        INIT_LIST_HEAD(&tcon->pending_opens);
 
        spin_lock(&cifs_tcp_ses_lock);
@@ -3659,10 +3725,10 @@ bind_socket(struct TCP_Server_Info *server)
                        saddr4 = (struct sockaddr_in *)&server->srcaddr;
                        saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
                        if (saddr6->sin6_family == AF_INET6)
-                               cifs_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
+                               cifs_server_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
                                         &saddr6->sin6_addr, rc);
                        else
-                               cifs_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
+                               cifs_server_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
                                         &saddr4->sin_addr.s_addr, rc);
                }
        }
@@ -3766,7 +3832,7 @@ generic_ip_connect(struct TCP_Server_Info *server)
                rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
                                   IPPROTO_TCP, &socket, 1);
                if (rc < 0) {
-                       cifs_dbg(VFS, "Error %d creating socket\n", rc);
+                       cifs_server_dbg(VFS, "Error %d creating socket\n", rc);
                        server->ssocket = NULL;
                        return rc;
                }
@@ -3814,7 +3880,11 @@ generic_ip_connect(struct TCP_Server_Info *server)
                 socket->sk->sk_sndbuf,
                 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
 
-       rc = socket->ops->connect(socket, saddr, slen, 0);
+       rc = socket->ops->connect(socket, saddr, slen,
+                                 server->noblockcnt ? O_NONBLOCK : 0);
+
+       if (rc == -EINPROGRESS)
+               rc = 0;
        if (rc < 0) {
                cifs_dbg(FYI, "Error %d connecting to server\n", rc);
                sock_release(socket);
@@ -4040,6 +4110,14 @@ int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
                cifs_dbg(FYI, "mounting share using direct i/o\n");
                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
        }
+       if (pvolume_info->cache_ro) {
+               cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n");
+               cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE;
+       } else if (pvolume_info->cache_rw) {
+               cifs_dbg(VFS, "mounting share in single client RW caching mode. Ensure that no other systems will be accessing the share.\n");
+               cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE |
+                                           CIFS_MOUNT_RW_CACHE);
+       }
        if (pvolume_info->mfsymlinks) {
                if (pvolume_info->sfu_emul) {
                        /*
@@ -4150,7 +4228,7 @@ static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
 
        if ((vol->persistent == true) && (!(ses->server->capabilities &
                                            SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) {
-               cifs_dbg(VFS, "persistent handles not supported by server\n");
+               cifs_server_dbg(VFS, "persistent handles not supported by server\n");
                return -EOPNOTSUPP;
        }
 
@@ -4182,8 +4260,18 @@ static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
                tcon->unix_ext = 0; /* server does not support them */
 
        /* do not care if a following call succeed - informational */
-       if (!tcon->pipe && server->ops->qfs_tcon)
+       if (!tcon->pipe && server->ops->qfs_tcon) {
                server->ops->qfs_tcon(*xid, tcon);
+               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) {
+                       if (tcon->fsDevInfo.DeviceCharacteristics &
+                           FILE_READ_ONLY_DEVICE)
+                               cifs_dbg(VFS, "mounted to read only share\n");
+                       else if ((cifs_sb->mnt_cifs_flags &
+                                 CIFS_MOUNT_RW_CACHE) == 0)
+                               cifs_dbg(VFS, "read only mount of RW share\n");
+                       /* no need to log a RW mount of a typical RW share */
+               }
+       }
 
        cifs_sb->wsize = server->ops->negotiate_wsize(tcon, vol);
        cifs_sb->rsize = server->ops->negotiate_rsize(tcon, vol);
@@ -4588,7 +4676,7 @@ static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
                rc = cifs_are_all_path_components_accessible(server, xid, tcon,
                        cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS);
                if (rc != 0) {
-                       cifs_dbg(VFS, "cannot query dirs between root and final path, "
+                       cifs_server_dbg(VFS, "cannot query dirs between root and final path, "
                                 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
                        cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
                        rc = 0;
@@ -5090,7 +5178,7 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
                rc = server->ops->sess_setup(xid, ses, nls_info);
 
        if (rc)
-               cifs_dbg(VFS, "Send error in SessSetup = %d\n", rc);
+               cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc);
 
        return rc;
 }
index be424e81e3ad98e20f65de41572d87a569a28c7b..dd5ac841aefa7fa45a9fe63cc24d1d07de4dd593 100644 (file)
@@ -125,7 +125,7 @@ cifs_bp_rename_retry:
        }
        rcu_read_unlock();
 
-       full_path = kmalloc(namelen+1, GFP_KERNEL);
+       full_path = kmalloc(namelen+1, GFP_ATOMIC);
        if (full_path == NULL)
                return full_path;
        full_path[namelen] = 0; /* trailing null */
index 97090693d18278045f5447fcf4de4cf162edaefb..4b95700c507c793abc9e594ca4ea4aeb42a2ceb7 100644 (file)
@@ -1693,9 +1693,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
        bool posix_lck = false;
        struct cifs_sb_info *cifs_sb;
        struct cifs_tcon *tcon;
-       struct cifsInodeInfo *cinode;
        struct cifsFileInfo *cfile;
-       __u16 netfid;
        __u32 type;
 
        rc = -EACCES;
@@ -1711,8 +1709,6 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
        cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag,
                        tcon->ses->server);
        cifs_sb = CIFS_FILE_SB(file);
-       netfid = cfile->fid.netfid;
-       cinode = CIFS_I(file_inode(file));
 
        if (cap_unix(tcon->ses) &&
            (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
@@ -1764,7 +1760,6 @@ cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data,
        int rc = 0;
        unsigned int bytes_written = 0;
        unsigned int total_written;
-       struct cifs_sb_info *cifs_sb;
        struct cifs_tcon *tcon;
        struct TCP_Server_Info *server;
        unsigned int xid;
@@ -1772,8 +1767,6 @@ cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data,
        struct cifsInodeInfo *cifsi = CIFS_I(d_inode(dentry));
        struct cifs_io_parms io_parms;
 
-       cifs_sb = CIFS_SB(dentry->d_sb);
-
        cifs_dbg(FYI, "write %zd bytes to offset %lld of %pd\n",
                 write_size, *offset, dentry);
 
@@ -1980,6 +1973,77 @@ find_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only)
        return cfile;
 }
 
+int
+cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,
+                      struct cifsFileInfo **ret_file)
+{
+       struct list_head *tmp;
+       struct cifsFileInfo *cfile;
+       struct cifsInodeInfo *cinode;
+       char *full_path;
+
+       *ret_file = NULL;
+
+       spin_lock(&tcon->open_file_lock);
+       list_for_each(tmp, &tcon->openFileList) {
+               cfile = list_entry(tmp, struct cifsFileInfo,
+                            tlist);
+               full_path = build_path_from_dentry(cfile->dentry);
+               if (full_path == NULL) {
+                       spin_unlock(&tcon->open_file_lock);
+                       return -ENOMEM;
+               }
+               if (strcmp(full_path, name)) {
+                       kfree(full_path);
+                       continue;
+               }
+
+               kfree(full_path);
+               cinode = CIFS_I(d_inode(cfile->dentry));
+               spin_unlock(&tcon->open_file_lock);
+               return cifs_get_writable_file(cinode, 0, ret_file);
+       }
+
+       spin_unlock(&tcon->open_file_lock);
+       return -ENOENT;
+}
+
+int
+cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
+                      struct cifsFileInfo **ret_file)
+{
+       struct list_head *tmp;
+       struct cifsFileInfo *cfile;
+       struct cifsInodeInfo *cinode;
+       char *full_path;
+
+       *ret_file = NULL;
+
+       spin_lock(&tcon->open_file_lock);
+       list_for_each(tmp, &tcon->openFileList) {
+               cfile = list_entry(tmp, struct cifsFileInfo,
+                            tlist);
+               full_path = build_path_from_dentry(cfile->dentry);
+               if (full_path == NULL) {
+                       spin_unlock(&tcon->open_file_lock);
+                       return -ENOMEM;
+               }
+               if (strcmp(full_path, name)) {
+                       kfree(full_path);
+                       continue;
+               }
+
+               kfree(full_path);
+               cinode = CIFS_I(d_inode(cfile->dentry));
+               spin_unlock(&tcon->open_file_lock);
+               *ret_file = find_readable_file(cinode, 0);
+               return *ret_file ? 0 : -ENOENT;
+       }
+
+       spin_unlock(&tcon->open_file_lock);
+       return -ENOENT;
+}
+
 static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
 {
        struct address_space *mapping = page->mapping;
@@ -3577,10 +3641,8 @@ collect_uncached_read_data(struct cifs_aio_ctx *ctx)
        struct cifs_readdata *rdata, *tmp;
        struct iov_iter *to = &ctx->iter;
        struct cifs_sb_info *cifs_sb;
-       struct cifs_tcon *tcon;
        int rc;
 
-       tcon = tlink_tcon(ctx->cfile->tlink);
        cifs_sb = CIFS_SB(ctx->cfile->dentry->d_sb);
 
        mutex_lock(&ctx->aio_mutex);
index 56ca4b8ccabac909abc312602506020363b52948..26cdfbf1e16475246f29ee222ea548d04fe17def 100644 (file)
@@ -893,8 +893,17 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
        }
 
        /* fill in 0777 bits from ACL */
-       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
-               rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid);
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) {
+               rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, true,
+                                      full_path, fid);
+               if (rc) {
+                       cifs_dbg(FYI, "%s: Get mode from SID failed. rc=%d\n",
+                               __func__, rc);
+                       goto cgii_exit;
+               }
+       } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
+               rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, false,
+                                      full_path, fid);
                if (rc) {
                        cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
                                 __func__, rc);
@@ -2480,7 +2489,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
        if (attrs->ia_valid & ATTR_GID)
                gid = attrs->ia_gid;
 
-       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
+       if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
+           (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
                if (uid_valid(uid) || gid_valid(gid)) {
                        rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
                                                        uid, gid);
@@ -2501,7 +2511,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
        if (attrs->ia_valid & ATTR_MODE) {
                mode = attrs->ia_mode;
                rc = 0;
-               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
+               if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
+                   (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
                        rc = id_mode_to_cifs_acl(inode, full_path, mode,
                                                INVALID_UID, INVALID_GID);
                        if (rc) {
index d8d9cdfa30b6bcbcfd8bc73646c0270a61ad0094..d2a3fb7e5c8dcc7260b7fa3672495f8ea9d5e70d 100644 (file)
@@ -51,7 +51,8 @@ static int
 smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
                 struct cifs_sb_info *cifs_sb, const char *full_path,
                 __u32 desired_access, __u32 create_disposition,
-                __u32 create_options, void *ptr, int command)
+                __u32 create_options, void *ptr, int command,
+                struct cifsFileInfo *cfile)
 {
        int rc;
        __le16 *utf16_path = NULL;
@@ -83,10 +84,16 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
        resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
        memset(rsp_iov, 0, sizeof(rsp_iov));
 
+       /* We already have a handle so we can skip the open */
+       if (cfile)
+               goto after_open;
+
        /* Open */
        utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
-       if (!utf16_path)
-               return -ENOMEM;
+       if (!utf16_path) {
+               rc = -ENOMEM;
+               goto finished;
+       }
 
        oparms.tcon = tcon;
        oparms.desired_access = desired_access;
@@ -106,7 +113,10 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
        if (rc)
                goto finished;
 
-       smb2_set_next_command(tcon, &rqst[num_rqst++]);
+       smb2_set_next_command(tcon, &rqst[num_rqst]);
+ after_open:
+       num_rqst++;
+       rc = 0;
 
        /* Operation */
        switch (command) {
@@ -115,15 +125,31 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
                rqst[num_rqst].rq_iov = qi_iov;
                rqst[num_rqst].rq_nvec = 1;
 
-               rc = SMB2_query_info_init(tcon, &rqst[num_rqst], COMPOUND_FID,
-                               COMPOUND_FID, FILE_ALL_INFORMATION,
+               if (cfile)
+                       rc = SMB2_query_info_init(tcon, &rqst[num_rqst],
+                               cfile->fid.persistent_fid,
+                               cfile->fid.volatile_fid,
+                               FILE_ALL_INFORMATION,
+                               SMB2_O_INFO_FILE, 0,
+                               sizeof(struct smb2_file_all_info) +
+                                         PATH_MAX * 2, 0, NULL);
+               else {
+                       rc = SMB2_query_info_init(tcon, &rqst[num_rqst],
+                               COMPOUND_FID,
+                               COMPOUND_FID,
+                                FILE_ALL_INFORMATION,
                                SMB2_O_INFO_FILE, 0,
                                sizeof(struct smb2_file_all_info) +
                                          PATH_MAX * 2, 0, NULL);
+                       if (!rc) {
+                               smb2_set_next_command(tcon, &rqst[num_rqst]);
+                               smb2_set_related(&rqst[num_rqst]);
+                       }
+               }
+
                if (rc)
                        goto finished;
-               smb2_set_next_command(tcon, &rqst[num_rqst]);
-               smb2_set_related(&rqst[num_rqst++]);
+               num_rqst++;
                trace_smb3_query_info_compound_enter(xid, ses->Suid, tcon->tid,
                                                     full_path);
                break;
@@ -182,14 +208,27 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
                size[0] = sizeof(FILE_BASIC_INFO);
                data[0] = ptr;
 
-               rc = SMB2_set_info_init(tcon, &rqst[num_rqst], COMPOUND_FID,
-                                       COMPOUND_FID, current->tgid,
-                                       FILE_BASIC_INFORMATION,
-                                       SMB2_O_INFO_FILE, 0, data, size);
+               if (cfile)
+                       rc = SMB2_set_info_init(tcon, &rqst[num_rqst],
+                               cfile->fid.persistent_fid,
+                               cfile->fid.volatile_fid, current->tgid,
+                               FILE_BASIC_INFORMATION,
+                               SMB2_O_INFO_FILE, 0, data, size);
+               else {
+                       rc = SMB2_set_info_init(tcon, &rqst[num_rqst],
+                               COMPOUND_FID,
+                               COMPOUND_FID, current->tgid,
+                               FILE_BASIC_INFORMATION,
+                               SMB2_O_INFO_FILE, 0, data, size);
+                       if (!rc) {
+                               smb2_set_next_command(tcon, &rqst[num_rqst]);
+                               smb2_set_related(&rqst[num_rqst]);
+                       }
+               }
+
                if (rc)
                        goto finished;
-               smb2_set_next_command(tcon, &rqst[num_rqst]);
-               smb2_set_related(&rqst[num_rqst++]);
+               num_rqst++;
                trace_smb3_set_info_compound_enter(xid, ses->Suid, tcon->tid,
                                                   full_path);
                break;
@@ -210,14 +249,25 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
                size[1] = len + 2 /* null */;
                data[1] = (__le16 *)ptr;
 
-               rc = SMB2_set_info_init(tcon, &rqst[num_rqst], COMPOUND_FID,
-                                       COMPOUND_FID, current->tgid,
-                                       FILE_RENAME_INFORMATION,
+               if (cfile)
+                       rc = SMB2_set_info_init(tcon, &rqst[num_rqst],
+                                               cfile->fid.persistent_fid,
+                                               cfile->fid.volatile_fid,
+                                       current->tgid, FILE_RENAME_INFORMATION,
+                                       SMB2_O_INFO_FILE, 0, data, size);
+               else {
+                       rc = SMB2_set_info_init(tcon, &rqst[num_rqst],
+                                       COMPOUND_FID, COMPOUND_FID,
+                                       current->tgid, FILE_RENAME_INFORMATION,
                                        SMB2_O_INFO_FILE, 0, data, size);
+                       if (!rc) {
+                               smb2_set_next_command(tcon, &rqst[num_rqst]);
+                               smb2_set_related(&rqst[num_rqst]);
+                       }
+               }
                if (rc)
                        goto finished;
-               smb2_set_next_command(tcon, &rqst[num_rqst]);
-               smb2_set_related(&rqst[num_rqst++]);
+               num_rqst++;
                trace_smb3_rename_enter(xid, ses->Suid, tcon->tid, full_path);
                break;
        case SMB2_OP_HARDLINK:
@@ -254,21 +304,43 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
        if (rc)
                goto finished;
 
+       /* We already have a handle so we can skip the close */
+       if (cfile)
+               goto after_close;
        /* Close */
        memset(&close_iov, 0, sizeof(close_iov));
        rqst[num_rqst].rq_iov = close_iov;
        rqst[num_rqst].rq_nvec = 1;
        rc = SMB2_close_init(tcon, &rqst[num_rqst], COMPOUND_FID,
                             COMPOUND_FID);
-       smb2_set_related(&rqst[num_rqst++]);
+       smb2_set_related(&rqst[num_rqst]);
        if (rc)
                goto finished;
-
-       rc = compound_send_recv(xid, ses, flags, num_rqst, rqst,
-                               resp_buftype, rsp_iov);
+ after_close:
+       num_rqst++;
+
+       if (cfile) {
+               cifsFileInfo_put(cfile);
+               cfile = NULL;
+               rc = compound_send_recv(xid, ses, flags, num_rqst - 2,
+                                       &rqst[1], &resp_buftype[1],
+                                       &rsp_iov[1]);
+       } else
+               rc = compound_send_recv(xid, ses, flags, num_rqst,
+                                       rqst, resp_buftype,
+                                       rsp_iov);
 
  finished:
+       if (cfile)
+               cifsFileInfo_put(cfile);
+
        SMB2_open_free(&rqst[0]);
+       if (rc == -EREMCHG) {
+               printk_once(KERN_WARNING "server share %s deleted\n",
+                           tcon->treeName);
+               tcon->need_reconnect = true;
+       }
+
        switch (command) {
        case SMB2_OP_QUERY_INFO:
                if (rc == 0) {
@@ -371,6 +443,7 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
        __u32 create_options = 0;
        struct cifs_fid fid;
        bool no_cached_open = tcon->nohandlecache;
+       struct cifsFileInfo *cfile;
 
        *adjust_tz = false;
        *symlink = false;
@@ -402,9 +475,10 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
        if (backup_cred(cifs_sb))
                create_options |= CREATE_OPEN_BACKUP_INTENT;
 
+       cifs_get_readable_path(tcon, full_path, &cfile);
        rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
                              FILE_READ_ATTRIBUTES, FILE_OPEN, create_options,
-                             smb2_data, SMB2_OP_QUERY_INFO);
+                             smb2_data, SMB2_OP_QUERY_INFO, cfile);
        if (rc == -EOPNOTSUPP) {
                *symlink = true;
                create_options |= OPEN_REPARSE_POINT;
@@ -413,7 +487,7 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
                rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
                                      FILE_READ_ATTRIBUTES, FILE_OPEN,
                                      create_options, smb2_data,
-                                     SMB2_OP_QUERY_INFO);
+                                     SMB2_OP_QUERY_INFO, NULL);
        }
        if (rc)
                goto out;
@@ -430,7 +504,7 @@ smb2_mkdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
 {
        return smb2_compound_op(xid, tcon, cifs_sb, name,
                                FILE_WRITE_ATTRIBUTES, FILE_CREATE,
-                               CREATE_NOT_FILE, NULL, SMB2_OP_MKDIR);
+                               CREATE_NOT_FILE, NULL, SMB2_OP_MKDIR, NULL);
 }
 
 void
@@ -440,6 +514,7 @@ smb2_mkdir_setinfo(struct inode *inode, const char *name,
 {
        FILE_BASIC_INFO data;
        struct cifsInodeInfo *cifs_i;
+       struct cifsFileInfo *cfile;
        u32 dosattrs;
        int tmprc;
 
@@ -447,9 +522,11 @@ smb2_mkdir_setinfo(struct inode *inode, const char *name,
        cifs_i = CIFS_I(inode);
        dosattrs = cifs_i->cifsAttrs | ATTR_READONLY;
        data.Attributes = cpu_to_le32(dosattrs);
+       cifs_get_writable_path(tcon, name, &cfile);
        tmprc = smb2_compound_op(xid, tcon, cifs_sb, name,
                                 FILE_WRITE_ATTRIBUTES, FILE_CREATE,
-                                CREATE_NOT_FILE, &data, SMB2_OP_SET_INFO);
+                                CREATE_NOT_FILE, &data, SMB2_OP_SET_INFO,
+                                cfile);
        if (tmprc == 0)
                cifs_i->cifsAttrs = dosattrs;
 }
@@ -460,7 +537,7 @@ smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
 {
        return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
                                CREATE_NOT_FILE,
-                               NULL, SMB2_OP_RMDIR);
+                               NULL, SMB2_OP_RMDIR, NULL);
 }
 
 int
@@ -469,13 +546,14 @@ smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
 {
        return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
                                CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT,
-                               NULL, SMB2_OP_DELETE);
+                               NULL, SMB2_OP_DELETE, NULL);
 }
 
 static int
 smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
                   const char *from_name, const char *to_name,
-                  struct cifs_sb_info *cifs_sb, __u32 access, int command)
+                  struct cifs_sb_info *cifs_sb, __u32 access, int command,
+                  struct cifsFileInfo *cfile)
 {
        __le16 *smb2_to_name = NULL;
        int rc;
@@ -486,7 +564,7 @@ smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
                goto smb2_rename_path;
        }
        rc = smb2_compound_op(xid, tcon, cifs_sb, from_name, access,
-                             FILE_OPEN, 0, smb2_to_name, command);
+                             FILE_OPEN, 0, smb2_to_name, command, cfile);
 smb2_rename_path:
        kfree(smb2_to_name);
        return rc;
@@ -497,8 +575,12 @@ smb2_rename_path(const unsigned int xid, struct cifs_tcon *tcon,
                 const char *from_name, const char *to_name,
                 struct cifs_sb_info *cifs_sb)
 {
-       return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
-                                 DELETE, SMB2_OP_RENAME);
+       struct cifsFileInfo *cfile;
+
+       cifs_get_writable_path(tcon, from_name, &cfile);
+
+       return smb2_set_path_attr(xid, tcon, from_name, to_name,
+                                 cifs_sb, DELETE, SMB2_OP_RENAME, cfile);
 }
 
 int
@@ -507,7 +589,8 @@ smb2_create_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
                     struct cifs_sb_info *cifs_sb)
 {
        return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
-                                 FILE_READ_ATTRIBUTES, SMB2_OP_HARDLINK);
+                                 FILE_READ_ATTRIBUTES, SMB2_OP_HARDLINK,
+                                 NULL);
 }
 
 int
@@ -519,7 +602,7 @@ smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
 
        return smb2_compound_op(xid, tcon, cifs_sb, full_path,
                                FILE_WRITE_DATA, FILE_OPEN, 0, &eof,
-                               SMB2_OP_SET_EOF);
+                               SMB2_OP_SET_EOF, NULL);
 }
 
 int
@@ -541,7 +624,7 @@ smb2_set_file_info(struct inode *inode, const char *full_path,
 
        rc = smb2_compound_op(xid, tlink_tcon(tlink), cifs_sb, full_path,
                              FILE_WRITE_ATTRIBUTES, FILE_OPEN, 0, buf,
-                             SMB2_OP_SET_INFO);
+                             SMB2_OP_SET_INFO, NULL);
        cifs_put_tlink(tlink);
        return rc;
 }
index 82ade16c9501a2ffc160655d2816ff95b2a7769d..7fde3775cb5748c5202c0b2f8359c853969bfd0d 100644 (file)
@@ -511,7 +511,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
        {STATUS_PRINT_QUEUE_FULL, -EIO, "STATUS_PRINT_QUEUE_FULL"},
        {STATUS_NO_SPOOL_SPACE, -EIO, "STATUS_NO_SPOOL_SPACE"},
        {STATUS_PRINT_CANCELLED, -EIO, "STATUS_PRINT_CANCELLED"},
-       {STATUS_NETWORK_NAME_DELETED, -EIO, "STATUS_NETWORK_NAME_DELETED"},
+       {STATUS_NETWORK_NAME_DELETED, -EREMCHG, "STATUS_NETWORK_NAME_DELETED"},
        {STATUS_NETWORK_ACCESS_DENIED, -EACCES, "STATUS_NETWORK_ACCESS_DENIED"},
        {STATUS_BAD_DEVICE_TYPE, -EIO, "STATUS_BAD_DEVICE_TYPE"},
        {STATUS_BAD_NETWORK_NAME, -ENOENT, "STATUS_BAD_NETWORK_NAME"},
index 64a5864127be9154fead53d4188a15d3f7ddaf17..eaed180613143652c1f6ef21049da0056790b41b 100644 (file)
@@ -109,10 +109,10 @@ smb2_add_credits(struct TCP_Server_Info *server,
                /* change_conf hasn't been executed */
                break;
        case 0:
-               cifs_dbg(VFS, "Possible client or server bug - zero credits\n");
+               cifs_server_dbg(VFS, "Possible client or server bug - zero credits\n");
                break;
        case 1:
-               cifs_dbg(VFS, "disabling echoes and oplocks\n");
+               cifs_server_dbg(VFS, "disabling echoes and oplocks\n");
                break;
        case 2:
                cifs_dbg(FYI, "disabling oplocks\n");
@@ -203,6 +203,8 @@ smb2_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
                        credits->instance = server->reconnect_instance;
                        server->credits -= credits->value;
                        server->in_flight++;
+                       if (server->in_flight > server->max_in_flight)
+                               server->max_in_flight = server->in_flight;
                        break;
                }
        }
@@ -230,7 +232,7 @@ smb2_adjust_credits(struct TCP_Server_Info *server,
 
        if (server->reconnect_instance != credits->instance) {
                spin_unlock(&server->req_lock);
-               cifs_dbg(VFS, "trying to return %d credits to old session\n",
+               cifs_server_dbg(VFS, "trying to return %d credits to old session\n",
                         credits->value - new_val);
                return -EAGAIN;
        }
@@ -270,7 +272,7 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf)
        __u64 wire_mid = le64_to_cpu(shdr->MessageId);
 
        if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
-               cifs_dbg(VFS, "Encrypted frame parsing not supported yet\n");
+               cifs_server_dbg(VFS, "Encrypted frame parsing not supported yet\n");
                return NULL;
        }
 
@@ -294,10 +296,10 @@ smb2_dump_detail(void *buf, struct TCP_Server_Info *server)
 #ifdef CONFIG_CIFS_DEBUG2
        struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
 
-       cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n",
+       cifs_server_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n",
                 shdr->Command, shdr->Status, shdr->Flags, shdr->MessageId,
                 shdr->ProcessId);
-       cifs_dbg(VFS, "smb buf %p len %u\n", buf,
+       cifs_server_dbg(VFS, "smb buf %p len %u\n", buf,
                 server->ops->calc_smb_size(buf, server));
 #endif
 }
@@ -576,7 +578,7 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon)
                         "server does not support query network interfaces\n");
                goto out;
        } else if (rc != 0) {
-               cifs_dbg(VFS, "error %d on ioctl to get interface list\n", rc);
+               cifs_tcon_dbg(VFS, "error %d on ioctl to get interface list\n", rc);
                goto out;
        }
 
@@ -656,6 +658,15 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid)
                return 0;
        }
 
+       /*
+        * We do not hold the lock for the open because in case
+        * SMB2_open needs to reconnect, it will end up calling
+        * cifs_mark_open_files_invalid() which takes the lock again
+        * thus causing a deadlock
+        */
+
+       mutex_unlock(&tcon->crfid.fid_mutex);
+
        if (smb3_encryption_required(tcon))
                flags |= CIFS_TRANSFORM_REQ;
 
@@ -677,7 +688,7 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid)
 
        rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, &utf16_path);
        if (rc)
-               goto oshr_exit;
+               goto oshr_free;
        smb2_set_next_command(tcon, &rqst[0]);
 
        memset(&qi_iov, 0, sizeof(qi_iov));
@@ -690,18 +701,10 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid)
                                  sizeof(struct smb2_file_all_info) +
                                  PATH_MAX * 2, 0, NULL);
        if (rc)
-               goto oshr_exit;
+               goto oshr_free;
 
        smb2_set_related(&rqst[1]);
 
-       /*
-        * We do not hold the lock for the open because in case
-        * SMB2_open needs to reconnect, it will end up calling
-        * cifs_mark_open_files_invalid() which takes the lock again
-        * thus causing a deadlock
-        */
-
-       mutex_unlock(&tcon->crfid.fid_mutex);
        rc = compound_send_recv(xid, ses, flags, 2, rqst,
                                resp_buftype, rsp_iov);
        mutex_lock(&tcon->crfid.fid_mutex);
@@ -739,8 +742,14 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid)
 
        /* Cached root is still invalid, continue normaly */
 
-       if (rc)
+       if (rc) {
+               if (rc == -EREMCHG) {
+                       tcon->need_reconnect = true;
+                       printk_once(KERN_WARNING "server share %s deleted\n",
+                                   tcon->treeName);
+               }
                goto oshr_exit;
+       }
 
        o_rsp = (struct smb2_create_rsp *)rsp_iov[0].iov_base;
        oparms.fid->persistent_fid = o_rsp->PersistentFileId;
@@ -1330,11 +1339,11 @@ SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon,
                        (char **)&res_key, &ret_data_len);
 
        if (rc) {
-               cifs_dbg(VFS, "refcpy ioctl error %d getting resume key\n", rc);
+               cifs_tcon_dbg(VFS, "refcpy ioctl error %d getting resume key\n", rc);
                goto req_res_key_exit;
        }
        if (ret_data_len < sizeof(struct resume_key_req)) {
-               cifs_dbg(VFS, "Invalid refcopy resume key length\n");
+               cifs_tcon_dbg(VFS, "Invalid refcopy resume key length\n");
                rc = -EINVAL;
                goto req_res_key_exit;
        }
@@ -1369,7 +1378,10 @@ smb2_ioctl_query_info(const unsigned int xid,
        struct cifs_fid fid;
        struct kvec qi_iov[1];
        struct kvec io_iov[SMB2_IOCTL_IOV_SIZE];
+       struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE];
        struct kvec close_iov[1];
+       unsigned int size[2];
+       void *data[2];
 
        memset(rqst, 0, sizeof(rqst));
        resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
@@ -1404,7 +1416,6 @@ smb2_ioctl_query_info(const unsigned int xid,
 
        memset(&oparms, 0, sizeof(oparms));
        oparms.tcon = tcon;
-       oparms.desired_access = FILE_READ_ATTRIBUTES | READ_CONTROL;
        oparms.disposition = FILE_OPEN;
        if (is_dir)
                oparms.create_options = CREATE_NOT_FILE;
@@ -1413,9 +1424,6 @@ smb2_ioctl_query_info(const unsigned int xid,
        oparms.fid = &fid;
        oparms.reconnect = false;
 
-       /*
-        * FSCTL codes encode the special access they need in the fsctl code.
-        */
        if (qi.flags & PASSTHRU_FSCTL) {
                switch (qi.info_type & FSCTL_DEVICE_ACCESS_MASK) {
                case FSCTL_DEVICE_ACCESS_FILE_READ_WRITE_ACCESS:
@@ -1431,6 +1439,10 @@ smb2_ioctl_query_info(const unsigned int xid,
                        oparms.desired_access = GENERIC_WRITE;
                        break;
                }
+       } else if (qi.flags & PASSTHRU_SET_INFO) {
+               oparms.desired_access = GENERIC_WRITE;
+       } else {
+               oparms.desired_access = FILE_READ_ATTRIBUTES | READ_CONTROL;
        }
 
        rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, path);
@@ -1454,6 +1466,24 @@ smb2_ioctl_query_info(const unsigned int xid,
                                             qi.output_buffer_length,
                                             CIFSMaxBufSize);
                }
+       } else if (qi.flags == PASSTHRU_SET_INFO) {
+               /* Can eventually relax perm check since server enforces too */
+               if (!capable(CAP_SYS_ADMIN))
+                       rc = -EPERM;
+               else  {
+                       memset(&si_iov, 0, sizeof(si_iov));
+                       rqst[1].rq_iov = si_iov;
+                       rqst[1].rq_nvec = 1;
+
+                       size[0] = 8;
+                       data[0] = buffer;
+
+                       rc = SMB2_set_info_init(tcon, &rqst[1],
+                                       COMPOUND_FID, COMPOUND_FID,
+                                       current->tgid,
+                                       FILE_END_OF_FILE_INFORMATION,
+                                       SMB2_O_INFO_FILE, 0, data, size);
+               }
        } else if (qi.flags == PASSTHRU_QUERY_INFO) {
                memset(&qi_iov, 0, sizeof(qi_iov));
                rqst[1].rq_iov = qi_iov;
@@ -1465,7 +1495,7 @@ smb2_ioctl_query_info(const unsigned int xid,
                                  qi.input_buffer_length,
                                  qi.output_buffer_length, buffer);
        } else { /* unknown flags */
-               cifs_dbg(VFS, "invalid passthru query flags: 0x%x\n", qi.flags);
+               cifs_tcon_dbg(VFS, "invalid passthru query flags: 0x%x\n", qi.flags);
                rc = -EINVAL;
        }
 
@@ -1592,7 +1622,7 @@ smb2_copychunk_range(const unsigned int xid,
                if (rc == 0) {
                        if (ret_data_len !=
                                        sizeof(struct copychunk_ioctl_rsp)) {
-                               cifs_dbg(VFS, "invalid cchunk response size\n");
+                               cifs_tcon_dbg(VFS, "invalid cchunk response size\n");
                                rc = -EIO;
                                goto cchunk_out;
                        }
@@ -1606,12 +1636,12 @@ smb2_copychunk_range(const unsigned int xid,
                         */
                        if (le32_to_cpu(retbuf->TotalBytesWritten) >
                            le32_to_cpu(pcchunk->Length)) {
-                               cifs_dbg(VFS, "invalid copy chunk response\n");
+                               cifs_tcon_dbg(VFS, "invalid copy chunk response\n");
                                rc = -EIO;
                                goto cchunk_out;
                        }
                        if (le32_to_cpu(retbuf->ChunksWritten) != 1) {
-                               cifs_dbg(VFS, "invalid num chunks written\n");
+                               cifs_tcon_dbg(VFS, "invalid num chunks written\n");
                                rc = -EIO;
                                goto cchunk_out;
                        }
@@ -2214,6 +2244,11 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
                                resp_buftype, rsp_iov);
        if (rc) {
                free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
+               if (rc == -EREMCHG) {
+                       tcon->need_reconnect = true;
+                       printk_once(KERN_WARNING "server share %s deleted\n",
+                                   tcon->treeName);
+               }
                goto qic_exit;
        }
        *rsp = rsp_iov[1];
@@ -2401,7 +2436,7 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
 
        if (rc) {
                if ((rc != -ENOENT) && (rc != -EOPNOTSUPP))
-                       cifs_dbg(VFS, "ioctl error in %s rc=%d\n", __func__, rc);
+                       cifs_tcon_dbg(VFS, "ioctl error in %s rc=%d\n", __func__, rc);
                goto out;
        }
 
@@ -2410,7 +2445,7 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
                                 nls_codepage, remap, search_name,
                                 true /* is_unicode */);
        if (rc) {
-               cifs_dbg(VFS, "parse error in %s rc=%d\n", __func__, rc);
+               cifs_tcon_dbg(VFS, "parse error in %s rc=%d\n", __func__, rc);
                goto out;
        }
 
@@ -2640,7 +2675,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
 
                if (plen + le32_to_cpu(ioctl_rsp->OutputOffset) >
                    rsp_iov[1].iov_len) {
-                       cifs_dbg(VFS, "srv returned invalid ioctl len: %d\n",
+                       cifs_tcon_dbg(VFS, "srv returned invalid ioctl len: %d\n",
                                 plen);
                        rc = -EIO;
                        goto querty_exit;
@@ -2939,7 +2974,6 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
                            loff_t offset, loff_t len)
 {
        struct inode *inode;
-       struct cifsInodeInfo *cifsi;
        struct cifsFileInfo *cfile = file->private_data;
        struct file_zero_data_information fsctl_buf;
        long rc;
@@ -2949,7 +2983,6 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
        xid = get_xid();
 
        inode = d_inode(cfile->dentry);
-       cifsi = CIFS_I(inode);
 
        /* Need to make file sparse, if not already, before freeing range. */
        /* Consider adding equivalent for compressed since it could also work */
@@ -3595,14 +3628,14 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
 
        rc = smb2_get_enc_key(server, tr_hdr->SessionId, enc, key);
        if (rc) {
-               cifs_dbg(VFS, "%s: Could not get %scryption key\n", __func__,
+               cifs_server_dbg(VFS, "%s: Could not get %scryption key\n", __func__,
                         enc ? "en" : "de");
                return 0;
        }
 
        rc = smb3_crypto_aead_allocate(server);
        if (rc) {
-               cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__);
+               cifs_server_dbg(VFS, "%s: crypto alloc failed\n", __func__);
                return rc;
        }
 
@@ -3610,19 +3643,19 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
                                                server->secmech.ccmaesdecrypt;
        rc = crypto_aead_setkey(tfm, key, SMB3_SIGN_KEY_SIZE);
        if (rc) {
-               cifs_dbg(VFS, "%s: Failed to set aead key %d\n", __func__, rc);
+               cifs_server_dbg(VFS, "%s: Failed to set aead key %d\n", __func__, rc);
                return rc;
        }
 
        rc = crypto_aead_setauthsize(tfm, SMB2_SIGNATURE_SIZE);
        if (rc) {
-               cifs_dbg(VFS, "%s: Failed to set authsize %d\n", __func__, rc);
+               cifs_server_dbg(VFS, "%s: Failed to set authsize %d\n", __func__, rc);
                return rc;
        }
 
        req = aead_request_alloc(tfm, GFP_KERNEL);
        if (!req) {
-               cifs_dbg(VFS, "%s: Failed to alloc aead request\n", __func__);
+               cifs_server_dbg(VFS, "%s: Failed to alloc aead request\n", __func__);
                return -ENOMEM;
        }
 
@@ -3633,7 +3666,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
 
        sg = init_sg(num_rqst, rqst, sign);
        if (!sg) {
-               cifs_dbg(VFS, "%s: Failed to init sg\n", __func__);
+               cifs_server_dbg(VFS, "%s: Failed to init sg\n", __func__);
                rc = -ENOMEM;
                goto free_req;
        }
@@ -3641,7 +3674,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
        iv_len = crypto_aead_ivsize(tfm);
        iv = kzalloc(iv_len, GFP_KERNEL);
        if (!iv) {
-               cifs_dbg(VFS, "%s: Failed to alloc iv\n", __func__);
+               cifs_server_dbg(VFS, "%s: Failed to alloc iv\n", __func__);
                rc = -ENOMEM;
                goto free_sg;
        }
@@ -3883,7 +3916,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
        bool use_rdma_mr = false;
 
        if (shdr->Command != SMB2_READ) {
-               cifs_dbg(VFS, "only big read responses are supported\n");
+               cifs_server_dbg(VFS, "only big read responses are supported\n");
                return -ENOTSUPP;
        }
 
@@ -3998,8 +4031,55 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
        return length;
 }
 
+struct smb2_decrypt_work {
+       struct work_struct decrypt;
+       struct TCP_Server_Info *server;
+       struct page **ppages;
+       char *buf;
+       unsigned int npages;
+       unsigned int len;
+};
+
+
+static void smb2_decrypt_offload(struct work_struct *work)
+{
+       struct smb2_decrypt_work *dw = container_of(work,
+                               struct smb2_decrypt_work, decrypt);
+       int i, rc;
+       struct mid_q_entry *mid;
+
+       rc = decrypt_raw_data(dw->server, dw->buf, dw->server->vals->read_rsp_size,
+                             dw->ppages, dw->npages, dw->len);
+       if (rc) {
+               cifs_dbg(VFS, "error decrypting rc=%d\n", rc);
+               goto free_pages;
+       }
+
+       dw->server->lstrp = jiffies;
+       mid = smb2_find_mid(dw->server, dw->buf);
+       if (mid == NULL)
+               cifs_dbg(FYI, "mid not found\n");
+       else {
+               mid->decrypted = true;
+               rc = handle_read_data(dw->server, mid, dw->buf,
+                                     dw->server->vals->read_rsp_size,
+                                     dw->ppages, dw->npages, dw->len);
+               mid->callback(mid);
+               cifs_mid_q_entry_release(mid);
+       }
+
+free_pages:
+       for (i = dw->npages-1; i >= 0; i--)
+               put_page(dw->ppages[i]);
+
+       kfree(dw->ppages);
+       cifs_small_buf_release(dw->buf);
+}
+
+
 static int
-receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)
+receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid,
+                      int *num_mids)
 {
        char *buf = server->smallbuf;
        struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf;
@@ -4009,7 +4089,9 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)
        unsigned int buflen = server->pdu_size;
        int rc;
        int i = 0;
+       struct smb2_decrypt_work *dw;
 
+       *num_mids = 1;
        len = min_t(unsigned int, buflen, server->vals->read_rsp_size +
                sizeof(struct smb2_transform_hdr)) - HEADER_SIZE(server) + 1;
 
@@ -4045,6 +4127,32 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)
        if (rc)
                goto free_pages;
 
+       /*
+        * For large reads, offload to different thread for better performance,
+        * use more cores decrypting which can be expensive
+        */
+
+       if ((server->min_offload) && (server->in_flight > 1) &&
+           (server->pdu_size >= server->min_offload)) {
+               dw = kmalloc(sizeof(struct smb2_decrypt_work), GFP_KERNEL);
+               if (dw == NULL)
+                       goto non_offloaded_decrypt;
+
+               dw->buf = server->smallbuf;
+               server->smallbuf = (char *)cifs_small_buf_get();
+
+               INIT_WORK(&dw->decrypt, smb2_decrypt_offload);
+
+               dw->npages = npages;
+               dw->server = server;
+               dw->ppages = pages;
+               dw->len = len;
+               queue_work(cifsiod_wq, &dw->decrypt);
+               *num_mids = 0; /* worker thread takes care of finding mid */
+               return -1;
+       }
+
+non_offloaded_decrypt:
        rc = decrypt_raw_data(server, buf, server->vals->read_rsp_size,
                              pages, npages, len);
        if (rc)
@@ -4129,7 +4237,7 @@ one_more:
        }
 
        if (*num_mids >= MAX_COMPOUND) {
-               cifs_dbg(VFS, "too many PDUs in compound\n");
+               cifs_server_dbg(VFS, "too many PDUs in compound\n");
                return -1;
        }
        bufs[*num_mids] = buf;
@@ -4175,7 +4283,7 @@ smb3_receive_transform(struct TCP_Server_Info *server,
 
        if (pdu_length < sizeof(struct smb2_transform_hdr) +
                                                sizeof(struct smb2_sync_hdr)) {
-               cifs_dbg(VFS, "Transform message is too small (%u)\n",
+               cifs_server_dbg(VFS, "Transform message is too small (%u)\n",
                         pdu_length);
                cifs_reconnect(server);
                wake_up(&server->response_q);
@@ -4183,7 +4291,7 @@ smb3_receive_transform(struct TCP_Server_Info *server,
        }
 
        if (pdu_length < orig_len + sizeof(struct smb2_transform_hdr)) {
-               cifs_dbg(VFS, "Transform message is broken\n");
+               cifs_server_dbg(VFS, "Transform message is broken\n");
                cifs_reconnect(server);
                wake_up(&server->response_q);
                return -ECONNABORTED;
@@ -4191,8 +4299,7 @@ smb3_receive_transform(struct TCP_Server_Info *server,
 
        /* TODO: add support for compounds containing READ. */
        if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server)) {
-               *num_mids = 1;
-               return receive_encrypted_read(server, &mids[0]);
+               return receive_encrypted_read(server, &mids[0], num_mids);
        }
 
        return receive_encrypted_standard(server, mids, bufs, num_mids);
index 31e4a1b0b1704b90e9ed8f0cdb123477933fb369..87066f1af12c0ccbc8451205efca24df34037940 100644 (file)
@@ -503,8 +503,7 @@ build_netname_ctxt(struct smb2_netname_neg_context *pneg_ctxt, char *hostname)
        pneg_ctxt->ContextType = SMB2_NETNAME_NEGOTIATE_CONTEXT_ID;
 
        /* copy up to max of first 100 bytes of server name to NetName field */
-       pneg_ctxt->DataLength = cpu_to_le16(2 +
-               (2 * cifs_strtoUTF16(pneg_ctxt->NetName, hostname, 100, cp)));
+       pneg_ctxt->DataLength = cpu_to_le16(2 * cifs_strtoUTF16(pneg_ctxt->NetName, hostname, 100, cp));
        /* context size is DataLength + minimal smb2_neg_context */
        return DIV_ROUND_UP(le16_to_cpu(pneg_ctxt->DataLength) +
                        sizeof(struct smb2_neg_context), 8) * 8;
@@ -543,7 +542,7 @@ assemble_neg_contexts(struct smb2_negotiate_req *req,
 
        if (*total_len > 200) {
                /* In case length corrupted don't want to overrun smb buffer */
-               cifs_dbg(VFS, "Bad frame length assembling neg contexts\n");
+               cifs_server_dbg(VFS, "Bad frame length assembling neg contexts\n");
                return;
        }
 
@@ -661,7 +660,7 @@ static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp,
 
        cifs_dbg(FYI, "decoding %d negotiate contexts\n", ctxt_cnt);
        if (len_of_smb <= offset) {
-               cifs_dbg(VFS, "Invalid response: negotiate context offset\n");
+               cifs_server_dbg(VFS, "Invalid response: negotiate context offset\n");
                return -EINVAL;
        }
 
@@ -693,7 +692,7 @@ static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp,
                else if (pctx->ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE)
                        server->posix_ext_supported = true;
                else
-                       cifs_dbg(VFS, "unknown negcontext of type %d ignored\n",
+                       cifs_server_dbg(VFS, "unknown negcontext of type %d ignored\n",
                                le16_to_cpu(pctx->ContextType));
 
                if (rc)
@@ -818,7 +817,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
                req->Dialects[1] = cpu_to_le16(SMB302_PROT_ID);
                req->DialectCount = cpu_to_le16(2);
                total_len += 4;
-       } else if (strcmp(ses->server->vals->version_string,
+       } else if (strcmp(server->vals->version_string,
                   SMBDEFAULT_VERSION_STRING) == 0) {
                req->Dialects[0] = cpu_to_le16(SMB21_PROT_ID);
                req->Dialects[1] = cpu_to_le16(SMB30_PROT_ID);
@@ -841,16 +840,16 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
        else
                req->SecurityMode = 0;
 
-       req->Capabilities = cpu_to_le32(ses->server->vals->req_capabilities);
+       req->Capabilities = cpu_to_le32(server->vals->req_capabilities);
 
        /* ClientGUID must be zero for SMB2.02 dialect */
-       if (ses->server->vals->protocol_id == SMB20_PROT_ID)
+       if (server->vals->protocol_id == SMB20_PROT_ID)
                memset(req->ClientGUID, 0, SMB2_CLIENT_GUID_SIZE);
        else {
                memcpy(req->ClientGUID, server->client_guid,
                        SMB2_CLIENT_GUID_SIZE);
-               if ((ses->server->vals->protocol_id == SMB311_PROT_ID) ||
-                   (strcmp(ses->server->vals->version_string,
+               if ((server->vals->protocol_id == SMB311_PROT_ID) ||
+                   (strcmp(server->vals->version_string,
                     SMBDEFAULT_VERSION_STRING) == 0))
                        assemble_neg_contexts(req, server, &total_len);
        }
@@ -869,42 +868,42 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
         * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
         */
        if (rc == -EOPNOTSUPP) {
-               cifs_dbg(VFS, "Dialect not supported by server. Consider "
+               cifs_server_dbg(VFS, "Dialect not supported by server. Consider "
                        "specifying vers=1.0 or vers=2.0 on mount for accessing"
                        " older servers\n");
                goto neg_exit;
        } else if (rc != 0)
                goto neg_exit;
 
-       if (strcmp(ses->server->vals->version_string,
+       if (strcmp(server->vals->version_string,
                   SMB3ANY_VERSION_STRING) == 0) {
                if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) {
-                       cifs_dbg(VFS,
+                       cifs_server_dbg(VFS,
                                "SMB2 dialect returned but not requested\n");
                        return -EIO;
                } else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) {
-                       cifs_dbg(VFS,
+                       cifs_server_dbg(VFS,
                                "SMB2.1 dialect returned but not requested\n");
                        return -EIO;
                }
-       } else if (strcmp(ses->server->vals->version_string,
+       } else if (strcmp(server->vals->version_string,
                   SMBDEFAULT_VERSION_STRING) == 0) {
                if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) {
-                       cifs_dbg(VFS,
+                       cifs_server_dbg(VFS,
                                "SMB2 dialect returned but not requested\n");
                        return -EIO;
                } else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) {
                        /* ops set to 3.0 by default for default so update */
-                       ses->server->ops = &smb21_operations;
-                       ses->server->vals = &smb21_values;
+                       server->ops = &smb21_operations;
+                       server->vals = &smb21_values;
                } else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) {
-                       ses->server->ops = &smb311_operations;
-                       ses->server->vals = &smb311_values;
+                       server->ops = &smb311_operations;
+                       server->vals = &smb311_values;
                }
        } else if (le16_to_cpu(rsp->DialectRevision) !=
-                               ses->server->vals->protocol_id) {
+                               server->vals->protocol_id) {
                /* if requested single dialect ensure returned dialect matched */
-               cifs_dbg(VFS, "Illegal 0x%x dialect returned: not requested\n",
+               cifs_server_dbg(VFS, "Illegal 0x%x dialect returned: not requested\n",
                        le16_to_cpu(rsp->DialectRevision));
                return -EIO;
        }
@@ -922,7 +921,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
        else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID))
                cifs_dbg(FYI, "negotiated smb3.1.1 dialect\n");
        else {
-               cifs_dbg(VFS, "Illegal dialect returned by server 0x%x\n",
+               cifs_server_dbg(VFS, "Illegal dialect returned by server 0x%x\n",
                         le16_to_cpu(rsp->DialectRevision));
                rc = -EIO;
                goto neg_exit;
@@ -982,7 +981,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
                        rc = smb311_decode_neg_context(rsp, server,
                                                       rsp_iov.iov_len);
                else
-                       cifs_dbg(VFS, "Missing expected negotiate contexts\n");
+                       cifs_server_dbg(VFS, "Missing expected negotiate contexts\n");
        }
 neg_exit:
        free_rsp_buf(resp_buftype, rsp);
@@ -996,11 +995,12 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
        struct validate_negotiate_info_rsp *pneg_rsp = NULL;
        u32 rsplen;
        u32 inbuflen; /* max of 4 dialects */
+       struct TCP_Server_Info *server = tcon->ses->server;
 
        cifs_dbg(FYI, "validate negotiate\n");
 
        /* In SMB3.11 preauth integrity supersedes validate negotiate */
-       if (tcon->ses->server->dialect == SMB311_PROT_ID)
+       if (server->dialect == SMB311_PROT_ID)
                return 0;
 
        /*
@@ -1019,15 +1019,15 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
        }
 
        if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_NULL)
-               cifs_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server\n");
+               cifs_tcon_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server\n");
 
        pneg_inbuf = kmalloc(sizeof(*pneg_inbuf), GFP_NOFS);
        if (!pneg_inbuf)
                return -ENOMEM;
 
        pneg_inbuf->Capabilities =
-                       cpu_to_le32(tcon->ses->server->vals->req_capabilities);
-       memcpy(pneg_inbuf->Guid, tcon->ses->server->client_guid,
+                       cpu_to_le32(server->vals->req_capabilities);
+       memcpy(pneg_inbuf->Guid, server->client_guid,
                                        SMB2_CLIENT_GUID_SIZE);
 
        if (tcon->ses->sign)
@@ -1040,7 +1040,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
                pneg_inbuf->SecurityMode = 0;
 
 
-       if (strcmp(tcon->ses->server->vals->version_string,
+       if (strcmp(server->vals->version_string,
                SMB3ANY_VERSION_STRING) == 0) {
                pneg_inbuf->Dialects[0] = cpu_to_le16(SMB30_PROT_ID);
                pneg_inbuf->Dialects[1] = cpu_to_le16(SMB302_PROT_ID);
@@ -1048,7 +1048,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
                /* structure is big enough for 3 dialects, sending only 2 */
                inbuflen = sizeof(*pneg_inbuf) -
                                (2 * sizeof(pneg_inbuf->Dialects[0]));
-       } else if (strcmp(tcon->ses->server->vals->version_string,
+       } else if (strcmp(server->vals->version_string,
                SMBDEFAULT_VERSION_STRING) == 0) {
                pneg_inbuf->Dialects[0] = cpu_to_le16(SMB21_PROT_ID);
                pneg_inbuf->Dialects[1] = cpu_to_le16(SMB30_PROT_ID);
@@ -1060,7 +1060,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
        } else {
                /* otherwise specific dialect was requested */
                pneg_inbuf->Dialects[0] =
-                       cpu_to_le16(tcon->ses->server->vals->protocol_id);
+                       cpu_to_le16(server->vals->protocol_id);
                pneg_inbuf->DialectCount = cpu_to_le16(1);
                /* structure is big enough for 3 dialects, sending only 1 */
                inbuflen = sizeof(*pneg_inbuf) -
@@ -1076,18 +1076,18 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
                 * Old Windows versions or Netapp SMB server can return
                 * not supported error. Client should accept it.
                 */
-               cifs_dbg(VFS, "Server does not support validate negotiate\n");
+               cifs_tcon_dbg(VFS, "Server does not support validate negotiate\n");
                rc = 0;
                goto out_free_inbuf;
        } else if (rc != 0) {
-               cifs_dbg(VFS, "validate protocol negotiate failed: %d\n", rc);
+               cifs_tcon_dbg(VFS, "validate protocol negotiate failed: %d\n", rc);
                rc = -EIO;
                goto out_free_inbuf;
        }
 
        rc = -EIO;
        if (rsplen != sizeof(*pneg_rsp)) {
-               cifs_dbg(VFS, "invalid protocol negotiate response size: %d\n",
+               cifs_tcon_dbg(VFS, "invalid protocol negotiate response size: %d\n",
                         rsplen);
 
                /* relax check since Mac returns max bufsize allowed on ioctl */
@@ -1096,16 +1096,16 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
        }
 
        /* check validate negotiate info response matches what we got earlier */
-       if (pneg_rsp->Dialect != cpu_to_le16(tcon->ses->server->dialect))
+       if (pneg_rsp->Dialect != cpu_to_le16(server->dialect))
                goto vneg_out;
 
-       if (pneg_rsp->SecurityMode != cpu_to_le16(tcon->ses->server->sec_mode))
+       if (pneg_rsp->SecurityMode != cpu_to_le16(server->sec_mode))
                goto vneg_out;
 
        /* do not validate server guid because not saved at negprot time yet */
 
        if ((le32_to_cpu(pneg_rsp->Capabilities) | SMB2_NT_FIND |
-             SMB2_LARGE_FILES) != tcon->ses->server->capabilities)
+             SMB2_LARGE_FILES) != server->capabilities)
                goto vneg_out;
 
        /* validate negotiate successful */
@@ -1114,7 +1114,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
        goto out_free_rsp;
 
 vneg_out:
-       cifs_dbg(VFS, "protocol revalidation - security settings mismatch\n");
+       cifs_tcon_dbg(VFS, "protocol revalidation - security settings mismatch\n");
 out_free_rsp:
        kfree(pneg_rsp);
 out_free_inbuf:
@@ -1568,7 +1568,7 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
                sess_data->func(sess_data);
 
        if ((ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST) && (ses->sign))
-               cifs_dbg(VFS, "signing requested but authenticated as guest\n");
+               cifs_server_dbg(VFS, "signing requested but authenticated as guest\n");
        rc = sess_data->result;
 out:
        kfree(sess_data);
@@ -1661,10 +1661,11 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
        __le16 *unc_path = NULL;
        int flags = 0;
        unsigned int total_len;
+       struct TCP_Server_Info *server = ses->server;
 
        cifs_dbg(FYI, "TCON\n");
 
-       if (!(ses->server) || !tree)
+       if (!server || !tree)
                return -EIO;
 
        unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL);
@@ -1707,7 +1708,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
         * unless it is guest or anonymous user. See MS-SMB2 3.2.5.3.1
         * (Samba servers don't always set the flag so also check if null user)
         */
-       if ((ses->server->dialect == SMB311_PROT_ID) &&
+       if ((server->dialect == SMB311_PROT_ID) &&
            !smb3_encryption_required(tcon) &&
            !(ses->session_flags &
                    (SMB2_SESSION_FLAG_IS_GUEST|SMB2_SESSION_FLAG_IS_NULL)) &&
@@ -1746,7 +1747,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
                cifs_dbg(FYI, "connection to printer\n");
                break;
        default:
-               cifs_dbg(VFS, "unknown share type %d\n", rsp->ShareType);
+               cifs_server_dbg(VFS, "unknown share type %d\n", rsp->ShareType);
                rc = -EOPNOTSUPP;
                goto tcon_error_exit;
        }
@@ -1761,15 +1762,15 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
 
        if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) &&
            ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0))
-               cifs_dbg(VFS, "DFS capability contradicts DFS flag\n");
+               cifs_tcon_dbg(VFS, "DFS capability contradicts DFS flag\n");
 
        if (tcon->seal &&
-           !(tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
-               cifs_dbg(VFS, "Encryption is requested but not supported\n");
+           !(server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
+               cifs_tcon_dbg(VFS, "Encryption is requested but not supported\n");
 
        init_copy_chunk_defaults(tcon);
-       if (tcon->ses->server->ops->validate_negotiate)
-               rc = tcon->ses->server->ops->validate_negotiate(xid, tcon);
+       if (server->ops->validate_negotiate)
+               rc = server->ops->validate_negotiate(xid, tcon);
 tcon_exit:
 
        free_rsp_buf(resp_buftype, rsp);
@@ -1778,7 +1779,7 @@ tcon_exit:
 
 tcon_error_exit:
        if (rsp && rsp->sync_hdr.Status == STATUS_BAD_NETWORK_NAME) {
-               cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree);
+               cifs_tcon_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree);
        }
        goto tcon_exit;
 }
@@ -2458,7 +2459,7 @@ SMB2_open_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, __u8 *oplock,
        iov[1].iov_len = uni_path_len;
        iov[1].iov_base = path;
 
-       if (!server->oplocks)
+       if ((!server->oplocks) || (tcon->no_lease))
                *oplock = SMB2_OPLOCK_LEVEL_NONE;
 
        if (!(server->capabilities & SMB2_GLOBAL_CAP_LEASING) ||
@@ -2594,6 +2595,11 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
                }
                trace_smb3_open_err(xid, tcon->tid, ses->Suid,
                                    oparms->create_options, oparms->desired_access, rc);
+               if (rc == -EREMCHG) {
+                       printk_once(KERN_WARNING "server share %s deleted\n",
+                                   tcon->treeName);
+                       tcon->need_reconnect = true;
+               }
                goto creat_exit;
        } else
                trace_smb3_open_done(xid, rsp->PersistentFileId, tcon->tid,
@@ -2742,6 +2748,7 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
        int resp_buftype = CIFS_NO_BUFFER;
        int rc = 0;
        int flags = 0;
+       struct TCP_Server_Info *server;
 
        cifs_dbg(FYI, "SMB2 IOCTL\n");
 
@@ -2757,7 +2764,10 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
        else
                return -EIO;
 
-       if (!ses || !(ses->server))
+       if (!ses)
+               return -EIO;
+       server = ses->server;
+       if (!server)
                return -EIO;
 
        if (smb3_encryption_required(tcon))
@@ -2807,14 +2817,14 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
        if (*plen == 0)
                goto ioctl_exit; /* server returned no data */
        else if (*plen > rsp_iov.iov_len || *plen > 0xFF00) {
-               cifs_dbg(VFS, "srv returned invalid ioctl length: %d\n", *plen);
+               cifs_tcon_dbg(VFS, "srv returned invalid ioctl length: %d\n", *plen);
                *plen = 0;
                rc = -EIO;
                goto ioctl_exit;
        }
 
        if (rsp_iov.iov_len - *plen < le32_to_cpu(rsp->OutputOffset)) {
-               cifs_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen,
+               cifs_tcon_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen,
                        le32_to_cpu(rsp->OutputOffset));
                *plen = 0;
                rc = -EIO;
@@ -2913,6 +2923,7 @@ SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon,
        rqst.rq_iov = iov;
        rqst.rq_nvec = 1;
 
+       trace_smb3_close_enter(xid, persistent_fid, tcon->tid, ses->Suid);
        rc = SMB2_close_init(tcon, &rqst, persistent_fid, volatile_fid);
        if (rc)
                goto close_exit;
@@ -2925,7 +2936,9 @@ SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon,
                trace_smb3_close_err(xid, persistent_fid, tcon->tid, ses->Suid,
                                     rc);
                goto close_exit;
-       }
+       } else
+               trace_smb3_close_done(xid, persistent_fid, tcon->tid,
+                                     ses->Suid);
 
        atomic_dec(&tcon->num_remote_opens);
 
@@ -3055,12 +3068,16 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
        int rc = 0;
        int resp_buftype = CIFS_NO_BUFFER;
        struct cifs_ses *ses = tcon->ses;
+       struct TCP_Server_Info *server;
        int flags = 0;
        bool allocated = false;
 
        cifs_dbg(FYI, "Query Info\n");
 
-       if (!ses || !(ses->server))
+       if (!ses)
+               return -EIO;
+       server = ses->server;
+       if (!server)
                return -EIO;
 
        if (smb3_encryption_required(tcon))
@@ -3098,7 +3115,7 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
                if (!*data) {
                        *data = kmalloc(*dlen, GFP_KERNEL);
                        if (!*data) {
-                               cifs_dbg(VFS,
+                               cifs_tcon_dbg(VFS,
                                        "Error %d allocating memory for acl\n",
                                        rc);
                                *dlen = 0;
@@ -3158,6 +3175,91 @@ SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon,
                          (void **)&uniqueid, NULL);
 }
 
+/*
+ * CHANGE_NOTIFY Request is sent to get notifications on changes to a directory
+ * See MS-SMB2 2.2.35 and 2.2.36
+ */
+
+int
+SMB2_notify_init(const unsigned int xid, struct smb_rqst *rqst,
+               struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid,
+               u32 completion_filter, bool watch_tree)
+{
+       struct smb2_change_notify_req *req;
+       struct kvec *iov = rqst->rq_iov;
+       unsigned int total_len;
+       int rc;
+
+       rc = smb2_plain_req_init(SMB2_CHANGE_NOTIFY, tcon, (void **) &req, &total_len);
+       if (rc)
+               return rc;
+
+       req->PersistentFileId = persistent_fid;
+       req->VolatileFileId = volatile_fid;
+       req->OutputBufferLength = SMB2_MAX_BUFFER_SIZE - MAX_SMB2_HDR_SIZE;
+       req->CompletionFilter = cpu_to_le32(completion_filter);
+       if (watch_tree)
+               req->Flags = cpu_to_le16(SMB2_WATCH_TREE);
+       else
+               req->Flags = 0;
+
+       iov[0].iov_base = (char *)req;
+       iov[0].iov_len = total_len;
+
+       return 0;
+}
+
+int
+SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon,
+               u64 persistent_fid, u64 volatile_fid, bool watch_tree,
+               u32 completion_filter)
+{
+       struct cifs_ses *ses = tcon->ses;
+       struct smb_rqst rqst;
+       struct kvec iov[1];
+       struct kvec rsp_iov = {NULL, 0};
+       int resp_buftype = CIFS_NO_BUFFER;
+       int flags = 0;
+       int rc = 0;
+
+       cifs_dbg(FYI, "change notify\n");
+       if (!ses || !(ses->server))
+               return -EIO;
+
+       if (smb3_encryption_required(tcon))
+               flags |= CIFS_TRANSFORM_REQ;
+
+       memset(&rqst, 0, sizeof(struct smb_rqst));
+       memset(&iov, 0, sizeof(iov));
+       rqst.rq_iov = iov;
+       rqst.rq_nvec = 1;
+
+       rc = SMB2_notify_init(xid, &rqst, tcon, persistent_fid, volatile_fid,
+                             completion_filter, watch_tree);
+       if (rc)
+               goto cnotify_exit;
+
+       trace_smb3_notify_enter(xid, persistent_fid, tcon->tid, ses->Suid,
+                               (u8)watch_tree, completion_filter);
+       rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
+
+       if (rc != 0) {
+               cifs_stats_fail_inc(tcon, SMB2_CHANGE_NOTIFY_HE);
+               trace_smb3_notify_err(xid, persistent_fid, tcon->tid, ses->Suid,
+                               (u8)watch_tree, completion_filter, rc);
+       } else
+               trace_smb3_notify_done(xid, persistent_fid, tcon->tid,
+                               ses->Suid, (u8)watch_tree, completion_filter);
+
+ cnotify_exit:
+       if (rqst.rq_iov)
+               cifs_small_buf_release(rqst.rq_iov[0].iov_base); /* request */
+       free_rsp_buf(resp_buftype, rsp_iov.iov_base);
+       return rc;
+}
+
+
+
 /*
  * This is a no-op for now. We're not really interested in the reply, but
  * rather in the fact that the server sent one and that server->lstrp
@@ -3287,51 +3389,76 @@ SMB2_echo(struct TCP_Server_Info *server)
        return rc;
 }
 
+void
+SMB2_flush_free(struct smb_rqst *rqst)
+{
+       if (rqst && rqst->rq_iov)
+               cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */
+}
+
 int
-SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
-          u64 volatile_fid)
+SMB2_flush_init(const unsigned int xid, struct smb_rqst *rqst,
+               struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid)
 {
-       struct smb_rqst rqst;
        struct smb2_flush_req *req;
-       struct cifs_ses *ses = tcon->ses;
-       struct kvec iov[1];
-       struct kvec rsp_iov;
-       int resp_buftype;
-       int rc = 0;
-       int flags = 0;
+       struct kvec *iov = rqst->rq_iov;
        unsigned int total_len;
-
-       cifs_dbg(FYI, "Flush\n");
-
-       if (!ses || !(ses->server))
-               return -EIO;
+       int rc;
 
        rc = smb2_plain_req_init(SMB2_FLUSH, tcon, (void **) &req, &total_len);
        if (rc)
                return rc;
 
-       if (smb3_encryption_required(tcon))
-               flags |= CIFS_TRANSFORM_REQ;
-
        req->PersistentFileId = persistent_fid;
        req->VolatileFileId = volatile_fid;
 
        iov[0].iov_base = (char *)req;
        iov[0].iov_len = total_len;
 
+       return 0;
+}
+
+int
+SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
+          u64 volatile_fid)
+{
+       struct cifs_ses *ses = tcon->ses;
+       struct smb_rqst rqst;
+       struct kvec iov[1];
+       struct kvec rsp_iov = {NULL, 0};
+       int resp_buftype = CIFS_NO_BUFFER;
+       int flags = 0;
+       int rc = 0;
+
+       cifs_dbg(FYI, "flush\n");
+       if (!ses || !(ses->server))
+               return -EIO;
+
+       if (smb3_encryption_required(tcon))
+               flags |= CIFS_TRANSFORM_REQ;
+
        memset(&rqst, 0, sizeof(struct smb_rqst));
+       memset(&iov, 0, sizeof(iov));
        rqst.rq_iov = iov;
        rqst.rq_nvec = 1;
 
+       rc = SMB2_flush_init(xid, &rqst, tcon, persistent_fid, volatile_fid);
+       if (rc)
+               goto flush_exit;
+
+       trace_smb3_flush_enter(xid, persistent_fid, tcon->tid, ses->Suid);
        rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
-       cifs_small_buf_release(req);
 
        if (rc != 0) {
                cifs_stats_fail_inc(tcon, SMB2_FLUSH_HE);
                trace_smb3_flush_err(xid, persistent_fid, tcon->tid, ses->Suid,
                                     rc);
-       }
+       } else
+               trace_smb3_flush_done(xid, persistent_fid, tcon->tid,
+                                     ses->Suid);
 
+ flush_exit:
+       SMB2_flush_free(&rqst);
        free_rsp_buf(resp_buftype, rsp_iov.iov_base);
        return rc;
 }
@@ -3446,8 +3573,8 @@ smb2_readv_callback(struct mid_q_entry *mid)
        struct smb2_sync_hdr *shdr =
                                (struct smb2_sync_hdr *)rdata->iov[0].iov_base;
        struct cifs_credits credits = { .value = 0, .instance = 0 };
-       struct smb_rqst rqst = { .rq_iov = rdata->iov,
-                                .rq_nvec = 2,
+       struct smb_rqst rqst = { .rq_iov = &rdata->iov[1],
+                                .rq_nvec = 1,
                                 .rq_pages = rdata->pages,
                                 .rq_offset = rdata->page_offset,
                                 .rq_npages = rdata->nr_pages,
@@ -3468,7 +3595,7 @@ smb2_readv_callback(struct mid_q_entry *mid)
 
                        rc = smb2_verify_signature(&rqst, server);
                        if (rc)
-                               cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
+                               cifs_tcon_dbg(VFS, "SMB signature verification returned error = %d\n",
                                         rc);
                }
                /* FIXME: should this be counted toward the initiating task? */
@@ -3595,7 +3722,7 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
          unsigned int *nbytes, char **buf, int *buf_type)
 {
        struct smb_rqst rqst;
-       int resp_buftype, rc = -EACCES;
+       int resp_buftype, rc;
        struct smb2_read_plain_req *req = NULL;
        struct smb2_read_rsp *rsp = NULL;
        struct kvec iov[1];
@@ -4058,7 +4185,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
                info_buf_size = sizeof(SEARCH_ID_FULL_DIR_INFO) - 1;
                break;
        default:
-               cifs_dbg(VFS, "info level %u isn't supported\n",
+               cifs_tcon_dbg(VFS, "info level %u isn't supported\n",
                         srch_inf->info_level);
                rc = -EINVAL;
                goto qdir_exit;
@@ -4149,7 +4276,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
        else if (resp_buftype == CIFS_SMALL_BUFFER)
                srch_inf->smallBuf = true;
        else
-               cifs_dbg(VFS, "illegal search buffer type\n");
+               cifs_tcon_dbg(VFS, "illegal search buffer type\n");
 
        trace_smb3_query_dir_done(xid, persistent_fid, tcon->tid,
                        tcon->ses->Suid, index, srch_inf->entries_in_buffer);
index 747de9317659198b923b1a850da47bb6641d195c..ea735d59c36e106e7f8ada92486941948eaa9528 100644 (file)
@@ -143,7 +143,9 @@ struct smb2_transform_hdr {
 #define SMB2_FLAGS_ASYNC_COMMAND       cpu_to_le32(0x00000002)
 #define SMB2_FLAGS_RELATED_OPERATIONS  cpu_to_le32(0x00000004)
 #define SMB2_FLAGS_SIGNED              cpu_to_le32(0x00000008)
+#define SMB2_FLAGS_PRIORITY_MASK       cpu_to_le32(0x00000070) /* SMB3.1.1 */
 #define SMB2_FLAGS_DFS_OPERATIONS      cpu_to_le32(0x10000000)
+#define SMB2_FLAGS_REPLAY_OPERATION    cpu_to_le32(0x20000000) /* SMB3 & up */
 
 /*
  *     Definitions for SMB2 Protocol Data Units (network frames)
index 07ca72486cfac50f7207487085f68036c4e635c6..67a91b11fd590a9bf666e78a85391ebe8b151ac1 100644 (file)
@@ -158,6 +158,10 @@ extern int SMB2_close_init(struct cifs_tcon *tcon, struct smb_rqst *rqst,
 extern void SMB2_close_free(struct smb_rqst *rqst);
 extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon,
                      u64 persistent_file_id, u64 volatile_file_id);
+extern int SMB2_flush_init(const unsigned int xid, struct smb_rqst *rqst,
+                          struct cifs_tcon *tcon,
+                          u64 persistent_file_id, u64 volatile_file_id);
+extern void SMB2_flush_free(struct smb_rqst *rqst);
 extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
                           u64 persistent_file_id, u64 volatile_file_id,
                           struct smb2_file_all_info *data);
index 1ccbcf9c2c3b009c056b4b0d83b661b3a10fd4d1..148d7942c796990bfa4949e319fd831116595e26 100644 (file)
@@ -176,7 +176,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
 
        ses = smb2_find_smb_ses(server, shdr->SessionId);
        if (!ses) {
-               cifs_dbg(VFS, "%s: Could not find session\n", __func__);
+               cifs_server_dbg(VFS, "%s: Could not find session\n", __func__);
                return 0;
        }
 
@@ -185,21 +185,21 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
 
        rc = smb2_crypto_shash_allocate(server);
        if (rc) {
-               cifs_dbg(VFS, "%s: sha256 alloc failed\n", __func__);
+               cifs_server_dbg(VFS, "%s: sha256 alloc failed\n", __func__);
                return rc;
        }
 
        rc = crypto_shash_setkey(server->secmech.hmacsha256,
                                 ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
        if (rc) {
-               cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
+               cifs_server_dbg(VFS, "%s: Could not update with response\n", __func__);
                return rc;
        }
 
        shash = &server->secmech.sdeschmacsha256->shash;
        rc = crypto_shash_init(shash);
        if (rc) {
-               cifs_dbg(VFS, "%s: Could not init sha256", __func__);
+               cifs_server_dbg(VFS, "%s: Could not init sha256", __func__);
                return rc;
        }
 
@@ -215,7 +215,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
                rc = crypto_shash_update(shash, iov[0].iov_base,
                                         iov[0].iov_len);
                if (rc) {
-                       cifs_dbg(VFS, "%s: Could not update with payload\n",
+                       cifs_server_dbg(VFS, "%s: Could not update with payload\n",
                                 __func__);
                        return rc;
                }
@@ -239,68 +239,69 @@ static int generate_key(struct cifs_ses *ses, struct kvec label,
        int rc = 0;
        unsigned char prfhash[SMB2_HMACSHA256_SIZE];
        unsigned char *hashptr = prfhash;
+       struct TCP_Server_Info *server = ses->server;
 
        memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);
        memset(key, 0x0, key_size);
 
-       rc = smb3_crypto_shash_allocate(ses->server);
+       rc = smb3_crypto_shash_allocate(server);
        if (rc) {
-               cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__);
+               cifs_server_dbg(VFS, "%s: crypto alloc failed\n", __func__);
                goto smb3signkey_ret;
        }
 
-       rc = crypto_shash_setkey(ses->server->secmech.hmacsha256,
+       rc = crypto_shash_setkey(server->secmech.hmacsha256,
                ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
        if (rc) {
-               cifs_dbg(VFS, "%s: Could not set with session key\n", __func__);
+               cifs_server_dbg(VFS, "%s: Could not set with session key\n", __func__);
                goto smb3signkey_ret;
        }
 
-       rc = crypto_shash_init(&ses->server->secmech.sdeschmacsha256->shash);
+       rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash);
        if (rc) {
-               cifs_dbg(VFS, "%s: Could not init sign hmac\n", __func__);
+               cifs_server_dbg(VFS, "%s: Could not init sign hmac\n", __func__);
                goto smb3signkey_ret;
        }
 
-       rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
+       rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
                                i, 4);
        if (rc) {
-               cifs_dbg(VFS, "%s: Could not update with n\n", __func__);
+               cifs_server_dbg(VFS, "%s: Could not update with n\n", __func__);
                goto smb3signkey_ret;
        }
 
-       rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
+       rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
                                label.iov_base, label.iov_len);
        if (rc) {
-               cifs_dbg(VFS, "%s: Could not update with label\n", __func__);
+               cifs_server_dbg(VFS, "%s: Could not update with label\n", __func__);
                goto smb3signkey_ret;
        }
 
-       rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
+       rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
                                &zero, 1);
        if (rc) {
-               cifs_dbg(VFS, "%s: Could not update with zero\n", __func__);
+               cifs_server_dbg(VFS, "%s: Could not update with zero\n", __func__);
                goto smb3signkey_ret;
        }
 
-       rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
+       rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
                                context.iov_base, context.iov_len);
        if (rc) {
-               cifs_dbg(VFS, "%s: Could not update with context\n", __func__);
+               cifs_server_dbg(VFS, "%s: Could not update with context\n", __func__);
                goto smb3signkey_ret;
        }
 
-       rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
+       rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
                                L, 4);
        if (rc) {
-               cifs_dbg(VFS, "%s: Could not update with L\n", __func__);
+               cifs_server_dbg(VFS, "%s: Could not update with L\n", __func__);
                goto smb3signkey_ret;
        }
 
-       rc = crypto_shash_final(&ses->server->secmech.sdeschmacsha256->shash,
+       rc = crypto_shash_final(&server->secmech.sdeschmacsha256->shash,
                                hashptr);
        if (rc) {
-               cifs_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__);
+               cifs_server_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__);
                goto smb3signkey_ret;
        }
 
@@ -436,7 +437,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
 
        ses = smb2_find_smb_ses(server, shdr->SessionId);
        if (!ses) {
-               cifs_dbg(VFS, "%s: Could not find session\n", __func__);
+               cifs_server_dbg(VFS, "%s: Could not find session\n", __func__);
                return 0;
        }
 
@@ -446,7 +447,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
        rc = crypto_shash_setkey(server->secmech.cmacaes,
                                 ses->smb3signingkey, SMB2_CMACAES_SIZE);
        if (rc) {
-               cifs_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__);
+               cifs_server_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__);
                return rc;
        }
 
@@ -457,7 +458,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
         */
        rc = crypto_shash_init(shash);
        if (rc) {
-               cifs_dbg(VFS, "%s: Could not init cmac aes\n", __func__);
+               cifs_server_dbg(VFS, "%s: Could not init cmac aes\n", __func__);
                return rc;
        }
 
@@ -473,7 +474,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
                rc = crypto_shash_update(shash, iov[0].iov_base,
                                         iov[0].iov_len);
                if (rc) {
-                       cifs_dbg(VFS, "%s: Could not update with payload\n",
+                       cifs_server_dbg(VFS, "%s: Could not update with payload\n",
                                 __func__);
                        return rc;
                }
@@ -521,6 +522,7 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
        if ((shdr->Command == SMB2_NEGOTIATE) ||
            (shdr->Command == SMB2_SESSION_SETUP) ||
            (shdr->Command == SMB2_OPLOCK_BREAK) ||
+           server->ignore_signature ||
            (!server->session_estab))
                return 0;
 
@@ -665,7 +667,7 @@ smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
 
                rc = smb2_verify_signature(&rqst, server);
                if (rc)
-                       cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
+                       cifs_server_dbg(VFS, "SMB signature verification returned error = %d\n",
                                 rc);
        }
 
@@ -739,7 +741,7 @@ smb3_crypto_aead_allocate(struct TCP_Server_Info *server)
                else
                        tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
                if (IS_ERR(tfm)) {
-                       cifs_dbg(VFS, "%s: Failed to alloc encrypt aead\n",
+                       cifs_server_dbg(VFS, "%s: Failed to alloc encrypt aead\n",
                                 __func__);
                        return PTR_ERR(tfm);
                }
@@ -754,7 +756,7 @@ smb3_crypto_aead_allocate(struct TCP_Server_Info *server)
                if (IS_ERR(tfm)) {
                        crypto_free_aead(server->secmech.ccmaesencrypt);
                        server->secmech.ccmaesencrypt = NULL;
-                       cifs_dbg(VFS, "%s: Failed to alloc decrypt aead\n",
+                       cifs_server_dbg(VFS, "%s: Failed to alloc decrypt aead\n",
                                 __func__);
                        return PTR_ERR(tfm);
                }
index 99c4d799c24b63c1f16efba4cf5ab1341c9ae90b..e7e350b13d6a074f6f07cff24979f0675d0100d9 100644 (file)
@@ -117,6 +117,41 @@ DEFINE_SMB3_RW_DONE_EVENT(falloc_done);
 /*
  * For handle based calls other than read and write, and get/set info
  */
+DECLARE_EVENT_CLASS(smb3_fd_class,
+       TP_PROTO(unsigned int xid,
+               __u64   fid,
+               __u32   tid,
+               __u64   sesid),
+       TP_ARGS(xid, fid, tid, sesid),
+       TP_STRUCT__entry(
+               __field(unsigned int, xid)
+               __field(__u64, fid)
+               __field(__u32, tid)
+               __field(__u64, sesid)
+       ),
+       TP_fast_assign(
+               __entry->xid = xid;
+               __entry->fid = fid;
+               __entry->tid = tid;
+               __entry->sesid = sesid;
+       ),
+       TP_printk("\txid=%u sid=0x%llx tid=0x%x fid=0x%llx",
+               __entry->xid, __entry->sesid, __entry->tid, __entry->fid)
+)
+
+#define DEFINE_SMB3_FD_EVENT(name)          \
+DEFINE_EVENT(smb3_fd_class, smb3_##name,    \
+       TP_PROTO(unsigned int xid,              \
+               __u64   fid,                    \
+               __u32   tid,                    \
+               __u64   sesid),                 \
+       TP_ARGS(xid, fid, tid, sesid))
+
+DEFINE_SMB3_FD_EVENT(flush_enter);
+DEFINE_SMB3_FD_EVENT(flush_done);
+DEFINE_SMB3_FD_EVENT(close_enter);
+DEFINE_SMB3_FD_EVENT(close_done);
+
 DECLARE_EVENT_CLASS(smb3_fd_err_class,
        TP_PROTO(unsigned int xid,
                __u64   fid,
@@ -200,6 +235,8 @@ DEFINE_EVENT(smb3_inf_enter_class, smb3_##name,    \
 
 DEFINE_SMB3_INF_ENTER_EVENT(query_info_enter);
 DEFINE_SMB3_INF_ENTER_EVENT(query_info_done);
+DEFINE_SMB3_INF_ENTER_EVENT(notify_enter);
+DEFINE_SMB3_INF_ENTER_EVENT(notify_done);
 
 DECLARE_EVENT_CLASS(smb3_inf_err_class,
        TP_PROTO(unsigned int xid,
@@ -246,6 +283,7 @@ DEFINE_EVENT(smb3_inf_err_class, smb3_##name,    \
 
 DEFINE_SMB3_INF_ERR_EVENT(query_info_err);
 DEFINE_SMB3_INF_ERR_EVENT(set_info_err);
+DEFINE_SMB3_INF_ERR_EVENT(notify_err);
 DEFINE_SMB3_INF_ERR_EVENT(fsctl_err);
 
 DECLARE_EVENT_CLASS(smb3_inf_compound_enter_class,
index 5d6d44bfe10a6f8b4442787f4eac3fc3bcccc34d..308ad0f495e10d513f9219e92d8ade62558337f6 100644 (file)
@@ -118,7 +118,7 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
 #ifdef CONFIG_CIFS_STATS2
        now = jiffies;
        if (now < midEntry->when_alloc)
-               cifs_dbg(VFS, "invalid mid allocation time\n");
+               cifs_server_dbg(VFS, "invalid mid allocation time\n");
        roundtrip_time = now - midEntry->when_alloc;
 
        if (smb_cmd < NUMBER_OF_SMB2_COMMANDS) {
@@ -232,7 +232,7 @@ smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
                        retries++;
                        if (retries >= 14 ||
                            (!server->noblocksnd && (retries > 2))) {
-                               cifs_dbg(VFS, "sends on sock %p stuck for 15 seconds\n",
+                               cifs_server_dbg(VFS, "sends on sock %p stuck for 15 seconds\n",
                                         ssocket);
                                return -EAGAIN;
                        }
@@ -246,7 +246,7 @@ smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
                if (rc == 0) {
                        /* should never happen, letting socket clear before
                           retrying is our only obvious option here */
-                       cifs_dbg(VFS, "tcp sent no data\n");
+                       cifs_server_dbg(VFS, "tcp sent no data\n");
                        msleep(500);
                        continue;
                }
@@ -440,7 +440,7 @@ unmask:
        }
 smbd_done:
        if (rc < 0 && rc != -EINTR)
-               cifs_dbg(VFS, "Error %d sending data on socket to server\n",
+               cifs_server_dbg(VFS, "Error %d sending data on socket to server\n",
                         rc);
        else if (rc > 0)
                rc = 0;
@@ -473,8 +473,8 @@ smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
        cur_rqst[0].rq_nvec = 1;
 
        if (!server->ops->init_transform_rq) {
-               cifs_dbg(VFS, "Encryption requested but transform callback "
-                        "is missing\n");
+               cifs_server_dbg(VFS, "Encryption requested but transform "
+                               "callback is missing\n");
                return -EIO;
        }
 
@@ -532,6 +532,8 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits,
        if ((flags & CIFS_TIMEOUT_MASK) == CIFS_NON_BLOCKING) {
                /* oplock breaks must not be held up */
                server->in_flight++;
+               if (server->in_flight > server->max_in_flight)
+                       server->max_in_flight = server->in_flight;
                *credits -= 1;
                *instance = server->reconnect_instance;
                spin_unlock(&server->req_lock);
@@ -548,7 +550,7 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits,
                        if (!rc) {
                                trace_smb3_credit_timeout(server->CurrentMid,
                                        server->hostname, num_credits);
-                               cifs_dbg(VFS, "wait timed out after %d ms\n",
+                               cifs_server_dbg(VFS, "wait timed out after %d ms\n",
                                         timeout);
                                return -ENOTSUPP;
                        }
@@ -589,7 +591,7 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits,
                                        trace_smb3_credit_timeout(
                                                server->CurrentMid,
                                                server->hostname, num_credits);
-                                       cifs_dbg(VFS, "wait timed out after %d ms\n",
+                                       cifs_server_dbg(VFS, "wait timed out after %d ms\n",
                                                 timeout);
                                        return -ENOTSUPP;
                                }
@@ -608,6 +610,8 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits,
                        if ((flags & CIFS_TIMEOUT_MASK) != CIFS_BLOCKING_OP) {
                                *credits -= num_credits;
                                server->in_flight += num_credits;
+                               if (server->in_flight > server->max_in_flight)
+                                       server->max_in_flight = server->in_flight;
                                *instance = server->reconnect_instance;
                        }
                        spin_unlock(&server->req_lock);
@@ -869,7 +873,7 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
                break;
        default:
                list_del_init(&mid->qhead);
-               cifs_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n",
+               cifs_server_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n",
                         __func__, mid->mid, mid->mid_state);
                rc = -EIO;
        }
@@ -910,7 +914,7 @@ cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
                rc = cifs_verify_signature(&rqst, server,
                                           mid->sequence_number);
                if (rc)
-                       cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
+                       cifs_server_dbg(VFS, "SMB signature verification returned error = %d\n",
                                 rc);
        }
 
@@ -1107,7 +1111,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
        }
        if (rc != 0) {
                for (; i < num_rqst; i++) {
-                       cifs_dbg(VFS, "Cancelling wait for mid %llu cmd: %d\n",
+                       cifs_server_dbg(VFS, "Cancelling wait for mid %llu cmd: %d\n",
                                 midQ[i]->mid, le16_to_cpu(midQ[i]->command));
                        send_cancel(server, &rqst[i], midQ[i]);
                        spin_lock(&GlobalMid_Lock);
@@ -1242,17 +1246,19 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
        struct kvec iov = { .iov_base = in_buf, .iov_len = len };
        struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 };
        struct cifs_credits credits = { .value = 1, .instance = 0 };
+       struct TCP_Server_Info *server;
 
        if (ses == NULL) {
                cifs_dbg(VFS, "Null smb session\n");
                return -EIO;
        }
-       if (ses->server == NULL) {
+       server = ses->server;
+       if (server == NULL) {
                cifs_dbg(VFS, "Null tcp session\n");
                return -EIO;
        }
 
-       if (ses->server->tcpStatus == CifsExiting)
+       if (server->tcpStatus == CifsExiting)
                return -ENOENT;
 
        /* Ensure that we do not send more than 50 overlapping requests
@@ -1260,12 +1266,12 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
           use ses->maxReq */
 
        if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
-               cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n",
+               cifs_server_dbg(VFS, "Illegal length, greater than maximum frame, %d\n",
                         len);
                return -EIO;
        }
 
-       rc = wait_for_free_request(ses->server, flags, &credits.instance);
+       rc = wait_for_free_request(server, flags, &credits.instance);
        if (rc)
                return rc;
 
@@ -1273,70 +1279,70 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
           and avoid races inside tcp sendmsg code that could cause corruption
           of smb data */
 
-       mutex_lock(&ses->server->srv_mutex);
+       mutex_lock(&server->srv_mutex);
 
        rc = allocate_mid(ses, in_buf, &midQ);
        if (rc) {
                mutex_unlock(&ses->server->srv_mutex);
                /* Update # of requests on wire to server */
-               add_credits(ses->server, &credits, 0);
+               add_credits(server, &credits, 0);
                return rc;
        }
 
-       rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
+       rc = cifs_sign_smb(in_buf, server, &midQ->sequence_number);
        if (rc) {
-               mutex_unlock(&ses->server->srv_mutex);
+               mutex_unlock(&server->srv_mutex);
                goto out;
        }
 
        midQ->mid_state = MID_REQUEST_SUBMITTED;
 
-       cifs_in_send_inc(ses->server);
-       rc = smb_send(ses->server, in_buf, len);
-       cifs_in_send_dec(ses->server);
+       cifs_in_send_inc(server);
+       rc = smb_send(server, in_buf, len);
+       cifs_in_send_dec(server);
        cifs_save_when_sent(midQ);
 
        if (rc < 0)
-               ses->server->sequence_number -= 2;
+               server->sequence_number -= 2;
 
-       mutex_unlock(&ses->server->srv_mutex);
+       mutex_unlock(&server->srv_mutex);
 
        if (rc < 0)
                goto out;
 
-       rc = wait_for_response(ses->server, midQ);
+       rc = wait_for_response(server, midQ);
        if (rc != 0) {
-               send_cancel(ses->server, &rqst, midQ);
+               send_cancel(server, &rqst, midQ);
                spin_lock(&GlobalMid_Lock);
                if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
                        /* no longer considered to be "in-flight" */
                        midQ->callback = DeleteMidQEntry;
                        spin_unlock(&GlobalMid_Lock);
-                       add_credits(ses->server, &credits, 0);
+                       add_credits(server, &credits, 0);
                        return rc;
                }
                spin_unlock(&GlobalMid_Lock);
        }
 
-       rc = cifs_sync_mid_result(midQ, ses->server);
+       rc = cifs_sync_mid_result(midQ, server);
        if (rc != 0) {
-               add_credits(ses->server, &credits, 0);
+               add_credits(server, &credits, 0);
                return rc;
        }
 
        if (!midQ->resp_buf || !out_buf ||
            midQ->mid_state != MID_RESPONSE_RECEIVED) {
                rc = -EIO;
-               cifs_dbg(VFS, "Bad MID state?\n");
+               cifs_server_dbg(VFS, "Bad MID state?\n");
                goto out;
        }
 
        *pbytes_returned = get_rfc1002_length(midQ->resp_buf);
        memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
-       rc = cifs_check_receive(midQ, ses->server, 0);
+       rc = cifs_check_receive(midQ, server, 0);
 out:
        cifs_delete_mid(midQ);
-       add_credits(ses->server, &credits, 0);
+       add_credits(server, &credits, 0);
 
        return rc;
 }
@@ -1379,19 +1385,21 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
        struct kvec iov = { .iov_base = in_buf, .iov_len = len };
        struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 };
        unsigned int instance;
+       struct TCP_Server_Info *server;
 
        if (tcon == NULL || tcon->ses == NULL) {
                cifs_dbg(VFS, "Null smb session\n");
                return -EIO;
        }
        ses = tcon->ses;
+       server = ses->server;
 
-       if (ses->server == NULL) {
+       if (server == NULL) {
                cifs_dbg(VFS, "Null tcp session\n");
                return -EIO;
        }
 
-       if (ses->server->tcpStatus == CifsExiting)
+       if (server->tcpStatus == CifsExiting)
                return -ENOENT;
 
        /* Ensure that we do not send more than 50 overlapping requests
@@ -1399,12 +1407,12 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
           use ses->maxReq */
 
        if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
-               cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n",
+               cifs_tcon_dbg(VFS, "Illegal length, greater than maximum frame, %d\n",
                         len);
                return -EIO;
        }
 
-       rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP, &instance);
+       rc = wait_for_free_request(server, CIFS_BLOCKING_OP, &instance);
        if (rc)
                return rc;
 
@@ -1412,31 +1420,31 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
           and avoid races inside tcp sendmsg code that could cause corruption
           of smb data */
 
-       mutex_lock(&ses->server->srv_mutex);
+       mutex_lock(&server->srv_mutex);
 
        rc = allocate_mid(ses, in_buf, &midQ);
        if (rc) {
-               mutex_unlock(&ses->server->srv_mutex);
+               mutex_unlock(&server->srv_mutex);
                return rc;
        }
 
-       rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
+       rc = cifs_sign_smb(in_buf, server, &midQ->sequence_number);
        if (rc) {
                cifs_delete_mid(midQ);
-               mutex_unlock(&ses->server->srv_mutex);
+               mutex_unlock(&server->srv_mutex);
                return rc;
        }
 
        midQ->mid_state = MID_REQUEST_SUBMITTED;
-       cifs_in_send_inc(ses->server);
-       rc = smb_send(ses->server, in_buf, len);
-       cifs_in_send_dec(ses->server);
+       cifs_in_send_inc(server);
+       rc = smb_send(server, in_buf, len);
+       cifs_in_send_dec(server);
        cifs_save_when_sent(midQ);
 
        if (rc < 0)
-               ses->server->sequence_number -= 2;
+               server->sequence_number -= 2;
 
-       mutex_unlock(&ses->server->srv_mutex);
+       mutex_unlock(&server->srv_mutex);
 
        if (rc < 0) {
                cifs_delete_mid(midQ);
@@ -1444,21 +1452,21 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
        }
 
        /* Wait for a reply - allow signals to interrupt. */
-       rc = wait_event_interruptible(ses->server->response_q,
+       rc = wait_event_interruptible(server->response_q,
                (!(midQ->mid_state == MID_REQUEST_SUBMITTED)) ||
-               ((ses->server->tcpStatus != CifsGood) &&
-                (ses->server->tcpStatus != CifsNew)));
+               ((server->tcpStatus != CifsGood) &&
+                (server->tcpStatus != CifsNew)));
 
        /* Were we interrupted by a signal ? */
        if ((rc == -ERESTARTSYS) &&
                (midQ->mid_state == MID_REQUEST_SUBMITTED) &&
-               ((ses->server->tcpStatus == CifsGood) ||
-                (ses->server->tcpStatus == CifsNew))) {
+               ((server->tcpStatus == CifsGood) ||
+                (server->tcpStatus == CifsNew))) {
 
                if (in_buf->Command == SMB_COM_TRANSACTION2) {
                        /* POSIX lock. We send a NT_CANCEL SMB to cause the
                           blocking lock to return. */
-                       rc = send_cancel(ses->server, &rqst, midQ);
+                       rc = send_cancel(server, &rqst, midQ);
                        if (rc) {
                                cifs_delete_mid(midQ);
                                return rc;
@@ -1477,9 +1485,9 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
                        }
                }
 
-               rc = wait_for_response(ses->server, midQ);
+               rc = wait_for_response(server, midQ);
                if (rc) {
-                       send_cancel(ses->server, &rqst, midQ);
+                       send_cancel(server, &rqst, midQ);
                        spin_lock(&GlobalMid_Lock);
                        if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
                                /* no longer considered to be "in-flight" */
@@ -1494,20 +1502,20 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
                rstart = 1;
        }
 
-       rc = cifs_sync_mid_result(midQ, ses->server);
+       rc = cifs_sync_mid_result(midQ, server);
        if (rc != 0)
                return rc;
 
        /* rcvd frame is ok */
        if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) {
                rc = -EIO;
-               cifs_dbg(VFS, "Bad MID state?\n");
+               cifs_tcon_dbg(VFS, "Bad MID state?\n");
                goto out;
        }
 
        *pbytes_returned = get_rfc1002_length(midQ->resp_buf);
        memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
-       rc = cifs_check_receive(midQ, ses->server, 0);
+       rc = cifs_check_receive(midQ, server, 0);
 out:
        cifs_delete_mid(midQ);
        if (rstart && rc == -EACCES)
index bab671b0782f60615e57d5c1172262ab839d16a6..4e78651371ba9225babe162ea488f814562829dc 100644 (file)
@@ -8,6 +8,7 @@
 
 enum {
        Root_NFS = MKDEV(UNNAMED_MAJOR, 255),
+       Root_CIFS = MKDEV(UNNAMED_MAJOR, 254),
        Root_RAM0 = MKDEV(RAMDISK_MAJOR, 0),
        Root_RAM1 = MKDEV(RAMDISK_MAJOR, 1),
        Root_FD0 = MKDEV(FLOPPY_MAJOR, 0),