Skip to content

Commit 84ced7f

Browse files
committed
Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6
Pull CIFS fixes from Steve French: "This is a set of CIFS/SMB3 fixes for stable. There is another set of four SMB3 reconnect fixes for stable in progress but they are still being reviewed/tested, so didn't want to wait any longer to send these five below" * 'for-next' of git://git.samba.org/sfrench/cifs-2.6: Reset TreeId to zero on SMB2 TREE_CONNECT CIFS: Fix build failure with smb2 Introduce cifs_copy_file_range() SMB3: Rename clone_range to copychunk_range Handle mismatched open calls
2 parents 462e9a3 + 806a28e commit 84ced7f

13 files changed

+268
-90
lines changed

fs/cifs/cifsfs.c

+87
Original file line numberDiff line numberDiff line change
@@ -972,6 +972,86 @@ static int cifs_clone_file_range(struct file *src_file, loff_t off,
972972
return rc;
973973
}
974974

975+
ssize_t cifs_file_copychunk_range(unsigned int xid,
976+
struct file *src_file, loff_t off,
977+
struct file *dst_file, loff_t destoff,
978+
size_t len, unsigned int flags)
979+
{
980+
struct inode *src_inode = file_inode(src_file);
981+
struct inode *target_inode = file_inode(dst_file);
982+
struct cifsFileInfo *smb_file_src;
983+
struct cifsFileInfo *smb_file_target;
984+
struct cifs_tcon *src_tcon;
985+
struct cifs_tcon *target_tcon;
986+
ssize_t rc;
987+
988+
cifs_dbg(FYI, "copychunk range\n");
989+
990+
if (src_inode == target_inode) {
991+
rc = -EINVAL;
992+
goto out;
993+
}
994+
995+
if (!src_file->private_data || !dst_file->private_data) {
996+
rc = -EBADF;
997+
cifs_dbg(VFS, "missing cifsFileInfo on copy range src file\n");
998+
goto out;
999+
}
1000+
1001+
rc = -EXDEV;
1002+
smb_file_target = dst_file->private_data;
1003+
smb_file_src = src_file->private_data;
1004+
src_tcon = tlink_tcon(smb_file_src->tlink);
1005+
target_tcon = tlink_tcon(smb_file_target->tlink);
1006+
1007+
if (src_tcon->ses != target_tcon->ses) {
1008+
cifs_dbg(VFS, "source and target of copy not on same server\n");
1009+
goto out;
1010+
}
1011+
1012+
/*
1013+
* Note: cifs case is easier than btrfs since server responsible for
1014+
* checks for proper open modes and file type and if it wants
1015+
* server could even support copy of range where source = target
1016+
*/
1017+
lock_two_nondirectories(target_inode, src_inode);
1018+
1019+
cifs_dbg(FYI, "about to flush pages\n");
1020+
/* should we flush first and last page first */
1021+
truncate_inode_pages(&target_inode->i_data, 0);
1022+
1023+
if (target_tcon->ses->server->ops->copychunk_range)
1024+
rc = target_tcon->ses->server->ops->copychunk_range(xid,
1025+
smb_file_src, smb_file_target, off, len, destoff);
1026+
else
1027+
rc = -EOPNOTSUPP;
1028+
1029+
/* force revalidate of size and timestamps of target file now
1030+
* that target is updated on the server
1031+
*/
1032+
CIFS_I(target_inode)->time = 0;
1033+
/* although unlocking in the reverse order from locking is not
1034+
* strictly necessary here it is a little cleaner to be consistent
1035+
*/
1036+
unlock_two_nondirectories(src_inode, target_inode);
1037+
1038+
out:
1039+
return rc;
1040+
}
1041+
1042+
static ssize_t cifs_copy_file_range(struct file *src_file, loff_t off,
1043+
struct file *dst_file, loff_t destoff,
1044+
size_t len, unsigned int flags)
1045+
{
1046+
unsigned int xid = get_xid();
1047+
ssize_t rc;
1048+
1049+
rc = cifs_file_copychunk_range(xid, src_file, off, dst_file, destoff,
1050+
len, flags);
1051+
free_xid(xid);
1052+
return rc;
1053+
}
1054+
9751055
const struct file_operations cifs_file_ops = {
9761056
.read_iter = cifs_loose_read_iter,
9771057
.write_iter = cifs_file_write_iter,
@@ -984,6 +1064,7 @@ const struct file_operations cifs_file_ops = {
9841064
.splice_read = generic_file_splice_read,
9851065
.llseek = cifs_llseek,
9861066
.unlocked_ioctl = cifs_ioctl,
1067+
.copy_file_range = cifs_copy_file_range,
9871068
.clone_file_range = cifs_clone_file_range,
9881069
.setlease = cifs_setlease,
9891070
.fallocate = cifs_fallocate,
@@ -1001,6 +1082,7 @@ const struct file_operations cifs_file_strict_ops = {
10011082
.splice_read = generic_file_splice_read,
10021083
.llseek = cifs_llseek,
10031084
.unlocked_ioctl = cifs_ioctl,
1085+
.copy_file_range = cifs_copy_file_range,
10041086
.clone_file_range = cifs_clone_file_range,
10051087
.setlease = cifs_setlease,
10061088
.fallocate = cifs_fallocate,
@@ -1018,6 +1100,7 @@ const struct file_operations cifs_file_direct_ops = {
10181100
.mmap = cifs_file_mmap,
10191101
.splice_read = generic_file_splice_read,
10201102
.unlocked_ioctl = cifs_ioctl,
1103+
.copy_file_range = cifs_copy_file_range,
10211104
.clone_file_range = cifs_clone_file_range,
10221105
.llseek = cifs_llseek,
10231106
.setlease = cifs_setlease,
@@ -1035,6 +1118,7 @@ const struct file_operations cifs_file_nobrl_ops = {
10351118
.splice_read = generic_file_splice_read,
10361119
.llseek = cifs_llseek,
10371120
.unlocked_ioctl = cifs_ioctl,
1121+
.copy_file_range = cifs_copy_file_range,
10381122
.clone_file_range = cifs_clone_file_range,
10391123
.setlease = cifs_setlease,
10401124
.fallocate = cifs_fallocate,
@@ -1051,6 +1135,7 @@ const struct file_operations cifs_file_strict_nobrl_ops = {
10511135
.splice_read = generic_file_splice_read,
10521136
.llseek = cifs_llseek,
10531137
.unlocked_ioctl = cifs_ioctl,
1138+
.copy_file_range = cifs_copy_file_range,
10541139
.clone_file_range = cifs_clone_file_range,
10551140
.setlease = cifs_setlease,
10561141
.fallocate = cifs_fallocate,
@@ -1067,6 +1152,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = {
10671152
.mmap = cifs_file_mmap,
10681153
.splice_read = generic_file_splice_read,
10691154
.unlocked_ioctl = cifs_ioctl,
1155+
.copy_file_range = cifs_copy_file_range,
10701156
.clone_file_range = cifs_clone_file_range,
10711157
.llseek = cifs_llseek,
10721158
.setlease = cifs_setlease,
@@ -1078,6 +1164,7 @@ const struct file_operations cifs_dir_ops = {
10781164
.release = cifs_closedir,
10791165
.read = generic_read_dir,
10801166
.unlocked_ioctl = cifs_ioctl,
1167+
.copy_file_range = cifs_copy_file_range,
10811168
.clone_file_range = cifs_clone_file_range,
10821169
.llseek = generic_file_llseek,
10831170
};

fs/cifs/cifsfs.h

+5
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
139139
# define cifs_listxattr NULL
140140
#endif
141141

142+
extern ssize_t cifs_file_copychunk_range(unsigned int xid,
143+
struct file *src_file, loff_t off,
144+
struct file *dst_file, loff_t destoff,
145+
size_t len, unsigned int flags);
146+
142147
extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
143148
#ifdef CONFIG_CIFS_NFSD_EXPORT
144149
extern const struct export_operations cifs_export_ops;

fs/cifs/cifsglob.h

+15-3
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ struct smb_version_operations {
243243
/* verify the message */
244244
int (*check_message)(char *, unsigned int, struct TCP_Server_Info *);
245245
bool (*is_oplock_break)(char *, struct TCP_Server_Info *);
246+
int (*handle_cancelled_mid)(char *, struct TCP_Server_Info *);
246247
void (*downgrade_oplock)(struct TCP_Server_Info *,
247248
struct cifsInodeInfo *, bool);
248249
/* process transaction2 response */
@@ -407,9 +408,10 @@ struct smb_version_operations {
407408
char * (*create_lease_buf)(u8 *, u8);
408409
/* parse lease context buffer and return oplock/epoch info */
409410
__u8 (*parse_lease_buf)(void *, unsigned int *);
410-
int (*clone_range)(const unsigned int, struct cifsFileInfo *src_file,
411-
struct cifsFileInfo *target_file, u64 src_off, u64 len,
412-
u64 dest_off);
411+
ssize_t (*copychunk_range)(const unsigned int,
412+
struct cifsFileInfo *src_file,
413+
struct cifsFileInfo *target_file,
414+
u64 src_off, u64 len, u64 dest_off);
413415
int (*duplicate_extents)(const unsigned int, struct cifsFileInfo *src,
414416
struct cifsFileInfo *target_file, u64 src_off, u64 len,
415417
u64 dest_off);
@@ -1343,13 +1345,20 @@ struct mid_q_entry {
13431345
void *callback_data; /* general purpose pointer for callback */
13441346
void *resp_buf; /* pointer to received SMB header */
13451347
int mid_state; /* wish this were enum but can not pass to wait_event */
1348+
unsigned int mid_flags;
13461349
__le16 command; /* smb command code */
13471350
bool large_buf:1; /* if valid response, is pointer to large buf */
13481351
bool multiRsp:1; /* multiple trans2 responses for one request */
13491352
bool multiEnd:1; /* both received */
13501353
bool decrypted:1; /* decrypted entry */
13511354
};
13521355

1356+
struct close_cancelled_open {
1357+
struct cifs_fid fid;
1358+
struct cifs_tcon *tcon;
1359+
struct work_struct work;
1360+
};
1361+
13531362
/* Make code in transport.c a little cleaner by moving
13541363
update of optional stats into function below */
13551364
#ifdef CONFIG_CIFS_STATS2
@@ -1481,6 +1490,9 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,
14811490
#define MID_RESPONSE_MALFORMED 0x10
14821491
#define MID_SHUTDOWN 0x20
14831492

1493+
/* Flags */
1494+
#define MID_WAIT_CANCELLED 1 /* Cancelled while waiting for response */
1495+
14841496
/* Types of response buffer returned from SendReceive2 */
14851497
#define CIFS_NO_BUFFER 0 /* Response buffer not returned */
14861498
#define CIFS_SMALL_BUFFER 1

fs/cifs/cifsproto.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ extern void cifs_delete_mid(struct mid_q_entry *mid);
7979
extern void cifs_wake_up_task(struct mid_q_entry *mid);
8080
extern int cifs_handle_standard(struct TCP_Server_Info *server,
8181
struct mid_q_entry *mid);
82-
extern int cifs_discard_remaining_data(struct TCP_Server_Info *server);
82+
extern int cifs_discard_remaining_data(struct TCP_Server_Info *server,
83+
char *buf);
8384
extern int cifs_call_async(struct TCP_Server_Info *server,
8485
struct smb_rqst *rqst,
8586
mid_receive_t *receive, mid_callback_t *callback,

fs/cifs/cifssmb.c

+7-4
Original file line numberDiff line numberDiff line change
@@ -1400,9 +1400,9 @@ CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
14001400
* current bigbuf.
14011401
*/
14021402
int
1403-
cifs_discard_remaining_data(struct TCP_Server_Info *server)
1403+
cifs_discard_remaining_data(struct TCP_Server_Info *server, char *buf)
14041404
{
1405-
unsigned int rfclen = get_rfc1002_length(server->smallbuf);
1405+
unsigned int rfclen = get_rfc1002_length(buf);
14061406
int remaining = rfclen + 4 - server->total_read;
14071407

14081408
while (remaining > 0) {
@@ -1426,7 +1426,7 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
14261426
int length;
14271427
struct cifs_readdata *rdata = mid->callback_data;
14281428

1429-
length = cifs_discard_remaining_data(server);
1429+
length = cifs_discard_remaining_data(server, mid->resp_buf);
14301430
dequeue_mid(mid, rdata->result);
14311431
return length;
14321432
}
@@ -1459,7 +1459,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
14591459

14601460
if (server->ops->is_status_pending &&
14611461
server->ops->is_status_pending(buf, server, 0)) {
1462-
cifs_discard_remaining_data(server);
1462+
cifs_discard_remaining_data(server, buf);
14631463
return -1;
14641464
}
14651465

@@ -1519,6 +1519,9 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
15191519
cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n",
15201520
rdata->iov[0].iov_base, server->total_read);
15211521

1522+
mid->resp_buf = server->smallbuf;
1523+
server->smallbuf = NULL;
1524+
15221525
/* how much data is in the response? */
15231526
data_len = server->ops->read_data_length(buf);
15241527
if (data_offset + data_len > buflen) {

fs/cifs/connect.c

+11-2
Original file line numberDiff line numberDiff line change
@@ -904,10 +904,19 @@ cifs_demultiplex_thread(void *p)
904904

905905
server->lstrp = jiffies;
906906
if (mid_entry != NULL) {
907+
if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) &&
908+
mid_entry->mid_state == MID_RESPONSE_RECEIVED &&
909+
server->ops->handle_cancelled_mid)
910+
server->ops->handle_cancelled_mid(
911+
mid_entry->resp_buf,
912+
server);
913+
907914
if (!mid_entry->multiRsp || mid_entry->multiEnd)
908915
mid_entry->callback(mid_entry);
909-
} else if (!server->ops->is_oplock_break ||
910-
!server->ops->is_oplock_break(buf, server)) {
916+
} else if (server->ops->is_oplock_break &&
917+
server->ops->is_oplock_break(buf, server)) {
918+
cifs_dbg(FYI, "Received oplock break\n");
919+
} else {
911920
cifs_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
912921
atomic_read(&midCount));
913922
cifs_dump_mem("Received Data is: ", buf,

fs/cifs/ioctl.c

+5-61
Original file line numberDiff line numberDiff line change
@@ -34,71 +34,14 @@
3434
#include "cifs_ioctl.h"
3535
#include <linux/btrfs.h>
3636

37-
static int cifs_file_clone_range(unsigned int xid, struct file *src_file,
38-
struct file *dst_file)
39-
{
40-
struct inode *src_inode = file_inode(src_file);
41-
struct inode *target_inode = file_inode(dst_file);
42-
struct cifsFileInfo *smb_file_src;
43-
struct cifsFileInfo *smb_file_target;
44-
struct cifs_tcon *src_tcon;
45-
struct cifs_tcon *target_tcon;
46-
int rc;
47-
48-
cifs_dbg(FYI, "ioctl clone range\n");
49-
50-
if (!src_file->private_data || !dst_file->private_data) {
51-
rc = -EBADF;
52-
cifs_dbg(VFS, "missing cifsFileInfo on copy range src file\n");
53-
goto out;
54-
}
55-
56-
rc = -EXDEV;
57-
smb_file_target = dst_file->private_data;
58-
smb_file_src = src_file->private_data;
59-
src_tcon = tlink_tcon(smb_file_src->tlink);
60-
target_tcon = tlink_tcon(smb_file_target->tlink);
61-
62-
if (src_tcon->ses != target_tcon->ses) {
63-
cifs_dbg(VFS, "source and target of copy not on same server\n");
64-
goto out;
65-
}
66-
67-
/*
68-
* Note: cifs case is easier than btrfs since server responsible for
69-
* checks for proper open modes and file type and if it wants
70-
* server could even support copy of range where source = target
71-
*/
72-
lock_two_nondirectories(target_inode, src_inode);
73-
74-
cifs_dbg(FYI, "about to flush pages\n");
75-
/* should we flush first and last page first */
76-
truncate_inode_pages(&target_inode->i_data, 0);
77-
78-
if (target_tcon->ses->server->ops->clone_range)
79-
rc = target_tcon->ses->server->ops->clone_range(xid,
80-
smb_file_src, smb_file_target, 0, src_inode->i_size, 0);
81-
else
82-
rc = -EOPNOTSUPP;
83-
84-
/* force revalidate of size and timestamps of target file now
85-
that target is updated on the server */
86-
CIFS_I(target_inode)->time = 0;
87-
/* although unlocking in the reverse order from locking is not
88-
strictly necessary here it is a little cleaner to be consistent */
89-
unlock_two_nondirectories(src_inode, target_inode);
90-
out:
91-
return rc;
92-
}
93-
94-
static long cifs_ioctl_clone(unsigned int xid, struct file *dst_file,
37+
static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
9538
unsigned long srcfd)
9639
{
9740
int rc;
9841
struct fd src_file;
9942
struct inode *src_inode;
10043

101-
cifs_dbg(FYI, "ioctl clone range\n");
44+
cifs_dbg(FYI, "ioctl copychunk range\n");
10245
/* the destination must be opened for writing */
10346
if (!(dst_file->f_mode & FMODE_WRITE)) {
10447
cifs_dbg(FYI, "file target not open for write\n");
@@ -129,7 +72,8 @@ static long cifs_ioctl_clone(unsigned int xid, struct file *dst_file,
12972
if (S_ISDIR(src_inode->i_mode))
13073
goto out_fput;
13174

132-
rc = cifs_file_clone_range(xid, src_file.file, dst_file);
75+
rc = cifs_file_copychunk_range(xid, src_file.file, 0, dst_file, 0,
76+
src_inode->i_size, 0);
13377

13478
out_fput:
13579
fdput(src_file);
@@ -251,7 +195,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
251195
}
252196
break;
253197
case CIFS_IOC_COPYCHUNK_FILE:
254-
rc = cifs_ioctl_clone(xid, filep, arg);
198+
rc = cifs_ioctl_copychunk(xid, filep, arg);
255199
break;
256200
case CIFS_IOC_SET_INTEGRITY:
257201
if (pSMBFile == NULL)

0 commit comments

Comments
 (0)