forked from mirrors/linux
		
	cifs: Cut over to using netfslib
Make the cifs filesystem use netfslib to handle reading and writing on
behalf of cifs.  The changes include:
 (1) Various read_iter/write_iter type functions are turned into wrappers
     around netfslib API functions or are pointed directly at those
     functions:
	cifs_file_direct{,_nobrl}_ops switch to use
	netfs_unbuffered_read_iter and netfs_unbuffered_write_iter.
Large pieces of code that will be removed are #if'd out and will be removed
in subsequent patches.
[?] Why does cifs mark the page dirty in the destination buffer of a DIO
    read?  Should that happen automatically?  Does netfs need to do that?
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Steve French <sfrench@samba.org>
cc: Shyam Prasad N <nspmangalore@gmail.com>
cc: Rohith Surabattula <rohiths.msft@gmail.com>
cc: Jeff Layton <jlayton@kernel.org>
cc: linux-cifs@vger.kernel.org
cc: netfs@lists.linux.dev
cc: linux-fsdevel@vger.kernel.org
cc: linux-mm@kvack.org
			
			
This commit is contained in:
		
							parent
							
								
									69c3c023af
								
							
						
					
					
						commit
						3ee1a1fc39
					
				
					 14 changed files with 361 additions and 180 deletions
				
			
		|  | @ -213,8 +213,13 @@ static void netfs_rreq_assess_dio(struct netfs_io_request *rreq) | |||
| 	unsigned int i; | ||||
| 	size_t transferred = 0; | ||||
| 
 | ||||
| 	for (i = 0; i < rreq->direct_bv_count; i++) | ||||
| 	for (i = 0; i < rreq->direct_bv_count; i++) { | ||||
| 		flush_dcache_page(rreq->direct_bv[i].bv_page); | ||||
| 		// TODO: cifs marks pages in the destination buffer
 | ||||
| 		// dirty under some circumstances after a read.  Do we
 | ||||
| 		// need to do that too?
 | ||||
| 		set_page_dirty(rreq->direct_bv[i].bv_page); | ||||
| 	} | ||||
| 
 | ||||
| 	list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { | ||||
| 		if (subreq->error || subreq->transferred == 0) | ||||
|  |  | |||
|  | @ -1522,8 +1522,8 @@ const struct file_operations cifs_file_strict_ops = { | |||
| }; | ||||
| 
 | ||||
| const struct file_operations cifs_file_direct_ops = { | ||||
| 	.read_iter = cifs_direct_readv, | ||||
| 	.write_iter = cifs_direct_writev, | ||||
| 	.read_iter = netfs_unbuffered_read_iter, | ||||
| 	.write_iter = netfs_file_write_iter, | ||||
| 	.open = cifs_open, | ||||
| 	.release = cifs_close, | ||||
| 	.lock = cifs_lock, | ||||
|  | @ -1578,8 +1578,8 @@ const struct file_operations cifs_file_strict_nobrl_ops = { | |||
| }; | ||||
| 
 | ||||
| const struct file_operations cifs_file_direct_nobrl_ops = { | ||||
| 	.read_iter = cifs_direct_readv, | ||||
| 	.write_iter = cifs_direct_writev, | ||||
| 	.read_iter = netfs_unbuffered_read_iter, | ||||
| 	.write_iter = netfs_file_write_iter, | ||||
| 	.open = cifs_open, | ||||
| 	.release = cifs_close, | ||||
| 	.fsync = cifs_fsync, | ||||
|  |  | |||
|  | @ -94,11 +94,7 @@ extern const struct file_operations cifs_file_strict_nobrl_ops; | |||
| extern int cifs_open(struct inode *inode, struct file *file); | ||||
| extern int cifs_close(struct inode *inode, struct file *file); | ||||
| extern int cifs_closedir(struct inode *inode, struct file *file); | ||||
| extern ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to); | ||||
| extern ssize_t cifs_direct_readv(struct kiocb *iocb, struct iov_iter *to); | ||||
| extern ssize_t cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to); | ||||
| extern ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from); | ||||
| extern ssize_t cifs_direct_writev(struct kiocb *iocb, struct iov_iter *from); | ||||
| extern ssize_t cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from); | ||||
| ssize_t cifs_file_write_iter(struct kiocb *iocb, struct iov_iter *from); | ||||
| ssize_t cifs_loose_read_iter(struct kiocb *iocb, struct iov_iter *iter); | ||||
|  | @ -112,9 +108,6 @@ extern int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma); | |||
| extern const struct file_operations cifs_dir_ops; | ||||
| extern int cifs_dir_open(struct inode *inode, struct file *file); | ||||
| extern int cifs_readdir(struct file *file, struct dir_context *ctx); | ||||
| extern void cifs_pages_written_back(struct inode *inode, loff_t start, unsigned int len); | ||||
| extern void cifs_pages_write_failed(struct inode *inode, loff_t start, unsigned int len); | ||||
| extern void cifs_pages_write_redirty(struct inode *inode, loff_t start, unsigned int len); | ||||
| 
 | ||||
| /* Functions related to dir entries */ | ||||
| extern const struct dentry_operations cifs_dentry_ops; | ||||
|  |  | |||
|  | @ -451,7 +451,7 @@ struct smb_version_operations { | |||
| 	/* async read from the server */ | ||||
| 	int (*async_readv)(struct cifs_io_subrequest *); | ||||
| 	/* async write to the server */ | ||||
| 	int (*async_writev)(struct cifs_io_subrequest *); | ||||
| 	void (*async_writev)(struct cifs_io_subrequest *); | ||||
| 	/* sync read from the server */ | ||||
| 	int (*sync_read)(const unsigned int, struct cifs_fid *, | ||||
| 			 struct cifs_io_parms *, unsigned int *, char **, | ||||
|  | @ -1516,7 +1516,7 @@ struct cifs_io_subrequest { | |||
| #endif | ||||
| 	struct cifs_credits		credits; | ||||
| 
 | ||||
| 	// TODO: Remove following elements
 | ||||
| #if 0 // TODO: Remove following elements
 | ||||
| 	struct list_head		list; | ||||
| 	struct completion		done; | ||||
| 	struct work_struct		work; | ||||
|  | @ -1526,6 +1526,7 @@ struct cifs_io_subrequest { | |||
| 	enum writeback_sync_modes	sync_mode; | ||||
| 	bool				uncached; | ||||
| 	struct bio_vec			*bv; | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  |  | |||
|  | @ -148,6 +148,8 @@ extern bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 eof, | |||
| 				   bool from_readdir); | ||||
| extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, | ||||
| 			    unsigned int bytes_written); | ||||
| void cifs_write_subrequest_terminated(struct cifs_io_subrequest *wdata, ssize_t result, | ||||
| 				      bool was_async); | ||||
| extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, int); | ||||
| extern int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, | ||||
| 				  int flags, | ||||
|  | @ -599,6 +601,7 @@ void __cifs_put_smb_ses(struct cifs_ses *ses); | |||
| extern struct cifs_ses * | ||||
| cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx); | ||||
| 
 | ||||
| #if 0 // TODO Remove
 | ||||
| void cifs_readdata_release(struct cifs_io_subrequest *rdata); | ||||
| static inline void cifs_get_readdata(struct cifs_io_subrequest *rdata) | ||||
| { | ||||
|  | @ -609,11 +612,13 @@ static inline void cifs_put_readdata(struct cifs_io_subrequest *rdata) | |||
| 	if (refcount_dec_and_test(&rdata->subreq.ref)) | ||||
| 		cifs_readdata_release(rdata); | ||||
| } | ||||
| #endif | ||||
| int cifs_async_readv(struct cifs_io_subrequest *rdata); | ||||
| int cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid); | ||||
| 
 | ||||
| int cifs_async_writev(struct cifs_io_subrequest *wdata); | ||||
| void cifs_async_writev(struct cifs_io_subrequest *wdata); | ||||
| void cifs_writev_complete(struct work_struct *work); | ||||
| #if 0 // TODO Remove
 | ||||
