diff options
-rw-r--r-- | fs/cifs/CHANGES | 4 | ||||
-rw-r--r-- | fs/cifs/cifs_debug.c | 2 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 1 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 7 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 21 | ||||
-rw-r--r-- | fs/cifs/file.c | 7 |
7 files changed, 44 insertions, 1 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 851388fafc73..d43e0fe33398 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -6,7 +6,9 @@ the server to treat subsequent connections, especially those that | |||
6 | are authenticated as guest, as reconnections, invalidating the earlier | 6 | are authenticated as guest, as reconnections, invalidating the earlier |
7 | user's smb session. This fix allows cifs to mount multiple times to the | 7 | user's smb session. This fix allows cifs to mount multiple times to the |
8 | same server with different userids without risking invalidating earlier | 8 | same server with different userids without risking invalidating earlier |
9 | established security contexts. | 9 | established security contexts. fsync now sends SMB Flush operation |
10 | to better ensure that we wait for server to write all of the data to | ||
11 | server disk (not just write it over the network). | ||
10 | 12 | ||
11 | Version 1.56 | 13 | Version 1.56 |
12 | ------------ | 14 | ------------ |
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 490e34bbf27a..877e4d9a1159 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c | |||
@@ -340,6 +340,8 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v) | |||
340 | seq_printf(m, "\nWrites: %d Bytes: %lld", | 340 | seq_printf(m, "\nWrites: %d Bytes: %lld", |
341 | atomic_read(&tcon->num_writes), | 341 | atomic_read(&tcon->num_writes), |
342 | (long long)(tcon->bytes_written)); | 342 | (long long)(tcon->bytes_written)); |
343 | seq_printf(m, "\nFlushes: %d", | ||
344 | atomic_read(&tcon->num_flushes)); | ||
343 | seq_printf(m, "\nLocks: %d HardLinks: %d " | 345 | seq_printf(m, "\nLocks: %d HardLinks: %d " |
344 | "Symlinks: %d", | 346 | "Symlinks: %d", |
345 | atomic_read(&tcon->num_locks), | 347 | atomic_read(&tcon->num_locks), |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index e004f6db5fc8..44ff94d37e18 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -254,6 +254,7 @@ struct cifsTconInfo { | |||
254 | atomic_t num_smbs_sent; | 254 | atomic_t num_smbs_sent; |
255 | atomic_t num_writes; | 255 | atomic_t num_writes; |
256 | atomic_t num_reads; | 256 | atomic_t num_reads; |
257 | atomic_t num_flushes; | ||
257 | atomic_t num_oplock_brks; | 258 | atomic_t num_oplock_brks; |
258 | atomic_t num_opens; | 259 | atomic_t num_opens; |
259 | atomic_t num_closes; | 260 | atomic_t num_closes; |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index b4e2e9f0ee3d..eda6e511fd3e 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -43,6 +43,7 @@ | |||
43 | #define SMB_COM_CREATE_DIRECTORY 0x00 /* trivial response */ | 43 | #define SMB_COM_CREATE_DIRECTORY 0x00 /* trivial response */ |
44 | #define SMB_COM_DELETE_DIRECTORY 0x01 /* trivial response */ | 44 | #define SMB_COM_DELETE_DIRECTORY 0x01 /* trivial response */ |
45 | #define SMB_COM_CLOSE 0x04 /* triv req/rsp, timestamp ignored */ | 45 | #define SMB_COM_CLOSE 0x04 /* triv req/rsp, timestamp ignored */ |
46 | #define SMB_COM_FLUSH 0x05 /* triv req/rsp */ | ||
46 | #define SMB_COM_DELETE 0x06 /* trivial response */ | 47 | #define SMB_COM_DELETE 0x06 /* trivial response */ |
47 | #define SMB_COM_RENAME 0x07 /* trivial response */ | 48 | #define SMB_COM_RENAME 0x07 /* trivial response */ |
48 | #define SMB_COM_QUERY_INFORMATION 0x08 /* aka getattr */ | 49 | #define SMB_COM_QUERY_INFORMATION 0x08 /* aka getattr */ |
@@ -790,6 +791,12 @@ typedef struct smb_com_close_rsp { | |||
790 | __u16 ByteCount; /* bct = 0 */ | 791 | __u16 ByteCount; /* bct = 0 */ |
791 | } __attribute__((packed)) CLOSE_RSP; | 792 | } __attribute__((packed)) CLOSE_RSP; |
792 | 793 | ||
794 | typedef struct smb_com_flush_req { | ||
795 | struct smb_hdr hdr; /* wct = 1 */ | ||
796 | __u16 FileID; | ||
797 | __u16 ByteCount; /* 0 */ | ||
798 | } __attribute__((packed)) FLUSH_REQ; | ||
799 | |||
793 | typedef struct smb_com_findclose_req { | 800 | typedef struct smb_com_findclose_req { |
794 | struct smb_hdr hdr; /* wct = 1 */ | 801 | struct smb_hdr hdr; /* wct = 1 */ |
795 | __u16 FileID; | 802 | __u16 FileID; |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 083dfc57c7a3..596fc8689371 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -281,6 +281,9 @@ extern int CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, | |||
281 | extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, | 281 | extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, |
282 | const int smb_file_id); | 282 | const int smb_file_id); |
283 | 283 | ||
284 | extern int CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, | ||
285 | const int smb_file_id); | ||
286 | |||
284 | extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, | 287 | extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, |
285 | const int netfid, unsigned int count, | 288 | const int netfid, unsigned int count, |
286 | const __u64 lseek, unsigned int *nbytes, char **buf, | 289 | const __u64 lseek, unsigned int *nbytes, char **buf, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 939e2f76b959..4c344fe7a152 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -1934,6 +1934,27 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) | |||
1934 | } | 1934 | } |
1935 | 1935 | ||
1936 | int | 1936 | int |
1937 | CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id) | ||
1938 | { | ||
1939 | int rc = 0; | ||
1940 | FLUSH_REQ *pSMB = NULL; | ||
1941 | cFYI(1, ("In CIFSSMBFlush")); | ||
1942 | |||
1943 | rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB); | ||
1944 | if (rc) | ||
1945 | return rc; | ||
1946 | |||
1947 | pSMB->FileID = (__u16) smb_file_id; | ||
1948 | pSMB->ByteCount = 0; | ||
1949 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | ||
1950 | cifs_stats_inc(&tcon->num_flushes); | ||
1951 | if (rc) | ||
1952 | cERROR(1, ("Send error in Flush = %d", rc)); | ||
1953 | |||
1954 | return rc; | ||
1955 | } | ||
1956 | |||
1957 | int | ||
1937 | CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, | 1958 | CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, |
1938 | const char *fromName, const char *toName, | 1959 | const char *fromName, const char *toName, |
1939 | const struct nls_table *nls_codepage, int remap) | 1960 | const struct nls_table *nls_codepage, int remap) |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 12bb656fbe75..83b4741b6ad0 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -1523,6 +1523,9 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) | |||
1523 | { | 1523 | { |
1524 | int xid; | 1524 | int xid; |
1525 | int rc = 0; | 1525 | int rc = 0; |
1526 | struct cifsTconInfo *tcon; | ||
1527 | struct cifsFileInfo *smbfile = | ||
1528 | (struct cifsFileInfo *)file->private_data; | ||
1526 | struct inode *inode = file->f_path.dentry->d_inode; | 1529 | struct inode *inode = file->f_path.dentry->d_inode; |
1527 | 1530 | ||
1528 | xid = GetXid(); | 1531 | xid = GetXid(); |
@@ -1534,7 +1537,11 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) | |||
1534 | if (rc == 0) { | 1537 | if (rc == 0) { |
1535 | rc = CIFS_I(inode)->write_behind_rc; | 1538 | rc = CIFS_I(inode)->write_behind_rc; |
1536 | CIFS_I(inode)->write_behind_rc = 0; | 1539 | CIFS_I(inode)->write_behind_rc = 0; |
1540 | tcon = CIFS_SB(inode->i_sb)->tcon; | ||
1541 | if (!rc && tcon && smbfile) | ||
1542 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); | ||
1537 | } | 1543 | } |
1544 | |||
1538 | FreeXid(xid); | 1545 | FreeXid(xid); |
1539 | return rc; | 1546 | return rc; |
1540 | } | 1547 | } |