From patchwork Wed Jul 25 15:54:10 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 1238531 Return-Path: X-Original-To: patchwork-cifs-client@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 70B0E3FDFB for ; Wed, 25 Jul 2012 15:54:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754968Ab2GYPy2 (ORCPT ); Wed, 25 Jul 2012 11:54:28 -0400 Received: from mail-yw0-f46.google.com ([209.85.213.46]:54961 "EHLO mail-yw0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754577Ab2GYPy1 (ORCPT ); Wed, 25 Jul 2012 11:54:27 -0400 Received: by mail-yw0-f46.google.com with SMTP id m54so857516yhm.19 for ; Wed, 25 Jul 2012 08:54:27 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references:x-gm-message-state; bh=R1+zf98J0s1i5B173neyEU2jstARrjNBaoNT5EDV4ZM=; b=J83KdCNdB9MwN6m6OLXKsT6K79T0d1E4JRT8NA+ogvC3/LPbbxp2CjrYR8DsyVZVxc XdgR8fjRRCvmXgx6HMk99HS/9z9DO0f7JnNllhpHLx2DisK7u1sp4ULM2rPLFl3hSuFF /r9SjpjUcUIkezIvYAQPoxtQ7Mp9OCuKyLE6/l9fJtrFe3icQrUEGWvCl10FyKWRyEs9 BJ88VBzgy2lBOPc350ygSe6jX3nhwbRIXBpVVHWRaafckNp1tlF4WWMFA1kE7Afz7FBM RG/TtU7UEFQY6vK2fgf6/JkE04jfrq0E7XKKU2pKCXVbX8pIJwyW7D6LxDMbmMR7cTBi 1AfA== Received: by 10.100.199.16 with SMTP id w16mr3240019anf.84.1343231667313; Wed, 25 Jul 2012 08:54:27 -0700 (PDT) Received: from salusa.poochiereds.net (cpe-076-182-054-194.nc.res.rr.com. [76.182.54.194]) by mx.google.com with ESMTPS id s1sm18764461anl.8.2012.07.25.08.54.26 (version=SSLv3 cipher=OTHER); Wed, 25 Jul 2012 08:54:26 -0700 (PDT) From: Jeff Layton To: smfrench@gmail.com Cc: linux-cifs@vger.kernel.org Subject: [PATCH v2 7/9] cifs: convert async write code to pass in data via rq_pages array Date: Wed, 25 Jul 2012 11:54:10 -0400 Message-Id: <1343231652-10459-8-git-send-email-jlayton@redhat.com> X-Mailer: git-send-email 1.7.11.2 In-Reply-To: <1343231652-10459-1-git-send-email-jlayton@redhat.com> References: <1343231652-10459-1-git-send-email-jlayton@redhat.com> X-Gm-Message-State: ALoCoQkRntGkVv92JV0MHQ8v+ElyesWLmaDCzYkfur4KcQXFok6JLMVhl8Xa5MJL2y7dQv6N4+8c Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org Signed-off-by: Jeff Layton Reviewed-by: Pavel Shilovsky --- fs/cifs/cifsproto.h | 4 ++-- fs/cifs/cifssmb.c | 39 +++++++++++---------------------------- fs/cifs/file.c | 47 +++++++++-------------------------------------- 3 files changed, 22 insertions(+), 68 deletions(-) diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 8075f23..179e29a 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -504,8 +504,8 @@ struct cifs_writedata { pid_t pid; unsigned int bytes; int result; - void (*marshal_iov) (struct kvec *iov, - struct cifs_writedata *wdata); + unsigned int pagesz; + unsigned int tailsz; unsigned int nr_pages; struct page *pages[1]; }; diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 7365460..0b0a33c 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -2050,11 +2050,11 @@ cifs_writev_callback(struct mid_q_entry *mid) int cifs_async_writev(struct cifs_writedata *wdata) { - int i, rc = -EACCES; + int rc = -EACCES; WRITE_REQ *smb = NULL; int wct; struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); - struct kvec *iov = NULL; + struct kvec iov; struct smb_rqst rqst = { }; if (tcon->ses->capabilities & CAP_LARGE_FILES) { @@ -2071,15 +2071,6 @@ cifs_async_writev(struct cifs_writedata *wdata) if (rc) goto async_writev_out; - /* 1 iov per page + 1 for header */ - rqst.rq_nvec = wdata->nr_pages + 1; - iov = kzalloc((rqst.rq_nvec) * sizeof(*iov), GFP_NOFS); - if (iov == NULL) { - rc = -ENOMEM; - goto async_writev_out; - } - rqst.rq_iov = iov; - smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid); smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16)); @@ -2096,18 +2087,15 @@ cifs_async_writev(struct cifs_writedata *wdata) cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4); /* 4 for RFC1001 length + 1 for BCC */ - iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1; - iov[0].iov_base = smb; + iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1; + iov.iov_base = smb; - /* - * This function should marshal up the page array into the kvec - * array, reserving [0] for the header. It should kmap the pages - * and set the iov_len properly for each one. It may also set - * wdata->bytes too. - */ - cifs_kmap_lock(); - wdata->marshal_iov(iov, wdata); - cifs_kmap_unlock(); + rqst.rq_iov = &iov; + rqst.rq_nvec = 1; + rqst.rq_pages = wdata->pages; + rqst.rq_npages = wdata->nr_pages; + rqst.rq_pagesz = wdata->pagesz; + rqst.rq_tailsz = wdata->tailsz; cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes); @@ -2123,7 +2111,7 @@ cifs_async_writev(struct cifs_writedata *wdata) (struct smb_com_writex_req *)smb; inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5); put_bcc(wdata->bytes + 5, &smbw->hdr); - iov[0].iov_len += 4; /* pad bigger by four bytes */ + iov.iov_len += 4; /* pad bigger by four bytes */ } kref_get(&wdata->refcount); @@ -2135,13 +2123,8 @@ cifs_async_writev(struct cifs_writedata *wdata) else kref_put(&wdata->refcount, cifs_writedata_release); - /* send is done, unmap pages */ - for (i = 0; i < wdata->nr_pages; i++) - kunmap(wdata->pages[i]); - async_writev_out: cifs_small_buf_release(smb); - kfree(iov); return rc; } diff --git a/fs/cifs/file.c b/fs/cifs/file.c index cd5b144..b18d963 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -1709,27 +1709,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) return rc; } -/* - * Marshal up the iov array, reserving the first one for the header. Also, - * set wdata->bytes. - */ -static void -cifs_writepages_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata) -{ - int i; - struct inode *inode = wdata->cfile->dentry->d_inode; - loff_t size = i_size_read(inode); - - /* marshal up the pages into iov array */ - wdata->bytes = 0; - for (i = 0; i < wdata->nr_pages; i++) { - iov[i + 1].iov_len = min(size - page_offset(wdata->pages[i]), - (loff_t)PAGE_CACHE_SIZE); - iov[i + 1].iov_base = kmap(wdata->pages[i]); - wdata->bytes += iov[i + 1].iov_len; - } -} - static int cifs_writepages(struct address_space *mapping, struct writeback_control *wbc) { @@ -1739,6 +1718,7 @@ static int cifs_writepages(struct address_space *mapping, struct cifs_writedata *wdata; struct page *page; int rc = 0; + loff_t isize = i_size_read(mapping->host); /* * If wsize is smaller than the page cache size, default to writing @@ -1843,7 +1823,7 @@ retry: */ set_page_writeback(page); - if (page_offset(page) >= mapping->host->i_size) { + if (page_offset(page) >= isize) { done = true; unlock_page(page); end_page_writeback(page); @@ -1874,7 +1854,11 @@ retry: wdata->sync_mode = wbc->sync_mode; wdata->nr_pages = nr_pages; wdata->offset = page_offset(wdata->pages[0]); - wdata->marshal_iov = cifs_writepages_marshal_iov; + wdata->pagesz = PAGE_CACHE_SIZE; + wdata->tailsz = min(isize - page_offset(wdata->pages[nr_pages - 1]), + (loff_t)PAGE_CACHE_SIZE); + wdata->bytes = ((nr_pages - 1) * PAGE_CACHE_SIZE) + + wdata->tailsz; do { if (wdata->cfile != NULL) @@ -2163,20 +2147,6 @@ size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len) } static void -cifs_uncached_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata) -{ - int i; - size_t bytes = wdata->bytes; - - /* marshal up the pages into iov array */ - for (i = 0; i < wdata->nr_pages; i++) { - iov[i + 1].iov_len = min_t(size_t, bytes, PAGE_SIZE); - iov[i + 1].iov_base = kmap(wdata->pages[i]); - bytes -= iov[i + 1].iov_len; - } -} - -static void cifs_uncached_writev_complete(struct work_struct *work) { int i; @@ -2289,7 +2259,8 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, wdata->cfile = cifsFileInfo_get(open_file); wdata->pid = pid; wdata->bytes = cur_len; - wdata->marshal_iov = cifs_uncached_marshal_iov; + wdata->pagesz = PAGE_SIZE; + wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE); rc = cifs_uncached_retry_writev(wdata); if (rc) { kref_put(&wdata->refcount, cifs_writedata_release);