| struct cifs_io_subrequest *cifs_writedata_alloc(work_func_t complete); | ||||
| void cifs_writedata_release(struct cifs_io_subrequest *rdata); | ||||
| static inline void cifs_get_writedata(struct cifs_io_subrequest *wdata) | ||||
|  | @ -625,6 +630,7 @@ static inline void cifs_put_writedata(struct cifs_io_subrequest *wdata) | |||
| 	if (refcount_dec_and_test(&wdata->subreq.ref)) | ||||
| 		cifs_writedata_release(wdata); | ||||
| } | ||||
| #endif | ||||
| int cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, | ||||
| 			  struct cifs_sb_info *cifs_sb, | ||||
| 			  const unsigned char *path, char *pbuf, | ||||
|  |  | |||
|  | @ -1265,7 +1265,7 @@ static void | |||
| cifs_readv_callback(struct mid_q_entry *mid) | ||||
| { | ||||
| 	struct cifs_io_subrequest *rdata = mid->callback_data; | ||||
| 	struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); | ||||
| 	struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink); | ||||
| 	struct TCP_Server_Info *server = tcon->ses->server; | ||||
| 	struct smb_rqst rqst = { .rq_iov = rdata->iov, | ||||
| 				 .rq_nvec = 2, | ||||
|  | @ -1306,7 +1306,13 @@ cifs_readv_callback(struct mid_q_entry *mid) | |||
| 		rdata->result = -EIO; | ||||
| 	} | ||||
| 
 | ||||
| 	queue_work(cifsiod_wq, &rdata->work); | ||||
| 	if (rdata->result == 0 || rdata->result == -EAGAIN) | ||||
| 		iov_iter_advance(&rdata->subreq.io_iter, rdata->got_bytes); | ||||
| 	rdata->credits.value = 0; | ||||
| 	netfs_subreq_terminated(&rdata->subreq, | ||||
| 				(rdata->result == 0 || rdata->result == -EAGAIN) ? | ||||
| 				rdata->got_bytes : rdata->result, | ||||
| 				false); | ||||
| 	release_mid(mid); | ||||
| 	add_credits(server, &credits, 0); | ||||
| } | ||||
|  | @ -1318,7 +1324,7 @@ cifs_async_readv(struct cifs_io_subrequest *rdata) | |||
| 	int rc; | ||||
| 	READ_REQ *smb = NULL; | ||||
| 	int wct; | ||||
| 	struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); | ||||
| 	struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink); | ||||
| 	struct smb_rqst rqst = { .rq_iov = rdata->iov, | ||||
| 				 .rq_nvec = 2 }; | ||||
| 
 | ||||
|  | @ -1343,7 +1349,7 @@ cifs_async_readv(struct cifs_io_subrequest *rdata) | |||
| 	smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16)); | ||||
| 
 | ||||
| 	smb->AndXCommand = 0xFF;	/* none */ | ||||
| 	smb->Fid = rdata->cfile->fid.netfid; | ||||
| 	smb->Fid = rdata->req->cfile->fid.netfid; | ||||
| 	smb->OffsetLow = cpu_to_le32(rdata->subreq.start & 0xFFFFFFFF); | ||||
| 	if (wct == 12) | ||||
| 		smb->OffsetHigh = cpu_to_le32(rdata->subreq.start >> 32); | ||||
|  | @ -1613,15 +1619,16 @@ static void | |||
| cifs_writev_callback(struct mid_q_entry *mid) | ||||
| { | ||||
| 	struct cifs_io_subrequest *wdata = mid->callback_data; | ||||
| 	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); | ||||
| 	unsigned int written; | ||||
| 	struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink); | ||||
| 	WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf; | ||||
| 	struct cifs_credits credits = { .value = 1, .instance = 0 }; | ||||
| 	ssize_t result; | ||||
| 	size_t written; | ||||
| 
 | ||||
| 	switch (mid->mid_state) { | ||||
| 	case MID_RESPONSE_RECEIVED: | ||||
| 		wdata->result = cifs_check_receive(mid, tcon->ses->server, 0); | ||||
| 		if (wdata->result != 0) | ||||
| 		result = cifs_check_receive(mid, tcon->ses->server, 0); | ||||
| 		if (result != 0) | ||||
| 			break; | ||||
| 
 | ||||
| 		written = le16_to_cpu(smb->CountHigh); | ||||
|  | @ -1637,32 +1644,33 @@ cifs_writev_callback(struct mid_q_entry *mid) | |||
| 			written &= 0xFFFF; | ||||
| 
 | ||||
| 		if (written < wdata->subreq.len) | ||||
| 			wdata->result = -ENOSPC; | ||||
| 			result = -ENOSPC; | ||||
| 		else | ||||
| 			wdata->subreq.len = written; | ||||
| 			result = written; | ||||
| 		break; | ||||
| 	case MID_REQUEST_SUBMITTED: | ||||
| 	case MID_RETRY_NEEDED: | ||||
| 		wdata->result = -EAGAIN; | ||||
| 		result = -EAGAIN; | ||||
| 		break; | ||||
| 	default: | ||||
| 		wdata->result = -EIO; | ||||
| 		result = -EIO; | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	queue_work(cifsiod_wq, &wdata->work); | ||||
| 	wdata->credits.value = 0; | ||||
| 	cifs_write_subrequest_terminated(wdata, result, true); | ||||
| 	release_mid(mid); | ||||
| 	add_credits(tcon->ses->server, &credits, 0); | ||||
| } | ||||
| 
 | ||||
| /* cifs_async_writev - send an async write, and set up mid to handle result */ | ||||
| int | ||||
| void | ||||
| cifs_async_writev(struct cifs_io_subrequest *wdata) | ||||
| { | ||||
| 	int rc = -EACCES; | ||||
| 	WRITE_REQ *smb = NULL; | ||||
| 	int wct; | ||||
| 	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); | ||||
| 	struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink); | ||||
| 	struct kvec iov[2]; | ||||
| 	struct smb_rqst rqst = { }; | ||||
| 
 | ||||
|  | @ -1672,7 +1680,8 @@ cifs_async_writev(struct cifs_io_subrequest *wdata) | |||
| 		wct = 12; | ||||
| 		if (wdata->subreq.start >> 32 > 0) { | ||||
| 			/* can not handle big offset for old srv */ | ||||
| 			return -EIO; | ||||
| 			rc = -EIO; | ||||
| 			goto out; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  | @ -1684,7 +1693,7 @@ cifs_async_writev(struct cifs_io_subrequest *wdata) | |||
| 	smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16)); | ||||
| 
 | ||||
| 	smb->AndXCommand = 0xFF;	/* none */ | ||||
| 	smb->Fid = wdata->cfile->fid.netfid; | ||||
| 	smb->Fid = wdata->req->cfile->fid.netfid; | ||||
| 	smb->OffsetLow = cpu_to_le32(wdata->subreq.start & 0xFFFFFFFF); | ||||
| 	if (wct == 14) | ||||
| 		smb->OffsetHigh = cpu_to_le32(wdata->subreq.start >> 32); | ||||
|  | @ -1724,18 +1733,19 @@ cifs_async_writev(struct cifs_io_subrequest *wdata) | |||
| 		iov[1].iov_len += 4; /* pad bigger by four bytes */ | ||||
| 	} | ||||
| 
 | ||||
| 	cifs_get_writedata(wdata); | ||||
| 	rc = cifs_call_async(tcon->ses->server, &rqst, NULL, | ||||
| 			     cifs_writev_callback, NULL, wdata, 0, NULL); | ||||
| 
 | ||||
| 	/* Can't touch wdata if rc == 0 */ | ||||
| 	if (rc == 0) | ||||
| 		cifs_stats_inc(&tcon->stats.cifs_stats.num_writes); | ||||
| 	else | ||||
| 		cifs_put_writedata(wdata); | ||||
| 
 | ||||
| async_writev_out: | ||||
| 	cifs_small_buf_release(smb); | ||||
| 	return rc; | ||||
| out: | ||||
| 	if (rc) { | ||||
| 		add_credits_and_wake_if(wdata->server, &wdata->credits, 0); | ||||
| 		cifs_write_subrequest_terminated(wdata, rc, false); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| int | ||||
|  |  | |||
|  | @ -119,7 +119,7 @@ static void cifs_issue_write(struct netfs_io_subrequest *subreq) | |||
| 	else | ||||
| 		trace_netfs_sreq(subreq, netfs_sreq_trace_fail); | ||||
| 	add_credits_and_wake_if(wdata->server, &wdata->credits, 0); | ||||
| 	netfs_write_subrequest_terminated(wdata, rc, false); | ||||
| 	cifs_write_subrequest_terminated(wdata, rc, false); | ||||
| 	goto out; | ||||
| } | ||||
| 
 | ||||
|  | @ -352,6 +352,7 @@ const struct netfs_request_ops cifs_req_ops = { | |||
| 	.issue_write		= cifs_issue_write, | ||||
| }; | ||||
| 
 | ||||
| #if 0 // TODO remove 397
 | ||||
