jhead lookup using bios
cover jhead lookup using bios
This is my latest version of this patchset based on inputs from Andreas and Steve.
We readahead the journal sequentially in large chunks using bios. Pagecache pages for the journal inode's mapping are used for the I/O.
There's also some cleanup of the bio functions with this patchset.
xfstests ran to completion with this.
Abhi Das (4):
gfs2: add more timing info to journal recovery process
gfs2: changes to gfs2_log_XXX_bio
gfs2: add a helper function to get_log_header that can be used
elsewhere
gfs2: read journal in large chunks to locate the head
fs/gfs2/bmap.c | 8 +- fs/gfs2/glops.c | 1 + fs/gfs2/log.c | 4 +- fs/gfs2/lops.c | 240 +++++++++++++++++++++++++++++++++++++++++++-------- fs/gfs2/lops.h | 4 +- fs/gfs2/ops_fstype.c | 1 + fs/gfs2/recovery.c | 178 ++++++++------------------------------ fs/gfs2/recovery.h | 4 +- fs/gfs2/super.c | 1 + 9 files changed, 255 insertions(+), 186 deletions(-)
Signature · 1 line
2.4.11
PATCH 1/4 gfs2: add more timing info to journal recovery process
Tells you how many milliseconds map_journal_extents and find_jhead take.
--- fs/gfs2/bmap.c | 8 ++++++-- fs/gfs2/recovery.c | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-)
fs/gfs2/bmap.c +6 -2
@@ -14,6 +14,7 @@#include <linux/gfs2_ondisk.h> #include <linux/crc32.h> #include <linux/iomap.h> +#include <linux/ktime.h> #include "gfs2.h" #include "incore.h"
@@ -2248,7 +2249,9 @@ int gfs2_map_journal_extents(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd)unsigned int shift = sdp->sd_sb.sb_bsize_shift;u64 size;int rc; +ktime_t start, end; + start =ktime_get (); lblock_stop =i_size_read (jd->jd_inode) >> shift; size = (lblock_stop - lblock) << shift; jd->nr_extents =0 ;
@@ -2268,8 +2271,9 @@ int gfs2_map_journal_extents(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd) lblock += (bh.b_size >> ip->i_inode.i_blkbits); }while (size >0 ); -fs_info (sdp,"journal %d mapped with %u extents\n" , jd->jd_jid, - jd->nr_extents); + end =ktime_get (); +fs_info (sdp,"journal %d mapped with %u extents in %lldms\n" , jd->jd_jid, + jd->nr_extents,ktime_ms_delta (end, start));return 0 ; fail:
fs/gfs2/recovery.c +2 -0
@@ -460,6 +460,8 @@ void gfs2_recover_func(struct work_struct *work)if (error) goto fail_gunlock_ji; t_jhd =ktime_get (); +fs_info (sdp,"jid=%u: Journal head lookup took %lldms\n" , jd->jd_jid, +ktime_ms_delta (t_jhd, t_jlck));if (!(head.lh_flags &GFS2_LOG_HEAD_UNMOUNT )) { fs_info(sdp, "jid=%u: Acquiring the transaction lock...\n",
Signature · 1 line
2.4.11
Andreas Gruenbacher
maintainerPATCH 1/4 gfs2: add more timing info to journal recovery process
Quoted 5 lines · Abhi Das
Tells you how many milliseconds
map_journal_extentsandfind_jheadtake.Signed-off-by Abhi Das <[email protected]>
Thanks,
Andreas
Quoted 55 lines
--- fs/gfs2/bmap.c | 8 ++++++-- fs/gfs2/recovery.c | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-)fs/gfs2/bmap.c +6
-2@@ -14,6 +14,7 @@#include <linux/gfs2_ondisk.h> #include <linux/crc32.h> #include <linux/iomap.h> +#include <linux/ktime.h> #include "gfs2.h" #include "incore.h" @@ -2248,7 +2249,9 @@ int gfs2_map_journal_extents(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd)unsigned int shift = sdp->sd_sb.sb_bsize_shift;u64 size;int rc; +ktime_t start, end; + start =ktime_get (); lblock_stop =i_size_read (jd->jd_inode) >> shift; size = (lblock_stop - lblock) << shift; jd->nr_extents =0 ;@@ -2268,8 +2271,9 @@ int gfs2_map_journal_extents(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd) lblock += (bh.b_size >> ip->i_inode.i_blkbits); }while (size >0 ); -fs_info (sdp,"journal %d mapped with %u extents\n" , jd->jd_jid, - jd->nr_extents); + end =ktime_get (); +fs_info (sdp,"journal %d mapped with %u extents in %lldms\n" , jd->jd_jid, + jd->nr_extents,ktime_ms_delta (end, start));return 0 ; fail:fs/gfs2/recovery.c +2
-1@@ -460,6 +460,8 @@ void gfs2_recover_func(struct work_struct *work)if (error) goto fail_gunlock_ji; t_jhd =ktime_get (); +fs_info (sdp,"jid=%u: Journal head lookup took %lldms\n" , jd->jd_jid, +ktime_ms_delta (t_jhd, t_jlck));if (!(head.lh_flags &GFS2_LOG_HEAD_UNMOUNT )) { fs_info(sdp, "jid=%u: Acquiring the transaction lock...\n", --2.4.11
PATCH 2/4 gfs2: changes to gfs2_log_XXX_bio
In reply to Abhi DasChange gfs2_log_XXX_bio family of functions so they can be used with different bios, not just sdp->sd_log_bio.
This patch also contains some clean up suggested by Andreas.
--- fs/gfs2/log.c | 4 ++-- fs/gfs2/lops.c | 73 +++++++++++++++++++++++++++++++--------------------------- fs/gfs2/lops.h | 2 +- 3 files changed, 42 insertions(+), 37 deletions(-)
fs/gfs2/log.c +2 -2
@@ -734,7 +734,7 @@ void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd, lh->lh_crc =cpu_to_be32 (crc);gfs2_log_write (sdp, page, sb->s_blocksize,0 , addr); -gfs2_log_flush_bio (sdp,REQ_OP_WRITE , op_flags); +gfs2_log_submit_bio (&sdp->sd_log_bio,REQ_OP_WRITE , op_flags);log_flush_wait (sdp); }
@@ -811,7 +811,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)gfs2_ordered_write (sdp);lops_before_commit (sdp, tr); -gfs2_log_flush_bio (sdp,REQ_OP_WRITE ,0 ); +gfs2_log_submit_bio (&sdp->sd_log_bio,REQ_OP_WRITE ,0 );if (sdp->sd_log_head != sdp->sd_log_flush_head) {log_flush_wait (sdp);
fs/gfs2/lops.c +39 -34
132 lines not on this page · raw message
fs/gfs2/lops.h +1 -1
@@ -30,7 +30,7 @@ extern u64 gfs2_log_bmap(struct gfs2_sbd *sdp);extern void gfs2_log_write (struct gfs2_sbd *sdp,struct page *page,unsigned size,unsigned offset,u64 blkno);extern void gfs2_log_write_page (struct gfs2_sbd *sdp,struct page *page); -extern void gfs2_log_flush_bio (struct gfs2_sbd *sdp,int op,int op_flags); +extern void gfs2_log_submit_bio (struct bio **biop,int op,int op_flags);extern void gfs2_pin (struct gfs2_sbd *sdp,struct buffer_head *bh);static inline unsigned int buf_limit (struct gfs2_sbd *sdp)
Signature · 1 line
2.4.11
PATCH 3/4 gfs2: add a helper function to get_log_header that can be used elsewhere
In reply to Abhi DasMove and re-order the error checks and hash/crc computations into another function __get_log_header() so it can be used in scenarios where buffer_heads are not being used for the log header.
--- fs/gfs2/recovery.c | 53 ++++++++++++++++++++++++++++++++--------------------- fs/gfs2/recovery.h | 2 ++ 2 files changed, 34 insertions(+), 21 deletions(-)
fs/gfs2/recovery.c +32 -21
@@ -120,6 +120,35 @@ void gfs2_revoke_clean(struct gfs2_jdesc *jd) } } +int __get_log_header (struct gfs2_sbd *sdp,const struct gfs2_log_header *lh, +unsigned int blkno,struct gfs2_log_header_host *head) +{ +u32 hash, crc; + +if (lh->lh_header.mh_magic !=cpu_to_be32 (GFS2_MAGIC ) || + lh->lh_header.mh_type !=cpu_to_be32 (GFS2_METATYPE_LH ) || + (blkno &&be32_to_cpu (lh->lh_blkno) != blkno)) +return 1 ; + + hash =crc32 (~0 , lh,LH_V1_SIZE -4 ); + hash = ~crc32_le_shift (hash,4 );/* assume lh_hash is zero */ + +if (be32_to_cpu (lh->lh_hash) != hash) +return 1 ; + + crc =crc32c (~0 , (void *)lh +LH_V1_SIZE +4 , + sdp->sd_sb.sb_bsize -LH_V1_SIZE -4 ); + +if ((lh->lh_crc !=0 &&be32_to_cpu (lh->lh_crc) != crc)) +return 1 ; + + head->lh_sequence =be64_to_cpu (lh->lh_sequence); + head->lh_flags =be32_to_cpu (lh->lh_flags); + head->lh_tail =be32_to_cpu (lh->lh_tail); + head->lh_blkno =be32_to_cpu (lh->lh_blkno); + +return 0 ; +}/** * get_log_header - read the log header for a given segment * @jd: the journal
@@ -137,36 +166,18 @@ void gfs2_revoke_clean(struct gfs2_jdesc *jd)static int get_log_header (struct gfs2_jdesc *jd,unsigned int blk,struct gfs2_log_header_host *head) { -struct gfs2_log_header *lh; +struct gfs2_sbd *sdp =GFS2_SB (jd->jd_inode);struct buffer_head *bh; -u32 hash, crc;int error; error =gfs2_replay_read_block (jd, blk, &bh);if (error)return error; - lh = (void *)bh->b_data; - - hash =crc32 (~0 , lh,LH_V1_SIZE -4 ); - hash = ~crc32_le_shift (hash,4 );/* assume lh_hash is zero */ - - crc =crc32c (~0 , (void *)lh +LH_V1_SIZE +4 , - bh->b_size -LH_V1_SIZE -4 ); - - error = lh->lh_header.mh_magic !=cpu_to_be32 (GFS2_MAGIC ) || - lh->lh_header.mh_type !=cpu_to_be32 (GFS2_METATYPE_LH ) || -be32_to_cpu (lh->lh_blkno) != blk || -be32_to_cpu (lh->lh_hash) != hash || - (lh->lh_crc !=0 &&be32_to_cpu (lh->lh_crc) != crc); + error =__get_log_header (sdp, (const struct gfs2_log_header *)bh->b_data, + blk, head);brelse (bh); -if (!error) { - head->lh_sequence =be64_to_cpu (lh->lh_sequence); - head->lh_flags =be32_to_cpu (lh->lh_flags); - head->lh_tail =be32_to_cpu (lh->lh_tail); - head->lh_blkno =be32_to_cpu (lh->lh_blkno); - }return error; }
fs/gfs2/recovery.h +2 -0
@@ -31,6 +31,8 @@ extern int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head);extern int gfs2_recover_journal (struct gfs2_jdesc *gfs2_jd,bool wait);extern void gfs2_recover_func (struct work_struct *work); +extern int __get_log_header (struct gfs2_sbd *sdp,const struct gfs2_log_header *lh, +unsigned int blkno,struct gfs2_log_header_host *head);#endif /* __RECOVERY_DOT_H__ */
Signature · 1 line
2.4.11
Andreas Gruenbacher
maintainerPATCH 3/4 gfs2: add a helper function to get_log_header that can be used elsewhere
Quoted 5 lines · Abhi Das
Move and re-order the error checks and hash/crc computations into another function
__get_log_header()so it can be used in scenarios wherebuffer_headsare not being used for the log header.Signed-off-by Abhi Das <[email protected]>
Thanks,
Andreas
Quoted 101 lines
--- fs/gfs2/recovery.c | 53 ++++++++++++++++++++++++++++++++--------------------- fs/gfs2/recovery.h | 2 ++ 2 files changed, 34 insertions(+), 21 deletions(-)fs/gfs2/recovery.c +32
-21@@ -120,6 +120,35 @@ void gfs2_revoke_clean(struct gfs2_jdesc *jd) } } +int __get_log_header (struct gfs2_sbd *sdp,const struct gfs2_log_header *lh, +unsigned int blkno,struct gfs2_log_header_host *head) +{ +u32 hash, crc; + +if (lh->lh_header.mh_magic !=cpu_to_be32 (GFS2_MAGIC ) || + lh->lh_header.mh_type !=cpu_to_be32 (GFS2_METATYPE_LH ) || + (blkno &&be32_to_cpu (lh->lh_blkno) != blkno)) +return 1 ; + + hash =crc32 (~0 , lh,LH_V1_SIZE -4 ); + hash = ~crc32_le_shift (hash,4 );/* assume lh_hash is zero */ + +if (be32_to_cpu (lh->lh_hash) != hash) +return 1 ; + + crc =crc32c (~0 , (void *)lh +LH_V1_SIZE +4 , + sdp->sd_sb.sb_bsize -LH_V1_SIZE -4 ); + +if ((lh->lh_crc !=0 &&be32_to_cpu (lh->lh_crc) != crc)) +return 1 ; + + head->lh_sequence =be64_to_cpu (lh->lh_sequence); + head->lh_flags =be32_to_cpu (lh->lh_flags); + head->lh_tail =be32_to_cpu (lh->lh_tail); + head->lh_blkno =be32_to_cpu (lh->lh_blkno); + +return 0 ; +}/** * get_log_header - read the log header for a given segment * @jd: the journal @@ -137,36 +166,18 @@ void gfs2_revoke_clean(struct gfs2_jdesc *jd)static int get_log_header (struct gfs2_jdesc *jd,unsigned int blk,struct gfs2_log_header_host *head) { -struct gfs2_log_header *lh; +struct gfs2_sbd *sdp =GFS2_SB (jd->jd_inode);struct buffer_head *bh; -u32 hash, crc;int error; error =gfs2_replay_read_block (jd, blk, &bh);if (error)return error; - lh = (void *)bh->b_data; - - hash =crc32 (~0 , lh,LH_V1_SIZE -4 ); - hash = ~crc32_le_shift (hash,4 );/* assume lh_hash is zero */ - - crc =crc32c (~0 , (void *)lh +LH_V1_SIZE +4 , - bh->b_size -LH_V1_SIZE -4 ); - - error = lh->lh_header.mh_magic !=cpu_to_be32 (GFS2_MAGIC ) || - lh->lh_header.mh_type !=cpu_to_be32 (GFS2_METATYPE_LH ) || -be32_to_cpu (lh->lh_blkno) != blk || -be32_to_cpu (lh->lh_hash) != hash || - (lh->lh_crc !=0 &&be32_to_cpu (lh->lh_crc) != crc); + error =__get_log_header (sdp, (const struct gfs2_log_header *)bh->b_data, + blk, head);brelse (bh); -if (!error) { - head->lh_sequence =be64_to_cpu (lh->lh_sequence); - head->lh_flags =be32_to_cpu (lh->lh_flags); - head->lh_tail =be32_to_cpu (lh->lh_tail); - head->lh_blkno =be32_to_cpu (lh->lh_blkno); - }return error; }fs/gfs2/recovery.h +2
-1@@ -31,6 +31,8 @@ extern int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head);extern int gfs2_recover_journal (struct gfs2_jdesc *gfs2_jd,bool wait);extern void gfs2_recover_func (struct work_struct *work); +extern int __get_log_header (struct gfs2_sbd *sdp,const struct gfs2_log_header *lh, +unsigned int blkno,struct gfs2_log_header_host *head);#endif /* __RECOVERY_DOT_H__ */ --2.4.11
PATCH 4/4 gfs2: read journal in large chunks to locate the head
In reply to Abhi DasUse bio(s) to read in the journal sequentially in large chunks and locate the head of the journal.
--- fs/gfs2/glops.c | 1 + fs/gfs2/lops.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++- fs/gfs2/lops.h | 2 + fs/gfs2/ops_fstype.c | 1 + fs/gfs2/recovery.c | 123 ------------------------------------- fs/gfs2/recovery.h | 2 - fs/gfs2/super.c | 1 + 7 files changed, 171 insertions(+), 126 deletions(-)
fs/gfs2/glops.c +1 -0
@@ -28,6 +28,7 @@#include "util.h" #include "trans.h" #include "dir.h" +#include "lops.h" struct workqueue_struct *gfs2_freeze_wq;
fs/gfs2/lops.c +166 -1
185 lines not on this page · raw message
fs/gfs2/lops.h +2 -0
@@ -32,6 +32,8 @@ extern void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page,extern void gfs2_log_write_page (struct gfs2_sbd *sdp,struct page *page);extern void gfs2_log_submit_bio (struct bio **biop,int op,int op_flags);extern void gfs2_pin (struct gfs2_sbd *sdp,struct buffer_head *bh); +extern int gfs2_find_jhead (struct gfs2_jdesc *jd, +struct gfs2_log_header_host *head);static inline unsigned int buf_limit (struct gfs2_sbd *sdp) {
fs/gfs2/ops_fstype.c +1 -0
@@ -41,6 +41,7 @@#include "dir.h" #include "meta_io.h" #include "trace_gfs2.h" +#include "lops.h" #define DO 0#define UNDO 1
fs/gfs2/recovery.c +0 -123
129 lines not on this page · raw message
fs/gfs2/recovery.h +0 -2
@@ -27,8 +27,6 @@ extern int gfs2_revoke_add(struct gfs2_jdesc *jd, u64 blkno, unsigned int where)extern int gfs2_revoke_check (struct gfs2_jdesc *jd,u64 blkno,unsigned int where);extern void gfs2_revoke_clean (struct gfs2_jdesc *jd); -extern int gfs2_find_jhead (struct gfs2_jdesc *jd, -struct gfs2_log_header_host *head);extern int gfs2_recover_journal (struct gfs2_jdesc *gfs2_jd,bool wait);extern void gfs2_recover_func (struct work_struct *work); extern int __get_log_header(struct gfs2_sbd *sdp, const struct gfs2_log_header *lh,
fs/gfs2/super.c +1 -0
@@ -45,6 +45,7 @@#include "util.h" #include "sys.h" #include "xattr.h" +#include "lops.h" #define args_neq (a1, a2, x) ((a1)->ar_##x != (a2)->ar_##x)
Signature · 1 line
2.4.11
PATCH 4/4 gfs2: read journal in large chunks to locate the head
Quoted 7 lines
fs/gfs2/lops.c +7
-0+/** +* gfs2_end_log_read - end I/O callback for reads from the log +* @bio: The bio +* +* Simply unlock the pages in the bio. The main thread will wait on them and +* process them in order as necessary. +*/
fs/gfs2/lops.c void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page) · line 394
Quoted 10 lines
fs/gfs2/lops.c +10
-0+ +static void gfs2_end_log_read (struct bio *bio) +{ +struct gfs2_sbd *sdp = bio->bi_private; +struct page *page; +struct bio_vec *bvec; +int i; + +if (bio->bi_status) +fs_err (sdp,"Error %d reading from journal\n" , bio->bi_status);
How is error handling forthis going to work?
fs/gfs2/lops.c void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page) · line 519
Quoted 1 line
fs/gfs2/lops.c +1
-0+bio_set_op_attrs (bio,REQ_OP_READ ,0 );
Please assign to bi_opf directly instead of using bio_set_op_attrs.
PATCH 4/4 gfs2: read journal in large chunks to locate the head
Quoted 20 lines · Christoph Hellwig
Quoted 5 lines
+/**
+ *gfs2_end_log_read- end I/O callback for reads from the log
+ * @bio: The bio
+ *
+ * Simply unlock the pages in the bio. The main thread will wait onthem and
fs/gfs2/lops.c void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page)
Quoted 12 lines
+ * process them in order as necessary.
+ */fs/gfs2/lops.c +10
-0+ +static void gfs2_end_log_read (struct bio *bio) +{ +struct gfs2_sbd *sdp = bio->bi_private; +struct page *page; +struct bio_vec *bvec; +int i; + +if (bio->bi_status) + fs_err(sdp, "Error %d reading from journal\n",
bio->bi_status);
Quoted 2 lines
How is error handling forthis going to work?
It's not. I'll post an updated version.
Quoted 5 lines
Quoted 2 lines
+
bio_set_op_attrs(bio, REQ_OP_READ, 0);Please assign to
bi_opfdirectly instead of usingbio_set_op_attrs.
Yes. Didn't realize this was deprecated. There's another place where this is used. The updated patch will address this.
Thanks for the review!
Cheers!
--Abhi
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/cluster-devel/attachments/20181017/4e080374/attachment.htm>
cover jhead lookup using bios
In reply to Abhi DasHi,
This all looks good to me, so now we just need lots of testing. Are you still seeing good speed ups vs the current code?
Steve.
Quoted 27 lines · Abhi Das
This is my latest version of this patchset based on inputs from Andreas and Steve.
We readahead the journal sequentially in large chunks using bios. Pagecache pages for the journal inode's mapping are used for the I/O.There's also some cleanup of the bio functions with this patchset.
xfstests ran to completion with this.
Abhi Das (4):
gfs2: add more timing info to journal recovery process
gfs2: changes togfs2_log_XXX_bio
gfs2: add a helper function toget_log_headerthat can be used
elsewhere
gfs2: read journal in large chunks to locate the headfs/gfs2/bmap.c | 8 +- fs/gfs2/glops.c | 1 + fs/gfs2/log.c | 4 +- fs/gfs2/lops.c | 240 +++++++++++++++++++++++++++++++++++++++++++-------- fs/gfs2/lops.h | 4 +- fs/gfs2/ops_fstype.c | 1 + fs/gfs2/recovery.c | 178 ++++++++------------------------------ fs/gfs2/recovery.h | 4 +- fs/gfs2/super.c | 1 + 9 files changed, 255 insertions(+), 186 deletions(-)
cover jhead lookup using bios
In reply to Abhi Das----- Original Message -----
Quoted 7 lines
This is my latest version of this patchset based on inputs from Andreas and Steve.
We readahead the journal sequentially in large chunks using bios. Pagecache pages for the journal inode's mapping are used for the I/O.There's also some cleanup of the bio functions with this patchset.
Quoted 8 lines
xfstests ran to completion with this.
Abhi Das (4):
gfs2: add more timing info to journal recovery process
gfs2: changes togfs2_log_XXX_bio
gfs2: add a helper function toget_log_headerthat can be used
elsewhere
gfs2: read journal in large chunks to locate the head
Hi,
Thanks. This patch set is now pushed to the for-next branch of the linux-gfs2 tree:
https://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2.git/commit/fs/gfs2?h=for-next&id=cc584ff3f572370af8e1ee85883db8280ed10965
https://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2.git/commit/fs/gfs2?h=for-next&id=5cc3cc8c5363d34098c67b31d688189a69225eba
https://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2.git/commit/fs/gfs2?h=for-next&id=0bb829823eab09efa001c9f35cc2763ea19d8055
https://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2.git/commit/fs/gfs2?h=for-next&id=8d52c6496a3d07fc784fe21dbbc3b48658b283e2
Regards,
Bob Peterson
Red Hat File Systems