Commit b298f223559e0205244f553ceef8c7df3674da74

Authored by Steve French
1 parent ebdcc81c71

[CIFS] Send SMB flush in cifs_fsync

In contrast to the now-obsolete smbfs, cifs does not send SMB_COM_FLUSH
in response to an explicit fsync(2) to guarantee that all volatile data
is written to stable storage on the server side, provided the server
honors the request (which, to my knowledge, is true for Windows and
Samba with 'strict sync' enabled).
This patch modifies the cifs_fsync implementation to restore the
fsync-behavior of smbfs by triggering SMB_COM_FLUSH after sending
outstanding data on the client side to the server.

Signed-off-by: Horst Reiterer <horst.reiterer@gmail.com>
Acked-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>

Showing 7 changed files with 44 additions and 1 deletions Side-by-side Diff

... ... @@ -6,7 +6,9 @@
6 6 are authenticated as guest, as reconnections, invalidating the earlier
7 7 user's smb session. This fix allows cifs to mount multiple times to the
8 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 13 Version 1.56
12 14 ------------
fs/cifs/cifs_debug.c
... ... @@ -340,6 +340,8 @@
340 340 seq_printf(m, "\nWrites: %d Bytes: %lld",
341 341 atomic_read(&tcon->num_writes),
342 342 (long long)(tcon->bytes_written));
  343 + seq_printf(m, "\nFlushes: %d",
  344 + atomic_read(&tcon->num_flushes));
343 345 seq_printf(m, "\nLocks: %d HardLinks: %d "
344 346 "Symlinks: %d",
345 347 atomic_read(&tcon->num_locks),
... ... @@ -254,6 +254,7 @@
254 254 atomic_t num_smbs_sent;
255 255 atomic_t num_writes;
256 256 atomic_t num_reads;
  257 + atomic_t num_flushes;
257 258 atomic_t num_oplock_brks;
258 259 atomic_t num_opens;
259 260 atomic_t num_closes;
... ... @@ -43,6 +43,7 @@
43 43 #define SMB_COM_CREATE_DIRECTORY 0x00 /* trivial response */
44 44 #define SMB_COM_DELETE_DIRECTORY 0x01 /* trivial response */
45 45 #define SMB_COM_CLOSE 0x04 /* triv req/rsp, timestamp ignored */
  46 +#define SMB_COM_FLUSH 0x05 /* triv req/rsp */
46 47 #define SMB_COM_DELETE 0x06 /* trivial response */
47 48 #define SMB_COM_RENAME 0x07 /* trivial response */
48 49 #define SMB_COM_QUERY_INFORMATION 0x08 /* aka getattr */
... ... @@ -789,6 +790,12 @@
789 790 struct smb_hdr hdr; /* wct = 0 */
790 791 __u16 ByteCount; /* bct = 0 */
791 792 } __attribute__((packed)) CLOSE_RSP;
  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;
792 799  
793 800 typedef struct smb_com_findclose_req {
794 801 struct smb_hdr hdr; /* wct = 1 */
... ... @@ -281,6 +281,9 @@
281 281 extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
282 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 287 extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
285 288 const int netfid, unsigned int count,
286 289 const __u64 lseek, unsigned int *nbytes, char **buf,
... ... @@ -1934,6 +1934,27 @@
1934 1934 }
1935 1935  
1936 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 1958 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1938 1959 const char *fromName, const char *toName,
1939 1960 const struct nls_table *nls_codepage, int remap)
... ... @@ -1523,6 +1523,9 @@
1523 1523 {
1524 1524 int xid;
1525 1525 int rc = 0;
  1526 + struct cifsTconInfo *tcon;
  1527 + struct cifsFileInfo *smbfile =
  1528 + (struct cifsFileInfo *)file->private_data;
1526 1529 struct inode *inode = file->f_path.dentry->d_inode;
1527 1530  
1528 1531 xid = GetXid();
1529 1532  
... ... @@ -1534,7 +1537,11 @@
1534 1537 if (rc == 0) {
1535 1538 rc = CIFS_I(inode)->write_behind_rc;
1536 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 1545 FreeXid(xid);
1539 1546 return rc;
1540 1547 }