| /*
 | ||||
|  * Remove the dirty flags from a span of pages. | ||||
|  */ | ||||
|  | @ -476,6 +477,7 @@ void cifs_pages_write_redirty(struct inode *inode, loff_t start, unsigned int le | |||
| 
 | ||||
| 	rcu_read_unlock(); | ||||
| } | ||||
| #endif // end netfslib remove 397
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Mark as invalid, all open files on tree connections since they | ||||
|  | @ -2522,20 +2524,23 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock) | |||
| 	return rc; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * update the file size (if needed) after a write. Should be called with | ||||
|  * the inode->i_lock held | ||||
|  */ | ||||
| void | ||||
| cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, | ||||
| 		      unsigned int bytes_written) | ||||
| void cifs_write_subrequest_terminated(struct cifs_io_subrequest *wdata, ssize_t result, | ||||
| 				      bool was_async) | ||||
| { | ||||
| 	loff_t end_of_write = offset + bytes_written; | ||||
| 	struct netfs_io_request *wreq = wdata->rreq; | ||||
| 	loff_t new_server_eof; | ||||
| 
 | ||||
| 	if (end_of_write > cifsi->netfs.remote_i_size) | ||||
| 		netfs_resize_file(&cifsi->netfs, end_of_write, true); | ||||
| 	if (result > 0) { | ||||
| 		new_server_eof = wdata->subreq.start + wdata->subreq.transferred + result; | ||||
| 
 | ||||
| 		if (new_server_eof > netfs_inode(wreq->inode)->remote_i_size) | ||||
| 			netfs_resize_file(netfs_inode(wreq->inode), new_server_eof, true); | ||||
| 	} | ||||
| 
 | ||||
| 	netfs_write_subrequest_terminated(&wdata->subreq, result, was_async); | ||||
| } | ||||
| 
 | ||||
| #if 0 // TODO remove 2483
 | ||||
| static ssize_t | ||||
| cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data, | ||||
| 	   size_t write_size, loff_t *offset) | ||||
|  | @ -2619,6 +2624,7 @@ cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data, | |||
| 	free_xid(xid); | ||||
| 	return total_written; | ||||
| } | ||||
| #endif // end netfslib remove 2483
 | ||||
| 
 | ||||
| struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode, | ||||
| 					bool fsuid_only) | ||||
|  | @ -2824,6 +2830,7 @@ cifs_get_readable_path(struct cifs_tcon *tcon, const char *name, | |||
| 	return -ENOENT; | ||||
| } | ||||
| 
 | ||||
| #if 0 // TODO remove 2773
 | ||||
| void | ||||
| cifs_writedata_release(struct cifs_io_subrequest *wdata) | ||||
| { | ||||
|  | @ -3454,7 +3461,11 @@ static int cifs_write_end(struct file *file, struct address_space *mapping, | |||
| 
 | ||||
| 	return rc; | ||||
| } | ||||
| #endif // End netfs removal 2773
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Flush data on a strict file. | ||||
|  */ | ||||
| int cifs_strict_fsync(struct file *file, loff_t start, loff_t end, | ||||
| 		      int datasync) | ||||
| { | ||||
|  | @ -3509,6 +3520,9 @@ int cifs_strict_fsync(struct file *file, loff_t start, loff_t end, | |||
| 	return rc; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Flush data on a non-strict data. | ||||
|  */ | ||||
| int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync) | ||||
| { | ||||
| 	unsigned int xid; | ||||
|  | @ -3575,6 +3589,7 @@ int cifs_flush(struct file *file, fl_owner_t id) | |||
| 	return rc; | ||||
| } | ||||
| 
 | ||||
| #if 0 // TODO remove 3594
 | ||||
| static void collect_uncached_write_data(struct cifs_aio_ctx *ctx); | ||||
| 
 | ||||
| static void | ||||
|  | @ -4037,6 +4052,7 @@ ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from) | |||
| { | ||||
| 	return __cifs_writev(iocb, from, false); | ||||
| } | ||||
| #endif // TODO remove 3594
 | ||||
| 
 | ||||
| static ssize_t | ||||
| cifs_writev(struct kiocb *iocb, struct iov_iter *from) | ||||
|  | @ -4048,7 +4064,10 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from) | |||
| 	struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; | ||||
| 	ssize_t rc; | ||||
| 
 | ||||
| 	inode_lock(inode); | ||||
| 	rc = netfs_start_io_write(inode); | ||||
| 	if (rc < 0) | ||||
| 		return rc; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * We need to hold the sem to be sure nobody modifies lock list | ||||
| 	 * with a brlock that prevents writing. | ||||
|  | @ -4062,13 +4081,12 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from) | |||
| 	if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(from), | ||||
| 				     server->vals->exclusive_lock_type, 0, | ||||
| 				     NULL, CIFS_WRITE_OP)) | ||||
| 		rc = __generic_file_write_iter(iocb, from); | ||||
| 		rc = netfs_buffered_write_iter_locked(iocb, from, NULL); | ||||
| 	else | ||||
| 		rc = -EACCES; | ||||
| out: | ||||
| 	up_read(&cinode->lock_sem); | ||||
| 	inode_unlock(inode); | ||||
| 
 | ||||
| 	netfs_end_io_write(inode); | ||||
| 	if (rc > 0) | ||||
| 		rc = generic_write_sync(iocb, rc); | ||||
| 	return rc; | ||||
|  | @ -4091,9 +4109,9 @@ cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from) | |||
| 
 | ||||
| 	if (CIFS_CACHE_WRITE(cinode)) { | ||||
| 		if (cap_unix(tcon->ses) && | ||||
| 		(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) | ||||
| 		  && ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) { | ||||
| 			written = generic_file_write_iter(iocb, from); | ||||
| 		    (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && | ||||
| 		    ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) { | ||||
| 			written = netfs_file_write_iter(iocb, from); | ||||
| 			goto out; | ||||
| 		} | ||||
| 		written = cifs_writev(iocb, from); | ||||
|  | @ -4105,7 +4123,7 @@ cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from) | |||
| 	 * affected pages because it may cause a error with mandatory locks on | ||||
| 	 * these pages but not on the region from pos to ppos+len-1. | ||||
| 	 */ | ||||
| 	written = cifs_user_writev(iocb, from); | ||||
| 	written = netfs_file_write_iter(iocb, from); | ||||
| 	if (CIFS_CACHE_READ(cinode)) { | ||||
| 		/*
 | ||||
| 		 * We have read level caching and we have just sent a write | ||||
|  | @ -4124,6 +4142,7 @@ cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from) | |||
| 	return written; | ||||
| } | ||||
| 
 | ||||
| #if 0 // TODO remove 4143
 | ||||
| static struct cifs_io_subrequest *cifs_readdata_alloc(work_func_t complete) | ||||
| { | ||||
| 	struct cifs_io_subrequest *rdata; | ||||
|  | @ -4563,7 +4582,9 @@ ssize_t cifs_direct_readv(struct kiocb *iocb, struct iov_iter *to) | |||
| ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to) | ||||
| { | ||||
| 	return __cifs_readv(iocb, to, false); | ||||
| 
 | ||||
| } | ||||
| #endif // end netfslib removal 4143
 | ||||
| 
 | ||||
| ssize_t cifs_loose_read_iter(struct kiocb *iocb, struct iov_iter *iter) | ||||
| { | ||||
|  | @ -4571,13 +4592,13 @@ ssize_t cifs_loose_read_iter(struct kiocb *iocb, struct iov_iter *iter) | |||
| 	struct inode *inode = file_inode(iocb->ki_filp); | ||||
| 
 | ||||
| 	if (iocb->ki_flags & IOCB_DIRECT) | ||||
| 		return cifs_user_readv(iocb, iter); | ||||
| 		return netfs_unbuffered_read_iter(iocb, iter); | ||||
| 
 | ||||
| 	rc = cifs_revalidate_mapping(inode); | ||||
| 	if (rc) | ||||
| 		return rc; | ||||
| 
 | ||||
| 	return generic_file_read_iter(iocb, iter); | ||||
| 	return netfs_file_read_iter(iocb, iter); | ||||
| } | ||||
| 
 | ||||
| ssize_t cifs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | ||||
|  | @ -4588,7 +4609,7 @@ ssize_t cifs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
| 	int rc; | ||||
| 
 | ||||
| 	if (iocb->ki_filp->f_flags & O_DIRECT) { | ||||
| 		written = cifs_user_writev(iocb, from); | ||||
| 		written = netfs_unbuffered_write_iter(iocb, from); | ||||
| 		if (written > 0 && CIFS_CACHE_READ(cinode)) { | ||||
| 			cifs_zap_mapping(inode); | ||||
| 			cifs_dbg(FYI, | ||||
|  | @ -4603,17 +4624,15 @@ ssize_t cifs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
| 	if (written) | ||||
| 		return written; | ||||
| 
 | ||||
| 	written = generic_file_write_iter(iocb, from); | ||||
| 
 | ||||
| 	if (CIFS_CACHE_WRITE(CIFS_I(inode))) | ||||
| 		goto out; | ||||
| 	written = netfs_file_write_iter(iocb, from); | ||||
| 
 | ||||
| 	if (!CIFS_CACHE_WRITE(CIFS_I(inode))) { | ||||
| 		rc = filemap_fdatawrite(inode->i_mapping); | ||||
| 		if (rc) | ||||
| 			cifs_dbg(FYI, "cifs_file_write_iter: %d rc on %p inode\n", | ||||
| 				 rc, inode); | ||||
| 	} | ||||
| 
 | ||||
| out: | ||||
| 	cifs_put_writer(cinode); | ||||
| 	return written; | ||||
| } | ||||
|  | @ -4638,12 +4657,15 @@ cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to) | |||
| 	 * pos+len-1. | ||||
| 	 */ | ||||
| 	if (!CIFS_CACHE_READ(cinode)) | ||||
| 		return cifs_user_readv(iocb, to); | ||||
| 		return netfs_unbuffered_read_iter(iocb, to); | ||||
| 
 | ||||
| 	if (cap_unix(tcon->ses) && | ||||
| 	    (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && | ||||
| 	    ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) | ||||
| 		return generic_file_read_iter(iocb, to); | ||||
| 	    ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) { | ||||
| 		if (iocb->ki_flags & IOCB_DIRECT) | ||||
| 			return netfs_unbuffered_read_iter(iocb, to); | ||||
| 		return netfs_buffered_read_iter(iocb, to); | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * We need to hold the sem to be sure nobody modifies lock list | ||||
|  | @ -4652,12 +4674,17 @@ cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to) | |||
| 	down_read(&cinode->lock_sem); | ||||
| 	if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(to), | ||||
| 				     tcon->ses->server->vals->shared_lock_type, | ||||
| 				     0, NULL, CIFS_READ_OP)) | ||||
| 		rc = generic_file_read_iter(iocb, to); | ||||
| 				     0, NULL, CIFS_READ_OP)) { | ||||
| 		if (iocb->ki_flags & IOCB_DIRECT) | ||||
| 			rc = netfs_unbuffered_read_iter(iocb, to); | ||||
| 		else | ||||
| 			rc = netfs_buffered_read_iter(iocb, to); | ||||
| 	} | ||||
| 	up_read(&cinode->lock_sem); | ||||
| 	return rc; | ||||
| } | ||||
| 
 | ||||
