diff --git a/lustre/mds/mds_reint.c b/lustre/mds/mds_reint.c index 22ca65b567f0e64aca18142ff0c1d893efcb9ddc..626248d4040a888469e8d0e8d3479d59504aac7d 100644 --- a/lustre/mds/mds_reint.c +++ b/lustre/mds/mds_reint.c @@ -1664,6 +1664,10 @@ static int mds_reint_rename(struct mds_update_record *rec, int offset, de_new->d_inode->i_ino == de_tgtdir->d_inode->i_ino)) GOTO(cleanup, rc = -EINVAL); + if (de_old->d_inode == de_new->d_inode) { + GOTO(cleanup, rc = 0); + } + /* if we are about to remove the target at first, pass the EA of * that inode to client to perform and cleanup on OST */ body = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*body)); diff --git a/lustre/tests/multiop.c b/lustre/tests/multiop.c index 2be0b93d10a81033328a43f873e31d68cce8eecc..de59be64fd7e3a701b6ed2e712f7a9cbbcd5e4be 100755 --- a/lustre/tests/multiop.c +++ b/lustre/tests/multiop.c @@ -21,10 +21,13 @@ char usage[] = " D open(O_DIRECTORY)\n" " o open(O_RDONLY)\n" " O open(O_CREAT|O_RDWR)\n" +" L link\n" +" l symlink\n" " u unlink\n" " U munmap\n" " m mknod\n" " M rw mmap to EOF (must open and stat prior)\n" +" N rename\n" " c close\n" " _ wait for signal\n" " R reference entire mmap-ed region\n" @@ -41,15 +44,28 @@ char usage[] = void null_handler(int unused) { } +static const char * +pop_arg(int argc, char *argv[]) +{ + static int cur_arg = 3; + + if (cur_arg >= argc) + return NULL; + + return argv[cur_arg++]; +} +#define POP_ARG() (pop_arg(argc, argv)) + int main(int argc, char **argv) { char *fname, *commands; + const char *newfile; struct stat st; size_t mmap_len, i; unsigned char *mmap_ptr = NULL, junk = 0; int fd = -1; - if (argc != 3) { + if (argc < 3) { fprintf(stderr, usage, argv[0]); exit(1); } @@ -82,6 +98,24 @@ int main(int argc, char **argv) exit(1); } break; + case 'l': + newfile = POP_ARG(); + if (!newfile) + newfile = fname; + if (symlink(fname, newfile)) { + perror("symlink()"); + exit(1); + } + break; + case 'L': + newfile = POP_ARG(); + if (!newfile) + newfile = fname; + if (link(fname, newfile)) { + perror("symlink()"); + exit(1); + } + break; case 'm': if (mknod(fname, S_IFREG | 0644, 0) == -1) { perror("mknod(S_IFREG|0644, 0)"); @@ -97,6 +131,15 @@ int main(int argc, char **argv) exit(1); } break; + case 'N': + newfile = POP_ARG(); + if (!newfile) + newfile = fname; + if (rename (fname, newfile)) { + perror("rename()"); + exit(1); + } + break; case 'O': fd = open(fname, O_CREAT|O_RDWR, 0644); if (fd == -1) { diff --git a/lustre/tests/rename.pl b/lustre/tests/rename.pl index ee9bb4d228428a6c9be4b425db82eb354442d2b6..dd6b5dc15874e06b555571308639a9c4b0faab76 100644 --- a/lustre/tests/rename.pl +++ b/lustre/tests/rename.pl @@ -93,7 +93,7 @@ for (my $i=1; $i<=$num_threads; $i++) { # Wait for all our threads to finish. my $child = 0; do { - $child = waitpid(-1, WNOHANG); + $child = waitpid(-1, 0); } until $child > 0; sleep 1; diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 0e9f0b09267f23774f2bacb7554d226d4a57cba0..1147bcf65cf6dcaa42eab06b21c7b6c9b4668800 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -611,6 +611,19 @@ test_24k() { } run_test 24k "touch .../R11a/f; mv .../R11a/f .../R11a/d =======" +# bug 2429 - rename foo foo foo creates invalid file +test_24l() { + f="$DIR/f24l" + multiop $f OcNs || error +} +run_test 24l "Renaming a file to itself ========================" + +test_24m() { + f="$DIR/f24m" + multiop $f OcLN ${f}2 ${f}2 || error +} +run_test 24m "Renaming a file to a hard link to itself =========" + test_25a() { echo '== symlink sanity =============================================' mkdir $DIR/d25