Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2422f676 authored by Jeff Layton's avatar Jeff Layton
Browse files

cifs: move cifs_new_fileinfo call out of cifs_posix_open



Having cifs_posix_open call cifs_new_fileinfo is problematic and
inconsistent with how "regular" opens work. It's also buggy as
cifs_reopen_file calls this function on a reconnect, which creates a new
struct cifsFileInfo that just gets leaked.

Push it out into the callers. This also allows us to get rid of the
"mnt" arg to cifs_posix_open.

Finally, in the event that a cifsFileInfo isn't or can't be created, we
always want to close the filehandle out on the server as the client
won't have a record of the filehandle and can't actually use it. Make
sure that CIFSSMBClose is called in those cases.

Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Reviewed-and-Tested-by: default avatarSuresh Jayaraman <sjayaraman@suse.de>
parent 0933a95d
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -106,7 +106,6 @@ extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode,
				__u16 fileHandle, struct file *file,
				struct vfsmount *mnt, unsigned int oflags);
extern int cifs_posix_open(char *full_path, struct inode **pinode,
				struct vfsmount *mnt,
				struct super_block *sb,
				int mode, int oflags,
				__u32 *poplock, __u16 *pnetfid, int xid);
+18 −25
Original line number Diff line number Diff line
@@ -188,8 +188,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle,
}

int cifs_posix_open(char *full_path, struct inode **pinode,
			struct vfsmount *mnt, struct super_block *sb,
			int mode, int oflags,
			struct super_block *sb, int mode, int oflags,
			__u32 *poplock, __u16 *pnetfid, int xid)
{
	int rc;
@@ -258,19 +257,6 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
		cifs_fattr_to_inode(*pinode, &fattr);
	}

	/*
	 * cifs_fill_filedata() takes care of setting cifsFileInfo pointer to
	 * file->private_data.
	 */
	if (mnt) {
		struct cifsFileInfo *pfile_info;

		pfile_info = cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt,
					       oflags);
		if (pfile_info == NULL)
			rc = -ENOMEM;
	}

posix_open_ret:
	kfree(presp_data);
	return rc;
@@ -298,7 +284,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
	int create_options = CREATE_NOT_DIR;
	__u32 oplock = 0;
	int oflags;
	bool posix_create = false;
	/*
	 * BB below access is probably too much for mknod to request
	 *    but we have to do query and setpathinfo so requesting
@@ -339,7 +324,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
	    (CIFS_UNIX_POSIX_PATH_OPS_CAP &
			le64_to_cpu(tcon->fsUnixInfo.Capability))) {
		rc = cifs_posix_open(full_path, &newinode,
			nd ? nd->path.mnt : NULL,
			inode->i_sb, mode, oflags, &oplock, &fileHandle, xid);
		/* EIO could indicate that (posix open) operation is not
		   supported, despite what server claimed in capability
@@ -347,7 +331,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
		   handled in posix open */

		if (rc == 0) {
			posix_create = true;
			if (newinode == NULL) /* query inode info */
				goto cifs_create_get_file_info;
			else /* success, no need to query */
@@ -478,11 +461,7 @@ cifs_create_set_dentry:
	else
		cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);

	/* nfsd case - nfs srv does not set nd */
	if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
		/* mknod case - do not leave file open */
		CIFSSMBClose(xid, tcon, fileHandle);
	} else if (!(posix_create) && (newinode)) {
	if (newinode && nd && (nd->flags & LOOKUP_OPEN)) {
		struct cifsFileInfo *pfile_info;
		/*
		 * cifs_fill_filedata() takes care of setting cifsFileInfo
@@ -492,7 +471,10 @@ cifs_create_set_dentry:
					       nd->path.mnt, oflags);
		if (pfile_info == NULL)
			rc = -ENOMEM;
	} else {
		CIFSSMBClose(xid, tcon, fileHandle);
	}

cifs_create_out:
	kfree(buf);
	kfree(full_path);
@@ -636,6 +618,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
	bool posix_open = false;
	struct cifs_sb_info *cifs_sb;
	struct cifsTconInfo *pTcon;
	struct cifsFileInfo *cfile;
	struct inode *newInode = NULL;
	char *full_path = NULL;
	struct file *filp;
@@ -703,7 +686,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
		if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
		     (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
		     (nd->intent.open.flags & O_CREAT)) {
			rc = cifs_posix_open(full_path, &newInode, nd->path.mnt,
			rc = cifs_posix_open(full_path, &newInode,
					parent_dir_inode->i_sb,
					nd->intent.open.create_mode,
					nd->intent.open.flags, &oplock,
@@ -733,8 +716,17 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
		else
			direntry->d_op = &cifs_dentry_ops;
		d_add(direntry, newInode);
		if (posix_open)
		if (posix_open) {
			cfile = cifs_new_fileinfo(newInode, fileHandle, NULL,
						  nd->path.mnt,
						  nd->intent.open.flags);
			if (cfile == NULL) {
				CIFSSMBClose(xid, pTcon, fileHandle);
				rc = -ENOMEM;
				goto lookup_out;
			}
			filp = lookup_instantiate_filp(nd, direntry, NULL);
		}
		/* since paths are not looked up by component - the parent
		   directories are presumed to be good here */
		renew_parental_timestamps(direntry);
@@ -755,6 +747,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
		is a common return code */
	}

lookup_out:
	kfree(full_path);
	FreeXid(xid);
	return ERR_PTR(rc);
+12 −5
Original line number Diff line number Diff line
@@ -299,8 +299,7 @@ int cifs_open(struct inode *inode, struct file *file)
		int oflags = (int) cifs_posix_convert_flags(file->f_flags);
		oflags |= SMB_O_CREAT;
		/* can not refresh inode info since size could be stale */
		rc = cifs_posix_open(full_path, &inode, file->f_path.mnt,
				inode->i_sb,
		rc = cifs_posix_open(full_path, &inode, inode->i_sb,
				cifs_sb->mnt_file_mode /* ignored */,
				oflags, &oplock, &netfid, xid);
		if (rc == 0) {
@@ -308,7 +307,16 @@ int cifs_open(struct inode *inode, struct file *file)
			/* no need for special case handling of setting mode
			   on read only files needed here */

			pCifsFile = cifs_fill_filedata(file);
			pCifsFile = cifs_new_fileinfo(inode, netfid, file,
							file->f_path.mnt,
							oflags);
			if (pCifsFile == NULL) {
				CIFSSMBClose(xid, tcon, netfid);
				rc = -ENOMEM;
				goto out;
			}
			file->private_data = pCifsFile;

			cifs_posix_open_inode_helper(inode, file, pCifsInode,
						     oplock, netfid);
			goto out;
@@ -513,8 +521,7 @@ reopen_error_exit:
			le64_to_cpu(tcon->fsUnixInfo.Capability))) {
		int oflags = (int) cifs_posix_convert_flags(file->f_flags);
		/* can not refresh inode info since size could be stale */
		rc = cifs_posix_open(full_path, NULL, file->f_path.mnt,
				inode->i_sb,
		rc = cifs_posix_open(full_path, NULL, inode->i_sb,
				cifs_sb->mnt_file_mode /* ignored */,
				oflags, &oplock, &netfid, xid);
		if (rc == 0) {