Commit 53dc20b9a3d928b0744dad5aee65b610de1cc85d

Authored by Xue jiufei
Committed by Linus Torvalds
1 parent 75dd112aac

ocfs2: fix the wrong directory passed to ocfs2_lookup_ino_from_name() when link file

In ocfs2_link(), the parent directory inode passed to function
ocfs2_lookup_ino_from_name() is wrong.  Parameter dir is the parent of
new_dentry not old_dentry.  We should get old_dir from old_dentry and
lookup old_dentry in old_dir in case another node remove the old dentry.

With this change, hard linking works again, when paths are relative with
at least one subdirectory.  This is how the problem was reproducable:

  # mkdir a
  # mkdir b
  # touch a/test
  # ln a/test b/test
  ln: failed to create hard link `b/test' => `a/test': No such file or  directory

However when creating links in the same dir, it worked well.

Now the link gets created.

Fixes: 0e048316ff57 ("ocfs2: check existence of old dentry in ocfs2_link()")
Signed-off-by: joyce.xue <xuejiufei@huawei.com>
Reported-by: Szabo Aron - UBIT <aron@ubit.hu>
Cc: Mark Fasheh <mfasheh@suse.com>
Cc: Joel Becker <jlbec@evilplan.org>
Tested-by: Aron Szabo <aron@ubit.hu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 1 changed file with 35 additions and 8 deletions Side-by-side Diff

... ... @@ -94,6 +94,14 @@
94 94 struct inode *inode,
95 95 const char *symname);
96 96  
  97 +static int ocfs2_double_lock(struct ocfs2_super *osb,
  98 + struct buffer_head **bh1,
  99 + struct inode *inode1,
  100 + struct buffer_head **bh2,
  101 + struct inode *inode2,
  102 + int rename);
  103 +
  104 +static void ocfs2_double_unlock(struct inode *inode1, struct inode *inode2);
97 105 /* An orphan dir name is an 8 byte value, printed as a hex string */
98 106 #define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64)))
99 107  
100 108  
... ... @@ -678,8 +686,10 @@
678 686 {
679 687 handle_t *handle;
680 688 struct inode *inode = old_dentry->d_inode;
  689 + struct inode *old_dir = old_dentry->d_parent->d_inode;
681 690 int err;
682 691 struct buffer_head *fe_bh = NULL;
  692 + struct buffer_head *old_dir_bh = NULL;
683 693 struct buffer_head *parent_fe_bh = NULL;
684 694 struct ocfs2_dinode *fe = NULL;
685 695 struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
686 696  
687 697  
... ... @@ -696,19 +706,33 @@
696 706  
697 707 dquot_initialize(dir);
698 708  
699   - err = ocfs2_inode_lock_nested(dir, &parent_fe_bh, 1, OI_LS_PARENT);
  709 + err = ocfs2_double_lock(osb, &old_dir_bh, old_dir,
  710 + &parent_fe_bh, dir, 0);
700 711 if (err < 0) {
701 712 if (err != -ENOENT)
702 713 mlog_errno(err);
703 714 return err;
704 715 }
705 716  
  717 + /* make sure both dirs have bhs
  718 + * get an extra ref on old_dir_bh if old==new */
  719 + if (!parent_fe_bh) {
  720 + if (old_dir_bh) {
  721 + parent_fe_bh = old_dir_bh;
  722 + get_bh(parent_fe_bh);
  723 + } else {
  724 + mlog(ML_ERROR, "%s: no old_dir_bh!\n", osb->uuid_str);
  725 + err = -EIO;
  726 + goto out;
  727 + }
  728 + }
  729 +
706 730 if (!dir->i_nlink) {
707 731 err = -ENOENT;
708 732 goto out;
709 733 }
710 734  
711   - err = ocfs2_lookup_ino_from_name(dir, old_dentry->d_name.name,
  735 + err = ocfs2_lookup_ino_from_name(old_dir, old_dentry->d_name.name,
712 736 old_dentry->d_name.len, &old_de_ino);
713 737 if (err) {
714 738 err = -ENOENT;
715 739  
... ... @@ -801,10 +825,11 @@
801 825 ocfs2_inode_unlock(inode, 1);
802 826  
803 827 out:
804   - ocfs2_inode_unlock(dir, 1);
  828 + ocfs2_double_unlock(old_dir, dir);
805 829  
806 830 brelse(fe_bh);
807 831 brelse(parent_fe_bh);
  832 + brelse(old_dir_bh);
808 833  
809 834 ocfs2_free_dir_lookup_result(&lookup);
810 835  
811 836  
... ... @@ -1072,14 +1097,15 @@
1072 1097 }
1073 1098  
1074 1099 /*
1075   - * The only place this should be used is rename!
  1100 + * The only place this should be used is rename and link!
1076 1101 * if they have the same id, then the 1st one is the only one locked.
1077 1102 */
1078 1103 static int ocfs2_double_lock(struct ocfs2_super *osb,
1079 1104 struct buffer_head **bh1,
1080 1105 struct inode *inode1,
1081 1106 struct buffer_head **bh2,
1082   - struct inode *inode2)
  1107 + struct inode *inode2,
  1108 + int rename)
1083 1109 {
1084 1110 int status;
1085 1111 int inode1_is_ancestor, inode2_is_ancestor;
... ... @@ -1127,7 +1153,7 @@
1127 1153 }
1128 1154 /* lock id2 */
1129 1155 status = ocfs2_inode_lock_nested(inode2, bh2, 1,
1130   - OI_LS_RENAME1);
  1156 + rename == 1 ? OI_LS_RENAME1 : OI_LS_PARENT);
1131 1157 if (status < 0) {
1132 1158 if (status != -ENOENT)
1133 1159 mlog_errno(status);
... ... @@ -1136,7 +1162,8 @@
1136 1162 }
1137 1163  
1138 1164 /* lock id1 */
1139   - status = ocfs2_inode_lock_nested(inode1, bh1, 1, OI_LS_RENAME2);
  1165 + status = ocfs2_inode_lock_nested(inode1, bh1, 1,
  1166 + rename == 1 ? OI_LS_RENAME2 : OI_LS_PARENT);
1140 1167 if (status < 0) {
1141 1168 /*
1142 1169 * An error return must mean that no cluster locks
... ... @@ -1252,7 +1279,7 @@
1252 1279  
1253 1280 /* if old and new are the same, this'll just do one lock. */
1254 1281 status = ocfs2_double_lock(osb, &old_dir_bh, old_dir,
1255   - &new_dir_bh, new_dir);
  1282 + &new_dir_bh, new_dir, 1);
1256 1283 if (status < 0) {
1257 1284 mlog_errno(status);
1258 1285 goto bail;