Skip to content

Commit 372b1db

Browse files
committed
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
2 parents 92075f9 + 3017562 commit 372b1db

File tree

14 files changed

+269
-22
lines changed

14 files changed

+269
-22
lines changed

fs/cifs/cifsfs.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,19 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
207207
return 0;
208208
}
209209

210+
static long cifs_fallocate(struct file *file, int mode, loff_t off, loff_t len)
211+
{
212+
struct super_block *sb = file->f_path.dentry->d_sb;
213+
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
214+
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
215+
struct TCP_Server_Info *server = tcon->ses->server;
216+
217+
if (server->ops->fallocate)
218+
return server->ops->fallocate(file, tcon, mode, off, len);
219+
220+
return -EOPNOTSUPP;
221+
}
222+
210223
static int cifs_permission(struct inode *inode, int mask)
211224
{
212225
struct cifs_sb_info *cifs_sb;
@@ -812,8 +825,9 @@ static int cifs_setlease(struct file *file, long arg, struct file_lock **lease)
812825
if (!(S_ISREG(inode->i_mode)))
813826
return -EINVAL;
814827

815-
/* check if file is oplocked */
816-
if (((arg == F_RDLCK) && CIFS_CACHE_READ(CIFS_I(inode))) ||
828+
/* Check if file is oplocked if this is request for new lease */
829+
if (arg == F_UNLCK ||
830+
((arg == F_RDLCK) && CIFS_CACHE_READ(CIFS_I(inode))) ||
817831
((arg == F_WRLCK) && CIFS_CACHE_WRITE(CIFS_I(inode))))
818832
return generic_setlease(file, arg, lease);
819833
else if (tlink_tcon(cfile->tlink)->local_lease &&
@@ -908,6 +922,7 @@ const struct file_operations cifs_file_ops = {
908922
.unlocked_ioctl = cifs_ioctl,
909923
#endif /* CONFIG_CIFS_POSIX */
910924
.setlease = cifs_setlease,
925+
.fallocate = cifs_fallocate,
911926
};
912927

913928
const struct file_operations cifs_file_strict_ops = {
@@ -927,6 +942,7 @@ const struct file_operations cifs_file_strict_ops = {
927942
.unlocked_ioctl = cifs_ioctl,
928943
#endif /* CONFIG_CIFS_POSIX */
929944
.setlease = cifs_setlease,
945+
.fallocate = cifs_fallocate,
930946
};
931947

932948
const struct file_operations cifs_file_direct_ops = {
@@ -947,6 +963,7 @@ const struct file_operations cifs_file_direct_ops = {
947963
#endif /* CONFIG_CIFS_POSIX */
948964
.llseek = cifs_llseek,
949965
.setlease = cifs_setlease,
966+
.fallocate = cifs_fallocate,
950967
};
951968

952969
const struct file_operations cifs_file_nobrl_ops = {
@@ -965,6 +982,7 @@ const struct file_operations cifs_file_nobrl_ops = {
965982
.unlocked_ioctl = cifs_ioctl,
966983
#endif /* CONFIG_CIFS_POSIX */
967984
.setlease = cifs_setlease,
985+
.fallocate = cifs_fallocate,
968986
};
969987

970988
const struct file_operations cifs_file_strict_nobrl_ops = {
@@ -983,6 +1001,7 @@ const struct file_operations cifs_file_strict_nobrl_ops = {
9831001
.unlocked_ioctl = cifs_ioctl,
9841002
#endif /* CONFIG_CIFS_POSIX */
9851003
.setlease = cifs_setlease,
1004+
.fallocate = cifs_fallocate,
9861005
};
9871006

9881007
const struct file_operations cifs_file_direct_nobrl_ops = {
@@ -1002,6 +1021,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = {
10021021
#endif /* CONFIG_CIFS_POSIX */
10031022
.llseek = cifs_llseek,
10041023
.setlease = cifs_setlease,
1024+
.fallocate = cifs_fallocate,
10051025
};
10061026

10071027
const struct file_operations cifs_dir_ops = {

fs/cifs/cifsglob.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,10 @@ struct smb_version_operations {
409409
/* get mtu credits */
410410
int (*wait_mtu_credits)(struct TCP_Server_Info *, unsigned int,
411411
unsigned int *, unsigned int *);
412+
/* check if we need to issue closedir */
413+
bool (*dir_needs_close)(struct cifsFileInfo *);
414+
long (*fallocate)(struct file *, struct cifs_tcon *, int, loff_t,
415+
loff_t);
412416
};
413417

414418
struct smb_version_values {
@@ -883,6 +887,7 @@ struct cifs_tcon {
883887
for this mount even if server would support */
884888
bool local_lease:1; /* check leases (only) on local system not remote */
885889
bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */
890+
bool broken_sparse_sup; /* if server or share does not support sparse */
886891
bool need_reconnect:1; /* connection reset, tid now invalid */
887892
#ifdef CONFIG_CIFS_SMB2
888893
bool print:1; /* set if connection to printer share */

fs/cifs/cifspdu.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2253,6 +2253,29 @@ typedef struct {
22532253
/* minimum includes first three fields, and empty FS Name */
22542254
#define MIN_FS_ATTR_INFO_SIZE 12
22552255

2256+
2257+
/* List of FileSystemAttributes - see 2.5.1 of MS-FSCC */
2258+
#define FILE_SUPPORT_INTEGRITY_STREAMS 0x04000000
2259+
#define FILE_SUPPORTS_USN_JOURNAL 0x02000000
2260+
#define FILE_SUPPORTS_OPEN_BY_FILE_ID 0x01000000
2261+
#define FILE_SUPPORTS_EXTENDED_ATTRIBUTES 0x00800000
2262+
#define FILE_SUPPORTS_HARD_LINKS 0x00400000
2263+
#define FILE_SUPPORTS_TRANSACTIONS 0x00200000
2264+
#define FILE_SEQUENTIAL_WRITE_ONCE 0x00100000
2265+
#define FILE_READ_ONLY_VOLUME 0x00080000
2266+
#define FILE_NAMED_STREAMS 0x00040000
2267+
#define FILE_SUPPORTS_ENCRYPTION 0x00020000
2268+
#define FILE_SUPPORTS_OBJECT_IDS 0x00010000
2269+
#define FILE_VOLUME_IS_COMPRESSED 0x00008000
2270+
#define FILE_SUPPORTS_REMOTE_STORAGE 0x00000100
2271+
#define FILE_SUPPORTS_REPARSE_POINTS 0x00000080
2272+
#define FILE_SUPPORTS_SPARSE_FILES 0x00000040
2273+
#define FILE_VOLUME_QUOTAS 0x00000020
2274+
#define FILE_FILE_COMPRESSION 0x00000010
2275+
#define FILE_PERSISTENT_ACLS 0x00000008
2276+
#define FILE_UNICODE_ON_DISK 0x00000004
2277+
#define FILE_CASE_PRESERVED_NAMES 0x00000002
2278+
#define FILE_CASE_SENSITIVE_SEARCH 0x00000001
22562279
typedef struct {
22572280
__le32 Attributes;
22582281
__le32 MaxPathNameComponentLength;

fs/cifs/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -762,7 +762,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
762762

763763
cifs_dbg(FYI, "Freeing private data in close dir\n");
764764
spin_lock(&cifs_file_list_lock);
765-
if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) {
765+
if (server->ops->dir_needs_close(cfile)) {
766766
cfile->invalidHandle = true;
767767
spin_unlock(&cifs_file_list_lock);
768768
if (server->ops->close_dir)

fs/cifs/inode.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1727,6 +1727,12 @@ cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
17271727
target_dentry, to_name);
17281728
}
17291729

1730+
/* force revalidate to go get info when needed */
1731+
CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
1732+
1733+
source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
1734+
target_dir->i_mtime = current_fs_time(source_dir->i_sb);
1735+
17301736
cifs_rename_exit:
17311737
kfree(info_buf_source);
17321738
kfree(from_name);

fs/cifs/misc.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -574,13 +574,6 @@ void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock)
574574
cinode->oplock = 0;
575575
}
576576

577-
static int
578-
cifs_oplock_break_wait(void *unused)
579-
{
580-
schedule();
581-
return signal_pending(current) ? -ERESTARTSYS : 0;
582-
}
583-
584577
/*
585578
* We wait for oplock breaks to be processed before we attempt to perform
586579
* writes.

fs/cifs/readdir.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
593593
/* close and restart search */
594594
cifs_dbg(FYI, "search backing up - close and restart search\n");
595595
spin_lock(&cifs_file_list_lock);
596-
if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) {
596+
if (server->ops->dir_needs_close(cfile)) {
597597
cfile->invalidHandle = true;
598598
spin_unlock(&cifs_file_list_lock);
599599
if (server->ops->close)

fs/cifs/smb1ops.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,6 +1015,12 @@ cifs_wp_retry_size(struct inode *inode)
10151015
return CIFS_SB(inode->i_sb)->wsize;
10161016
}
10171017

1018+
static bool
1019+
cifs_dir_needs_close(struct cifsFileInfo *cfile)
1020+
{
1021+
return !cfile->srch_inf.endOfSearch && !cfile->invalidHandle;
1022+
}
1023+
10181024
struct smb_version_operations smb1_operations = {
10191025
.send_cancel = send_nt_cancel,
10201026
.compare_fids = cifs_compare_fids,
@@ -1086,6 +1092,7 @@ struct smb_version_operations smb1_operations = {
10861092
.create_mf_symlink = cifs_create_mf_symlink,
10871093
.is_read_op = cifs_is_read_op,
10881094
.wp_retry_size = cifs_wp_retry_size,
1095+
.dir_needs_close = cifs_dir_needs_close,
10891096
#ifdef CONFIG_CIFS_XATTR
10901097
.query_all_EAs = CIFSSMBQAllEAs,
10911098
.set_EA = CIFSSMBSetEA,

fs/cifs/smb2maperror.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
214214
{STATUS_BREAKPOINT, -EIO, "STATUS_BREAKPOINT"},
215215
{STATUS_SINGLE_STEP, -EIO, "STATUS_SINGLE_STEP"},
216216
{STATUS_BUFFER_OVERFLOW, -EIO, "STATUS_BUFFER_OVERFLOW"},
217-
{STATUS_NO_MORE_FILES, -EIO, "STATUS_NO_MORE_FILES"},
217+
{STATUS_NO_MORE_FILES, -ENODATA, "STATUS_NO_MORE_FILES"},
218218
{STATUS_WAKE_SYSTEM_DEBUGGER, -EIO, "STATUS_WAKE_SYSTEM_DEBUGGER"},
219219
{STATUS_HANDLES_CLOSED, -EIO, "STATUS_HANDLES_CLOSED"},
220220
{STATUS_NO_INHERITANCE, -EIO, "STATUS_NO_INHERITANCE"},
@@ -298,7 +298,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
298298
{STATUS_INVALID_PARAMETER, -EINVAL, "STATUS_INVALID_PARAMETER"},
299299
{STATUS_NO_SUCH_DEVICE, -ENODEV, "STATUS_NO_SUCH_DEVICE"},
300300
{STATUS_NO_SUCH_FILE, -ENOENT, "STATUS_NO_SUCH_FILE"},
301-
{STATUS_INVALID_DEVICE_REQUEST, -EIO, "STATUS_INVALID_DEVICE_REQUEST"},
301+
{STATUS_INVALID_DEVICE_REQUEST, -EOPNOTSUPP, "STATUS_INVALID_DEVICE_REQUEST"},
302302
{STATUS_END_OF_FILE, -ENODATA, "STATUS_END_OF_FILE"},
303303
{STATUS_WRONG_VOLUME, -EIO, "STATUS_WRONG_VOLUME"},
304304
{STATUS_NO_MEDIA_IN_DEVICE, -EIO, "STATUS_NO_MEDIA_IN_DEVICE"},

fs/cifs/smb2misc.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,24 @@ smb2_check_message(char *buf, unsigned int length)
178178
/* Windows 7 server returns 24 bytes more */
179179
if (clc_len + 20 == len && command == SMB2_OPLOCK_BREAK_HE)
180180
return 0;
181-
/* server can return one byte more */
181+
/* server can return one byte more due to implied bcc[0] */
182182
if (clc_len == 4 + len + 1)
183183
return 0;
184+
185+
/*
186+
* MacOS server pads after SMB2.1 write response with 3 bytes
187+
* of junk. Other servers match RFC1001 len to actual
188+
* SMB2/SMB3 frame length (header + smb2 response specific data)
189+
* Log the server error (once), but allow it and continue
190+
* since the frame is parseable.
191+
*/
192+
if (clc_len < 4 /* RFC1001 header size */ + len) {
193+
printk_once(KERN_WARNING
194+
"SMB2 server sent bad RFC1001 len %d not %d\n",
195+
len, clc_len - 4);
196+
return 0;
197+
}
198+
184199
return 1;
185200
}
186201
return 0;

0 commit comments

Comments
 (0)