Merge branch 'for-linus' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French: "Most important fixes in this set include three SMB3 fixes for stable (including fix for possible kernel oops), and a workaround to allow writes to Mac servers (only cifs dialect, not more current SMB2.1, worked to Mac servers). Also fallocate support added, and lease fix from Jeff" * 'for-linus' of git://git.samba.org/sfrench/cifs-2.6: [SMB3] Enable fallocate -z support for SMB3 mounts enable fallocate punch hole ("fallocate -p") for SMB3 Incorrect error returned on setting file compressed on SMB2 CIFS: Fix wrong directory attributes after rename CIFS: Fix SMB2 readdir error handling [CIFS] Possible null ptr deref in SMB2_tcon [CIFS] Workaround MacOS server problem with SMB2.1 write response cifs: handle lease F_UNLCK requests properly Cleanup sparse file support by creating worker function for it Add sparse file support to SMB2/SMB3 mounts Add missing definitions for CIFS File System Attributes cifs: remove unused function cifs_oplock_break_wait
This commit is contained in:
Коммит
372b1dbdd1
|
@ -207,6 +207,19 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static long cifs_fallocate(struct file *file, int mode, loff_t off, loff_t len)
|
||||
{
|
||||
struct super_block *sb = file->f_path.dentry->d_sb;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
struct TCP_Server_Info *server = tcon->ses->server;
|
||||
|
||||
if (server->ops->fallocate)
|
||||
return server->ops->fallocate(file, tcon, mode, off, len);
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int cifs_permission(struct inode *inode, int mask)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
|
@ -812,8 +825,9 @@ static int cifs_setlease(struct file *file, long arg, struct file_lock **lease)
|
|||
if (!(S_ISREG(inode->i_mode)))
|
||||
return -EINVAL;
|
||||
|
||||
/* check if file is oplocked */
|
||||
if (((arg == F_RDLCK) && CIFS_CACHE_READ(CIFS_I(inode))) ||
|
||||
/* Check if file is oplocked if this is request for new lease */
|
||||
if (arg == F_UNLCK ||
|
||||
((arg == F_RDLCK) && CIFS_CACHE_READ(CIFS_I(inode))) ||
|
||||
((arg == F_WRLCK) && CIFS_CACHE_WRITE(CIFS_I(inode))))
|
||||
return generic_setlease(file, arg, lease);
|
||||
else if (tlink_tcon(cfile->tlink)->local_lease &&
|
||||
|
@ -908,6 +922,7 @@ const struct file_operations cifs_file_ops = {
|
|||
.unlocked_ioctl = cifs_ioctl,
|
||||
#endif /* CONFIG_CIFS_POSIX */
|
||||
.setlease = cifs_setlease,
|
||||
.fallocate = cifs_fallocate,
|
||||
};
|
||||
|
||||
const struct file_operations cifs_file_strict_ops = {
|
||||
|
@ -927,6 +942,7 @@ const struct file_operations cifs_file_strict_ops = {
|
|||
.unlocked_ioctl = cifs_ioctl,
|
||||
#endif /* CONFIG_CIFS_POSIX */
|
||||
.setlease = cifs_setlease,
|
||||
.fallocate = cifs_fallocate,
|
||||
};
|
||||
|
||||
const struct file_operations cifs_file_direct_ops = {
|
||||
|
@ -947,6 +963,7 @@ const struct file_operations cifs_file_direct_ops = {
|
|||
#endif /* CONFIG_CIFS_POSIX */
|
||||
.llseek = cifs_llseek,
|
||||
.setlease = cifs_setlease,
|
||||
.fallocate = cifs_fallocate,
|
||||
};
|
||||
|
||||
const struct file_operations cifs_file_nobrl_ops = {
|
||||
|
@ -965,6 +982,7 @@ const struct file_operations cifs_file_nobrl_ops = {
|
|||
.unlocked_ioctl = cifs_ioctl,
|
||||
#endif /* CONFIG_CIFS_POSIX */
|
||||
.setlease = cifs_setlease,
|
||||
.fallocate = cifs_fallocate,
|
||||
};
|
||||
|
||||
const struct file_operations cifs_file_strict_nobrl_ops = {
|
||||
|
@ -983,6 +1001,7 @@ const struct file_operations cifs_file_strict_nobrl_ops = {
|
|||
.unlocked_ioctl = cifs_ioctl,
|
||||
#endif /* CONFIG_CIFS_POSIX */
|
||||
.setlease = cifs_setlease,
|
||||
.fallocate = cifs_fallocate,
|
||||
};
|
||||
|
||||
const struct file_operations cifs_file_direct_nobrl_ops = {
|
||||
|
@ -1002,6 +1021,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = {
|
|||
#endif /* CONFIG_CIFS_POSIX */
|
||||
.llseek = cifs_llseek,
|
||||
.setlease = cifs_setlease,
|
||||
.fallocate = cifs_fallocate,
|
||||
};
|
||||
|
||||
const struct file_operations cifs_dir_ops = {
|
||||
|
|
|
@ -409,6 +409,10 @@ struct smb_version_operations {
|
|||
/* get mtu credits */
|
||||
int (*wait_mtu_credits)(struct TCP_Server_Info *, unsigned int,
|
||||
unsigned int *, unsigned int *);
|
||||
/* check if we need to issue closedir */
|
||||
bool (*dir_needs_close)(struct cifsFileInfo *);
|
||||
long (*fallocate)(struct file *, struct cifs_tcon *, int, loff_t,
|
||||
loff_t);
|
||||
};
|
||||
|
||||
struct smb_version_values {
|
||||
|
@ -883,6 +887,7 @@ struct cifs_tcon {
|
|||
for this mount even if server would support */
|
||||
bool local_lease:1; /* check leases (only) on local system not remote */
|
||||
bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */
|
||||
bool broken_sparse_sup; /* if server or share does not support sparse */
|
||||
bool need_reconnect:1; /* connection reset, tid now invalid */
|
||||
#ifdef CONFIG_CIFS_SMB2
|
||||
bool print:1; /* set if connection to printer share */
|
||||
|
|
|
@ -2253,6 +2253,29 @@ typedef struct {
|
|||
/* minimum includes first three fields, and empty FS Name */
|
||||
#define MIN_FS_ATTR_INFO_SIZE 12
|
||||
|
||||
|
||||
/* List of FileSystemAttributes - see 2.5.1 of MS-FSCC */
|
||||
#define FILE_SUPPORT_INTEGRITY_STREAMS 0x04000000
|
||||
#define FILE_SUPPORTS_USN_JOURNAL 0x02000000
|
||||
#define FILE_SUPPORTS_OPEN_BY_FILE_ID 0x01000000
|
||||
#define FILE_SUPPORTS_EXTENDED_ATTRIBUTES 0x00800000
|
||||
#define FILE_SUPPORTS_HARD_LINKS 0x00400000
|
||||
#define FILE_SUPPORTS_TRANSACTIONS 0x00200000
|
||||
#define FILE_SEQUENTIAL_WRITE_ONCE 0x00100000
|
||||
#define FILE_READ_ONLY_VOLUME 0x00080000
|
||||
#define FILE_NAMED_STREAMS 0x00040000
|
||||
#define FILE_SUPPORTS_ENCRYPTION 0x00020000
|
||||
#define FILE_SUPPORTS_OBJECT_IDS 0x00010000
|
||||
#define FILE_VOLUME_IS_COMPRESSED 0x00008000
|
||||
#define FILE_SUPPORTS_REMOTE_STORAGE 0x00000100
|
||||
#define FILE_SUPPORTS_REPARSE_POINTS 0x00000080
|
||||
#define FILE_SUPPORTS_SPARSE_FILES 0x00000040
|
||||
#define FILE_VOLUME_QUOTAS 0x00000020
|
||||
#define FILE_FILE_COMPRESSION 0x00000010
|
||||
#define FILE_PERSISTENT_ACLS 0x00000008
|
||||
#define FILE_UNICODE_ON_DISK 0x00000004
|
||||
#define FILE_CASE_PRESERVED_NAMES 0x00000002
|
||||
#define FILE_CASE_SENSITIVE_SEARCH 0x00000001
|
||||
typedef struct {
|
||||
__le32 Attributes;
|
||||
__le32 MaxPathNameComponentLength;
|
||||
|
|
|
@ -762,7 +762,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
|
|||
|
||||
cifs_dbg(FYI, "Freeing private data in close dir\n");
|
||||
spin_lock(&cifs_file_list_lock);
|
||||
if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) {
|
||||
if (server->ops->dir_needs_close(cfile)) {
|
||||
cfile->invalidHandle = true;
|
||||
spin_unlock(&cifs_file_list_lock);
|
||||
if (server->ops->close_dir)
|
||||
|
|
|
@ -1727,6 +1727,12 @@ unlink_target:
|
|||
target_dentry, to_name);
|
||||
}
|
||||
|
||||
/* force revalidate to go get info when needed */
|
||||
CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
|
||||
|
||||
source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
|
||||
target_dir->i_mtime = current_fs_time(source_dir->i_sb);
|
||||
|
||||
cifs_rename_exit:
|
||||
kfree(info_buf_source);
|
||||
kfree(from_name);
|
||||
|
|
|
@ -574,13 +574,6 @@ void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock)
|
|||
cinode->oplock = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
cifs_oplock_break_wait(void *unused)
|
||||
{
|
||||
schedule();
|
||||
return signal_pending(current) ? -ERESTARTSYS : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We wait for oplock breaks to be processed before we attempt to perform
|
||||
* writes.
|
||||
|
|
|
@ -593,7 +593,7 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
|
|||
/* close and restart search */
|
||||
cifs_dbg(FYI, "search backing up - close and restart search\n");
|
||||
spin_lock(&cifs_file_list_lock);
|
||||
if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) {
|
||||
if (server->ops->dir_needs_close(cfile)) {
|
||||
cfile->invalidHandle = true;
|
||||
spin_unlock(&cifs_file_list_lock);
|
||||
if (server->ops->close)
|
||||
|
|
|
@ -1015,6 +1015,12 @@ cifs_wp_retry_size(struct inode *inode)
|
|||
return CIFS_SB(inode->i_sb)->wsize;
|
||||
}
|
||||
|
||||
static bool
|
||||
cifs_dir_needs_close(struct cifsFileInfo *cfile)
|
||||
{
|
||||
return !cfile->srch_inf.endOfSearch && !cfile->invalidHandle;
|
||||
}
|
||||
|
||||
struct smb_version_operations smb1_operations = {
|
||||
.send_cancel = send_nt_cancel,
|
||||
.compare_fids = cifs_compare_fids,
|
||||
|
@ -1086,6 +1092,7 @@ struct smb_version_operations smb1_operations = {
|
|||
.create_mf_symlink = cifs_create_mf_symlink,
|
||||
.is_read_op = cifs_is_read_op,
|
||||
.wp_retry_size = cifs_wp_retry_size,
|
||||
.dir_needs_close = cifs_dir_needs_close,
|
||||
#ifdef CONFIG_CIFS_XATTR
|
||||
.query_all_EAs = CIFSSMBQAllEAs,
|
||||
.set_EA = CIFSSMBSetEA,
|
||||
|
|
|
@ -214,7 +214,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
|
|||
{STATUS_BREAKPOINT, -EIO, "STATUS_BREAKPOINT"},
|
||||
{STATUS_SINGLE_STEP, -EIO, "STATUS_SINGLE_STEP"},
|
||||
{STATUS_BUFFER_OVERFLOW, -EIO, "STATUS_BUFFER_OVERFLOW"},
|
||||
{STATUS_NO_MORE_FILES, -EIO, "STATUS_NO_MORE_FILES"},
|
||||
{STATUS_NO_MORE_FILES, -ENODATA, "STATUS_NO_MORE_FILES"},
|
||||
{STATUS_WAKE_SYSTEM_DEBUGGER, -EIO, "STATUS_WAKE_SYSTEM_DEBUGGER"},
|
||||
{STATUS_HANDLES_CLOSED, -EIO, "STATUS_HANDLES_CLOSED"},
|
||||
{STATUS_NO_INHERITANCE, -EIO, "STATUS_NO_INHERITANCE"},
|
||||
|
@ -298,7 +298,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
|
|||
{STATUS_INVALID_PARAMETER, -EINVAL, "STATUS_INVALID_PARAMETER"},
|
||||
{STATUS_NO_SUCH_DEVICE, -ENODEV, "STATUS_NO_SUCH_DEVICE"},
|
||||
{STATUS_NO_SUCH_FILE, -ENOENT, "STATUS_NO_SUCH_FILE"},
|
||||
{STATUS_INVALID_DEVICE_REQUEST, -EIO, "STATUS_INVALID_DEVICE_REQUEST"},
|
||||
{STATUS_INVALID_DEVICE_REQUEST, -EOPNOTSUPP, "STATUS_INVALID_DEVICE_REQUEST"},
|
||||
{STATUS_END_OF_FILE, -ENODATA, "STATUS_END_OF_FILE"},
|
||||
{STATUS_WRONG_VOLUME, -EIO, "STATUS_WRONG_VOLUME"},
|
||||
{STATUS_NO_MEDIA_IN_DEVICE, -EIO, "STATUS_NO_MEDIA_IN_DEVICE"},
|
||||
|
|
|
@ -178,9 +178,24 @@ smb2_check_message(char *buf, unsigned int length)
|
|||
/* Windows 7 server returns 24 bytes more */
|
||||
if (clc_len + 20 == len && command == SMB2_OPLOCK_BREAK_HE)
|
||||
return 0;
|
||||
/* server can return one byte more */
|
||||
/* server can return one byte more due to implied bcc[0] */
|
||||
if (clc_len == 4 + len + 1)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* MacOS server pads after SMB2.1 write response with 3 bytes
|
||||
* of junk. Other servers match RFC1001 len to actual
|
||||
* SMB2/SMB3 frame length (header + smb2 response specific data)
|
||||
* Log the server error (once), but allow it and continue
|
||||
* since the frame is parseable.
|
||||
*/
|
||||
if (clc_len < 4 /* RFC1001 header size */ + len) {
|
||||
printk_once(KERN_WARNING
|
||||
"SMB2 server sent bad RFC1001 len %d not %d\n",
|
||||
len, clc_len - 4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -731,11 +731,72 @@ smb2_sync_write(const unsigned int xid, struct cifsFileInfo *cfile,
|
|||
return SMB2_write(xid, parms, written, iov, nr_segs);
|
||||
}
|
||||
|
||||
/* Set or clear the SPARSE_FILE attribute based on value passed in setsparse */
|
||||
static bool smb2_set_sparse(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct cifsFileInfo *cfile, struct inode *inode, __u8 setsparse)
|
||||
{
|
||||
struct cifsInodeInfo *cifsi;
|
||||
int rc;
|
||||
|
||||
cifsi = CIFS_I(inode);
|
||||
|
||||
/* if file already sparse don't bother setting sparse again */
|
||||
if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) && setsparse)
|
||||
return true; /* already sparse */
|
||||
|
||||
if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) && !setsparse)
|
||||
return true; /* already not sparse */
|
||||
|
||||
/*
|
||||
* Can't check for sparse support on share the usual way via the
|
||||
* FS attribute info (FILE_SUPPORTS_SPARSE_FILES) on the share
|
||||
* since Samba server doesn't set the flag on the share, yet
|
||||
* supports the set sparse FSCTL and returns sparse correctly
|
||||
* in the file attributes. If we fail setting sparse though we
|
||||
* mark that server does not support sparse files for this share
|
||||
* to avoid repeatedly sending the unsupported fsctl to server
|
||||
* if the file is repeatedly extended.
|
||||
*/
|
||||
if (tcon->broken_sparse_sup)
|
||||
return false;
|
||||
|
||||
rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
|
||||
cfile->fid.volatile_fid, FSCTL_SET_SPARSE,
|
||||
true /* is_fctl */, &setsparse, 1, NULL, NULL);
|
||||
if (rc) {
|
||||
tcon->broken_sparse_sup = true;
|
||||
cifs_dbg(FYI, "set sparse rc = %d\n", rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (setsparse)
|
||||
cifsi->cifsAttrs |= FILE_ATTRIBUTE_SPARSE_FILE;
|
||||
else
|
||||
cifsi->cifsAttrs &= (~FILE_ATTRIBUTE_SPARSE_FILE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
smb2_set_file_size(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct cifsFileInfo *cfile, __u64 size, bool set_alloc)
|
||||
{
|
||||
__le64 eof = cpu_to_le64(size);
|
||||
struct inode *inode;
|
||||
|
||||
/*
|
||||
* If extending file more than one page make sparse. Many Linux fs
|
||||
* make files sparse by default when extending via ftruncate
|
||||
*/
|
||||
inode = cfile->dentry->d_inode;
|
||||
|
||||
if (!set_alloc && (size > inode->i_size + 8192)) {
|
||||
__u8 set_sparse = 1;
|
||||
|
||||
/* whether set sparse succeeds or not, extend the file */
|
||||
smb2_set_sparse(xid, tcon, cfile, inode, set_sparse);
|
||||
}
|
||||
|
||||
return SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
|
||||
cfile->fid.volatile_fid, cfile->pid, &eof, false);
|
||||
}
|
||||
|
@ -954,6 +1015,105 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
|
||||
loff_t offset, loff_t len, bool keep_size)
|
||||
{
|
||||
struct inode *inode;
|
||||
struct cifsInodeInfo *cifsi;
|
||||
struct cifsFileInfo *cfile = file->private_data;
|
||||
struct file_zero_data_information fsctl_buf;
|
||||
long rc;
|
||||
unsigned int xid;
|
||||
|
||||
xid = get_xid();
|
||||
|
||||
inode = cfile->dentry->d_inode;
|
||||
cifsi = CIFS_I(inode);
|
||||
|
||||
/* if file not oplocked can't be sure whether asking to extend size */
|
||||
if (!CIFS_CACHE_READ(cifsi))
|
||||
if (keep_size == false)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/*
|
||||
* Must check if file sparse since fallocate -z (zero range) assumes
|
||||
* non-sparse allocation
|
||||
*/
|
||||
if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/*
|
||||
* need to make sure we are not asked to extend the file since the SMB3
|
||||
* fsctl does not change the file size. In the future we could change
|
||||
* this to zero the first part of the range then set the file size
|
||||
* which for a non sparse file would zero the newly extended range
|
||||
*/
|
||||
if (keep_size == false)
|
||||
if (i_size_read(inode) < offset + len)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
cifs_dbg(FYI, "offset %lld len %lld", offset, len);
|
||||
|
||||
fsctl_buf.FileOffset = cpu_to_le64(offset);
|
||||
fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len);
|
||||
|
||||
rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
|
||||
cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
|
||||
true /* is_fctl */, (char *)&fsctl_buf,
|
||||
sizeof(struct file_zero_data_information), NULL, NULL);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
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;
|
||||
unsigned int xid;
|
||||
__u8 set_sparse = 1;
|
||||
|
||||
xid = get_xid();
|
||||
|
||||
inode = cfile->dentry->d_inode;
|
||||
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 */
|
||||
if (!smb2_set_sparse(xid, tcon, cfile, inode, set_sparse))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
cifs_dbg(FYI, "offset %lld len %lld", offset, len);
|
||||
|
||||
fsctl_buf.FileOffset = cpu_to_le64(offset);
|
||||
fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len);
|
||||
|
||||
rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
|
||||
cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
|
||||
true /* is_fctl */, (char *)&fsctl_buf,
|
||||
sizeof(struct file_zero_data_information), NULL, NULL);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static long smb3_fallocate(struct file *file, struct cifs_tcon *tcon, int mode,
|
||||
loff_t off, loff_t len)
|
||||
{
|
||||
/* KEEP_SIZE already checked for by do_fallocate */
|
||||
if (mode & FALLOC_FL_PUNCH_HOLE)
|
||||
return smb3_punch_hole(file, tcon, off, len);
|
||||
else if (mode & FALLOC_FL_ZERO_RANGE) {
|
||||
if (mode & FALLOC_FL_KEEP_SIZE)
|
||||
return smb3_zero_range(file, tcon, off, len, true);
|
||||
return smb3_zero_range(file, tcon, off, len, false);
|
||||
}
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static void
|
||||
smb2_downgrade_oplock(struct TCP_Server_Info *server,
|
||||
struct cifsInodeInfo *cinode, bool set_level2)
|
||||
|
@ -1161,6 +1321,12 @@ smb2_wp_retry_size(struct inode *inode)
|
|||
SMB2_MAX_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
static bool
|
||||
smb2_dir_needs_close(struct cifsFileInfo *cfile)
|
||||
{
|
||||
return !cfile->invalidHandle;
|
||||
}
|
||||
|
||||
struct smb_version_operations smb20_operations = {
|
||||
.compare_fids = smb2_compare_fids,
|
||||
.setup_request = smb2_setup_request,
|
||||
|
@ -1236,6 +1402,7 @@ struct smb_version_operations smb20_operations = {
|
|||
.parse_lease_buf = smb2_parse_lease_buf,
|
||||
.clone_range = smb2_clone_range,
|
||||
.wp_retry_size = smb2_wp_retry_size,
|
||||
.dir_needs_close = smb2_dir_needs_close,
|
||||
};
|
||||
|
||||
struct smb_version_operations smb21_operations = {
|
||||
|
@ -1313,6 +1480,7 @@ struct smb_version_operations smb21_operations = {
|
|||
.parse_lease_buf = smb2_parse_lease_buf,
|
||||
.clone_range = smb2_clone_range,
|
||||
.wp_retry_size = smb2_wp_retry_size,
|
||||
.dir_needs_close = smb2_dir_needs_close,
|
||||
};
|
||||
|
||||
struct smb_version_operations smb30_operations = {
|
||||
|
@ -1393,6 +1561,8 @@ struct smb_version_operations smb30_operations = {
|
|||
.clone_range = smb2_clone_range,
|
||||
.validate_negotiate = smb3_validate_negotiate,
|
||||
.wp_retry_size = smb2_wp_retry_size,
|
||||
.dir_needs_close = smb2_dir_needs_close,
|
||||
.fallocate = smb3_fallocate,
|
||||
};
|
||||
|
||||
struct smb_version_values smb20_values = {
|
||||
|
|
|
@ -907,7 +907,8 @@ tcon_exit:
|
|||
tcon_error_exit:
|
||||
if (rsp->hdr.Status == STATUS_BAD_NETWORK_NAME) {
|
||||
cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree);
|
||||
tcon->bad_network_name = true;
|
||||
if (tcon)
|
||||
tcon->bad_network_name = true;
|
||||
}
|
||||
goto tcon_exit;
|
||||
}
|
||||
|
@ -1224,7 +1225,9 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
|
|||
|
||||
cifs_dbg(FYI, "SMB2 IOCTL\n");
|
||||
|
||||
*out_data = NULL;
|
||||
if (out_data != NULL)
|
||||
*out_data = NULL;
|
||||
|
||||
/* zero out returned data len, in case of error */
|
||||
if (plen)
|
||||
*plen = 0;
|
||||
|
@ -2177,6 +2180,10 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
rsp = (struct smb2_query_directory_rsp *)iov[0].iov_base;
|
||||
|
||||
if (rc) {
|
||||
if (rc == -ENODATA && rsp->hdr.Status == STATUS_NO_MORE_FILES) {
|
||||
srch_inf->endOfSearch = true;
|
||||
rc = 0;
|
||||
}
|
||||
cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
|
||||
goto qdir_exit;
|
||||
}
|
||||
|
@ -2214,11 +2221,6 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
else
|
||||
cifs_dbg(VFS, "illegal search buffer type\n");
|
||||
|
||||
if (rsp->hdr.Status == STATUS_NO_MORE_FILES)
|
||||
srch_inf->endOfSearch = 1;
|
||||
else
|
||||
srch_inf->endOfSearch = 0;
|
||||
|
||||
return rc;
|
||||
|
||||
qdir_exit:
|
||||
|
|
|
@ -573,6 +573,12 @@ struct copychunk_ioctl {
|
|||
__u32 Reserved2;
|
||||
} __packed;
|
||||
|
||||
/* this goes in the ioctl buffer when doing FSCTL_SET_ZERO_DATA */
|
||||
struct file_zero_data_information {
|
||||
__le64 FileOffset;
|
||||
__le64 BeyondFinalZero;
|
||||
} __packed;
|
||||
|
||||
struct copychunk_ioctl_rsp {
|
||||
__le32 ChunksWritten;
|
||||
__le32 ChunkBytesWritten;
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
#define FSCTL_SET_OBJECT_ID_EXTENDED 0x000900BC /* BB add struct */
|
||||
#define FSCTL_CREATE_OR_GET_OBJECT_ID 0x000900C0 /* BB add struct */
|
||||
#define FSCTL_SET_SPARSE 0x000900C4 /* BB add struct */
|
||||
#define FSCTL_SET_ZERO_DATA 0x000900C8 /* BB add struct */
|
||||
#define FSCTL_SET_ZERO_DATA 0x000980C8
|
||||
#define FSCTL_SET_ENCRYPTION 0x000900D7 /* BB add struct */
|
||||
#define FSCTL_ENCRYPTION_FSCTL_IO 0x000900DB /* BB add struct */
|
||||
#define FSCTL_WRITE_RAW_ENCRYPTED 0x000900DF /* BB add struct */
|
||||
|
|
Загрузка…
Ссылка в новой задаче