提交 0a32c26e 编写于 作者: D Dave Chinner 提交者: Ben Myers

xfs: inode unlinked list needs to recalculate the inode CRC

The inode unlinked list manipulations operate directly on the inode
buffer, and so bypass the inode CRC calculation mechanisms. Hence an
inode on the unlinked list has an invalid CRC. Fix this by
recalculating the CRC whenever we modify an unlinked list pointer in
an inode, ncluding during log recovery. This is trivial to do and
results in  unlinked list operations always leaving a consistent
inode in the buffer.
Signed-off-by: NDave Chinner <dchinner@redhat.com>
Reviewed-by: NMark Tinguely <tinguely@sgi.com>
Signed-off-by: NBen Myers <bpm@sgi.com>
上级 a775ad77
...@@ -1638,6 +1638,10 @@ xfs_iunlink( ...@@ -1638,6 +1638,10 @@ xfs_iunlink(
dip->di_next_unlinked = agi->agi_unlinked[bucket_index]; dip->di_next_unlinked = agi->agi_unlinked[bucket_index];
offset = ip->i_imap.im_boffset + offset = ip->i_imap.im_boffset +
offsetof(xfs_dinode_t, di_next_unlinked); offsetof(xfs_dinode_t, di_next_unlinked);
/* need to recalc the inode CRC if appropriate */
xfs_dinode_calc_crc(mp, dip);
xfs_trans_inode_buf(tp, ibp); xfs_trans_inode_buf(tp, ibp);
xfs_trans_log_buf(tp, ibp, offset, xfs_trans_log_buf(tp, ibp, offset,
(offset + sizeof(xfs_agino_t) - 1)); (offset + sizeof(xfs_agino_t) - 1));
...@@ -1723,6 +1727,10 @@ xfs_iunlink_remove( ...@@ -1723,6 +1727,10 @@ xfs_iunlink_remove(
dip->di_next_unlinked = cpu_to_be32(NULLAGINO); dip->di_next_unlinked = cpu_to_be32(NULLAGINO);
offset = ip->i_imap.im_boffset + offset = ip->i_imap.im_boffset +
offsetof(xfs_dinode_t, di_next_unlinked); offsetof(xfs_dinode_t, di_next_unlinked);
/* need to recalc the inode CRC if appropriate */
xfs_dinode_calc_crc(mp, dip);
xfs_trans_inode_buf(tp, ibp); xfs_trans_inode_buf(tp, ibp);
xfs_trans_log_buf(tp, ibp, offset, xfs_trans_log_buf(tp, ibp, offset,
(offset + sizeof(xfs_agino_t) - 1)); (offset + sizeof(xfs_agino_t) - 1));
...@@ -1796,6 +1804,10 @@ xfs_iunlink_remove( ...@@ -1796,6 +1804,10 @@ xfs_iunlink_remove(
dip->di_next_unlinked = cpu_to_be32(NULLAGINO); dip->di_next_unlinked = cpu_to_be32(NULLAGINO);
offset = ip->i_imap.im_boffset + offset = ip->i_imap.im_boffset +
offsetof(xfs_dinode_t, di_next_unlinked); offsetof(xfs_dinode_t, di_next_unlinked);
/* need to recalc the inode CRC if appropriate */
xfs_dinode_calc_crc(mp, dip);
xfs_trans_inode_buf(tp, ibp); xfs_trans_inode_buf(tp, ibp);
xfs_trans_log_buf(tp, ibp, offset, xfs_trans_log_buf(tp, ibp, offset,
(offset + sizeof(xfs_agino_t) - 1)); (offset + sizeof(xfs_agino_t) - 1));
...@@ -1809,6 +1821,10 @@ xfs_iunlink_remove( ...@@ -1809,6 +1821,10 @@ xfs_iunlink_remove(
last_dip->di_next_unlinked = cpu_to_be32(next_agino); last_dip->di_next_unlinked = cpu_to_be32(next_agino);
ASSERT(next_agino != 0); ASSERT(next_agino != 0);
offset = last_offset + offsetof(xfs_dinode_t, di_next_unlinked); offset = last_offset + offsetof(xfs_dinode_t, di_next_unlinked);
/* need to recalc the inode CRC if appropriate */
xfs_dinode_calc_crc(mp, last_dip);
xfs_trans_inode_buf(tp, last_ibp); xfs_trans_inode_buf(tp, last_ibp);
xfs_trans_log_buf(tp, last_ibp, offset, xfs_trans_log_buf(tp, last_ibp, offset,
(offset + sizeof(xfs_agino_t) - 1)); (offset + sizeof(xfs_agino_t) - 1));
......
...@@ -1912,6 +1912,15 @@ xlog_recover_do_inode_buffer( ...@@ -1912,6 +1912,15 @@ xlog_recover_do_inode_buffer(
buffer_nextp = (xfs_agino_t *)xfs_buf_offset(bp, buffer_nextp = (xfs_agino_t *)xfs_buf_offset(bp,
next_unlinked_offset); next_unlinked_offset);
*buffer_nextp = *logged_nextp; *buffer_nextp = *logged_nextp;
/*
* If necessary, recalculate the CRC in the on-disk inode. We
* have to leave the inode in a consistent state for whoever
* reads it next....
*/
xfs_dinode_calc_crc(mp, (struct xfs_dinode *)
xfs_buf_offset(bp, i * mp->m_sb.sb_inodesize));
} }
return 0; return 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册