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

CIFS: Simplify cifs_mkdir call

Signed-off-by: default avatarPavel Shilovsky <piastry@etersoft.ru>
Signed-off-by: default avatarSteve French <smfrench@gmail.com>
parent b387e41e
...@@ -289,10 +289,10 @@ extern int CIFSSMBUnixSetFileInfo(const unsigned int xid, ...@@ -289,10 +289,10 @@ extern int CIFSSMBUnixSetFileInfo(const unsigned int xid,
u16 fid, u32 pid_of_opener); u16 fid, u32 pid_of_opener);
extern int CIFSSMBUnixSetPathInfo(const unsigned int xid, 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 cifs_unix_set_info_args *args,
const struct nls_table *nls_codepage, const struct nls_table *nls_codepage,
int remap_special_chars); int remap);
extern int CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, extern int CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon,
const char *newName, const char *newName,
......
...@@ -5943,7 +5943,7 @@ CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -5943,7 +5943,7 @@ CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
int int
CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon, 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 cifs_unix_set_info_args *args,
const struct nls_table *nls_codepage, int remap) const struct nls_table *nls_codepage, int remap)
{ {
...@@ -5964,14 +5964,14 @@ CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -5964,14 +5964,14 @@ CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len =
cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName, cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ } 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 */ name_len++; /* trailing null */
strncpy(pSMB->FileName, fileName, name_len); strncpy(pSMB->FileName, file_name, name_len);
} }
params = 6 + name_len; params = 6 + name_len;
......
...@@ -1219,107 +1219,30 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -1219,107 +1219,30 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
return rc; 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; int rc = 0;
unsigned int xid;
struct cifs_sb_info *cifs_sb;
struct tcon_link *tlink;
struct cifs_tcon *tcon;
char *full_path = NULL;
struct inode *newinode = NULL; 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) if (tcon->unix_ext)
rc = cifs_get_inode_info_unix(&newinode, full_path, rc = cifs_get_inode_info_unix(&newinode, full_path, inode->i_sb,
inode->i_sb, xid); xid);
else else
rc = cifs_get_inode_info(&newinode, full_path, NULL, rc = cifs_get_inode_info(&newinode, full_path, NULL,
inode->i_sb, xid, NULL); inode->i_sb, xid, NULL);
if (rc)
return rc;
d_instantiate(direntry, newinode); d_instantiate(dentry, newinode);
/* setting nlink not necessary except in cases where we /*
* failed to get it from the server or was set bogus */ * setting nlink not necessary except in cases where we failed to get it
if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2)) * from the server or was set bogus
set_nlink(direntry->d_inode, 2); */
if ((dentry->d_inode) && (dentry->d_inode->i_nlink < 2))
set_nlink(dentry->d_inode, 2);
mode &= ~current_umask(); mode &= ~current_umask();
/* must turn on setgid bit if parent dir has it */ /* must turn on setgid bit if parent dir has it */
...@@ -1351,42 +1274,146 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode) ...@@ -1351,42 +1274,146 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
} else { } else {
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
(mode & S_IWUGO) == 0) { (mode & S_IWUGO) == 0) {
FILE_BASIC_INFO pInfo; FILE_BASIC_INFO info;
struct cifsInodeInfo *cifsInode; struct cifsInodeInfo *cifsInode;
u32 dosattrs; u32 dosattrs;
int tmprc;
memset(&pInfo, 0, sizeof(pInfo)); memset(&info, 0, sizeof(info));
cifsInode = CIFS_I(newinode); cifsInode = CIFS_I(newinode);
dosattrs = cifsInode->cifsAttrs|ATTR_READONLY; dosattrs = cifsInode->cifsAttrs|ATTR_READONLY;
pInfo.Attributes = cpu_to_le32(dosattrs); info.Attributes = cpu_to_le32(dosattrs);
tmprc = CIFSSMBSetPathInfo(xid, tcon, tmprc = CIFSSMBSetPathInfo(xid, tcon, full_path, &info,
full_path, &pInfo,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if (tmprc == 0) if (tmprc == 0)
cifsInode->cifsAttrs = dosattrs; cifsInode->cifsAttrs = dosattrs;
} }
if (direntry->d_inode) { if (dentry->d_inode) {
if (cifs_sb->mnt_cifs_flags & if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
CIFS_MOUNT_DYNPERM) dentry->d_inode->i_mode = (mode | S_IFDIR);
direntry->d_inode->i_mode =
(mode | S_IFDIR);
if (cifs_sb->mnt_cifs_flags & if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
CIFS_MOUNT_SET_UID) { dentry->d_inode->i_uid = current_fsuid();
direntry->d_inode->i_uid =
current_fsuid();
if (inode->i_mode & S_ISGID) if (inode->i_mode & S_ISGID)
direntry->d_inode->i_gid = dentry->d_inode->i_gid = inode->i_gid;
inode->i_gid;
else else
direntry->d_inode->i_gid = dentry->d_inode->i_gid =
current_fsgid(); 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: mkdir_out:
/* /*
* Force revalidate to get parent dir info when needed since cached * Force revalidate to get parent dir info when needed since cached
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment