diff options
| author | Ronnie Sahlberg <lsahlber@redhat.com> | 2019-09-09 15:30:00 +1000 | 
|---|---|---|
| committer | Steve French <stfrench@microsoft.com> | 2019-09-16 11:43:38 -0500 | 
| commit | 496902dc173dead0e5eeba1f2fd4abd9ba6f2da0 (patch) | |
| tree | 196a00f93a641cb5e1cc4c9981c1e24dcfae66bb /fs/cifs | |
| parent | 563317ec3083f7e126d7e30821ff8505ac338ee5 (diff) | |
| download | linux-496902dc173dead0e5eeba1f2fd4abd9ba6f2da0.tar.bz2 | |
cifs: add a helper to find an existing readable handle to a file
and convert smb2_query_path_info() to use it.
This will eliminate the need for a SMB2_Create when we already have an
open handle that can be used. This will also prevent a oplock break
in case the other handle holds a lease.
Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/cifs')
| -rw-r--r-- | fs/cifs/cifsproto.h | 2 | ||||
| -rw-r--r-- | fs/cifs/file.c | 36 | ||||
| -rw-r--r-- | fs/cifs/smb2inode.c | 28 | 
3 files changed, 61 insertions, 5 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 7b69037bed24..99b1b1ef558c 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -140,6 +140,8 @@ extern int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,  extern int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,  				  struct cifsFileInfo **ret_file);  extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); +extern int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name, +				  struct cifsFileInfo **ret_file);  extern unsigned int smbCalcSize(void *buf, struct TCP_Server_Info *server);  extern int decode_negTokenInit(unsigned char *security_blob, int length,  			struct TCP_Server_Info *server); diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 6124b1d1ab05..4b95700c507c 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -2008,6 +2008,42 @@ cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,  	return -ENOENT;  } +int +cifs_get_readable_path(struct cifs_tcon *tcon, const char *name, +		       struct cifsFileInfo **ret_file) +{ +	struct list_head *tmp; +	struct cifsFileInfo *cfile; +	struct cifsInodeInfo *cinode; +	char *full_path; + +	*ret_file = NULL; + +	spin_lock(&tcon->open_file_lock); +	list_for_each(tmp, &tcon->openFileList) { +		cfile = list_entry(tmp, struct cifsFileInfo, +			     tlist); +		full_path = build_path_from_dentry(cfile->dentry); +		if (full_path == NULL) { +			spin_unlock(&tcon->open_file_lock); +			return -ENOMEM; +		} +		if (strcmp(full_path, name)) { +			kfree(full_path); +			continue; +		} + +		kfree(full_path); +		cinode = CIFS_I(d_inode(cfile->dentry)); +		spin_unlock(&tcon->open_file_lock); +		*ret_file = find_readable_file(cinode, 0); +		return *ret_file ? 0 : -ENOENT; +	} + +	spin_unlock(&tcon->open_file_lock); +	return -ENOENT; +} +  static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)  {  	struct address_space *mapping = page->mapping; diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c index 9bb0a5bc38c9..c866555b6278 100644 --- a/fs/cifs/smb2inode.c +++ b/fs/cifs/smb2inode.c @@ -125,15 +125,31 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,  		rqst[num_rqst].rq_iov = qi_iov;  		rqst[num_rqst].rq_nvec = 1; -		rc = SMB2_query_info_init(tcon, &rqst[num_rqst], COMPOUND_FID, -				COMPOUND_FID, FILE_ALL_INFORMATION, +		if (cfile) +			rc = SMB2_query_info_init(tcon, &rqst[num_rqst], +				cfile->fid.persistent_fid, +				cfile->fid.volatile_fid, +				FILE_ALL_INFORMATION,  				SMB2_O_INFO_FILE, 0,  				sizeof(struct smb2_file_all_info) +  					  PATH_MAX * 2, 0, NULL); +		else { +			rc = SMB2_query_info_init(tcon, &rqst[num_rqst], +				COMPOUND_FID, +				COMPOUND_FID, +				 FILE_ALL_INFORMATION, +				SMB2_O_INFO_FILE, 0, +				sizeof(struct smb2_file_all_info) + +					  PATH_MAX * 2, 0, NULL); +			if (!rc) { +				smb2_set_next_command(tcon, &rqst[num_rqst]); +				smb2_set_related(&rqst[num_rqst]); +			} +		} +  		if (rc)  			goto finished; -		smb2_set_next_command(tcon, &rqst[num_rqst]); -		smb2_set_related(&rqst[num_rqst++]); +		num_rqst++;  		trace_smb3_query_info_compound_enter(xid, ses->Suid, tcon->tid,  						     full_path);  		break; @@ -421,6 +437,7 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,  	__u32 create_options = 0;  	struct cifs_fid fid;  	bool no_cached_open = tcon->nohandlecache; +	struct cifsFileInfo *cfile;  	*adjust_tz = false;  	*symlink = false; @@ -452,9 +469,10 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,  	if (backup_cred(cifs_sb))  		create_options |= CREATE_OPEN_BACKUP_INTENT; +	cifs_get_readable_path(tcon, full_path, &cfile);  	rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,  			      FILE_READ_ATTRIBUTES, FILE_OPEN, create_options, -			      smb2_data, SMB2_OP_QUERY_INFO, NULL); +			      smb2_data, SMB2_OP_QUERY_INFO, cfile);  	if (rc == -EOPNOTSUPP) {  		*symlink = true;  		create_options |= OPEN_REPARSE_POINT;  |