| To: | Dave Chinner <david@xxxxxxxxxxxxx> |
|---|---|
| Subject: | Re: xfs: invalid requests to request_fn from xfs_repair |
| From: | Jamie Pocas <pocas.jamie@xxxxxxxxx> |
| Date: | Mon, 7 Apr 2014 23:56:10 -0400 |
| Cc: | xfs@xxxxxxxxxxx |
| Delivered-to: | xfs@xxxxxxxxxxx |
| Dkim-signature: | v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=muXswuTIIHFMmIvgodip0sky8kQAL4IhrtMBTIfuA9E=; b=fu9uOJP4pMbkH6bdZh1wEGNCL49ddlIrnXMsx0TZae8XmPlxTfWsYyixwcj/FdTGAK smzXNFXm4V2Br/JgDLvMCALdwFQ/tmkx65rWc2b077sNcrdRbOO0AMHsLpItxLG8SWRx GDg8woyDp3Cy1ncfeNSEUhxUxmRBfsVFMNupF/n7AI2RcqsAOgp+4xxu4c8Y89puPa/l oPj8Ywm61jQN/rVtEDdzRIEcWpU6yp08UIBSx5kMdozgG+A7QyV2kh5cMY03+M2HqG9a azzNI4TY57GV8loWg1xCr0N4wqJh8JvV1MkLNn/arJRaRDlVo3CvIUEEBKCSmF8JPNpL 9LDQ== |
| In-reply-to: | <CABHf-sx3H2=R72gFZik3QhygiF4VhUMXGt1VPw2AaXoXMcz8OQ@xxxxxxxxxxxxxx> |
| References: | <CABHf-sxmxmM0+WVzvGGJqKrrGngm0qrGTsYDnEmUEf+GJ_pK8A@xxxxxxxxxxxxxx> <20140401204215.GG17603@dastard> <CABHf-sxeACnsSoJszM8Xan-VcXLkLdrY7cBM9=FCAxdMBaQohA@xxxxxxxxxxxxxx> <20140402044749.GK17603@dastard> <CABHf-sx3H2=R72gFZik3QhygiF4VhUMXGt1VPw2AaXoXMcz8OQ@xxxxxxxxxxxxxx> |
|
Hi Dave, Okay, I think I've found a workaround but I don't have the root cause yet. So just to recap there is a macro defined in include/linux/blkdev.h called rq_for_each_segment(bvec, rq, iter). The arguments are of type struct bio_vec*, struct request*, and struct req_iterator respectively. The macro expands to several other macro invocations, which eventually expand to approx. 40-50 lines of code. (NOTE: in newer kernels the first argument is a bio_vec, and not a bio_vec*. I think this is due to the immutable bio_vec changes, but I could be wrong. For more on that, see http://lwn.net/Articles/544713/ , but I digress.) It seems like in some instances when using O_DIRECT and iterating through the request using the above macro, I see that some fields of iter.bio are not updated to the correct value and macros like blk_rq_cur_sectors(), which ultimately rely on rq->bio, thus do not return the correct values. If I assume (<--- dangerous word) that the sectors are all adjacent, as they really are supposed to be in all my investigation, and use only the bio_vec fields to track progress then the problems go away. I have been running all sorts of data consistency tests since this discovery and I don't have any further problems so far. Also, xfs_repair is returning cleanly as expected now. So basically I am only using blk_rq_pos(rq) once before the loop to get the start sector, and then only relying on fields of bvec after that. For example if I need to count the number of sectors, I can accumulate (bvec->bv_len >> 9) through all the iterations. Summing up all of blk_req_curr_sectors(rq) only worked sometimes, and so was unreliable. Basically, the code to walk the request * looks something like this now, where it used to make use of iter.bio->bi_sector and blk_rq_cur_sectors. sector_t curr_sector = blk_rq_pos(req); // Should not do the memory mapping on a discard request, payload is invalid /* Iterate through the request */ /* Do the transfer to the device. This part is not really relevant to the discussion here kunmap(bvec->bv_page); /* FAIL */ total_sectors += curr_num_sectors; // Just for accounting I am going to run the compiler with -E and examine the rq_for_each_segment() macro expansion to see where the suspected problem happens. If it does look like a bug, I am going to write to LKML. Perhaps it's something I am supposed to implicitly understand that is not well documented (like the rest of O_DIRECT), and they can set me straight. As it stands this doesn't seem to be an xfs issue so I'm going to drop this discussion unless anyone else is interested in this issue or wants more info. Regards, On Wed, Apr 2, 2014 at 12:47 AM, Dave Chinner <david@xxxxxxxxxxxxx> wrote:
I agree that the iterator *looks* wrong, Like I said earlier, I am just using the rq_for_each_segment() macro (defined in include/linux/blkdev.h and expands to a few dozen lines of code). This is the recommended way of iterating requests instead of using the lower level bio iterating functions or going it yourself which is why it's recommended to use that instead of going deeper and breaking compatibility when the kernel changes. I suspect it's the request itself which was constructed incorrectly, or contains bios that should not have been grouped into the same request, or contains bios that have their bi_sector set incorrectly.
This is the xfs_repair tool being run directly against a block device, so if I am reading the fs/direct-io.c code correctly this means that the mapping function (get_block_t) is using fs/block_dev.c:blkdev_get_block(). Is that correct? That function is very short and simple, so I can't imagine how there would be a bug in there. If it were a file on an xfs filesystem, the get_block_t callback would be xfs_get_blocks or xfs_get_blocks_direct (which both internally call __xfs_get_blocks). Is my understanding correct?
|
| <Prev in Thread] | Current Thread | [Next in Thread> |
|---|---|---|
| ||
| Previous by Date: | Re: XFS fragmentation on file append, Keyur Govande |
|---|---|
| Next by Date: | [PATCH] xfstests: fix wallclock possibly wrapped problem, Wanlong Gao |
| Previous by Thread: | Re: xfs: invalid requests to request_fn from xfs_repair, Jamie Pocas |
| Next by Thread: | Re: [PATCH] xfs: fix bad hash ordering, Dave Chinner |
| Indexes: | [Date] [Thread] [Top] [All Lists] |