[prev in list] [next in list] [prev in thread] [next in thread]
List: linux-cifs
Subject: Re: [PATCH] cifs: don't allow mmap'ed pages to be dirtied while under
From: Steve French <smfrench () gmail ! com>
Date: 2011-03-28 20:51:35
Message-ID: AANLkTinm0i8Unw2=LQD3CFZXadbEm7tu+ViWM3hcmSmW () mail ! gmail ! com
[Download RAW message or body]
Reviewed and merged into cifs-2.6.git
This looks like nice work.
On Mon, Mar 28, 2011 at 3:09 PM, Jeff Layton <jlayton@redhat.com> wrote:
> 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>
> ---
> fs/cifs/cifsfs.c | 4 ---
> fs/cifs/cifsglob.h | 1 -
> fs/cifs/file.c | 64 ++++++++++++++++++++++++++-------------------------
> 3 files changed, 33 insertions(+), 36 deletions(-)
>
> diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
> index de49fbb..1af2470 100644
> --- a/fs/cifs/cifsfs.c
> +++ b/fs/cifs/cifsfs.c
> @@ -81,10 +81,6 @@ module_param(echo_retries, ushort, 0644);
> MODULE_PARM_DESC(echo_retries, "Number of echo attempts before giving up and "
> "reconnecting server. Default: 5. 0 means "
> "never reconnect.");
> -bool sign_zero_copy; /* globals init to false automatically */
> -module_param(sign_zero_copy, bool, 0644);
> -MODULE_PARM_DESC(sign_zero_copy, "Don't copy pages on write with signing "
> - "enabled. Default: N");
> extern mempool_t *cifs_sm_req_poolp;
> extern mempool_t *cifs_req_poolp;
> extern mempool_t *cifs_mid_poolp;
> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
> index 2c52c14..ccbac61 100644
> --- a/fs/cifs/cifsglob.h
> +++ b/fs/cifs/cifsglob.h
> @@ -907,7 +907,6 @@ GLOBAL_EXTERN unsigned int CIFSMaxBufSize; /* max size not including hdr */
> GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */
> GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */
> GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/
> -GLOBAL_EXTERN bool sign_zero_copy; /* don't copy written pages with signing */
>
> /* reconnect after this many failed echo attempts */
> GLOBAL_EXTERN unsigned short echo_retries;
> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
> index b9731c9..da53246 100644
> --- a/fs/cifs/file.c
> +++ b/fs/cifs/file.c
> @@ -881,6 +881,9 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file,
> total_written += bytes_written) {
> rc = -EAGAIN;
> while (rc == -EAGAIN) {
> + struct kvec iov[2];
> + unsigned int len;
> +
> if (open_file->invalidHandle) {
> /* we could deadlock if we called
> filemap_fdatawait from here so tell
> @@ -890,31 +893,14 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file,
> if (rc != 0)
> break;
> }
> - if (sign_zero_copy || (pTcon->ses->server &&
> - ((pTcon->ses->server->sec_mode &
> - (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
> - == 0))) {
> - struct kvec iov[2];
> - unsigned int len;
> -
> - len = min((size_t)cifs_sb->wsize,
> - write_size - total_written);
> - /* iov[0] is reserved for smb header */
> - iov[1].iov_base = (char *)write_data +
> - total_written;
> - iov[1].iov_len = len;
> - rc = CIFSSMBWrite2(xid, pTcon,
> - open_file->netfid, len,
> - *poffset, &bytes_written,
> - iov, 1, 0);
> - } else
> - rc = CIFSSMBWrite(xid, pTcon,
> - open_file->netfid,
> - min_t(const int, cifs_sb->wsize,
> - write_size - total_written),
> - *poffset, &bytes_written,
> - write_data + total_written,
> - NULL, 0);
> +
> + len = min((size_t)cifs_sb->wsize,
> + write_size - total_written);
> + /* iov[0] is reserved for smb header */
> + iov[1].iov_base = (char *)write_data + total_written;
> + iov[1].iov_len = len;
> + rc = CIFSSMBWrite2(xid, pTcon, open_file->netfid, len,
> + *poffset, &bytes_written, iov, 1, 0);
> }
> if (rc || (bytes_written == 0)) {
> if (total_written)
> @@ -1151,12 +1137,6 @@ static int cifs_writepages(struct address_space *mapping,
> }
>
> tcon = tlink_tcon(open_file->tlink);
> - if (!sign_zero_copy && tcon->ses->server->sec_mode &
> - (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
> - cifsFileInfo_put(open_file);
> - kfree(iov);
> - return generic_writepages(mapping, wbc);
> - }
> cifsFileInfo_put(open_file);
>
> xid = GetXid();
> @@ -1909,6 +1889,24 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
> return total_read;
> }
>
> +/*
> + * If the page is mmap'ed into a process' page tables, then we need to make
> + * sure that it doesn't change while being written back.
> + */
> +static int
> +cifs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
> +{
> + struct page *page = vmf->page;
> +
> + lock_page(page);
> + return VM_FAULT_LOCKED;
> +}
> +
> +static struct vm_operations_struct cifs_file_vm_ops = {
> + .fault = filemap_fault,
> + .page_mkwrite = cifs_page_mkwrite,
> +};
> +
> int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
> {
> int rc, xid;
> @@ -1920,6 +1918,8 @@ int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
> cifs_invalidate_mapping(inode);
>
> rc = generic_file_mmap(file, vma);
> + if (rc == 0)
> + vma->vm_ops = &cifs_file_vm_ops;
> FreeXid(xid);
> return rc;
> }
> @@ -1936,6 +1936,8 @@ int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
> return rc;
> }
> rc = generic_file_mmap(file, vma);
> + if (rc == 0)
> + vma->vm_ops = &cifs_file_vm_ops;
> FreeXid(xid);
> return rc;
> }
> --
> 1.7.4
>
>
--
Thanks,
Steve
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic