diff options
author | Pavel Shilovsky <pshilovsky@samba.org> | 2012-07-13 06:04:46 -0400 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2012-07-27 16:17:16 -0400 |
commit | ff691e969433a54e26fb6502a6613e02c680e8ee (patch) | |
tree | 3a9fdbbcf7adca4f90f303dc65acef7d9d3b16f4 /fs/cifs/inode.c | |
parent | b387e41e523c1aa347cff055455d0dd129357df4 (diff) |
CIFS: Simplify cifs_mkdir call
Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru>
Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 295 |
1 files changed, 161 insertions, 134 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 35cb6a374a45..e9ba1a150fe3 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -1219,16 +1219,165 @@ unlink_out: | |||
1219 | return rc; | 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 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && | ||
1276 | (mode & S_IWUGO) == 0) { | ||
1277 | FILE_BASIC_INFO info; | ||
1278 | struct cifsInodeInfo *cifsInode; | ||
1279 | u32 dosattrs; | ||
1280 | int tmprc; | ||
1281 | |||
1282 | memset(&info, 0, sizeof(info)); | ||
1283 | cifsInode = CIFS_I(newinode); | ||
1284 | dosattrs = cifsInode->cifsAttrs|ATTR_READONLY; | ||
1285 | info.Attributes = cpu_to_le32(dosattrs); | ||
1286 | tmprc = CIFSSMBSetPathInfo(xid, tcon, full_path, &info, | ||
1287 | cifs_sb->local_nls, | ||
1288 | cifs_sb->mnt_cifs_flags & | ||
1289 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1290 | if (tmprc == 0) | ||
1291 | cifsInode->cifsAttrs = dosattrs; | ||
1292 | } | ||
1293 | if (dentry->d_inode) { | ||
1294 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) | ||
1295 | dentry->d_inode->i_mode = (mode | S_IFDIR); | ||
1296 | |||
1297 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | ||
1298 | dentry->d_inode->i_uid = current_fsuid(); | ||
1299 | if (inode->i_mode & S_ISGID) | ||
1300 | dentry->d_inode->i_gid = inode->i_gid; | ||
1301 | else | ||
1302 | dentry->d_inode->i_gid = | ||
1303 | current_fsgid(); | ||
1304 | } | ||
1305 | } | ||
1306 | } | ||
1307 | return rc; | ||
1308 | } | ||
1309 | |||
1310 | static int | ||
1311 | cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode, | ||
1312 | const char *full_path, struct cifs_sb_info *cifs_sb, | ||
1313 | struct cifs_tcon *tcon, const unsigned int xid) | ||
1314 | { | ||
1315 | int rc = 0; | ||
1316 | u32 oplock = 0; | ||
1317 | FILE_UNIX_BASIC_INFO *info = NULL; | ||
1318 | struct inode *newinode = NULL; | ||
1319 | struct cifs_fattr fattr; | ||
1320 | |||
1321 | info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); | ||
1322 | if (info == NULL) { | ||
1323 | rc = -ENOMEM; | ||
1324 | goto posix_mkdir_out; | ||
1325 | } | ||
1326 | |||
1327 | mode &= ~current_umask(); | ||
1328 | rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode, | ||
1329 | NULL /* netfid */, info, &oplock, full_path, | ||
1330 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | ||
1331 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1332 | if (rc == -EOPNOTSUPP) | ||
1333 | goto posix_mkdir_out; | ||
1334 | else if (rc) { | ||
1335 | cFYI(1, "posix mkdir returned 0x%x", rc); | ||
1336 | d_drop(dentry); | ||
1337 | goto posix_mkdir_out; | ||
1338 | } | ||
1339 | |||
1340 | if (info->Type == cpu_to_le32(-1)) | ||
1341 | /* no return info, go query for it */ | ||
1342 | goto posix_mkdir_get_info; | ||
1343 | /* | ||
1344 | * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if | ||
1345 | * need to set uid/gid. | ||
1346 | */ | ||
1347 | |||
1348 | cifs_unix_basic_to_fattr(&fattr, info, cifs_sb); | ||
1349 | cifs_fill_uniqueid(inode->i_sb, &fattr); | ||
1350 | newinode = cifs_iget(inode->i_sb, &fattr); | ||
1351 | if (!newinode) | ||
1352 | goto posix_mkdir_get_info; | ||
1353 | |||
1354 | d_instantiate(dentry, newinode); | ||
1355 | |||
1356 | #ifdef CONFIG_CIFS_DEBUG2 | ||
1357 | cFYI(1, "instantiated dentry %p %s to inode %p", dentry, | ||
1358 | dentry->d_name.name, newinode); | ||
1359 | |||
1360 | if (newinode->i_nlink != 2) | ||
1361 | cFYI(1, "unexpected number of links %d", newinode->i_nlink); | ||
1362 | #endif | ||
1363 | |||
1364 | posix_mkdir_out: | ||
1365 | kfree(info); | ||
1366 | return rc; | ||
1367 | posix_mkdir_get_info: | ||
1368 | rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon, | ||
1369 | xid); | ||
1370 | goto posix_mkdir_out; | ||
1371 | } | ||
1372 | |||
1222 | int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode) | 1373 | int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode) |
1223 | { | 1374 | { |
1224 | int rc = 0, tmprc; | 1375 | int rc = 0; |
1225 | unsigned int xid; | 1376 | unsigned int xid; |
1226 | struct cifs_sb_info *cifs_sb; | 1377 | struct cifs_sb_info *cifs_sb; |
1227 | struct tcon_link *tlink; | 1378 | struct tcon_link *tlink; |
1228 | struct cifs_tcon *tcon; | 1379 | struct cifs_tcon *tcon; |
1229 | char *full_path = NULL; | 1380 | char *full_path; |
1230 | struct inode *newinode = NULL; | ||
1231 | struct cifs_fattr fattr; | ||
1232 | 1381 | ||
1233 | cFYI(1, "In cifs_mkdir, mode = 0x%hx inode = 0x%p", mode, inode); | 1382 | cFYI(1, "In cifs_mkdir, mode = 0x%hx inode = 0x%p", mode, inode); |
1234 | 1383 | ||
@@ -1248,145 +1397,23 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode) | |||
1248 | 1397 | ||
1249 | if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP & | 1398 | if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP & |
1250 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { | 1399 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { |
1251 | u32 oplock = 0; | 1400 | rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb, |
1252 | FILE_UNIX_BASIC_INFO *pInfo = | 1401 | tcon, xid); |
1253 | kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); | 1402 | if (rc != -EOPNOTSUPP) |
1254 | if (pInfo == NULL) { | ||
1255 | rc = -ENOMEM; | ||
1256 | goto mkdir_out; | 1403 | 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); | ||
1289 | |||
1290 | #ifdef CONFIG_CIFS_DEBUG2 | ||
1291 | cFYI(1, "instantiated dentry %p %s to inode %p", | ||
1292 | direntry, direntry->d_name.name, newinode); | ||
1293 | |||
1294 | if (newinode->i_nlink != 2) | ||
1295 | cFYI(1, "unexpected number of links %d", | ||
1296 | newinode->i_nlink); | ||
1297 | #endif | ||
1298 | } | ||
1299 | kfree(pInfo); | ||
1300 | goto mkdir_out; | ||
1301 | } | 1404 | } |
1302 | mkdir_retry_old: | 1405 | |
1303 | /* BB add setting the equivalent of mode via CreateX w/ACLs */ | 1406 | /* BB add setting the equivalent of mode via CreateX w/ACLs */ |
1304 | rc = CIFSSMBMkDir(xid, tcon, full_path, cifs_sb->local_nls, | 1407 | rc = CIFSSMBMkDir(xid, tcon, full_path, cifs_sb->local_nls, |
1305 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 1408 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
1306 | if (rc) { | 1409 | if (rc) { |
1307 | cFYI(1, "cifs_mkdir returned 0x%x", rc); | 1410 | cFYI(1, "cifs_mkdir returned 0x%x", rc); |
1308 | d_drop(direntry); | 1411 | d_drop(direntry); |
1309 | } else { | 1412 | goto mkdir_out; |
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 | } | ||
1389 | } | 1413 | } |
1414 | |||
1415 | rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon, | ||
1416 | xid); | ||
1390 | mkdir_out: | 1417 | mkdir_out: |
1391 | /* | 1418 | /* |
1392 | * Force revalidate to get parent dir info when needed since cached | 1419 | * Force revalidate to get parent dir info when needed since cached |