* [PATCH 00/13] Updated CRC patches
@ 2009-02-10 20:22 Christoph Hellwig
2009-02-10 20:22 ` [PATCH 01/13] xfs: cleanup xlog_bread Christoph Hellwig
` (12 more replies)
0 siblings, 13 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
To: xfs
This is an updated version of the CRC patches, against the current
development tree. There are new patches for CRCs on the inode (including
a new version 3 inode format leaving space for other requested fields),
the AGFL (including a proper header for it) and quotas.
The log crc patch has been updated to properly deal with split logbuffers
and to checksum not only the log payload but also the log record header
and cycle data.
In general the kernel code should be pretty solid now, but the dir2 and
attr CRC support is still missing. The inode crc patch will probably
get some sort of makeover after Dave's icreate transaction and the
reworked unlinked inode list handling go in.
The userspace support is available at:
http://verein.lst.de/~hch/xfs/patches.xfsprogs.crc-20090210.tgz
and has gotten update for the new features, as well as support in xfs_db
for all the new fields. It's not quite as solid as the kernel code yet,
we'll need another large libxfs resync and a solution to the different
uuid prototypes in userspace first.
There's a couple of new xfsqa failures with these patches, most are
due to different logprint output, or because the CRC catch xfs_db
induced corruptions in a different way than the old code would.
Some are because the new minimal inode size of 512 bytes confuse
various tests.
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 01/13] xfs: cleanup xlog_bread
2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
@ 2009-02-10 20:22 ` Christoph Hellwig
2009-02-10 20:22 ` [PATCH 02/13] xfs: remove m_litino Christoph Hellwig
` (11 subsequent siblings)
12 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
To: xfs
[-- Attachment #1: xfs-cleanup-xlog_bread --]
[-- Type: text/plain, Size: 13632 bytes --]
Most callers of xlog_bread need to call xlog_align to get the actual offset.
Consolidate that call into the main xlog_bread and provide a _xlog_bread
for those few that don't want the actual offset.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: xfs/fs/xfs/xfs_log_priv.h
===================================================================
--- xfs.orig/fs/xfs/xfs_log_priv.h 2009-02-10 19:16:19.308944151 +0100
+++ xfs/fs/xfs/xfs_log_priv.h 2009-02-10 19:22:43.915068626 +0100
@@ -455,7 +455,6 @@ extern void xlog_recover_process_iunlin
extern struct xfs_buf *xlog_get_bp(xlog_t *, int);
extern void xlog_put_bp(struct xfs_buf *);
-extern int xlog_bread(xlog_t *, xfs_daddr_t, int, struct xfs_buf *);
extern kmem_zone_t *xfs_log_ticket_zone;
Index: xfs/fs/xfs/xfs_log_recover.c
===================================================================
--- xfs.orig/fs/xfs/xfs_log_recover.c 2009-02-10 19:16:19.314973900 +0100
+++ xfs/fs/xfs/xfs_log_recover.c 2009-02-10 19:22:43.917068532 +0100
@@ -94,12 +94,30 @@ xlog_put_bp(
xfs_buf_free(bp);
}
+STATIC xfs_caddr_t
+xlog_align(
+ xlog_t *log,
+ xfs_daddr_t blk_no,
+ int nbblks,
+ xfs_buf_t *bp)
+{
+ xfs_caddr_t ptr;
+
+ if (!log->l_sectbb_log)
+ return XFS_BUF_PTR(bp);
+
+ ptr = XFS_BUF_PTR(bp) + BBTOB((int)blk_no & log->l_sectbb_mask);
+ ASSERT(XFS_BUF_SIZE(bp) >=
+ BBTOB(nbblks + (blk_no & log->l_sectbb_mask)));
+ return ptr;
+}
+
/*
* nbblks should be uint, but oh well. Just want to catch that 32-bit length.
*/
-int
-xlog_bread(
+STATIC int
+_xlog_bread(
xlog_t *log,
xfs_daddr_t blk_no,
int nbblks,
@@ -137,6 +155,24 @@ xlog_bread(
return error;
}
+STATIC int
+xlog_bread(
+ xlog_t *log,
+ xfs_daddr_t blk_no,
+ int nbblks,
+ xfs_buf_t *bp,
+ xfs_caddr_t *offset)
+{
+ int error;
+
+ error = _xlog_bread(log, blk_no, nbblks, bp);
+ if (error)
+ return error;
+
+ *offset = xlog_align(log, blk_no, nbblks, bp);
+ return 0;
+}
+
/*
* Write out the buffer at the given block for the given number of blocks.
* The buffer is kept locked across the write and is returned locked.
@@ -180,24 +216,6 @@ xlog_bwrite(
return error;
}
-STATIC xfs_caddr_t
-xlog_align(
- xlog_t *log,
- xfs_daddr_t blk_no,
- int nbblks,
- xfs_buf_t *bp)
-{
- xfs_caddr_t ptr;
-
- if (!log->l_sectbb_log)
- return XFS_BUF_PTR(bp);
-
- ptr = XFS_BUF_PTR(bp) + BBTOB((int)blk_no & log->l_sectbb_mask);
- ASSERT(XFS_BUF_SIZE(bp) >=
- BBTOB(nbblks + (blk_no & log->l_sectbb_mask)));
- return ptr;
-}
-
#ifdef DEBUG
/*
* dump debug superblock and log record information
@@ -321,9 +339,9 @@ xlog_find_cycle_start(
mid_blk = BLK_AVG(first_blk, *last_blk);
while (mid_blk != first_blk && mid_blk != *last_blk) {
- if ((error = xlog_bread(log, mid_blk, 1, bp)))
+ error = xlog_bread(log, mid_blk, 1, bp, &offset);
+ if (error)
return error;
- offset = xlog_align(log, mid_blk, 1, bp);
mid_cycle = xlog_get_cycle(offset);
if (mid_cycle == cycle) {
*last_blk = mid_blk;
@@ -379,10 +397,10 @@ xlog_find_verify_cycle(
bcount = min(bufblks, (start_blk + nbblks - i));
- if ((error = xlog_bread(log, i, bcount, bp)))
+ error = xlog_bread(log, i, bcount, bp, &buf);
+ if (error)
goto out;
- buf = xlog_align(log, i, bcount, bp);
for (j = 0; j < bcount; j++) {
cycle = xlog_get_cycle(buf);
if (cycle == stop_on_cycle_no) {
@@ -436,9 +454,9 @@ xlog_find_verify_log_record(
return ENOMEM;
smallmem = 1;
} else {
- if ((error = xlog_bread(log, start_blk, num_blks, bp)))
+ error = xlog_bread(log, start_blk, num_blks, bp, &offset);
+ if (error)
goto out;
- offset = xlog_align(log, start_blk, num_blks, bp);
offset += ((num_blks - 1) << BBSHIFT);
}
@@ -453,9 +471,9 @@ xlog_find_verify_log_record(
}
if (smallmem) {
- if ((error = xlog_bread(log, i, 1, bp)))
+ error = xlog_bread(log, i, 1, bp, &offset);
+ if (error)
goto out;
- offset = xlog_align(log, i, 1, bp);
}
head = (xlog_rec_header_t *)offset;
@@ -559,15 +577,18 @@ xlog_find_head(
bp = xlog_get_bp(log, 1);
if (!bp)
return ENOMEM;
- if ((error = xlog_bread(log, 0, 1, bp)))
+
+ error = xlog_bread(log, 0, 1, bp, &offset);
+ if (error)
goto bp_err;
- offset = xlog_align(log, 0, 1, bp);
+
first_half_cycle = xlog_get_cycle(offset);
last_blk = head_blk = log_bbnum - 1; /* get cycle # of last block */
- if ((error = xlog_bread(log, last_blk, 1, bp)))
+ error = xlog_bread(log, last_blk, 1, bp, &offset);
+ if (error)
goto bp_err;
- offset = xlog_align(log, last_blk, 1, bp);
+
last_half_cycle = xlog_get_cycle(offset);
ASSERT(last_half_cycle != 0);
@@ -817,9 +838,10 @@ xlog_find_tail(
if (!bp)
return ENOMEM;
if (*head_blk == 0) { /* special case */
- if ((error = xlog_bread(log, 0, 1, bp)))
+ error = xlog_bread(log, 0, 1, bp, &offset);
+ if (error)
goto bread_err;
- offset = xlog_align(log, 0, 1, bp);
+
if (xlog_get_cycle(offset) == 0) {
*tail_blk = 0;
/* leave all other log inited values alone */
@@ -832,9 +854,10 @@ xlog_find_tail(
*/
ASSERT(*head_blk < INT_MAX);
for (i = (int)(*head_blk) - 1; i >= 0; i--) {
- if ((error = xlog_bread(log, i, 1, bp)))
+ error = xlog_bread(log, i, 1, bp, &offset);
+ if (error)
goto bread_err;
- offset = xlog_align(log, i, 1, bp);
+
if (XLOG_HEADER_MAGIC_NUM == be32_to_cpu(*(__be32 *)offset)) {
found = 1;
break;
@@ -848,9 +871,10 @@ xlog_find_tail(
*/
if (!found) {
for (i = log->l_logBBsize - 1; i >= (int)(*head_blk); i--) {
- if ((error = xlog_bread(log, i, 1, bp)))
+ error = xlog_bread(log, i, 1, bp, &offset);
+ if (error)
goto bread_err;
- offset = xlog_align(log, i, 1, bp);
+
if (XLOG_HEADER_MAGIC_NUM ==
be32_to_cpu(*(__be32 *)offset)) {
found = 2;
@@ -922,10 +946,10 @@ xlog_find_tail(
if (*head_blk == after_umount_blk &&
be32_to_cpu(rhead->h_num_logops) == 1) {
umount_data_blk = (i + hblks) % log->l_logBBsize;
- if ((error = xlog_bread(log, umount_data_blk, 1, bp))) {
+ error = xlog_bread(log, umount_data_blk, 1, bp, &offset);
+ if (error)
goto bread_err;
- }
- offset = xlog_align(log, umount_data_blk, 1, bp);
+
op_head = (xlog_op_header_t *)offset;
if (op_head->oh_flags & XLOG_UNMOUNT_TRANS) {
/*
@@ -1017,9 +1041,10 @@ xlog_find_zeroed(
bp = xlog_get_bp(log, 1);
if (!bp)
return ENOMEM;
- if ((error = xlog_bread(log, 0, 1, bp)))
+ error = xlog_bread(log, 0, 1, bp, &offset);
+ if (error)
goto bp_err;
- offset = xlog_align(log, 0, 1, bp);
+
first_cycle = xlog_get_cycle(offset);
if (first_cycle == 0) { /* completely zeroed log */
*blk_no = 0;
@@ -1028,9 +1053,10 @@ xlog_find_zeroed(
}
/* check partially zeroed log */
- if ((error = xlog_bread(log, log_bbnum-1, 1, bp)))
+ error = xlog_bread(log, log_bbnum-1, 1, bp, &offset);
+ if (error)
goto bp_err;
- offset = xlog_align(log, log_bbnum-1, 1, bp);
+
last_cycle = xlog_get_cycle(offset);
if (last_cycle != 0) { /* log completely written to */
xlog_put_bp(bp);
@@ -1152,10 +1178,10 @@ xlog_write_log_records(
*/
balign = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, start_block);
if (balign != start_block) {
- if ((error = xlog_bread(log, start_block, 1, bp))) {
- xlog_put_bp(bp);
- return error;
- }
+ error = _xlog_bread(log, start_block, 1, bp);
+ if (error)
+ goto out_put_bp;
+
j = start_block - balign;
}
@@ -1175,10 +1201,14 @@ xlog_write_log_records(
balign = BBTOB(ealign - start_block);
error = XFS_BUF_SET_PTR(bp, offset + balign,
BBTOB(sectbb));
- if (!error)
- error = xlog_bread(log, ealign, sectbb, bp);
- if (!error)
- error = XFS_BUF_SET_PTR(bp, offset, bufblks);
+ if (error)
+ break;
+
+ error = _xlog_bread(log, ealign, sectbb, bp);
+ if (error)
+ break;
+
+ error = XFS_BUF_SET_PTR(bp, offset, bufblks);
if (error)
break;
}
@@ -1195,6 +1225,8 @@ xlog_write_log_records(
start_block += endcount;
j = 0;
}
+
+ out_put_bp:
xlog_put_bp(bp);
return error;
}
@@ -3481,9 +3513,11 @@ xlog_do_recovery_pass(
hbp = xlog_get_bp(log, 1);
if (!hbp)
return ENOMEM;
- if ((error = xlog_bread(log, tail_blk, 1, hbp)))
+
+ error = xlog_bread(log, tail_blk, 1, hbp, &offset);
+ if (error)
goto bread_err1;
- offset = xlog_align(log, tail_blk, 1, hbp);
+
rhead = (xlog_rec_header_t *)offset;
error = xlog_valid_rec_header(log, rhead, tail_blk);
if (error)
@@ -3517,9 +3551,10 @@ xlog_do_recovery_pass(
memset(rhash, 0, sizeof(rhash));
if (tail_blk <= head_blk) {
for (blk_no = tail_blk; blk_no < head_blk; ) {
- if ((error = xlog_bread(log, blk_no, hblks, hbp)))
+ error = xlog_bread(log, blk_no, hblks, hbp, &offset);
+ if (error)
goto bread_err2;
- offset = xlog_align(log, blk_no, hblks, hbp);
+
rhead = (xlog_rec_header_t *)offset;
error = xlog_valid_rec_header(log, rhead, blk_no);
if (error)
@@ -3527,10 +3562,11 @@ xlog_do_recovery_pass(
/* blocks in data section */
bblks = (int)BTOBB(be32_to_cpu(rhead->h_len));
- error = xlog_bread(log, blk_no + hblks, bblks, dbp);
+ error = xlog_bread(log, blk_no + hblks, bblks, dbp,
+ &offset);
if (error)
goto bread_err2;
- offset = xlog_align(log, blk_no + hblks, bblks, dbp);
+
xlog_unpack_data(rhead, offset, log);
if ((error = xlog_recover_process_data(log,
rhash, rhead, offset, pass)))
@@ -3553,10 +3589,10 @@ xlog_do_recovery_pass(
wrapped_hblks = 0;
if (blk_no + hblks <= log->l_logBBsize) {
/* Read header in one read */
- error = xlog_bread(log, blk_no, hblks, hbp);
+ error = xlog_bread(log, blk_no, hblks, hbp,
+ &offset);
if (error)
goto bread_err2;
- offset = xlog_align(log, blk_no, hblks, hbp);
} else {
/* This LR is split across physical log end */
if (blk_no != log->l_logBBsize) {
@@ -3564,12 +3600,13 @@ xlog_do_recovery_pass(
ASSERT(blk_no <= INT_MAX);
split_hblks = log->l_logBBsize - (int)blk_no;
ASSERT(split_hblks > 0);
- if ((error = xlog_bread(log, blk_no,
- split_hblks, hbp)))
+ error = xlog_bread(log, blk_no,
+ split_hblks, hbp,
+ &offset);
+ if (error)
goto bread_err2;
- offset = xlog_align(log, blk_no,
- split_hblks, hbp);
}
+
/*
* Note: this black magic still works with
* large sector sizes (non-512) only because:
@@ -3587,14 +3624,18 @@ xlog_do_recovery_pass(
error = XFS_BUF_SET_PTR(hbp,
bufaddr + BBTOB(split_hblks),
BBTOB(hblks - split_hblks));
- if (!error)
- error = xlog_bread(log, 0,
- wrapped_hblks, hbp);
- if (!error)
- error = XFS_BUF_SET_PTR(hbp, bufaddr,
+ if (error)
+ goto bread_err2;
+
+ error = _xlog_bread(log, 0, wrapped_hblks, hbp);
+ if (error)
+ goto bread_err2;
+
+ error = XFS_BUF_SET_PTR(hbp, bufaddr,
BBTOB(hblks));
if (error)
goto bread_err2;
+
if (!offset)
offset = xlog_align(log, 0,
wrapped_hblks, hbp);
@@ -3610,10 +3651,10 @@ xlog_do_recovery_pass(
/* Read in data for log record */
if (blk_no + bblks <= log->l_logBBsize) {
- error = xlog_bread(log, blk_no, bblks, dbp);
+ error = xlog_bread(log, blk_no, bblks, dbp,
+ &offset);
if (error)
goto bread_err2;
- offset = xlog_align(log, blk_no, bblks, dbp);
} else {
/* This log record is split across the
* physical end of log */
@@ -3627,12 +3668,13 @@ xlog_do_recovery_pass(
split_bblks =
log->l_logBBsize - (int)blk_no;
ASSERT(split_bblks > 0);
- if ((error = xlog_bread(log, blk_no,
- split_bblks, dbp)))
+ error = xlog_bread(log, blk_no,
+ split_bblks, dbp,
+ &offset);
+ if (error)
goto bread_err2;
- offset = xlog_align(log, blk_no,
- split_bblks, dbp);
}
+
/*
* Note: this black magic still works with
* large sector sizes (non-512) only because:
@@ -3649,15 +3691,19 @@ xlog_do_recovery_pass(
error = XFS_BUF_SET_PTR(dbp,
bufaddr + BBTOB(split_bblks),
BBTOB(bblks - split_bblks));
- if (!error)
- error = xlog_bread(log, wrapped_hblks,
- bblks - split_bblks,
- dbp);
- if (!error)
- error = XFS_BUF_SET_PTR(dbp, bufaddr,
- h_size);
if (error)
goto bread_err2;
+
+ error = _xlog_bread(log, wrapped_hblks,
+ bblks - split_bblks,
+ dbp);
+ if (error)
+ goto bread_err2;
+
+ error = XFS_BUF_SET_PTR(dbp, bufaddr, h_size);
+ if (error)
+ goto bread_err2;
+
if (!offset)
offset = xlog_align(log, wrapped_hblks,
bblks - split_bblks, dbp);
@@ -3674,17 +3720,21 @@ xlog_do_recovery_pass(
/* read first part of physical log */
while (blk_no < head_blk) {
- if ((error = xlog_bread(log, blk_no, hblks, hbp)))
+ error = xlog_bread(log, blk_no, hblks, hbp, &offset);
+ if (error)
goto bread_err2;
- offset = xlog_align(log, blk_no, hblks, hbp);
+
rhead = (xlog_rec_header_t *)offset;
error = xlog_valid_rec_header(log, rhead, blk_no);
if (error)
goto bread_err2;
+
bblks = (int)BTOBB(be32_to_cpu(rhead->h_len));
- if ((error = xlog_bread(log, blk_no+hblks, bblks, dbp)))
+ error = xlog_bread(log, blk_no+hblks, bblks, dbp,
+ &offset);
+ if (error)
goto bread_err2;
- offset = xlog_align(log, blk_no+hblks, bblks, dbp);
+
xlog_unpack_data(rhead, offset, log);
if ((error = xlog_recover_process_data(log, rhash,
rhead, offset, pass)))
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 02/13] xfs: remove m_litino
2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
2009-02-10 20:22 ` [PATCH 01/13] xfs: cleanup xlog_bread Christoph Hellwig
@ 2009-02-10 20:22 ` Christoph Hellwig
2009-02-10 20:22 ` [PATCH 03/13] xfs: remove m_attroffset Christoph Hellwig
` (10 subsequent siblings)
12 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
To: xfs
[-- Attachment #1: xfs-kill-m_litino --]
[-- Type: text/plain, Size: 2188 bytes --]
With the upcoming v3 inodes the inode data/attr area size needs to be
calculated for each specific inode, so we can't cache it in the superblock
anymore.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: xfs/fs/xfs/xfs_dinode.h
===================================================================
--- xfs.orig/fs/xfs/xfs_dinode.h 2009-02-09 19:15:18.816069935 +0100
+++ xfs/fs/xfs/xfs_dinode.h 2009-02-09 19:15:29.082068921 +0100
@@ -103,7 +103,9 @@ typedef enum xfs_dinode_fmt {
/*
* Inode size for given fs.
*/
-#define XFS_LITINO(mp) ((mp)->m_litino)
+#define XFS_LITINO(mp) \
+ ((int)(((mp)->m_sb.sb_inodesize) - sizeof(struct xfs_dinode)))
+
#define XFS_BROOT_SIZE_ADJ \
(XFS_BTREE_LBLOCK_LEN - sizeof(xfs_bmdr_block_t))
Index: xfs/fs/xfs/xfs_mount.c
===================================================================
--- xfs.orig/fs/xfs/xfs_mount.c 2009-02-09 19:15:18.820068559 +0100
+++ xfs/fs/xfs/xfs_mount.c 2009-02-09 19:15:29.083069118 +0100
@@ -574,7 +574,6 @@ xfs_mount_common(xfs_mount_t *mp, xfs_sb
mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT;
mp->m_agno_log = xfs_highbit32(sbp->sb_agcount - 1) + 1;
mp->m_agino_log = sbp->sb_inopblog + sbp->sb_agblklog;
- mp->m_litino = sbp->sb_inodesize - sizeof(struct xfs_dinode);
mp->m_blockmask = sbp->sb_blocksize - 1;
mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG;
mp->m_blockwmask = mp->m_blockwsize - 1;
Index: xfs/fs/xfs/xfs_mount.h
===================================================================
--- xfs.orig/fs/xfs/xfs_mount.h 2009-02-09 19:15:18.826069182 +0100
+++ xfs/fs/xfs/xfs_mount.h 2009-02-09 19:15:29.084069385 +0100
@@ -281,7 +281,6 @@ typedef struct xfs_mount {
uint m_attr_node_ents; /* #entries in attr danode */
int m_ialloc_inos; /* inodes in inode allocation */
int m_ialloc_blks; /* blocks in inode allocation */
- int m_litino; /* size of inode union area */
int m_inoalign_mask;/* mask sb_inoalignmt if used */
uint m_qflags; /* quota status flags */
xfs_trans_reservations_t m_reservations;/* precomputed res values */
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 03/13] xfs: remove m_attroffset
2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
2009-02-10 20:22 ` [PATCH 01/13] xfs: cleanup xlog_bread Christoph Hellwig
2009-02-10 20:22 ` [PATCH 02/13] xfs: remove m_litino Christoph Hellwig
@ 2009-02-10 20:22 ` Christoph Hellwig
2009-02-10 20:22 ` [PATCH 04/13] xfs: take inode version into account in XFS_LITINO Christoph Hellwig
` (9 subsequent siblings)
12 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
To: xfs
[-- Attachment #1: xfs-xfs_default_attroffset --]
[-- Type: text/plain, Size: 6676 bytes --]
With the upcoming v3 inodes the default attroffset needs to be calculated
for each specific inode, so we can't cache it in the superblock anymore.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: xfs/fs/xfs/xfs_mount.c
===================================================================
--- xfs.orig/fs/xfs/xfs_mount.c 2009-02-09 19:15:29.083069118 +0100
+++ xfs/fs/xfs/xfs_mount.c 2009-02-09 19:15:35.578944518 +0100
@@ -566,6 +566,9 @@ xfs_readsb(xfs_mount_t *mp, int flags)
STATIC void
xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp)
{
+ ASSERT(sbp->sb_inodesize == 256 || sbp->sb_inodesize == 512 ||
+ sbp->sb_inodesize == 1024 || sbp->sb_inodesize == 2048);
+
mp->m_agfrotor = mp->m_agirotor = 0;
spin_lock_init(&mp->m_agirotor_lock);
mp->m_maxagi = mp->m_sb.sb_agcount;
@@ -578,27 +581,6 @@ xfs_mount_common(xfs_mount_t *mp, xfs_sb
mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG;
mp->m_blockwmask = mp->m_blockwsize - 1;
- /*
- * Setup for attributes, in case they get created.
- * This value is for inodes getting attributes for the first time,
- * the per-inode value is for old attribute values.
- */
- ASSERT(sbp->sb_inodesize >= 256 && sbp->sb_inodesize <= 2048);
- switch (sbp->sb_inodesize) {
- case 256:
- mp->m_attroffset = XFS_LITINO(mp) -
- XFS_BMDR_SPACE_CALC(MINABTPTRS);
- break;
- case 512:
- case 1024:
- case 2048:
- mp->m_attroffset = XFS_BMDR_SPACE_CALC(6 * MINABTPTRS);
- break;
- default:
- ASSERT(0);
- }
- ASSERT(mp->m_attroffset < XFS_LITINO(mp));
-
mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 1);
mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 0);
mp->m_alloc_mnr[0] = mp->m_alloc_mxr[0] / 2;
Index: xfs/fs/xfs/xfs_attr_leaf.c
===================================================================
--- xfs.orig/fs/xfs/xfs_attr_leaf.c 2009-02-09 19:15:18.754098923 +0100
+++ xfs/fs/xfs/xfs_attr_leaf.c 2009-02-09 19:15:35.580944493 +0100
@@ -155,7 +155,8 @@ xfs_attr_shortform_bytesfit(xfs_inode_t
* minimum offset only needs to be the space required for
* the btree root.
*/
- if (!dp->i_d.di_forkoff && dp->i_df.if_bytes > mp->m_attroffset)
+ if (!dp->i_d.di_forkoff && dp->i_df.if_bytes >
+ xfs_default_attroffset(dp))
dsize = XFS_BMDR_SPACE_CALC(MINDBTPTRS);
break;
Index: xfs/fs/xfs/xfs_bmap.c
===================================================================
--- xfs.orig/fs/xfs/xfs_bmap.c 2009-02-09 19:15:18.758069609 +0100
+++ xfs/fs/xfs/xfs_bmap.c 2009-02-09 19:15:35.583944247 +0100
@@ -3577,6 +3577,27 @@ xfs_bmap_extents_to_btree(
}
/*
+ * Calculate the default attribute fork offset for newly created inodes.
+ */
+uint
+xfs_default_attroffset(
+ struct xfs_inode *ip)
+{
+ struct xfs_mount *mp = ip->i_mount;
+ uint offset;
+
+ if (mp->m_sb.sb_inodesize == 256) {
+ offset = XFS_LITINO(mp) -
+ XFS_BMDR_SPACE_CALC(MINABTPTRS);
+ } else {
+ offset = XFS_BMDR_SPACE_CALC(6 * MINABTPTRS);
+ }
+
+ ASSERT(offset < XFS_LITINO(mp));
+ return offset;
+}
+
+/*
* Helper routine to reset inode di_forkoff field when switching
* attribute fork from local to extent format - we reset it where
* possible to make space available for inline data fork extents.
@@ -3588,15 +3609,18 @@ xfs_bmap_forkoff_reset(
int whichfork)
{
if (whichfork == XFS_ATTR_FORK &&
- (ip->i_d.di_format != XFS_DINODE_FMT_DEV) &&
- (ip->i_d.di_format != XFS_DINODE_FMT_UUID) &&
- (ip->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
- ((mp->m_attroffset >> 3) > ip->i_d.di_forkoff)) {
- ip->i_d.di_forkoff = mp->m_attroffset >> 3;
- ip->i_df.if_ext_max = XFS_IFORK_DSIZE(ip) /
- (uint)sizeof(xfs_bmbt_rec_t);
- ip->i_afp->if_ext_max = XFS_IFORK_ASIZE(ip) /
- (uint)sizeof(xfs_bmbt_rec_t);
+ ip->i_d.di_format != XFS_DINODE_FMT_DEV &&
+ ip->i_d.di_format != XFS_DINODE_FMT_UUID &&
+ ip->i_d.di_format != XFS_DINODE_FMT_BTREE) {
+ uint dfl_forkoff = xfs_default_attroffset(ip) >> 3;
+
+ if (dfl_forkoff > ip->i_d.di_forkoff) {
+ ip->i_d.di_forkoff = dfl_forkoff;
+ ip->i_df.if_ext_max =
+ XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t);
+ ip->i_afp->if_ext_max =
+ XFS_IFORK_ASIZE(ip) / sizeof(xfs_bmbt_rec_t);
+ }
}
}
@@ -4065,7 +4089,7 @@ xfs_bmap_add_attrfork(
case XFS_DINODE_FMT_BTREE:
ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size);
if (!ip->i_d.di_forkoff)
- ip->i_d.di_forkoff = mp->m_attroffset >> 3;
+ ip->i_d.di_forkoff = xfs_default_attroffset(ip) >> 3;
else if (mp->m_flags & XFS_MOUNT_ATTR2)
version = 2;
break;
@@ -4212,12 +4236,12 @@ xfs_bmap_compute_maxlevels(
* (a signed 16-bit number, xfs_aextnum_t).
*
* Note that we can no longer assume that if we are in ATTR1 that
- * the fork offset of all the inodes will be (m_attroffset >> 3)
- * because we could have mounted with ATTR2 and then mounted back
- * with ATTR1, keeping the di_forkoff's fixed but probably at
- * various positions. Therefore, for both ATTR1 and ATTR2
- * we have to assume the worst case scenario of a minimum size
- * available.
+ * the fork offset of all the inodes will be
+ * (xfs_default_attroffset(ip) >> 3) because we could have mounted
+ * with ATTR2 and then mounted back with ATTR1, keeping the
+ * di_forkoff's fixed but probably at various positions. Therefore,
+ * for both ATTR1 and ATTR2 we have to assume the worst case scenario
+ * of a minimum size available.
*/
if (whichfork == XFS_DATA_FORK) {
maxleafents = MAXEXTNUM;
Index: xfs/fs/xfs/xfs_bmap.h
===================================================================
--- xfs.orig/fs/xfs/xfs_bmap.h 2009-02-09 19:15:18.763069338 +0100
+++ xfs/fs/xfs/xfs_bmap.h 2009-02-09 19:15:35.583944247 +0100
@@ -338,6 +338,10 @@ xfs_check_nostate_extents(
xfs_extnum_t idx,
xfs_extnum_t num);
+uint
+xfs_default_attroffset(
+ struct xfs_inode *ip);
+
#ifdef __KERNEL__
/*
Index: xfs/fs/xfs/xfs_mount.h
===================================================================
--- xfs.orig/fs/xfs/xfs_mount.h 2009-02-09 19:15:29.084069385 +0100
+++ xfs/fs/xfs/xfs_mount.h 2009-02-09 19:15:35.584944583 +0100
@@ -276,7 +276,6 @@ typedef struct xfs_mount {
int m_fixedfsid[2]; /* unchanged for life of FS */
uint m_dmevmask; /* DMI events for this FS */
__uint64_t m_flags; /* global mount flags */
- uint m_attroffset; /* inode attribute offset */
uint m_dir_node_ents; /* #entries in a dir danode */
uint m_attr_node_ents; /* #entries in attr danode */
int m_ialloc_inos; /* inodes in inode allocation */
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 04/13] xfs: take inode version into account in XFS_LITINO
2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
` (2 preceding siblings ...)
2009-02-10 20:22 ` [PATCH 03/13] xfs: remove m_attroffset Christoph Hellwig
@ 2009-02-10 20:22 ` Christoph Hellwig
2009-02-10 20:22 ` [PATCH 05/13] xfs: add CRC infrastructure Christoph Hellwig
` (8 subsequent siblings)
12 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
To: xfs
[-- Attachment #1: xfs-XFS_LITINO-per-inode --]
[-- Type: text/plain, Size: 4137 bytes --]
Add a version argument to XFS_LITINO so that it can return different values
depending on the inode version. This is required for the upcoming v3 inodes
with a larger fixed layout dinode.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: xfs/fs/xfs/xfs_dinode.h
===================================================================
--- xfs.orig/fs/xfs/xfs_dinode.h 2009-02-09 19:15:29.082068921 +0100
+++ xfs/fs/xfs/xfs_dinode.h 2009-02-09 19:15:37.179944489 +0100
@@ -103,7 +103,7 @@ typedef enum xfs_dinode_fmt {
/*
* Inode size for given fs.
*/
-#define XFS_LITINO(mp) \
+#define XFS_LITINO(version, mp) \
((int)(((mp)->m_sb.sb_inodesize) - sizeof(struct xfs_dinode)))
#define XFS_BROOT_SIZE_ADJ \
@@ -118,10 +118,10 @@ typedef enum xfs_dinode_fmt {
#define XFS_DFORK_DSIZE(dip,mp) \
(XFS_DFORK_Q(dip) ? \
XFS_DFORK_BOFF(dip) : \
- XFS_LITINO(mp))
+ XFS_LITINO((dip)->di_version, mp))
#define XFS_DFORK_ASIZE(dip,mp) \
(XFS_DFORK_Q(dip) ? \
- XFS_LITINO(mp) - XFS_DFORK_BOFF(dip) : \
+ XFS_LITINO((dip)->di_version, mp) - XFS_DFORK_BOFF(dip) : \
0)
#define XFS_DFORK_SIZE(dip,mp,w) \
((w) == XFS_DATA_FORK ? \
Index: xfs/fs/xfs/xfs_attr_leaf.c
===================================================================
--- xfs.orig/fs/xfs/xfs_attr_leaf.c 2009-02-09 19:15:35.580944493 +0100
+++ xfs/fs/xfs/xfs_attr_leaf.c 2009-02-09 19:15:37.185944554 +0100
@@ -127,7 +127,8 @@ xfs_attr_shortform_bytesfit(xfs_inode_t
int dsize;
xfs_mount_t *mp = dp->i_mount;
- offset = (XFS_LITINO(mp) - bytes) >> 3; /* rounded down */
+ /* rounded down */
+ offset = (XFS_LITINO(dp->i_d.di_version, mp) - bytes) >> 3;
switch (dp->i_d.di_format) {
case XFS_DINODE_FMT_DEV:
@@ -185,7 +186,8 @@ xfs_attr_shortform_bytesfit(xfs_inode_t
minforkoff = roundup(minforkoff, 8) >> 3;
/* attr fork btree root can have at least this many key/ptr pairs */
- maxforkoff = XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(MINABTPTRS);
+ maxforkoff = XFS_LITINO(dp->i_d.di_version, mp) -
+ XFS_BMDR_SPACE_CALC(MINABTPTRS);
maxforkoff = maxforkoff >> 3; /* rounded down */
if (offset >= minforkoff && offset < maxforkoff)
Index: xfs/fs/xfs/xfs_bmap.c
===================================================================
--- xfs.orig/fs/xfs/xfs_bmap.c 2009-02-09 19:15:35.583944247 +0100
+++ xfs/fs/xfs/xfs_bmap.c 2009-02-09 19:15:37.192068867 +0100
@@ -3587,13 +3587,13 @@ xfs_default_attroffset(
uint offset;
if (mp->m_sb.sb_inodesize == 256) {
- offset = XFS_LITINO(mp) -
+ offset = XFS_LITINO(ip->i_d.di_version, mp) -
XFS_BMDR_SPACE_CALC(MINABTPTRS);
} else {
offset = XFS_BMDR_SPACE_CALC(6 * MINABTPTRS);
}
- ASSERT(offset < XFS_LITINO(mp));
+ ASSERT(offset < XFS_LITINO(ip->i_d.di_version, mp));
return offset;
}
Index: xfs/fs/xfs/xfs_inode.h
===================================================================
--- xfs.orig/fs/xfs/xfs_inode.h 2009-02-09 19:15:18.690944589 +0100
+++ xfs/fs/xfs/xfs_inode.h 2009-02-09 19:15:37.193072276 +0100
@@ -180,10 +180,11 @@ typedef struct xfs_icdinode {
#define XFS_IFORK_DSIZE(ip) \
(XFS_IFORK_Q(ip) ? \
XFS_IFORK_BOFF(ip) : \
- XFS_LITINO((ip)->i_mount))
+ XFS_LITINO((ip)->i_d.di_version, (ip)->i_mount))
#define XFS_IFORK_ASIZE(ip) \
(XFS_IFORK_Q(ip) ? \
- XFS_LITINO((ip)->i_mount) - XFS_IFORK_BOFF(ip) : \
+ XFS_LITINO((ip)->i_d.di_version, (ip)->i_mount) - \
+ XFS_IFORK_BOFF(ip) : \
0)
#define XFS_IFORK_SIZE(ip,w) \
((w) == XFS_DATA_FORK ? \
Index: xfs/fs/xfs/xfs_vnodeops.c
===================================================================
--- xfs.orig/fs/xfs/xfs_vnodeops.c 2009-02-09 19:15:18.700944674 +0100
+++ xfs/fs/xfs/xfs_vnodeops.c 2009-02-09 19:15:37.194069750 +0100
@@ -2210,7 +2210,7 @@ xfs_symlink(
* The symlink will fit into the inode data fork?
* There can't be any attributes so we get the whole variable part.
*/
- if (pathlen <= XFS_LITINO(mp))
+ if (pathlen <= XFS_LITINO(dp->i_d.di_version, mp))
fs_blocks = 0;
else
fs_blocks = XFS_B_TO_FSB(mp, pathlen);
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 05/13] xfs: add CRC infrastructure
2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
` (3 preceding siblings ...)
2009-02-10 20:22 ` [PATCH 04/13] xfs: take inode version into account in XFS_LITINO Christoph Hellwig
@ 2009-02-10 20:22 ` Christoph Hellwig
2009-02-12 6:10 ` Josef 'Jeff' Sipek
2009-02-10 20:22 ` [PATCH 06/13] xfs: add support for large btree blocks Christoph Hellwig
` (7 subsequent siblings)
12 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
To: xfs
[-- Attachment #1: xfs-crc-bit --]
[-- Type: text/plain, Size: 8099 bytes --]
- add a mount feature bit for CRC enabled filesystems
- add some helpers for generating and verifying the CRCs
- add a copy_uuid helper
- add a pre-io callback to xfs_buf for calculating the CRCs
The checksumming helpers are losely based on similar ones in sctp,
all other bits come from Dave Chinner.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: xfs/fs/xfs/Kconfig
===================================================================
--- xfs.orig/fs/xfs/Kconfig 2009-02-03 16:52:11.665916316 +0100
+++ xfs/fs/xfs/Kconfig 2009-02-05 19:04:41.218218577 +0100
@@ -2,6 +2,7 @@ config XFS_FS
tristate "XFS filesystem support"
depends on BLOCK
select EXPORTFS
+ select LIBCRC32C
help
XFS is a high performance journaling filesystem which originated
on the SGI IRIX platform. It is completely multi-threaded, can
Index: xfs/fs/xfs/linux-2.6/xfs_linux.h
===================================================================
--- xfs.orig/fs/xfs/linux-2.6/xfs_linux.h 2009-02-05 17:53:06.742088475 +0100
+++ xfs/fs/xfs/linux-2.6/xfs_linux.h 2009-02-05 19:04:31.269945065 +0100
@@ -72,6 +72,7 @@
#include <linux/random.h>
#include <linux/ctype.h>
#include <linux/writeback.h>
+#include <linux/crc32c.h>
#include <asm/page.h>
#include <asm/div64.h>
Index: xfs/fs/xfs/xfs_sb.h
===================================================================
--- xfs.orig/fs/xfs/xfs_sb.h 2009-02-03 16:52:12.358436358 +0100
+++ xfs/fs/xfs/xfs_sb.h 2009-02-05 19:04:31.272973243 +0100
@@ -80,10 +80,12 @@ struct xfs_mount;
#define XFS_SB_VERSION2_RESERVED4BIT 0x00000004
#define XFS_SB_VERSION2_ATTR2BIT 0x00000008 /* Inline attr rework */
#define XFS_SB_VERSION2_PARENTBIT 0x00000010 /* parent pointers */
+#define XFS_SB_VERSION2_CRCBIT 0x00000020 /* metadata has CRCs */
#define XFS_SB_VERSION2_OKREALFBITS \
(XFS_SB_VERSION2_LAZYSBCOUNTBIT | \
- XFS_SB_VERSION2_ATTR2BIT)
+ XFS_SB_VERSION2_ATTR2BIT | \
+ XFS_SB_VERSION2_CRCBIT)
#define XFS_SB_VERSION2_OKSASHFBITS \
(0)
#define XFS_SB_VERSION2_OKREALBITS \
@@ -495,6 +497,12 @@ static inline void xfs_sb_version_remove
sbp->sb_versionnum &= ~XFS_SB_VERSION_MOREBITSBIT;
}
+static inline int xfs_sb_version_hascrc(xfs_sb_t *sbp)
+{
+ return (xfs_sb_version_hasmorebits(sbp) &&
+ (sbp->sb_features2 & XFS_SB_VERSION2_CRCBIT));
+}
+
/*
* end of superblock version macros
*/
Index: xfs/fs/xfs/linux-2.6/xfs_buf.c
===================================================================
--- xfs.orig/fs/xfs/linux-2.6/xfs_buf.c 2009-02-05 17:53:06.643944544 +0100
+++ xfs/fs/xfs/linux-2.6/xfs_buf.c 2009-02-05 19:04:31.273973789 +0100
@@ -1108,6 +1108,14 @@ _xfs_buf_ioapply(
(bp->b_flags & XBF_READ_AHEAD) ? READA : READ;
}
+ /*
+ * call out to buffer specific pre-write I/O functions. Used for
+ * validation of buffers and CRC calculations prior to I/O issue.
+ */
+ if (bp->b_io_callback && (bp->b_flags & XBF_WRITE))
+ bp->b_io_callback(bp);
+
+
/* Special code path for reading a sub page size buffer in --
* we populate up the whole page, and hence the other metadata
* in the same page. This optimization is only valid when the
Index: xfs/fs/xfs/linux-2.6/xfs_buf.h
===================================================================
--- xfs.orig/fs/xfs/linux-2.6/xfs_buf.h 2009-01-21 21:03:27.825295146 +0100
+++ xfs/fs/xfs/linux-2.6/xfs_buf.h 2009-02-05 19:04:31.273973789 +0100
@@ -174,6 +174,8 @@ typedef struct xfs_buf {
unsigned int b_offset; /* page offset in first page */
struct page **b_pages; /* array of page pointers */
struct page *b_page_array[XB_PAGES]; /* inline pages */
+ void (*b_io_callback)(struct xfs_buf *);
+ /* pre-write I/O callback */
#ifdef XFS_BUF_LOCK_TRACKING
int b_last_holder;
#endif
@@ -236,6 +238,16 @@ static inline int xfs_buf_geterror(xfs_b
/* Buffer Utility Routines */
extern xfs_caddr_t xfs_buf_offset(xfs_buf_t *, size_t);
+/*
+ * Set the function that should be called immediately prior
+ * to a write I/O being issued on this buffer.
+ */
+static inline void
+xfs_buf_set_io_callback(xfs_buf_t *bp, void (*func)(xfs_buf_t *))
+{
+ bp->b_io_callback = func;
+}
+
/* Pinning Buffer Storage in Memory */
extern void xfs_buf_pin(xfs_buf_t *);
extern void xfs_buf_unpin(xfs_buf_t *);
Index: xfs/fs/xfs/support/uuid.c
===================================================================
--- xfs.orig/fs/xfs/support/uuid.c 2009-01-21 21:03:27.838294778 +0100
+++ xfs/fs/xfs/support/uuid.c 2009-02-05 19:04:31.274944514 +0100
@@ -72,6 +72,12 @@ uuid_equal(uuid_t *uuid1, uuid_t *uuid2)
return memcmp(uuid1, uuid2, sizeof(uuid_t)) ? 0 : 1;
}
+void
+uuid_copy(uuid_t *dst, uuid_t *src)
+{
+ memcpy(dst, src, sizeof(uuid_t));
+}
+
/*
* Given a 128-bit uuid, return a 64-bit value by adding the top and bottom
* 64-bit words. NOTE: This function can not be changed EVER. Although
Index: xfs/fs/xfs/support/uuid.h
===================================================================
--- xfs.orig/fs/xfs/support/uuid.h 2009-01-21 21:03:27.838294778 +0100
+++ xfs/fs/xfs/support/uuid.h 2009-02-05 19:04:31.279944870 +0100
@@ -25,6 +25,7 @@ typedef struct {
extern void uuid_create_nil(uuid_t *uuid);
extern int uuid_is_nil(uuid_t *uuid);
extern int uuid_equal(uuid_t *uuid1, uuid_t *uuid2);
+extern void uuid_copy(uuid_t *dst, uuid_t *src);
extern void uuid_getnodeuniq(uuid_t *uuid, int fsid [2]);
extern __uint64_t uuid_hash64(uuid_t *uuid);
extern int uuid_table_insert(uuid_t *uuid);
Index: xfs/fs/xfs/xfs_cksum.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ xfs/fs/xfs/xfs_cksum.h 2009-02-05 19:04:31.282972630 +0100
@@ -0,0 +1,62 @@
+#ifndef _XFS_CKSUM_H
+#define _XFS_CKSUM_H 1
+
+#define XFS_CRC_SEED (~(__uint32_t)0)
+
+/*
+ * Calculate the intermediate checksum for a buffer that has the CRC field
+ * inside it. The offset of the 32bit crc fields is passed as the
+ * cksum_offset parameter.
+ */
+static inline __uint32_t
+xfs_start_cksum(char *buffer, size_t length, unsigned long cksum_offset)
+{
+ __uint32_t zero = 0;
+ __uint32_t crc;
+
+ /* Calculate CRC up to the checksum. */
+ crc = crc32c(XFS_CRC_SEED, buffer, cksum_offset);
+
+ /* Skip checksum field */
+ crc = crc32c(crc, &zero, sizeof(__u32));
+
+ /* Calculate the rest of the CRC. */
+ return crc32c(crc, &buffer[cksum_offset + sizeof(__be32)],
+ length - (cksum_offset + sizeof(__be32)));
+}
+
+/*
+ * Convert the intermediate checksum to the final ondisk format.
+ *
+ * Note that crc32c is already endianess agnostic, so no additional
+ * byte swap is needed.
+ */
+static inline __be32
+xfs_end_cksum(__uint32_t crc)
+{
+ return (__force __be32)~crc;
+}
+
+/*
+ * Helper to generate the checksum for a buffer.
+ */
+static inline void
+xfs_update_cksum(char *buffer, size_t length, unsigned long cksum_offset)
+{
+ __uint32_t crc = xfs_start_cksum(buffer, length, cksum_offset);
+
+ *(__be32 *)(buffer + cksum_offset) = xfs_end_cksum(crc);
+}
+
+/*
+ * Helper to verify the checksum for a buffer.
+ */
+static inline int
+xfs_verify_cksum(char *buffer, size_t length, unsigned long cksum_offset)
+{
+ __uint32_t crc = xfs_start_cksum(buffer, length, cksum_offset);
+
+ return *(__be32 *)(buffer + cksum_offset) == xfs_end_cksum(crc);
+}
+
+#endif /* _XFS_CKSUM_H */
Index: xfs/fs/xfs/xfs_mount.c
===================================================================
--- xfs.orig/fs/xfs/xfs_mount.c 2009-02-05 17:53:07.338944053 +0100
+++ xfs/fs/xfs/xfs_mount.c 2009-02-05 19:04:31.286943944 +0100
@@ -569,6 +569,11 @@ xfs_mount_common(xfs_mount_t *mp, xfs_sb
ASSERT(sbp->sb_inodesize == 256 || sbp->sb_inodesize == 512 ||
sbp->sb_inodesize == 1024 || sbp->sb_inodesize == 2048);
+ if (xfs_sb_version_hascrc(sbp))
+ printk("XFS: using CRCs\n");
+ else
+ printk("XFS: not using CRCs\n");
+
mp->m_agfrotor = mp->m_agirotor = 0;
spin_lock_init(&mp->m_agirotor_lock);
mp->m_maxagi = mp->m_sb.sb_agcount;
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 06/13] xfs: add support for large btree blocks
2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
` (4 preceding siblings ...)
2009-02-10 20:22 ` [PATCH 05/13] xfs: add CRC infrastructure Christoph Hellwig
@ 2009-02-10 20:22 ` Christoph Hellwig
2009-02-10 20:22 ` [PATCH 07/13] xfs: add CRC checks to the superblock Christoph Hellwig
` (6 subsequent siblings)
12 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
To: xfs
[-- Attachment #1: xfs-large-btree-blocks --]
[-- Type: text/plain, Size: 36929 bytes --]
Add support for larger btree blocks that contains a CRC32C checksum, a
filesystem uuid and block number for detecting filesystem consistency
and out of place writes.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: xfs/fs/xfs/xfs_btree.h
===================================================================
--- xfs.orig/fs/xfs/xfs_btree.h 2009-02-09 19:05:49.005068530 +0100
+++ xfs/fs/xfs/xfs_btree.h 2009-02-09 19:15:42.836068971 +0100
@@ -47,6 +47,10 @@ extern kmem_zone_t *xfs_btree_cur_zone;
*
* To get the size of the actual short or long form headers please use
* the size macros below. Never use sizeof(xfs_btree_block).
+ *
+ * The blkno, crc and uuid fields are only available in filesystems with
+ * the crc feature bit, and all accesses to them must be conditional on
+ * that flag.
*/
struct xfs_btree_block {
__be32 bb_magic; /* magic number for block type */
@@ -56,16 +60,32 @@ struct xfs_btree_block {
struct {
__be32 bb_leftsib;
__be32 bb_rightsib;
+
+ __be64 bb_blkno;
+ uuid_t bb_uuid;
+ __be32 bb_crc;
+ __be32 bb_pad; /* padding for alignment */
} s; /* short form pointers */
struct {
__be64 bb_leftsib;
__be64 bb_rightsib;
+
+ __be64 bb_blkno;
+ uuid_t bb_uuid;
+ __be32 bb_crc;
+ __be32 bb_pad; /* padding for alignment */
} l; /* long form pointers */
} bb_u; /* rest */
};
#define XFS_BTREE_SBLOCK_LEN 16 /* size of a short form block */
#define XFS_BTREE_LBLOCK_LEN 24 /* size of a long form block */
+#define XFS_BTREE_CRCBLOCK_ADD 32 /* size of blkno + crc + uuid */
+
+#define XFS_BTREE_SBLOCK_CRC_OFF \
+ offsetof(struct xfs_btree_block, bb_u.s.bb_crc)
+#define XFS_BTREE_LBLOCK_CRC_OFF \
+ offsetof(struct xfs_btree_block, bb_u.l.bb_crc)
/*
@@ -101,13 +121,11 @@ union xfs_btree_rec {
#define XFS_BB_NUMRECS 0x04
#define XFS_BB_LEFTSIB 0x08
#define XFS_BB_RIGHTSIB 0x10
+#define XFS_BB_BLKNO 0x20
#define XFS_BB_NUM_BITS 5
#define XFS_BB_ALL_BITS ((1 << XFS_BB_NUM_BITS) - 1)
-
-/*
- * Magic numbers for btree blocks.
- */
-extern const __uint32_t xfs_magics[];
+#define XFS_BB_NUM_BITS_CRC 8
+#define XFS_BB_ALL_BITS_CRC ((1 << XFS_BB_NUM_BITS_CRC) - 1)
/*
* Generic stats interface
@@ -275,6 +293,7 @@ typedef struct xfs_btree_cur
#define XFS_BTREE_LONG_PTRS (1<<0) /* pointers are 64bits long */
#define XFS_BTREE_ROOT_IN_INODE (1<<1) /* root may be variable size */
#define XFS_BTREE_LASTREC_UPDATE (1<<2) /* track last rec externally */
+#define XFS_BTREE_CRC_BLOCKS (1<<3) /* uses extended btree blocks */
#define XFS_BTREE_NOERROR 0
@@ -438,6 +457,12 @@ int xfs_btree_delete(struct xfs_btree_cu
int xfs_btree_get_rec(struct xfs_btree_cur *, union xfs_btree_rec **, int *);
/*
+ * CRC calculation is also needed for growfs.
+ */
+void xfs_btree_lblock_calc_crc(struct xfs_buf *);
+void xfs_btree_sblock_calc_crc(struct xfs_buf *);
+
+/*
* Internal btree helpers also used by xfs_bmap.c.
*/
void xfs_btree_log_block(struct xfs_btree_cur *, struct xfs_buf *, int);
Index: xfs/fs/xfs/xfs_bmap_btree.c
===================================================================
--- xfs.orig/fs/xfs/xfs_bmap_btree.c 2009-02-09 19:05:49.009069179 +0100
+++ xfs/fs/xfs/xfs_bmap_btree.c 2009-02-09 19:15:42.838069994 +0100
@@ -77,12 +77,20 @@ xfs_bmdr_to_bmbt(
xfs_bmbt_key_t *tkp;
__be64 *tpp;
- rblock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
+ if (xfs_sb_version_hascrc(&mp->m_sb))
+ rblock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
+ else
+ rblock->bb_magic = cpu_to_be32(XFS_BMAP_CRC_MAGIC);
rblock->bb_level = dblock->bb_level;
ASSERT(be16_to_cpu(rblock->bb_level) > 0);
rblock->bb_numrecs = dblock->bb_numrecs;
rblock->bb_u.l.bb_leftsib = cpu_to_be64(NULLDFSBNO);
rblock->bb_u.l.bb_rightsib = cpu_to_be64(NULLDFSBNO);
+ if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ rblock->bb_u.l.bb_blkno = cpu_to_be64(XFS_BUF_DADDR_NULL);
+ uuid_copy(&rblock->bb_u.l.bb_uuid, &mp->m_sb.sb_uuid);
+ rblock->bb_u.l.bb_pad = 0;
+ }
dmxr = xfs_bmdr_maxrecs(mp, dblocklen, 0);
fkp = XFS_BMDR_KEY_ADDR(dblock, 1);
tkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1);
@@ -441,10 +449,18 @@ xfs_bmbt_to_bmdr(
xfs_bmbt_key_t *tkp;
__be64 *tpp;
- ASSERT(be32_to_cpu(rblock->bb_magic) == XFS_BMAP_MAGIC);
+ if (xfs_sb_version_hascrc(&mp->m_sb))
+ ASSERT(be32_to_cpu(rblock->bb_magic) == XFS_BMAP_CRC_MAGIC);
+ else
+ ASSERT(be32_to_cpu(rblock->bb_magic) == XFS_BMAP_MAGIC);
ASSERT(be64_to_cpu(rblock->bb_u.l.bb_leftsib) == NULLDFSBNO);
ASSERT(be64_to_cpu(rblock->bb_u.l.bb_rightsib) == NULLDFSBNO);
ASSERT(be16_to_cpu(rblock->bb_level) > 0);
+ if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ ASSERT(uuid_equal(&rblock->bb_u.l.bb_uuid, &mp->m_sb.sb_uuid));
+ ASSERT(rblock->bb_u.l.bb_blkno ==
+ cpu_to_be64(XFS_BUF_DADDR_NULL));
+ }
dblock->bb_level = rblock->bb_level;
dblock->bb_numrecs = rblock->bb_numrecs;
dmxr = xfs_bmdr_maxrecs(mp, dblocklen, 0);
@@ -886,6 +902,8 @@ xfs_bmbt_init_cursor(
cur->bc_ops = &xfs_bmbt_ops;
cur->bc_flags = XFS_BTREE_LONG_PTRS | XFS_BTREE_ROOT_IN_INODE;
+ if (xfs_sb_version_hascrc(&mp->m_sb))
+ cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
cur->bc_private.b.forksize = XFS_IFORK_SIZE(ip, whichfork);
cur->bc_private.b.ip = ip;
Index: xfs/fs/xfs/xfs_bmap_btree.h
===================================================================
--- xfs.orig/fs/xfs/xfs_bmap_btree.h 2009-02-09 19:05:49.013068710 +0100
+++ xfs/fs/xfs/xfs_bmap_btree.h 2009-02-09 19:15:42.838069994 +0100
@@ -18,7 +18,8 @@
#ifndef __XFS_BMAP_BTREE_H__
#define __XFS_BMAP_BTREE_H__
-#define XFS_BMAP_MAGIC 0x424d4150 /* 'BMAP' */
+#define XFS_BMAP_MAGIC 0x424d4150 /* 'BMAP' */
+#define XFS_BMAP_CRC_MAGIC 0x424d4158
struct xfs_btree_cur;
struct xfs_btree_block;
@@ -144,10 +145,11 @@ typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_
/*
* Btree block header size depends on a superblock flag.
- *
- * (not quite yet, but soon)
*/
-#define XFS_BMBT_BLOCK_LEN(mp) XFS_BTREE_LBLOCK_LEN
+#define XFS_BMBT_BLOCK_LEN(mp) \
+ (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \
+ XFS_BTREE_LBLOCK_LEN + XFS_BTREE_CRCBLOCK_ADD : \
+ XFS_BTREE_LBLOCK_LEN)
#define XFS_BMBT_REC_ADDR(mp, block, index) \
((xfs_bmbt_rec_t *) \
@@ -194,12 +196,12 @@ typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_
#define XFS_BMAP_BROOT_PTR_ADDR(mp, bb, i, sz) \
XFS_BMBT_PTR_ADDR(mp, bb, i, xfs_bmbt_maxrecs(mp, sz, 0))
-#define XFS_BMAP_BROOT_SPACE_CALC(nrecs) \
- (int)(XFS_BTREE_LBLOCK_LEN + \
+#define XFS_BMAP_BROOT_SPACE_CALC(mp, nrecs) \
+ (int)(XFS_BMBT_BLOCK_LEN(mp) + \
((nrecs) * (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t))))
-#define XFS_BMAP_BROOT_SPACE(bb) \
- (XFS_BMAP_BROOT_SPACE_CALC(be16_to_cpu((bb)->bb_numrecs)))
+#define XFS_BMAP_BROOT_SPACE(mp, bb) \
+ (XFS_BMAP_BROOT_SPACE_CALC(mp, be16_to_cpu((bb)->bb_numrecs)))
#define XFS_BMDR_SPACE_CALC(nrecs) \
(int)(sizeof(xfs_bmdr_block_t) + \
((nrecs) * (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t))))
Index: xfs/fs/xfs/xfs_btree.c
===================================================================
--- xfs.orig/fs/xfs/xfs_btree.c 2009-02-09 19:05:49.018069067 +0100
+++ xfs/fs/xfs/xfs_btree.c 2009-02-09 19:15:42.842069176 +0100
@@ -39,6 +39,7 @@
#include "xfs_btree_trace.h"
#include "xfs_ialloc.h"
#include "xfs_error.h"
+#include "xfs_cksum.h"
/*
* Cursor allocation zone.
@@ -48,9 +49,13 @@ kmem_zone_t *xfs_btree_cur_zone;
/*
* Btree magic numbers.
*/
-const __uint32_t xfs_magics[XFS_BTNUM_MAX] = {
- XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, XFS_BMAP_MAGIC, XFS_IBT_MAGIC
+static const __uint32_t xfs_magics[2][XFS_BTNUM_MAX] = {
+ { XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, XFS_BMAP_MAGIC, XFS_IBT_MAGIC },
+ { XFS_ABTB_CRC_MAGIC, XFS_ABTC_CRC_MAGIC,
+ XFS_BMAP_CRC_MAGIC, XFS_IBT_CRC_MAGIC }
};
+#define xfs_btree_magic(cur) \
+ xfs_magics[!!((cur)->bc_flags & XFS_BTREE_CRC_BLOCKS)][cur->bc_btnum]
STATIC int /* error (0 or EFSCORRUPTED) */
@@ -64,8 +69,34 @@ xfs_btree_check_lblock(
struct xfs_mount *mp; /* file system mount point */
mp = cur->bc_mp;
+
+ if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ /*
+ * Validate the CRC of the btree block only if the block is
+ * clean (i.e. it just came from disk) and we have CRCs enabled.
+ *
+ * If we are called for an in inode root block don't check the
+ * crc because we only calculate it for real btree blocks on
+ * disk.
+ */
+ if (bp && !(XFS_BUF_ISWRITE(bp) || XFS_BUF_ISDELAYWRITE(bp)) &&
+ !xfs_verify_cksum(XFS_BUF_PTR(bp), XFS_BUF_SIZE(bp),
+ XFS_BTREE_LBLOCK_CRC_OFF)) {
+ XFS_CORRUPTION_ERROR("xfs_btree_check_lblock crc",
+ XFS_ERRLEVEL_LOW, mp, mp);
+ return XFS_ERROR(EFSCORRUPTED);
+ }
+
+ lblock_ok =
+ uuid_equal(&block->bb_u.l.bb_uuid, &mp->m_sb.sb_uuid) &&
+ block->bb_u.l.bb_blkno == cpu_to_be64(
+ bp ? XFS_BUF_ADDR(bp) : XFS_BUF_DADDR_NULL);
+ if (!lblock_ok)
+ goto test_error;
+ }
+
lblock_ok =
- be32_to_cpu(block->bb_magic) == xfs_magics[cur->bc_btnum] &&
+ be32_to_cpu(block->bb_magic) == xfs_btree_magic(cur) &&
be16_to_cpu(block->bb_level) == level &&
be16_to_cpu(block->bb_numrecs) <=
cur->bc_ops->get_maxrecs(cur, level) &&
@@ -77,6 +108,8 @@ xfs_btree_check_lblock(
(be64_to_cpu(block->bb_u.l.bb_rightsib) == NULLDFSBNO ||
XFS_FSB_SANITY_CHECK(mp,
be64_to_cpu(block->bb_u.l.bb_rightsib)));
+
+ test_error:
if (unlikely(XFS_TEST_ERROR(!lblock_ok, mp,
XFS_ERRTAG_BTREE_CHECK_LBLOCK,
XFS_RANDOM_BTREE_CHECK_LBLOCK))) {
@@ -96,16 +129,40 @@ xfs_btree_check_sblock(
int level, /* level of the btree block */
struct xfs_buf *bp) /* buffer containing block */
{
+ struct xfs_mount *mp; /* file system mount point */
struct xfs_buf *agbp; /* buffer for ag. freespace struct */
struct xfs_agf *agf; /* ag. freespace structure */
xfs_agblock_t agflen; /* native ag. freespace length */
int sblock_ok; /* block passes checks */
+ mp = cur->bc_mp;
agbp = cur->bc_private.a.agbp;
agf = XFS_BUF_TO_AGF(agbp);
agflen = be32_to_cpu(agf->agf_length);
+
+ if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ /*
+ * Validate the CRC of the btree block only if the block is
+ * clean (i.e. it just came from disk) and we have CRCs enabled.
+ */
+ if (!(XFS_BUF_ISWRITE(bp) || XFS_BUF_ISDELAYWRITE(bp)) &&
+ !xfs_verify_cksum(XFS_BUF_PTR(bp), XFS_BUF_SIZE(bp),
+ XFS_BTREE_SBLOCK_CRC_OFF)) {
+ XFS_CORRUPTION_ERROR("xfs_btree_check_sblock crc",
+ XFS_ERRLEVEL_LOW, mp, mp);
+ return XFS_ERROR(EFSCORRUPTED);
+ }
+
+ sblock_ok =
+ uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid) &&
+ block->bb_u.s.bb_blkno == cpu_to_be64(
+ bp ? XFS_BUF_ADDR(bp) : XFS_BUF_DADDR_NULL);
+ if (!sblock_ok)
+ goto test_error;
+ }
+
sblock_ok =
- be32_to_cpu(block->bb_magic) == xfs_magics[cur->bc_btnum] &&
+ be32_to_cpu(block->bb_magic) == xfs_btree_magic(cur) &&
be16_to_cpu(block->bb_level) == level &&
be16_to_cpu(block->bb_numrecs) <=
cur->bc_ops->get_maxrecs(cur, level) &&
@@ -115,13 +172,15 @@ xfs_btree_check_sblock(
(be32_to_cpu(block->bb_u.s.bb_rightsib) == NULLAGBLOCK ||
be32_to_cpu(block->bb_u.s.bb_rightsib) < agflen) &&
block->bb_u.s.bb_rightsib;
- if (unlikely(XFS_TEST_ERROR(!sblock_ok, cur->bc_mp,
+
+ test_error:
+ if (unlikely(XFS_TEST_ERROR(!sblock_ok, mp,
XFS_ERRTAG_BTREE_CHECK_SBLOCK,
XFS_RANDOM_BTREE_CHECK_SBLOCK))) {
if (bp)
xfs_buftrace("SBTREE ERROR", bp);
XFS_ERROR_REPORT("xfs_btree_check_sblock", XFS_ERRLEVEL_LOW,
- cur->bc_mp);
+ mp);
return XFS_ERROR(EFSCORRUPTED);
}
return 0;
@@ -272,18 +331,28 @@ xfs_btree_dup_cursor(
for (i = 0; i < new->bc_nlevels; i++) {
new->bc_ptrs[i] = cur->bc_ptrs[i];
new->bc_ra[i] = cur->bc_ra[i];
- if ((bp = cur->bc_bufs[i])) {
- if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
- XFS_BUF_ADDR(bp), mp->m_bsize, 0, &bp))) {
+ bp = cur->bc_bufs[i];
+ if (bp) {
+ error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
+ XFS_BUF_ADDR(bp), mp->m_bsize, 0, &bp);
+ if (error) {
xfs_btree_del_cursor(new, error);
*ncur = NULL;
return error;
}
- new->bc_bufs[i] = bp;
+
ASSERT(bp);
ASSERT(!XFS_BUF_GETERROR(bp));
- } else
- new->bc_bufs[i] = NULL;
+
+ if (cur->bc_flags & XFS_BTREE_CRC_BLOCKS) {
+ xfs_buf_set_io_callback(bp,
+ (cur->bc_flags & XFS_BTREE_LONG_PTRS) ?
+ xfs_btree_lblock_calc_crc :
+ xfs_btree_sblock_calc_crc);
+ }
+
+ }
+ new->bc_bufs[i] = bp;
}
*ncur = new;
return 0;
@@ -324,9 +393,17 @@ xfs_btree_dup_cursor(
*/
static inline size_t xfs_btree_block_len(struct xfs_btree_cur *cur)
{
- return (cur->bc_flags & XFS_BTREE_LONG_PTRS) ?
- XFS_BTREE_LBLOCK_LEN :
- XFS_BTREE_SBLOCK_LEN;
+ size_t len;
+
+ if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
+ len = XFS_BTREE_LBLOCK_LEN;
+ else
+ len = XFS_BTREE_SBLOCK_LEN;
+
+ if (cur->bc_flags & XFS_BTREE_CRC_BLOCKS)
+ len += XFS_BTREE_CRCBLOCK_ADD;
+
+ return len;
}
/*
@@ -420,6 +497,30 @@ xfs_btree_ptr_addr(
}
/*
+ * Calculate CRC on the whole btree block and stuff it into the
+ * long-form btree header.
+ */
+void
+xfs_btree_lblock_calc_crc(
+ struct xfs_buf *bp)
+{
+ xfs_update_cksum(XFS_BUF_PTR(bp), XFS_BUF_SIZE(bp),
+ XFS_BTREE_LBLOCK_CRC_OFF);
+}
+
+/*
+ * Calculate CRC on the whole btree block and stuff it into the
+ * short-form btree header.
+ */
+void
+xfs_btree_sblock_calc_crc(
+ struct xfs_buf *bp)
+{
+ xfs_update_cksum(XFS_BUF_PTR(bp), XFS_BUF_SIZE(bp),
+ XFS_BTREE_SBLOCK_CRC_OFF);
+}
+
+/*
* Get a the root block which is stored in the inode.
*
* For now this btree implementation assumes the btree root is always
@@ -474,6 +575,9 @@ xfs_btree_get_bufl(
bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);
ASSERT(bp);
ASSERT(!XFS_BUF_GETERROR(bp));
+
+ if (xfs_sb_version_hascrc(&mp->m_sb))
+ xfs_buf_set_io_callback(bp, xfs_btree_lblock_calc_crc);
return bp;
}
@@ -498,6 +602,9 @@ xfs_btree_get_bufs(
bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);
ASSERT(bp);
ASSERT(!XFS_BUF_GETERROR(bp));
+
+ if (xfs_sb_version_hascrc(&mp->m_sb))
+ xfs_buf_set_io_callback(bp, xfs_btree_sblock_calc_crc);
return bp;
}
@@ -640,6 +747,8 @@ xfs_btree_read_bufl(
ASSERT(!bp || !XFS_BUF_GETERROR(bp));
if (bp != NULL) {
XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, refval);
+ if (xfs_sb_version_hascrc(&mp->m_sb))
+ xfs_buf_set_io_callback(bp, xfs_btree_lblock_calc_crc);
}
*bpp = bp;
return 0;
@@ -680,6 +789,8 @@ xfs_btree_read_bufs(
XFS_BUF_SET_VTYPE_REF(bp, B_FS_INOMAP, refval);
break;
}
+ if (xfs_sb_version_hascrc(&mp->m_sb))
+ xfs_buf_set_io_callback(bp, xfs_btree_sblock_calc_crc);
}
*bpp = bp;
return 0;
@@ -909,20 +1020,34 @@ xfs_btree_set_sibling(
STATIC void
xfs_btree_init_block(
struct xfs_btree_cur *cur,
+ struct xfs_buf *bp,
int level,
- int numrecs,
- struct xfs_btree_block *new) /* new block */
+ int numrecs)
{
- new->bb_magic = cpu_to_be32(xfs_magics[cur->bc_btnum]);
+ struct xfs_btree_block *new = XFS_BUF_TO_BLOCK(bp);
+
+ new->bb_magic = cpu_to_be32(xfs_btree_magic(cur));
new->bb_level = cpu_to_be16(level);
new->bb_numrecs = cpu_to_be16(numrecs);
if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
new->bb_u.l.bb_leftsib = cpu_to_be64(NULLDFSBNO);
new->bb_u.l.bb_rightsib = cpu_to_be64(NULLDFSBNO);
+ if (cur->bc_flags & XFS_BTREE_CRC_BLOCKS) {
+ new->bb_u.l.bb_blkno = cpu_to_be64(XFS_BUF_ADDR(bp));
+ uuid_copy(&new->bb_u.l.bb_uuid,
+ &cur->bc_mp->m_sb.sb_uuid);
+ new->bb_u.l.bb_pad = 0;
+ }
} else {
new->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK);
new->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK);
+ if (cur->bc_flags & XFS_BTREE_CRC_BLOCKS) {
+ new->bb_u.s.bb_blkno = cpu_to_be64(XFS_BUF_ADDR(bp));
+ uuid_copy(&new->bb_u.s.bb_uuid,
+ &cur->bc_mp->m_sb.sb_uuid);
+ new->bb_u.s.bb_pad = 0;
+ }
}
}
@@ -1013,19 +1138,28 @@ xfs_btree_get_buf_block(
struct xfs_buf **bpp)
{
struct xfs_mount *mp = cur->bc_mp;
+ struct xfs_buf *bp;
xfs_daddr_t d;
/* need to sort out how callers deal with failures first */
ASSERT(!(flags & XFS_BUF_TRYLOCK));
d = xfs_btree_ptr_to_daddr(cur, ptr);
- *bpp = xfs_trans_get_buf(cur->bc_tp, mp->m_ddev_targp, d,
- mp->m_bsize, flags);
+ bp = xfs_trans_get_buf(cur->bc_tp, mp->m_ddev_targp, d,
+ mp->m_bsize, flags);
- ASSERT(*bpp);
- ASSERT(!XFS_BUF_GETERROR(*bpp));
+ ASSERT(bp);
+ ASSERT(!XFS_BUF_GETERROR(bp));
+
+ if (cur->bc_flags & XFS_BTREE_CRC_BLOCKS) {
+ if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
+ xfs_buf_set_io_callback(bp, xfs_btree_lblock_calc_crc);
+ else
+ xfs_buf_set_io_callback(bp, xfs_btree_sblock_calc_crc);
+ }
- *block = XFS_BUF_TO_BLOCK(*bpp);
+ *block = XFS_BUF_TO_BLOCK(bp);
+ *bpp = bp;
return 0;
}
@@ -1043,6 +1177,7 @@ xfs_btree_read_buf_block(
struct xfs_buf **bpp)
{
struct xfs_mount *mp = cur->bc_mp;
+ struct xfs_buf *bp;
xfs_daddr_t d;
int error;
@@ -1051,20 +1186,31 @@ xfs_btree_read_buf_block(
d = xfs_btree_ptr_to_daddr(cur, ptr);
error = xfs_trans_read_buf(mp, cur->bc_tp, mp->m_ddev_targp, d,
- mp->m_bsize, flags, bpp);
+ mp->m_bsize, flags, &bp);
if (error)
return error;
- ASSERT(*bpp != NULL);
- ASSERT(!XFS_BUF_GETERROR(*bpp));
+ ASSERT(bp != NULL);
+ ASSERT(!XFS_BUF_GETERROR(bp));
- xfs_btree_set_refs(cur, *bpp);
- *block = XFS_BUF_TO_BLOCK(*bpp);
+ xfs_btree_set_refs(cur, bp);
+ *block = XFS_BUF_TO_BLOCK(bp);
- error = xfs_btree_check_block(cur, *block, level, *bpp);
- if (error)
- xfs_trans_brelse(cur->bc_tp, *bpp);
- return error;
+ if (cur->bc_flags & XFS_BTREE_CRC_BLOCKS) {
+ if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
+ xfs_buf_set_io_callback(bp, xfs_btree_lblock_calc_crc);
+ else
+ xfs_buf_set_io_callback(bp, xfs_btree_sblock_calc_crc);
+ }
+
+ error = xfs_btree_check_block(cur, *block, level, bp);
+ if (error) {
+ xfs_trans_brelse(cur->bc_tp, bp);
+ return error;
+ }
+
+ *bpp = bp;
+ return 0;
}
/*
@@ -1250,31 +1396,56 @@ xfs_btree_log_block(
{
int first; /* first byte offset logged */
int last; /* last byte offset logged */
- static const short soffsets[] = { /* table of offsets (short) */
+ static const short soffsets[] = { /* short + crc */
offsetof(struct xfs_btree_block, bb_magic),
offsetof(struct xfs_btree_block, bb_level),
offsetof(struct xfs_btree_block, bb_numrecs),
offsetof(struct xfs_btree_block, bb_u.s.bb_leftsib),
offsetof(struct xfs_btree_block, bb_u.s.bb_rightsib),
- XFS_BTREE_SBLOCK_LEN
+ offsetof(struct xfs_btree_block, bb_u.s.bb_blkno),
+ offsetof(struct xfs_btree_block, bb_u.s.bb_crc),
+ offsetof(struct xfs_btree_block, bb_u.s.bb_uuid),
+ offsetof(struct xfs_btree_block, bb_u.s.bb_pad),
+ XFS_BTREE_SBLOCK_LEN + XFS_BTREE_CRCBLOCK_ADD
};
- static const short loffsets[] = { /* table of offsets (long) */
+ static const short loffsets[] = { /* long + crc */
offsetof(struct xfs_btree_block, bb_magic),
offsetof(struct xfs_btree_block, bb_level),
offsetof(struct xfs_btree_block, bb_numrecs),
offsetof(struct xfs_btree_block, bb_u.l.bb_leftsib),
offsetof(struct xfs_btree_block, bb_u.l.bb_rightsib),
- XFS_BTREE_LBLOCK_LEN
+ offsetof(struct xfs_btree_block, bb_u.l.bb_blkno),
+ offsetof(struct xfs_btree_block, bb_u.l.bb_crc),
+ offsetof(struct xfs_btree_block, bb_u.l.bb_uuid),
+ offsetof(struct xfs_btree_block, bb_u.l.bb_pad),
+ XFS_BTREE_LBLOCK_LEN + XFS_BTREE_CRCBLOCK_ADD
};
XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
XFS_BTREE_TRACE_ARGBI(cur, bp, fields);
if (bp) {
+ int nbits;
+
+ if (cur->bc_flags & XFS_BTREE_CRC_BLOCKS) {
+ /*
+ * We don't log the CRC when updating a btree
+ * block but instead recreate it during log
+ * recovery. As the log buffers have checksums
+ * of their this is safe and avoids logging a crc
+ * update in a lot of places.
+ */
+ if (fields == XFS_BB_ALL_BITS)
+ fields = XFS_BB_ALL_BITS_CRC;
+ nbits = XFS_BB_NUM_BITS_CRC;
+ } else {
+ nbits = XFS_BB_NUM_BITS;
+ }
+
xfs_btree_offsets(fields,
(cur->bc_flags & XFS_BTREE_LONG_PTRS) ?
- loffsets : soffsets,
- XFS_BB_NUM_BITS, &first, &last);
+ loffsets : soffsets,
+ nbits, &first, &last);
xfs_trans_log_buf(cur->bc_tp, bp, first, last);
} else {
xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip,
@@ -2237,7 +2408,7 @@ xfs_btree_split(
goto error0;
/* Fill in the btree header for the new right block. */
- xfs_btree_init_block(cur, xfs_btree_get_level(left), 0, right);
+ xfs_btree_init_block(cur, rbp, xfs_btree_get_level(left), 0);
/*
* Split the entries between the old and the new block evenly.
@@ -2546,7 +2717,7 @@ xfs_btree_new_root(
nptr = 2;
}
/* Fill in the new block's btree header and log it. */
- xfs_btree_init_block(cur, cur->bc_nlevels, 2, new);
+ xfs_btree_init_block(cur, nbp, cur->bc_nlevels, 2);
xfs_btree_log_block(cur, nbp, XFS_BB_ALL_BITS);
ASSERT(!xfs_btree_ptr_is_null(cur, &lptr) &&
!xfs_btree_ptr_is_null(cur, &rptr));
Index: xfs/fs/xfs/xfs_dinode.h
===================================================================
--- xfs.orig/fs/xfs/xfs_dinode.h 2009-02-09 19:15:37.179944489 +0100
+++ xfs/fs/xfs/xfs_dinode.h 2009-02-09 19:15:42.843068745 +0100
@@ -106,8 +106,8 @@ typedef enum xfs_dinode_fmt {
#define XFS_LITINO(version, mp) \
((int)(((mp)->m_sb.sb_inodesize) - sizeof(struct xfs_dinode)))
-#define XFS_BROOT_SIZE_ADJ \
- (XFS_BTREE_LBLOCK_LEN - sizeof(xfs_bmdr_block_t))
+#define XFS_BROOT_SIZE_ADJ(ip) \
+ (XFS_BMBT_BLOCK_LEN((ip)->i_mount) - sizeof(xfs_bmdr_block_t))
/*
* Inode data & attribute fork sizes, per inode.
Index: xfs/fs/xfs/xfs_inode.c
===================================================================
--- xfs.orig/fs/xfs/xfs_inode.c 2009-02-09 19:05:49.026068758 +0100
+++ xfs/fs/xfs/xfs_inode.c 2009-02-09 19:15:42.848068962 +0100
@@ -596,6 +596,7 @@ xfs_iformat_btree(
xfs_dinode_t *dip,
int whichfork)
{
+ struct xfs_mount *mp = ip->i_mount;
xfs_bmdr_block_t *dfp;
xfs_ifork_t *ifp;
/* REFERENCED */
@@ -604,7 +605,7 @@ xfs_iformat_btree(
ifp = XFS_IFORK_PTR(ip, whichfork);
dfp = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork);
- size = XFS_BMAP_BROOT_SPACE(dfp);
+ size = XFS_BMAP_BROOT_SPACE(mp, dfp);
nrecs = be16_to_cpu(dfp->bb_numrecs);
/*
@@ -616,13 +617,12 @@ xfs_iformat_btree(
*/
if (unlikely(XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max
|| XFS_BMDR_SPACE_CALC(nrecs) >
- XFS_DFORK_SIZE(dip, ip->i_mount, whichfork)
+ XFS_DFORK_SIZE(dip, mp, whichfork)
|| XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks)) {
- xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
+ xfs_fs_repair_cmn_err(CE_WARN, mp,
"corrupt inode %Lu (btree).",
(unsigned long long) ip->i_ino);
- XFS_ERROR_REPORT("xfs_iformat_btree", XFS_ERRLEVEL_LOW,
- ip->i_mount);
+ XFS_ERROR_REPORT("xfs_iformat_btree", XFS_ERRLEVEL_LOW, mp);
return XFS_ERROR(EFSCORRUPTED);
}
@@ -2247,7 +2247,7 @@ xfs_iroot_realloc(
* allocate it now and get out.
*/
if (ifp->if_broot_bytes == 0) {
- new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(rec_diff);
+ new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, rec_diff);
ifp->if_broot = kmem_alloc(new_size, KM_SLEEP);
ifp->if_broot_bytes = (int)new_size;
return;
@@ -2261,9 +2261,9 @@ xfs_iroot_realloc(
*/
cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0);
new_max = cur_max + rec_diff;
- new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(new_max);
+ new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(mp, new_max);
ifp->if_broot = kmem_realloc(ifp->if_broot, new_size,
- (size_t)XFS_BMAP_BROOT_SPACE_CALC(cur_max), /* old size */
+ (size_t)XFS_BMAP_BROOT_SPACE_CALC(mp, cur_max), /* old size */
KM_SLEEP);
op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
ifp->if_broot_bytes);
@@ -2271,7 +2271,7 @@ xfs_iroot_realloc(
(int)new_size);
ifp->if_broot_bytes = (int)new_size;
ASSERT(ifp->if_broot_bytes <=
- XFS_IFORK_SIZE(ip, whichfork) + XFS_BROOT_SIZE_ADJ);
+ XFS_IFORK_SIZE(ip, whichfork) + XFS_BROOT_SIZE_ADJ(ip));
memmove(np, op, cur_max * (uint)sizeof(xfs_dfsbno_t));
return;
}
@@ -2286,7 +2286,7 @@ xfs_iroot_realloc(
new_max = cur_max + rec_diff;
ASSERT(new_max >= 0);
if (new_max > 0)
- new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(new_max);
+ new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(mp, new_max);
else
new_size = 0;
if (new_size > 0) {
@@ -2294,7 +2294,8 @@ xfs_iroot_realloc(
/*
* First copy over the btree block header.
*/
- memcpy(new_broot, ifp->if_broot, XFS_BTREE_LBLOCK_LEN);
+ memcpy(new_broot, ifp->if_broot,
+ XFS_BMBT_BLOCK_LEN(ip->i_mount));
} else {
new_broot = NULL;
ifp->if_flags &= ~XFS_IFBROOT;
@@ -2324,7 +2325,7 @@ xfs_iroot_realloc(
ifp->if_broot = new_broot;
ifp->if_broot_bytes = (int)new_size;
ASSERT(ifp->if_broot_bytes <=
- XFS_IFORK_SIZE(ip, whichfork) + XFS_BROOT_SIZE_ADJ);
+ XFS_IFORK_SIZE(ip, whichfork) + XFS_BROOT_SIZE_ADJ(ip));
return;
}
@@ -2665,7 +2666,7 @@ xfs_iflush_fork(
ASSERT(ifp->if_broot != NULL);
ASSERT(ifp->if_broot_bytes <=
(XFS_IFORK_SIZE(ip, whichfork) +
- XFS_BROOT_SIZE_ADJ));
+ XFS_BROOT_SIZE_ADJ(ip)));
xfs_bmbt_to_bmdr(mp, ifp->if_broot, ifp->if_broot_bytes,
(xfs_bmdr_block_t *)cp,
XFS_DFORK_SIZE(dip, mp, whichfork));
Index: xfs/fs/xfs/xfs_attr_leaf.c
===================================================================
--- xfs.orig/fs/xfs/xfs_attr_leaf.c 2009-02-09 19:15:37.185944554 +0100
+++ xfs/fs/xfs/xfs_attr_leaf.c 2009-02-09 19:15:42.850068937 +0100
@@ -174,7 +174,7 @@ xfs_attr_shortform_bytesfit(xfs_inode_t
else
return dp->i_d.di_forkoff;
} else
- dsize = XFS_BMAP_BROOT_SPACE(dp->i_df.if_broot);
+ dsize = XFS_BMAP_BROOT_SPACE(mp, dp->i_df.if_broot);
break;
}
Index: xfs/fs/xfs/xfs_bmap.c
===================================================================
--- xfs.orig/fs/xfs/xfs_bmap.c 2009-02-09 19:15:37.192068867 +0100
+++ xfs/fs/xfs/xfs_bmap.c 2009-02-09 19:15:42.854098570 +0100
@@ -3465,6 +3465,7 @@ xfs_bmap_extents_to_btree(
xfs_extnum_t nextents; /* number of file extents */
xfs_bmbt_ptr_t *pp; /* root block address pointer */
+ mp = ip->i_mount;
ifp = XFS_IFORK_PTR(ip, whichfork);
ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS);
ASSERT(ifp->if_ext_max ==
@@ -3479,16 +3480,23 @@ xfs_bmap_extents_to_btree(
* Fill in the root.
*/
block = ifp->if_broot;
- block->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
+ if (xfs_sb_version_hascrc(&mp->m_sb))
+ block->bb_magic = cpu_to_be32(XFS_BMAP_CRC_MAGIC);
+ else
+ block->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
block->bb_level = cpu_to_be16(1);
block->bb_numrecs = cpu_to_be16(1);
block->bb_u.l.bb_leftsib = cpu_to_be64(NULLDFSBNO);
block->bb_u.l.bb_rightsib = cpu_to_be64(NULLDFSBNO);
+ if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ block->bb_u.l.bb_blkno = cpu_to_be64(XFS_BUF_DADDR_NULL);
+ uuid_copy(&block->bb_u.l.bb_uuid, &mp->m_sb.sb_uuid);
+ block->bb_u.l.bb_pad = 0;
+ }
/*
* Need a cursor. Can't allocate until bb_level is filled in.
*/
- mp = ip->i_mount;
cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
cur->bc_private.b.firstblock = *firstblock;
cur->bc_private.b.flist = flist;
@@ -3537,10 +3545,18 @@ xfs_bmap_extents_to_btree(
* Fill in the child block.
*/
ablock = XFS_BUF_TO_BLOCK(abp);
- ablock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
+ if (xfs_sb_version_hascrc(&mp->m_sb))
+ ablock->bb_magic = cpu_to_be32(XFS_BMAP_CRC_MAGIC);
+ else
+ ablock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
ablock->bb_level = 0;
ablock->bb_u.l.bb_leftsib = cpu_to_be64(NULLDFSBNO);
ablock->bb_u.l.bb_rightsib = cpu_to_be64(NULLDFSBNO);
+ if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ ablock->bb_u.l.bb_blkno = cpu_to_be64(XFS_BUF_ADDR(abp));
+ uuid_copy(&ablock->bb_u.l.bb_uuid, &mp->m_sb.sb_uuid);
+ ablock->bb_u.l.bb_pad = 0;
+ }
arp = XFS_BMBT_REC_ADDR(mp, ablock, 1);
nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
for (cnt = i = 0; i < nextents; i++) {
@@ -3568,8 +3584,8 @@ xfs_bmap_extents_to_btree(
* Do all this logging at the end so that
* the root is at the right level.
*/
- xfs_btree_log_block(cur, abp, XFS_BB_ALL_BITS);
xfs_btree_log_recs(cur, abp, 1, be16_to_cpu(ablock->bb_numrecs));
+ xfs_btree_log_block(cur, abp, XFS_BB_ALL_BITS);
ASSERT(*curp == NULL);
*curp = cur;
*logflagsp = XFS_ILOG_CORE | xfs_ilog_fbroot(whichfork);
@@ -3686,7 +3702,13 @@ xfs_bmap_local_to_extents(
ASSERT(args.fsbno != NULLFSBLOCK);
ASSERT(args.len == 1);
*firstblock = args.fsbno;
- bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno, 0);
+
+ bp = xfs_trans_get_buf(args.tp, args.mp->m_ddev_targp,
+ XFS_FSB_TO_DADDR(args.mp, args.fsbno),
+ args.mp->m_bsize, 0);
+ ASSERT(bp);
+ ASSERT(!XFS_BUF_GETERROR(bp));
+
memcpy((char *)XFS_BUF_PTR(bp), ifp->if_u1.if_data,
ifp->if_bytes);
xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1);
@@ -4562,11 +4584,21 @@ xfs_bmap_sanity_check(
{
struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);
- if (be32_to_cpu(block->bb_magic) != XFS_BMAP_MAGIC ||
- be16_to_cpu(block->bb_level) != level ||
+ if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ if (be32_to_cpu(block->bb_magic) != XFS_BMAP_CRC_MAGIC ||
+ !uuid_equal(&block->bb_u.l.bb_uuid, &mp->m_sb.sb_uuid) ||
+ block->bb_u.l.bb_blkno != cpu_to_be64(XFS_BUF_ADDR(bp)))
+ return 0;
+ } else {
+ if (be32_to_cpu(block->bb_magic) != XFS_BMAP_MAGIC)
+ return 0;
+ }
+
+ if (be16_to_cpu(block->bb_level) != level ||
be16_to_cpu(block->bb_numrecs) == 0 ||
be16_to_cpu(block->bb_numrecs) > mp->m_bmap_dmxr[level != 0])
return 0;
+
return 1;
}
Index: xfs/fs/xfs/xfs_alloc_btree.c
===================================================================
--- xfs.orig/fs/xfs/xfs_alloc_btree.c 2009-02-09 19:05:49.038069167 +0100
+++ xfs/fs/xfs/xfs_alloc_btree.c 2009-02-09 19:15:42.855068736 +0100
@@ -474,6 +474,8 @@ xfs_allocbt_init_cursor(
cur->bc_ops = &xfs_allocbt_ops;
if (btnum == XFS_BTNUM_CNT)
cur->bc_flags = XFS_BTREE_LASTREC_UPDATE;
+ if (xfs_sb_version_hascrc(&mp->m_sb))
+ cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
cur->bc_private.a.agbp = agbp;
cur->bc_private.a.agno = agno;
Index: xfs/fs/xfs/xfs_ialloc_btree.c
===================================================================
--- xfs.orig/fs/xfs/xfs_ialloc_btree.c 2009-02-09 19:05:49.043068895 +0100
+++ xfs/fs/xfs/xfs_ialloc_btree.c 2009-02-09 19:15:42.857069060 +0100
@@ -359,6 +359,8 @@ xfs_inobt_init_cursor(
cur->bc_blocklog = mp->m_sb.sb_blocklog;
cur->bc_ops = &xfs_inobt_ops;
+ if (xfs_sb_version_hascrc(&mp->m_sb))
+ cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
cur->bc_private.a.agbp = agbp;
cur->bc_private.a.agno = agno;
Index: xfs/fs/xfs/xfs_fsops.c
===================================================================
--- xfs.orig/fs/xfs/xfs_fsops.c 2009-02-09 19:05:49.047068705 +0100
+++ xfs/fs/xfs/xfs_fsops.c 2009-02-09 19:15:42.860069581 +0100
@@ -253,11 +253,19 @@ xfs_growfs_data_private(
BTOBB(mp->m_sb.sb_blocksize), 0);
block = XFS_BUF_TO_BLOCK(bp);
memset(block, 0, mp->m_sb.sb_blocksize);
- block->bb_magic = cpu_to_be32(XFS_ABTB_MAGIC);
block->bb_level = 0;
block->bb_numrecs = cpu_to_be16(1);
block->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK);
block->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK);
+ if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ block->bb_magic = cpu_to_be32(XFS_ABTB_CRC_MAGIC);
+ block->bb_u.s.bb_blkno = cpu_to_be64(XFS_BUF_ADDR(bp));
+ uuid_copy(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid);
+ block->bb_u.s.bb_pad = 0;
+ xfs_buf_set_io_callback(bp, xfs_btree_sblock_calc_crc);
+ } else {
+ block->bb_magic = cpu_to_be32(XFS_ABTB_MAGIC);
+ }
arec = XFS_ALLOC_REC_ADDR(mp, block, 1);
arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
arec->ar_blockcount = cpu_to_be32(
@@ -274,11 +282,19 @@ xfs_growfs_data_private(
BTOBB(mp->m_sb.sb_blocksize), 0);
block = XFS_BUF_TO_BLOCK(bp);
memset(block, 0, mp->m_sb.sb_blocksize);
- block->bb_magic = cpu_to_be32(XFS_ABTC_MAGIC);
block->bb_level = 0;
block->bb_numrecs = cpu_to_be16(1);
block->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK);
block->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK);
+ if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ block->bb_magic = cpu_to_be32(XFS_ABTC_CRC_MAGIC);
+ block->bb_u.s.bb_blkno = cpu_to_be64(XFS_BUF_ADDR(bp));
+ uuid_copy(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid);
+ block->bb_u.s.bb_pad = 0;
+ xfs_buf_set_io_callback(bp, xfs_btree_sblock_calc_crc);
+ } else {
+ block->bb_magic = cpu_to_be32(XFS_ABTC_MAGIC);
+ }
arec = XFS_ALLOC_REC_ADDR(mp, block, 1);
arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
arec->ar_blockcount = cpu_to_be32(
@@ -296,11 +312,19 @@ xfs_growfs_data_private(
BTOBB(mp->m_sb.sb_blocksize), 0);
block = XFS_BUF_TO_BLOCK(bp);
memset(block, 0, mp->m_sb.sb_blocksize);
- block->bb_magic = cpu_to_be32(XFS_IBT_MAGIC);
block->bb_level = 0;
block->bb_numrecs = 0;
block->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK);
block->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK);
+ if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ block->bb_magic = cpu_to_be32(XFS_IBT_CRC_MAGIC);
+ block->bb_u.s.bb_blkno = cpu_to_be64(XFS_BUF_ADDR(bp));
+ uuid_copy(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid);
+ block->bb_u.s.bb_pad = 0;
+ xfs_buf_set_io_callback(bp, xfs_btree_sblock_calc_crc);
+ } else {
+ block->bb_magic = cpu_to_be32(XFS_IBT_MAGIC);
+ }
error = xfs_bwrite(mp, bp);
if (error) {
goto error0;
Index: xfs/fs/xfs/xfs_alloc_btree.h
===================================================================
--- xfs.orig/fs/xfs/xfs_alloc_btree.h 2009-02-09 19:05:49.051069843 +0100
+++ xfs/fs/xfs/xfs_alloc_btree.h 2009-02-09 19:15:42.862069766 +0100
@@ -31,8 +31,10 @@ struct xfs_mount;
* by blockcount and blockno. All blocks look the same to make the code
* simpler; if we have time later, we'll make the optimizations.
*/
-#define XFS_ABTB_MAGIC 0x41425442 /* 'ABTB' for bno tree */
-#define XFS_ABTC_MAGIC 0x41425443 /* 'ABTC' for cnt tree */
+#define XFS_ABTB_MAGIC 0x41425442 /* 'ABTB' for bno tree */
+#define XFS_ABTB_CRC_MAGIC 0x4142544a
+#define XFS_ABTC_MAGIC 0x41425443 /* 'ABTC' for cnt tree */
+#define XFS_ABTC_CRC_MAGIC 0x4142544b
/*
* Data record/key structure
@@ -73,10 +75,11 @@ typedef __be32 xfs_alloc_ptr_t;
/*
* Btree block header size depends on a superblock flag.
- *
- * (not quite yet, but soon)
*/
-#define XFS_ALLOC_BLOCK_LEN(mp) XFS_BTREE_SBLOCK_LEN
+#define XFS_ALLOC_BLOCK_LEN(mp) \
+ (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \
+ XFS_BTREE_SBLOCK_LEN + XFS_BTREE_CRCBLOCK_ADD : \
+ XFS_BTREE_SBLOCK_LEN)
/*
* Record, key, and pointer address macros for btree blocks.
Index: xfs/fs/xfs/xfs_ialloc_btree.h
===================================================================
--- xfs.orig/fs/xfs/xfs_ialloc_btree.h 2009-02-09 19:05:49.055069304 +0100
+++ xfs/fs/xfs/xfs_ialloc_btree.h 2009-02-09 19:15:42.866069437 +0100
@@ -29,7 +29,8 @@ struct xfs_mount;
/*
* There is a btree for the inode map per allocation group.
*/
-#define XFS_IBT_MAGIC 0x49414254 /* 'IABT' */
+#define XFS_IBT_MAGIC 0x49414254 /* 'IABT' */
+#define XFS_IBT_CRC_MAGIC 0x4941425c
typedef __uint64_t xfs_inofree_t;
#define XFS_INODES_PER_CHUNK (NBBY * sizeof(xfs_inofree_t))
@@ -76,10 +77,11 @@ typedef __be32 xfs_inobt_ptr_t;
/*
* Btree block header size depends on a superblock flag.
- *
- * (not quite yet, but soon)
*/
-#define XFS_INOBT_BLOCK_LEN(mp) XFS_BTREE_SBLOCK_LEN
+#define XFS_INOBT_BLOCK_LEN(mp) \
+ (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \
+ XFS_BTREE_SBLOCK_LEN + XFS_BTREE_CRCBLOCK_ADD : \
+ XFS_BTREE_SBLOCK_LEN)
/*
* Record, key, and pointer address macros for btree blocks.
Index: xfs/fs/xfs/xfs_log_recover.c
===================================================================
--- xfs.orig/fs/xfs/xfs_log_recover.c 2009-02-09 19:15:38.648943978 +0100
+++ xfs/fs/xfs/xfs_log_recover.c 2009-02-09 19:15:42.873069001 +0100
@@ -31,6 +31,7 @@
#include "xfs_bmap_btree.h"
#include "xfs_alloc_btree.h"
#include "xfs_ialloc_btree.h"
+#include "xfs_btree.h"
#include "xfs_dir2_sf.h"
#include "xfs_attr_sf.h"
#include "xfs_dinode.h"
@@ -1980,6 +1981,19 @@ xlog_recover_do_reg_buffer(
bit += nbits;
}
+ switch (be32_to_cpu(*(__be32 *)XFS_BUF_PTR(bp))) {
+ case XFS_ABTB_CRC_MAGIC:
+ case XFS_ABTC_CRC_MAGIC:
+ case XFS_IBT_CRC_MAGIC:
+ xfs_btree_sblock_calc_crc(bp);
+ break;
+ case XFS_BMAP_CRC_MAGIC:
+ xfs_btree_lblock_calc_crc(bp);
+ break;
+ default:
+ break;
+ }
+
/* Shouldn't be any more regions */
ASSERT(i == item->ri_total);
}
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 07/13] xfs: add CRC checks to the superblock
2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
` (5 preceding siblings ...)
2009-02-10 20:22 ` [PATCH 06/13] xfs: add support for large btree blocks Christoph Hellwig
@ 2009-02-10 20:22 ` Christoph Hellwig
2009-02-10 20:22 ` [PATCH 08/13] xfs: add CRC checks to the AGF Christoph Hellwig
` (5 subsequent siblings)
12 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
To: xfs; +Cc: Dave Chinner
[-- Attachment #1: xfs-sb-crc --]
[-- Type: text/plain, Size: 7323 bytes --]
[hch: minor adaptions]
Signed-off-by: Dave Chinner <dgc@sgi.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: xfs/fs/xfs/xfs_mount.c
===================================================================
--- xfs.orig/fs/xfs/xfs_mount.c 2009-02-09 19:15:40.377949194 +0100
+++ xfs/fs/xfs/xfs_mount.c 2009-02-09 19:15:45.187943691 +0100
@@ -44,6 +44,7 @@
#include "xfs_quota.h"
#include "xfs_fsops.h"
#include "xfs_utils.h"
+#include "xfs_cksum.h"
STATIC int xfs_uuid_mount(xfs_mount_t *);
STATIC void xfs_unmountfs_wait(xfs_mount_t *);
@@ -118,6 +119,8 @@ static const struct {
{ offsetof(xfs_sb_t, sb_logsunit), 0 },
{ offsetof(xfs_sb_t, sb_features2), 0 },
{ offsetof(xfs_sb_t, sb_bad_features2), 0 },
+ { offsetof(xfs_sb_t, sb_crc), 0 },
+ { offsetof(xfs_sb_t, sb_pad), 0 },
{ sizeof(xfs_sb_t), 0 }
};
@@ -408,6 +411,7 @@ xfs_sb_from_disk(
to->sb_logsunit = be32_to_cpu(from->sb_logsunit);
to->sb_features2 = be32_to_cpu(from->sb_features2);
to->sb_bad_features2 = be32_to_cpu(from->sb_bad_features2);
+ to->sb_crc = be32_to_cpu(from->sb_crc);
}
/*
@@ -464,6 +468,24 @@ xfs_sb_to_disk(
}
/*
+ * Calculate the superblock CRC and stuff it in the buffer.
+ *
+ * We get called here just before the superblock is written
+ * to disk. We should also do some validity checking here.
+ *
+ * We CRC the entire superblock sector, not just the bits we use
+ * so that changes in structure size as features are included do
+ * not invalidate CRCs.
+ */
+void
+xfs_sb_calc_crc(
+ struct xfs_buf *bp)
+{
+ xfs_update_cksum(XFS_BUF_PTR(bp), XFS_BUF_SIZE(bp),
+ offsetof(struct xfs_sb, sb_crc));
+}
+
+/*
* xfs_readsb
*
* Does the initial read of the superblock.
@@ -474,6 +496,7 @@ xfs_readsb(xfs_mount_t *mp, int flags)
unsigned int sector_size;
unsigned int extra_flags;
xfs_buf_t *bp;
+ xfs_sb_t *sbp = &mp->m_sb;
int error;
ASSERT(mp->m_sb_bp == NULL);
@@ -503,7 +526,25 @@ xfs_readsb(xfs_mount_t *mp, int flags)
*/
xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp));
- error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags);
+ /*
+ * If the superblock has the CRC feature bit set or
+ * the CRC field is non-null, check that the CRC is valid.
+ * We check the CRC field is non-null because a single bit
+ * error could clear the feature bit and unused parts of
+ * the superblock are supposed to be zero. Hence a non-null
+ * crc field indicates that we've potentially lost a feature
+ * bit and we should check it anyway.
+ */
+ if (xfs_sb_version_hascrc(sbp) || sbp->sb_crc != 0) {
+ if (!xfs_verify_cksum(XFS_BUF_PTR(bp), sbp->sb_sectsize,
+ offsetof(struct xfs_sb, sb_crc))) {
+ xfs_fs_mount_cmn_err(flags, "SB CRC check failed");
+ error = EFSCORRUPTED;
+ goto fail;
+ }
+ }
+
+ error = xfs_mount_validate_sb(mp, sbp, flags);
if (error) {
xfs_fs_mount_cmn_err(flags, "SB validate failed");
goto fail;
@@ -512,10 +553,10 @@ xfs_readsb(xfs_mount_t *mp, int flags)
/*
* We must be able to do sector-sized and sector-aligned IO.
*/
- if (sector_size > mp->m_sb.sb_sectsize) {
+ if (sector_size > sbp->sb_sectsize) {
xfs_fs_mount_cmn_err(flags,
"device supports only %u byte sectors (not %u)",
- sector_size, mp->m_sb.sb_sectsize);
+ sector_size, sbp->sb_sectsize);
error = ENOSYS;
goto fail;
}
@@ -524,10 +565,10 @@ xfs_readsb(xfs_mount_t *mp, int flags)
* If device sector size is smaller than the superblock size,
* re-read the superblock so the buffer is correctly sized.
*/
- if (sector_size < mp->m_sb.sb_sectsize) {
+ if (sector_size < sbp->sb_sectsize) {
XFS_BUF_UNMANAGE(bp);
xfs_buf_relse(bp);
- sector_size = mp->m_sb.sb_sectsize;
+ sector_size = sbp->sb_sectsize;
bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR,
BTOBB(sector_size), extra_flags);
if (!bp || XFS_BUF_ISERROR(bp)) {
@@ -543,11 +584,13 @@ xfs_readsb(xfs_mount_t *mp, int flags)
xfs_icsb_reinit_counters(mp);
mp->m_sb_bp = bp;
+ if (xfs_sb_version_hascrc(sbp))
+ xfs_buf_set_io_callback(bp, xfs_sb_calc_crc);
xfs_buf_relse(bp);
ASSERT(XFS_BUF_VALUSEMA(bp) > 0);
return 0;
- fail:
+fail:
if (bp) {
XFS_BUF_UNMANAGE(bp);
xfs_buf_relse(bp);
Index: xfs/fs/xfs/xfs_sb.h
===================================================================
--- xfs.orig/fs/xfs/xfs_sb.h 2009-02-09 19:15:40.363974092 +0100
+++ xfs/fs/xfs/xfs_sb.h 2009-02-09 19:15:45.192944467 +0100
@@ -160,7 +160,10 @@ typedef struct xfs_sb {
*/
__uint32_t sb_bad_features2;
+ __uint32_t sb_crc; /* superblock crc */
+
/* must be padded to 64 bit alignment */
+ __uint32_t sb_pad;
} xfs_sb_t;
/*
@@ -228,9 +231,12 @@ typedef struct xfs_dsb {
* for features2 bits. Easiest just to mark it bad and not use
* it for anything else.
*/
- __be32 sb_bad_features2;
+ __be32 sb_bad_features2;
+
+ __be32 sb_crc; /* superblock crc */
/* must be padded to 64 bit alignment */
+ __be32 sb_pad;
} xfs_dsb_t;
/*
@@ -249,7 +255,7 @@ typedef enum {
XFS_SBS_GQUOTINO, XFS_SBS_QFLAGS, XFS_SBS_FLAGS, XFS_SBS_SHARED_VN,
XFS_SBS_INOALIGNMT, XFS_SBS_UNIT, XFS_SBS_WIDTH, XFS_SBS_DIRBLKLOG,
XFS_SBS_LOGSECTLOG, XFS_SBS_LOGSECTSIZE, XFS_SBS_LOGSUNIT,
- XFS_SBS_FEATURES2, XFS_SBS_BAD_FEATURES2,
+ XFS_SBS_FEATURES2, XFS_SBS_BAD_FEATURES2, XFS_SBS_CRC, XFS_SBS_PAD,
XFS_SBS_FIELDCOUNT
} xfs_sb_field_t;
@@ -275,6 +281,8 @@ typedef enum {
#define XFS_SB_FDBLOCKS XFS_SB_MVAL(FDBLOCKS)
#define XFS_SB_FEATURES2 XFS_SB_MVAL(FEATURES2)
#define XFS_SB_BAD_FEATURES2 XFS_SB_MVAL(BAD_FEATURES2)
+#define XFS_SB_CRC XFS_SB_MVAL(CRC)
+#define XFS_SB_PAD XFS_SB_MVAL(PAD)
#define XFS_SB_NUM_BITS ((int)XFS_SBS_FIELDCOUNT)
#define XFS_SB_ALL_BITS ((1LL << XFS_SB_NUM_BITS) - 1)
#define XFS_SB_MOD_BITS \
Index: xfs/fs/xfs/xfs_trans.c
===================================================================
--- xfs.orig/fs/xfs/xfs_trans.c 2009-02-09 19:05:48.429078156 +0100
+++ xfs/fs/xfs/xfs_trans.c 2009-02-09 19:15:45.194049007 +0100
@@ -44,6 +44,7 @@
#include "xfs_trans_priv.h"
#include "xfs_trans_space.h"
#include "xfs_inode_item.h"
+#include "xfs_cksum.h"
STATIC void xfs_trans_apply_sb_deltas(xfs_trans_t *);
Index: xfs/fs/xfs/xfs_mount.h
===================================================================
--- xfs.orig/fs/xfs/xfs_mount.h 2009-02-09 19:15:35.584944583 +0100
+++ xfs/fs/xfs/xfs_mount.h 2009-02-09 19:15:45.194049007 +0100
@@ -521,6 +521,7 @@ extern struct xfs_dmops xfs_dmcore_xfs;
#endif /* __KERNEL__ */
+extern void xfs_sb_calc_crc(struct xfs_buf *);
extern void xfs_mod_sb(struct xfs_trans *, __int64_t);
extern xfs_agnumber_t xfs_initialize_perag(struct xfs_mount *, xfs_agnumber_t);
extern void xfs_sb_from_disk(struct xfs_sb *, struct xfs_dsb *);
Index: xfs/fs/xfs/xfs_log_recover.c
===================================================================
--- xfs.orig/fs/xfs/xfs_log_recover.c 2009-02-09 19:15:42.873069001 +0100
+++ xfs/fs/xfs/xfs_log_recover.c 2009-02-09 19:15:45.196071052 +0100
@@ -1990,6 +1990,9 @@ xlog_recover_do_reg_buffer(
case XFS_BMAP_CRC_MAGIC:
xfs_btree_lblock_calc_crc(bp);
break;
+ case XFS_SB_MAGIC:
+ xfs_sb_calc_crc(bp);
+ break;
default:
break;
}
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 08/13] xfs: add CRC checks to the AGF
2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
` (6 preceding siblings ...)
2009-02-10 20:22 ` [PATCH 07/13] xfs: add CRC checks to the superblock Christoph Hellwig
@ 2009-02-10 20:22 ` Christoph Hellwig
2009-02-10 20:22 ` [PATCH 09/13] xfs: add CRC checks to the AGI Christoph Hellwig
` (4 subsequent siblings)
12 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
To: xfs; +Cc: Dave Chinner
[-- Attachment #1: xfs-agf-crc --]
[-- Type: text/plain, Size: 4171 bytes --]
[hch: minor adaptions]
Signed-off-by: Dave Chinner <dgc@sgi.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: xfs/fs/xfs/xfs_ag.h
===================================================================
--- xfs.orig/fs/xfs/xfs_ag.h 2009-02-09 19:05:48.120069296 +0100
+++ xfs/fs/xfs/xfs_ag.h 2009-02-09 19:15:46.916949727 +0100
@@ -69,6 +69,8 @@ typedef struct xfs_agf {
__be32 agf_freeblks; /* total free blocks */
__be32 agf_longest; /* longest free space */
__be32 agf_btreeblks; /* # of blocks held in AGF btrees */
+ __be32 agf_crc; /* crc of agf sector */
+ uuid_t agf_uuid; /* uuid of filesystem */
} xfs_agf_t;
#define XFS_AGF_MAGICNUM 0x00000001
@@ -91,6 +93,7 @@ typedef struct xfs_agf {
#define XFS_AGF_BLOCK(mp) XFS_HDR_BLOCK(mp, XFS_AGF_DADDR(mp))
#define XFS_BUF_TO_AGF(bp) ((xfs_agf_t *)XFS_BUF_PTR(bp))
+extern void xfs_agf_calc_crc(struct xfs_buf *bp);
extern int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_agnumber_t agno, int flags, struct xfs_buf **bpp);
Index: xfs/fs/xfs/xfs_fsops.c
===================================================================
--- xfs.orig/fs/xfs/xfs_fsops.c 2009-02-09 19:15:42.860069581 +0100
+++ xfs/fs/xfs/xfs_fsops.c 2009-02-09 19:15:46.917943848 +0100
@@ -217,6 +217,10 @@ xfs_growfs_data_private(
tmpsize = agsize - XFS_PREALLOC_BLOCKS(mp);
agf->agf_freeblks = cpu_to_be32(tmpsize);
agf->agf_longest = cpu_to_be32(tmpsize);
+ if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ uuid_copy(&agf->agf_uuid, &mp->m_sb.sb_uuid);
+ xfs_buf_set_io_callback(bp, xfs_agf_calc_crc);
+ }
error = xfs_bwrite(mp, bp);
if (error) {
goto error0;
Index: xfs/fs/xfs/xfs_alloc.c
===================================================================
--- xfs.orig/fs/xfs/xfs_alloc.c 2009-02-09 19:05:48.190069960 +0100
+++ xfs/fs/xfs/xfs_alloc.c 2009-02-09 19:15:46.920944300 +0100
@@ -38,6 +38,7 @@
#include "xfs_ialloc.h"
#include "xfs_alloc.h"
#include "xfs_error.h"
+#include "xfs_cksum.h"
#define XFS_ABSDIFF(a,b) (((a) <= (b)) ? ((b) - (a)) : ((a) - (b)))
@@ -2230,6 +2231,23 @@ xfs_alloc_put_freelist(
}
/*
+ * Calculate CRC on AGF and stuff it into the structure.
+ *
+ * We CRC the entire AGF sector, not just the bits we use so that changes
+ * in structure size as features are included do not invalidate CRCs.
+ *
+ * We get called here just before the AGF is written to disk. We should
+ * also do some validity checking here.
+ */
+void
+xfs_agf_calc_crc(
+ struct xfs_buf *bp)
+{
+ xfs_update_cksum(XFS_BUF_PTR(bp), XFS_BUF_SIZE(bp),
+ offsetof(struct xfs_agf, agf_crc));
+}
+
+/*
* Read in the allocation group header (free/alloc section).
*/
int /* error */
@@ -2258,6 +2276,22 @@ xfs_read_agf(
agf = XFS_BUF_TO_AGF(*bpp);
/*
+ * Validate the CRC of the AGF block only if the block is clean (i.e.
+ * it just came from disk) and we have CRCs enabled.
+ */
+ if (xfs_sb_version_hascrc(&mp->m_sb) &&
+ !(XFS_BUF_ISWRITE(*bpp) || XFS_BUF_ISDELAYWRITE(*bpp))) {
+ if (!xfs_verify_cksum(XFS_BUF_PTR(*bpp), XFS_BUF_SIZE(*bpp),
+ offsetof(struct xfs_agf, agf_crc)) ||
+ !uuid_equal(&agf->agf_uuid, &mp->m_sb.sb_uuid)) {
+ XFS_CORRUPTION_ERROR("xfs_read_agf crc",
+ XFS_ERRLEVEL_LOW, mp, agf);
+ xfs_trans_brelse(tp, *bpp);
+ return XFS_ERROR(EFSCORRUPTED);
+ }
+ }
+
+ /*
* Validate the magic number of the agf block.
*/
agf_ok =
@@ -2280,6 +2314,9 @@ xfs_read_agf(
}
XFS_BUF_SET_VTYPE_REF(*bpp, B_FS_AGF, XFS_AGF_REF);
+
+ if (xfs_sb_version_hascrc(&mp->m_sb))
+ xfs_buf_set_io_callback(*bpp, xfs_agf_calc_crc);
return 0;
}
Index: xfs/fs/xfs/xfs_log_recover.c
===================================================================
--- xfs.orig/fs/xfs/xfs_log_recover.c 2009-02-09 19:15:45.196071052 +0100
+++ xfs/fs/xfs/xfs_log_recover.c 2009-02-09 19:15:46.924974841 +0100
@@ -1993,6 +1993,9 @@ xlog_recover_do_reg_buffer(
case XFS_SB_MAGIC:
xfs_sb_calc_crc(bp);
break;
+ case XFS_AGF_MAGIC:
+ xfs_agf_calc_crc(bp);
+ break;
default:
break;
}
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 09/13] xfs: add CRC checks to the AGI
2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
` (7 preceding siblings ...)
2009-02-10 20:22 ` [PATCH 08/13] xfs: add CRC checks to the AGF Christoph Hellwig
@ 2009-02-10 20:22 ` Christoph Hellwig
2009-02-10 20:22 ` [PATCH 10/13] xfs: add CRC checks to the AGFL Christoph Hellwig
` (3 subsequent siblings)
12 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
To: xfs; +Cc: Dave Chinner
[-- Attachment #1: xfs-agi-crc --]
[-- Type: text/plain, Size: 5249 bytes --]
[hch: minor adaptions]
Signed-off-by: Dave Chinner <dgc@sgi.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: xfs/fs/xfs/xfs_ag.h
===================================================================
--- xfs.orig/fs/xfs/xfs_ag.h 2009-02-09 19:15:46.916949727 +0100
+++ xfs/fs/xfs/xfs_ag.h 2009-02-09 19:15:48.966944136 +0100
@@ -126,6 +126,8 @@ typedef struct xfs_agi {
* still being referenced.
*/
__be32 agi_unlinked[XFS_AGI_UNLINKED_BUCKETS];
+ __be32 agi_crc; /* crc of agi sector */
+ uuid_t agi_uuid; /* uuid of filesystem */
} xfs_agi_t;
#define XFS_AGI_MAGICNUM 0x00000001
@@ -139,6 +141,9 @@ typedef struct xfs_agi {
#define XFS_AGI_NEWINO 0x00000100
#define XFS_AGI_DIRINO 0x00000200
#define XFS_AGI_UNLINKED 0x00000400
+/*
+ * XXX(hch): update for the CRC additions? It's unused anyway..
+ */
#define XFS_AGI_NUM_BITS 11
#define XFS_AGI_ALL_BITS ((1 << XFS_AGI_NUM_BITS) - 1)
@@ -147,6 +152,7 @@ typedef struct xfs_agi {
#define XFS_AGI_BLOCK(mp) XFS_HDR_BLOCK(mp, XFS_AGI_DADDR(mp))
#define XFS_BUF_TO_AGI(bp) ((xfs_agi_t *)XFS_BUF_PTR(bp))
+extern void xfs_agi_calc_crc(struct xfs_buf *bp);
extern int xfs_read_agi(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_agnumber_t agno, struct xfs_buf **bpp);
Index: xfs/fs/xfs/xfs_fsops.c
===================================================================
--- xfs.orig/fs/xfs/xfs_fsops.c 2009-02-09 19:15:46.917943848 +0100
+++ xfs/fs/xfs/xfs_fsops.c 2009-02-09 19:15:48.966944136 +0100
@@ -245,6 +245,10 @@ xfs_growfs_data_private(
agi->agi_dirino = cpu_to_be32(NULLAGINO);
for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++)
agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO);
+ if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ uuid_copy(&agi->agi_uuid, &mp->m_sb.sb_uuid);
+ xfs_buf_set_io_callback(bp, xfs_agi_calc_crc);
+ }
error = xfs_bwrite(mp, bp);
if (error) {
goto error0;
Index: xfs/fs/xfs/xfs_ialloc.c
===================================================================
--- xfs.orig/fs/xfs/xfs_ialloc.c 2009-02-09 19:05:48.022069819 +0100
+++ xfs/fs/xfs/xfs_ialloc.c 2009-02-09 19:15:48.968944600 +0100
@@ -40,6 +40,7 @@
#include "xfs_rtalloc.h"
#include "xfs_error.h"
#include "xfs_bmap.h"
+#include "xfs_cksum.h"
/*
@@ -1455,6 +1456,24 @@ xfs_check_agi_unlinked(
#endif
/*
+ * Calculate CRC on AGI and stuff it into the structure.
+ *
+ * We CRC the entire AGI sector, not just the bits we use so that changes
+ * in structure size as features are included do not invalidate CRCs.
+ *
+ * We get called here just before the AGI is written to disk. We should
+ * also do some validity checking here.
+ */
+void
+xfs_agi_calc_crc(
+ xfs_buf_t *bp)
+{
+ xfs_update_cksum(XFS_BUF_PTR(bp), XFS_BUF_SIZE(bp),
+ offsetof(struct xfs_agi, agi_crc));
+
+}
+
+/*
* Read in the allocation group header (inode allocation section)
*/
int
@@ -1464,6 +1483,7 @@ xfs_read_agi(
xfs_agnumber_t agno, /* allocation group number */
struct xfs_buf **bpp) /* allocation group hdr buf */
{
+ struct xfs_buf *bp;
struct xfs_agi *agi; /* allocation group header */
int agi_ok; /* agi is consistent */
int error;
@@ -1472,12 +1492,28 @@ xfs_read_agi(
error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
- XFS_FSS_TO_BB(mp, 1), 0, bpp);
+ XFS_FSS_TO_BB(mp, 1), 0, &bp);
if (error)
return error;
- ASSERT(*bpp && !XFS_BUF_GETERROR(*bpp));
- agi = XFS_BUF_TO_AGI(*bpp);
+ ASSERT(bp && !XFS_BUF_GETERROR(bp));
+ agi = XFS_BUF_TO_AGI(bp);
+
+ /*
+ * Validate the CRC of the AGI block only if the block is clean (i.e.
+ * it just came from disk) and we have CRCs enabled.
+ */
+ if (xfs_sb_version_hascrc(&mp->m_sb) &&
+ !(XFS_BUF_ISWRITE(bp) || XFS_BUF_ISDELAYWRITE(bp))) {
+ if (!xfs_verify_cksum(XFS_BUF_PTR(bp), XFS_BUF_SIZE(bp),
+ offsetof(struct xfs_agi, agi_crc)) ||
+ !uuid_equal(&agi->agi_uuid, &mp->m_sb.sb_uuid)) {
+ XFS_CORRUPTION_ERROR("xfs_read_agi crc",
+ XFS_ERRLEVEL_LOW, mp, agi);
+ xfs_trans_brelse(tp, bp);
+ return XFS_ERROR(EFSCORRUPTED);
+ }
+ }
/*
* Validate the magic number of the agi block.
@@ -1489,13 +1525,18 @@ xfs_read_agi(
XFS_RANDOM_IALLOC_READ_AGI))) {
XFS_CORRUPTION_ERROR("xfs_read_agi", XFS_ERRLEVEL_LOW,
mp, agi);
- xfs_trans_brelse(tp, *bpp);
+ xfs_trans_brelse(tp, bp);
return XFS_ERROR(EFSCORRUPTED);
}
- XFS_BUF_SET_VTYPE_REF(*bpp, B_FS_AGI, XFS_AGI_REF);
+ XFS_BUF_SET_VTYPE_REF(bp, B_FS_AGI, XFS_AGI_REF);
xfs_check_agi_unlinked(agi);
+
+ if (xfs_sb_version_hascrc(&mp->m_sb))
+ xfs_buf_set_io_callback(bp, xfs_agi_calc_crc);
+
+ *bpp = bp;
return 0;
}
Index: xfs/fs/xfs/xfs_log_recover.c
===================================================================
--- xfs.orig/fs/xfs/xfs_log_recover.c 2009-02-09 19:15:46.924974841 +0100
+++ xfs/fs/xfs/xfs_log_recover.c 2009-02-09 19:15:48.970972860 +0100
@@ -1996,6 +1996,9 @@ xlog_recover_do_reg_buffer(
case XFS_AGF_MAGIC:
xfs_agf_calc_crc(bp);
break;
+ case XFS_AGI_MAGIC:
+ xfs_agi_calc_crc(bp);
+ break;
default:
break;
}
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 10/13] xfs: add CRC checks to the AGFL
2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
` (8 preceding siblings ...)
2009-02-10 20:22 ` [PATCH 09/13] xfs: add CRC checks to the AGI Christoph Hellwig
@ 2009-02-10 20:22 ` Christoph Hellwig
2009-02-11 7:54 ` Dave Chinner
2009-02-10 20:22 ` [PATCH 11/13] xfs: add CRC checks to the log Christoph Hellwig
` (2 subsequent siblings)
12 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
To: xfs
[-- Attachment #1: xfs-agfl-crc --]
[-- Type: text/plain, Size: 8422 bytes --]
Add CRC checks, location information and a magic number to the AGFL.
Previously the AGFL was just a block containing nothing but the
free block pointers. The new AGFL has a real header with the usual
boilerplate instead, so that we can verify it's not corrupted and
written into the right place.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: xfs/fs/xfs/xfs_ag.h
===================================================================
--- xfs.orig/fs/xfs/xfs_ag.h 2009-02-09 19:15:48.966944136 +0100
+++ xfs/fs/xfs/xfs_ag.h 2009-02-09 19:15:51.063944366 +0100
@@ -30,6 +30,7 @@ struct xfs_trans;
#define XFS_AGF_MAGIC 0x58414746 /* 'XAGF' */
#define XFS_AGI_MAGIC 0x58414749 /* 'XAGI' */
+#define XFS_AGFL_MAGIC 0x5841464c /* 'XAFL' */
#define XFS_AGF_VERSION 1
#define XFS_AGI_VERSION 1
@@ -162,13 +163,31 @@ extern int xfs_read_agi(struct xfs_mount
*/
#define XFS_AGFL_DADDR(mp) ((xfs_daddr_t)(3 << (mp)->m_sectbb_log))
#define XFS_AGFL_BLOCK(mp) XFS_HDR_BLOCK(mp, XFS_AGFL_DADDR(mp))
-#define XFS_AGFL_SIZE(mp) ((mp)->m_sb.sb_sectsize / sizeof(xfs_agblock_t))
#define XFS_BUF_TO_AGFL(bp) ((xfs_agfl_t *)XFS_BUF_PTR(bp))
+#define XFS_BUF_TO_AGFL_BNO(mp, bp) \
+ (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \
+ &(XFS_BUF_TO_AGFL(bp)->agfl_bno[0]) : \
+ (__be32 *)XFS_BUF_PTR(bp))
+
+/*
+ * Size of the AGFL. For CRC-enabled filesystes we steal the last two slots
+ * for location information (agno) and the crc.
+ */
+#define XFS_AGFL_SIZE(mp) \
+ ((mp)->m_sb.sb_sectsize / sizeof(xfs_agblock_t) - \
+ (xfs_sb_version_hascrc(&((mp)->m_sb)) ? sizeof(struct xfs_agfl) : 0))
+
typedef struct xfs_agfl {
- __be32 agfl_bno[1]; /* actually XFS_AGFL_SIZE(mp) */
+ __be32 agfl_magicnum;
+ __be32 agfl_seqno;
+ uuid_t agfl_uuid;
+ __be32 agfl_crc;
+ __be32 agfl_bno[]; /* actually XFS_AGFL_SIZE(mp) */
} xfs_agfl_t;
+extern void xfs_agfl_calc_crc(struct xfs_buf *bp);
+
/*
* Busy block/extent entry. Used in perag to mark blocks that have been freed
* but whose transactions aren't committed to disk yet.
Index: xfs/fs/xfs/xfs_alloc.c
===================================================================
--- xfs.orig/fs/xfs/xfs_alloc.c 2009-02-09 19:15:46.920944300 +0100
+++ xfs/fs/xfs/xfs_alloc.c 2009-02-09 19:15:51.064977738 +0100
@@ -472,6 +472,27 @@ xfs_alloc_fixup_trees(
return 0;
}
+#define xfs_buf_verify_cksum(bp, offset) \
+ xfs_verify_cksum(XFS_BUF_PTR(bp), XFS_BUF_SIZE(bp), offset)
+#define xfs_buf_update_cksum(bp, offset) \
+ xfs_update_cksum(XFS_BUF_PTR(bp), XFS_BUF_SIZE(bp), offset)
+
+/*
+ * Calculate CRC on AGFL and stuff it into the structure.
+ *
+ * We CRC the entire AGFL sector, not just the bits we use so that changes
+ * in structure size as features are included do not invalidate CRCs.
+ *
+ * We get called here just before the AGFL is written to disk. We should
+ * also do some validity checking here.
+ */
+void
+xfs_agfl_calc_crc(
+ struct xfs_buf *bp)
+{
+ xfs_buf_update_cksum(bp, offsetof(struct xfs_agfl, agfl_crc));
+}
+
/*
* Read in the allocation group free block array.
*/
@@ -494,8 +515,31 @@ xfs_alloc_read_agfl(
return error;
ASSERT(bp);
ASSERT(!XFS_BUF_GETERROR(bp));
+
+ /*
+ * Validate the CRC of the AGF block only if the block is clean (i.e.
+ * it just came from disk) and we have CRCs enabled.
+ */
+ if (xfs_sb_version_hascrc(&mp->m_sb) &&
+ !(XFS_BUF_ISWRITE(bp) || XFS_BUF_ISDELAYWRITE(bp))) {
+ struct xfs_agfl *agfl = XFS_BUF_TO_AGFL(bp);
+
+ if (!xfs_buf_verify_cksum(bp, offsetof(xfs_agfl_t, agfl_crc)) ||
+ !uuid_equal(&agfl->agfl_uuid, &mp->m_sb.sb_uuid) ||
+ be32_to_cpu(agfl->agfl_magicnum) != XFS_AGFL_MAGIC ||
+ be32_to_cpu(agfl->agfl_seqno) != agno) {
+ XFS_CORRUPTION_ERROR("xfs_read_agfl crc",
+ XFS_ERRLEVEL_LOW, mp, agfl);
+ xfs_trans_brelse(tp, bp);
+ return XFS_ERROR(EFSCORRUPTED);
+ }
+
+ xfs_buf_set_io_callback(bp, xfs_agfl_calc_crc);
+ }
+
XFS_BUF_SET_VTYPE_REF(bp, B_FS_AGFL, XFS_AGFL_REF);
*bpp = bp;
+
return 0;
}
@@ -2063,18 +2107,18 @@ xfs_alloc_get_freelist(
int btreeblk) /* destination is a AGF btree */
{
xfs_agf_t *agf; /* a.g. freespace structure */
- xfs_agfl_t *agfl; /* a.g. freelist structure */
xfs_buf_t *agflbp;/* buffer for a.g. freelist structure */
xfs_agblock_t bno; /* block number returned */
+ __be32 *agfl_bno;
int error;
int logflags;
- xfs_mount_t *mp; /* mount structure */
+ xfs_mount_t *mp = tp->t_mountp;
xfs_perag_t *pag; /* per allocation group data */
- agf = XFS_BUF_TO_AGF(agbp);
/*
* Freelist is empty, give up.
*/
+ agf = XFS_BUF_TO_AGF(agbp);
if (!agf->agf_flcount) {
*bnop = NULLAGBLOCK;
return 0;
@@ -2082,15 +2126,17 @@ xfs_alloc_get_freelist(
/*
* Read the array of free blocks.
*/
- mp = tp->t_mountp;
- if ((error = xfs_alloc_read_agfl(mp, tp,
- be32_to_cpu(agf->agf_seqno), &agflbp)))
+ error = xfs_alloc_read_agfl(mp, tp, be32_to_cpu(agf->agf_seqno),
+ &agflbp);
+ if (error)
return error;
- agfl = XFS_BUF_TO_AGFL(agflbp);
+
+
/*
* Get the block number and update the data structures.
*/
- bno = be32_to_cpu(agfl->agfl_bno[be32_to_cpu(agf->agf_flfirst)]);
+ agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, agflbp);
+ bno = be32_to_cpu(agfl_bno[be32_to_cpu(agf->agf_flfirst)]);
be32_add_cpu(&agf->agf_flfirst, 1);
xfs_trans_brelse(tp, agflbp);
if (be32_to_cpu(agf->agf_flfirst) == XFS_AGFL_SIZE(mp))
@@ -2186,12 +2232,13 @@ xfs_alloc_put_freelist(
int btreeblk) /* block came from a AGF btree */
{
xfs_agf_t *agf; /* a.g. freespace structure */
- xfs_agfl_t *agfl; /* a.g. free block array */
__be32 *blockp;/* pointer to array entry */
int error;
int logflags;
xfs_mount_t *mp; /* mount structure */
xfs_perag_t *pag; /* per allocation group data */
+ __be32 *agfl_bno;
+ int startoff;
agf = XFS_BUF_TO_AGF(agbp);
mp = tp->t_mountp;
@@ -2199,7 +2246,6 @@ xfs_alloc_put_freelist(
if (!agflbp && (error = xfs_alloc_read_agfl(mp, tp,
be32_to_cpu(agf->agf_seqno), &agflbp)))
return error;
- agfl = XFS_BUF_TO_AGFL(agflbp);
be32_add_cpu(&agf->agf_fllast, 1);
if (be32_to_cpu(agf->agf_fllast) == XFS_AGFL_SIZE(mp))
agf->agf_fllast = 0;
@@ -2219,14 +2265,17 @@ xfs_alloc_put_freelist(
xfs_alloc_log_agf(tp, agbp, logflags);
ASSERT(be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp));
- blockp = &agfl->agfl_bno[be32_to_cpu(agf->agf_fllast)];
+
+ agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, agflbp);
+ blockp = &agfl_bno[be32_to_cpu(agf->agf_fllast)];
*blockp = cpu_to_be32(bno);
+
TRACE_MODAGF(NULL, agf, logflags);
xfs_alloc_log_agf(tp, agbp, logflags);
- xfs_trans_log_buf(tp, agflbp,
- (int)((xfs_caddr_t)blockp - (xfs_caddr_t)agfl),
- (int)((xfs_caddr_t)blockp - (xfs_caddr_t)agfl +
- sizeof(xfs_agblock_t) - 1));
+
+ startoff = (char *)blockp - XFS_BUF_PTR(agflbp);
+ xfs_trans_log_buf(tp, agflbp, startoff,
+ startoff + sizeof(xfs_agblock_t) - 1);
return 0;
}
Index: xfs/fs/xfs/xfs_log_recover.c
===================================================================
--- xfs.orig/fs/xfs/xfs_log_recover.c 2009-02-09 19:15:48.970972860 +0100
+++ xfs/fs/xfs/xfs_log_recover.c 2009-02-09 19:15:51.066944119 +0100
@@ -1999,6 +1999,9 @@ xlog_recover_do_reg_buffer(
case XFS_AGI_MAGIC:
xfs_agi_calc_crc(bp);
break;
+ case XFS_AGFL_MAGIC:
+ xfs_agfl_calc_crc(bp);
+ break;
default:
break;
}
Index: xfs/fs/xfs/xfs_fsops.c
===================================================================
--- xfs.orig/fs/xfs/xfs_fsops.c 2009-02-09 19:15:48.966944136 +0100
+++ xfs/fs/xfs/xfs_fsops.c 2009-02-09 19:15:51.066944119 +0100
@@ -253,6 +253,30 @@ xfs_growfs_data_private(
if (error) {
goto error0;
}
+
+ /*
+ * AGFL block.
+ */
+ if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ struct xfs_agfl *agfl;
+
+ bp = xfs_buf_get(mp->m_ddev_targp,
+ XFS_AG_DADDR(mp, agno,
+ XFS_AGFL_DADDR(mp)),
+ XFS_FSS_TO_BB(mp, 1), 0);
+ agfl = XFS_BUF_TO_AGFL(bp);
+
+ memset(agfl, 0, mp->m_sb.sb_sectsize);
+ agfl->agfl_magicnum = cpu_to_be32(XFS_AGFL_MAGIC);
+ agfl->agfl_seqno = cpu_to_be32(agno);
+ uuid_copy(&agfl->agfl_uuid, &mp->m_sb.sb_uuid);
+ xfs_buf_set_io_callback(bp, xfs_agfl_calc_crc);
+
+ error = xfs_bwrite(mp, bp);
+ if (error)
+ goto error0;
+ }
+
/*
* BNO btree root block
*/
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 11/13] xfs: add CRC checks to the log
2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
` (9 preceding siblings ...)
2009-02-10 20:22 ` [PATCH 10/13] xfs: add CRC checks to the AGFL Christoph Hellwig
@ 2009-02-10 20:22 ` Christoph Hellwig
2009-02-10 20:22 ` [PATCH 12/13] xfs: add version 3 inode format with CRCs Christoph Hellwig
2009-02-10 20:22 ` [PATCH 13/13] xfs: add CRC checks for quota blocks Christoph Hellwig
12 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
To: xfs
[-- Attachment #1: xfs-log-crc --]
[-- Type: text/plain, Size: 13720 bytes --]
Implement CRCs for the log buffers. We re-use a field in
struct xlog_rec_header that was used for a weak checksum of the
log buffer payload in debug builds before.
The new checksumming uses the same crc32c checksum we use elsewhere
in XFS, and also protects the record header and addition cycle data.
Due to this there are some interesting changes in xlog_sync, as we
need to do the cycle wrapping for the split buffer case much earlier,
as we would touch the buffer after generating the checksum otherwise.
Based on a patch from Dave Chinner with lots of changes.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: xfs/fs/xfs/xfs_log_priv.h
===================================================================
--- xfs.orig/fs/xfs/xfs_log_priv.h 2009-02-10 19:22:43.915068626 +0100
+++ xfs/fs/xfs/xfs_log_priv.h 2009-02-10 19:45:54.102069909 +0100
@@ -142,7 +142,7 @@ static inline uint xlog_get_client_id(__
/*
* Flags for log structure
*/
-#define XLOG_CHKSUM_MISMATCH 0x1 /* used only during recovery */
+#define XLOG_CRC_MISMATCH 0x1 /* used only during recovery */
#define XLOG_ACTIVE_RECOVERY 0x2 /* in the middle of recovery */
#define XLOG_RECOVERY_NEEDED 0x4 /* log was recovered */
#define XLOG_IO_ERROR 0x8 /* log hit an I/O error, and being
@@ -294,7 +294,7 @@ typedef struct xlog_rec_header {
__be32 h_len; /* len in bytes; should be 64-bit aligned: 4 */
__be64 h_lsn; /* lsn of this LR : 8 */
__be64 h_tail_lsn; /* lsn of 1st LR w/ buffers not committed: 8 */
- __be32 h_chksum; /* may not be used; non-zero if used : 4 */
+ __be32 h_crc; /* crc of log record : 4 */
__be32 h_prev_block; /* block number to previous LR : 4 */
__be32 h_num_logops; /* number of log operations in this LR : 4 */
__be32 h_cycle_data[XLOG_HEADER_CYCLE_SIZE / BBSIZE];
@@ -450,9 +450,11 @@ extern int xlog_find_tail(xlog_t *log,
xfs_daddr_t *tail_blk);
extern int xlog_recover(xlog_t *log);
extern int xlog_recover_finish(xlog_t *log);
-extern void xlog_pack_data(xlog_t *log, xlog_in_core_t *iclog, int);
extern void xlog_recover_process_iunlinks(xlog_t *log);
+extern __be32 xlog_cksum(struct log *log, struct xlog_rec_header *rhead,
+ char *dp, int size);
+
extern struct xfs_buf *xlog_get_bp(xlog_t *, int);
extern void xlog_put_bp(struct xfs_buf *);
Index: xfs/fs/xfs/xfs_log_recover.c
===================================================================
--- xfs.orig/fs/xfs/xfs_log_recover.c 2009-02-10 19:45:53.757070823 +0100
+++ xfs/fs/xfs/xfs_log_recover.c 2009-02-10 19:45:54.105069313 +0100
@@ -47,6 +47,7 @@
#include "xfs_quota.h"
#include "xfs_rw.h"
#include "xfs_utils.h"
+#include "xfs_cksum.h"
STATIC int xlog_find_zeroed(xlog_t *, xfs_daddr_t *);
STATIC int xlog_clear_stale_blocks(xlog_t *, xfs_lsn_t);
@@ -3334,116 +3335,48 @@ xlog_recover_process_iunlinks(
mp->m_dmevmask = mp_dmevmask;
}
-
-#ifdef DEBUG
-STATIC void
-xlog_pack_data_checksum(
- xlog_t *log,
- xlog_in_core_t *iclog,
- int size)
-{
- int i;
- __be32 *up;
- uint chksum = 0;
-
- up = (__be32 *)iclog->ic_datap;
- /* divide length by 4 to get # words */
- for (i = 0; i < (size >> 2); i++) {
- chksum ^= be32_to_cpu(*up);
- up++;
- }
- iclog->ic_header.h_chksum = cpu_to_be32(chksum);
-}
-#else
-#define xlog_pack_data_checksum(log, iclog, size)
-#endif
-
-/*
- * Stamp cycle number in every block
- */
-void
-xlog_pack_data(
- xlog_t *log,
- xlog_in_core_t *iclog,
- int roundoff)
-{
- int i, j, k;
- int size = iclog->ic_offset + roundoff;
- __be32 cycle_lsn;
- xfs_caddr_t dp;
-
- xlog_pack_data_checksum(log, iclog, size);
-
- cycle_lsn = CYCLE_LSN_DISK(iclog->ic_header.h_lsn);
-
- dp = iclog->ic_datap;
- for (i = 0; i < BTOBB(size) &&
- i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) {
- iclog->ic_header.h_cycle_data[i] = *(__be32 *)dp;
- *(__be32 *)dp = cycle_lsn;
- dp += BBSIZE;
- }
-
- if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
- xlog_in_core_2_t *xhdr = iclog->ic_data;
-
- for ( ; i < BTOBB(size); i++) {
- j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
- k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
- xhdr[j].hic_xheader.xh_cycle_data[k] = *(__be32 *)dp;
- *(__be32 *)dp = cycle_lsn;
- dp += BBSIZE;
- }
-
- for (i = 1; i < log->l_iclog_heads; i++) {
- xhdr[i].hic_xheader.xh_cycle = cycle_lsn;
- }
- }
-}
-
-#if defined(DEBUG) && defined(XFS_LOUD_RECOVERY)
-STATIC void
-xlog_unpack_data_checksum(
+STATIC int
+xlog_unpack_data_crc(
xlog_rec_header_t *rhead,
xfs_caddr_t dp,
xlog_t *log)
{
- __be32 *up = (__be32 *)dp;
- uint chksum = 0;
- int i;
+ __be32 crc;
- /* divide length by 4 to get # words */
- for (i=0; i < be32_to_cpu(rhead->h_len) >> 2; i++) {
- chksum ^= be32_to_cpu(*up);
- up++;
- }
- if (chksum != be32_to_cpu(rhead->h_chksum)) {
- if (rhead->h_chksum ||
- ((log->l_flags & XLOG_CHKSUM_MISMATCH) == 0)) {
- cmn_err(CE_DEBUG,
- "XFS: LogR chksum mismatch: was (0x%x) is (0x%x)\n",
- be32_to_cpu(rhead->h_chksum), chksum);
- cmn_err(CE_DEBUG,
-"XFS: Disregard message if filesystem was created with non-DEBUG kernel");
- if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
- cmn_err(CE_DEBUG,
- "XFS: LogR this is a LogV2 filesystem\n");
- }
- log->l_flags |= XLOG_CHKSUM_MISMATCH;
- }
+ crc = xlog_cksum(log, rhead, dp, be32_to_cpu(rhead->h_len));
+ if (crc != rhead->h_crc) {
+ cmn_err(CE_ALERT, "XFS recovery: log record CRC error: "
+ "found 0x%x, expected 0x%x.\n",
+ be32_to_cpu(rhead->h_crc),
+ be32_to_cpu(crc));
+ print_hex_dump(KERN_ALERT, "record: ", 0, 32, 1, dp, 32, 0);
+
+ /*
+ * If we've detected a log record corruption, then we
+ * can't recover past this point. Abort recovery and
+ * punt an error back up the stack.
+ */
+ log->l_flags |= XLOG_CRC_MISMATCH;
+ return EUCLEAN;
}
+
+ return 0;
}
-#else
-#define xlog_unpack_data_checksum(rhead, dp, log)
-#endif
-STATIC void
+STATIC int
xlog_unpack_data(
xlog_rec_header_t *rhead,
xfs_caddr_t dp,
xlog_t *log)
{
int i, j, k;
+ int error;
+
+ if (xfs_sb_version_hascrc(&log->l_mp->m_sb)) {
+ error = xlog_unpack_data_crc(rhead, dp, log);
+ if (error)
+ return error;
+ }
for (i = 0; i < BTOBB(be32_to_cpu(rhead->h_len)) &&
i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) {
@@ -3461,7 +3394,7 @@ xlog_unpack_data(
}
}
- xlog_unpack_data_checksum(rhead, dp, log);
+ return 0;
}
STATIC int
@@ -3593,9 +3526,13 @@ xlog_do_recovery_pass(
if (error)
goto bread_err2;
- xlog_unpack_data(rhead, offset, log);
- if ((error = xlog_recover_process_data(log,
- rhash, rhead, offset, pass)))
+ error = xlog_unpack_data(rhead, offset, log);
+ if (error)
+ goto bread_err2;
+
+ error = xlog_recover_process_data(log,
+ rhash, rhead, offset, pass);
+ if (error)
goto bread_err2;
blk_no += bblks + hblks;
}
@@ -3734,9 +3671,14 @@ xlog_do_recovery_pass(
offset = xlog_align(log, wrapped_hblks,
bblks - split_bblks, dbp);
}
- xlog_unpack_data(rhead, offset, log);
- if ((error = xlog_recover_process_data(log, rhash,
- rhead, offset, pass)))
+
+ error = xlog_unpack_data(rhead, offset, log);
+ if (error)
+ goto bread_err2;
+
+ error = xlog_recover_process_data(log, rhash,
+ rhead, offset, pass);
+ if (error)
goto bread_err2;
blk_no += bblks;
}
@@ -3761,9 +3703,13 @@ xlog_do_recovery_pass(
if (error)
goto bread_err2;
- xlog_unpack_data(rhead, offset, log);
- if ((error = xlog_recover_process_data(log, rhash,
- rhead, offset, pass)))
+ error = xlog_unpack_data(rhead, offset, log);
+ if (error)
+ goto bread_err2;
+
+ error = xlog_recover_process_data(log, rhash,
+ rhead, offset, pass);
+ if (error)
goto bread_err2;
blk_no += bblks + hblks;
}
Index: xfs/fs/xfs/xfs_log.c
===================================================================
--- xfs.orig/fs/xfs/xfs_log.c 2009-02-10 19:21:28.338068613 +0100
+++ xfs/fs/xfs/xfs_log.c 2009-02-10 19:45:54.108070252 +0100
@@ -40,6 +40,7 @@
#include "xfs_dinode.h"
#include "xfs_inode.h"
#include "xfs_rw.h"
+#include "xfs_cksum.h"
kmem_zone_t *xfs_log_ticket_zone;
@@ -1407,6 +1408,83 @@ xlog_grant_push_ail(xfs_mount_t *mp,
xfs_trans_ail_push(log->l_ailp, threshold_lsn);
} /* xlog_grant_push_ail */
+/*
+ * Stamp cycle number in every block
+ */
+STATIC void
+xlog_pack_data(
+ xlog_t *log,
+ xlog_in_core_t *iclog,
+ int roundoff)
+{
+ int i, j, k;
+ int size = iclog->ic_offset + roundoff;
+ __be32 cycle_lsn;
+ xfs_caddr_t dp;
+
+ cycle_lsn = CYCLE_LSN_DISK(iclog->ic_header.h_lsn);
+
+ dp = iclog->ic_datap;
+ for (i = 0; i < BTOBB(size); i++) {
+ if (i >= (XLOG_HEADER_CYCLE_SIZE / BBSIZE))
+ break;
+ iclog->ic_header.h_cycle_data[i] = *(__be32 *)dp;
+ *(__be32 *)dp = cycle_lsn;
+ dp += BBSIZE;
+ }
+
+ if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
+ xlog_in_core_2_t *xhdr = iclog->ic_data;
+
+ for ( ; i < BTOBB(size); i++) {
+ j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
+ k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
+ xhdr[j].hic_xheader.xh_cycle_data[k] = *(__be32 *)dp;
+ *(__be32 *)dp = cycle_lsn;
+ dp += BBSIZE;
+ }
+
+ for (i = 1; i < log->l_iclog_heads; i++)
+ xhdr[i].hic_xheader.xh_cycle = cycle_lsn;
+ }
+}
+
+/*
+ * Calculate the checksum for a log buffer.
+ *
+ * This is a little more complicated than it should be because the various
+ * headers and the actual data are non-contiguous.
+ */
+__be32
+xlog_cksum(
+ struct log *log,
+ struct xlog_rec_header *rhead,
+ char *dp,
+ int size)
+{
+ __uint32_t crc;
+
+ /* first generate the crc for the record header ... */
+ crc = xfs_start_cksum((char *)rhead,
+ sizeof(struct xlog_rec_header),
+ offsetof(struct xlog_rec_header, h_crc));
+
+ /* ... then for additional cycle data for v2 logs ... */
+ if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
+ union xlog_in_core2 *xhdr = (union xlog_in_core2 *)rhead;
+ int i;
+
+ for (i = 1; i < log->l_iclog_heads; i++) {
+ crc = crc32c(crc, &xhdr[i].hic_xheader,
+ sizeof(struct xlog_rec_ext_header));
+ }
+ }
+
+ /* ... and finally for the payload */
+ crc = crc32c(crc, dp, size);
+
+ return xfs_end_cksum(crc);
+}
/*
* Flush out the in-core log (iclog) to the on-disk log in an asynchronous
@@ -1437,7 +1515,6 @@ STATIC int
xlog_sync(xlog_t *log,
xlog_in_core_t *iclog)
{
- xfs_caddr_t dptr; /* pointer to byte sized element */
xfs_buf_t *bp;
int i;
uint count; /* byte count of bwrite */
@@ -1446,6 +1523,7 @@ xlog_sync(xlog_t *log,
int split = 0; /* split write into two regions */
int error;
int v2 = xfs_sb_version_haslogv2(&log->l_mp->m_sb);
+ int size;
XFS_STATS_INC(xs_log_writes);
ASSERT(atomic_read(&iclog->ic_refcnt) == 0);
@@ -1477,13 +1555,10 @@ xlog_sync(xlog_t *log,
xlog_pack_data(log, iclog, roundoff);
/* real byte length */
- if (v2) {
- iclog->ic_header.h_len =
- cpu_to_be32(iclog->ic_offset + roundoff);
- } else {
- iclog->ic_header.h_len =
- cpu_to_be32(iclog->ic_offset);
- }
+ size = iclog->ic_offset;
+ if (v2)
+ size += roundoff;
+ iclog->ic_header.h_len = cpu_to_be32(size);
bp = iclog->ic_bp;
ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) == (unsigned long)1);
@@ -1494,12 +1569,39 @@ xlog_sync(xlog_t *log,
/* Do we need to split this write into 2 parts? */
if (XFS_BUF_ADDR(bp) + BTOBB(count) > log->l_logBBsize) {
+ char *dptr;
+
split = count - (BBTOB(log->l_logBBsize - XFS_BUF_ADDR(bp)));
count = BBTOB(log->l_logBBsize - XFS_BUF_ADDR(bp));
- iclog->ic_bwritecnt = 2; /* split into 2 writes */
+ iclog->ic_bwritecnt = 2;
+
+ /*
+ * Bump the cycle numbers at the start of each block in the
+ * part of the iclog that ends up in the buffer that gets
+ * written to the start of the log.
+ *
+ * Watch out for the header magic number case, though.
+ */
+ dptr = (char *)&iclog->ic_header + count;
+ for (i = 0; i < split; i += BBSIZE) {
+ __uint32_t cycle = be32_to_cpu(*(__be32 *)dptr);
+ if (++cycle == XLOG_HEADER_MAGIC_NUM)
+ cycle++;
+ *(__be32 *)dptr = cpu_to_be32(cycle);
+
+ dptr += BBSIZE;
+ }
} else {
iclog->ic_bwritecnt = 1;
}
+
+ /* calculcate the checksum */
+ if (xfs_sb_version_hascrc(&log->l_mp->m_sb)) {
+ iclog->ic_header.h_crc =
+ xlog_cksum(log, &iclog->ic_header,
+ iclog->ic_datap, size);
+ }
+
XFS_BUF_SET_COUNT(bp, count);
XFS_BUF_SET_FSPRIVATE(bp, iclog); /* save for later */
XFS_BUF_ZEROFLAGS(bp);
@@ -1536,27 +1638,13 @@ xlog_sync(xlog_t *log,
(unsigned long)1);
XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)2);
XFS_BUF_SET_ADDR(bp, 0); /* logical 0 */
- XFS_BUF_SET_PTR(bp, (xfs_caddr_t)((__psint_t)&(iclog->ic_header)+
- (__psint_t)count), split);
+ XFS_BUF_SET_PTR(bp, (char *)&iclog->ic_header + count, split);
XFS_BUF_SET_FSPRIVATE(bp, iclog);
XFS_BUF_ZEROFLAGS(bp);
XFS_BUF_BUSY(bp);
XFS_BUF_ASYNC(bp);
if (log->l_mp->m_flags & XFS_MOUNT_BARRIER)
XFS_BUF_ORDERED(bp);
- dptr = XFS_BUF_PTR(bp);
- /*
- * Bump the cycle numbers at the start of each block
- * since this part of the buffer is at the start of
- * a new cycle. Watch out for the header magic number
- * case, though.
- */
- for (i = 0; i < split; i += BBSIZE) {
- be32_add_cpu((__be32 *)dptr, 1);
- if (be32_to_cpu(*(__be32 *)dptr) == XLOG_HEADER_MAGIC_NUM)
- be32_add_cpu((__be32 *)dptr, 1);
- dptr += BBSIZE;
- }
ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1);
ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize);
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 12/13] xfs: add version 3 inode format with CRCs
2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
` (10 preceding siblings ...)
2009-02-10 20:22 ` [PATCH 11/13] xfs: add CRC checks to the log Christoph Hellwig
@ 2009-02-10 20:22 ` Christoph Hellwig
2009-02-12 6:38 ` Josef 'Jeff' Sipek
2009-02-10 20:22 ` [PATCH 13/13] xfs: add CRC checks for quota blocks Christoph Hellwig
12 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
To: xfs
[-- Attachment #1: xfs-inode-crc --]
[-- Type: text/plain, Size: 15143 bytes --]
Add a new inode version with a larger core. The primary objective is
to allow for a crc of the inode, and location information (uuid and ino)
to verify it was written in the right place. We also extend it by
a creation time (for Samba) and a changecount (for NFSv4) and some
additional padding. These additional fields are not implemented yet,
but already layed out in the structure.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: xfs/fs/xfs/xfs_inode.h
===================================================================
--- xfs.orig/fs/xfs/xfs_inode.h 2009-02-10 19:45:50.921943721 +0100
+++ xfs/fs/xfs/xfs_inode.h 2009-02-10 19:45:59.186069347 +0100
@@ -152,6 +152,11 @@ typedef struct xfs_icdinode {
__uint32_t di_gen; /* generation number */
} xfs_icdinode_t;
+static inline uint xfs_icdinode_size(struct xfs_icdinode *dicp)
+{
+ return sizeof(struct xfs_icdinode);
+}
+
/*
* Flags for xfs_ichgtime().
*/
Index: xfs/fs/xfs/xfs_inode_item.c
===================================================================
--- xfs.orig/fs/xfs/xfs_inode_item.c 2009-02-10 19:16:18.696943663 +0100
+++ xfs/fs/xfs/xfs_inode_item.c 2009-02-10 19:45:59.190098211 +0100
@@ -281,7 +281,7 @@ xfs_inode_item_format(
xfs_mark_inode_dirty_sync(ip);
vecp->i_addr = (xfs_caddr_t)&ip->i_d;
- vecp->i_len = sizeof(struct xfs_icdinode);
+ vecp->i_len = xfs_icdinode_size(&ip->i_d);
XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_ICORE);
vecp++;
nvecs++;
Index: xfs/fs/xfs/xfs_log_recover.c
===================================================================
--- xfs.orig/fs/xfs/xfs_log_recover.c 2009-02-10 19:45:54.105069313 +0100
+++ xfs/fs/xfs/xfs_log_recover.c 2009-02-10 19:46:08.354069897 +0100
@@ -2325,6 +2325,7 @@ xlog_recover_do_inode_trans(
int attr_index;
uint fields;
xfs_icdinode_t *dicp;
+ uint isize;
int need_free = 0;
if (pass == XLOG_RECOVER_PASS1) {
@@ -2459,7 +2460,9 @@ xlog_recover_do_inode_trans(
error = EFSCORRUPTED;
goto error;
}
- if (unlikely(item->ri_buf[1].i_len > sizeof(struct xfs_icdinode))) {
+
+ isize = xfs_icdinode_size(dicp);
+ if (unlikely(item->ri_buf[1].i_len > isize)) {
XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(7)",
XFS_ERRLEVEL_LOW, mp, dicp);
xfs_buf_relse(bp);
@@ -2471,13 +2474,13 @@ xlog_recover_do_inode_trans(
}
/* The core is in in-core format */
- xfs_dinode_to_disk(dip, (xfs_icdinode_t *)item->ri_buf[1].i_addr);
+ xfs_dinode_to_disk(dip, dicp);
/* the rest is in on-disk format */
- if (item->ri_buf[1].i_len > sizeof(struct xfs_icdinode)) {
- memcpy((xfs_caddr_t) dip + sizeof(struct xfs_icdinode),
- item->ri_buf[1].i_addr + sizeof(struct xfs_icdinode),
- item->ri_buf[1].i_len - sizeof(struct xfs_icdinode));
+ if (item->ri_buf[1].i_len > isize) {
+ memcpy((xfs_caddr_t) dip + isize,
+ item->ri_buf[1].i_addr + isize,
+ item->ri_buf[1].i_len - isize);
}
fields = in_f->ilf_fields;
@@ -2561,6 +2564,15 @@ xlog_recover_do_inode_trans(
}
write_inode_buffer:
+ /* re-generate the checksum. */
+ if (dip->di_version == 3) {
+ __uint32_t crc;
+
+ crc = xfs_start_cksum((char *)dip, mp->m_sb.sb_inodesize,
+ offsetof(struct xfs_dinode, di_crc));
+ dip->di_crc = xfs_end_cksum(crc);
+ }
+
if (ITEM_TYPE(item) == XFS_LI_INODE) {
ASSERT(bp->b_mount == NULL || bp->b_mount == mp);
bp->b_mount = mp;
Index: xfs/fs/xfs/xfs_dinode.h
===================================================================
--- xfs.orig/fs/xfs/xfs_dinode.h 2009-02-10 19:45:51.939069576 +0100
+++ xfs/fs/xfs/xfs_dinode.h 2009-02-10 19:45:59.195068745 +0100
@@ -19,7 +19,7 @@
#define __XFS_DINODE_H__
#define XFS_DINODE_MAGIC 0x494e /* 'IN' */
-#define XFS_DINODE_GOOD_VERSION(v) (((v) == 1 || (v) == 2))
+#define XFS_DINODE_GOOD_VERSION(v) ((v) >= 1 && (v) <= 3)
typedef struct xfs_timestamp {
__be32 t_sec; /* timestamp seconds */
@@ -69,11 +69,32 @@ typedef struct xfs_dinode {
/* di_next_unlinked is the only non-core field in the old dinode */
__be32 di_next_unlinked;/* agi unlinked list ptr */
-} __attribute__((packed)) xfs_dinode_t;
+
+ /* start of the extended dinode, writable fields */
+ __be32 di_crc; /* CRC of the inode */
+ __be64 di_changecount; /* number of attribute changes */
+ __u8 di_pad2[16]; /* more padding for future expansion */
+
+ /* fields only written to during inode creation */
+ xfs_timestamp_t di_crtime; /* time created */
+ __be64 di_ino; /* inode number */
+ uuid_t di_uuid; /* UUID of the filesystem */
+} xfs_dinode_t;
#define DI_MAX_FLUSH 0xffff
/*
+ * Size of the core inode on disk. Version 1 and 2 inodes have
+ * the same size, but version 3 has grown a few additional fields.
+ */
+static inline uint xfs_dinode_size(int version)
+{
+ if (version == 3)
+ return sizeof(struct xfs_dinode);
+ return offsetof(struct xfs_dinode, di_crc);
+}
+
+/*
* The 32 bit link count in the inode theoretically maxes out at UINT_MAX.
* Since the pathconf interface is signed, we use 2^31 - 1 instead.
* The old inode format had a 16 bit link count, so its maximum is USHRT_MAX.
@@ -104,7 +125,7 @@ typedef enum xfs_dinode_fmt {
* Inode size for given fs.
*/
#define XFS_LITINO(version, mp) \
- ((int)(((mp)->m_sb.sb_inodesize) - sizeof(struct xfs_dinode)))
+ ((int)(((mp)->m_sb.sb_inodesize) - xfs_dinode_size(version)))
#define XFS_BROOT_SIZE_ADJ(ip) \
(XFS_BMBT_BLOCK_LEN((ip)->i_mount) - sizeof(xfs_bmdr_block_t))
@@ -132,7 +153,7 @@ typedef enum xfs_dinode_fmt {
* Return pointers to the data or attribute forks.
*/
#define XFS_DFORK_DPTR(dip) \
- ((char *)(dip) + sizeof(struct xfs_dinode))
+ ((char *)dip + xfs_dinode_size(dip->di_version))
#define XFS_DFORK_APTR(dip) \
(XFS_DFORK_DPTR(dip) + XFS_DFORK_BOFF(dip))
#define XFS_DFORK_PTR(dip,w) \
Index: xfs/fs/xfs/xfs_ialloc.c
===================================================================
--- xfs.orig/fs/xfs/xfs_ialloc.c 2009-02-10 19:45:53.408069901 +0100
+++ xfs/fs/xfs/xfs_ialloc.c 2009-02-10 19:46:08.351069375 +0100
@@ -163,6 +163,7 @@ xfs_ialloc_ag_alloc(
xfs_buf_t *agbp, /* alloc group buffer */
int *alloc)
{
+ xfs_mount_t *mp = tp->t_mountp;
xfs_agi_t *agi; /* allocation group header */
xfs_alloc_arg_t args; /* allocation argument structure */
int blks_per_cluster; /* fs blocks per inode cluster */
@@ -191,11 +192,10 @@ xfs_ialloc_ag_alloc(
* Locking will ensure that we don't have two callers in here
* at one time.
*/
- newlen = XFS_IALLOC_INODES(args.mp);
- if (args.mp->m_maxicount &&
- args.mp->m_sb.sb_icount + newlen > args.mp->m_maxicount)
+ newlen = XFS_IALLOC_INODES(mp);
+ if (mp->m_maxicount && mp->m_sb.sb_icount + newlen > mp->m_maxicount)
return XFS_ERROR(ENOSPC);
- args.minlen = args.maxlen = XFS_IALLOC_BLOCKS(args.mp);
+ args.minlen = args.maxlen = XFS_IALLOC_BLOCKS(mp);
/*
* First try to allocate inodes contiguous with the last-allocated
* chunk of inodes. If the filesystem is striped, this will fill
@@ -203,12 +203,13 @@ xfs_ialloc_ag_alloc(
*/
agi = XFS_BUF_TO_AGI(agbp);
newino = be32_to_cpu(agi->agi_newino);
- args.agbno = XFS_AGINO_TO_AGBNO(args.mp, newino) +
- XFS_IALLOC_BLOCKS(args.mp);
+ agno = be32_to_cpu(agi->agi_seqno);
+
+ args.agbno = XFS_AGINO_TO_AGBNO(mp, newino) + XFS_IALLOC_BLOCKS(mp);
+
if (likely(newino != NULLAGINO &&
(args.agbno < be32_to_cpu(agi->agi_length)))) {
- args.fsbno = XFS_AGB_TO_FSB(args.mp,
- be32_to_cpu(agi->agi_seqno), args.agbno);
+ args.fsbno = XFS_AGB_TO_FSB(mp, agno, args.agbno);
args.type = XFS_ALLOCTYPE_THIS_BNO;
args.mod = args.total = args.wasdel = args.isfl =
args.userdata = args.minalignslop = 0;
@@ -231,7 +232,7 @@ xfs_ialloc_ag_alloc(
args.minalignslop = xfs_ialloc_cluster_alignment(&args) - 1;
/* Allow space for the inode btree to split. */
- args.minleft = args.mp->m_in_maxlevels - 1;
+ args.minleft = mp->m_in_maxlevels - 1;
if ((error = xfs_alloc_vextent(&args)))
return error;
} else
@@ -247,9 +248,9 @@ xfs_ialloc_ag_alloc(
* pieces, so don't need alignment anyway.
*/
isaligned = 0;
- if (args.mp->m_sinoalign) {
- ASSERT(!(args.mp->m_flags & XFS_MOUNT_NOALIGN));
- args.alignment = args.mp->m_dalign;
+ if (mp->m_sinoalign) {
+ ASSERT(!(mp->m_flags & XFS_MOUNT_NOALIGN));
+ args.alignment = mp->m_dalign;
isaligned = 1;
} else
args.alignment = xfs_ialloc_cluster_alignment(&args);
@@ -259,8 +260,7 @@ xfs_ialloc_ag_alloc(
* For now, just allocate blocks up front.
*/
args.agbno = be32_to_cpu(agi->agi_root);
- args.fsbno = XFS_AGB_TO_FSB(args.mp,
- be32_to_cpu(agi->agi_seqno), args.agbno);
+ args.fsbno = XFS_AGB_TO_FSB(mp, agno, args.agbno);
/*
* Allocate a fixed-size extent of inodes.
*/
@@ -271,7 +271,7 @@ xfs_ialloc_ag_alloc(
/*
* Allow space for the inode btree to split.
*/
- args.minleft = args.mp->m_in_maxlevels - 1;
+ args.minleft = mp->m_in_maxlevels - 1;
if ((error = xfs_alloc_vextent(&args)))
return error;
}
@@ -283,8 +283,7 @@ xfs_ialloc_ag_alloc(
if (isaligned && args.fsbno == NULLFSBLOCK) {
args.type = XFS_ALLOCTYPE_NEAR_BNO;
args.agbno = be32_to_cpu(agi->agi_root);
- args.fsbno = XFS_AGB_TO_FSB(args.mp,
- be32_to_cpu(agi->agi_seqno), args.agbno);
+ args.fsbno = XFS_AGB_TO_FSB(mp, agno, args.agbno);
args.alignment = xfs_ialloc_cluster_alignment(&args);
if ((error = xfs_alloc_vextent(&args)))
return error;
@@ -298,21 +297,21 @@ xfs_ialloc_ag_alloc(
/*
* Convert the results.
*/
- newino = XFS_OFFBNO_TO_AGINO(args.mp, args.agbno, 0);
+ newino = XFS_OFFBNO_TO_AGINO(mp, args.agbno, 0);
/*
* Loop over the new block(s), filling in the inodes.
* For small block sizes, manipulate the inodes in buffers
* which are multiples of the blocks size.
*/
- if (args.mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(args.mp)) {
+ if (mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(mp)) {
blks_per_cluster = 1;
nbufs = (int)args.len;
- ninodes = args.mp->m_sb.sb_inopblock;
+ ninodes = mp->m_sb.sb_inopblock;
} else {
- blks_per_cluster = XFS_INODE_CLUSTER_SIZE(args.mp) /
- args.mp->m_sb.sb_blocksize;
+ blks_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) /
+ mp->m_sb.sb_blocksize;
nbufs = (int)args.len / blks_per_cluster;
- ninodes = blks_per_cluster * args.mp->m_sb.sb_inopblock;
+ ninodes = blks_per_cluster * mp->m_sb.sb_inopblock;
}
/*
* Figure out what version number to use in the inodes we create.
@@ -321,7 +320,9 @@ xfs_ialloc_ag_alloc(
* use the old version so that old kernels will continue to be
* able to use the file system.
*/
- if (xfs_sb_version_hasnlink(&args.mp->m_sb))
+ if (xfs_sb_version_hascrc(&mp->m_sb))
+ version = 3;
+ else if (xfs_sb_version_hasnlink(&mp->m_sb))
version = 2;
else
version = 1;
@@ -335,13 +336,15 @@ xfs_ialloc_ag_alloc(
*/
gen = random32();
for (j = 0; j < nbufs; j++) {
+ xfs_agblock_t agbno;
+
/*
* Get the block.
*/
- d = XFS_AGB_TO_DADDR(args.mp, be32_to_cpu(agi->agi_seqno),
- args.agbno + (j * blks_per_cluster));
- fbuf = xfs_trans_get_buf(tp, args.mp->m_ddev_targp, d,
- args.mp->m_bsize * blks_per_cluster,
+ agbno = args.agbno + (j * blks_per_cluster);
+ d = XFS_AGB_TO_DADDR(mp, agno, agbno);
+ fbuf = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
+ mp->m_bsize * blks_per_cluster,
XFS_BUF_LOCK);
ASSERT(fbuf);
ASSERT(!XFS_BUF_GETERROR(fbuf));
@@ -353,31 +356,44 @@ xfs_ialloc_ag_alloc(
* log a whole cluster of inodes instead of all the indivdual
* transactions causing a lot of log traffic.
*/
- xfs_biozero(fbuf, 0, ninodes << args.mp->m_sb.sb_inodelog);
+ xfs_biozero(fbuf, 0, ninodes << mp->m_sb.sb_inodelog);
for (i = 0; i < ninodes; i++) {
- int ioffset = i << args.mp->m_sb.sb_inodelog;
- uint isize = sizeof(struct xfs_dinode);
+ int ioffset = i << mp->m_sb.sb_inodelog;
+ uint isize = xfs_dinode_size(version);
- free = xfs_make_iptr(args.mp, fbuf, i);
+ free = xfs_make_iptr(mp, fbuf, i);
free->di_magic = cpu_to_be16(XFS_DINODE_MAGIC);
free->di_version = version;
free->di_gen = cpu_to_be32(gen);
free->di_next_unlinked = cpu_to_be32(NULLAGINO);
+
+ if (version == 3) {
+ __uint32_t crc;
+
+ free->di_ino = cpu_to_be64(
+ XFS_AGINO_TO_INO(mp, agno,
+ XFS_OFFBNO_TO_AGINO(mp, agbno, i)));
+ uuid_copy(&free->di_uuid, &mp->m_sb.sb_uuid);
+
+ crc = xfs_start_cksum((char *)free,
+ mp->m_sb.sb_inodesize,
+ offsetof(struct xfs_dinode, di_crc));
+ free->di_crc = xfs_end_cksum(crc);
+ }
xfs_trans_log_buf(tp, fbuf, ioffset, ioffset + isize - 1);
}
xfs_trans_inode_alloc_buf(tp, fbuf);
}
be32_add_cpu(&agi->agi_count, newlen);
be32_add_cpu(&agi->agi_freecount, newlen);
- agno = be32_to_cpu(agi->agi_seqno);
- down_read(&args.mp->m_peraglock);
- args.mp->m_perag[agno].pagi_freecount += newlen;
- up_read(&args.mp->m_peraglock);
+ down_read(&mp->m_peraglock);
+ mp->m_perag[agno].pagi_freecount += newlen;
+ up_read(&mp->m_peraglock);
agi->agi_newino = cpu_to_be32(newino);
/*
* Insert records describing the new inode chunk into the btree.
*/
- cur = xfs_inobt_init_cursor(args.mp, tp, agbp, agno);
+ cur = xfs_inobt_init_cursor(mp, tp, agbp, agno);
for (thisino = newino;
thisino < newino + newlen;
thisino += XFS_INODES_PER_CHUNK) {
Index: xfs/fs/xfs/xfs_inode.c
===================================================================
--- xfs.orig/fs/xfs/xfs_inode.c 2009-02-10 19:46:02.110944088 +0100
+++ xfs/fs/xfs/xfs_inode.c 2009-02-10 19:46:08.309069135 +0100
@@ -52,6 +52,7 @@
#include "xfs_acl.h"
#include "xfs_filestream.h"
#include "xfs_vnodeops.h"
+#include "xfs_cksum.h"
kmem_zone_t *xfs_ifork_zone;
kmem_zone_t *xfs_inode_zone;
@@ -827,6 +828,23 @@ xfs_iread(
* Otherwise, just get the truly permanent information.
*/
if (dip->di_mode) {
+ /* validate the checksum. */
+ if (dip->di_version == 3) {
+ if (!xfs_verify_cksum((char *)dip, mp->m_sb.sb_inodesize,
+ offsetof(struct xfs_dinode, di_crc)) ||
+ !uuid_equal(&dip->di_uuid, &mp->m_sb.sb_uuid) ||
+ be64_to_cpu(dip->di_ino) != ip->i_ino) {
+ xfs_fs_cmn_err(CE_ALERT, mp,
+ "xfs_iread: checksum validation failed for inode %lld", ip->i_ino);
+
+ XFS_CORRUPTION_ERROR("xfs_iread crc",
+ XFS_ERRLEVEL_LOW,
+ mp, dip);
+ error = XFS_ERROR(EFSCORRUPTED);
+ goto out_brelse;
+ }
+ }
+
xfs_dinode_from_disk(&ip->i_d, dip);
error = xfs_iformat(ip, dip);
if (error) {
@@ -3171,6 +3189,15 @@ xfs_iflush_int(
xfs_iflush_fork(ip, dip, iip, XFS_ATTR_FORK, bp);
xfs_inobp_check(mp, bp);
+ /* generate the checksum. */
+ if (dip->di_version == 3) {
+ __uint32_t crc;
+
+ crc = xfs_start_cksum((char *)dip, mp->m_sb.sb_inodesize,
+ offsetof(struct xfs_dinode, di_crc));
+ dip->di_crc = xfs_end_cksum(crc);
+ }
+
/*
* We've recorded everything logged in the inode, so we'd
* like to clear the ilf_fields bits so we don't log and
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 13/13] xfs: add CRC checks for quota blocks
2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
` (11 preceding siblings ...)
2009-02-10 20:22 ` [PATCH 12/13] xfs: add version 3 inode format with CRCs Christoph Hellwig
@ 2009-02-10 20:22 ` Christoph Hellwig
2009-02-12 6:41 ` Josef 'Jeff' Sipek
12 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
To: xfs
[-- Attachment #1: xfs-quota-crc --]
[-- Type: text/plain, Size: 4270 bytes --]
Use the reserved space in struct xfs_dqblk to store a UUID and a crc
for the quota blocks.
I'm pondering if we should just move the crc check into xfs_qm_dqcheck
where all the other validity checks are located.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: xfs/fs/xfs/xfs_quota.h
===================================================================
--- xfs.orig/fs/xfs/xfs_quota.h 2009-02-09 08:47:34.234069111 +0100
+++ xfs/fs/xfs/xfs_quota.h 2009-02-10 20:15:36.874947481 +0100
@@ -77,7 +77,13 @@ typedef struct xfs_disk_dquot {
*/
typedef struct xfs_dqblk {
xfs_disk_dquot_t dd_diskdq; /* portion that lives incore as well */
- char dd_fill[32]; /* filling for posterity */
+ char dd_fill[12]; /* filling for posterity */
+
+ /*
+ * These two are only present one filesystems with the CRC bits set.
+ */
+ __be32 dd_crc; /* checksum */
+ uuid_t dd_uuid; /* location information */
} xfs_dqblk_t;
/*
Index: xfs/fs/xfs/quota/xfs_dquot.c
===================================================================
--- xfs.orig/fs/xfs/quota/xfs_dquot.c 2009-02-10 19:55:01.982070089 +0100
+++ xfs/fs/xfs/quota/xfs_dquot.c 2009-02-10 20:23:25.618944664 +0100
@@ -48,6 +48,7 @@
#include "xfs_trans_space.h"
#include "xfs_trans_priv.h"
#include "xfs_qm.h"
+#include "xfs_cksum.h"
/*
@@ -368,6 +369,40 @@ xfs_qm_adjust_dqtimers(
}
}
+STATIC void
+xfs_dquot_calc_crc(
+ struct xfs_buf *bp)
+{
+ struct xfs_dqblk *d = (struct xfs_dqblk *)XFS_BUF_PTR(bp);
+ int i;
+
+ for (i = 0; i < XFS_QM_DQPERBLK(bp->b_mount); i++, d++) {
+ xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk),
+ offsetof(struct xfs_dqblk, dd_crc));
+ }
+}
+
+STATIC int
+xfs_dquot_verify_crc(
+ struct xfs_mount *mp,
+ struct xfs_buf *bp)
+{
+ struct xfs_dqblk *d = (struct xfs_dqblk *)XFS_BUF_PTR(bp);
+ int i;
+
+ for (i = 0; i < XFS_QM_DQPERBLK(mp); i++, d++) {
+ if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk),
+ offsetof(struct xfs_dqblk, dd_crc))) {
+// !uuid_equal(&agfl->agfl_uuid, &mp->m_sb.sb_uuid) ||
+ XFS_CORRUPTION_ERROR("xfs_qm_dqtobp crc",
+ XFS_ERRLEVEL_LOW, mp, d);
+ return XFS_ERROR(EFSCORRUPTED);
+ }
+ }
+
+ return 0;
+}
+
/*
* initialize a buffer full of dquots and log the whole thing
*/
@@ -476,6 +511,10 @@ xfs_qm_dqalloc(
0);
if (!bp || (error = XFS_BUF_GETERROR(bp)))
goto error1;
+
+ if (xfs_sb_version_hascrc(&mp->m_sb))
+ xfs_buf_set_io_callback(bp, xfs_dquot_calc_crc);
+
/*
* Make a chunk of dquots out of this buffer and log
* the entire thing.
@@ -539,6 +578,7 @@ xfs_qm_dqtobp(
xfs_inode_t *quotip;
xfs_mount_t *mp;
xfs_disk_dquot_t *ddq;
+ struct xfs_dqblk *d;
xfs_dqid_t id;
boolean_t newdquot;
xfs_trans_t *tp = (tpp ? *tpp : NULL);
@@ -622,6 +662,22 @@ xfs_qm_dqtobp(
}
if (error || !bp)
return XFS_ERROR(error);
+
+ /*
+ * Validate the CRC of the AGF block only if the block is clean (i.e.
+ * it just came from disk).
+ */
+ if (xfs_sb_version_hascrc(&mp->m_sb) &&
+ !(XFS_BUF_ISWRITE(bp) || XFS_BUF_ISDELAYWRITE(bp))) {
+ error = xfs_dquot_verify_crc(mp, bp);
+ if (error) {
+ xfs_trans_brelse(tp, bp);
+ return error;
+ }
+
+ xfs_buf_set_io_callback(bp, xfs_dquot_calc_crc);
+ }
+
}
ASSERT(XFS_BUF_ISBUSY(bp));
ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
@@ -629,7 +685,8 @@ xfs_qm_dqtobp(
/*
* calculate the location of the dquot inside the buffer.
*/
- ddq = (xfs_disk_dquot_t *)((char *)XFS_BUF_PTR(bp) + dqp->q_bufoffset);
+ d = (struct xfs_dqblk *)(XFS_BUF_PTR(bp) + dqp->q_bufoffset);
+ ddq = &d->dd_diskdq;
/*
* A simple sanity check in case we got a corrupted dquot...
Index: xfs/fs/xfs/quota/xfs_qm.c
===================================================================
--- xfs.orig/fs/xfs/quota/xfs_qm.c 2009-02-10 19:55:02.006069507 +0100
+++ xfs/fs/xfs/quota/xfs_qm.c 2009-02-10 19:58:48.005974236 +0100
@@ -1430,6 +1430,10 @@ xfs_qm_dqiter_bufs(
if (error)
break;
+ /*
+ * XXX(hch): need to figure out if it makes sense to validate
+ * the CRC here.
+ */
xfs_qm_reset_dqcounts(mp, bp, firstid, type);
xfs_bdwrite(mp, bp);
/*
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 10/13] xfs: add CRC checks to the AGFL
2009-02-10 20:22 ` [PATCH 10/13] xfs: add CRC checks to the AGFL Christoph Hellwig
@ 2009-02-11 7:54 ` Dave Chinner
2009-02-15 18:23 ` Christoph Hellwig
0 siblings, 1 reply; 22+ messages in thread
From: Dave Chinner @ 2009-02-11 7:54 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: xfs
On Tue, Feb 10, 2009 at 03:22:51PM -0500, Christoph Hellwig wrote:
> Add CRC checks, location information and a magic number to the AGFL.
> Previously the AGFL was just a block containing nothing but the
> free block pointers. The new AGFL has a real header with the usual
> boilerplate instead, so that we can verify it's not corrupted and
> written into the right place.
I haven't had a chance to look over any of this series in detail - just
a quick glance really - but this popped out as looking wrong:
> +/*
> + * Size of the AGFL. For CRC-enabled filesystes we steal the last two slots
> + * for location information (agno) and the crc.
> + */
> +#define XFS_AGFL_SIZE(mp) \
> + ((mp)->m_sb.sb_sectsize / sizeof(xfs_agblock_t) - \
> + (xfs_sb_version_hascrc(&((mp)->m_sb)) ? sizeof(struct xfs_agfl) : 0))
sb_sectsize is in bytes, sizeof(xfs_agblock_t) is in bytes, which
means that the numerator is a count of the number of agblocks that
will fit in the AGFL. sizeof(struct xfs_agfl) is also in bytes,
so your subtracting a number of bytes from a count of agblocks....
I think you mean:
#define XFS_AGFL_SIZE(mp) \
(((mp)->m_sb.sb_sectsize - (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \
sizeof(struct xfs_agfl) : 0)) \
/ sizeof(xfs_agblock_t))
> typedef struct xfs_agfl {
> - __be32 agfl_bno[1]; /* actually XFS_AGFL_SIZE(mp) */
> + __be32 agfl_magicnum;
> + __be32 agfl_seqno;
> + uuid_t agfl_uuid;
> + __be32 agfl_crc;
> + __be32 agfl_bno[]; /* actually XFS_AGFL_SIZE(mp) */
> } xfs_agfl_t;
And judging by that you are stealing more than 2 slots - more like
8 slots.
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 05/13] xfs: add CRC infrastructure
2009-02-10 20:22 ` [PATCH 05/13] xfs: add CRC infrastructure Christoph Hellwig
@ 2009-02-12 6:10 ` Josef 'Jeff' Sipek
0 siblings, 0 replies; 22+ messages in thread
From: Josef 'Jeff' Sipek @ 2009-02-12 6:10 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: xfs
On Tue, Feb 10, 2009 at 03:22:46PM -0500, Christoph Hellwig wrote:
...
> Index: xfs/fs/xfs/xfs_cksum.h
> ===================================================================
> --- /dev/null 1970-01-01 00:00:00.000000000 +0000
> +++ xfs/fs/xfs/xfs_cksum.h 2009-02-05 19:04:31.282972630 +0100
> @@ -0,0 +1,62 @@
> +#ifndef _XFS_CKSUM_H
> +#define _XFS_CKSUM_H 1
> +
> +#define XFS_CRC_SEED (~(__uint32_t)0)
Is this the final seed you want to use, or was this just a
work-in-progress-non-zero value for testing?
...
> +/*
> + * Convert the intermediate checksum to the final ondisk format.
> + *
> + * Note that crc32c is already endianess agnostic, so no additional
> + * byte swap is needed.
> + */
> +static inline __be32
> +xfs_end_cksum(__uint32_t crc)
> +{
> + return (__force __be32)~crc;
> +}
Why the bit-wise not?
Josef 'Jeff' Sipek.
--
Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are, by
definition, not smart enough to debug it.
- Brian W. Kernighan
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 12/13] xfs: add version 3 inode format with CRCs
2009-02-10 20:22 ` [PATCH 12/13] xfs: add version 3 inode format with CRCs Christoph Hellwig
@ 2009-02-12 6:38 ` Josef 'Jeff' Sipek
2009-02-12 18:42 ` Eric Sandeen
0 siblings, 1 reply; 22+ messages in thread
From: Josef 'Jeff' Sipek @ 2009-02-12 6:38 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: xfs
On Tue, Feb 10, 2009 at 03:22:53PM -0500, Christoph Hellwig wrote:
...
> Index: xfs/fs/xfs/xfs_dinode.h
> ===================================================================
> --- xfs.orig/fs/xfs/xfs_dinode.h 2009-02-10 19:45:51.939069576 +0100
> +++ xfs/fs/xfs/xfs_dinode.h 2009-02-10 19:45:59.195068745 +0100
> @@ -69,11 +69,32 @@ typedef struct xfs_dinode {
>
> /* di_next_unlinked is the only non-core field in the old dinode */
> __be32 di_next_unlinked;/* agi unlinked list ptr */
> -} __attribute__((packed)) xfs_dinode_t;
> +
> + /* start of the extended dinode, writable fields */
> + __be32 di_crc; /* CRC of the inode */
> + __be64 di_changecount; /* number of attribute changes */
> + __u8 di_pad2[16]; /* more padding for future expansion */
> +
> + /* fields only written to during inode creation */
> + xfs_timestamp_t di_crtime; /* time created */
> + __be64 di_ino; /* inode number */
> + uuid_t di_uuid; /* UUID of the filesystem */
> +} xfs_dinode_t;
Hrm...removing the packed attribute... Eric, do you remember the ARM ABI
alignment rules? Regardless of ARM, are those fields aligned nicely? (From a
quick glance at the code looks ok.)
Also, why is the padding filed in the middle of these fields? IOW, why are
crtime/ino/uuid at the end?
Josef 'Jeff' Sipek.
--
Bad pun of the week: The formula 1 control computer suffered from a race
condition
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 13/13] xfs: add CRC checks for quota blocks
2009-02-10 20:22 ` [PATCH 13/13] xfs: add CRC checks for quota blocks Christoph Hellwig
@ 2009-02-12 6:41 ` Josef 'Jeff' Sipek
2009-02-13 20:10 ` Christoph Hellwig
0 siblings, 1 reply; 22+ messages in thread
From: Josef 'Jeff' Sipek @ 2009-02-12 6:41 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: xfs
On Tue, Feb 10, 2009 at 03:22:54PM -0500, Christoph Hellwig wrote:
> Use the reserved space in struct xfs_dqblk to store a UUID and a crc
> for the quota blocks.
>
> I'm pondering if we should just move the crc check into xfs_qm_dqcheck
> where all the other validity checks are located.
>
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
>
> Index: xfs/fs/xfs/xfs_quota.h
> ===================================================================
> --- xfs.orig/fs/xfs/xfs_quota.h 2009-02-09 08:47:34.234069111 +0100
> +++ xfs/fs/xfs/xfs_quota.h 2009-02-10 20:15:36.874947481 +0100
> @@ -77,7 +77,13 @@ typedef struct xfs_disk_dquot {
> */
> typedef struct xfs_dqblk {
> xfs_disk_dquot_t dd_diskdq; /* portion that lives incore as well */
> - char dd_fill[32]; /* filling for posterity */
> + char dd_fill[12]; /* filling for posterity */
> +
> + /*
> + * These two are only present one filesystems with the CRC bits set.
> + */
> + __be32 dd_crc; /* checksum */
> + uuid_t dd_uuid; /* location information */
> } xfs_dqblk_t;
Again, why put the crc/uuid at the end?
> Index: xfs/fs/xfs/quota/xfs_dquot.c
> ===================================================================
> --- xfs.orig/fs/xfs/quota/xfs_dquot.c 2009-02-10 19:55:01.982070089 +0100
> +++ xfs/fs/xfs/quota/xfs_dquot.c 2009-02-10 20:23:25.618944664 +0100
> @@ -368,6 +369,40 @@ xfs_qm_adjust_dqtimers(
...
> +STATIC int
> +xfs_dquot_verify_crc(
> + struct xfs_mount *mp,
> + struct xfs_buf *bp)
> +{
> + struct xfs_dqblk *d = (struct xfs_dqblk *)XFS_BUF_PTR(bp);
> + int i;
> +
> + for (i = 0; i < XFS_QM_DQPERBLK(mp); i++, d++) {
> + if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk),
> + offsetof(struct xfs_dqblk, dd_crc))) {
> +// !uuid_equal(&agfl->agfl_uuid, &mp->m_sb.sb_uuid) ||
Dead code?
Josef 'Jeff' Sipek.
--
FORTUNE PROVIDES QUESTIONS FOR THE GREAT ANSWERS: #19
A: To be or not to be.
Q: What is the square root of 4b^2?
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 12/13] xfs: add version 3 inode format with CRCs
2009-02-12 6:38 ` Josef 'Jeff' Sipek
@ 2009-02-12 18:42 ` Eric Sandeen
2009-02-12 18:51 ` Christoph Hellwig
0 siblings, 1 reply; 22+ messages in thread
From: Eric Sandeen @ 2009-02-12 18:42 UTC (permalink / raw)
To: Josef 'Jeff' Sipek; +Cc: Christoph Hellwig, xfs
Josef 'Jeff' Sipek wrote:
> On Tue, Feb 10, 2009 at 03:22:53PM -0500, Christoph Hellwig wrote:
> ...
>> Index: xfs/fs/xfs/xfs_dinode.h
>> ===================================================================
>> --- xfs.orig/fs/xfs/xfs_dinode.h 2009-02-10 19:45:51.939069576 +0100
>> +++ xfs/fs/xfs/xfs_dinode.h 2009-02-10 19:45:59.195068745 +0100
>> @@ -69,11 +69,32 @@ typedef struct xfs_dinode {
>>
>> /* di_next_unlinked is the only non-core field in the old dinode */
>> __be32 di_next_unlinked;/* agi unlinked list ptr */
>> -} __attribute__((packed)) xfs_dinode_t;
>> +
>> + /* start of the extended dinode, writable fields */
>> + __be32 di_crc; /* CRC of the inode */
>> + __be64 di_changecount; /* number of attribute changes */
>> + __u8 di_pad2[16]; /* more padding for future expansion */
>> +
>> + /* fields only written to during inode creation */
>> + xfs_timestamp_t di_crtime; /* time created */
>> + __be64 di_ino; /* inode number */
>> + uuid_t di_uuid; /* UUID of the filesystem */
>> +} xfs_dinode_t;
>
> Hrm...removing the packed attribute... Eric, do you remember the ARM ABI
> alignment rules? Regardless of ARM, are those fields aligned nicely? (From a
> quick glance at the code looks ok.)
I'll just have to just test it again I suppose. Removing packed is
good, as long as the padding makes it all come out right.
-=Eric
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 12/13] xfs: add version 3 inode format with CRCs
2009-02-12 18:42 ` Eric Sandeen
@ 2009-02-12 18:51 ` Christoph Hellwig
0 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-12 18:51 UTC (permalink / raw)
To: Eric Sandeen; +Cc: Christoph Hellwig, Josef 'Jeff' Sipek, xfs
On Thu, Feb 12, 2009 at 12:42:02PM -0600, Eric Sandeen wrote:
> Josef 'Jeff' Sipek wrote:
> > On Tue, Feb 10, 2009 at 03:22:53PM -0500, Christoph Hellwig wrote:
> > ...
> >> Index: xfs/fs/xfs/xfs_dinode.h
> >> ===================================================================
> >> --- xfs.orig/fs/xfs/xfs_dinode.h 2009-02-10 19:45:51.939069576 +0100
> >> +++ xfs/fs/xfs/xfs_dinode.h 2009-02-10 19:45:59.195068745 +0100
> >> @@ -69,11 +69,32 @@ typedef struct xfs_dinode {
> >>
> >> /* di_next_unlinked is the only non-core field in the old dinode */
> >> __be32 di_next_unlinked;/* agi unlinked list ptr */
> >> -} __attribute__((packed)) xfs_dinode_t;
> >> +
> >> + /* start of the extended dinode, writable fields */
> >> + __be32 di_crc; /* CRC of the inode */
> >> + __be64 di_changecount; /* number of attribute changes */
> >> + __u8 di_pad2[16]; /* more padding for future expansion */
> >> +
> >> + /* fields only written to during inode creation */
> >> + xfs_timestamp_t di_crtime; /* time created */
> >> + __be64 di_ino; /* inode number */
> >> + uuid_t di_uuid; /* UUID of the filesystem */
> >> +} xfs_dinode_t;
> >
> > Hrm...removing the packed attribute... Eric, do you remember the ARM ABI
> > alignment rules? Regardless of ARM, are those fields aligned nicely? (From a
> > quick glance at the code looks ok.)
>
> I'll just have to just test it again I suppose. Removing packed is
> good, as long as the padding makes it all come out right.
The reason why the current dinode needs the packed attribute is that
it's end on an un-even 32bit word, and thus the last field might be
wrongly aligned on 64-bit big-endian platforms (same issue as the
bad features2 one). With the CRC patchset we now have a dinode
that's properly aligned on a even 32bit word.
>
> -=Eric
---end quoted text---
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 13/13] xfs: add CRC checks for quota blocks
2009-02-12 6:41 ` Josef 'Jeff' Sipek
@ 2009-02-13 20:10 ` Christoph Hellwig
0 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-13 20:10 UTC (permalink / raw)
To: Josef 'Jeff' Sipek; +Cc: Christoph Hellwig, xfs
On Thu, Feb 12, 2009 at 01:41:28AM -0500, Josef 'Jeff' Sipek wrote:
> > xfs_disk_dquot_t dd_diskdq; /* portion that lives incore as well */
> > - char dd_fill[32]; /* filling for posterity */
> > + char dd_fill[12]; /* filling for posterity */
> > +
> > + /*
> > + * These two are only present one filesystems with the CRC bits set.
> > + */
> > + __be32 dd_crc; /* checksum */
> > + uuid_t dd_uuid; /* location information */
> > } xfs_dqblk_t;
>
> Again, why put the crc/uuid at the end?
So that we can add additional infos either to xfs_disk_dquot_t
(preserved in-core) or xfs_dqblk_t (purly on-disk).
> > + if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk),
> > + offsetof(struct xfs_dqblk, dd_crc))) {
> > +// !uuid_equal(&agfl->agfl_uuid, &mp->m_sb.sb_uuid) ||
>
> Dead code?
Sorry, sent out a too early version. The final patch actually verifies
the uuid and the correct location in the quota file.
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 10/13] xfs: add CRC checks to the AGFL
2009-02-11 7:54 ` Dave Chinner
@ 2009-02-15 18:23 ` Christoph Hellwig
0 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-15 18:23 UTC (permalink / raw)
To: Christoph Hellwig, xfs
On Wed, Feb 11, 2009 at 06:54:33PM +1100, Dave Chinner wrote:
> I haven't had a chance to look over any of this series in detail - just
> a quick glance really - but this popped out as looking wrong:
>
> > +/*
> > + * Size of the AGFL. For CRC-enabled filesystes we steal the last two slots
> > + * for location information (agno) and the crc.
> > + */
> > +#define XFS_AGFL_SIZE(mp) \
> > + ((mp)->m_sb.sb_sectsize / sizeof(xfs_agblock_t) - \
> > + (xfs_sb_version_hascrc(&((mp)->m_sb)) ? sizeof(struct xfs_agfl) : 0))
>
> sb_sectsize is in bytes, sizeof(xfs_agblock_t) is in bytes, which
> means that the numerator is a count of the number of agblocks that
> will fit in the AGFL. sizeof(struct xfs_agfl) is also in bytes,
> so your subtracting a number of bytes from a count of agblocks....
>
> I think you mean:
>
> #define XFS_AGFL_SIZE(mp) \
> (((mp)->m_sb.sb_sectsize - (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \
> sizeof(struct xfs_agfl) : 0)) \
> / sizeof(xfs_agblock_t))
Yeah. Either that, or dividing the sizeof by four.
> > typedef struct xfs_agfl {
> > - __be32 agfl_bno[1]; /* actually XFS_AGFL_SIZE(mp) */
> > + __be32 agfl_magicnum;
> > + __be32 agfl_seqno;
> > + uuid_t agfl_uuid;
> > + __be32 agfl_crc;
> > + __be32 agfl_bno[]; /* actually XFS_AGFL_SIZE(mp) */
> > } xfs_agfl_t;
>
> And judging by that you are stealing more than 2 slots - more like
> 8 slots.
Yeah, two slots was the very first implementation, I'll fix up the
comment too.
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2009-02-15 18:24 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
2009-02-10 20:22 ` [PATCH 01/13] xfs: cleanup xlog_bread Christoph Hellwig
2009-02-10 20:22 ` [PATCH 02/13] xfs: remove m_litino Christoph Hellwig
2009-02-10 20:22 ` [PATCH 03/13] xfs: remove m_attroffset Christoph Hellwig
2009-02-10 20:22 ` [PATCH 04/13] xfs: take inode version into account in XFS_LITINO Christoph Hellwig
2009-02-10 20:22 ` [PATCH 05/13] xfs: add CRC infrastructure Christoph Hellwig
2009-02-12 6:10 ` Josef 'Jeff' Sipek
2009-02-10 20:22 ` [PATCH 06/13] xfs: add support for large btree blocks Christoph Hellwig
2009-02-10 20:22 ` [PATCH 07/13] xfs: add CRC checks to the superblock Christoph Hellwig
2009-02-10 20:22 ` [PATCH 08/13] xfs: add CRC checks to the AGF Christoph Hellwig
2009-02-10 20:22 ` [PATCH 09/13] xfs: add CRC checks to the AGI Christoph Hellwig
2009-02-10 20:22 ` [PATCH 10/13] xfs: add CRC checks to the AGFL Christoph Hellwig
2009-02-11 7:54 ` Dave Chinner
2009-02-15 18:23 ` Christoph Hellwig
2009-02-10 20:22 ` [PATCH 11/13] xfs: add CRC checks to the log Christoph Hellwig
2009-02-10 20:22 ` [PATCH 12/13] xfs: add version 3 inode format with CRCs Christoph Hellwig
2009-02-12 6:38 ` Josef 'Jeff' Sipek
2009-02-12 18:42 ` Eric Sandeen
2009-02-12 18:51 ` Christoph Hellwig
2009-02-10 20:22 ` [PATCH 13/13] xfs: add CRC checks for quota blocks Christoph Hellwig
2009-02-12 6:41 ` Josef 'Jeff' Sipek
2009-02-13 20:10 ` Christoph Hellwig
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.