aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorYounger Liu <younger.liu@huawei.com>2013-07-03 18:00:58 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-03 19:07:24 -0400
commitea45466aec98b68faaf354901c42e281e58af50a (patch)
tree1b14611557df4312b0e70df80e5162a00432818c /fs
parent096b2ef83c87d7a7e0d2838f7f1391c74fdad0e6 (diff)
ocfs2: need rollback when journal_access failed in ocfs2_orphan_add()
While adding a file into orphan dir in ocfs2_orphan_add(), it calls __ocfs2_add_entry() before ocfs2_journal_access_di(). If ocfs2_journal_access_di() failed, the file is added into orphan dir, and orphan dir dinode updated, but file dinode has not been updated. Accordingly, the data is not consistent between file dinode and orphan dir. So, need to call ocfs2_journal_access_di() before __ocfs2_add_entry(), and if ocfs2_journal_access_di() failed, orphan_fe and orphan_dir_inode->i_nlink need rollback. This bug was added by 3939fda4 ("Ocfs2: Journaling i_flags and i_orphaned_slot when adding inode to orphan dir."). Signed-off-by: Younger Liu <younger.liu@huawei.com> Acked-by: Jeff Liu <jeff.liu@oracle.com> Cc: Sunil Mushran <sunil.mushran@gmail.com> Cc: Mark Fasheh <mfasheh@suse.com> Cc: Joel Becker <jlbec@evilplan.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/ocfs2/namei.c41
1 files changed, 23 insertions, 18 deletions
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 75964addfe32..30842f5cf590 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -2012,6 +2012,21 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
2012 goto leave; 2012 goto leave;
2013 } 2013 }
2014 2014
2015 /*
2016 * We're going to journal the change of i_flags and i_orphaned_slot.
2017 * It's safe anyway, though some callers may duplicate the journaling.
2018 * Journaling within the func just make the logic look more
2019 * straightforward.
2020 */
2021 status = ocfs2_journal_access_di(handle,
2022 INODE_CACHE(inode),
2023 fe_bh,
2024 OCFS2_JOURNAL_ACCESS_WRITE);
2025 if (status < 0) {
2026 mlog_errno(status);
2027 goto leave;
2028 }
2029
2015 /* we're a cluster, and nlink can change on disk from 2030 /* we're a cluster, and nlink can change on disk from
2016 * underneath us... */ 2031 * underneath us... */
2017 orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data; 2032 orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data;
@@ -2026,22 +2041,7 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
2026 orphan_dir_bh, lookup); 2041 orphan_dir_bh, lookup);
2027 if (status < 0) { 2042 if (status < 0) {
2028 mlog_errno(status); 2043 mlog_errno(status);
2029 goto leave; 2044 goto rollback;
2030 }
2031
2032 /*
2033 * We're going to journal the change of i_flags and i_orphaned_slot.
2034 * It's safe anyway, though some callers may duplicate the journaling.
2035 * Journaling within the func just make the logic look more
2036 * straightforward.
2037 */
2038 status = ocfs2_journal_access_di(handle,
2039 INODE_CACHE(inode),
2040 fe_bh,
2041 OCFS2_JOURNAL_ACCESS_WRITE);
2042 if (status < 0) {
2043 mlog_errno(status);
2044 goto leave;
2045 } 2045 }
2046 2046
2047 fe->i_flags |= cpu_to_le32(OCFS2_ORPHANED_FL); 2047 fe->i_flags |= cpu_to_le32(OCFS2_ORPHANED_FL);
@@ -2057,11 +2057,16 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
2057 trace_ocfs2_orphan_add_end((unsigned long long)OCFS2_I(inode)->ip_blkno, 2057 trace_ocfs2_orphan_add_end((unsigned long long)OCFS2_I(inode)->ip_blkno,
2058 osb->slot_num); 2058 osb->slot_num);
2059 2059
2060rollback:
2061 if (status < 0) {
2062 if (S_ISDIR(inode->i_mode))
2063 ocfs2_add_links_count(orphan_fe, -1);
2064 set_nlink(orphan_dir_inode, ocfs2_read_links_count(orphan_fe));
2065 }
2066
2060leave: 2067leave:
2061 brelse(orphan_dir_bh); 2068 brelse(orphan_dir_bh);
2062 2069
2063 if (status)
2064 mlog_errno(status);
2065 return status; 2070 return status;
2066} 2071}
2067 2072