From 185f71c96883eb378909d728b599198c4fee5cb1 Mon Sep 17 00:00:00 2001 From: nikita Date: Tue, 28 Jun 2005 08:58:24 +0000 Subject: [PATCH] fixes for bug 6854: - add a comment describing ->fs_send_bio() return convention. - fsfilt_ext3_commit_async(): check for journal abort after waiting for commit. - fsfilt_ext3_send_bio(): handle short writes. - filter_commitrw_write(): print error message on commit failure. - added patch linux-2.4.24-jbd-handle-EIO.patch (trivial backport from 2.6 jbd) to check for IO erros during transaction commit. Approved: https://bugzilla.lustre.org/show_bug.cgi?id=6854#c38 --- lustre/include/linux/lustre_fsfilt.h | 15 +++++-- .../patches/linux-2.4.24-jbd-handle-EIO.patch | 51 ++++++++++++++++++++++ lustre/kernel_patches/series/vanilla-2.4.24 | 1 + lustre/lvfs/fsfilt_ext3.c | 29 +++++++++--- lustre/obdfilter/filter_io_24.c | 8 ++-- 5 files changed, 91 insertions(+), 13 deletions(-) create mode 100644 lustre/kernel_patches/patches/linux-2.4.24-jbd-handle-EIO.patch diff --git a/lustre/include/linux/lustre_fsfilt.h b/lustre/include/linux/lustre_fsfilt.h index 11fd2a9..2cc850e 100644 --- a/lustre/include/linux/lustre_fsfilt.h +++ b/lustre/include/linux/lustre_fsfilt.h @@ -58,7 +58,16 @@ struct fsfilt_operations { int (* fs_set_md)(struct inode *inode, void *handle, void *md, int size); int (* fs_get_md)(struct inode *inode, void *md, int size); - /* this method is needed to make IO operation fsfilt nature depend. */ + /* + * this method is needed to make IO operation fsfilt nature depend. + * + * This operation maybe synchronous or asynchronous. + * + * Return convention: positive number of bytes written (synchronously) + * on success. Negative errno value on failure. Zero if asynchronous + * IO was submitted successfully. + * + */ int (* fs_send_bio)(int rw, struct inode *inode,struct kiobuf *bio); ssize_t (* fs_readpage)(struct file *file, char *buf, size_t count, loff_t *offset); @@ -82,7 +91,7 @@ struct fsfilt_operations { struct obd_quotactl *oqctl); int (* fs_quotactl)(struct super_block *sb, struct obd_quotactl *oqctl); - int (* fs_quotainfo)(struct lustre_quota_info *lqi, int type, + int (* fs_quotainfo)(struct lustre_quota_info *lqi, int type, int cmd); int (* fs_dquot)(struct lustre_dquot *dquot, int cmd); }; @@ -253,7 +262,7 @@ static inline int fsfilt_send_bio(int rw, struct obd_device *obd, struct inode *inode, void *bio) { LASSERTF(rw == OBD_BRW_WRITE || rw == OBD_BRW_READ, "%x\n", rw); - + if (rw == OBD_BRW_READ) return obd->obd_fsops->fs_send_bio(READ, inode, bio); return obd->obd_fsops->fs_send_bio(WRITE, inode, bio); diff --git a/lustre/kernel_patches/patches/linux-2.4.24-jbd-handle-EIO.patch b/lustre/kernel_patches/patches/linux-2.4.24-jbd-handle-EIO.patch new file mode 100644 index 0000000..ff2991f --- /dev/null +++ b/lustre/kernel_patches/patches/linux-2.4.24-jbd-handle-EIO.patch @@ -0,0 +1,51 @@ +diff -X /home/nikita/src/linux-git/linux-2.6.git/Documentation/dontdiff -rupbB linux-2.4.24.orig/fs/jbd/commit.c linux-2.4.24/fs/jbd/commit.c +--- linux-2.4.24.orig/fs/jbd/commit.c 2005-06-23 17:39:32.000000000 +0400 ++++ linux-2.4.24/fs/jbd/commit.c 2005-06-23 15:56:05.000000000 +0400 +@@ -47,7 +47,7 @@ void journal_commit_transaction(journal_ + struct buffer_head *wbuf[64]; + int bufs; + int flags; +- int err; ++ int err = 0; + unsigned long blocknr; + char *tagp = NULL; + journal_header_t *header; +@@ -505,6 +505,9 @@ start_journal_io: + goto wait_for_iobuf; + } + ++ if (unlikely(!buffer_uptodate(bh))) ++ err = -EIO; ++ + clear_bit(BH_JWrite, &jh2bh(jh)->b_state); + + JBUFFER_TRACE(jh, "ph4: unfile after journal write"); +@@ -566,6 +569,9 @@ start_journal_io: + goto wait_for_ctlbuf; + } + ++ if (unlikely(!buffer_uptodate(bh))) ++ err = -EIO; ++ + BUFFER_TRACE(bh, "ph5: control buffer writeout done: unfile"); + clear_bit(BH_JWrite, &bh->b_state); + journal_unfile_buffer(jh); +@@ -610,6 +616,8 @@ start_journal_io: + bh->b_end_io = journal_end_buffer_io_sync; + submit_bh(WRITE, bh); + wait_on_buffer(bh); ++ if (unlikely(!buffer_uptodate(bh))) ++ err = -EIO; + put_bh(bh); /* One for getblk() */ + journal_unlock_journal_head(descriptor); + } +@@ -621,6 +629,9 @@ start_journal_io: + + skip_commit: /* The journal should be unlocked by now. */ + ++ if (err) ++ __journal_abort_hard(journal); ++ + /* Call any callbacks that had been registered for handles in this + * transaction. It is up to the callback to free any allocated + * memory. diff --git a/lustre/kernel_patches/series/vanilla-2.4.24 b/lustre/kernel_patches/series/vanilla-2.4.24 index 144e66e..a8ee3e0 100644 --- a/lustre/kernel_patches/series/vanilla-2.4.24 +++ b/lustre/kernel_patches/series/vanilla-2.4.24 @@ -46,3 +46,4 @@ remove-suid-2.4-rhel.patch uml-exprt-clearuser.patch fsprivate-2.4.patch nfsd_iallocsem.patch +linux-2.4.24-jbd-handle-EIO.patch diff --git a/lustre/lvfs/fsfilt_ext3.c b/lustre/lvfs/fsfilt_ext3.c index d52c088..c5ff7a9 100644 --- a/lustre/lvfs/fsfilt_ext3.c +++ b/lustre/lvfs/fsfilt_ext3.c @@ -388,14 +388,17 @@ static int fsfilt_ext3_commit_async(struct inode *inode, void *h, static int fsfilt_ext3_commit_wait(struct inode *inode, void *h) { + journal_t *journal = EXT3_JOURNAL(inode); tid_t tid = (tid_t)(long)h; CDEBUG(D_INODE, "commit wait: %lu\n", (unsigned long) tid); - if (is_journal_aborted(EXT3_JOURNAL(inode))) + if (unlikely(is_journal_aborted(journal))) return -EIO; log_wait_commit(EXT3_JOURNAL(inode), tid); + if (unlikely(is_journal_aborted(journal))) + return -EIO; return 0; } @@ -518,17 +521,29 @@ static int fsfilt_ext3_send_bio(int rw, struct inode *inode, struct bio *bio) #else static int fsfilt_ext3_send_bio(int rw, struct inode *inode, struct kiobuf *bio) { - int rc, blocks_per_page; + int rc, blk_per_page; rc = brw_kiovec(rw, 1, &bio, inode->i_dev, KIOBUF_GET_BLOCKS(bio), 1 << inode->i_blkbits); + /* + * brw_kiovec() returns number of bytes actually written. If error + * occurred after something was written, error code is returned though + * kiobuf->errno. (See bug 6854.) + */ - blocks_per_page = PAGE_SIZE >> inode->i_blkbits; + blk_per_page = PAGE_CACHE_SIZE >> inode->i_blkbits; - if (rc != (1 << inode->i_blkbits) * bio->nr_pages * blocks_per_page) { - CERROR("short write? expected %d, wrote %d\n", - (1 << inode->i_blkbits) * bio->nr_pages * - blocks_per_page, rc); + if (rc != (1 << inode->i_blkbits) * bio->nr_pages * blk_per_page) { + CERROR("short write? expected %d, wrote %d (%d)\n", + (1 << inode->i_blkbits) * bio->nr_pages * blk_per_page, + rc, bio->errno); + } + if (bio->errno != 0) { + CERROR("IO error. Wrote %d of %d (%d)\n", + rc, + (1 << inode->i_blkbits) * bio->nr_pages * blk_per_page, + bio->errno); + rc = bio->errno; } return rc; diff --git a/lustre/obdfilter/filter_io_24.c b/lustre/obdfilter/filter_io_24.c index b131b0e..4d43bb3 100644 --- a/lustre/obdfilter/filter_io_24.c +++ b/lustre/obdfilter/filter_io_24.c @@ -79,7 +79,7 @@ static void check_pending_bhs(unsigned long *blocks, int nr_pages, dev_t dev, /* when brw_kiovec() is asked to read from block -1UL it just zeros * the page. this gives us a chance to verify the write mappings * as well */ -static int filter_cleanup_mappings(int rw, struct kiobuf *iobuf, +static int filter_cleanup_mappings(int rw, struct kiobuf *iobuf, struct inode *inode) { int i, blocks_per_page_bits = PAGE_SHIFT - inode->i_blkbits; @@ -179,7 +179,7 @@ int filter_direct_io(int rw, struct dentry *dchild, void *buf, if (iobuf->nr_pages * blocks_per_page > KIO_MAX_SECTORS) GOTO(cleanup, rc = -EINVAL); - if (iobuf->nr_pages * blocks_per_page > + if (iobuf->nr_pages * blocks_per_page > OBDFILTER_CREATED_SCRATCHPAD_ENTRIES) GOTO(cleanup, rc = -EINVAL); @@ -432,8 +432,10 @@ int filter_commitrw_write(struct obd_export *exp, struct obdo *oa, int objcount, fsfilt_check_slow(now, obd_timeout, "direct_io"); err = fsfilt_commit_wait(obd, inode, wait_handle); - if (err) + if (err) { + CERROR("Failure to commit OST transaction (%d)?\n", err); rc = err; + } if (obd_sync_filter && !err) LASSERTF(oti->oti_transno <= obd->obd_last_committed, "oti_transno "LPU64" last_committed "LPU64"\n", -- 1.8.3.1