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
Unified · Split
| @@ -246,6 +246,16 @@ struct smb_version_operations { · 245 unmodified lines | ||
| 246 | 246 | bool (*can_echo)(struct TCP_Server_Info *); |
| 247 | 247 | /* send echo request */ |
| 248 | 248 | 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 *); | |
| 249 | 259 | }; |
| 250 | 260 | |
| 251 | 261 | struct smb_version_values { |
| @@ -289,18 +289,15 @@ extern int CIFSSMBUnixSetFileInfo(const unsigned int xid, · 288 unmodified lines | ||
| 289 | 289 | u16 fid, u32 pid_of_opener); |
| 290 | 290 | |
| 291 | 291 | extern int CIFSSMBUnixSetPathInfo(const unsigned int xid, |
| 292 | − struct cifs_tcon *tcon, char *file_name, | |
| 292 | + struct cifs_tcon *tcon, const char *file_name, | |
| 293 | 293 | const struct cifs_unix_set_info_args *args, |
| 294 | 294 | const struct nls_table *nls_codepage, |
| 295 | − int remap_special_chars); | |
| 295 | + int remap); | |
| 296 | 296 | |
| 297 | 297 | 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); | |
| 301 | 299 | 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); | |
| 304 | 301 | extern int CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon, |
| 305 | 302 | const char *name, __u16 type, |
| 306 | 303 | const struct nls_table *nls_codepage, |
| @@ -948,15 +948,15 @@ DelFileRetry: · 947 unmodified lines | ||
| 948 | 948 | } |
| 949 | 949 | |
| 950 | 950 | 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) | |
| 954 | 953 | { |
| 955 | 954 | DELETE_DIRECTORY_REQ *pSMB = NULL; |
| 956 | 955 | DELETE_DIRECTORY_RSP *pSMBr = NULL; |
| 957 | 956 | int rc = 0; |
| 958 | 957 | int bytes_returned; |
| 959 | 958 | int name_len; |
| 959 | + int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; | |
| 960 | 960 | |
| 961 | 961 | cFYI(1, "In CIFSSMBRmDir"); |
| 962 | 962 | RmDirRetry: |
| @@ -966,14 +966,15 @@ RmDirRetry: · 3 unmodified lines | ||
| 966 | 966 | return rc; |
| 967 | 967 | |
| 968 | 968 | 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); | |
| 971 | 972 | name_len++; /* trailing null */ |
| 972 | 973 | name_len *= 2; |
| 973 | 974 | } else { /* BB improve check for buffer overruns BB */ |
| 974 | − name_len = strnlen(dirName, PATH_MAX); | |
| 975 | + name_len = strnlen(name, PATH_MAX); | |
| 975 | 976 | name_len++; /* trailing null */ |
| 976 | − strncpy(pSMB->DirName, dirName, name_len); | |
| 977 | + strncpy(pSMB->DirName, name, name_len); | |
| 977 | 978 | } |
| 978 | 979 | |
| 979 | 980 | pSMB->BufferFormat = 0x04; |
| @@ -992,14 +993,15 @@ RmDirRetry: · 12 unmodified lines | ||
| 992 | 993 | } |
| 993 | 994 | |
| 994 | 995 | 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) | |
| 997 | 998 | { |
| 998 | 999 | int rc = 0; |
| 999 | 1000 | CREATE_DIRECTORY_REQ *pSMB = NULL; |
| 1000 | 1001 | CREATE_DIRECTORY_RSP *pSMBr = NULL; |
| 1001 | 1002 | int bytes_returned; |
| 1002 | 1003 | int name_len; |
| 1004 | + int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; | |
| 1003 | 1005 | |
| 1004 | 1006 | cFYI(1, "In CIFSSMBMkDir"); |
| 1005 | 1007 | MkDirRetry: |
| @@ -1010,7 +1012,8 @@ MkDirRetry: · 4 unmodified lines | ||
| 1010 | 1012 | |
| 1011 | 1013 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
| 1012 | 1014 | name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name, |
| 1013 | − PATH_MAX, nls_codepage, remap); | |
| 1015 | + PATH_MAX, cifs_sb->local_nls, | |
| 1016 | + remap); | |
| 1014 | 1017 | name_len++; /* trailing null */ |
| 1015 | 1018 | name_len *= 2; |
| 1016 | 1019 | } else { /* BB improve check for buffer overruns BB */ |
| @@ -5943,7 +5946,7 @@ CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon, · 4926 unmodified lines | ||
| 5943 | 5946 | |
| 5944 | 5947 | int |
| 5945 | 5948 | CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon, |
| 5946 | − char *fileName, | |
| 5949 | + const char *file_name, | |
| 5947 | 5950 | const struct cifs_unix_set_info_args *args, |
| 5948 | 5951 | const struct nls_table *nls_codepage, int remap) |
| 5949 | 5952 | { |
| @@ -5964,14 +5967,14 @@ setPermsRetry: · 14 unmodified lines | ||
| 5964 | 5967 | |
| 5965 | 5968 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
| 5966 | 5969 | name_len = |
| 5967 | − cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName, | |
| 5970 | + cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name, | |
| 5968 | 5971 | PATH_MAX, nls_codepage, remap); |
| 5969 | 5972 | name_len++; /* trailing null */ |
| 5970 | 5973 | name_len *= 2; |
| 5971 | 5974 | } else { /* BB improve the check for buffer overruns BB */ |
| 5972 | − name_len = strnlen(fileName, PATH_MAX); | |
| 5975 | + name_len = strnlen(file_name, PATH_MAX); | |
| 5973 | 5976 | name_len++; /* trailing null */ |
| 5974 | − strncpy(pSMB->FileName, fileName, name_len); | |
| 5977 | + strncpy(pSMB->FileName, file_name, name_len); | |
| 5975 | 5978 | } |
| 5976 | 5979 | |
| 5977 | 5980 | params = 6 + name_len; |
| @@ -1219,16 +1219,153 @@ unlink_out: · 1218 unmodified lines | ||
| 1219 | 1219 | return rc; |
| 1220 | 1220 | } |
| 1221 | 1221 | |
| 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 | + | |
| 1222 | 1360 | int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode) |
| 1223 | 1361 | { |
| 1224 | − int rc = 0, tmprc; | |
| 1362 | + int rc = 0; | |
| 1225 | 1363 | unsigned int xid; |
| 1226 | 1364 | struct cifs_sb_info *cifs_sb; |
| 1227 | 1365 | struct tcon_link *tlink; |
| 1228 | 1366 | 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; | |
| 1232 | 1369 | |
| 1233 | 1370 | cFYI(1, "In cifs_mkdir, mode = 0x%hx inode = 0x%p", mode, inode); |
| 1234 | 1371 | |
| @@ -1248,145 +1385,29 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode) · 13 unmodified lines | ||
| 1248 | 1385 | |
| 1249 | 1386 | if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP & |
| 1250 | 1387 | 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) | |
| 1256 | 1391 | 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 | + } | |
| 1289 | 1393 | |
| 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; | |
| 1293 | 1395 | |
| 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; | |
| 1300 | 1398 | goto mkdir_out; |
| 1301 | 1399 | } |
| 1302 | −mkdir_retry_old: | |
| 1400 | + | |
| 1303 | 1401 | /* 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); | |
| 1306 | 1403 | if (rc) { |
| 1307 | 1404 | cFYI(1, "cifs_mkdir returned 0x%x", rc); |
| 1308 | 1405 | 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; | |
| 1389 | 1407 | } |
| 1408 | + | |
| 1409 | + rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon, | |
| 1410 | + xid); | |
| 1390 | 1411 | mkdir_out: |
| 1391 | 1412 | /* |
| 1392 | 1413 | * 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 | ||
| 1405 | 1426 | unsigned int xid; |
| 1406 | 1427 | struct cifs_sb_info *cifs_sb; |
| 1407 | 1428 | struct tcon_link *tlink; |
| 1408 | − struct cifs_tcon *pTcon; | |
| 1429 | + struct cifs_tcon *tcon; | |
| 1430 | + struct TCP_Server_Info *server; | |
| 1409 | 1431 | char *full_path = NULL; |
| 1410 | 1432 | struct cifsInodeInfo *cifsInode; |
| 1411 | 1433 | |
| @@ -1425,10 +1447,16 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) · 13 unmodified lines | ||
| 1425 | 1447 | rc = PTR_ERR(tlink); |
| 1426 | 1448 | goto rmdir_exit; |
| 1427 | 1449 | } |
| 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 | + } | |
| 1429 | 1458 | |
| 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); | |
| 1432 | 1460 | cifs_put_tlink(tlink); |
| 1433 | 1461 | |
| 1434 | 1462 | if (!rc) { |
| @@ -586,6 +586,27 @@ cifs_print_stats(struct seq_file *m, struct cifs_tcon *tcon) · 585 unmodified lines | ||
| 586 | 586 | #endif |
| 587 | 587 | } |
| 588 | 588 | |
| 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 | + | |
| 589 | 610 | struct smb_version_operations smb1_operations = { |
| 590 | 611 | .send_cancel = send_nt_cancel, |
| 591 | 612 | .compare_fids = cifs_compare_fids, |
| @@ -620,6 +641,9 @@ struct smb_version_operations smb1_operations = { · 28 unmodified lines | ||
| 620 | 641 | .get_srv_inum = cifs_get_srv_inum, |
| 621 | 642 | .build_path_to_root = cifs_build_path_to_root, |
| 622 | 643 | .echo = CIFSSMBEcho, |
| 644 | + .mkdir = CIFSSMBMkDir, | |
| 645 | + .mkdir_setinfo = cifs_mkdir_setinfo, | |
| 646 | + .rmdir = CIFSSMBRmDir, | |
| 623 | 647 | }; |
| 624 | 648 | |
| 625 | 649 | struct smb_version_values smb1_values = { |
| @@ -122,3 +122,42 @@ out: · 121 unmodified lines | ||
| 122 | 122 | kfree(smb2_data); |
| 123 | 123 | return rc; |
| 124 | 124 | } |
| 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 | +} | |
| @@ -318,6 +318,9 @@ struct smb_version_operations smb21_operations = { · 317 unmodified lines | ||
| 318 | 318 | .query_path_info = smb2_query_path_info, |
| 319 | 319 | .get_srv_inum = smb2_get_srv_inum, |
| 320 | 320 | .build_path_to_root = smb2_build_path_to_root, |
| 321 | + .mkdir = smb2_mkdir, | |
| 322 | + .mkdir_setinfo = smb2_mkdir_setinfo, | |
| 323 | + .rmdir = smb2_rmdir, | |
| 321 | 324 | }; |
| 322 | 325 | |
| 323 | 326 | struct smb_version_values smb21_values = { |
| @@ -52,6 +52,14 @@ extern int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, · 51 unmodified lines | ||
| 52 | 52 | struct cifs_sb_info *cifs_sb, |
| 53 | 53 | const char *full_path, FILE_ALL_INFO *data, |
| 54 | 54 | 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 | + | |
| 55 | 63 | /* |
| 56 | 64 | * SMB2 Worker functions - most of protocol specific implementation details |
| 57 | 65 | * are contained within these calls. |