From: Barry Naujok Date: Thu, 19 Jul 2007 16:04:12 +0000 (+0000) Subject: Make xfs_repair support > 512 byte sector sizes properly X-Git-Tag: v2.10.0~43 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2aa2e7b912502211f25e9c5a9ec5d383411c2432;p=thirdparty%2Fxfsprogs-dev.git Make xfs_repair support > 512 byte sector sizes properly Merge of master-melb:xfs-cmds:29181a by kenmcd. Fix up SET_COUNT macro --- diff --git a/include/libxfs.h b/include/libxfs.h index b55c72dc3..1c0a62ed6 100644 --- a/include/libxfs.h +++ b/include/libxfs.h @@ -243,9 +243,9 @@ enum xfs_buf_flags_t { /* b_flags bits */ #define XFS_BUF_COUNT(bp) ((bp)->b_bcount) #define XFS_BUF_TARGET(bp) ((bp)->b_dev) #define XFS_BUF_SET_PTR(bp,p,cnt) ((bp)->b_addr = (char *)(p)); \ - XFS_BUF_SETCOUNT(bp,cnt) + XFS_BUF_SET_COUNT(bp,cnt) #define XFS_BUF_SET_ADDR(bp,blk) ((bp)->b_blkno = (blk)) -#define XFS_BUF_SETCOUNT(bp,cnt) ((bp)->b_bcount = (cnt)) +#define XFS_BUF_SET_COUNT(bp,cnt) ((bp)->b_bcount = (cnt)) #define XFS_BUF_FSPRIVATE(bp,type) ((type)(bp)->b_fsprivate) #define XFS_BUF_SET_FSPRIVATE(bp,val) (bp)->b_fsprivate = (void *)(val) @@ -512,7 +512,7 @@ extern int libxfs_bmap_finish (xfs_trans_t **, xfs_bmap_free_t *, extern void libxfs_bmap_cancel(xfs_bmap_free_t *); extern int libxfs_bmap_next_offset (xfs_trans_t *, xfs_inode_t *, xfs_fileoff_t *, int); -extern int libxfs_bmap_last_offset(xfs_trans_t *, xfs_inode_t *, +extern int libxfs_bmap_last_offset(xfs_trans_t *, xfs_inode_t *, xfs_fileoff_t *, int); extern int libxfs_bunmapi (xfs_trans_t *, xfs_inode_t *, xfs_fileoff_t, xfs_filblks_t, int, xfs_extnum_t, diff --git a/include/libxlog.h b/include/libxlog.h index 2717d38da..f7f14f997 100644 --- a/include/libxlog.h +++ b/include/libxlog.h @@ -44,6 +44,8 @@ typedef struct log { int l_grant_write_cycle; /* */ int l_grant_write_bytes; /* */ uint l_sectbb_log; /* log2 of sector size in bbs */ + uint l_sectbb_mask; /* sector size (in BBs) + * alignment mask */ } xlog_t; #include @@ -79,13 +81,6 @@ extern void xlog_warn(char *fmt,...); extern void xlog_exit(char *fmt,...); extern void xlog_panic(char *fmt,...); -#define xlog_get_bp(log,bbs) libxfs_getbufr(x.logdev, (xfs_daddr_t)-1, (bbs)) -#define xlog_put_bp(bp) libxfs_putbufr(bp) -#define xlog_bread(log,blkno,bbs,bp) \ - (libxfs_readbufr(x.logdev, \ - (log)->l_logBBstart+(blkno), bp, (bbs), 1), 0) -#define xlog_align(log,blkno,nbblks,bp) XFS_BUF_PTR(bp) - #define kmem_zalloc(size, foo) calloc(size,1) #define kmem_alloc(size, foo) calloc(size,1) #define kmem_free(ptr, foo) free(ptr) @@ -99,6 +94,10 @@ extern int print_record_header; /* libxfs parameters */ extern libxfs_init_t x; +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 int xlog_find_zeroed(xlog_t *log, xfs_daddr_t *blk_no); extern int xlog_find_cycle_start(xlog_t *log, xfs_buf_t *bp, xfs_daddr_t first_blk, xfs_daddr_t *last_blk, uint cycle); diff --git a/libxlog/xfs_log_recover.c b/libxlog/xfs_log_recover.c index b26b0e1ca..91a1a50b8 100644 --- a/libxlog/xfs_log_recover.c +++ b/libxlog/xfs_log_recover.c @@ -22,6 +22,84 @@ #define xlog_clear_stale_blocks(log, tail_lsn) (0) #define xfs_readonly_buftarg(buftarg) (0) + +/* + * Sector aligned buffer routines for buffer create/read/write/access + */ + +#define XLOG_SECTOR_ROUNDUP_BBCOUNT(log, bbs) \ + ( ((log)->l_sectbb_mask && (bbs & (log)->l_sectbb_mask)) ? \ + ((bbs + (log)->l_sectbb_mask + 1) & ~(log)->l_sectbb_mask) : (bbs) ) +#define XLOG_SECTOR_ROUNDDOWN_BLKNO(log, bno) ((bno) & ~(log)->l_sectbb_mask) + +xfs_buf_t * +xlog_get_bp( + xlog_t *log, + int num_bblks) +{ + ASSERT(num_bblks > 0); + + if (log->l_sectbb_log) { + if (num_bblks > 1) + num_bblks += XLOG_SECTOR_ROUNDUP_BBCOUNT(log, 1); + num_bblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, num_bblks); + } + return libxfs_getbufr(log->l_dev, (xfs_daddr_t)-1, num_bblks); +} + +void +xlog_put_bp( + xfs_buf_t *bp) +{ + libxfs_putbufr(bp); +} + + +/* + * nbblks should be uint, but oh well. Just want to catch that 32-bit length. + */ +int +xlog_bread( + xlog_t *log, + xfs_daddr_t blk_no, + int nbblks, + xfs_buf_t *bp) +{ + if (log->l_sectbb_log) { + blk_no = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, blk_no); + nbblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, nbblks); + } + + ASSERT(nbblks > 0); + ASSERT(BBTOB(nbblks) <= XFS_BUF_SIZE(bp)); + ASSERT(bp); + + XFS_BUF_SET_ADDR(bp, log->l_logBBstart + blk_no); + XFS_BUF_SET_COUNT(bp, BBTOB(nbblks)); + + return libxfs_readbufr(log->l_dev, XFS_BUF_ADDR(bp), bp, nbblks, 0); +} + + +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; +} + + /* * This routine finds (to an approximation) the first block in the physical * log which contains the given cycle. It uses a binary search algorithm. diff --git a/repair/phase2.c b/repair/phase2.c index e9adef25d..d4ceceafa 100644 --- a/repair/phase2.c +++ b/repair/phase2.c @@ -50,6 +50,16 @@ zero_log(xfs_mount_t *mp) log.l_logBBsize = x.logBBsize; log.l_logBBstart = x.logBBstart; log.l_mp = mp; + if (XFS_SB_VERSION_HASSECTOR(&mp->m_sb)) { + log.l_sectbb_log = mp->m_sb.sb_logsectlog - BBSHIFT; + ASSERT(log.l_sectbb_log <= mp->m_sectbb_log); + /* for larger sector sizes, must have v2 or external log */ + ASSERT(log.l_sectbb_log == 0 || + log.l_logBBstart == 0 || + XFS_SB_VERSION_HASLOGV2(&mp->m_sb)); + ASSERT(mp->m_sb.sb_logsectlog >= BBSHIFT); + } + log.l_sectbb_mask = (1 << log.l_sectbb_log) - 1; if ((error = xlog_find_tail(&log, &head_blk, &tail_blk, 0))) { do_warn(_("zero_log: cannot find log head/tail " diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c index 7013b378c..dd5b6247b 100644 --- a/repair/xfs_repair.c +++ b/repair/xfs_repair.c @@ -266,7 +266,6 @@ process_args(int argc, char **argv) case 't': report_interval = (int) strtol(optarg, 0, 0); break; - case '?': usage(); } @@ -497,7 +496,8 @@ main(int argc, char **argv) } /* prepare the mount structure */ - sbp = libxfs_readbuf(x.ddev, XFS_SB_DADDR, 1, 0); + sbp = libxfs_readbuf(x.ddev, XFS_SB_DADDR, + 1 << (XFS_MAX_SECTORSIZE_LOG - BBSHIFT), 0); memset(&xfs_m, 0, sizeof(xfs_mount_t)); sb = &xfs_m.m_sb; libxfs_xlate_sb(XFS_BUF_PTR(sbp), sb, 1, XFS_SB_ALL_BITS); @@ -511,6 +511,7 @@ main(int argc, char **argv) exit(1); } libxfs_putbuf(sbp); + libxfs_purgebuf(sbp); /* * set XFS-independent status vars from the mount/sb structure