History

Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6

Pull CIFS update from Steve French: "Adds SMB2 rmdir/mkdir capability to the SMB2/SMB2.1 support in cifs. I am holding up a few more days on merging the remainder of the SMB2/SMB2.1 enablement although it is nearing review completion, in order to address some review comments from Jeff Layton on a few of the subsequent SMB2 patches, and also to debug an unrelated cifs problem that Pavel discovered." * 'for-next' of git://git.samba.org/sfrench/cifs-2.6: CIFS: Add SMB2 support for rmdir CIFS: Move rmdir code to ops struct CIFS: Add SMB2 support for mkdir operation CIFS: Separate protocol specific part from mkdir CIFS: Simplify cifs_mkdir call

Linus Torvalds committed 14 years ago

Commit 630103e2 parents 8783b6e 1a500f08 files · +270 −158Browse files

Unified · Split

8 files
  1. fs/cifs/cifsglob.h +10 −0
  2. fs/cifs/cifsproto.h +4 −7
  3. fs/cifs/cifssmb.c +17 −14
  4. fs/cifs/inode.c +165 −137
  5. fs/cifs/smb1ops.c +24 −0
  6. fs/cifs/smb2inode.c +39 −0
  7. fs/cifs/smb2ops.c +3 −0
  8. fs/cifs/smb2proto.h +8 −0
