aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2011-04-12 09:13:44 -0400
committerSteve French <sfrench@us.ibm.com>2011-04-12 10:19:55 -0400
commitca83ce3d5b9ad321ee24f5870a77f0b21ac5a5de (patch)
tree7added4d982e03c89599ef7c78c9b69845a7504d /fs
parentd9b942013730c38ac83564d6669c6d0ecf6d754d (diff)
cifs: don't allow mmap'ed pages to be dirtied while under writeback (try #3)
This is more or less the same patch as before, but with some merge conflicts fixed up. If a process has a dirty page mapped into its page tables, then it has the ability to change it while the client is trying to write the data out to the server. If that happens after the signature has been calculated then that signature will then be wrong, and the server will likely reset the TCP connection. This patch adds a page_mkwrite handler for CIFS that simply takes the page lock. Because the page lock is held over the life of writepage and writepages, this prevents the page from becoming writeable until the write call has completed. With this, we can also remove the "sign_zero_copy" module option and always inline the pages when writing. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/cifsfs.c4
-rw-r--r--fs/cifs/cifsglob.h1
-rw-r--r--fs/cifs/file.c64
3 files changed, 33 insertions, 36 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index e3352a1ac479..5c412b33cd7c 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -81,10 +81,6 @@ module_param(echo_retries, ushort, 0644);
81MODULE_PARM_DESC(echo_retries, "Number of echo attempts before giving up and " 81MODULE_PARM_DESC(echo_retries, "Number of echo attempts before giving up and "
82 "reconnecting server. Default: 5. 0 means " 82 "reconnecting server. Default: 5. 0 means "
83 "never reconnect."); 83 "never reconnect.");
84bool sign_zero_copy; /* globals init to false automatically */
85module_param(sign_zero_copy, bool, 0644);
86MODULE_PARM_DESC(sign_zero_copy, "Don't copy pages on write with signing "
87 "enabled. Default: N");
88extern mempool_t *cifs_sm_req_poolp; 84extern mempool_t *cifs_sm_req_poolp;
89extern mempool_t *cifs_req_poolp; 85extern mempool_t *cifs_req_poolp;
90extern mempool_t *cifs_mid_poolp; 86extern mempool_t *cifs_mid_poolp;
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index ddb359906708..a5d1106fcbde 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -826,7 +826,6 @@ GLOBAL_EXTERN unsigned int CIFSMaxBufSize; /* max size not including hdr */
826GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */ 826GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */
827GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */ 827GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */
828GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/ 828GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/
829GLOBAL_EXTERN bool sign_zero_copy; /* don't copy written pages with signing */
830 829
831/* reconnect after this many failed echo attempts */ 830/* reconnect after this many failed echo attempts */
832GLOBAL_EXTERN unsigned short echo_retries; 831GLOBAL_EXTERN unsigned short echo_retries;
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index e2d7b6bada6f..faf59529e847 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -972,6 +972,9 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file,
972 total_written += bytes_written) { 972 total_written += bytes_written) {
973 rc = -EAGAIN; 973 rc = -EAGAIN;
974 while (rc == -EAGAIN) { 974 while (rc == -EAGAIN) {
975 struct kvec iov[2];
976 unsigned int len;
977
975 if (open_file->invalidHandle) { 978 if (open_file->invalidHandle) {
976 /* we could deadlock if we called 979 /* we could deadlock if we called
977 filemap_fdatawait from here so tell 980 filemap_fdatawait from here so tell
@@ -981,31 +984,14 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file,
981 if (rc != 0) 984 if (rc != 0)
982 break; 985 break;
983 } 986 }
984 if (sign_zero_copy || (pTcon->ses->server && 987
985 ((pTcon->ses->server->secMode & 988 len = min((size_t)cifs_sb->wsize,
986 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) 989 write_size - total_written);
987 == 0))) { 990 /* iov[0] is reserved for smb header */
988 struct kvec iov[2]; 991 iov[1].iov_base = (char *)write_data + total_written;
989 unsigned int len; 992 iov[1].iov_len = len;
990 993 rc = CIFSSMBWrite2(xid, pTcon, open_file->netfid, len,
991 len = min((size_t)cifs_sb->wsize, 994 *poffset, &bytes_written, iov, 1, 0);
992 write_size - total_written);
993 /* iov[0] is reserved for smb header */
994 iov[1].iov_base = (char *)write_data +
995 total_written;
996 iov[1].iov_len = len;
997 rc = CIFSSMBWrite2(xid, pTcon,
998 open_file->netfid, len,
999 *poffset, &bytes_written,
1000 iov, 1, 0);
1001 } else
1002 rc = CIFSSMBWrite(xid, pTcon,
1003 open_file->netfid,
1004 min_t(const int, cifs_sb->wsize,
1005 write_size - total_written),
1006 *poffset, &bytes_written,
1007 write_data + total_written,
1008 NULL, 0);
1009 } 995 }
1010 if (rc || (bytes_written == 0)) { 996 if (rc || (bytes_written == 0)) {
1011 if (total_written) 997 if (total_written)
@@ -1242,12 +1228,6 @@ static int cifs_writepages(struct address_space *mapping,
1242 } 1228 }
1243 1229
1244 tcon = tlink_tcon(open_file->tlink); 1230 tcon = tlink_tcon(open_file->tlink);
1245 if (!sign_zero_copy && tcon->ses->server->secMode &
1246 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
1247 cifsFileInfo_put(open_file);
1248 kfree(iov);
1249 return generic_writepages(mapping, wbc);
1250 }
1251 cifsFileInfo_put(open_file); 1231 cifsFileInfo_put(open_file);
1252 1232
1253 xid = GetXid(); 1233 xid = GetXid();
@@ -1982,6 +1962,24 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1982 return total_read; 1962 return total_read;
1983} 1963}
1984 1964
1965/*
1966 * If the page is mmap'ed into a process' page tables, then we need to make
1967 * sure that it doesn't change while being written back.
1968 */
1969static int
1970cifs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
1971{
1972 struct page *page = vmf->page;
1973
1974 lock_page(page);
1975 return VM_FAULT_LOCKED;
1976}
1977
1978static struct vm_operations_struct cifs_file_vm_ops = {
1979 .fault = filemap_fault,
1980 .page_mkwrite = cifs_page_mkwrite,
1981};
1982
1985int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma) 1983int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
1986{ 1984{
1987 int rc, xid; 1985 int rc, xid;
@@ -1993,6 +1991,8 @@ int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
1993 cifs_invalidate_mapping(inode); 1991 cifs_invalidate_mapping(inode);
1994 1992
1995 rc = generic_file_mmap(file, vma); 1993 rc = generic_file_mmap(file, vma);
1994 if (rc == 0)
1995 vma->vm_ops = &cifs_file_vm_ops;
1996 FreeXid(xid); 1996 FreeXid(xid);
1997 return rc; 1997 return rc;
1998} 1998}
@@ -2009,6 +2009,8 @@ int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
2009 return rc; 2009 return rc;
2010 } 2010 }
2011 rc = generic_file_mmap(file, vma); 2011 rc = generic_file_mmap(file, vma);
2012 if (rc == 0)
2013 vma->vm_ops = &cifs_file_vm_ops;
2012 FreeXid(xid); 2014 FreeXid(xid);
2013 return rc; 2015 return rc;
2014} 2016}