| #if 0 // TODO remove 4633
 | ||||
| static ssize_t | ||||
| cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset) | ||||
| { | ||||
|  | @ -4749,29 +4776,11 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset) | |||
| 	free_xid(xid); | ||||
| 	return total_read; | ||||
| } | ||||
| #endif // end netfslib remove 4633
 | ||||
| 
 | ||||
| /*
 | ||||
|  * 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 vm_fault_t cifs_page_mkwrite(struct vm_fault *vmf) | ||||
| { | ||||
| 	struct folio *folio = page_folio(vmf->page); | ||||
| 
 | ||||
| 	/* Wait for the folio to be written to the cache before we allow it to
 | ||||
| 	 * be modified.  We then assume the entire folio will need writing back. | ||||
| 	 */ | ||||
| #ifdef CONFIG_CIFS_FSCACHE | ||||
| 	if (folio_test_private_2(folio) && /* [DEPRECATED] */ | ||||
| 	    folio_wait_private_2_killable(folio) < 0) | ||||
| 		return VM_FAULT_RETRY; | ||||
| #endif | ||||
| 
 | ||||
| 	folio_wait_writeback(folio); | ||||
| 
 | ||||
| 	if (folio_lock_killable(folio) < 0) | ||||
| 		return VM_FAULT_RETRY; | ||||
| 	return VM_FAULT_LOCKED; | ||||
| 	return netfs_page_mkwrite(vmf, NULL); | ||||
| } | ||||
| 
 | ||||
| static const struct vm_operations_struct cifs_file_vm_ops = { | ||||
|  | @ -4817,6 +4826,7 @@ int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) | |||
| 	return rc; | ||||
| } | ||||
| 
 | ||||
| #if 0 // TODO remove 4794
 | ||||
| /*
 | ||||
|  * Unlock a bunch of folios in the pagecache. | ||||
|  */ | ||||
|  | @ -5101,6 +5111,7 @@ static int cifs_read_folio(struct file *file, struct folio *folio) | |||
| 	free_xid(xid); | ||||
| 	return rc; | ||||
| } | ||||
| #endif // end netfslib remove 4794
 | ||||
| 
 | ||||
| static int is_inode_writable(struct cifsInodeInfo *cifs_inode) | ||||
| { | ||||
|  | @ -5149,6 +5160,7 @@ bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file, | |||
| 		return true; | ||||
| } | ||||
| 
 | ||||
| #if 0 // TODO remove 5152
 | ||||
| static int cifs_write_begin(struct file *file, struct address_space *mapping, | ||||
| 			loff_t pos, unsigned len, | ||||
| 			struct page **pagep, void **fsdata) | ||||
|  | @ -5244,6 +5256,7 @@ static void cifs_invalidate_folio(struct folio *folio, size_t offset, | |||
| { | ||||
| 	folio_wait_private_2(folio); /* [DEPRECATED] */ | ||||
| } | ||||
| #endif // end netfslib remove 5152
 | ||||
| 
 | ||||
| void cifs_oplock_break(struct work_struct *work) | ||||
| { | ||||
|  | @ -5334,6 +5347,7 @@ void cifs_oplock_break(struct work_struct *work) | |||
| 	cifs_done_oplock_break(cinode); | ||||
| } | ||||
| 
 | ||||
| #if 0 // TODO remove 5333
 | ||||
| /*
 | ||||
|  * The presence of cifs_direct_io() in the address space ops vector | ||||
|  * allowes open() O_DIRECT flags which would have failed otherwise. | ||||
|  | @ -5352,6 +5366,7 @@ cifs_direct_io(struct kiocb *iocb, struct iov_iter *iter) | |||
|          */ | ||||
|         return -EINVAL; | ||||
| } | ||||
| #endif // netfs end remove 5333
 | ||||
| 
 | ||||
| static int cifs_swap_activate(struct swap_info_struct *sis, | ||||
| 			      struct file *swap_file, sector_t *span) | ||||
|  | @ -5414,15 +5429,13 @@ static void cifs_swap_deactivate(struct file *file) | |||
| } | ||||
| 
 | ||||
| const struct address_space_operations cifs_addr_ops = { | ||||
| 	.read_folio = cifs_read_folio, | ||||
| 	.readahead = cifs_readahead, | ||||
| 	.writepages = cifs_writepages, | ||||
| 	.write_begin = cifs_write_begin, | ||||
| 	.write_end = cifs_write_end, | ||||
| 	.read_folio	= netfs_read_folio, | ||||
| 	.readahead	= netfs_readahead, | ||||
| 	.writepages	= netfs_writepages, | ||||
| 	.dirty_folio	= netfs_dirty_folio, | ||||
| 	.release_folio = cifs_release_folio, | ||||
| 	.direct_IO = cifs_direct_io, | ||||
| 	.invalidate_folio = cifs_invalidate_folio, | ||||
| 	.release_folio	= netfs_release_folio, | ||||
| 	.direct_IO	= noop_direct_IO, | ||||
| 	.invalidate_folio = netfs_invalidate_folio, | ||||
| 	.migrate_folio	= filemap_migrate_folio, | ||||
| 	/*
 | ||||
| 	 * TODO: investigate and if useful we could add an is_dirty_writeback | ||||
|  | @ -5438,12 +5451,10 @@ const struct address_space_operations cifs_addr_ops = { | |||
|  * to leave cifs_readahead out of the address space operations. | ||||
|  */ | ||||
| const struct address_space_operations cifs_addr_ops_smallbuf = { | ||||
| 	.read_folio = cifs_read_folio, | ||||
| 	.writepages = cifs_writepages, | ||||
| 	.write_begin = cifs_write_begin, | ||||
| 	.write_end = cifs_write_end, | ||||
| 	.read_folio	= netfs_read_folio, | ||||
| 	.writepages	= netfs_writepages, | ||||
| 	.dirty_folio	= netfs_dirty_folio, | ||||
| 	.release_folio = cifs_release_folio, | ||||
| 	.invalidate_folio = cifs_invalidate_folio, | ||||
| 	.release_folio	= netfs_release_folio, | ||||
| 	.invalidate_folio = netfs_invalidate_folio, | ||||
| 	.migrate_folio	= filemap_migrate_folio, | ||||
| }; | ||||
|  |  | |||
|  | @ -171,6 +171,7 @@ void cifs_fscache_release_inode_cookie(struct inode *inode) | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| #if 0 // TODO remove
 | ||||
| /*
 | ||||
|  * Fallback page reading interface. | ||||
|  */ | ||||
|  | @ -279,3 +280,4 @@ int __cifs_fscache_query_occupancy(struct inode *inode, | |||
| 	fscache_end_operation(&cres); | ||||
| 	return ret; | ||||
| } | ||||
| #endif | ||||
|  |  | |||
|  | @ -74,6 +74,7 @@ static inline void cifs_invalidate_cache(struct inode *inode, unsigned int flags | |||
| 			   i_size_read(inode), flags); | ||||
| } | ||||
| 
 | ||||
| #if 0 // TODO remove
 | ||||
| extern int __cifs_fscache_query_occupancy(struct inode *inode, | ||||
| 					  pgoff_t first, unsigned int nr_pages, | ||||
| 					  pgoff_t *_data_first, | ||||
|  | @ -108,6 +109,7 @@ static inline void cifs_readahead_to_fscache(struct inode *inode, | |||
| 	if (cifs_inode_cookie(inode)) | ||||
| 		__cifs_readahead_to_fscache(inode, pos, len); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| static inline bool cifs_fscache_enabled(struct inode *inode) | ||||
| { | ||||
|  | @ -131,6 +133,7 @@ static inline struct fscache_cookie *cifs_inode_cookie(struct inode *inode) { re | |||
| static inline void cifs_invalidate_cache(struct inode *inode, unsigned int flags) {} | ||||
| static inline bool cifs_fscache_enabled(struct inode *inode) { return false; } | ||||
| 
 | ||||
| #if 0 // TODO remove
 | ||||
| static inline int cifs_fscache_query_occupancy(struct inode *inode, | ||||
| 					       pgoff_t first, unsigned int nr_pages, | ||||
| 					       pgoff_t *_data_first, | ||||
|  | @ -149,6 +152,7 @@ cifs_readpage_from_fscache(struct inode *inode, struct page *page) | |||
| 
 | ||||
| static inline | ||||
| void cifs_readahead_to_fscache(struct inode *inode, loff_t pos, size_t len) {} | ||||
| #endif | ||||
| 
 | ||||
| #endif /* CONFIG_CIFS_FSCACHE */ | ||||
| 
 | ||||
|  |  | |||
|  | @ -28,14 +28,29 @@ | |||
| #include "cached_dir.h" | ||||
| #include "reparse.h" | ||||
| 
 | ||||
| /*
 | ||||
|  * Set parameters for the netfs library | ||||
|  */ | ||||
| static void cifs_set_netfs_context(struct inode *inode) | ||||
| { | ||||
| 	struct cifsInodeInfo *cifs_i = CIFS_I(inode); | ||||
| 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||||
| 
 | ||||
| 	netfs_inode_init(&cifs_i->netfs, &cifs_req_ops, true); | ||||
| 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) | ||||
| 		__set_bit(NETFS_ICTX_WRITETHROUGH, &cifs_i->netfs.flags); | ||||
| } | ||||
| 
 | ||||
| static void cifs_set_ops(struct inode *inode) | ||||
| { | ||||
| 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||||
| 	struct netfs_inode *ictx = netfs_inode(inode); | ||||
| 
 | ||||
| 	switch (inode->i_mode & S_IFMT) { | ||||
| 	case S_IFREG: | ||||
| 		inode->i_op = &cifs_file_inode_ops; | ||||
| 		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { | ||||
| 			set_bit(NETFS_ICTX_UNBUFFERED, &ictx->flags); | ||||
| 			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||||
| 				inode->i_fop = &cifs_file_direct_nobrl_ops; | ||||
| 			else | ||||
|  | @ -221,8 +236,10 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr, | |||
| 
 | ||||
| 	if (fattr->cf_flags & CIFS_FATTR_JUNCTION) | ||||
| 		inode->i_flags |= S_AUTOMOUNT; | ||||
| 	if (inode->i_state & I_NEW) | ||||
| 	if (inode->i_state & I_NEW) { | ||||
| 		cifs_set_netfs_context(inode); | ||||
| 		cifs_set_ops(inode); | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -4421,7 +4421,9 @@ smb2_new_read_req(void **buf, unsigned int *total_len, | |||
| 	req->Length = cpu_to_le32(io_parms->length); | ||||
| 	req->Offset = cpu_to_le64(io_parms->offset); | ||||
| 
 | ||||
| 	trace_smb3_read_enter(0 /* xid */, | ||||
| 	trace_smb3_read_enter(rdata ? rdata->rreq->debug_id : 0, | ||||
| 			      rdata ? rdata->subreq.debug_index : 0, | ||||
| 			      rdata ? rdata->xid : 0, | ||||
| 			      io_parms->persistent_fid, | ||||
| 			      io_parms->tcon->tid, io_parms->tcon->ses->Suid, | ||||
| 			      io_parms->offset, io_parms->length); | ||||
|  | @ -4486,7 +4488,7 @@ static void | |||
| smb2_readv_callback(struct mid_q_entry *mid) | ||||
| { | ||||
| 	struct cifs_io_subrequest *rdata = mid->callback_data; | ||||
| 	struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); | ||||
| 	struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink); | ||||
| 	struct TCP_Server_Info *server = rdata->server; | ||||
| 	struct smb2_hdr *shdr = | ||||
| 				(struct smb2_hdr *)rdata->iov[0].iov_base; | ||||
|  | @ -4514,7 +4516,6 @@ smb2_readv_callback(struct mid_q_entry *mid) | |||
| 		if (server->sign && !mid->decrypted) { | ||||
| 			int rc; | ||||
| 
 | ||||
| 			iov_iter_revert(&rqst.rq_iter, rdata->got_bytes); | ||||
| 			iov_iter_truncate(&rqst.rq_iter, rdata->got_bytes); | ||||
| 			rc = smb2_verify_signature(&rqst, server); | ||||
| 			if (rc) | ||||
|  | @ -4555,17 +4556,33 @@ smb2_readv_callback(struct mid_q_entry *mid) | |||
| #endif | ||||
| 	if (rdata->result && rdata->result != -ENODATA) { | ||||
| 		cifs_stats_fail_inc(tcon, SMB2_READ_HE); | ||||
| 		trace_smb3_read_err(0 /* xid */, | ||||
| 				    rdata->cfile->fid.persistent_fid, | ||||
| 		trace_smb3_read_err(rdata->rreq->debug_id, | ||||
| 				    rdata->subreq.debug_index, | ||||
| 				    rdata->xid, | ||||
| 				    rdata->req->cfile->fid.persistent_fid, | ||||
| 				    tcon->tid, tcon->ses->Suid, rdata->subreq.start, | ||||
| 				    rdata->subreq.len, rdata->result); | ||||
| 	} else | ||||
| 		trace_smb3_read_done(0 /* xid */, | ||||
| 				     rdata->cfile->fid.persistent_fid, | ||||
| 		trace_smb3_read_done(rdata->rreq->debug_id, | ||||
| 				     rdata->subreq.debug_index, | ||||
| 				     rdata->xid, | ||||
| 				     rdata->req->cfile->fid.persistent_fid, | ||||
| 				     tcon->tid, tcon->ses->Suid, | ||||
| 				     rdata->subreq.start, rdata->got_bytes); | ||||
| 
 | ||||
| 	queue_work(cifsiod_wq, &rdata->work); | ||||
| 	if (rdata->result == -ENODATA) { | ||||
| 		/* We may have got an EOF error because fallocate
 | ||||
| 		 * failed to enlarge the file. | ||||
| 		 */ | ||||
| 		if (rdata->subreq.start < rdata->subreq.rreq->i_size) | ||||
| 			rdata->result = 0; | ||||
| 	} | ||||
| 	if (rdata->result == 0 || rdata->result == -EAGAIN) | ||||
| 		iov_iter_advance(&rdata->subreq.io_iter, rdata->got_bytes); | ||||
| 	rdata->credits.value = 0; | ||||
| 	netfs_subreq_terminated(&rdata->subreq, | ||||
| 				(rdata->result == 0 || rdata->result == -EAGAIN) ? | ||||
| 				rdata->got_bytes : rdata->result, true); | ||||
| 	release_mid(mid); | ||||
| 	add_credits(server, &credits, 0); | ||||
| } | ||||
|  | @ -4581,7 +4598,7 @@ smb2_async_readv(struct cifs_io_subrequest *rdata) | |||
| 	struct smb_rqst rqst = { .rq_iov = rdata->iov, | ||||
| 				 .rq_nvec = 1 }; | ||||
| 	struct TCP_Server_Info *server; | ||||
| 	struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); | ||||
| 	struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink); | ||||
| 	unsigned int total_len; | ||||
| 	int credit_request; | ||||
| 
 | ||||
|  | @ -4591,12 +4608,12 @@ smb2_async_readv(struct cifs_io_subrequest *rdata) | |||
| 	if (!rdata->server) | ||||
| 		rdata->server = cifs_pick_channel(tcon->ses); | ||||
| 
 | ||||
| 	io_parms.tcon = tlink_tcon(rdata->cfile->tlink); | ||||
| 	io_parms.tcon = tlink_tcon(rdata->req->cfile->tlink); | ||||
| 	io_parms.server = server = rdata->server; | ||||
| 	io_parms.offset = rdata->subreq.start; | ||||
| 	io_parms.length = rdata->subreq.len; | ||||
| 	io_parms.persistent_fid = rdata->cfile->fid.persistent_fid; | ||||
| 	io_parms.volatile_fid = rdata->cfile->fid.volatile_fid; | ||||
| 	io_parms.persistent_fid = rdata->req->cfile->fid.persistent_fid; | ||||
| 	io_parms.volatile_fid = rdata->req->cfile->fid.volatile_fid; | ||||
| 	io_parms.pid = rdata->pid; | ||||
| 
 | ||||
| 	rc = smb2_new_read_req( | ||||
|  | @ -4630,15 +4647,15 @@ smb2_async_readv(struct cifs_io_subrequest *rdata) | |||
| 		flags |= CIFS_HAS_CREDITS; | ||||
| 	} | ||||
| 
 | ||||
| 	cifs_get_readdata(rdata); | ||||
| 	rc = cifs_call_async(server, &rqst, | ||||
| 			     cifs_readv_receive, smb2_readv_callback, | ||||
| 			     smb3_handle_read_data, rdata, flags, | ||||
| 			     &rdata->credits); | ||||
| 	if (rc) { | ||||
| 		cifs_put_readdata(rdata); | ||||
| 		cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE); | ||||
| 		trace_smb3_read_err(0 /* xid */, io_parms.persistent_fid, | ||||
| 		trace_smb3_read_err(rdata->rreq->debug_id, | ||||
| 				    rdata->subreq.debug_index, | ||||
| 				    rdata->xid, io_parms.persistent_fid, | ||||
| 				    io_parms.tcon->tid, | ||||
| 				    io_parms.tcon->ses->Suid, | ||||
| 				    io_parms.offset, io_parms.length, rc); | ||||
|  | @ -4689,19 +4706,20 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, | |||
| 		if (rc != -ENODATA) { | ||||
| 			cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE); | ||||
| 			cifs_dbg(VFS, "Send error in read = %d\n", rc); | ||||
| 			trace_smb3_read_err(xid, | ||||
| 			trace_smb3_read_err(0, 0, xid, | ||||
| 					    req->PersistentFileId, | ||||
| 					    io_parms->tcon->tid, ses->Suid, | ||||
| 					    io_parms->offset, io_parms->length, | ||||
| 					    rc); | ||||
| 		} else | ||||
| 			trace_smb3_read_done(xid, req->PersistentFileId, io_parms->tcon->tid, | ||||
| 			trace_smb3_read_done(0, 0, xid, | ||||
| 					     req->PersistentFileId, io_parms->tcon->tid, | ||||
| 					     ses->Suid, io_parms->offset, 0); | ||||
| 		free_rsp_buf(resp_buftype, rsp_iov.iov_base); | ||||
| 		cifs_small_buf_release(req); | ||||
| 		return rc == -ENODATA ? 0 : rc; | ||||
| 	} else | ||||
| 		trace_smb3_read_done(xid, | ||||
| 		trace_smb3_read_done(0, 0, xid, | ||||
| 				     req->PersistentFileId, | ||||
| 				     io_parms->tcon->tid, ses->Suid, | ||||
| 				     io_parms->offset, io_parms->length); | ||||
|  | @ -4738,11 +4756,12 @@ static void | |||
| smb2_writev_callback(struct mid_q_entry *mid) | ||||
| { | ||||
| 	struct cifs_io_subrequest *wdata = mid->callback_data; | ||||
| 	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); | ||||
| 	struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink); | ||||
| 	struct TCP_Server_Info *server = wdata->server; | ||||
| 	unsigned int written; | ||||
| 	struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf; | ||||
| 	struct cifs_credits credits = { .value = 0, .instance = 0 }; | ||||
| 	ssize_t result = 0; | ||||
| 	size_t written; | ||||
| 
 | ||||
| 	WARN_ONCE(wdata->server != mid->server, | ||||
| 		  "wdata server %p != mid server %p", | ||||
|  | @ -4752,8 +4771,8 @@ smb2_writev_callback(struct mid_q_entry *mid) | |||
| 	case MID_RESPONSE_RECEIVED: | ||||
| 		credits.value = le16_to_cpu(rsp->hdr.CreditRequest); | ||||
| 		credits.instance = server->reconnect_instance; | ||||
| 		wdata->result = smb2_check_receive(mid, server, 0); | ||||
| 		if (wdata->result != 0) | ||||
| 		result = smb2_check_receive(mid, server, 0); | ||||
| 		if (result != 0) | ||||
| 			break; | ||||
| 
 | ||||
| 		written = le32_to_cpu(rsp->DataLength); | ||||
|  | @ -4770,17 +4789,18 @@ smb2_writev_callback(struct mid_q_entry *mid) | |||
| 			wdata->result = -ENOSPC; | ||||
| 		else | ||||
| 			wdata->subreq.len = written; | ||||
| 		iov_iter_advance(&wdata->subreq.io_iter, written); | ||||
| 		break; | ||||
| 	case MID_REQUEST_SUBMITTED: | ||||
| 	case MID_RETRY_NEEDED: | ||||
| 		wdata->result = -EAGAIN; | ||||
| 		result = -EAGAIN; | ||||
| 		break; | ||||
| 	case MID_RESPONSE_MALFORMED: | ||||
| 		credits.value = le16_to_cpu(rsp->hdr.CreditRequest); | ||||
| 		credits.instance = server->reconnect_instance; | ||||
| 		fallthrough; | ||||
| 	default: | ||||
| 		wdata->result = -EIO; | ||||
| 		result = -EIO; | ||||
| 		break; | ||||
| 	} | ||||
| #ifdef CONFIG_CIFS_SMB_DIRECT | ||||
|  | @ -4796,10 +4816,10 @@ smb2_writev_callback(struct mid_q_entry *mid) | |||
| 		wdata->mr = NULL; | ||||
| 	} | ||||
| #endif | ||||
| 	if (wdata->result) { | ||||
| 	if (result) { | ||||
| 		cifs_stats_fail_inc(tcon, SMB2_WRITE_HE); | ||||
| 		trace_smb3_write_err(0 /* no xid */, | ||||
| 				     wdata->cfile->fid.persistent_fid, | ||||
| 		trace_smb3_write_err(wdata->xid, | ||||
| 				     wdata->req->cfile->fid.persistent_fid, | ||||
| 				     tcon->tid, tcon->ses->Suid, wdata->subreq.start, | ||||
| 				     wdata->subreq.len, wdata->result); | ||||
| 		if (wdata->result == -ENOSPC) | ||||
|  | @ -4807,27 +4827,28 @@ smb2_writev_callback(struct mid_q_entry *mid) | |||
| 				     tcon->tree_name); | ||||
| 	} else | ||||
| 		trace_smb3_write_done(0 /* no xid */, | ||||
| 				      wdata->cfile->fid.persistent_fid, | ||||
| 				      wdata->req->cfile->fid.persistent_fid, | ||||
| 				      tcon->tid, tcon->ses->Suid, | ||||
| 				      wdata->subreq.start, wdata->subreq.len); | ||||
| 
 | ||||
| 	queue_work(cifsiod_wq, &wdata->work); | ||||
| 	wdata->credits.value = 0; | ||||
| 	cifs_write_subrequest_terminated(wdata, result ?: written, true); | ||||
| 	release_mid(mid); | ||||
| 	add_credits(server, &credits, 0); | ||||
| } | ||||
| 
 | ||||
| /* smb2_async_writev - send an async write, and set up mid to handle result */ | ||||
| int | ||||
| void | ||||
| smb2_async_writev(struct cifs_io_subrequest *wdata) | ||||
| { | ||||
| 	int rc = -EACCES, flags = 0; | ||||
| 	struct smb2_write_req *req = NULL; | ||||
| 	struct smb2_hdr *shdr; | ||||
| 	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); | ||||
| 	struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink); | ||||
| 	struct TCP_Server_Info *server = wdata->server; | ||||
| 	struct kvec iov[1]; | ||||
| 	struct smb_rqst rqst = { }; | ||||
| 	unsigned int total_len; | ||||
| 	unsigned int total_len, xid = wdata->xid; | ||||
| 	struct cifs_io_parms _io_parms; | ||||
| 	struct cifs_io_parms *io_parms = NULL; | ||||
| 	int credit_request; | ||||
|  | @ -4844,8 +4865,8 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) | |||
| 		.server = server, | ||||
| 		.offset = wdata->subreq.start, | ||||
| 		.length = wdata->subreq.len, | ||||
| 		.persistent_fid = wdata->cfile->fid.persistent_fid, | ||||
| 		.volatile_fid = wdata->cfile->fid.volatile_fid, | ||||
| 		.persistent_fid = wdata->req->cfile->fid.persistent_fid, | ||||
| 		.volatile_fid = wdata->req->cfile->fid.volatile_fid, | ||||
| 		.pid = wdata->pid, | ||||
| 	}; | ||||
| 	io_parms = &_io_parms; | ||||
|  | @ -4853,7 +4874,7 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) | |||
| 	rc = smb2_plain_req_init(SMB2_WRITE, tcon, server, | ||||
| 				 (void **) &req, &total_len); | ||||
| 	if (rc) | ||||
| 		return rc; | ||||
| 		goto out; | ||||
| 
 | ||||
| 	if (smb3_encryption_required(tcon)) | ||||
| 		flags |= CIFS_TRANSFORM_REQ; | ||||
|  | @ -4871,7 +4892,7 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) | |||
| 				offsetof(struct smb2_write_req, Buffer)); | ||||
| 	req->RemainingBytes = 0; | ||||
| 
 | ||||
| 	trace_smb3_write_enter(0 /* xid */, | ||||
| 	trace_smb3_write_enter(wdata->xid, | ||||
| 			       io_parms->persistent_fid, | ||||
| 			       io_parms->tcon->tid, | ||||
| 			       io_parms->tcon->ses->Suid, | ||||
|  | @ -4952,25 +4973,27 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) | |||
| 		flags |= CIFS_HAS_CREDITS; | ||||
| 	} | ||||
| 
 | ||||
| 	cifs_get_writedata(wdata); | ||||
| 	rc = cifs_call_async(server, &rqst, NULL, smb2_writev_callback, NULL, | ||||
| 			     wdata, flags, &wdata->credits); | ||||
| 
 | ||||
| 	/* Can't touch wdata if rc == 0 */ | ||||
| 	if (rc) { | ||||
| 		trace_smb3_write_err(0 /* no xid */, | ||||
| 		trace_smb3_write_err(xid, | ||||
| 				     io_parms->persistent_fid, | ||||
| 				     io_parms->tcon->tid, | ||||
| 				     io_parms->tcon->ses->Suid, | ||||
| 				     io_parms->offset, | ||||
| 				     io_parms->length, | ||||
| 				     rc); | ||||
| 		cifs_put_writedata(wdata); | ||||
| 		cifs_stats_fail_inc(tcon, SMB2_WRITE_HE); | ||||
| 	} | ||||
| 
 | ||||
| async_writev_out: | ||||
| 	cifs_small_buf_release(req); | ||||
| 	return rc; | ||||
| out: | ||||
| 	if (rc) { | ||||
| 		add_credits_and_wake_if(wdata->server, &wdata->credits, 0); | ||||
| 		cifs_write_subrequest_terminated(wdata, rc, true); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  |  | |||
|  | @ -213,7 +213,7 @@ extern int SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon, | |||
| extern int smb2_async_readv(struct cifs_io_subrequest *rdata); | ||||
| extern int SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, | ||||
| 		     unsigned int *nbytes, char **buf, int *buf_type); | ||||
| extern int smb2_async_writev(struct cifs_io_subrequest *wdata); | ||||
| extern void smb2_async_writev(struct cifs_io_subrequest *wdata); | ||||
| extern int SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms, | ||||
| 		      unsigned int *nbytes, struct kvec *iov, int n_vec); | ||||
| extern int SMB2_echo(struct TCP_Server_Info *server); | ||||
|  |  | |||
|  | @ -85,6 +85,62 @@ smb3_tcon_ref_traces; | |||
| 
 | ||||
| /* For logging errors in read or write */ | ||||
| DECLARE_EVENT_CLASS(smb3_rw_err_class, | ||||
| 	TP_PROTO(unsigned int rreq_debug_id, | ||||
| 		 unsigned int rreq_debug_index, | ||||
| 		 unsigned int xid, | ||||
| 		 __u64	fid, | ||||
| 		 __u32	tid, | ||||
| 		 __u64	sesid, | ||||
| 		 __u64	offset, | ||||
| 		 __u32	len, | ||||
| 		 int	rc), | ||||
| 	TP_ARGS(rreq_debug_id, rreq_debug_index, | ||||
| 		xid, fid, tid, sesid, offset, len, rc), | ||||
| 	TP_STRUCT__entry( | ||||
| 		__field(unsigned int, rreq_debug_id) | ||||
| 		__field(unsigned int, rreq_debug_index) | ||||
| 		__field(unsigned int, xid) | ||||
| 		__field(__u64, fid) | ||||
| 		__field(__u32, tid) | ||||
| 		__field(__u64, sesid) | ||||
| 		__field(__u64, offset) | ||||
| 		__field(__u32, len) | ||||
| 		__field(int, rc) | ||||
| 	), | ||||
| 	TP_fast_assign( | ||||
| 		__entry->rreq_debug_id = rreq_debug_id; | ||||
| 		__entry->rreq_debug_index = rreq_debug_index; | ||||
| 		__entry->xid = xid; | ||||
| 		__entry->fid = fid; | ||||
| 		__entry->tid = tid; | ||||
| 		__entry->sesid = sesid; | ||||
| 		__entry->offset = offset; | ||||
| 		__entry->len = len; | ||||
| 		__entry->rc = rc; | ||||
| 	), | ||||
| 	TP_printk("\tR=%08x[%x] xid=%u sid=0x%llx tid=0x%x fid=0x%llx offset=0x%llx len=0x%x rc=%d", | ||||
| 		  __entry->rreq_debug_id, __entry->rreq_debug_index, | ||||
| 		  __entry->xid, __entry->sesid, __entry->tid, __entry->fid, | ||||
| 		  __entry->offset, __entry->len, __entry->rc) | ||||
| ) | ||||
| 
 | ||||
| #define DEFINE_SMB3_RW_ERR_EVENT(name)          \ | ||||
| DEFINE_EVENT(smb3_rw_err_class, smb3_##name,    \ | ||||
| 	TP_PROTO(unsigned int rreq_debug_id,	\ | ||||
| 		 unsigned int rreq_debug_index,		\ | ||||
| 		 unsigned int xid,			\ | ||||
| 		 __u64	fid,				\ | ||||
| 		 __u32	tid,				\ | ||||
| 		 __u64	sesid,				\ | ||||
| 		 __u64	offset,				\ | ||||
| 		 __u32	len,				\ | ||||
| 		 int	rc),				\ | ||||
| 	TP_ARGS(rreq_debug_id, rreq_debug_index, xid, fid, tid, sesid, offset, len, rc)) | ||||
| 
 | ||||
| DEFINE_SMB3_RW_ERR_EVENT(read_err); | ||||
| 
 | ||||
| /* For logging errors in other file I/O ops */ | ||||
| DECLARE_EVENT_CLASS(smb3_other_err_class, | ||||
| 	TP_PROTO(unsigned int xid, | ||||
| 		__u64	fid, | ||||
| 		__u32	tid, | ||||
|  | @ -116,8 +172,8 @@ DECLARE_EVENT_CLASS(smb3_rw_err_class, | |||
| 		__entry->offset, __entry->len, __entry->rc) | ||||
| ) | ||||
| 
 | ||||
| #define DEFINE_SMB3_RW_ERR_EVENT(name)          \ | ||||
| DEFINE_EVENT(smb3_rw_err_class, smb3_##name,    \ | ||||
| #define DEFINE_SMB3_OTHER_ERR_EVENT(name)	\ | ||||
| DEFINE_EVENT(smb3_other_err_class, smb3_##name, \ | ||||
| 	TP_PROTO(unsigned int xid,		\ | ||||
| 		__u64	fid,			\ | ||||
| 		__u32	tid,			\ | ||||
|  | @ -127,15 +183,67 @@ DEFINE_EVENT(smb3_rw_err_class, smb3_##name,    \ | |||
| 		int	rc),			\ | ||||
| 	TP_ARGS(xid, fid, tid, sesid, offset, len, rc)) | ||||
| 
 | ||||
| DEFINE_SMB3_RW_ERR_EVENT(write_err); | ||||
| DEFINE_SMB3_RW_ERR_EVENT(read_err); | ||||
| DEFINE_SMB3_RW_ERR_EVENT(query_dir_err); | ||||
| DEFINE_SMB3_RW_ERR_EVENT(zero_err); | ||||
| DEFINE_SMB3_RW_ERR_EVENT(falloc_err); | ||||
| DEFINE_SMB3_OTHER_ERR_EVENT(write_err); | ||||
| DEFINE_SMB3_OTHER_ERR_EVENT(query_dir_err); | ||||
| DEFINE_SMB3_OTHER_ERR_EVENT(zero_err); | ||||
| DEFINE_SMB3_OTHER_ERR_EVENT(falloc_err); | ||||
| 
 | ||||
| 
 | ||||
| /* For logging successful read or write */ | ||||
| DECLARE_EVENT_CLASS(smb3_rw_done_class, | ||||
| 	TP_PROTO(unsigned int rreq_debug_id, | ||||
| 		 unsigned int rreq_debug_index, | ||||
| 		 unsigned int xid, | ||||
| 		 __u64	fid, | ||||
| 		 __u32	tid, | ||||
| 		 __u64	sesid, | ||||
| 		 __u64	offset, | ||||
| 		 __u32	len), | ||||
| 	TP_ARGS(rreq_debug_id, rreq_debug_index, | ||||
| 		xid, fid, tid, sesid, offset, len), | ||||
| 	TP_STRUCT__entry( | ||||
| 		__field(unsigned int, rreq_debug_id) | ||||
| 		__field(unsigned int, rreq_debug_index) | ||||
| 		__field(unsigned int, xid) | ||||
| 		__field(__u64, fid) | ||||
| 		__field(__u32, tid) | ||||
| 		__field(__u64, sesid) | ||||
| 		__field(__u64, offset) | ||||
| 		__field(__u32, len) | ||||
| 	), | ||||
| 	TP_fast_assign( | ||||
| 		__entry->rreq_debug_id = rreq_debug_id; | ||||
| 		__entry->rreq_debug_index = rreq_debug_index; | ||||
| 		__entry->xid = xid; | ||||
| 		__entry->fid = fid; | ||||
| 		__entry->tid = tid; | ||||
| 		__entry->sesid = sesid; | ||||
| 		__entry->offset = offset; | ||||
| 		__entry->len = len; | ||||
| 	), | ||||
| 	TP_printk("R=%08x[%x] xid=%u sid=0x%llx tid=0x%x fid=0x%llx offset=0x%llx len=0x%x", | ||||
| 		  __entry->rreq_debug_id, __entry->rreq_debug_index, | ||||
| 		  __entry->xid, __entry->sesid, __entry->tid, __entry->fid, | ||||
| 		  __entry->offset, __entry->len) | ||||
| ) | ||||
| 
 | ||||
| #define DEFINE_SMB3_RW_DONE_EVENT(name)         \ | ||||
| DEFINE_EVENT(smb3_rw_done_class, smb3_##name,   \ | ||||
| 	TP_PROTO(unsigned int rreq_debug_id,	\ | ||||
| 		 unsigned int rreq_debug_index,	\ | ||||
| 		 unsigned int xid,		\ | ||||
| 		__u64	fid,			\ | ||||
| 		__u32	tid,			\ | ||||
| 		__u64	sesid,			\ | ||||
| 		__u64	offset,			\ | ||||
| 		__u32	len),			\ | ||||
| 	TP_ARGS(rreq_debug_id, rreq_debug_index, xid, fid, tid, sesid, offset, len)) | ||||
| 
 | ||||
| DEFINE_SMB3_RW_DONE_EVENT(read_enter); | ||||
| DEFINE_SMB3_RW_DONE_EVENT(read_done); | ||||
| 
 | ||||
| /* For logging successful other op */ | ||||
| DECLARE_EVENT_CLASS(smb3_other_done_class, | ||||
| 	TP_PROTO(unsigned int xid, | ||||
| 		__u64	fid, | ||||
| 		__u32	tid, | ||||
|  | @ -164,8 +272,8 @@ DECLARE_EVENT_CLASS(smb3_rw_done_class, | |||
| 		__entry->offset, __entry->len) | ||||
| ) | ||||
| 
 | ||||
| #define DEFINE_SMB3_RW_DONE_EVENT(name)         \ | ||||
| DEFINE_EVENT(smb3_rw_done_class, smb3_##name,   \ | ||||
| #define DEFINE_SMB3_OTHER_DONE_EVENT(name)         \ | ||||
| DEFINE_EVENT(smb3_other_done_class, smb3_##name,   \ | ||||
| 	TP_PROTO(unsigned int xid,		\ | ||||
| 		__u64	fid,			\ | ||||
| 		__u32	tid,			\ | ||||
|  | @ -174,16 +282,14 @@ DEFINE_EVENT(smb3_rw_done_class, smb3_##name,   \ | |||
| 		__u32	len),			\ | ||||
| 	TP_ARGS(xid, fid, tid, sesid, offset, len)) | ||||
| 
 | ||||
| DEFINE_SMB3_RW_DONE_EVENT(write_enter); | ||||
| DEFINE_SMB3_RW_DONE_EVENT(read_enter); | ||||
| DEFINE_SMB3_RW_DONE_EVENT(query_dir_enter); | ||||
| DEFINE_SMB3_RW_DONE_EVENT(zero_enter); | ||||
| DEFINE_SMB3_RW_DONE_EVENT(falloc_enter); | ||||
| DEFINE_SMB3_RW_DONE_EVENT(write_done); | ||||
| DEFINE_SMB3_RW_DONE_EVENT(read_done); | ||||
| DEFINE_SMB3_RW_DONE_EVENT(query_dir_done); | ||||
| DEFINE_SMB3_RW_DONE_EVENT(zero_done); | ||||
| DEFINE_SMB3_RW_DONE_EVENT(falloc_done); | ||||
| DEFINE_SMB3_OTHER_DONE_EVENT(write_enter); | ||||
| DEFINE_SMB3_OTHER_DONE_EVENT(query_dir_enter); | ||||
| DEFINE_SMB3_OTHER_DONE_EVENT(zero_enter); | ||||
| DEFINE_SMB3_OTHER_DONE_EVENT(falloc_enter); | ||||
| DEFINE_SMB3_OTHER_DONE_EVENT(write_done); | ||||
| DEFINE_SMB3_OTHER_DONE_EVENT(query_dir_done); | ||||
| DEFINE_SMB3_OTHER_DONE_EVENT(zero_done); | ||||
| DEFINE_SMB3_OTHER_DONE_EVENT(falloc_done); | ||||
| 
 | ||||
| /* For logging successful set EOF (truncate) */ | ||||
| DECLARE_EVENT_CLASS(smb3_eof_class, | ||||
|  |  | |||
|  | @ -1813,8 +1813,11 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
| 		length = data_len; /* An RDMA read is already done. */ | ||||
| 	else | ||||
| #endif | ||||
| 	{ | ||||
| 		length = cifs_read_iter_from_socket(server, &rdata->subreq.io_iter, | ||||
| 						    data_len); | ||||
| 		iov_iter_revert(&rdata->subreq.io_iter, data_len); | ||||
| 	} | ||||
| 	if (length > 0) | ||||
| 		rdata->got_bytes += length; | ||||
| 	server->total_read += length; | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 David Howells
						David Howells