Commit 173b04ae6c52c5d38ed2cec2cdd631bd38b77875

Authored by Xue jiufei
Committed by Greg Kroah-Hartman
1 parent 8d38927891

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

commit 53dc20b9a3d928b0744dad5aee65b610de1cc85d upstream.

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.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  
... ... @@ -656,8 +664,10 @@
656 664 {
657 665 handle_t *handle;
658 666 struct inode *inode = old_dentry->d_inode;
  667 + struct inode *old_dir = old_dentry->d_parent->d_inode;
659 668 int err;
660 669 struct buffer_head *fe_bh = NULL;
  670 + struct buffer_head *old_dir_bh = NULL;
661 671 struct buffer_head *parent_fe_bh = NULL;
662 672 struct ocfs2_dinode *fe = NULL;
663 673 struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
664 674  
665 675  
... ... @@ -674,19 +684,33 @@
674 684  
675 685 dquot_initialize(dir);
676 686  
677   - err = ocfs2_inode_lock_nested(dir, &parent_fe_bh, 1, OI_LS_PARENT);
  687 + err = ocfs2_double_lock(osb, &old_dir_bh, old_dir,
  688 + &parent_fe_bh, dir, 0);
678 689 if (err < 0) {
679 690 if (err != -ENOENT)
680 691 mlog_errno(err);
681 692 return err;
682 693 }
683 694  
  695 + /* make sure both dirs have bhs
  696 + * get an extra ref on old_dir_bh if old==new */
  697 + if (!parent_fe_bh) {
  698 + if (old_dir_bh) {
  699 + parent_fe_bh = old_dir_bh;
  700 + get_bh(parent_fe_bh);
  701 + } else {
  702 + mlog(ML_ERROR, "%s: no old_dir_bh!\n", osb->uuid_str);
  703 + err = -EIO;
  704 + goto out;
  705 + }
  706 + }
  707 +
684 708 if (!dir->i_nlink) {
685 709 err = -ENOENT;
686 710 goto out;
687 711 }
688 712  
689   - err = ocfs2_lookup_ino_from_name(dir, old_dentry->d_name.name,
  713 + err = ocfs2_lookup_ino_from_name(old_dir, old_dentry->d_name.name,
690 714 old_dentry->d_name.len, &old_de_ino);
691 715 if (err) {
692 716 err = -ENOENT;
693 717  
... ... @@ -779,10 +803,11 @@
779 803 ocfs2_inode_unlock(inode, 1);
780 804  
781 805 out:
782   - ocfs2_inode_unlock(dir, 1);
  806 + ocfs2_double_unlock(old_dir, dir);
783 807  
784 808 brelse(fe_bh);
785 809 brelse(parent_fe_bh);
  810 + brelse(old_dir_bh);
786 811  
787 812 ocfs2_free_dir_lookup_result(&lookup);
788 813  
789 814  
... ... @@ -991,14 +1016,15 @@
991 1016 }
992 1017  
993 1018 /*
994   - * The only place this should be used is rename!
  1019 + * The only place this should be used is rename and link!
995 1020 * if they have the same id, then the 1st one is the only one locked.
996 1021 */
997 1022 static int ocfs2_double_lock(struct ocfs2_super *osb,
998 1023 struct buffer_head **bh1,
999 1024 struct inode *inode1,
1000 1025 struct buffer_head **bh2,
1001   - struct inode *inode2)
  1026 + struct inode *inode2,
  1027 + int rename)
1002 1028 {
1003 1029 int status;
1004 1030 struct ocfs2_inode_info *oi1 = OCFS2_I(inode1);
... ... @@ -1028,7 +1054,7 @@
1028 1054 }
1029 1055 /* lock id2 */
1030 1056 status = ocfs2_inode_lock_nested(inode2, bh2, 1,
1031   - OI_LS_RENAME1);
  1057 + rename == 1 ? OI_LS_RENAME1 : OI_LS_PARENT);
1032 1058 if (status < 0) {
1033 1059 if (status != -ENOENT)
1034 1060 mlog_errno(status);
... ... @@ -1037,7 +1063,8 @@
1037 1063 }
1038 1064  
1039 1065 /* lock id1 */
1040   - status = ocfs2_inode_lock_nested(inode1, bh1, 1, OI_LS_RENAME2);
  1066 + status = ocfs2_inode_lock_nested(inode1, bh1, 1,
  1067 + rename == 1 ? OI_LS_RENAME2 : OI_LS_PARENT);
1041 1068 if (status < 0) {
1042 1069 /*
1043 1070 * An error return must mean that no cluster locks
... ... @@ -1137,7 +1164,7 @@
1137 1164  
1138 1165 /* if old and new are the same, this'll just do one lock. */
1139 1166 status = ocfs2_double_lock(osb, &old_dir_bh, old_dir,
1140   - &new_dir_bh, new_dir);
  1167 + &new_dir_bh, new_dir, 1);
1141 1168 if (status < 0) {
1142 1169 mlog_errno(status);
1143 1170 goto bail;