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

Commit ff691e96 authored by Pavel Shilovsky's avatar Pavel Shilovsky Committed by Steve French
Browse files

CIFS: Simplify cifs_mkdir call

parent b387e41e
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -289,10 +289,10 @@ extern int CIFSSMBUnixSetFileInfo(const unsigned int xid,
				  u16 fid, u32 pid_of_opener);

extern int CIFSSMBUnixSetPathInfo(const unsigned int xid,
				  struct cifs_tcon *tcon, char *file_name,
				  struct cifs_tcon *tcon, const char *file_name,
				  const struct cifs_unix_set_info_args *args,
				  const struct nls_table *nls_codepage,
				  int remap_special_chars);
				  int remap);

extern int CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon,
			const char *newName,
+4 −4
Original line number Diff line number Diff line
@@ -5943,7 +5943,7 @@ CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,

int
CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
		       char *fileName,
		       const char *file_name,
		       const struct cifs_unix_set_info_args *args,
		       const struct nls_table *nls_codepage, int remap)
{
@@ -5964,14 +5964,14 @@ setPermsRetry:

	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
		name_len =
		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
		    cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
				       PATH_MAX, nls_codepage, remap);
		name_len++;	/* trailing null */
		name_len *= 2;
	} else {	/* BB improve the check for buffer overruns BB */
		name_len = strnlen(fileName, PATH_MAX);
		name_len = strnlen(file_name, PATH_MAX);
		name_len++;	/* trailing null */
		strncpy(pSMB->FileName, fileName, name_len);
		strncpy(pSMB->FileName, file_name, name_len);
	}

	params = 6 + name_len;
+161 −134
Original line number Diff line number Diff line
@@ -1219,107 +1219,30 @@ unlink_out:
	return rc;
}

int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
static int
cifs_mkdir_qinfo(struct inode *inode, struct dentry *dentry, umode_t mode,
		 const char *full_path, struct cifs_sb_info *cifs_sb,
		 struct cifs_tcon *tcon, const unsigned int xid)
{
	int rc = 0, tmprc;
	unsigned int xid;
	struct cifs_sb_info *cifs_sb;
	struct tcon_link *tlink;
	struct cifs_tcon *tcon;
	char *full_path = NULL;
	int rc = 0;
	struct inode *newinode = NULL;
	struct cifs_fattr fattr;

	cFYI(1, "In cifs_mkdir, mode = 0x%hx inode = 0x%p", mode, inode);

	cifs_sb = CIFS_SB(inode->i_sb);
	tlink = cifs_sb_tlink(cifs_sb);
	if (IS_ERR(tlink))
		return PTR_ERR(tlink);
	tcon = tlink_tcon(tlink);

	xid = get_xid();

	full_path = build_path_from_dentry(direntry);
	if (full_path == NULL) {
		rc = -ENOMEM;
		goto mkdir_out;
	}

	if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
				le64_to_cpu(tcon->fsUnixInfo.Capability))) {
		u32 oplock = 0;
		FILE_UNIX_BASIC_INFO *pInfo =
			kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
		if (pInfo == NULL) {
			rc = -ENOMEM;
			goto mkdir_out;
		}

		mode &= ~current_umask();
		rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT,
				mode, NULL /* netfid */, pInfo, &oplock,
				full_path, cifs_sb->local_nls,
				cifs_sb->mnt_cifs_flags &
					CIFS_MOUNT_MAP_SPECIAL_CHR);
		if (rc == -EOPNOTSUPP) {
			kfree(pInfo);
			goto mkdir_retry_old;
		} else if (rc) {
			cFYI(1, "posix mkdir returned 0x%x", rc);
			d_drop(direntry);
		} else {
			if (pInfo->Type == cpu_to_le32(-1)) {
				/* no return info, go query for it */
				kfree(pInfo);
				goto mkdir_get_info;
			}
/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need
	to set uid/gid */

			cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb);
			cifs_fill_uniqueid(inode->i_sb, &fattr);
			newinode = cifs_iget(inode->i_sb, &fattr);
			if (!newinode) {
				kfree(pInfo);
				goto mkdir_get_info;
			}

			d_instantiate(direntry, newinode);

#ifdef CONFIG_CIFS_DEBUG2
			cFYI(1, "instantiated dentry %p %s to inode %p",
				direntry, direntry->d_name.name, newinode);

			if (newinode->i_nlink != 2)
				cFYI(1, "unexpected number of links %d",
					newinode->i_nlink);
#endif
		}
		kfree(pInfo);
		goto mkdir_out;
	}
mkdir_retry_old:
	/* BB add setting the equivalent of mode via CreateX w/ACLs */
	rc = CIFSSMBMkDir(xid, tcon, full_path, cifs_sb->local_nls,
			  cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
	if (rc) {
		cFYI(1, "cifs_mkdir returned 0x%x", rc);
		d_drop(direntry);
	} else {
mkdir_get_info:
	if (tcon->unix_ext)
			rc = cifs_get_inode_info_unix(&newinode, full_path,
						      inode->i_sb, xid);
		rc = cifs_get_inode_info_unix(&newinode, full_path, inode->i_sb,
					      xid);
	else
		rc = cifs_get_inode_info(&newinode, full_path, NULL,
					 inode->i_sb, xid, NULL);
	if (rc)
		return rc;

		d_instantiate(direntry, newinode);
		 /* setting nlink not necessary except in cases where we
		  * failed to get it from the server or was set bogus */
		if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
			set_nlink(direntry->d_inode, 2);
	d_instantiate(dentry, newinode);
	/*
	 * setting nlink not necessary except in cases where we failed to get it
	 * from the server or was set bogus
	 */
	if ((dentry->d_inode) && (dentry->d_inode->i_nlink < 2))
		set_nlink(dentry->d_inode, 2);

	mode &= ~current_umask();
	/* must turn on setgid bit if parent dir has it */
@@ -1351,42 +1274,146 @@ mkdir_get_info:
	} else {
		if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
		    (mode & S_IWUGO) == 0) {
				FILE_BASIC_INFO pInfo;
			FILE_BASIC_INFO info;
			struct cifsInodeInfo *cifsInode;
			u32 dosattrs;
			int tmprc;

				memset(&pInfo, 0, sizeof(pInfo));
			memset(&info, 0, sizeof(info));
			cifsInode = CIFS_I(newinode);
			dosattrs = cifsInode->cifsAttrs|ATTR_READONLY;
				pInfo.Attributes = cpu_to_le32(dosattrs);
				tmprc = CIFSSMBSetPathInfo(xid, tcon,
						full_path, &pInfo,
			info.Attributes = cpu_to_le32(dosattrs);
			tmprc = CIFSSMBSetPathInfo(xid, tcon, full_path, &info,
						   cifs_sb->local_nls,
						   cifs_sb->mnt_cifs_flags &
						   CIFS_MOUNT_MAP_SPECIAL_CHR);
			if (tmprc == 0)
				cifsInode->cifsAttrs = dosattrs;
		}
			if (direntry->d_inode) {
				if (cifs_sb->mnt_cifs_flags &
				     CIFS_MOUNT_DYNPERM)
					direntry->d_inode->i_mode =
						(mode | S_IFDIR);
		if (dentry->d_inode) {
			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
				dentry->d_inode->i_mode = (mode | S_IFDIR);

				if (cifs_sb->mnt_cifs_flags &
				     CIFS_MOUNT_SET_UID) {
					direntry->d_inode->i_uid =
						current_fsuid();
			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
				dentry->d_inode->i_uid = current_fsuid();
				if (inode->i_mode & S_ISGID)
						direntry->d_inode->i_gid =
							inode->i_gid;
					dentry->d_inode->i_gid = inode->i_gid;
				else
						direntry->d_inode->i_gid =
					dentry->d_inode->i_gid =
								current_fsgid();
			}
		}
	}
	return rc;
}

static int
cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
		 const char *full_path, struct cifs_sb_info *cifs_sb,
		 struct cifs_tcon *tcon, const unsigned int xid)
{
	int rc = 0;
	u32 oplock = 0;
	FILE_UNIX_BASIC_INFO *info = NULL;
	struct inode *newinode = NULL;
	struct cifs_fattr fattr;

	info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
	if (info == NULL) {
		rc = -ENOMEM;
		goto posix_mkdir_out;
	}

	mode &= ~current_umask();
	rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
			     NULL /* netfid */, info, &oplock, full_path,
			     cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
			     CIFS_MOUNT_MAP_SPECIAL_CHR);
	if (rc == -EOPNOTSUPP)
		goto posix_mkdir_out;
	else if (rc) {
		cFYI(1, "posix mkdir returned 0x%x", rc);
		d_drop(dentry);
		goto posix_mkdir_out;
	}

	if (info->Type == cpu_to_le32(-1))
		/* no return info, go query for it */
		goto posix_mkdir_get_info;
	/*
	 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
	 * need to set uid/gid.
	 */

	cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
	cifs_fill_uniqueid(inode->i_sb, &fattr);
	newinode = cifs_iget(inode->i_sb, &fattr);
	if (!newinode)
		goto posix_mkdir_get_info;

	d_instantiate(dentry, newinode);

#ifdef CONFIG_CIFS_DEBUG2
	cFYI(1, "instantiated dentry %p %s to inode %p", dentry,
	     dentry->d_name.name, newinode);

	if (newinode->i_nlink != 2)
		cFYI(1, "unexpected number of links %d", newinode->i_nlink);
#endif

posix_mkdir_out:
	kfree(info);
	return rc;
posix_mkdir_get_info:
	rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
			      xid);
	goto posix_mkdir_out;
}

int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
{
	int rc = 0;
	unsigned int xid;
	struct cifs_sb_info *cifs_sb;
	struct tcon_link *tlink;
	struct cifs_tcon *tcon;
	char *full_path;

	cFYI(1, "In cifs_mkdir, mode = 0x%hx inode = 0x%p", mode, inode);

	cifs_sb = CIFS_SB(inode->i_sb);
	tlink = cifs_sb_tlink(cifs_sb);
	if (IS_ERR(tlink))
		return PTR_ERR(tlink);
	tcon = tlink_tcon(tlink);

	xid = get_xid();

	full_path = build_path_from_dentry(direntry);
	if (full_path == NULL) {
		rc = -ENOMEM;
		goto mkdir_out;
	}

	if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
				le64_to_cpu(tcon->fsUnixInfo.Capability))) {
		rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
				      tcon, xid);
		if (rc != -EOPNOTSUPP)
			goto mkdir_out;
	}

	/* BB add setting the equivalent of mode via CreateX w/ACLs */
	rc = CIFSSMBMkDir(xid, tcon, full_path, cifs_sb->local_nls,
			  cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
	if (rc) {
		cFYI(1, "cifs_mkdir returned 0x%x", rc);
		d_drop(direntry);
		goto mkdir_out;
	}

	rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
			      xid);
mkdir_out:
	/*
	 * Force revalidate to get parent dir info when needed since cached