repair: discontiguous directory block support
v2 cover repair: discontiguous directory block support
Hi folks,
This is version 2 of the patchset first posted here:
http://oss.sgi.com/archives/xfs/2014-01/msg00341.html
Version 2 changes:
- rework extent tracking logic in discontiguous block support as requested by Brain. (patch 3/3)
Cheers,
Dave.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
PATCH v2 1/3 libxfs: add a flags field to libxfs_getbuf_map
From: Dave Chinner <[email protected]>
It will be needed to make the repair prefetch code aware of compound buffers.
--- include/libxfs.h | 8 ++++---- libxfs/rdwr.c | 15 +++++++++------ libxfs/trans.c | 4 ++-- 3 files changed, 15 insertions(+), 12 deletions(-)
include/libxfs.h +4 -4
@@ -392,9 +392,9 @@ extern struct cache_operations libxfs_bcache_operations;#define libxfs_getbuf (dev, daddr, len) \ libxfs_trace_getbuf(__FUNCTION__, __FILE__, __LINE__, \ (dev), (daddr), (len)) -#define libxfs_getbuf_map (dev, map, nmaps) \ +#define libxfs_getbuf_map (dev, map, nmaps, flags) \ libxfs_trace_getbuf_map(__FUNCTION__, __FILE__, __LINE__, \ - (dev), (map), (nmaps)) + (dev), (map), (nmaps), (flags))#define libxfs_getbuf_flags (dev, daddr, len, flags) \ libxfs_trace_getbuf_flags(__FUNCTION__, __FILE__, __LINE__, \ (dev), (daddr), (len), (flags))
@@ -412,7 +412,7 @@ extern int libxfs_trace_writebuf(const char *, const char *, int,extern xfs_buf_t *libxfs_trace_getbuf (const char *,const char *,int ,struct xfs_buftarg *,xfs_daddr_t ,int );extern xfs_buf_t *libxfs_trace_getbuf_map (const char *,const char *,int , -struct xfs_buftarg *,struct xfs_buf_map *,int ); +struct xfs_buftarg *,struct xfs_buf_map *,int ,int );extern xfs_buf_t *libxfs_trace_getbuf_flags (const char *,const char *,int ,struct xfs_buftarg *,xfs_daddr_t ,int ,unsigned int ); extern void libxfs_trace_putbuf (const char *, const char *, int,
@@ -427,7 +427,7 @@ extern xfs_buf_t *libxfs_readbuf_map(struct xfs_buftarg *, struct xfs_buf_map *,extern int libxfs_writebuf (xfs_buf_t *,int );extern xfs_buf_t *libxfs_getbuf (struct xfs_buftarg *,xfs_daddr_t ,int );extern xfs_buf_t *libxfs_getbuf_map (struct xfs_buftarg *, -struct xfs_buf_map *,int ); +struct xfs_buf_map *,int ,int );extern xfs_buf_t *libxfs_getbuf_flags (struct xfs_buftarg *,xfs_daddr_t ,int ,unsigned int );extern void libxfs_putbuf (xfs_buf_t *);
libxfs/rdwr.c +9 -6
@@ -203,7 +203,8 @@ xfs_buf_t *libxfs_readbuf_map(struct xfs_buftarg *, struct xfs_buf_map *, int, int, const struct xfs_buf_ops *);int libxfs_writebuf (xfs_buf_t *,int );xfs_buf_t *libxfs_getbuf (struct xfs_buftarg *,xfs_daddr_t ,int ); -xfs_buf_t *libxfs_getbuf_map (struct xfs_buftarg *,struct xfs_buf_map *,int ); +xfs_buf_t *libxfs_getbuf_map (struct xfs_buftarg *,struct xfs_buf_map *, +int ,int );xfs_buf_t *libxfs_getbuf_flags (struct xfs_buftarg *,xfs_daddr_t ,int ,unsigned int );void libxfs_putbuf (xfs_buf_t *);
@@ -255,9 +256,10 @@ libxfs_trace_getbuf(const char *func, const char *file, int line,xfs_buf_t *libxfs_trace_getbuf_map (const char *func,const char *file,int line, -struct xfs_buftarg *btp,struct xfs_buf_map *map,int nmaps) +struct xfs_buftarg *btp,struct xfs_buf_map *map,int nmaps, +int flags) { -xfs_buf_t *bp =libxfs_getbuf_map (btp, map, nmaps); +xfs_buf_t *bp =libxfs_getbuf_map (btp, map, nmaps, flags);__add_trace (bp, func, file, line);return bp; }
@@ -582,7 +584,8 @@ libxfs_getbuf(struct xfs_buftarg *btp, xfs_daddr_t blkno, int len) }struct xfs_buf * -libxfs_getbuf_map (struct xfs_buftarg *btp,struct xfs_buf_map *map,int nmaps) +libxfs_getbuf_map (struct xfs_buftarg *btp,struct xfs_buf_map *map, +int nmaps,int flags) {struct xfs_bufkey key = {0 };int i;
@@ -595,7 +598,7 @@ libxfs_getbuf_map(struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps) key.map = map; key.nmaps = nmaps; -return __cache_lookup (&key,0 ); +return __cache_lookup (&key, flags); }void
@@ -775,7 +778,7 @@ libxfs_readbuf_map(struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps,return libxfs_readbuf (btp, map[0 ].bm_bn, map[0 ].bm_len, flags, ops); - bp =libxfs_getbuf_map (btp, map, nmaps); + bp =libxfs_getbuf_map (btp, map, nmaps,0 );if (!bp)return NULL ;
libxfs/trans.c +2 -2
@@ -511,7 +511,7 @@ libxfs_trans_get_buf_map(xfs_buf_log_item_t *bip;if (tp ==NULL ) -return libxfs_getbuf_map (btp, map, nmaps); +return libxfs_getbuf_map (btp, map, nmaps,0 ); bp =xfs_trans_buf_item_match (tp, btp, map, nmaps);if (bp !=NULL ) {
@@ -522,7 +522,7 @@ libxfs_trans_get_buf_map(return bp; } - bp =libxfs_getbuf_map (btp, map, nmaps); + bp =libxfs_getbuf_map (btp, map, nmaps,0 );if (bp ==NULL )return NULL ;#ifdef XACT_DEBUG
Signature · 6 lines
1.8.4.rc3 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH v2 2/3 libxfs: remove map from libxfs_readbufr_map
In reply to Dave ChinnerFrom: Dave Chinner <[email protected]>
The map passed in to libxfs_readbufr_map is used to check the buffer matches the map. However, the repair readahead code has no map it can use to validate the buffer it set up previously, so just get rid of the map being passed in because it serves no useful purpose.
--- db/io.c | 4 +--- include/libxfs.h | 3 +-- libxfs/rdwr.c | 12 ++---------- 3 files changed, 4 insertions(+), 15 deletions(-)
db/io.c +1 -3
@@ -449,9 +449,7 @@ write_cur_bbs(void)/* re-read buffer from disk */ - ret =libxfs_readbufr_map (mp->m_ddev_targp, iocur_top->bp, - iocur_top->bbmap->b, iocur_top->bbmap->nmaps, -0 ); + ret =libxfs_readbufr_map (mp->m_ddev_targp, iocur_top->bp,0 );if (ret !=0 )dbprintf (_ ("read error: %s\n" ),strerror (ret)); }
include/libxfs.h +1 -2
@@ -448,8 +448,7 @@ extern void libxfs_putbufr(xfs_buf_t *);extern int libxfs_writebuf_int (xfs_buf_t *,int );extern int libxfs_writebufr (struct xfs_buf *);extern int libxfs_readbufr (struct xfs_buftarg *,xfs_daddr_t ,xfs_buf_t *,int ,int ); -extern int libxfs_readbufr_map (struct xfs_buftarg *,struct xfs_buf *, -struct xfs_buf_map *,int ,int ); +extern int libxfs_readbufr_map (struct xfs_buftarg *,struct xfs_buf *,int );extern int libxfs_bhash_size;
libxfs/rdwr.c +2 -10
@@ -727,27 +727,19 @@ libxfs_readbuf(struct xfs_buftarg *btp, xfs_daddr_t blkno, int len, int flags, }int -libxfs_readbufr_map (struct xfs_buftarg *btp,struct xfs_buf *bp, -struct xfs_buf_map *map,int nmaps,int flags) +libxfs_readbufr_map (struct xfs_buftarg *btp,struct xfs_buf *bp,int flags) {int fd =libxfs_device_to_fd (btp->dev);int error =0 ;char *buf;int i; -ASSERT (BBTOB (len) <= bp->b_bcount); - -ASSERT (bp->b_nmaps == nmaps); - fd =libxfs_device_to_fd (btp->dev); buf = bp->b_addr;for (i =0 ; i < bp->b_nmaps; i++) {off64_t offset =LIBXFS_BBTOOFF64 (bp->b_map[i].bm_bn);int len =BBTOB (bp->b_map[i].bm_len); -ASSERT (bp->b_map[i].bm_bn == map[i].bm_bn); -ASSERT (bp->b_map[i].bm_len == map[i].bm_len); - error =__read_buf (fd, buf, len, offset, flags);if (error) { bp->b_error = error;
@@ -787,7 +779,7 @@ libxfs_readbuf_map(struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps,if ((bp->b_flags & (LIBXFS_B_UPTODATE |LIBXFS_B_DIRTY )))return bp; - error =libxfs_readbufr_map (btp, bp, map, nmaps, flags); + error =libxfs_readbufr_map (btp, bp, flags);if (!error) { bp->b_flags |=LIBXFS_B_UPTODATE ;if (bp->b_ops)
Signature · 6 lines
1.8.4.rc3 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 2/3] libxfs: remove map from libxfs_readbufr_map
Quoted 9 lines · Dave Chinner
From: Dave Chinner <[email protected]>
The map passed in to
libxfs_readbufr_mapis used to check the buffer matches the map. However, the repair readahead code has no map it can use to validate the buffer it set up previously, so just get rid of the map being passed in because it serves no useful purpose.Signed-off-by Dave Chinner <[email protected]>---
Quoted 69 lines
db/io.c | 4 +--- include/libxfs.h | 3 +-- libxfs/rdwr.c | 12 ++---------- 3 files changed, 4 insertions(+), 15 deletions(-)db/io.c +1
-3@@ -449,9 +449,7 @@ write_cur_bbs(void)/* re-read buffer from disk */ - ret =libxfs_readbufr_map (mp->m_ddev_targp, iocur_top->bp, - iocur_top->bbmap->b, iocur_top->bbmap->nmaps, -0 ); + ret =libxfs_readbufr_map (mp->m_ddev_targp, iocur_top->bp,0 );if (ret !=0 )dbprintf (_ ("read error: %s\n" ),strerror (ret)); }include/libxfs.h +1
-2@@ -448,8 +448,7 @@ extern void libxfs_putbufr(xfs_buf_t *);extern int libxfs_writebuf_int (xfs_buf_t *,int );extern int libxfs_writebufr (struct xfs_buf *);extern int libxfs_readbufr (struct xfs_buftarg *,xfs_daddr_t ,xfs_buf_t *,int ,int ); -extern int libxfs_readbufr_map (struct xfs_buftarg *,struct xfs_buf *, -struct xfs_buf_map *,int ,int ); +extern int libxfs_readbufr_map (struct xfs_buftarg *,struct xfs_buf *,int );extern int libxfs_bhash_size;libxfs/rdwr.c +1
-9@@ -727,27 +727,19 @@ libxfs_readbuf(struct xfs_buftarg *btp, xfs_daddr_t blkno, int len, int flags, }int -libxfs_readbufr_map (struct xfs_buftarg *btp,struct xfs_buf *bp, -struct xfs_buf_map *map,int nmaps,int flags) +libxfs_readbufr_map (struct xfs_buftarg *btp,struct xfs_buf *bp,int flags) {int fd =libxfs_device_to_fd (btp->dev);int error =0 ;char *buf;int i; -ASSERT (BBTOB (len) <= bp->b_bcount); - -ASSERT (bp->b_nmaps == nmaps); - fd =libxfs_device_to_fd (btp->dev); buf = bp->b_addr;for (i =0 ; i < bp->b_nmaps; i++) {off64_t offset =LIBXFS_BBTOOFF64 (bp->b_map[i].bm_bn);int len =BBTOB (bp->b_map[i].bm_len); -ASSERT (bp->b_map[i].bm_bn == map[i].bm_bn); -ASSERT (bp->b_map[i].bm_len == map[i].bm_len); - error =__read_buf (fd, buf, len, offset, flags);if (error) { bp->b_error = error;
libxfs/rdwr.c libxfs_readbuf_map(struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps, · line 785
Quoted 8 lines
libxfs/rdwr.c +1
-1@@ -787,7 +779,7 @@ libxfs_readbuf_map(struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps,if ((bp->b_flags & (LIBXFS_B_UPTODATE |LIBXFS_B_DIRTY )))return bp; - error =libxfs_readbufr_map (btp, bp, map, nmaps, flags); + error =libxfs_readbufr_map (btp, bp, flags);if (!error) { bp->b_flags |=LIBXFS_B_UPTODATE ;if (bp->b_ops)
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
PATCH v2 3/3 repair: fix discontiguous directory block support
In reply to Dave ChinnerFrom: Dave Chinner <[email protected]>
xfs/291 tests fragmented multi-block directories, and xfs_repair throws lots of lookup badness errors in phase 3:
- agno = 17fa3d2758740: Badness in key lookup (length)
bp=(bno 0x1e040, len 4096 bytes) key=(bno 0x1e040, len 16384 bytes)
- agno = 27fa3d2758740: Badness in key lookup (length)
bp=(bno 0x2d0e8, len 4096 bytes) key=(bno 0x2d0e8, len 16384 bytes) 7fa3d2758740: Badness in key lookup (length)
bp=(bno 0x2d068, len 4096 bytes) key=(bno 0x2d068, len 16384 bytes)
- agno = 37fa3d2758740: Badness in key lookup (length)
bp=(bno 0x39130, len 4096 bytes) key=(bno 0x39130, len 16384 bytes) 7fa3d2758740: Badness in key lookup (length)
bp=(bno 0x391b0, len 4096 bytes) key=(bno 0x391b0, len 16384 bytes) 7fa3d2758740: Badness in key lookup (length)
This is because it is trying to read a directory buffer in full (16k), but is finding a single 4k block in the cache instead.
The opposite is happening in phase 6 - phase 6 is trying to read 4k buffers but is finding a 16k buffer there instead.
The problem is caused by the fact that directory buffers can be represented as compound buffers or as individual buffers depending on the code reading the directory blocks. The main problem is that the IO prefetch code doesn't understand compound buffers, so teach it about compound buffers to make the problem go away.
--- repair/prefetch.c | 120 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 99 insertions(+), 21 deletions(-)
repair/prefetch.c +99 -21
@@ -105,11 +105,12 @@ pf_start_io_workers(static void pf_queue_io (prefetch_args_t *args, -xfs_fsblock_t fsbno, -int blen, +struct xfs_buf_map *map, +int nmaps,int flag) { -xfs_buf_t *bp; +struct xfs_buf *bp; +xfs_fsblock_t fsbno =XFS_DADDR_TO_FSB (mp, map[0 ].bm_bn);/* * Never block on a buffer lock here, given that the actual repair
@@ -117,8 +118,7 @@ pf_queue_io(* the lock holder is either reading it from disk himself or * completely overwriting it this behaviour is perfectly fine. */ - bp =libxfs_getbuf_flags (mp->m_dev,XFS_FSB_TO_DADDR (mp, fsbno), -XFS_FSB_TO_BB (mp, blen),LIBXFS_GETBUF_TRYLOCK ); + bp =libxfs_getbuf_map (mp->m_dev, map, nmaps,LIBXFS_GETBUF_TRYLOCK );if (!bp)return ;
@@ -167,6 +167,14 @@ pf_read_bmbt_reclist(xfs_bmbt_irec_t irec;xfs_dfilblks_t cp =0 ;/* prev count */ xfs_dfiloff_t op =0 ;/* prev offset */ +#define MAP_ARRAY_SZ 4 +struct xfs_buf_map map_array[MAP_ARRAY_SZ ]; +struct xfs_buf_map *map = map_array; +int max_extents =MAP_ARRAY_SZ ; +int nmaps =0 ;; +unsigned int len =0 ; +int ret =0 ; +for (i =0 ; i < numrecs; i++) {libxfs_bmbt_disk_get_all (rp + i, &irec);
@@ -174,11 +182,11 @@ pf_read_bmbt_reclist(if (((i >0 ) && (op + cp > irec.br_startoff)) || (irec.br_blockcount ==0 ) || (irec.br_startoff >= fs_max_file_offset)) -return 0 ; + goto out_free;if (!verify_dfsbno (mp, irec.br_startblock) || !verify_dfsbno (mp, irec.br_startblock + irec.br_blockcount -1 )) -return 0 ; + goto out_free;if (!args->dirs_only && ((irec.br_startoff + irec.br_blockcount) >= mp->m_dirfreeblk))
@@ -188,18 +196,59 @@ pf_read_bmbt_reclist( cp = irec.br_blockcount;while (irec.br_blockcount) { -unsigned int len; +unsigned int bm_len;pftrace ("queuing dir extent in AG %d" , args->agno); - len = (irec.br_blockcount > mp->m_dirblkfsbs) ? - mp->m_dirblkfsbs : irec.br_blockcount; -pf_queue_io (args, irec.br_startblock, len,B_DIR_META ); - irec.br_blockcount -= len; - irec.br_startblock += len; +if (len + irec.br_blockcount >= mp->m_dirblkfsbs) + bm_len = mp->m_dirblkfsbs - len; +else + bm_len = irec.br_blockcount; + len += bm_len; + + map[nmaps].bm_bn =XFS_FSB_TO_DADDR (mp, + irec.br_startblock); + map[nmaps].bm_len =XFS_FSB_TO_BB (mp, bm_len); + nmaps++; + +if (len == mp->m_dirblkfsbs) { +pf_queue_io (args, map, nmaps,B_DIR_META ); + len =0 ; + nmaps =0 ; + } + + irec.br_blockcount -= bm_len; + irec.br_startblock += bm_len; + +/* +* Handle very fragmented dir2 blocks with dynamically +* allocated buffer maps. +*/ +if (nmaps >= max_extents) { +struct xfs_buf_map *old_map =NULL ; + +if (map == map_array) { + old_map = map; + map =NULL ; + } + max_extents *=2 ; + map =realloc (map, max_extents *sizeof (*map)); +if (map ==NULL ) { +do_error ( +_ ("couldn't malloc dir2 buffer list\n" )); +exit (1 ); + } +if (old_map) +memcpy (map, old_map,sizeof (map_array)); + } + } } -return 1 ; + ret =1 ; +out_free: +if (map != map_array) +free (map); +return ret; }/*
@@ -395,9 +444,28 @@ pf_read_inode_dirs( }/* -* pf_batch_read must be called with the lock locked. +* Discontiguous buffers require multiple IOs to fill, so we can't use any +* linearising, hole filling algorithms on them to avoid seeks. Just remove them +* for the prefetch queue and read them straight into the cache and release +* them. */ +static void +pf_read_discontig ( +struct prefetch_args *args, +struct xfs_buf *bp) +{ +if (!btree_delete (args->io_queue,XFS_DADDR_TO_FSB (mp, bp->b_bn))) +do_error (_ ("prefetch corruption\n" )); + +pthread_mutex_unlock (&args->lock); +libxfs_readbufr_map (mp->m_ddev_targp, bp,0 ); +libxfs_putbuf (bp); +pthread_mutex_lock (&args->lock); +} +/* +* pf_batch_read must be called with the lock locked. +*/ static void pf_batch_read( prefetch_args_t *args,
@@ -426,8 +494,15 @@ pf_batch_read( max_fsbno = fsbno + pf_max_fsbs; }while (bplist[num] && num <MAX_BUFS && fsbno < max_fsbno) { -if (which !=PF_META_ONLY || - !B_IS_INODE (XFS_BUF_PRIORITY (bplist[num]))) +/* +* Handle discontiguous buffers outside the seek +* optimised IO loop below. +*/ +if ((bplist[num]->b_flags &LIBXFS_B_DISCONTIG )) { +pf_read_discontig (args, bplist[num]); + bplist[num] =NULL ; + }else if (which !=PF_META_ONLY || + !B_IS_INODE (XFS_BUF_PRIORITY (bplist[num]))) num++;if (num ==MAX_BUFS )break ;
@@ -664,10 +739,13 @@ pf_queuing_worker( bno =XFS_AGINO_TO_AGBNO (mp, cur_irec->ino_startnum);do { -pf_queue_io (args,XFS_AGB_TO_FSB (mp, args->agno, bno), - blks_per_cluster, - (cur_irec->ino_isa_dir !=0 ) ? -B_DIR_INODE :B_INODE ); +struct xfs_buf_map map; + + map.bm_bn =XFS_AGB_TO_DADDR (mp, args->agno, bno); + map.bm_len =XFS_FSB_TO_BB (mp, blks_per_cluster); +pf_queue_io (args, &map,1 , + (cur_irec->ino_isa_dir !=0 ) ?B_DIR_INODE + :B_INODE ); bno += blks_per_cluster; num_inos += inodes_per_cluster; }while (num_inos <XFS_IALLOC_INODES (mp));
Signature · 6 lines
1.8.4.rc3 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 3/3] repair: fix discontiguous directory block support
Quoted 26 lines · Dave Chinner
From: Dave Chinner <[email protected]>
xfs/291 tests fragmented multi-block directories, and
xfs_repairthrows lots of lookup badness errors in phase 3:- agno = 1
7fa3d2758740: Badness in key lookup (length)
bp=(bno0x1e040, len 4096 bytes) key=(bno0x1e040, len 16384 bytes)
- agno = 27fa3d2758740: Badness in key lookup (length)
bp=(bno0x2d0e8, len 4096 bytes) key=(bno0x2d0e8, len 16384 bytes)7fa3d2758740: Badness in key lookup (length)
bp=(bno0x2d068, len 4096 bytes) key=(bno0x2d068, len 16384 bytes)
- agno = 37fa3d2758740: Badness in key lookup (length)
bp=(bno0x39130, len 4096 bytes) key=(bno0x39130, len 16384 bytes)7fa3d2758740: Badness in key lookup (length)
bp=(bno0x391b0, len 4096 bytes) key=(bno0x391b0, len 16384 bytes)7fa3d2758740: Badness in key lookup (length)This is because it is trying to read a directory buffer in full (16k), but is finding a single 4k block in the cache instead.
The opposite is happening in phase 6 - phase 6 is trying to read 4k buffers but is finding a 16k buffer there instead.
Quoted 8 lines
The problem is caused by the fact that directory buffers can be represented as compound buffers or as individual buffers depending on the code reading the directory blocks. The main problem is that the IO prefetch code doesn't understand compound buffers, so teach it about compound buffers to make the problem go away.
Signed-off-by Dave Chinner <[email protected]>---
Quoted 186 lines
repair/prefetch.c | 120 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 99 insertions(+), 21 deletions(-)repair/prefetch.c +92
-21@@ -105,11 +105,12 @@ pf_start_io_workers(static void pf_queue_io (prefetch_args_t *args, -xfs_fsblock_t fsbno, -int blen, +struct xfs_buf_map *map, +int nmaps,int flag) { -xfs_buf_t *bp; +struct xfs_buf *bp; +xfs_fsblock_t fsbno =XFS_DADDR_TO_FSB (mp, map[0 ].bm_bn);/* * Never block on a buffer lock here, given that the actual repair @@ -117,8 +118,7 @@ pf_queue_io(* the lock holder is either reading it from disk himself or * completely overwriting it this behaviour is perfectly fine. */ - bp =libxfs_getbuf_flags (mp->m_dev,XFS_FSB_TO_DADDR (mp, fsbno), -XFS_FSB_TO_BB (mp, blen),LIBXFS_GETBUF_TRYLOCK ); + bp =libxfs_getbuf_map (mp->m_dev, map, nmaps,LIBXFS_GETBUF_TRYLOCK );if (!bp)return ;@@ -167,6 +167,14 @@ pf_read_bmbt_reclist(xfs_bmbt_irec_t irec;xfs_dfilblks_t cp =0 ;/* prev count */ xfs_dfiloff_t op =0 ;/* prev offset */ +#define MAP_ARRAY_SZ 4 +struct xfs_buf_map map_array[MAP_ARRAY_SZ ]; +struct xfs_buf_map *map = map_array; +int max_extents =MAP_ARRAY_SZ ; +int nmaps =0 ;; +unsigned int len =0 ; +int ret =0 ; +for (i =0 ; i < numrecs; i++) {libxfs_bmbt_disk_get_all (rp + i, &irec);@@ -174,11 +182,11 @@ pf_read_bmbt_reclist(if (((i >0 ) && (op + cp > irec.br_startoff)) || (irec.br_blockcount ==0 ) || (irec.br_startoff >= fs_max_file_offset)) -return 0 ; + goto out_free;if (!verify_dfsbno (mp, irec.br_startblock) || !verify_dfsbno (mp, irec.br_startblock + irec.br_blockcount -1 )) -return 0 ; + goto out_free;if (!args->dirs_only && ((irec.br_startoff + irec.br_blockcount) >= mp->m_dirfreeblk))@@ -188,18 +196,59 @@ pf_read_bmbt_reclist( cp = irec.br_blockcount;while (irec.br_blockcount) { -unsigned int len; +unsigned int bm_len;pftrace ("queuing dir extent in AG %d" , args->agno); - len = (irec.br_blockcount > mp->m_dirblkfsbs) ? - mp->m_dirblkfsbs : irec.br_blockcount; -pf_queue_io (args, irec.br_startblock, len,B_DIR_META ); - irec.br_blockcount -= len; - irec.br_startblock += len; +if (len + irec.br_blockcount >= mp->m_dirblkfsbs) + bm_len = mp->m_dirblkfsbs - len; +else + bm_len = irec.br_blockcount; + len += bm_len; + + map[nmaps].bm_bn =XFS_FSB_TO_DADDR (mp, + irec.br_startblock); + map[nmaps].bm_len =XFS_FSB_TO_BB (mp, bm_len); + nmaps++; + +if (len == mp->m_dirblkfsbs) { +pf_queue_io (args, map, nmaps,B_DIR_META ); + len =0 ; + nmaps =0 ; + } + + irec.br_blockcount -= bm_len; + irec.br_startblock += bm_len; + +/* +* Handle very fragmented dir2 blocks with dynamically +* allocated buffer maps. +*/ +if (nmaps >= max_extents) { +struct xfs_buf_map *old_map =NULL ; + +if (map == map_array) { + old_map = map; + map =NULL ; + } + max_extents *=2 ; + map =realloc (map, max_extents *sizeof (*map)); +if (map ==NULL ) { +do_error ( +_ ("couldn't malloc dir2 buffer list\n" )); +exit (1 ); + } +if (old_map) +memcpy (map, old_map,sizeof (map_array)); + } + } } -return 1 ; + ret =1 ; +out_free: +if (map != map_array) +free (map); +return ret; }/* @@ -395,9 +444,28 @@ pf_read_inode_dirs( }/* -* pf_batch_read must be called with the lock locked. +* Discontiguous buffers require multiple IOs to fill, so we can't use any +* linearising, hole filling algorithms on them to avoid seeks. Just remove them +* for the prefetch queue and read them straight into the cache and release +* them. */ +static void +pf_read_discontig ( +struct prefetch_args *args, +struct xfs_buf *bp) +{ +if (!btree_delete (args->io_queue,XFS_DADDR_TO_FSB (mp, bp->b_bn))) +do_error (_ ("prefetch corruption\n" )); + +pthread_mutex_unlock (&args->lock); +libxfs_readbufr_map (mp->m_ddev_targp, bp,0 ); +libxfs_putbuf (bp); +pthread_mutex_lock (&args->lock); +} +/* +* pf_batch_read must be called with the lock locked. +*/ static void pf_batch_read( prefetch_args_t *args,@@ -426,8 +494,15 @@ pf_batch_read( max_fsbno = fsbno + pf_max_fsbs; }while (bplist[num] && num <MAX_BUFS && fsbno < max_fsbno) { -if (which !=PF_META_ONLY || - !B_IS_INODE (XFS_BUF_PRIORITY (bplist[num]))) +/* +* Handle discontiguous buffers outside the seek +* optimised IO loop below. +*/ +if ((bplist[num]->b_flags &LIBXFS_B_DISCONTIG )) { +pf_read_discontig (args, bplist[num]); + bplist[num] =NULL ; + }else if (which !=PF_META_ONLY || + !B_IS_INODE (XFS_BUF_PRIORITY (bplist[num]))) num++;if (num ==MAX_BUFS )break ;@@ -664,10 +739,13 @@ pf_queuing_worker( bno =XFS_AGINO_TO_AGBNO (mp, cur_irec->ino_startnum); do { - pf_queue_io(args, XFS_AGB_TO_FSB(mp, args->agno, bno), - blks_per_cluster, - (cur_irec->ino_isa_dir != 0) ? - B_DIR_INODE : B_INODE);
repair/prefetch.c pf_queuing_worker( · line 751
Quoted 10 lines
repair/prefetch.c +7
-0+struct xfs_buf_map map; + + map.bm_bn =XFS_AGB_TO_DADDR (mp, args->agno, bno); + map.bm_len =XFS_FSB_TO_BB (mp, blks_per_cluster); +pf_queue_io (args, &map,1 , + (cur_irec->ino_isa_dir !=0 ) ?B_DIR_INODE + :B_INODE ); bno += blks_per_cluster; num_inos += inodes_per_cluster; }while (num_inos <XFS_IALLOC_INODES (mp));
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs