aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/inode.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2008-10-22 13:57:01 -0400
committerSteve French <sfrench@us.ibm.com>2008-10-23 00:50:17 -0400
commit8d281efb67463fe8aac8f6e10b31492fc218bf2b (patch)
tree72b5642a48725656f2d1edac506ab5d2152de648 /fs/cifs/inode.c
parent84210e9120a8c01a14379ba1f9a9b0f963641d94 (diff)
cifs: fix unlinking of rename target when server doesn't support open file renames
cifs: fix unlinking of rename target when server doesn't support open file renames The patch to make cifs_rename undoable broke renaming one file on top of another when the server doesn't support busy file renames. Remove the code that uses busy file renames to unlink the target file, and just have it call cifs_unlink. If the rename of the source file fails, then the unlink won't be undoable, but hopefully that's rare enough that it won't be a problem. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r--fs/cifs/inode.c87
1 files changed, 8 insertions, 79 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 8ac4eabc1f8b..d54fa8aeaea9 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1293,12 +1293,9 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
1293 struct cifs_sb_info *cifs_sb_source; 1293 struct cifs_sb_info *cifs_sb_source;
1294 struct cifs_sb_info *cifs_sb_target; 1294 struct cifs_sb_info *cifs_sb_target;
1295 struct cifsTconInfo *tcon; 1295 struct cifsTconInfo *tcon;
1296 struct cifsInodeInfo *target_cinode;
1297 FILE_UNIX_BASIC_INFO *info_buf_source = NULL; 1296 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
1298 FILE_UNIX_BASIC_INFO *info_buf_target; 1297 FILE_UNIX_BASIC_INFO *info_buf_target;
1299 __u16 dstfid; 1298 int xid, rc, tmprc;
1300 int xid, rc, tmprc, oplock = 0;
1301 bool delete_already_pending;
1302 1299
1303 cifs_sb_target = CIFS_SB(target_dir->i_sb); 1300 cifs_sb_target = CIFS_SB(target_dir->i_sb);
1304 cifs_sb_source = CIFS_SB(source_dir->i_sb); 1301 cifs_sb_source = CIFS_SB(source_dir->i_sb);
@@ -1348,104 +1345,36 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
1348 } 1345 }
1349 1346
1350 info_buf_target = info_buf_source + 1; 1347 info_buf_target = info_buf_source + 1;
1351 rc = CIFSSMBUnixQPathInfo(xid, tcon, fromName, 1348 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName,
1352 info_buf_source, 1349 info_buf_source,
1353 cifs_sb_source->local_nls, 1350 cifs_sb_source->local_nls,
1354 cifs_sb_source->mnt_cifs_flags & 1351 cifs_sb_source->mnt_cifs_flags &
1355 CIFS_MOUNT_MAP_SPECIAL_CHR); 1352 CIFS_MOUNT_MAP_SPECIAL_CHR);
1356 if (rc != 0) 1353 if (tmprc != 0)
1357 goto unlink_target; 1354 goto unlink_target;
1358 1355
1359 rc = CIFSSMBUnixQPathInfo(xid, tcon, 1356 tmprc = CIFSSMBUnixQPathInfo(xid, tcon,
1360 toName, info_buf_target, 1357 toName, info_buf_target,
1361 cifs_sb_target->local_nls, 1358 cifs_sb_target->local_nls,
1362 /* remap based on source sb */ 1359 /* remap based on source sb */
1363 cifs_sb_source->mnt_cifs_flags & 1360 cifs_sb_source->mnt_cifs_flags &
1364 CIFS_MOUNT_MAP_SPECIAL_CHR); 1361 CIFS_MOUNT_MAP_SPECIAL_CHR);
1365 1362
1366 if (rc == 0 && (info_buf_source->UniqueId == 1363 if (tmprc == 0 && (info_buf_source->UniqueId ==
1367 info_buf_target->UniqueId)) 1364 info_buf_target->UniqueId))
1368 /* same file, POSIX says that this is a noop */ 1365 /* same file, POSIX says that this is a noop */
1369 goto cifs_rename_exit; 1366 goto cifs_rename_exit;
1370
1371 rc = -EEXIST;
1372 } /* else ... BB we could add the same check for Windows by 1367 } /* else ... BB we could add the same check for Windows by
1373 checking the UniqueId via FILE_INTERNAL_INFO */ 1368 checking the UniqueId via FILE_INTERNAL_INFO */
1374 1369
1375 if ((rc == -EACCES) || (rc == -EEXIST)) {
1376unlink_target: 1370unlink_target:
1377 /* don't bother if this is a negative dentry */ 1371 if ((rc == -EACCES) || (rc == -EEXIST)) {
1378 if (!target_dentry->d_inode) 1372 tmprc = cifs_unlink(target_dir, target_dentry);
1379 goto cifs_rename_exit;
1380
1381 target_cinode = CIFS_I(target_dentry->d_inode);
1382
1383 /* try to move the target out of the way */
1384 tmprc = CIFSSMBOpen(xid, tcon, toName, FILE_OPEN, DELETE,
1385 CREATE_NOT_DIR, &dstfid, &oplock, NULL,
1386 cifs_sb_target->local_nls,
1387 cifs_sb_target->mnt_cifs_flags &
1388 CIFS_MOUNT_MAP_SPECIAL_CHR);
1389 if (tmprc) 1373 if (tmprc)
1390 goto cifs_rename_exit; 1374 goto cifs_rename_exit;
1391 1375
1392 /* rename the file to random name */
1393 tmprc = CIFSSMBRenameOpenFile(xid, tcon, dstfid, NULL,
1394 cifs_sb_target->local_nls,
1395 cifs_sb_target->mnt_cifs_flags &
1396 CIFS_MOUNT_MAP_SPECIAL_CHR);
1397
1398 if (tmprc)
1399 goto close_target;
1400
1401 delete_already_pending = target_cinode->delete_pending;
1402
1403 if (!delete_already_pending) {
1404 /* set delete on close */
1405 tmprc = CIFSSMBSetFileDisposition(xid, tcon,
1406 true, dstfid,
1407 current->tgid);
1408 /*
1409 * This hack is for broken samba servers, remove this
1410 * once more fixed ones are in the field.
1411 */
1412 if (tmprc == -ENOENT)
1413 delete_already_pending = false;
1414 else if (tmprc)
1415 goto undo_target_rename;
1416
1417 target_cinode->delete_pending = true;
1418 }
1419
1420
1421 rc = cifs_do_rename(xid, source_dentry, fromName, 1376 rc = cifs_do_rename(xid, source_dentry, fromName,
1422 target_dentry, toName); 1377 target_dentry, toName);
1423
1424 if (rc == 0)
1425 goto close_target;
1426
1427 /*
1428 * after this point, we can't bother with error handling on
1429 * the undo's. This is best effort since we can't do anything
1430 * about failures here.
1431 */
1432 if (!delete_already_pending) {
1433 tmprc = CIFSSMBSetFileDisposition(xid, tcon,
1434 false, dstfid,
1435 current->tgid);
1436 if (tmprc == 0)
1437 target_cinode->delete_pending = false;
1438 }
1439
1440undo_target_rename:
1441 /* rename failed: undo target rename */
1442 CIFSSMBRenameOpenFile(xid, tcon, dstfid,
1443 target_dentry->d_name.name,
1444 cifs_sb_target->local_nls,
1445 cifs_sb_target->mnt_cifs_flags &
1446 CIFS_MOUNT_MAP_SPECIAL_CHR);
1447close_target:
1448 CIFSSMBClose(xid, tcon, dstfid);
1449 } 1378 }
1450 1379
1451cifs_rename_exit: 1380cifs_rename_exit: