diff --git a/lustre/mds/mds_unlink_open.c b/lustre/mds/mds_unlink_open.c index f6280ce99621bd7adb174bf99fb42259380bbaea..330ef32646a5a6c30afe75882e7e39a92da2ba8a 100644 --- a/lustre/mds/mds_unlink_open.c +++ b/lustre/mds/mds_unlink_open.c @@ -199,7 +199,12 @@ static int mds_unlink_orphan(struct obd_device *obd, struct dentry *dchild, handle = NULL; GOTO(out_free_msg, rc); } - rc = vfs_unlink(pending_dir, dchild); + + if (S_ISDIR(inode->i_mode)) { + rc = vfs_rmdir(pending_dir, dchild); + } else { + rc = vfs_unlink(pending_dir, dchild); + } if (rc) CERROR("error %d unlinking orphan %*s from PENDING directory\n", rc, dchild->d_name.len, dchild->d_name.name); diff --git a/lustre/tests/multiop.c b/lustre/tests/multiop.c index 07605bebe6b8f7b5ee6f41fc8948011cd39c1245..2be0b93d10a81033328a43f873e31d68cce8eecc 100755 --- a/lustre/tests/multiop.c +++ b/lustre/tests/multiop.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE /* pull in O_DIRECTORY in bits/fcntl.h */ #include <stdio.h> #include <fcntl.h> #include <string.h> @@ -17,6 +18,7 @@ char usage[] = "Usage: %s filename command-sequence\n" " command-sequence items:\n" " d mkdir\n" +" D open(O_DIRECTORY)\n" " o open(O_RDONLY)\n" " O open(O_CREAT|O_RDWR)\n" " u unlink\n" @@ -74,6 +76,12 @@ int main(int argc, char **argv) exit(1); } break; + case 'D': + if (open(fname, O_DIRECTORY) == -1) { + perror("open(O_DIRECTORY)"); + exit(1); + } + break; case 'm': if (mknod(fname, S_IFREG | 0644, 0) == -1) { perror("mknod(S_IFREG|0644, 0)"); diff --git a/lustre/tests/replay-single.sh b/lustre/tests/replay-single.sh index 9292b0a987e34c112abc7b04af415e57781e59fd..034ee8a351727f4ef5bb3d372097d9b25ccca881 100755 --- a/lustre/tests/replay-single.sh +++ b/lustre/tests/replay-single.sh @@ -653,8 +653,7 @@ test_34() { fail_abort mds kill -USR1 $pid [ -e $DIR/$tfile ] && return 1 - sleep 3 - # wait for commitment of removal + sync return 0 } run_test 34 "abort recovery before client does replay (test mds_cleanup_orphans)" @@ -687,5 +686,26 @@ test_36() { } run_test 36 "don't resend cancel" +# b=2368 +# directory orphans can't be unlinked from PENDING directory +test_37() { + rmdir $DIR/$tfile 2>/dev/null + multiop $DIR/$tfile dD_c & + pid=$! + # give multiop a chance to open + sleep 1 + rmdir $DIR/$tfile + + replay_barrier mds + # clear the dmesg buffer so we only see errors from this recovery + dmesg -c >/dev/null + fail_abort mds + kill -USR1 $pid + dmesg | grep "mds_unlink_orphan.*error .* unlinking orphan" && return 1 + sync + return 0 +} +run_test 37 "abort recovery before client does replay (test mds_cleanup_orphans for directories)" + equals_msg test complete, cleaning up $CLEANUP