cifs: convert async write code to pass in data via rq_pages array
Reviewed-by: Pavel Shilovsky <pshilovsky@samba.org> Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <smfrench@gmail.com>
This commit is contained in:
		
					parent
					
						
							
								fec344e3f3
							
						
					
				
			
			
				commit
				
					
						eddb079deb
					
				
			
		
					 4 changed files with 33 additions and 95 deletions
				
			
		|  | @ -999,8 +999,8 @@ struct cifs_writedata { | ||||||
| 	pid_t				pid; | 	pid_t				pid; | ||||||
| 	unsigned int			bytes; | 	unsigned int			bytes; | ||||||
| 	int				result; | 	int				result; | ||||||
| 	void (*marshal_iov) (struct kvec *iov, | 	unsigned int			pagesz; | ||||||
| 			     struct cifs_writedata *wdata); | 	unsigned int			tailsz; | ||||||
| 	unsigned int			nr_pages; | 	unsigned int			nr_pages; | ||||||
| 	struct page			*pages[1]; | 	struct page			*pages[1]; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -2033,11 +2033,11 @@ cifs_writev_callback(struct mid_q_entry *mid) | ||||||
| int | int | ||||||
| cifs_async_writev(struct cifs_writedata *wdata) | cifs_async_writev(struct cifs_writedata *wdata) | ||||||
| { | { | ||||||
| 	int i, rc = -EACCES; | 	int rc = -EACCES; | ||||||
| 	WRITE_REQ *smb = NULL; | 	WRITE_REQ *smb = NULL; | ||||||
| 	int wct; | 	int wct; | ||||||
| 	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); | 	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); | ||||||
| 	struct kvec *iov = NULL; | 	struct kvec iov; | ||||||
| 	struct smb_rqst rqst = { }; | 	struct smb_rqst rqst = { }; | ||||||
| 
 | 
 | ||||||
| 	if (tcon->ses->capabilities & CAP_LARGE_FILES) { | 	if (tcon->ses->capabilities & CAP_LARGE_FILES) { | ||||||
|  | @ -2054,15 +2054,6 @@ cifs_async_writev(struct cifs_writedata *wdata) | ||||||
| 	if (rc) | 	if (rc) | ||||||
| 		goto async_writev_out; | 		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.Pid = cpu_to_le16((__u16)wdata->pid); | ||||||
| 	smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16)); | 	smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16)); | ||||||
| 
 | 
 | ||||||
|  | @ -2079,18 +2070,15 @@ cifs_async_writev(struct cifs_writedata *wdata) | ||||||
| 	    cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4); | 	    cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4); | ||||||
| 
 | 
 | ||||||
| 	/* 4 for RFC1001 length + 1 for BCC */ | 	/* 4 for RFC1001 length + 1 for BCC */ | ||||||
| 	iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1; | 	iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1; | ||||||
| 	iov[0].iov_base = smb; | 	iov.iov_base = smb; | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	rqst.rq_iov = &iov; | ||||||
| 	 * This function should marshal up the page array into the kvec | 	rqst.rq_nvec = 1; | ||||||
| 	 * array, reserving [0] for the header. It should kmap the pages | 	rqst.rq_pages = wdata->pages; | ||||||
| 	 * and set the iov_len properly for each one. It may also set | 	rqst.rq_npages = wdata->nr_pages; | ||||||
| 	 * wdata->bytes too. | 	rqst.rq_pagesz = wdata->pagesz; | ||||||
| 	 */ | 	rqst.rq_tailsz = wdata->tailsz; | ||||||
| 	cifs_kmap_lock(); |  | ||||||
| 	wdata->marshal_iov(iov, wdata); |  | ||||||
| 	cifs_kmap_unlock(); |  | ||||||
| 
 | 
 | ||||||
| 	cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes); | 	cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes); | ||||||
| 
 | 
 | ||||||
|  | @ -2106,7 +2094,7 @@ cifs_async_writev(struct cifs_writedata *wdata) | ||||||
| 				(struct smb_com_writex_req *)smb; | 				(struct smb_com_writex_req *)smb; | ||||||
| 		inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5); | 		inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5); | ||||||
| 		put_bcc(wdata->bytes + 5, &smbw->hdr); | 		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); | 	kref_get(&wdata->refcount); | ||||||
|  | @ -2118,13 +2106,8 @@ cifs_async_writev(struct cifs_writedata *wdata) | ||||||
| 	else | 	else | ||||||
| 		kref_put(&wdata->refcount, cifs_writedata_release); | 		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: | async_writev_out: | ||||||
| 	cifs_small_buf_release(smb); | 	cifs_small_buf_release(smb); | ||||||
| 	kfree(iov); |  | ||||||
| 	return rc; | 	return rc; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1738,27 +1738,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) | ||||||
| 	return rc; | 	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, | static int cifs_writepages(struct address_space *mapping, | ||||||
| 			   struct writeback_control *wbc) | 			   struct writeback_control *wbc) | ||||||
| { | { | ||||||
|  | @ -1769,6 +1748,7 @@ static int cifs_writepages(struct address_space *mapping, | ||||||
| 	struct TCP_Server_Info *server; | 	struct TCP_Server_Info *server; | ||||||
| 	struct page *page; | 	struct page *page; | ||||||
| 	int rc = 0; | 	int rc = 0; | ||||||
|  | 	loff_t isize = i_size_read(mapping->host); | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * If wsize is smaller than the page cache size, default to writing | 	 * If wsize is smaller than the page cache size, default to writing | ||||||
|  | @ -1873,7 +1853,7 @@ retry: | ||||||
| 			 */ | 			 */ | ||||||
| 			set_page_writeback(page); | 			set_page_writeback(page); | ||||||
| 
 | 
 | ||||||
| 			if (page_offset(page) >= mapping->host->i_size) { | 			if (page_offset(page) >= isize) { | ||||||
| 				done = true; | 				done = true; | ||||||
| 				unlock_page(page); | 				unlock_page(page); | ||||||
| 				end_page_writeback(page); | 				end_page_writeback(page); | ||||||
|  | @ -1904,7 +1884,12 @@ retry: | ||||||
| 		wdata->sync_mode = wbc->sync_mode; | 		wdata->sync_mode = wbc->sync_mode; | ||||||
| 		wdata->nr_pages = nr_pages; | 		wdata->nr_pages = nr_pages; | ||||||
| 		wdata->offset = page_offset(wdata->pages[0]); | 		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 { | 		do { | ||||||
| 			if (wdata->cfile != NULL) | 			if (wdata->cfile != NULL) | ||||||
|  | @ -2205,20 +2190,6 @@ size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len) | ||||||
| 	return num_pages; | 	return num_pages; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 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 | static void | ||||||
| cifs_uncached_writev_complete(struct work_struct *work) | cifs_uncached_writev_complete(struct work_struct *work) | ||||||
| { | { | ||||||
|  | @ -2339,7 +2310,8 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, | ||||||
| 		wdata->cfile = cifsFileInfo_get(open_file); | 		wdata->cfile = cifsFileInfo_get(open_file); | ||||||
| 		wdata->pid = pid; | 		wdata->pid = pid; | ||||||
| 		wdata->bytes = cur_len; | 		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); | 		rc = cifs_uncached_retry_writev(wdata); | ||||||
| 		if (rc) { | 		if (rc) { | ||||||
| 			kref_put(&wdata->refcount, cifs_writedata_release); | 			kref_put(&wdata->refcount, cifs_writedata_release); | ||||||
|  |  | ||||||
|  | @ -1484,25 +1484,16 @@ smb2_writev_callback(struct mid_q_entry *mid) | ||||||
| int | int | ||||||
| smb2_async_writev(struct cifs_writedata *wdata) | smb2_async_writev(struct cifs_writedata *wdata) | ||||||
| { | { | ||||||
| 	int i, rc = -EACCES; | 	int rc = -EACCES; | ||||||
| 	struct smb2_write_req *req = NULL; | 	struct smb2_write_req *req = NULL; | ||||||
| 	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); | 	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); | ||||||
| 	struct kvec *iov = NULL; | 	struct kvec iov; | ||||||
| 	struct smb_rqst rqst; | 	struct smb_rqst rqst; | ||||||
| 
 | 
 | ||||||
| 	rc = small_smb2_init(SMB2_WRITE, tcon, (void **) &req); | 	rc = small_smb2_init(SMB2_WRITE, tcon, (void **) &req); | ||||||
| 	if (rc) | 	if (rc) | ||||||
| 		goto async_writev_out; | 		goto async_writev_out; | ||||||
| 
 | 
 | ||||||
| 	/* 1 iov per page + 1 for header */ |  | ||||||
| 	iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS); |  | ||||||
| 	if (iov == NULL) { |  | ||||||
| 		rc = -ENOMEM; |  | ||||||
| 		goto async_writev_out; |  | ||||||
| 	} |  | ||||||
| 	rqst.rq_iov = iov; |  | ||||||
| 	rqst.rq_nvec = wdata->nr_pages + 1; |  | ||||||
| 
 |  | ||||||
| 	req->hdr.ProcessId = cpu_to_le32(wdata->cfile->pid); | 	req->hdr.ProcessId = cpu_to_le32(wdata->cfile->pid); | ||||||
| 
 | 
 | ||||||
| 	req->PersistentFileId = wdata->cfile->fid.persistent_fid; | 	req->PersistentFileId = wdata->cfile->fid.persistent_fid; | ||||||
|  | @ -1517,18 +1508,15 @@ smb2_async_writev(struct cifs_writedata *wdata) | ||||||
| 	req->RemainingBytes = 0; | 	req->RemainingBytes = 0; | ||||||
| 
 | 
 | ||||||
| 	/* 4 for rfc1002 length field and 1 for Buffer */ | 	/* 4 for rfc1002 length field and 1 for Buffer */ | ||||||
| 	iov[0].iov_len = get_rfc1002_length(req) + 4 - 1; | 	iov.iov_len = get_rfc1002_length(req) + 4 - 1; | ||||||
| 	iov[0].iov_base = (char *)req; | 	iov.iov_base = req; | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	rqst.rq_iov = &iov; | ||||||
| 	 * This function should marshal up the page array into the kvec | 	rqst.rq_nvec = 1; | ||||||
| 	 * array, reserving [0] for the header. It should kmap the pages | 	rqst.rq_pages = wdata->pages; | ||||||
| 	 * and set the iov_len properly for each one. It may also set | 	rqst.rq_npages = wdata->nr_pages; | ||||||
| 	 * wdata->bytes too. | 	rqst.rq_pagesz = wdata->pagesz; | ||||||
| 	 */ | 	rqst.rq_tailsz = wdata->tailsz; | ||||||
| 	cifs_kmap_lock(); |  | ||||||
| 	wdata->marshal_iov(iov, wdata); |  | ||||||
| 	cifs_kmap_unlock(); |  | ||||||
| 
 | 
 | ||||||
| 	cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes); | 	cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes); | ||||||
| 
 | 
 | ||||||
|  | @ -1543,13 +1531,8 @@ smb2_async_writev(struct cifs_writedata *wdata) | ||||||
| 	if (rc) | 	if (rc) | ||||||
| 		kref_put(&wdata->refcount, cifs_writedata_release); | 		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: | async_writev_out: | ||||||
| 	cifs_small_buf_release(req); | 	cifs_small_buf_release(req); | ||||||
| 	kfree(iov); |  | ||||||
| 	return rc; | 	return rc; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jeff Layton
				Jeff Layton