Commit 8e938e39 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag '6.9-rc-smb3-client-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:

 - Various get_inode_info_fixes

 - Fix for querying xattrs of cached dirs

 - Four minor cleanup fixes (including adding some header corrections
   and a missing flag)

 - Performance improvement for deferred close

 - Two query interface fixes

* tag '6.9-rc-smb3-client-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6:
  smb311: additional compression flag defined in updated protocol spec
  smb311: correct incorrect offset field in compression header
  cifs: Move some extern decls from .c files to .h
  cifs: remove redundant variable assignment
  cifs: fixes for get_inode_info
  cifs: open_cached_dir(): add FILE_READ_EA to desired access
  cifs: reduce warning log level for server not advertising interfaces
  cifs: make sure server interfaces are requested only for SMB3+
  cifs: defer close file handles having RH lease
parents 7ee04901 e56bc745
...@@ -239,7 +239,8 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon, ...@@ -239,7 +239,8 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
.tcon = tcon, .tcon = tcon,
.path = path, .path = path,
.create_options = cifs_create_options(cifs_sb, CREATE_NOT_FILE), .create_options = cifs_create_options(cifs_sb, CREATE_NOT_FILE),
.desired_access = FILE_READ_DATA | FILE_READ_ATTRIBUTES, .desired_access = FILE_READ_DATA | FILE_READ_ATTRIBUTES |
FILE_READ_EA,
.disposition = FILE_OPEN, .disposition = FILE_OPEN,
.fid = pfid, .fid = pfid,
.replay = !!(retries), .replay = !!(retries),
......
...@@ -151,10 +151,6 @@ MODULE_PARM_DESC(disable_legacy_dialects, "To improve security it may be " ...@@ -151,10 +151,6 @@ MODULE_PARM_DESC(disable_legacy_dialects, "To improve security it may be "
"vers=1.0 (CIFS/SMB1) and vers=2.0 are weaker" "vers=1.0 (CIFS/SMB1) and vers=2.0 are weaker"
" and less secure. Default: n/N/0"); " and less secure. Default: n/N/0");
extern mempool_t *cifs_sm_req_poolp;
extern mempool_t *cifs_req_poolp;
extern mempool_t *cifs_mid_poolp;
struct workqueue_struct *cifsiod_wq; struct workqueue_struct *cifsiod_wq;
struct workqueue_struct *decrypt_wq; struct workqueue_struct *decrypt_wq;
struct workqueue_struct *fileinfo_put_wq; struct workqueue_struct *fileinfo_put_wq;
......
...@@ -355,6 +355,9 @@ struct smb_version_operations { ...@@ -355,6 +355,9 @@ struct smb_version_operations {
/* informational QFS call */ /* informational QFS call */
void (*qfs_tcon)(const unsigned int, struct cifs_tcon *, void (*qfs_tcon)(const unsigned int, struct cifs_tcon *,
struct cifs_sb_info *); struct cifs_sb_info *);
/* query for server interfaces */
int (*query_server_interfaces)(const unsigned int, struct cifs_tcon *,
bool);
/* check if a path is accessible or not */ /* check if a path is accessible or not */
int (*is_path_accessible)(const unsigned int, struct cifs_tcon *, int (*is_path_accessible)(const unsigned int, struct cifs_tcon *,
struct cifs_sb_info *, const char *); struct cifs_sb_info *, const char *);
...@@ -2104,6 +2107,8 @@ extern struct workqueue_struct *cifsoplockd_wq; ...@@ -2104,6 +2107,8 @@ extern struct workqueue_struct *cifsoplockd_wq;
extern struct workqueue_struct *deferredclose_wq; extern struct workqueue_struct *deferredclose_wq;
extern __u32 cifs_lock_secret; extern __u32 cifs_lock_secret;
extern mempool_t *cifs_sm_req_poolp;
extern mempool_t *cifs_req_poolp;
extern mempool_t *cifs_mid_poolp; extern mempool_t *cifs_mid_poolp;
/* Operations for different SMB versions */ /* Operations for different SMB versions */
......
...@@ -52,9 +52,6 @@ ...@@ -52,9 +52,6 @@
#include "fs_context.h" #include "fs_context.h"
#include "cifs_swn.h" #include "cifs_swn.h"
extern mempool_t *cifs_req_poolp;
extern bool disable_legacy_dialects;
/* FIXME: should these be tunable? */ /* FIXME: should these be tunable? */
#define TLINK_ERROR_EXPIRE (1 * HZ) #define TLINK_ERROR_EXPIRE (1 * HZ)
#define TLINK_IDLE_EXPIRE (600 * HZ) #define TLINK_IDLE_EXPIRE (600 * HZ)
...@@ -123,12 +120,16 @@ static void smb2_query_server_interfaces(struct work_struct *work) ...@@ -123,12 +120,16 @@ static void smb2_query_server_interfaces(struct work_struct *work)
struct cifs_tcon *tcon = container_of(work, struct cifs_tcon *tcon = container_of(work,
struct cifs_tcon, struct cifs_tcon,
query_interfaces.work); query_interfaces.work);
struct TCP_Server_Info *server = tcon->ses->server;
/* /*
* query server network interfaces, in case they change * query server network interfaces, in case they change
*/ */
if (!server->ops->query_server_interfaces)
return;
xid = get_xid(); xid = get_xid();
rc = SMB3_request_interfaces(xid, tcon, false); rc = server->ops->query_server_interfaces(xid, tcon, false);
free_xid(xid); free_xid(xid);
if (rc) { if (rc) {
......
...@@ -486,7 +486,6 @@ struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file, ...@@ -486,7 +486,6 @@ struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
cfile->uid = current_fsuid(); cfile->uid = current_fsuid();
cfile->dentry = dget(dentry); cfile->dentry = dget(dentry);
cfile->f_flags = file->f_flags; cfile->f_flags = file->f_flags;
cfile->status_file_deleted = false;
cfile->invalidHandle = false; cfile->invalidHandle = false;
cfile->deferred_close_scheduled = false; cfile->deferred_close_scheduled = false;
cfile->tlink = cifs_get_tlink(tlink); cfile->tlink = cifs_get_tlink(tlink);
...@@ -1073,6 +1072,19 @@ void smb2_deferred_work_close(struct work_struct *work) ...@@ -1073,6 +1072,19 @@ void smb2_deferred_work_close(struct work_struct *work)
_cifsFileInfo_put(cfile, true, false); _cifsFileInfo_put(cfile, true, false);
} }
static bool
smb2_can_defer_close(struct inode *inode, struct cifs_deferred_close *dclose)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifsInodeInfo *cinode = CIFS_I(inode);
return (cifs_sb->ctx->closetimeo && cinode->lease_granted && dclose &&
(cinode->oplock == CIFS_CACHE_RHW_FLG ||
cinode->oplock == CIFS_CACHE_RH_FLG) &&
!test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags));
}
int cifs_close(struct inode *inode, struct file *file) int cifs_close(struct inode *inode, struct file *file)
{ {
struct cifsFileInfo *cfile; struct cifsFileInfo *cfile;
...@@ -1086,10 +1098,8 @@ int cifs_close(struct inode *inode, struct file *file) ...@@ -1086,10 +1098,8 @@ int cifs_close(struct inode *inode, struct file *file)
cfile = file->private_data; cfile = file->private_data;
file->private_data = NULL; file->private_data = NULL;
dclose = kmalloc(sizeof(struct cifs_deferred_close), GFP_KERNEL); dclose = kmalloc(sizeof(struct cifs_deferred_close), GFP_KERNEL);
if ((cifs_sb->ctx->closetimeo && cinode->oplock == CIFS_CACHE_RHW_FLG) if ((cfile->status_file_deleted == false) &&
&& cinode->lease_granted && (smb2_can_defer_close(inode, dclose))) {
!test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags) &&
dclose && !(cfile->status_file_deleted)) {
if (test_and_clear_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) { if (test_and_clear_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) {
inode_set_mtime_to_ts(inode, inode_set_mtime_to_ts(inode,
inode_set_ctime_current(inode)); inode_set_ctime_current(inode));
......
...@@ -401,7 +401,6 @@ cifs_get_file_info_unix(struct file *filp) ...@@ -401,7 +401,6 @@ cifs_get_file_info_unix(struct file *filp)
cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
} else if (rc == -EREMOTE) { } else if (rc == -EREMOTE) {
cifs_create_junction_fattr(&fattr, inode->i_sb); cifs_create_junction_fattr(&fattr, inode->i_sb);
rc = 0;
} else } else
goto cifs_gfiunix_out; goto cifs_gfiunix_out;
...@@ -820,8 +819,10 @@ cifs_get_file_info(struct file *filp) ...@@ -820,8 +819,10 @@ cifs_get_file_info(struct file *filp)
void *page = alloc_dentry_path(); void *page = alloc_dentry_path();
const unsigned char *path; const unsigned char *path;
if (!server->ops->query_file_info) if (!server->ops->query_file_info) {
free_dentry_path(page);
return -ENOSYS; return -ENOSYS;
}
xid = get_xid(); xid = get_xid();
rc = server->ops->query_file_info(xid, tcon, cfile, &data); rc = server->ops->query_file_info(xid, tcon, cfile, &data);
...@@ -835,8 +836,8 @@ cifs_get_file_info(struct file *filp) ...@@ -835,8 +836,8 @@ cifs_get_file_info(struct file *filp)
} }
path = build_path_from_dentry(dentry, page); path = build_path_from_dentry(dentry, page);
if (IS_ERR(path)) { if (IS_ERR(path)) {
free_dentry_path(page); rc = PTR_ERR(path);
return PTR_ERR(path); goto cgfi_exit;
} }
cifs_open_info_to_fattr(&fattr, &data, inode->i_sb); cifs_open_info_to_fattr(&fattr, &data, inode->i_sb);
if (fattr.cf_flags & CIFS_FATTR_DELETE_PENDING) if (fattr.cf_flags & CIFS_FATTR_DELETE_PENDING)
...@@ -844,7 +845,6 @@ cifs_get_file_info(struct file *filp) ...@@ -844,7 +845,6 @@ cifs_get_file_info(struct file *filp)
break; break;
case -EREMOTE: case -EREMOTE:
cifs_create_junction_fattr(&fattr, inode->i_sb); cifs_create_junction_fattr(&fattr, inode->i_sb);
rc = 0;
break; break;
case -EOPNOTSUPP: case -EOPNOTSUPP:
case -EINVAL: case -EINVAL:
...@@ -1009,7 +1009,6 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data, ...@@ -1009,7 +1009,6 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
struct kvec rsp_iov, *iov = NULL; struct kvec rsp_iov, *iov = NULL;
int rsp_buftype = CIFS_NO_BUFFER; int rsp_buftype = CIFS_NO_BUFFER;
u32 tag = data->reparse.tag; u32 tag = data->reparse.tag;
struct inode *inode = NULL;
int rc = 0; int rc = 0;
if (!tag && server->ops->query_reparse_point) { if (!tag && server->ops->query_reparse_point) {
...@@ -1049,12 +1048,8 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data, ...@@ -1049,12 +1048,8 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
if (tcon->posix_extensions) if (tcon->posix_extensions)
smb311_posix_info_to_fattr(fattr, data, sb); smb311_posix_info_to_fattr(fattr, data, sb);
else { else
cifs_open_info_to_fattr(fattr, data, sb); cifs_open_info_to_fattr(fattr, data, sb);
inode = cifs_iget(sb, fattr);
if (inode && fattr->cf_flags & CIFS_FATTR_DELETE_PENDING)
cifs_mark_open_handles_for_deleted_file(inode, full_path);
}
out: out:
fattr->cf_cifstag = data->reparse.tag; fattr->cf_cifstag = data->reparse.tag;
free_rsp_buf(rsp_buftype, rsp_iov.iov_base); free_rsp_buf(rsp_buftype, rsp_iov.iov_base);
...@@ -1109,9 +1104,9 @@ static int cifs_get_fattr(struct cifs_open_info_data *data, ...@@ -1109,9 +1104,9 @@ static int cifs_get_fattr(struct cifs_open_info_data *data,
full_path, fattr); full_path, fattr);
} else { } else {
cifs_open_info_to_fattr(fattr, data, sb); cifs_open_info_to_fattr(fattr, data, sb);
if (fattr->cf_flags & CIFS_FATTR_DELETE_PENDING)
cifs_mark_open_handles_for_deleted_file(*inode, full_path);
} }
if (!rc && fattr->cf_flags & CIFS_FATTR_DELETE_PENDING)
cifs_mark_open_handles_for_deleted_file(*inode, full_path);
break; break;
case -EREMOTE: case -EREMOTE:
/* DFS link, no metadata available on this server */ /* DFS link, no metadata available on this server */
...@@ -1340,6 +1335,8 @@ int smb311_posix_get_inode_info(struct inode **inode, ...@@ -1340,6 +1335,8 @@ int smb311_posix_get_inode_info(struct inode **inode,
goto out; goto out;
rc = update_inode_info(sb, &fattr, inode); rc = update_inode_info(sb, &fattr, inode);
if (!rc && fattr.cf_flags & CIFS_FATTR_DELETE_PENDING)
cifs_mark_open_handles_for_deleted_file(*inode, full_path);
out: out:
kfree(fattr.cf_symlink_target); kfree(fattr.cf_symlink_target);
return rc; return rc;
...@@ -1501,6 +1498,9 @@ struct inode *cifs_root_iget(struct super_block *sb) ...@@ -1501,6 +1498,9 @@ struct inode *cifs_root_iget(struct super_block *sb)
goto out; goto out;
} }
if (!rc && fattr.cf_flags & CIFS_FATTR_DELETE_PENDING)
cifs_mark_open_handles_for_deleted_file(inode, path);
if (rc && tcon->pipe) { if (rc && tcon->pipe) {
cifs_dbg(FYI, "ipc connection - fake read inode\n"); cifs_dbg(FYI, "ipc connection - fake read inode\n");
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
......
...@@ -27,9 +27,6 @@ ...@@ -27,9 +27,6 @@
#include "fs_context.h" #include "fs_context.h"
#include "cached_dir.h" #include "cached_dir.h"
extern mempool_t *cifs_sm_req_poolp;
extern mempool_t *cifs_req_poolp;
/* The xid serves as a useful identifier for each incoming vfs request, /* The xid serves as a useful identifier for each incoming vfs request,
in a similar way to the mid which is useful to track each sent smb, in a similar way to the mid which is useful to track each sent smb,
and CurrentXid can also provide a running counter (although it and CurrentXid can also provide a running counter (although it
......
...@@ -230,7 +230,7 @@ int cifs_try_adding_channels(struct cifs_ses *ses) ...@@ -230,7 +230,7 @@ int cifs_try_adding_channels(struct cifs_ses *ses)
spin_lock(&ses->iface_lock); spin_lock(&ses->iface_lock);
if (!ses->iface_count) { if (!ses->iface_count) {
spin_unlock(&ses->iface_lock); spin_unlock(&ses->iface_lock);
cifs_dbg(VFS, "server %s does not advertise interfaces\n", cifs_dbg(ONCE, "server %s does not advertise interfaces\n",
ses->server->hostname); ses->server->hostname);
break; break;
} }
...@@ -396,7 +396,7 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server) ...@@ -396,7 +396,7 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
spin_lock(&ses->iface_lock); spin_lock(&ses->iface_lock);
if (!ses->iface_count) { if (!ses->iface_count) {
spin_unlock(&ses->iface_lock); spin_unlock(&ses->iface_lock);
cifs_dbg(VFS, "server %s does not advertise interfaces\n", ses->server->hostname); cifs_dbg(ONCE, "server %s does not advertise interfaces\n", ses->server->hostname);
return; return;
} }
......
...@@ -5290,6 +5290,7 @@ struct smb_version_operations smb30_operations = { ...@@ -5290,6 +5290,7 @@ struct smb_version_operations smb30_operations = {
.tree_connect = SMB2_tcon, .tree_connect = SMB2_tcon,
.tree_disconnect = SMB2_tdis, .tree_disconnect = SMB2_tdis,
.qfs_tcon = smb3_qfs_tcon, .qfs_tcon = smb3_qfs_tcon,
.query_server_interfaces = SMB3_request_interfaces,
.is_path_accessible = smb2_is_path_accessible, .is_path_accessible = smb2_is_path_accessible,
.can_echo = smb2_can_echo, .can_echo = smb2_can_echo,
.echo = SMB2_echo, .echo = SMB2_echo,
...@@ -5405,6 +5406,7 @@ struct smb_version_operations smb311_operations = { ...@@ -5405,6 +5406,7 @@ struct smb_version_operations smb311_operations = {
.tree_connect = SMB2_tcon, .tree_connect = SMB2_tcon,
.tree_disconnect = SMB2_tdis, .tree_disconnect = SMB2_tdis,
.qfs_tcon = smb3_qfs_tcon, .qfs_tcon = smb3_qfs_tcon,
.query_server_interfaces = SMB3_request_interfaces,
.is_path_accessible = smb2_is_path_accessible, .is_path_accessible = smb2_is_path_accessible,
.can_echo = smb2_can_echo, .can_echo = smb2_can_echo,
.echo = SMB2_echo, .echo = SMB2_echo,
......
...@@ -409,14 +409,15 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon, ...@@ -409,14 +409,15 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
spin_unlock(&ses->ses_lock); spin_unlock(&ses->ses_lock);
if (!rc && if (!rc &&
(server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) { (server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL) &&
server->ops->query_server_interfaces) {
mutex_unlock(&ses->session_mutex); mutex_unlock(&ses->session_mutex);
/* /*
* query server network interfaces, in case they change * query server network interfaces, in case they change
*/ */
xid = get_xid(); xid = get_xid();
rc = SMB3_request_interfaces(xid, tcon, false); rc = server->ops->query_server_interfaces(xid, tcon, false);
free_xid(xid); free_xid(xid);
if (rc == -EOPNOTSUPP && ses->chan_count > 1) { if (rc == -EOPNOTSUPP && ses->chan_count > 1) {
......
...@@ -227,7 +227,7 @@ struct smb2_compression_hdr { ...@@ -227,7 +227,7 @@ struct smb2_compression_hdr {
__le32 OriginalCompressedSegmentSize; __le32 OriginalCompressedSegmentSize;
__le16 CompressionAlgorithm; __le16 CompressionAlgorithm;
__le16 Flags; __le16 Flags;
__le16 Offset; /* this is the size of the uncompressed SMB2 header below */ __le32 Offset; /* this is the size of the uncompressed SMB2 header below */
/* uncompressed SMB2 header (READ or WRITE) goes here */ /* uncompressed SMB2 header (READ or WRITE) goes here */
/* compressed data goes here */ /* compressed data goes here */
} __packed; } __packed;
...@@ -280,15 +280,16 @@ struct smb3_blob_data { ...@@ -280,15 +280,16 @@ struct smb3_blob_data {
#define SE_GROUP_RESOURCE 0x20000000 #define SE_GROUP_RESOURCE 0x20000000
#define SE_GROUP_LOGON_ID 0xC0000000 #define SE_GROUP_LOGON_ID 0xC0000000
/* struct sid_attr_data is SidData array in BlobData format then le32 Attr */
struct sid_array_data { struct sid_array_data {
__le16 SidAttrCount; __le16 SidAttrCount;
/* SidAttrList - array of sid_attr_data structs */ /* SidAttrList - array of sid_attr_data structs */
} __packed; } __packed;
struct luid_attr_data { /* struct sid_attr_data is SidData array in BlobData format then le32 Attr */
struct sid_attr_data {
__le16 BlobSize;
__u8 BlobData[];
/* __le32 Attr */
} __packed; } __packed;
/* /*
...@@ -502,6 +503,7 @@ struct smb2_encryption_neg_context { ...@@ -502,6 +503,7 @@ struct smb2_encryption_neg_context {
#define SMB3_COMPRESS_LZ77_HUFF cpu_to_le16(0x0003) #define SMB3_COMPRESS_LZ77_HUFF cpu_to_le16(0x0003)
/* Pattern scanning algorithm See MS-SMB2 3.1.4.4.1 */ /* Pattern scanning algorithm See MS-SMB2 3.1.4.4.1 */
#define SMB3_COMPRESS_PATTERN cpu_to_le16(0x0004) /* Pattern_V1 */ #define SMB3_COMPRESS_PATTERN cpu_to_le16(0x0004) /* Pattern_V1 */
#define SMB3_COMPRESS_LZ4 cpu_to_le16(0x0005)
/* Compression Flags */ /* Compression Flags */
#define SMB2_COMPRESSION_CAPABILITIES_FLAG_NONE cpu_to_le32(0x00000000) #define SMB2_COMPRESSION_CAPABILITIES_FLAG_NONE cpu_to_le32(0x00000000)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment