forked from Minki/linux
CIFS: Simplify cifs_mkdir call
Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru> Signed-off-by: Steve French <smfrench@gmail.com>
This commit is contained in:
parent
b387e41e52
commit
ff691e9694
@ -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,
|
||||
|
@ -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;
|
||||
|
295
fs/cifs/inode.c
295
fs/cifs/inode.c
@ -1219,16 +1219,165 @@ unlink_out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
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;
|
||||
struct inode *newinode = NULL;
|
||||
|
||||
if (tcon->unix_ext)
|
||||
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(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 */
|
||||
if (inode->i_mode & S_ISGID)
|
||||
mode |= S_ISGID;
|
||||
|
||||
if (tcon->unix_ext) {
|
||||
struct cifs_unix_set_info_args args = {
|
||||
.mode = mode,
|
||||
.ctime = NO_CHANGE_64,
|
||||
.atime = NO_CHANGE_64,
|
||||
.mtime = NO_CHANGE_64,
|
||||
.device = 0,
|
||||
};
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||
args.uid = (__u64)current_fsuid();
|
||||
if (inode->i_mode & S_ISGID)
|
||||
args.gid = (__u64)inode->i_gid;
|
||||
else
|
||||
args.gid = (__u64)current_fsgid();
|
||||
} else {
|
||||
args.uid = NO_CHANGE_64;
|
||||
args.gid = NO_CHANGE_64;
|
||||
}
|
||||
CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
} else {
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
|
||||
(mode & S_IWUGO) == 0) {
|
||||
FILE_BASIC_INFO info;
|
||||
struct cifsInodeInfo *cifsInode;
|
||||
u32 dosattrs;
|
||||
int tmprc;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
cifsInode = CIFS_I(newinode);
|
||||
dosattrs = cifsInode->cifsAttrs|ATTR_READONLY;
|
||||
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 (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) {
|
||||
dentry->d_inode->i_uid = current_fsuid();
|
||||
if (inode->i_mode & S_ISGID)
|
||||
dentry->d_inode->i_gid = inode->i_gid;
|
||||
else
|
||||
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, 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 cifs_fattr fattr;
|
||||
char *full_path;
|
||||
|
||||
cFYI(1, "In cifs_mkdir, mode = 0x%hx inode = 0x%p", mode, inode);
|
||||
|
||||
@ -1248,145 +1397,23 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
|
||||
|
||||
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;
|
||||
rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
|
||||
tcon, xid);
|
||||
if (rc != -EOPNOTSUPP)
|
||||
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);
|
||||
else
|
||||
rc = cifs_get_inode_info(&newinode, full_path, NULL,
|
||||
inode->i_sb, xid, NULL);
|
||||
|
||||
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);
|
||||
|
||||
mode &= ~current_umask();
|
||||
/* must turn on setgid bit if parent dir has it */
|
||||
if (inode->i_mode & S_ISGID)
|
||||
mode |= S_ISGID;
|
||||
|
||||
if (tcon->unix_ext) {
|
||||
struct cifs_unix_set_info_args args = {
|
||||
.mode = mode,
|
||||
.ctime = NO_CHANGE_64,
|
||||
.atime = NO_CHANGE_64,
|
||||
.mtime = NO_CHANGE_64,
|
||||
.device = 0,
|
||||
};
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||
args.uid = (__u64)current_fsuid();
|
||||
if (inode->i_mode & S_ISGID)
|
||||
args.gid = (__u64)inode->i_gid;
|
||||
else
|
||||
args.gid = (__u64)current_fsgid();
|
||||
} else {
|
||||
args.uid = NO_CHANGE_64;
|
||||
args.gid = NO_CHANGE_64;
|
||||
}
|
||||
CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
} else {
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
|
||||
(mode & S_IWUGO) == 0) {
|
||||
FILE_BASIC_INFO pInfo;
|
||||
struct cifsInodeInfo *cifsInode;
|
||||
u32 dosattrs;
|
||||
|
||||
memset(&pInfo, 0, sizeof(pInfo));
|
||||
cifsInode = CIFS_I(newinode);
|
||||
dosattrs = cifsInode->cifsAttrs|ATTR_READONLY;
|
||||
pInfo.Attributes = cpu_to_le32(dosattrs);
|
||||
tmprc = CIFSSMBSetPathInfo(xid, tcon,
|
||||
full_path, &pInfo,
|
||||
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 (cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_SET_UID) {
|
||||
direntry->d_inode->i_uid =
|
||||
current_fsuid();
|
||||
if (inode->i_mode & S_ISGID)
|
||||
direntry->d_inode->i_gid =
|
||||
inode->i_gid;
|
||||
else
|
||||
direntry->d_inode->i_gid =
|
||||
current_fsgid();
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user