diff options
Diffstat (limited to 'fs/ocfs2/namei.c')
-rw-r--r-- | fs/ocfs2/namei.c | 51 |
1 files changed, 25 insertions, 26 deletions
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 849c3b4bb94a..259155f0eb2e 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -429,7 +429,7 @@ static int ocfs2_mknod(struct inode *dir, | |||
429 | mlog_errno(status); | 429 | mlog_errno(status); |
430 | goto leave; | 430 | goto leave; |
431 | } | 431 | } |
432 | dir->i_nlink++; | 432 | inc_nlink(dir); |
433 | } | 433 | } |
434 | 434 | ||
435 | status = ocfs2_add_entry(handle, dentry, inode, | 435 | status = ocfs2_add_entry(handle, dentry, inode, |
@@ -730,7 +730,7 @@ static int ocfs2_link(struct dentry *old_dentry, | |||
730 | goto bail; | 730 | goto bail; |
731 | } | 731 | } |
732 | 732 | ||
733 | inode->i_nlink++; | 733 | inc_nlink(inode); |
734 | inode->i_ctime = CURRENT_TIME; | 734 | inode->i_ctime = CURRENT_TIME; |
735 | fe->i_links_count = cpu_to_le16(inode->i_nlink); | 735 | fe->i_links_count = cpu_to_le16(inode->i_nlink); |
736 | fe->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec); | 736 | fe->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec); |
@@ -739,7 +739,7 @@ static int ocfs2_link(struct dentry *old_dentry, | |||
739 | err = ocfs2_journal_dirty(handle, fe_bh); | 739 | err = ocfs2_journal_dirty(handle, fe_bh); |
740 | if (err < 0) { | 740 | if (err < 0) { |
741 | le16_add_cpu(&fe->i_links_count, -1); | 741 | le16_add_cpu(&fe->i_links_count, -1); |
742 | inode->i_nlink--; | 742 | drop_nlink(inode); |
743 | mlog_errno(err); | 743 | mlog_errno(err); |
744 | goto bail; | 744 | goto bail; |
745 | } | 745 | } |
@@ -749,7 +749,7 @@ static int ocfs2_link(struct dentry *old_dentry, | |||
749 | parent_fe_bh, de_bh); | 749 | parent_fe_bh, de_bh); |
750 | if (err) { | 750 | if (err) { |
751 | le16_add_cpu(&fe->i_links_count, -1); | 751 | le16_add_cpu(&fe->i_links_count, -1); |
752 | inode->i_nlink--; | 752 | drop_nlink(inode); |
753 | mlog_errno(err); | 753 | mlog_errno(err); |
754 | goto bail; | 754 | goto bail; |
755 | } | 755 | } |
@@ -795,11 +795,23 @@ static int ocfs2_remote_dentry_delete(struct dentry *dentry) | |||
795 | return ret; | 795 | return ret; |
796 | } | 796 | } |
797 | 797 | ||
798 | static inline int inode_is_unlinkable(struct inode *inode) | ||
799 | { | ||
800 | if (S_ISDIR(inode->i_mode)) { | ||
801 | if (inode->i_nlink == 2) | ||
802 | return 1; | ||
803 | return 0; | ||
804 | } | ||
805 | |||
806 | if (inode->i_nlink == 1) | ||
807 | return 1; | ||
808 | return 0; | ||
809 | } | ||
810 | |||
798 | static int ocfs2_unlink(struct inode *dir, | 811 | static int ocfs2_unlink(struct inode *dir, |
799 | struct dentry *dentry) | 812 | struct dentry *dentry) |
800 | { | 813 | { |
801 | int status; | 814 | int status; |
802 | unsigned int saved_nlink = 0; | ||
803 | struct inode *inode = dentry->d_inode; | 815 | struct inode *inode = dentry->d_inode; |
804 | struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); | 816 | struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); |
805 | u64 blkno; | 817 | u64 blkno; |
@@ -874,16 +886,6 @@ static int ocfs2_unlink(struct inode *dir, | |||
874 | } | 886 | } |
875 | } | 887 | } |
876 | 888 | ||
877 | /* There are still a few steps left until we can consider the | ||
878 | * unlink to have succeeded. Save off nlink here before | ||
879 | * modification so we can set it back in case we hit an issue | ||
880 | * before commit. */ | ||
881 | saved_nlink = inode->i_nlink; | ||
882 | if (S_ISDIR(inode->i_mode)) | ||
883 | inode->i_nlink = 0; | ||
884 | else | ||
885 | inode->i_nlink--; | ||
886 | |||
887 | status = ocfs2_remote_dentry_delete(dentry); | 889 | status = ocfs2_remote_dentry_delete(dentry); |
888 | if (status < 0) { | 890 | if (status < 0) { |
889 | /* This vote should succeed under all normal | 891 | /* This vote should succeed under all normal |
@@ -892,7 +894,7 @@ static int ocfs2_unlink(struct inode *dir, | |||
892 | goto leave; | 894 | goto leave; |
893 | } | 895 | } |
894 | 896 | ||
895 | if (!inode->i_nlink) { | 897 | if (inode_is_unlinkable(inode)) { |
896 | status = ocfs2_prepare_orphan_dir(osb, handle, inode, | 898 | status = ocfs2_prepare_orphan_dir(osb, handle, inode, |
897 | orphan_name, | 899 | orphan_name, |
898 | &orphan_entry_bh); | 900 | &orphan_entry_bh); |
@@ -919,7 +921,7 @@ static int ocfs2_unlink(struct inode *dir, | |||
919 | 921 | ||
920 | fe = (struct ocfs2_dinode *) fe_bh->b_data; | 922 | fe = (struct ocfs2_dinode *) fe_bh->b_data; |
921 | 923 | ||
922 | if (!inode->i_nlink) { | 924 | if (inode_is_unlinkable(inode)) { |
923 | status = ocfs2_orphan_add(osb, handle, inode, fe, orphan_name, | 925 | status = ocfs2_orphan_add(osb, handle, inode, fe, orphan_name, |
924 | orphan_entry_bh); | 926 | orphan_entry_bh); |
925 | if (status < 0) { | 927 | if (status < 0) { |
@@ -935,10 +937,10 @@ static int ocfs2_unlink(struct inode *dir, | |||
935 | goto leave; | 937 | goto leave; |
936 | } | 938 | } |
937 | 939 | ||
938 | /* We can set nlink on the dinode now. clear the saved version | 940 | if (S_ISDIR(inode->i_mode)) |
939 | * so that it doesn't get set later. */ | 941 | drop_nlink(inode); |
942 | drop_nlink(inode); | ||
940 | fe->i_links_count = cpu_to_le16(inode->i_nlink); | 943 | fe->i_links_count = cpu_to_le16(inode->i_nlink); |
941 | saved_nlink = 0; | ||
942 | 944 | ||
943 | status = ocfs2_journal_dirty(handle, fe_bh); | 945 | status = ocfs2_journal_dirty(handle, fe_bh); |
944 | if (status < 0) { | 946 | if (status < 0) { |
@@ -947,19 +949,16 @@ static int ocfs2_unlink(struct inode *dir, | |||
947 | } | 949 | } |
948 | 950 | ||
949 | if (S_ISDIR(inode->i_mode)) { | 951 | if (S_ISDIR(inode->i_mode)) { |
950 | dir->i_nlink--; | 952 | drop_nlink(dir); |
951 | status = ocfs2_mark_inode_dirty(handle, dir, | 953 | status = ocfs2_mark_inode_dirty(handle, dir, |
952 | parent_node_bh); | 954 | parent_node_bh); |
953 | if (status < 0) { | 955 | if (status < 0) { |
954 | mlog_errno(status); | 956 | mlog_errno(status); |
955 | dir->i_nlink++; | 957 | inc_nlink(dir); |
956 | } | 958 | } |
957 | } | 959 | } |
958 | 960 | ||
959 | leave: | 961 | leave: |
960 | if (status < 0 && saved_nlink) | ||
961 | inode->i_nlink = saved_nlink; | ||
962 | |||
963 | if (handle) | 962 | if (handle) |
964 | ocfs2_commit_trans(handle); | 963 | ocfs2_commit_trans(handle); |
965 | 964 | ||
@@ -1382,7 +1381,7 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1382 | if (new_inode) { | 1381 | if (new_inode) { |
1383 | new_inode->i_nlink--; | 1382 | new_inode->i_nlink--; |
1384 | } else { | 1383 | } else { |
1385 | new_dir->i_nlink++; | 1384 | inc_nlink(new_dir); |
1386 | mark_inode_dirty(new_dir); | 1385 | mark_inode_dirty(new_dir); |
1387 | } | 1386 | } |
1388 | } | 1387 | } |