aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Fasheh <mark.fasheh@oracle.com>2006-10-01 02:29:05 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-01 03:39:30 -0400
commit17ff785691503f63ec648df82a7fdaece7695561 (patch)
tree9777f4787253941c723aac1e13ab37fb285bcc4a
parentd8c76e6f45c111c32a4b3e50a2adc9210737b0d8 (diff)
[PATCH] r/o bind mounts: clean up OCFS2 nlink handling
OCFS2 does some operations on i_nlink, then reverts them if some of its operations fail to complete. This does not fit in well with the drop_nlink() logic where we expect i_nlink to stay at zero once it gets there. So, delay all of the nlink operations until we're sure that the operations have completed. Also, introduce a small helper to check whether an inode has proper "unlinkable" i_nlink counts no matter whether it is a directory or regular inode. This patch is broken out from the others because it does contain some logical changes. Signed-off-by: Dave Hansen <haveblue@us.ibm.com> Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--fs/ocfs2/namei.c39
1 files changed, 19 insertions, 20 deletions
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 8c370a39e0c1..259155f0eb2e 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -795,11 +795,23 @@ static int ocfs2_remote_dentry_delete(struct dentry *dentry)
795 return ret; 795 return ret;
796} 796}
797 797
798static 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
798static int ocfs2_unlink(struct inode *dir, 811static 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,7 +949,7 @@ 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) {
@@ -957,9 +959,6 @@ static int ocfs2_unlink(struct inode *dir,
957 } 959 }
958 960
959leave: 961leave:
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