fs/cifs/cifsglob.h+10−0
@@ -246,6 +246,16 @@ struct smb_version_operations { · 245 unmodified lines
246246 bool (*can_echo)(struct TCP_Server_Info *);
247247 /* send echo request */
248248 int (*echo)(struct TCP_Server_Info *);
249+ /* create directory */
250+ int (*mkdir)(const unsigned int, struct cifs_tcon *, const char *,
251+ struct cifs_sb_info *);
252+ /* set info on created directory */
253+ void (*mkdir_setinfo)(struct inode *, const char *,
254+ struct cifs_sb_info *, struct cifs_tcon *,
255+ const unsigned int);
256+ /* remove directory */
257+ int (*rmdir)(const unsigned int, struct cifs_tcon *, const char *,
258+ struct cifs_sb_info *);
249259 };
250260
251261 struct smb_version_values {
fs/cifs/cifsproto.h+4−7
@@ -289,18 +289,15 @@ extern int CIFSSMBUnixSetFileInfo(const unsigned int xid, · 288 unmodified lines
289289 u16 fid, u32 pid_of_opener);
290290
291291 extern int CIFSSMBUnixSetPathInfo(const unsigned int xid,
292− struct cifs_tcon *tcon, char *file_name,
292+ struct cifs_tcon *tcon, const char *file_name,
293293 const struct cifs_unix_set_info_args *args,
294294 const struct nls_table *nls_codepage,
295− int remap_special_chars);
295+ int remap);
296296
297297 extern int CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon,
298− const char *newName,
299− const struct nls_table *nls_codepage,
300− int remap_special_chars);
298+ const char *name, struct cifs_sb_info *cifs_sb);
301299 extern int CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon,
302− const char *name, const struct nls_table *nls_codepage,
303− int remap_special_chars);
300+ const char *name, struct cifs_sb_info *cifs_sb);
304301 extern int CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
305302 const char *name, __u16 type,
306303 const struct nls_table *nls_codepage,
fs/cifs/cifssmb.c+17−14
@@ -948,15 +948,15 @@ DelFileRetry: · 947 unmodified lines
948948 }
949949
950950 int
951−CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon,
952− const char *dirName, const struct nls_table *nls_codepage,
953− int remap)
951+CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
952+ struct cifs_sb_info *cifs_sb)
954953 {
955954 DELETE_DIRECTORY_REQ *pSMB = NULL;
956955 DELETE_DIRECTORY_RSP *pSMBr = NULL;
957956 int rc = 0;
958957 int bytes_returned;
959958 int name_len;
959+ int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
960960
961961 cFYI(1, "In CIFSSMBRmDir");
962962 RmDirRetry:
@@ -966,14 +966,15 @@ RmDirRetry: · 3 unmodified lines
966966 return rc;
967967
968968 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
969− name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, dirName,
970− PATH_MAX, nls_codepage, remap);
969+ name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
970+ PATH_MAX, cifs_sb->local_nls,
971+ remap);
971972 name_len++; /* trailing null */
972973 name_len *= 2;
973974 } else { /* BB improve check for buffer overruns BB */
974− name_len = strnlen(dirName, PATH_MAX);
975+ name_len = strnlen(name, PATH_MAX);
975976 name_len++; /* trailing null */
976− strncpy(pSMB->DirName, dirName, name_len);
977+ strncpy(pSMB->DirName, name, name_len);
977978 }
978979
979980 pSMB->BufferFormat = 0x04;
@@ -992,14 +993,15 @@ RmDirRetry: · 12 unmodified lines
992993 }
993994
994995 int
995−CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon,
996− const char *name, const struct nls_table *nls_codepage, int remap)
996+CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
997+ struct cifs_sb_info *cifs_sb)
997998 {
998999 int rc = 0;
9991000 CREATE_DIRECTORY_REQ *pSMB = NULL;
10001001 CREATE_DIRECTORY_RSP *pSMBr = NULL;
10011002 int bytes_returned;
10021003 int name_len;
1004+ int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
10031005
10041006 cFYI(1, "In CIFSSMBMkDir");
10051007 MkDirRetry:
@@ -1010,7 +1012,8 @@ MkDirRetry: · 4 unmodified lines
10101012
10111013 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
10121014 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
1013− PATH_MAX, nls_codepage, remap);
1015+ PATH_MAX, cifs_sb->local_nls,
1016+ remap);
10141017 name_len++; /* trailing null */
10151018 name_len *= 2;
10161019 } else { /* BB improve check for buffer overruns BB */
@@ -5943,7 +5946,7 @@ CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon, · 4926 unmodified lines
59435946
59445947 int
59455948 CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5946− char *fileName,
5949+ const char *file_name,
59475950 const struct cifs_unix_set_info_args *args,
59485951 const struct nls_table *nls_codepage, int remap)
59495952 {
@@ -5964,14 +5967,14 @@ setPermsRetry: · 14 unmodified lines
59645967
59655968 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
59665969 name_len =
5967− cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5970+ cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
59685971 PATH_MAX, nls_codepage, remap);
59695972 name_len++; /* trailing null */
59705973 name_len *= 2;
59715974 } else { /* BB improve the check for buffer overruns BB */
5972− name_len = strnlen(fileName, PATH_MAX);
5975+ name_len = strnlen(file_name, PATH_MAX);
59735976 name_len++; /* trailing null */
5974− strncpy(pSMB->FileName, fileName, name_len);
5977+ strncpy(pSMB->FileName, file_name, name_len);
59755978 }
59765979
59775980 params = 6 + name_len;
fs/cifs/inode.c+165−137
@@ -1219,16 +1219,153 @@ unlink_out: · 1218 unmodified lines
12191219 return rc;
12201220 }
12211221
1222+static int
1223+cifs_mkdir_qinfo(struct inode *inode, struct dentry *dentry, umode_t mode,
1224+ const char *full_path, struct cifs_sb_info *cifs_sb,
1225+ struct cifs_tcon *tcon, const unsigned int xid)
1226+{
1227+ int rc = 0;
1228+ struct inode *newinode = NULL;
1229+
1230+ if (tcon->unix_ext)
1231+ rc = cifs_get_inode_info_unix(&newinode, full_path, inode->i_sb,
1232+ xid);
1233+ else
1234+ rc = cifs_get_inode_info(&newinode, full_path, NULL,
1235+ inode->i_sb, xid, NULL);
1236+ if (rc)
1237+ return rc;
1238+
1239+ d_instantiate(dentry, newinode);
1240+ /*
1241+ * setting nlink not necessary except in cases where we failed to get it
1242+ * from the server or was set bogus
1243+ */
1244+ if ((dentry->d_inode) && (dentry->d_inode->i_nlink < 2))
1245+ set_nlink(dentry->d_inode, 2);
1246+
1247+ mode &= ~current_umask();
1248+ /* must turn on setgid bit if parent dir has it */
1249+ if (inode->i_mode & S_ISGID)
1250+ mode |= S_ISGID;
1251+
1252+ if (tcon->unix_ext) {
1253+ struct cifs_unix_set_info_args args = {
1254+ .mode = mode,
1255+ .ctime = NO_CHANGE_64,
1256+ .atime = NO_CHANGE_64,
1257+ .mtime = NO_CHANGE_64,
1258+ .device = 0,
1259+ };
1260+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1261+ args.uid = (__u64)current_fsuid();
1262+ if (inode->i_mode & S_ISGID)
1263+ args.gid = (__u64)inode->i_gid;
1264+ else
1265+ args.gid = (__u64)current_fsgid();
1266+ } else {
1267+ args.uid = NO_CHANGE_64;
1268+ args.gid = NO_CHANGE_64;
1269+ }
1270+ CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1271+ cifs_sb->local_nls,
1272+ cifs_sb->mnt_cifs_flags &
1273+ CIFS_MOUNT_MAP_SPECIAL_CHR);
1274+ } else {
1275+ struct TCP_Server_Info *server = tcon->ses->server;
1276+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
1277+ (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
1278+ server->ops->mkdir_setinfo(newinode, full_path, cifs_sb,
1279+ tcon, xid);
1280+ if (dentry->d_inode) {
1281+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
1282+ dentry->d_inode->i_mode = (mode | S_IFDIR);
1283+
1284+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1285+ dentry->d_inode->i_uid = current_fsuid();
1286+ if (inode->i_mode & S_ISGID)
1287+ dentry->d_inode->i_gid = inode->i_gid;
1288+ else
1289+ dentry->d_inode->i_gid =
1290+ current_fsgid();
1291+ }
1292+ }
1293+ }
1294+ return rc;
1295+}
1296+
1297+static int
1298+cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
1299+ const char *full_path, struct cifs_sb_info *cifs_sb,
1300+ struct cifs_tcon *tcon, const unsigned int xid)
1301+{
1302+ int rc = 0;
1303+ u32 oplock = 0;
1304+ FILE_UNIX_BASIC_INFO *info = NULL;
1305+ struct inode *newinode = NULL;
1306+ struct cifs_fattr fattr;
1307+
1308+ info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1309+ if (info == NULL) {
1310+ rc = -ENOMEM;
1311+ goto posix_mkdir_out;
1312+ }
1313+
1314+ mode &= ~current_umask();
1315+ rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
1316+ NULL /* netfid */, info, &oplock, full_path,
1317+ cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1318+ CIFS_MOUNT_MAP_SPECIAL_CHR);
1319+ if (rc == -EOPNOTSUPP)
1320+ goto posix_mkdir_out;
1321+ else if (rc) {
1322+ cFYI(1, "posix mkdir returned 0x%x", rc);
1323+ d_drop(dentry);
1324+ goto posix_mkdir_out;
1325+ }
1326+
1327+ if (info->Type == cpu_to_le32(-1))
1328+ /* no return info, go query for it */
1329+ goto posix_mkdir_get_info;
1330+ /*
1331+ * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
1332+ * need to set uid/gid.
1333+ */
1334+
1335+ cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
1336+ cifs_fill_uniqueid(inode->i_sb, &fattr);
1337+ newinode = cifs_iget(inode->i_sb, &fattr);
1338+ if (!newinode)
1339+ goto posix_mkdir_get_info;
1340+
1341+ d_instantiate(dentry, newinode);
1342+
1343+#ifdef CONFIG_CIFS_DEBUG2
1344+ cFYI(1, "instantiated dentry %p %s to inode %p", dentry,
1345+ dentry->d_name.name, newinode);
1346+
1347+ if (newinode->i_nlink != 2)
1348+ cFYI(1, "unexpected number of links %d", newinode->i_nlink);
1349+#endif
1350+
1351+posix_mkdir_out:
1352+ kfree(info);
1353+ return rc;
1354+posix_mkdir_get_info:
1355+ rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
1356+ xid);
1357+ goto posix_mkdir_out;
1358+}
1359+
12221360 int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
12231361 {
1224− int rc = 0, tmprc;
1362+ int rc = 0;
12251363 unsigned int xid;
12261364 struct cifs_sb_info *cifs_sb;
12271365 struct tcon_link *tlink;
12281366 struct cifs_tcon *tcon;
1229− char *full_path = NULL;
1230− struct inode *newinode = NULL;
1231− struct cifs_fattr fattr;
1367+ struct TCP_Server_Info *server;
1368+ char *full_path;
12321369
12331370 cFYI(1, "In cifs_mkdir, mode = 0x%hx inode = 0x%p", mode, inode);
12341371
@@ -1248,145 +1385,29 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode) · 13 unmodified lines
12481385
12491386 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
12501387 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
1251− u32 oplock = 0;
1252− FILE_UNIX_BASIC_INFO *pInfo =
1253− kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1254− if (pInfo == NULL) {
1255− rc = -ENOMEM;
1388+ rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
1389+ tcon, xid);
1390+ if (rc != -EOPNOTSUPP)
12561391 goto mkdir_out;
1257− }
1258−
1259− mode &= ~current_umask();
1260− rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT,
1261− mode, NULL /* netfid */, pInfo, &oplock,
1262− full_path, cifs_sb->local_nls,
1263− cifs_sb->mnt_cifs_flags &
1264− CIFS_MOUNT_MAP_SPECIAL_CHR);
1265− if (rc == -EOPNOTSUPP) {
1266− kfree(pInfo);
1267− goto mkdir_retry_old;
1268− } else if (rc) {
1269− cFYI(1, "posix mkdir returned 0x%x", rc);
1270− d_drop(direntry);
1271− } else {
1272− if (pInfo->Type == cpu_to_le32(-1)) {
1273− /* no return info, go query for it */
1274− kfree(pInfo);
1275− goto mkdir_get_info;
1276− }
1277−/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need
1278− to set uid/gid */
1279−
1280− cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb);
1281− cifs_fill_uniqueid(inode->i_sb, &fattr);
1282− newinode = cifs_iget(inode->i_sb, &fattr);
1283− if (!newinode) {
1284− kfree(pInfo);
1285− goto mkdir_get_info;
1286− }
1287−
1288− d_instantiate(direntry, newinode);
1392+ }
12891393
1290−#ifdef CONFIG_CIFS_DEBUG2
1291− cFYI(1, "instantiated dentry %p %s to inode %p",
1292− direntry, direntry->d_name.name, newinode);
1394+ server = tcon->ses->server;
12931395
1294− if (newinode->i_nlink != 2)
1295− cFYI(1, "unexpected number of links %d",
1296− newinode->i_nlink);
1297−#endif
1298− }
1299− kfree(pInfo);
1396+ if (!server->ops->mkdir) {
1397+ rc = -ENOSYS;
13001398 goto mkdir_out;
13011399 }
1302−mkdir_retry_old:
1400+
13031401 /* BB add setting the equivalent of mode via CreateX w/ACLs */
1304− rc = CIFSSMBMkDir(xid, tcon, full_path, cifs_sb->local_nls,
1305− cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1402+ rc = server->ops->mkdir(xid, tcon, full_path, cifs_sb);
13061403 if (rc) {
13071404 cFYI(1, "cifs_mkdir returned 0x%x", rc);
13081405 d_drop(direntry);
1309− } else {
1310−mkdir_get_info:
1311− if (tcon->unix_ext)
1312− rc = cifs_get_inode_info_unix(&newinode, full_path,
1313− inode->i_sb, xid);
1314− else
1315− rc = cifs_get_inode_info(&newinode, full_path, NULL,
1316− inode->i_sb, xid, NULL);
1317−
1318− d_instantiate(direntry, newinode);
1319− /* setting nlink not necessary except in cases where we
1320− * failed to get it from the server or was set bogus */
1321− if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
1322− set_nlink(direntry->d_inode, 2);
1323−
1324− mode &= ~current_umask();
1325− /* must turn on setgid bit if parent dir has it */
1326− if (inode->i_mode & S_ISGID)
1327− mode |= S_ISGID;
1328−
1329− if (tcon->unix_ext) {
1330− struct cifs_unix_set_info_args args = {
1331− .mode = mode,
1332− .ctime = NO_CHANGE_64,
1333− .atime = NO_CHANGE_64,
1334− .mtime = NO_CHANGE_64,
1335− .device = 0,
1336− };
1337− if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1338− args.uid = (__u64)current_fsuid();
1339− if (inode->i_mode & S_ISGID)
1340− args.gid = (__u64)inode->i_gid;
1341− else
1342− args.gid = (__u64)current_fsgid();
1343− } else {
1344− args.uid = NO_CHANGE_64;
1345− args.gid = NO_CHANGE_64;
1346− }
1347− CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1348− cifs_sb->local_nls,
1349− cifs_sb->mnt_cifs_flags &
1350− CIFS_MOUNT_MAP_SPECIAL_CHR);
1351− } else {
1352− if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
1353− (mode & S_IWUGO) == 0) {
1354− FILE_BASIC_INFO pInfo;
1355− struct cifsInodeInfo *cifsInode;
1356− u32 dosattrs;
1357−
1358− memset(&pInfo, 0, sizeof(pInfo));
1359− cifsInode = CIFS_I(newinode);
1360− dosattrs = cifsInode->cifsAttrs|ATTR_READONLY;
1361− pInfo.Attributes = cpu_to_le32(dosattrs);
1362− tmprc = CIFSSMBSetPathInfo(xid, tcon,
1363− full_path, &pInfo,
1364− cifs_sb->local_nls,
1365− cifs_sb->mnt_cifs_flags &
1366− CIFS_MOUNT_MAP_SPECIAL_CHR);
1367− if (tmprc == 0)
1368− cifsInode->cifsAttrs = dosattrs;
1369− }
1370− if (direntry->d_inode) {
1371− if (cifs_sb->mnt_cifs_flags &
1372− CIFS_MOUNT_DYNPERM)
1373− direntry->d_inode->i_mode =
1374− (mode | S_IFDIR);
1375−
1376− if (cifs_sb->mnt_cifs_flags &
1377− CIFS_MOUNT_SET_UID) {
1378− direntry->d_inode->i_uid =
1379− current_fsuid();
1380− if (inode->i_mode & S_ISGID)
1381− direntry->d_inode->i_gid =
1382− inode->i_gid;
1383− else
1384− direntry->d_inode->i_gid =
1385− current_fsgid();
1386− }
1387− }
1388− }
1406+ goto mkdir_out;
13891407 }
1408+
1409+ rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
1410+ xid);
13901411 mkdir_out:
13911412 /*
13921413 * Force revalidate to get parent dir info when needed since cached
@@ -1405,7 +1426,8 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) · 12 unmodified lines
14051426 unsigned int xid;
14061427 struct cifs_sb_info *cifs_sb;
14071428 struct tcon_link *tlink;
1408− struct cifs_tcon *pTcon;
1429+ struct cifs_tcon *tcon;
1430+ struct TCP_Server_Info *server;
14091431 char *full_path = NULL;
14101432 struct cifsInodeInfo *cifsInode;
14111433
@@ -1425,10 +1447,16 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) · 13 unmodified lines
14251447 rc = PTR_ERR(tlink);
14261448 goto rmdir_exit;
14271449 }
1428− pTcon = tlink_tcon(tlink);
1450+ tcon = tlink_tcon(tlink);
1451+ server = tcon->ses->server;
1452+
1453+ if (!server->ops->rmdir) {
1454+ rc = -ENOSYS;
1455+ cifs_put_tlink(tlink);
1456+ goto rmdir_exit;
1457+ }
14291458
1430− rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
1431− cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1459+ rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
14321460 cifs_put_tlink(tlink);
14331461
14341462 if (!rc) {
fs/cifs/smb1ops.c+24−0
@@ -586,6 +586,27 @@ cifs_print_stats(struct seq_file *m, struct cifs_tcon *tcon) · 585 unmodified lines
586586 #endif
587587 }
588588
589+static void
590+cifs_mkdir_setinfo(struct inode *inode, const char *full_path,
591+ struct cifs_sb_info *cifs_sb, struct cifs_tcon *tcon,
592+ const unsigned int xid)
593+{
594+ FILE_BASIC_INFO info;
595+ struct cifsInodeInfo *cifsInode;
596+ u32 dosattrs;
597+ int rc;
598+
599+ memset(&info, 0, sizeof(info));
600+ cifsInode = CIFS_I(inode);
601+ dosattrs = cifsInode->cifsAttrs|ATTR_READONLY;
602+ info.Attributes = cpu_to_le32(dosattrs);
603+ rc = CIFSSMBSetPathInfo(xid, tcon, full_path, &info, cifs_sb->local_nls,
604+ cifs_sb->mnt_cifs_flags &
605+ CIFS_MOUNT_MAP_SPECIAL_CHR);
606+ if (rc == 0)
607+ cifsInode->cifsAttrs = dosattrs;
608+}
609+
589610 struct smb_version_operations smb1_operations = {
590611 .send_cancel = send_nt_cancel,
591612 .compare_fids = cifs_compare_fids,
@@ -620,6 +641,9 @@ struct smb_version_operations smb1_operations = { · 28 unmodified lines
620641 .get_srv_inum = cifs_get_srv_inum,
621642 .build_path_to_root = cifs_build_path_to_root,
622643 .echo = CIFSSMBEcho,
644+ .mkdir = CIFSSMBMkDir,
645+ .mkdir_setinfo = cifs_mkdir_setinfo,
646+ .rmdir = CIFSSMBRmDir,
623647 };
624648
625649 struct smb_version_values smb1_values = {
fs/cifs/smb2inode.c+39−0
@@ -122,3 +122,42 @@ out: · 121 unmodified lines
122122 kfree(smb2_data);
123123 return rc;
124124 }
125+
126+int
127+smb2_mkdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
128+ struct cifs_sb_info *cifs_sb)
129+{
130+ return smb2_open_op_close(xid, tcon, cifs_sb, name,
131+ FILE_WRITE_ATTRIBUTES, FILE_CREATE, 0,
132+ CREATE_NOT_FILE, NULL, SMB2_OP_MKDIR);
133+}
134+
135+void
136+smb2_mkdir_setinfo(struct inode *inode, const char *name,
137+ struct cifs_sb_info *cifs_sb, struct cifs_tcon *tcon,
138+ const unsigned int xid)
139+{
140+ FILE_BASIC_INFO data;
141+ struct cifsInodeInfo *cifs_i;
142+ u32 dosattrs;
143+ int tmprc;
144+
145+ memset(&data, 0, sizeof(data));
146+ cifs_i = CIFS_I(inode);
147+ dosattrs = cifs_i->cifsAttrs | ATTR_READONLY;
148+ data.Attributes = cpu_to_le32(dosattrs);
149+ tmprc = smb2_open_op_close(xid, tcon, cifs_sb, name,
150+ FILE_WRITE_ATTRIBUTES, FILE_CREATE, 0,
151+ CREATE_NOT_FILE, &data, SMB2_OP_SET_INFO);
152+ if (tmprc == 0)
153+ cifs_i->cifsAttrs = dosattrs;
154+}
155+
156+int
157+smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
158+ struct cifs_sb_info *cifs_sb)
159+{
160+ return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
161+ 0, CREATE_NOT_FILE | CREATE_DELETE_ON_CLOSE,
162+ NULL, SMB2_OP_DELETE);
163+}
fs/cifs/smb2ops.c+3−0
@@ -318,6 +318,9 @@ struct smb_version_operations smb21_operations = { · 317 unmodified lines
318318 .query_path_info = smb2_query_path_info,
319319 .get_srv_inum = smb2_get_srv_inum,
320320 .build_path_to_root = smb2_build_path_to_root,
321+ .mkdir = smb2_mkdir,
322+ .mkdir_setinfo = smb2_mkdir_setinfo,
323+ .rmdir = smb2_rmdir,
321324 };
322325
323326 struct smb_version_values smb21_values = {
fs/cifs/smb2proto.h+8−0
@@ -52,6 +52,14 @@ extern int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, · 51 unmodified lines
5252 struct cifs_sb_info *cifs_sb,
5353 const char *full_path, FILE_ALL_INFO *data,
5454 bool *adjust_tz);
55+extern int smb2_mkdir(const unsigned int xid, struct cifs_tcon *tcon,
56+ const char *name, struct cifs_sb_info *cifs_sb);
57+extern void smb2_mkdir_setinfo(struct inode *inode, const char *full_path,
58+ struct cifs_sb_info *cifs_sb,
59+ struct cifs_tcon *tcon, const unsigned int xid);
60+extern int smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon,
61+ const char *name, struct cifs_sb_info *cifs_sb);
62+
5563 /*
5664 * SMB2 Worker functions - most of protocol specific implementation details
5765 * are contained within these calls.