Loading fs/cifs/cifsproto.h +2 −2 Original line number Diff line number Diff line Loading @@ -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, Loading fs/cifs/cifssmb.c +4 −4 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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; Loading fs/cifs/inode.c +161 −134 Original line number Diff line number Diff line Loading @@ -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 */ Loading Loading @@ -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 Loading Loading
fs/cifs/cifsproto.h +2 −2 Original line number Diff line number Diff line Loading @@ -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, Loading
fs/cifs/cifssmb.c +4 −4 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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; Loading
fs/cifs/inode.c +161 −134 Original line number Diff line number Diff line Loading @@ -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 */ Loading Loading @@ -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 Loading