* Re: [PATCH 11/19] block: implement bio helper to add iter bvec pages to bio
From: Ming Lei @ 2019-02-27 2:37 UTC (permalink / raw)
To: Jens Axboe
Cc: Ming Lei, Eric Biggers, open list:AIO, linux-block, linux-api,
Christoph Hellwig, Jeff Moyer, Avi Kivity, jannh, Al Viro
In-Reply-To: <b54683e8-fbff-01ab-db98-c35de8e00e9f@kernel.dk>
On Tue, Feb 26, 2019 at 07:28:54PM -0700, Jens Axboe wrote:
> On 2/26/19 7:21 PM, Ming Lei wrote:
> > On Tue, Feb 26, 2019 at 06:57:16PM -0700, Jens Axboe wrote:
> >> On 2/26/19 6:53 PM, Ming Lei wrote:
> >>> On Tue, Feb 26, 2019 at 06:47:54PM -0700, Jens Axboe wrote:
> >>>> On 2/26/19 6:21 PM, Ming Lei wrote:
> >>>>> On Tue, Feb 26, 2019 at 11:56 PM Jens Axboe <axboe@kernel.dk> wrote:
> >>>>>>
> >>>>>> On 2/25/19 9:34 PM, Jens Axboe wrote:
> >>>>>>> On 2/25/19 8:46 PM, Eric Biggers wrote:
> >>>>>>>> Hi Jens,
> >>>>>>>>
> >>>>>>>> On Thu, Feb 21, 2019 at 10:45:27AM -0700, Jens Axboe wrote:
> >>>>>>>>> On 2/20/19 3:58 PM, Ming Lei wrote:
> >>>>>>>>>> On Mon, Feb 11, 2019 at 12:00:41PM -0700, Jens Axboe wrote:
> >>>>>>>>>>> For an ITER_BVEC, we can just iterate the iov and add the pages
> >>>>>>>>>>> to the bio directly. This requires that the caller doesn't releases
> >>>>>>>>>>> the pages on IO completion, we add a BIO_NO_PAGE_REF flag for that.
> >>>>>>>>>>>
> >>>>>>>>>>> The current two callers of bio_iov_iter_get_pages() are updated to
> >>>>>>>>>>> check if they need to release pages on completion. This makes them
> >>>>>>>>>>> work with bvecs that contain kernel mapped pages already.
> >>>>>>>>>>>
> >>>>>>>>>>> Reviewed-by: Hannes Reinecke <hare@suse.com>
> >>>>>>>>>>> Reviewed-by: Christoph Hellwig <hch@lst.de>
> >>>>>>>>>>> Signed-off-by: Jens Axboe <axboe@kernel.dk>
> >>>>>>>>>>> ---
> >>>>>>>>>>> block/bio.c | 59 ++++++++++++++++++++++++++++++++-------
> >>>>>>>>>>> fs/block_dev.c | 5 ++--
> >>>>>>>>>>> fs/iomap.c | 5 ++--
> >>>>>>>>>>> include/linux/blk_types.h | 1 +
> >>>>>>>>>>> 4 files changed, 56 insertions(+), 14 deletions(-)
> >>>>>>>>>>>
> >>>>>>>>>>> diff --git a/block/bio.c b/block/bio.c
> >>>>>>>>>>> index 4db1008309ed..330df572cfb8 100644
> >>>>>>>>>>> --- a/block/bio.c
> >>>>>>>>>>> +++ b/block/bio.c
> >>>>>>>>>>> @@ -828,6 +828,23 @@ int bio_add_page(struct bio *bio, struct page *page,
> >>>>>>>>>>> }
> >>>>>>>>>>> EXPORT_SYMBOL(bio_add_page);
> >>>>>>>>>>>
> >>>>>>>>>>> +static int __bio_iov_bvec_add_pages(struct bio *bio, struct iov_iter *iter)
> >>>>>>>>>>> +{
> >>>>>>>>>>> + const struct bio_vec *bv = iter->bvec;
> >>>>>>>>>>> + unsigned int len;
> >>>>>>>>>>> + size_t size;
> >>>>>>>>>>> +
> >>>>>>>>>>> + len = min_t(size_t, bv->bv_len, iter->count);
> >>>>>>>>>>> + size = bio_add_page(bio, bv->bv_page, len,
> >>>>>>>>>>> + bv->bv_offset + iter->iov_offset);
> >>>>>>>>>>
> >>>>>>>>>> iter->iov_offset needs to be subtracted from 'len', looks
> >>>>>>>>>> the following delta change[1] is required, otherwise memory corruption
> >>>>>>>>>> can be observed when running xfstests over loop/dio.
> >>>>>>>>>
> >>>>>>>>> Thanks, I folded this in.
> >>>>>>>>>
> >>>>>>>>> --
> >>>>>>>>> Jens Axboe
> >>>>>>>>>
> >>>>>>>>
> >>>>>>>> syzkaller started hitting a crash on linux-next starting with this commit, and
> >>>>>>>> it still occurs even with your latest version that has Ming's fix folded in.
> >>>>>>>> Specifically, commit a566653ab5ab80a from your io_uring branch with commit date
> >>>>>>>> Sun Feb 24 08:20:53 2019 -0700.
> >>>>>>>>
> >>>>>>>> Reproducer:
> >>>>>>>>
> >>>>>>>> #define _GNU_SOURCE
> >>>>>>>> #include <fcntl.h>
> >>>>>>>> #include <linux/loop.h>
> >>>>>>>> #include <sys/ioctl.h>
> >>>>>>>> #include <sys/sendfile.h>
> >>>>>>>> #include <sys/syscall.h>
> >>>>>>>> #include <unistd.h>
> >>>>>>>>
> >>>>>>>> int main(void)
> >>>>>>>> {
> >>>>>>>> int memfd, loopfd;
> >>>>>>>>
> >>>>>>>> memfd = syscall(__NR_memfd_create, "foo", 0);
> >>>>>>>>
> >>>>>>>> pwrite(memfd, "\xa8", 1, 4096);
> >>>>>>>>
> >>>>>>>> loopfd = open("/dev/loop0", O_RDWR|O_DIRECT);
> >>>>>>>>
> >>>>>>>> ioctl(loopfd, LOOP_SET_FD, memfd);
> >>>>>>>>
> >>>>>>>> sendfile(loopfd, loopfd, NULL, 1000000);
> >>>>>>>> }
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> Crash:
> >>>>>>>>
> >>>>>>>> page:ffffea0001a6aab8 count:0 mapcount:0 mapping:0000000000000000 index:0x0
> >>>>>>>> flags: 0x100000000000000()
> >>>>>>>> raw: 0100000000000000 ffffea0001ad2c50 ffff88807fca49d0 0000000000000000
> >>>>>>>> raw: 0000000000000000 0000000000000000 00000000ffffffff
> >>>>>>>> page dumped because: VM_BUG_ON_PAGE(page_ref_count(page) == 0)
> >>>>>>>
> >>>>>>> I see what this is, I'll cut a fix for this tomorrow.
> >>>>>>
> >>>>>> Folded in a fix for this, it's in my current io_uring branch and my for-next
> >>>>>> branch.
> >>>>>
> >>>>> Hi Jens,
> >>>>>
> >>>>> I saw the following change is added:
> >>>>>
> >>>>> + if (size == len) {
> >>>>> + /*
> >>>>> + * For the normal O_DIRECT case, we could skip grabbing this
> >>>>> + * reference and then not have to put them again when IO
> >>>>> + * completes. But this breaks some in-kernel users, like
> >>>>> + * splicing to/from a loop device, where we release the pipe
> >>>>> + * pages unconditionally. If we can fix that case, we can
> >>>>> + * get rid of the get here and the need to call
> >>>>> + * bio_release_pages() at IO completion time.
> >>>>> + */
> >>>>> + get_page(bv->bv_page);
> >>>>>
> >>>>> Now the 'bv' may point to more than one page, so the following one may be
> >>>>> needed:
> >>>>>
> >>>>> int i;
> >>>>> struct bvec_iter_all iter_all;
> >>>>> struct bio_vec *tmp;
> >>>>>
> >>>>> mp_bvec_for_each_segment(tmp, bv, i, iter_all)
> >>>>> get_page(tmp->bv_page);
> >>>>
> >>>> I guess that would be the safest, even if we don't currently have more
> >>>> than one page in there. I'll fix it up.
> >>>
> >>> It is easy to see multipage bvec from loop, :-)
> >>
> >> Speaking of this, I took a quick look at why we've now regressed a lot
> >> on IOPS perf with the multipage work. It looks like it's all related to
> >> the (much) fatter setup around iteration, which is related to this very
> >> topic too.
> >>
> >> Basically setup of things like bio_for_each_bvec() and indexing through
> >> nth_page() is MUCH slower than before.
> >
> > But bio_for_each_bvec() needn't nth_page(), and only bio_for_each_segment()
> > needs that. However, bio_for_each_segment() isn't called from
> > blk_queue_split() and blk_rq_map_sg().
> >
> > One issue is that bio_for_each_bvec() still advances by page size
> > instead of bvec->len, I guess that is the problem, will cook a patch
> > for your test.
>
> Probably won't make a difference for my test case...
>
> >> We need to do something about this, it's like tossing out months of
> >> optimizations.
> >
> > Some following optimization can be done, such as removing
> > biovec_phys_mergeable() from blk_bio_segment_split().
>
> I think we really need a fast path for <= PAGE_SIZE IOs, to the extent
> that it is possible. But iteration startup cost is a problem in a lot of
> spots, and a split fast path will only help a bit for that specific
> case.
>
> 5% regressions is HUGE. I know I've mentioned this before, I just want
> to really stress how big of a deal that is. It's enough to make me
> consider just reverting it again, which sucks, but I don't feel great
> shipping something that is known that much slower.
>
> Suggestions?
You mentioned nth_page() costs much in bio_for_each_bvec(), but which
shouldn't call into nth_page(). I will look into it first.
Thanks,
Ming
--
To unsubscribe, send a message with 'unsubscribe linux-aio' in
the body to majordomo@kvack.org. For more info on Linux AIO,
see: http://www.kvack.org/aio/
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>
^ permalink raw reply
* Re: [PATCH 11/19] block: implement bio helper to add iter bvec pages to bio
From: Jens Axboe @ 2019-02-27 2:28 UTC (permalink / raw)
To: Ming Lei
Cc: Ming Lei, Eric Biggers, open list:AIO, linux-block, linux-api,
Christoph Hellwig, Jeff Moyer, Avi Kivity, jannh, Al Viro
In-Reply-To: <20190227022144.GE16802@ming.t460p>
On 2/26/19 7:21 PM, Ming Lei wrote:
> On Tue, Feb 26, 2019 at 06:57:16PM -0700, Jens Axboe wrote:
>> On 2/26/19 6:53 PM, Ming Lei wrote:
>>> On Tue, Feb 26, 2019 at 06:47:54PM -0700, Jens Axboe wrote:
>>>> On 2/26/19 6:21 PM, Ming Lei wrote:
>>>>> On Tue, Feb 26, 2019 at 11:56 PM Jens Axboe <axboe@kernel.dk> wrote:
>>>>>>
>>>>>> On 2/25/19 9:34 PM, Jens Axboe wrote:
>>>>>>> On 2/25/19 8:46 PM, Eric Biggers wrote:
>>>>>>>> Hi Jens,
>>>>>>>>
>>>>>>>> On Thu, Feb 21, 2019 at 10:45:27AM -0700, Jens Axboe wrote:
>>>>>>>>> On 2/20/19 3:58 PM, Ming Lei wrote:
>>>>>>>>>> On Mon, Feb 11, 2019 at 12:00:41PM -0700, Jens Axboe wrote:
>>>>>>>>>>> For an ITER_BVEC, we can just iterate the iov and add the pages
>>>>>>>>>>> to the bio directly. This requires that the caller doesn't releases
>>>>>>>>>>> the pages on IO completion, we add a BIO_NO_PAGE_REF flag for that.
>>>>>>>>>>>
>>>>>>>>>>> The current two callers of bio_iov_iter_get_pages() are updated to
>>>>>>>>>>> check if they need to release pages on completion. This makes them
>>>>>>>>>>> work with bvecs that contain kernel mapped pages already.
>>>>>>>>>>>
>>>>>>>>>>> Reviewed-by: Hannes Reinecke <hare@suse.com>
>>>>>>>>>>> Reviewed-by: Christoph Hellwig <hch@lst.de>
>>>>>>>>>>> Signed-off-by: Jens Axboe <axboe@kernel.dk>
>>>>>>>>>>> ---
>>>>>>>>>>> block/bio.c | 59 ++++++++++++++++++++++++++++++++-------
>>>>>>>>>>> fs/block_dev.c | 5 ++--
>>>>>>>>>>> fs/iomap.c | 5 ++--
>>>>>>>>>>> include/linux/blk_types.h | 1 +
>>>>>>>>>>> 4 files changed, 56 insertions(+), 14 deletions(-)
>>>>>>>>>>>
>>>>>>>>>>> diff --git a/block/bio.c b/block/bio.c
>>>>>>>>>>> index 4db1008309ed..330df572cfb8 100644
>>>>>>>>>>> --- a/block/bio.c
>>>>>>>>>>> +++ b/block/bio.c
>>>>>>>>>>> @@ -828,6 +828,23 @@ int bio_add_page(struct bio *bio, struct page *page,
>>>>>>>>>>> }
>>>>>>>>>>> EXPORT_SYMBOL(bio_add_page);
>>>>>>>>>>>
>>>>>>>>>>> +static int __bio_iov_bvec_add_pages(struct bio *bio, struct iov_iter *iter)
>>>>>>>>>>> +{
>>>>>>>>>>> + const struct bio_vec *bv = iter->bvec;
>>>>>>>>>>> + unsigned int len;
>>>>>>>>>>> + size_t size;
>>>>>>>>>>> +
>>>>>>>>>>> + len = min_t(size_t, bv->bv_len, iter->count);
>>>>>>>>>>> + size = bio_add_page(bio, bv->bv_page, len,
>>>>>>>>>>> + bv->bv_offset + iter->iov_offset);
>>>>>>>>>>
>>>>>>>>>> iter->iov_offset needs to be subtracted from 'len', looks
>>>>>>>>>> the following delta change[1] is required, otherwise memory corruption
>>>>>>>>>> can be observed when running xfstests over loop/dio.
>>>>>>>>>
>>>>>>>>> Thanks, I folded this in.
>>>>>>>>>
>>>>>>>>> --
>>>>>>>>> Jens Axboe
>>>>>>>>>
>>>>>>>>
>>>>>>>> syzkaller started hitting a crash on linux-next starting with this commit, and
>>>>>>>> it still occurs even with your latest version that has Ming's fix folded in.
>>>>>>>> Specifically, commit a566653ab5ab80a from your io_uring branch with commit date
>>>>>>>> Sun Feb 24 08:20:53 2019 -0700.
>>>>>>>>
>>>>>>>> Reproducer:
>>>>>>>>
>>>>>>>> #define _GNU_SOURCE
>>>>>>>> #include <fcntl.h>
>>>>>>>> #include <linux/loop.h>
>>>>>>>> #include <sys/ioctl.h>
>>>>>>>> #include <sys/sendfile.h>
>>>>>>>> #include <sys/syscall.h>
>>>>>>>> #include <unistd.h>
>>>>>>>>
>>>>>>>> int main(void)
>>>>>>>> {
>>>>>>>> int memfd, loopfd;
>>>>>>>>
>>>>>>>> memfd = syscall(__NR_memfd_create, "foo", 0);
>>>>>>>>
>>>>>>>> pwrite(memfd, "\xa8", 1, 4096);
>>>>>>>>
>>>>>>>> loopfd = open("/dev/loop0", O_RDWR|O_DIRECT);
>>>>>>>>
>>>>>>>> ioctl(loopfd, LOOP_SET_FD, memfd);
>>>>>>>>
>>>>>>>> sendfile(loopfd, loopfd, NULL, 1000000);
>>>>>>>> }
>>>>>>>>
>>>>>>>>
>>>>>>>> Crash:
>>>>>>>>
>>>>>>>> page:ffffea0001a6aab8 count:0 mapcount:0 mapping:0000000000000000 index:0x0
>>>>>>>> flags: 0x100000000000000()
>>>>>>>> raw: 0100000000000000 ffffea0001ad2c50 ffff88807fca49d0 0000000000000000
>>>>>>>> raw: 0000000000000000 0000000000000000 00000000ffffffff
>>>>>>>> page dumped because: VM_BUG_ON_PAGE(page_ref_count(page) == 0)
>>>>>>>
>>>>>>> I see what this is, I'll cut a fix for this tomorrow.
>>>>>>
>>>>>> Folded in a fix for this, it's in my current io_uring branch and my for-next
>>>>>> branch.
>>>>>
>>>>> Hi Jens,
>>>>>
>>>>> I saw the following change is added:
>>>>>
>>>>> + if (size == len) {
>>>>> + /*
>>>>> + * For the normal O_DIRECT case, we could skip grabbing this
>>>>> + * reference and then not have to put them again when IO
>>>>> + * completes. But this breaks some in-kernel users, like
>>>>> + * splicing to/from a loop device, where we release the pipe
>>>>> + * pages unconditionally. If we can fix that case, we can
>>>>> + * get rid of the get here and the need to call
>>>>> + * bio_release_pages() at IO completion time.
>>>>> + */
>>>>> + get_page(bv->bv_page);
>>>>>
>>>>> Now the 'bv' may point to more than one page, so the following one may be
>>>>> needed:
>>>>>
>>>>> int i;
>>>>> struct bvec_iter_all iter_all;
>>>>> struct bio_vec *tmp;
>>>>>
>>>>> mp_bvec_for_each_segment(tmp, bv, i, iter_all)
>>>>> get_page(tmp->bv_page);
>>>>
>>>> I guess that would be the safest, even if we don't currently have more
>>>> than one page in there. I'll fix it up.
>>>
>>> It is easy to see multipage bvec from loop, :-)
>>
>> Speaking of this, I took a quick look at why we've now regressed a lot
>> on IOPS perf with the multipage work. It looks like it's all related to
>> the (much) fatter setup around iteration, which is related to this very
>> topic too.
>>
>> Basically setup of things like bio_for_each_bvec() and indexing through
>> nth_page() is MUCH slower than before.
>
> But bio_for_each_bvec() needn't nth_page(), and only bio_for_each_segment()
> needs that. However, bio_for_each_segment() isn't called from
> blk_queue_split() and blk_rq_map_sg().
>
> One issue is that bio_for_each_bvec() still advances by page size
> instead of bvec->len, I guess that is the problem, will cook a patch
> for your test.
Probably won't make a difference for my test case...
>> We need to do something about this, it's like tossing out months of
>> optimizations.
>
> Some following optimization can be done, such as removing
> biovec_phys_mergeable() from blk_bio_segment_split().
I think we really need a fast path for <= PAGE_SIZE IOs, to the extent
that it is possible. But iteration startup cost is a problem in a lot of
spots, and a split fast path will only help a bit for that specific
case.
5% regressions is HUGE. I know I've mentioned this before, I just want
to really stress how big of a deal that is. It's enough to make me
consider just reverting it again, which sucks, but I don't feel great
shipping something that is known that much slower.
Suggestions?
--
Jens Axboe
--
To unsubscribe, send a message with 'unsubscribe linux-aio' in
the body to majordomo@kvack.org. For more info on Linux AIO,
see: http://www.kvack.org/aio/
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>
^ permalink raw reply
* Re: [PATCH 11/19] block: implement bio helper to add iter bvec pages to bio
From: Ming Lei @ 2019-02-27 2:21 UTC (permalink / raw)
To: Jens Axboe
Cc: Ming Lei, Eric Biggers, open list:AIO, linux-block, linux-api,
Christoph Hellwig, Jeff Moyer, Avi Kivity, jannh, Al Viro
In-Reply-To: <e4dace7b-6a6f-2606-9a7e-8ae3c97c26b0@kernel.dk>
On Tue, Feb 26, 2019 at 06:57:16PM -0700, Jens Axboe wrote:
> On 2/26/19 6:53 PM, Ming Lei wrote:
> > On Tue, Feb 26, 2019 at 06:47:54PM -0700, Jens Axboe wrote:
> >> On 2/26/19 6:21 PM, Ming Lei wrote:
> >>> On Tue, Feb 26, 2019 at 11:56 PM Jens Axboe <axboe@kernel.dk> wrote:
> >>>>
> >>>> On 2/25/19 9:34 PM, Jens Axboe wrote:
> >>>>> On 2/25/19 8:46 PM, Eric Biggers wrote:
> >>>>>> Hi Jens,
> >>>>>>
> >>>>>> On Thu, Feb 21, 2019 at 10:45:27AM -0700, Jens Axboe wrote:
> >>>>>>> On 2/20/19 3:58 PM, Ming Lei wrote:
> >>>>>>>> On Mon, Feb 11, 2019 at 12:00:41PM -0700, Jens Axboe wrote:
> >>>>>>>>> For an ITER_BVEC, we can just iterate the iov and add the pages
> >>>>>>>>> to the bio directly. This requires that the caller doesn't releases
> >>>>>>>>> the pages on IO completion, we add a BIO_NO_PAGE_REF flag for that.
> >>>>>>>>>
> >>>>>>>>> The current two callers of bio_iov_iter_get_pages() are updated to
> >>>>>>>>> check if they need to release pages on completion. This makes them
> >>>>>>>>> work with bvecs that contain kernel mapped pages already.
> >>>>>>>>>
> >>>>>>>>> Reviewed-by: Hannes Reinecke <hare@suse.com>
> >>>>>>>>> Reviewed-by: Christoph Hellwig <hch@lst.de>
> >>>>>>>>> Signed-off-by: Jens Axboe <axboe@kernel.dk>
> >>>>>>>>> ---
> >>>>>>>>> block/bio.c | 59 ++++++++++++++++++++++++++++++++-------
> >>>>>>>>> fs/block_dev.c | 5 ++--
> >>>>>>>>> fs/iomap.c | 5 ++--
> >>>>>>>>> include/linux/blk_types.h | 1 +
> >>>>>>>>> 4 files changed, 56 insertions(+), 14 deletions(-)
> >>>>>>>>>
> >>>>>>>>> diff --git a/block/bio.c b/block/bio.c
> >>>>>>>>> index 4db1008309ed..330df572cfb8 100644
> >>>>>>>>> --- a/block/bio.c
> >>>>>>>>> +++ b/block/bio.c
> >>>>>>>>> @@ -828,6 +828,23 @@ int bio_add_page(struct bio *bio, struct page *page,
> >>>>>>>>> }
> >>>>>>>>> EXPORT_SYMBOL(bio_add_page);
> >>>>>>>>>
> >>>>>>>>> +static int __bio_iov_bvec_add_pages(struct bio *bio, struct iov_iter *iter)
> >>>>>>>>> +{
> >>>>>>>>> + const struct bio_vec *bv = iter->bvec;
> >>>>>>>>> + unsigned int len;
> >>>>>>>>> + size_t size;
> >>>>>>>>> +
> >>>>>>>>> + len = min_t(size_t, bv->bv_len, iter->count);
> >>>>>>>>> + size = bio_add_page(bio, bv->bv_page, len,
> >>>>>>>>> + bv->bv_offset + iter->iov_offset);
> >>>>>>>>
> >>>>>>>> iter->iov_offset needs to be subtracted from 'len', looks
> >>>>>>>> the following delta change[1] is required, otherwise memory corruption
> >>>>>>>> can be observed when running xfstests over loop/dio.
> >>>>>>>
> >>>>>>> Thanks, I folded this in.
> >>>>>>>
> >>>>>>> --
> >>>>>>> Jens Axboe
> >>>>>>>
> >>>>>>
> >>>>>> syzkaller started hitting a crash on linux-next starting with this commit, and
> >>>>>> it still occurs even with your latest version that has Ming's fix folded in.
> >>>>>> Specifically, commit a566653ab5ab80a from your io_uring branch with commit date
> >>>>>> Sun Feb 24 08:20:53 2019 -0700.
> >>>>>>
> >>>>>> Reproducer:
> >>>>>>
> >>>>>> #define _GNU_SOURCE
> >>>>>> #include <fcntl.h>
> >>>>>> #include <linux/loop.h>
> >>>>>> #include <sys/ioctl.h>
> >>>>>> #include <sys/sendfile.h>
> >>>>>> #include <sys/syscall.h>
> >>>>>> #include <unistd.h>
> >>>>>>
> >>>>>> int main(void)
> >>>>>> {
> >>>>>> int memfd, loopfd;
> >>>>>>
> >>>>>> memfd = syscall(__NR_memfd_create, "foo", 0);
> >>>>>>
> >>>>>> pwrite(memfd, "\xa8", 1, 4096);
> >>>>>>
> >>>>>> loopfd = open("/dev/loop0", O_RDWR|O_DIRECT);
> >>>>>>
> >>>>>> ioctl(loopfd, LOOP_SET_FD, memfd);
> >>>>>>
> >>>>>> sendfile(loopfd, loopfd, NULL, 1000000);
> >>>>>> }
> >>>>>>
> >>>>>>
> >>>>>> Crash:
> >>>>>>
> >>>>>> page:ffffea0001a6aab8 count:0 mapcount:0 mapping:0000000000000000 index:0x0
> >>>>>> flags: 0x100000000000000()
> >>>>>> raw: 0100000000000000 ffffea0001ad2c50 ffff88807fca49d0 0000000000000000
> >>>>>> raw: 0000000000000000 0000000000000000 00000000ffffffff
> >>>>>> page dumped because: VM_BUG_ON_PAGE(page_ref_count(page) == 0)
> >>>>>
> >>>>> I see what this is, I'll cut a fix for this tomorrow.
> >>>>
> >>>> Folded in a fix for this, it's in my current io_uring branch and my for-next
> >>>> branch.
> >>>
> >>> Hi Jens,
> >>>
> >>> I saw the following change is added:
> >>>
> >>> + if (size == len) {
> >>> + /*
> >>> + * For the normal O_DIRECT case, we could skip grabbing this
> >>> + * reference and then not have to put them again when IO
> >>> + * completes. But this breaks some in-kernel users, like
> >>> + * splicing to/from a loop device, where we release the pipe
> >>> + * pages unconditionally. If we can fix that case, we can
> >>> + * get rid of the get here and the need to call
> >>> + * bio_release_pages() at IO completion time.
> >>> + */
> >>> + get_page(bv->bv_page);
> >>>
> >>> Now the 'bv' may point to more than one page, so the following one may be
> >>> needed:
> >>>
> >>> int i;
> >>> struct bvec_iter_all iter_all;
> >>> struct bio_vec *tmp;
> >>>
> >>> mp_bvec_for_each_segment(tmp, bv, i, iter_all)
> >>> get_page(tmp->bv_page);
> >>
> >> I guess that would be the safest, even if we don't currently have more
> >> than one page in there. I'll fix it up.
> >
> > It is easy to see multipage bvec from loop, :-)
>
> Speaking of this, I took a quick look at why we've now regressed a lot
> on IOPS perf with the multipage work. It looks like it's all related to
> the (much) fatter setup around iteration, which is related to this very
> topic too.
>
> Basically setup of things like bio_for_each_bvec() and indexing through
> nth_page() is MUCH slower than before.
But bio_for_each_bvec() needn't nth_page(), and only bio_for_each_segment()
needs that. However, bio_for_each_segment() isn't called from
blk_queue_split() and blk_rq_map_sg().
One issue is that bio_for_each_bvec() still advances by page size
instead of bvec->len, I guess that is the problem, will cook a patch
for your test.
>
> We need to do something about this, it's like tossing out months of
> optimizations.
Some following optimization can be done, such as removing
biovec_phys_mergeable() from blk_bio_segment_split().
Thanks,
Ming
--
To unsubscribe, send a message with 'unsubscribe linux-aio' in
the body to majordomo@kvack.org. For more info on Linux AIO,
see: http://www.kvack.org/aio/
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>
^ permalink raw reply
* Re: [PATCH 11/19] block: implement bio helper to add iter bvec pages to bio
From: Jens Axboe @ 2019-02-27 2:03 UTC (permalink / raw)
To: Ming Lei
Cc: Ming Lei, Eric Biggers, open list:AIO, linux-block, linux-api,
Christoph Hellwig, Jeff Moyer, Avi Kivity, jannh, Al Viro
In-Reply-To: <e4dace7b-6a6f-2606-9a7e-8ae3c97c26b0@kernel.dk>
[-- Attachment #1: Type: text/plain, Size: 846 bytes --]
On 2/26/19 6:57 PM, Jens Axboe wrote:
> Speaking of this, I took a quick look at why we've now regressed a lot
> on IOPS perf with the multipage work. It looks like it's all related to
> the (much) fatter setup around iteration, which is related to this very
> topic too.
>
> Basically setup of things like bio_for_each_bvec() and indexing through
> nth_page() is MUCH slower than before.
>
> We need to do something about this, it's like tossing out months of
> optimizations.
See attached quick profile. This is doing 4k IOS, btw, so just single
segment requests. Yet we spend most of the time in blk_rq_map_sg(), and
blk_queue_split() is not far behind. Between just the two of them,
that's more than 8% of the total CPU utilization. As this test case is
running on just one CPU for all of it, that's a LOT of wasted time.
--
Jens Axboe
[-- Attachment #2: perf.jpg --]
[-- Type: image/jpeg, Size: 191091 bytes --]
^ permalink raw reply
* Re: [PATCH 11/19] block: implement bio helper to add iter bvec pages to bio
From: Jens Axboe @ 2019-02-27 1:57 UTC (permalink / raw)
To: Ming Lei
Cc: Ming Lei, Eric Biggers, open list:AIO, linux-block, linux-api,
Christoph Hellwig, Jeff Moyer, Avi Kivity, jannh, Al Viro
In-Reply-To: <20190227015336.GD16802@ming.t460p>
On 2/26/19 6:53 PM, Ming Lei wrote:
> On Tue, Feb 26, 2019 at 06:47:54PM -0700, Jens Axboe wrote:
>> On 2/26/19 6:21 PM, Ming Lei wrote:
>>> On Tue, Feb 26, 2019 at 11:56 PM Jens Axboe <axboe@kernel.dk> wrote:
>>>>
>>>> On 2/25/19 9:34 PM, Jens Axboe wrote:
>>>>> On 2/25/19 8:46 PM, Eric Biggers wrote:
>>>>>> Hi Jens,
>>>>>>
>>>>>> On Thu, Feb 21, 2019 at 10:45:27AM -0700, Jens Axboe wrote:
>>>>>>> On 2/20/19 3:58 PM, Ming Lei wrote:
>>>>>>>> On Mon, Feb 11, 2019 at 12:00:41PM -0700, Jens Axboe wrote:
>>>>>>>>> For an ITER_BVEC, we can just iterate the iov and add the pages
>>>>>>>>> to the bio directly. This requires that the caller doesn't releases
>>>>>>>>> the pages on IO completion, we add a BIO_NO_PAGE_REF flag for that.
>>>>>>>>>
>>>>>>>>> The current two callers of bio_iov_iter_get_pages() are updated to
>>>>>>>>> check if they need to release pages on completion. This makes them
>>>>>>>>> work with bvecs that contain kernel mapped pages already.
>>>>>>>>>
>>>>>>>>> Reviewed-by: Hannes Reinecke <hare@suse.com>
>>>>>>>>> Reviewed-by: Christoph Hellwig <hch@lst.de>
>>>>>>>>> Signed-off-by: Jens Axboe <axboe@kernel.dk>
>>>>>>>>> ---
>>>>>>>>> block/bio.c | 59 ++++++++++++++++++++++++++++++++-------
>>>>>>>>> fs/block_dev.c | 5 ++--
>>>>>>>>> fs/iomap.c | 5 ++--
>>>>>>>>> include/linux/blk_types.h | 1 +
>>>>>>>>> 4 files changed, 56 insertions(+), 14 deletions(-)
>>>>>>>>>
>>>>>>>>> diff --git a/block/bio.c b/block/bio.c
>>>>>>>>> index 4db1008309ed..330df572cfb8 100644
>>>>>>>>> --- a/block/bio.c
>>>>>>>>> +++ b/block/bio.c
>>>>>>>>> @@ -828,6 +828,23 @@ int bio_add_page(struct bio *bio, struct page *page,
>>>>>>>>> }
>>>>>>>>> EXPORT_SYMBOL(bio_add_page);
>>>>>>>>>
>>>>>>>>> +static int __bio_iov_bvec_add_pages(struct bio *bio, struct iov_iter *iter)
>>>>>>>>> +{
>>>>>>>>> + const struct bio_vec *bv = iter->bvec;
>>>>>>>>> + unsigned int len;
>>>>>>>>> + size_t size;
>>>>>>>>> +
>>>>>>>>> + len = min_t(size_t, bv->bv_len, iter->count);
>>>>>>>>> + size = bio_add_page(bio, bv->bv_page, len,
>>>>>>>>> + bv->bv_offset + iter->iov_offset);
>>>>>>>>
>>>>>>>> iter->iov_offset needs to be subtracted from 'len', looks
>>>>>>>> the following delta change[1] is required, otherwise memory corruption
>>>>>>>> can be observed when running xfstests over loop/dio.
>>>>>>>
>>>>>>> Thanks, I folded this in.
>>>>>>>
>>>>>>> --
>>>>>>> Jens Axboe
>>>>>>>
>>>>>>
>>>>>> syzkaller started hitting a crash on linux-next starting with this commit, and
>>>>>> it still occurs even with your latest version that has Ming's fix folded in.
>>>>>> Specifically, commit a566653ab5ab80a from your io_uring branch with commit date
>>>>>> Sun Feb 24 08:20:53 2019 -0700.
>>>>>>
>>>>>> Reproducer:
>>>>>>
>>>>>> #define _GNU_SOURCE
>>>>>> #include <fcntl.h>
>>>>>> #include <linux/loop.h>
>>>>>> #include <sys/ioctl.h>
>>>>>> #include <sys/sendfile.h>
>>>>>> #include <sys/syscall.h>
>>>>>> #include <unistd.h>
>>>>>>
>>>>>> int main(void)
>>>>>> {
>>>>>> int memfd, loopfd;
>>>>>>
>>>>>> memfd = syscall(__NR_memfd_create, "foo", 0);
>>>>>>
>>>>>> pwrite(memfd, "\xa8", 1, 4096);
>>>>>>
>>>>>> loopfd = open("/dev/loop0", O_RDWR|O_DIRECT);
>>>>>>
>>>>>> ioctl(loopfd, LOOP_SET_FD, memfd);
>>>>>>
>>>>>> sendfile(loopfd, loopfd, NULL, 1000000);
>>>>>> }
>>>>>>
>>>>>>
>>>>>> Crash:
>>>>>>
>>>>>> page:ffffea0001a6aab8 count:0 mapcount:0 mapping:0000000000000000 index:0x0
>>>>>> flags: 0x100000000000000()
>>>>>> raw: 0100000000000000 ffffea0001ad2c50 ffff88807fca49d0 0000000000000000
>>>>>> raw: 0000000000000000 0000000000000000 00000000ffffffff
>>>>>> page dumped because: VM_BUG_ON_PAGE(page_ref_count(page) == 0)
>>>>>
>>>>> I see what this is, I'll cut a fix for this tomorrow.
>>>>
>>>> Folded in a fix for this, it's in my current io_uring branch and my for-next
>>>> branch.
>>>
>>> Hi Jens,
>>>
>>> I saw the following change is added:
>>>
>>> + if (size == len) {
>>> + /*
>>> + * For the normal O_DIRECT case, we could skip grabbing this
>>> + * reference and then not have to put them again when IO
>>> + * completes. But this breaks some in-kernel users, like
>>> + * splicing to/from a loop device, where we release the pipe
>>> + * pages unconditionally. If we can fix that case, we can
>>> + * get rid of the get here and the need to call
>>> + * bio_release_pages() at IO completion time.
>>> + */
>>> + get_page(bv->bv_page);
>>>
>>> Now the 'bv' may point to more than one page, so the following one may be
>>> needed:
>>>
>>> int i;
>>> struct bvec_iter_all iter_all;
>>> struct bio_vec *tmp;
>>>
>>> mp_bvec_for_each_segment(tmp, bv, i, iter_all)
>>> get_page(tmp->bv_page);
>>
>> I guess that would be the safest, even if we don't currently have more
>> than one page in there. I'll fix it up.
>
> It is easy to see multipage bvec from loop, :-)
Speaking of this, I took a quick look at why we've now regressed a lot
on IOPS perf with the multipage work. It looks like it's all related to
the (much) fatter setup around iteration, which is related to this very
topic too.
Basically setup of things like bio_for_each_bvec() and indexing through
nth_page() is MUCH slower than before.
We need to do something about this, it's like tossing out months of
optimizations.
--
Jens Axboe
--
To unsubscribe, send a message with 'unsubscribe linux-aio' in
the body to majordomo@kvack.org. For more info on Linux AIO,
see: http://www.kvack.org/aio/
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>
^ permalink raw reply
* Re: [PATCH 11/19] block: implement bio helper to add iter bvec pages to bio
From: Ming Lei @ 2019-02-27 1:53 UTC (permalink / raw)
To: Jens Axboe
Cc: Ming Lei, Eric Biggers, open list:AIO, linux-block, linux-api,
Christoph Hellwig, Jeff Moyer, Avi Kivity, jannh, Al Viro
In-Reply-To: <09820845-07cb-5153-e1c5-59ed185db26f@kernel.dk>
On Tue, Feb 26, 2019 at 06:47:54PM -0700, Jens Axboe wrote:
> On 2/26/19 6:21 PM, Ming Lei wrote:
> > On Tue, Feb 26, 2019 at 11:56 PM Jens Axboe <axboe@kernel.dk> wrote:
> >>
> >> On 2/25/19 9:34 PM, Jens Axboe wrote:
> >>> On 2/25/19 8:46 PM, Eric Biggers wrote:
> >>>> Hi Jens,
> >>>>
> >>>> On Thu, Feb 21, 2019 at 10:45:27AM -0700, Jens Axboe wrote:
> >>>>> On 2/20/19 3:58 PM, Ming Lei wrote:
> >>>>>> On Mon, Feb 11, 2019 at 12:00:41PM -0700, Jens Axboe wrote:
> >>>>>>> For an ITER_BVEC, we can just iterate the iov and add the pages
> >>>>>>> to the bio directly. This requires that the caller doesn't releases
> >>>>>>> the pages on IO completion, we add a BIO_NO_PAGE_REF flag for that.
> >>>>>>>
> >>>>>>> The current two callers of bio_iov_iter_get_pages() are updated to
> >>>>>>> check if they need to release pages on completion. This makes them
> >>>>>>> work with bvecs that contain kernel mapped pages already.
> >>>>>>>
> >>>>>>> Reviewed-by: Hannes Reinecke <hare@suse.com>
> >>>>>>> Reviewed-by: Christoph Hellwig <hch@lst.de>
> >>>>>>> Signed-off-by: Jens Axboe <axboe@kernel.dk>
> >>>>>>> ---
> >>>>>>> block/bio.c | 59 ++++++++++++++++++++++++++++++++-------
> >>>>>>> fs/block_dev.c | 5 ++--
> >>>>>>> fs/iomap.c | 5 ++--
> >>>>>>> include/linux/blk_types.h | 1 +
> >>>>>>> 4 files changed, 56 insertions(+), 14 deletions(-)
> >>>>>>>
> >>>>>>> diff --git a/block/bio.c b/block/bio.c
> >>>>>>> index 4db1008309ed..330df572cfb8 100644
> >>>>>>> --- a/block/bio.c
> >>>>>>> +++ b/block/bio.c
> >>>>>>> @@ -828,6 +828,23 @@ int bio_add_page(struct bio *bio, struct page *page,
> >>>>>>> }
> >>>>>>> EXPORT_SYMBOL(bio_add_page);
> >>>>>>>
> >>>>>>> +static int __bio_iov_bvec_add_pages(struct bio *bio, struct iov_iter *iter)
> >>>>>>> +{
> >>>>>>> + const struct bio_vec *bv = iter->bvec;
> >>>>>>> + unsigned int len;
> >>>>>>> + size_t size;
> >>>>>>> +
> >>>>>>> + len = min_t(size_t, bv->bv_len, iter->count);
> >>>>>>> + size = bio_add_page(bio, bv->bv_page, len,
> >>>>>>> + bv->bv_offset + iter->iov_offset);
> >>>>>>
> >>>>>> iter->iov_offset needs to be subtracted from 'len', looks
> >>>>>> the following delta change[1] is required, otherwise memory corruption
> >>>>>> can be observed when running xfstests over loop/dio.
> >>>>>
> >>>>> Thanks, I folded this in.
> >>>>>
> >>>>> --
> >>>>> Jens Axboe
> >>>>>
> >>>>
> >>>> syzkaller started hitting a crash on linux-next starting with this commit, and
> >>>> it still occurs even with your latest version that has Ming's fix folded in.
> >>>> Specifically, commit a566653ab5ab80a from your io_uring branch with commit date
> >>>> Sun Feb 24 08:20:53 2019 -0700.
> >>>>
> >>>> Reproducer:
> >>>>
> >>>> #define _GNU_SOURCE
> >>>> #include <fcntl.h>
> >>>> #include <linux/loop.h>
> >>>> #include <sys/ioctl.h>
> >>>> #include <sys/sendfile.h>
> >>>> #include <sys/syscall.h>
> >>>> #include <unistd.h>
> >>>>
> >>>> int main(void)
> >>>> {
> >>>> int memfd, loopfd;
> >>>>
> >>>> memfd = syscall(__NR_memfd_create, "foo", 0);
> >>>>
> >>>> pwrite(memfd, "\xa8", 1, 4096);
> >>>>
> >>>> loopfd = open("/dev/loop0", O_RDWR|O_DIRECT);
> >>>>
> >>>> ioctl(loopfd, LOOP_SET_FD, memfd);
> >>>>
> >>>> sendfile(loopfd, loopfd, NULL, 1000000);
> >>>> }
> >>>>
> >>>>
> >>>> Crash:
> >>>>
> >>>> page:ffffea0001a6aab8 count:0 mapcount:0 mapping:0000000000000000 index:0x0
> >>>> flags: 0x100000000000000()
> >>>> raw: 0100000000000000 ffffea0001ad2c50 ffff88807fca49d0 0000000000000000
> >>>> raw: 0000000000000000 0000000000000000 00000000ffffffff
> >>>> page dumped because: VM_BUG_ON_PAGE(page_ref_count(page) == 0)
> >>>
> >>> I see what this is, I'll cut a fix for this tomorrow.
> >>
> >> Folded in a fix for this, it's in my current io_uring branch and my for-next
> >> branch.
> >
> > Hi Jens,
> >
> > I saw the following change is added:
> >
> > + if (size == len) {
> > + /*
> > + * For the normal O_DIRECT case, we could skip grabbing this
> > + * reference and then not have to put them again when IO
> > + * completes. But this breaks some in-kernel users, like
> > + * splicing to/from a loop device, where we release the pipe
> > + * pages unconditionally. If we can fix that case, we can
> > + * get rid of the get here and the need to call
> > + * bio_release_pages() at IO completion time.
> > + */
> > + get_page(bv->bv_page);
> >
> > Now the 'bv' may point to more than one page, so the following one may be
> > needed:
> >
> > int i;
> > struct bvec_iter_all iter_all;
> > struct bio_vec *tmp;
> >
> > mp_bvec_for_each_segment(tmp, bv, i, iter_all)
> > get_page(tmp->bv_page);
>
> I guess that would be the safest, even if we don't currently have more
> than one page in there. I'll fix it up.
It is easy to see multipage bvec from loop, :-)
Thanks,
Ming
--
To unsubscribe, send a message with 'unsubscribe linux-aio' in
the body to majordomo@kvack.org. For more info on Linux AIO,
see: http://www.kvack.org/aio/
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>
^ permalink raw reply
* Re: [PATCH 11/19] block: implement bio helper to add iter bvec pages to bio
From: Jens Axboe @ 2019-02-27 1:47 UTC (permalink / raw)
To: Ming Lei
Cc: Eric Biggers, Ming Lei, open list:AIO, linux-block, linux-api,
Christoph Hellwig, Jeff Moyer, Avi Kivity, jannh, Al Viro
In-Reply-To: <CACVXFVNOFA8_p+hVvaCffWAQ7+dgn++0b4Wn3naJzyNZN=CoFg@mail.gmail.com>
On 2/26/19 6:21 PM, Ming Lei wrote:
> On Tue, Feb 26, 2019 at 11:56 PM Jens Axboe <axboe@kernel.dk> wrote:
>>
>> On 2/25/19 9:34 PM, Jens Axboe wrote:
>>> On 2/25/19 8:46 PM, Eric Biggers wrote:
>>>> Hi Jens,
>>>>
>>>> On Thu, Feb 21, 2019 at 10:45:27AM -0700, Jens Axboe wrote:
>>>>> On 2/20/19 3:58 PM, Ming Lei wrote:
>>>>>> On Mon, Feb 11, 2019 at 12:00:41PM -0700, Jens Axboe wrote:
>>>>>>> For an ITER_BVEC, we can just iterate the iov and add the pages
>>>>>>> to the bio directly. This requires that the caller doesn't releases
>>>>>>> the pages on IO completion, we add a BIO_NO_PAGE_REF flag for that.
>>>>>>>
>>>>>>> The current two callers of bio_iov_iter_get_pages() are updated to
>>>>>>> check if they need to release pages on completion. This makes them
>>>>>>> work with bvecs that contain kernel mapped pages already.
>>>>>>>
>>>>>>> Reviewed-by: Hannes Reinecke <hare@suse.com>
>>>>>>> Reviewed-by: Christoph Hellwig <hch@lst.de>
>>>>>>> Signed-off-by: Jens Axboe <axboe@kernel.dk>
>>>>>>> ---
>>>>>>> block/bio.c | 59 ++++++++++++++++++++++++++++++++-------
>>>>>>> fs/block_dev.c | 5 ++--
>>>>>>> fs/iomap.c | 5 ++--
>>>>>>> include/linux/blk_types.h | 1 +
>>>>>>> 4 files changed, 56 insertions(+), 14 deletions(-)
>>>>>>>
>>>>>>> diff --git a/block/bio.c b/block/bio.c
>>>>>>> index 4db1008309ed..330df572cfb8 100644
>>>>>>> --- a/block/bio.c
>>>>>>> +++ b/block/bio.c
>>>>>>> @@ -828,6 +828,23 @@ int bio_add_page(struct bio *bio, struct page *page,
>>>>>>> }
>>>>>>> EXPORT_SYMBOL(bio_add_page);
>>>>>>>
>>>>>>> +static int __bio_iov_bvec_add_pages(struct bio *bio, struct iov_iter *iter)
>>>>>>> +{
>>>>>>> + const struct bio_vec *bv = iter->bvec;
>>>>>>> + unsigned int len;
>>>>>>> + size_t size;
>>>>>>> +
>>>>>>> + len = min_t(size_t, bv->bv_len, iter->count);
>>>>>>> + size = bio_add_page(bio, bv->bv_page, len,
>>>>>>> + bv->bv_offset + iter->iov_offset);
>>>>>>
>>>>>> iter->iov_offset needs to be subtracted from 'len', looks
>>>>>> the following delta change[1] is required, otherwise memory corruption
>>>>>> can be observed when running xfstests over loop/dio.
>>>>>
>>>>> Thanks, I folded this in.
>>>>>
>>>>> --
>>>>> Jens Axboe
>>>>>
>>>>
>>>> syzkaller started hitting a crash on linux-next starting with this commit, and
>>>> it still occurs even with your latest version that has Ming's fix folded in.
>>>> Specifically, commit a566653ab5ab80a from your io_uring branch with commit date
>>>> Sun Feb 24 08:20:53 2019 -0700.
>>>>
>>>> Reproducer:
>>>>
>>>> #define _GNU_SOURCE
>>>> #include <fcntl.h>
>>>> #include <linux/loop.h>
>>>> #include <sys/ioctl.h>
>>>> #include <sys/sendfile.h>
>>>> #include <sys/syscall.h>
>>>> #include <unistd.h>
>>>>
>>>> int main(void)
>>>> {
>>>> int memfd, loopfd;
>>>>
>>>> memfd = syscall(__NR_memfd_create, "foo", 0);
>>>>
>>>> pwrite(memfd, "\xa8", 1, 4096);
>>>>
>>>> loopfd = open("/dev/loop0", O_RDWR|O_DIRECT);
>>>>
>>>> ioctl(loopfd, LOOP_SET_FD, memfd);
>>>>
>>>> sendfile(loopfd, loopfd, NULL, 1000000);
>>>> }
>>>>
>>>>
>>>> Crash:
>>>>
>>>> page:ffffea0001a6aab8 count:0 mapcount:0 mapping:0000000000000000 index:0x0
>>>> flags: 0x100000000000000()
>>>> raw: 0100000000000000 ffffea0001ad2c50 ffff88807fca49d0 0000000000000000
>>>> raw: 0000000000000000 0000000000000000 00000000ffffffff
>>>> page dumped because: VM_BUG_ON_PAGE(page_ref_count(page) == 0)
>>>
>>> I see what this is, I'll cut a fix for this tomorrow.
>>
>> Folded in a fix for this, it's in my current io_uring branch and my for-next
>> branch.
>
> Hi Jens,
>
> I saw the following change is added:
>
> + if (size == len) {
> + /*
> + * For the normal O_DIRECT case, we could skip grabbing this
> + * reference and then not have to put them again when IO
> + * completes. But this breaks some in-kernel users, like
> + * splicing to/from a loop device, where we release the pipe
> + * pages unconditionally. If we can fix that case, we can
> + * get rid of the get here and the need to call
> + * bio_release_pages() at IO completion time.
> + */
> + get_page(bv->bv_page);
>
> Now the 'bv' may point to more than one page, so the following one may be
> needed:
>
> int i;
> struct bvec_iter_all iter_all;
> struct bio_vec *tmp;
>
> mp_bvec_for_each_segment(tmp, bv, i, iter_all)
> get_page(tmp->bv_page);
I guess that would be the safest, even if we don't currently have more
than one page in there. I'll fix it up.
--
Jens Axboe
--
To unsubscribe, send a message with 'unsubscribe linux-aio' in
the body to majordomo@kvack.org. For more info on Linux AIO,
see: http://www.kvack.org/aio/
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>
^ permalink raw reply
* Re: [PATCH 11/19] block: implement bio helper to add iter bvec pages to bio
From: Ming Lei @ 2019-02-27 1:21 UTC (permalink / raw)
To: Jens Axboe
Cc: Eric Biggers, Ming Lei, open list:AIO, linux-block, linux-api,
Christoph Hellwig, Jeff Moyer, Avi Kivity, jannh, Al Viro
In-Reply-To: <1652577e-787b-638e-625d-c200fb144a9d@kernel.dk>
On Tue, Feb 26, 2019 at 11:56 PM Jens Axboe <axboe@kernel.dk> wrote:
>
> On 2/25/19 9:34 PM, Jens Axboe wrote:
> > On 2/25/19 8:46 PM, Eric Biggers wrote:
> >> Hi Jens,
> >>
> >> On Thu, Feb 21, 2019 at 10:45:27AM -0700, Jens Axboe wrote:
> >>> On 2/20/19 3:58 PM, Ming Lei wrote:
> >>>> On Mon, Feb 11, 2019 at 12:00:41PM -0700, Jens Axboe wrote:
> >>>>> For an ITER_BVEC, we can just iterate the iov and add the pages
> >>>>> to the bio directly. This requires that the caller doesn't releases
> >>>>> the pages on IO completion, we add a BIO_NO_PAGE_REF flag for that.
> >>>>>
> >>>>> The current two callers of bio_iov_iter_get_pages() are updated to
> >>>>> check if they need to release pages on completion. This makes them
> >>>>> work with bvecs that contain kernel mapped pages already.
> >>>>>
> >>>>> Reviewed-by: Hannes Reinecke <hare@suse.com>
> >>>>> Reviewed-by: Christoph Hellwig <hch@lst.de>
> >>>>> Signed-off-by: Jens Axboe <axboe@kernel.dk>
> >>>>> ---
> >>>>> block/bio.c | 59 ++++++++++++++++++++++++++++++++-------
> >>>>> fs/block_dev.c | 5 ++--
> >>>>> fs/iomap.c | 5 ++--
> >>>>> include/linux/blk_types.h | 1 +
> >>>>> 4 files changed, 56 insertions(+), 14 deletions(-)
> >>>>>
> >>>>> diff --git a/block/bio.c b/block/bio.c
> >>>>> index 4db1008309ed..330df572cfb8 100644
> >>>>> --- a/block/bio.c
> >>>>> +++ b/block/bio.c
> >>>>> @@ -828,6 +828,23 @@ int bio_add_page(struct bio *bio, struct page *page,
> >>>>> }
> >>>>> EXPORT_SYMBOL(bio_add_page);
> >>>>>
> >>>>> +static int __bio_iov_bvec_add_pages(struct bio *bio, struct iov_iter *iter)
> >>>>> +{
> >>>>> + const struct bio_vec *bv = iter->bvec;
> >>>>> + unsigned int len;
> >>>>> + size_t size;
> >>>>> +
> >>>>> + len = min_t(size_t, bv->bv_len, iter->count);
> >>>>> + size = bio_add_page(bio, bv->bv_page, len,
> >>>>> + bv->bv_offset + iter->iov_offset);
> >>>>
> >>>> iter->iov_offset needs to be subtracted from 'len', looks
> >>>> the following delta change[1] is required, otherwise memory corruption
> >>>> can be observed when running xfstests over loop/dio.
> >>>
> >>> Thanks, I folded this in.
> >>>
> >>> --
> >>> Jens Axboe
> >>>
> >>
> >> syzkaller started hitting a crash on linux-next starting with this commit, and
> >> it still occurs even with your latest version that has Ming's fix folded in.
> >> Specifically, commit a566653ab5ab80a from your io_uring branch with commit date
> >> Sun Feb 24 08:20:53 2019 -0700.
> >>
> >> Reproducer:
> >>
> >> #define _GNU_SOURCE
> >> #include <fcntl.h>
> >> #include <linux/loop.h>
> >> #include <sys/ioctl.h>
> >> #include <sys/sendfile.h>
> >> #include <sys/syscall.h>
> >> #include <unistd.h>
> >>
> >> int main(void)
> >> {
> >> int memfd, loopfd;
> >>
> >> memfd = syscall(__NR_memfd_create, "foo", 0);
> >>
> >> pwrite(memfd, "\xa8", 1, 4096);
> >>
> >> loopfd = open("/dev/loop0", O_RDWR|O_DIRECT);
> >>
> >> ioctl(loopfd, LOOP_SET_FD, memfd);
> >>
> >> sendfile(loopfd, loopfd, NULL, 1000000);
> >> }
> >>
> >>
> >> Crash:
> >>
> >> page:ffffea0001a6aab8 count:0 mapcount:0 mapping:0000000000000000 index:0x0
> >> flags: 0x100000000000000()
> >> raw: 0100000000000000 ffffea0001ad2c50 ffff88807fca49d0 0000000000000000
> >> raw: 0000000000000000 0000000000000000 00000000ffffffff
> >> page dumped because: VM_BUG_ON_PAGE(page_ref_count(page) == 0)
> >
> > I see what this is, I'll cut a fix for this tomorrow.
>
> Folded in a fix for this, it's in my current io_uring branch and my for-next
> branch.
Hi Jens,
I saw the following change is added:
+ if (size == len) {
+ /*
+ * For the normal O_DIRECT case, we could skip grabbing this
+ * reference and then not have to put them again when IO
+ * completes. But this breaks some in-kernel users, like
+ * splicing to/from a loop device, where we release the pipe
+ * pages unconditionally. If we can fix that case, we can
+ * get rid of the get here and the need to call
+ * bio_release_pages() at IO completion time.
+ */
+ get_page(bv->bv_page);
Now the 'bv' may point to more than one page, so the following one may be
needed:
int i;
struct bvec_iter_all iter_all;
struct bio_vec *tmp;
mp_bvec_for_each_segment(tmp, bv, i, iter_all)
get_page(tmp->bv_page);
Thanks,
Ming Lei
--
To unsubscribe, send a message with 'unsubscribe linux-aio' in
the body to majordomo@kvack.org. For more info on Linux AIO,
see: http://www.kvack.org/aio/
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>
^ permalink raw reply
* Re: [PATCH] mm,mremap: Bail out earlier in mremap_to under map pressure
From: Andrew Morton @ 2019-02-26 22:04 UTC (permalink / raw)
To: Oscar Salvador
Cc: linux-mm, linux-kernel, linux-api, hughd, kirill, vbabka, joel,
jglisse, yang.shi, mgorman
In-Reply-To: <20190226091314.18446-1-osalvador@suse.de>
On Tue, 26 Feb 2019 10:13:14 +0100 Oscar Salvador <osalvador@suse.de> wrote:
> When using mremap() syscall in addition to MREMAP_FIXED flag,
> mremap() calls mremap_to() which does the following:
>
> 1) unmaps the destination region where we are going to move the map
> 2) If the new region is going to be smaller, we unmap the last part
> of the old region
>
> Then, we will eventually call move_vma() to do the actual move.
>
> move_vma() checks whether we are at least 4 maps below max_map_count
> before going further, otherwise it bails out with -ENOMEM.
> The problem is that we might have already unmapped the vma's in steps
> 1) and 2), so it is not possible for userspace to figure out the state
> of the vma's after it gets -ENOMEM, and it gets tricky for userspace
> to clean up properly on error path.
>
> While it is true that we can return -ENOMEM for more reasons
> (e.g: see may_expand_vm() or move_page_tables()), I think that we can
> avoid this scenario in concret if we check early in mremap_to() if the
> operation has high chances to succeed map-wise.
>
> Should not be that the case, we can bail out before we even try to unmap
> anything, so we make sure the vma's are left untouched in case we are likely
> to be short of maps.
>
> The thumb-rule now is to rely on the worst-scenario case we can have.
> That is when both vma's (old region and new region) are going to be split
> in 3, so we get two more maps to the ones we already hold (one per each).
> If current map count + 2 maps still leads us to 4 maps below the threshold,
> we are going to pass the check in move_vma().
>
> Of course, this is not free, as it might generate false positives when it is
> true that we are tight map-wise, but the unmap operation can release several
> vma's leading us to a good state.
>
> Another approach was also investigated [1], but it may be too much hassle
> for what it brings.
>
How is this going to affect existing userspace which is aware of the
current behaviour?
And how does it affect your existing cleanup code, come to that? Does
it work as well or better after this change?
^ permalink raw reply
* Re: [PATCH 11/19] block: implement bio helper to add iter bvec pages to bio
From: Jens Axboe @ 2019-02-26 15:54 UTC (permalink / raw)
To: Eric Biggers
Cc: Ming Lei, linux-aio, linux-block, linux-api, hch, jmoyer, avi,
jannh, viro
In-Reply-To: <aa1184bb-b482-0637-21e4-1ddb0e7aea90@kernel.dk>
On 2/25/19 9:34 PM, Jens Axboe wrote:
> On 2/25/19 8:46 PM, Eric Biggers wrote:
>> Hi Jens,
>>
>> On Thu, Feb 21, 2019 at 10:45:27AM -0700, Jens Axboe wrote:
>>> On 2/20/19 3:58 PM, Ming Lei wrote:
>>>> On Mon, Feb 11, 2019 at 12:00:41PM -0700, Jens Axboe wrote:
>>>>> For an ITER_BVEC, we can just iterate the iov and add the pages
>>>>> to the bio directly. This requires that the caller doesn't releases
>>>>> the pages on IO completion, we add a BIO_NO_PAGE_REF flag for that.
>>>>>
>>>>> The current two callers of bio_iov_iter_get_pages() are updated to
>>>>> check if they need to release pages on completion. This makes them
>>>>> work with bvecs that contain kernel mapped pages already.
>>>>>
>>>>> Reviewed-by: Hannes Reinecke <hare@suse.com>
>>>>> Reviewed-by: Christoph Hellwig <hch@lst.de>
>>>>> Signed-off-by: Jens Axboe <axboe@kernel.dk>
>>>>> ---
>>>>> block/bio.c | 59 ++++++++++++++++++++++++++++++++-------
>>>>> fs/block_dev.c | 5 ++--
>>>>> fs/iomap.c | 5 ++--
>>>>> include/linux/blk_types.h | 1 +
>>>>> 4 files changed, 56 insertions(+), 14 deletions(-)
>>>>>
>>>>> diff --git a/block/bio.c b/block/bio.c
>>>>> index 4db1008309ed..330df572cfb8 100644
>>>>> --- a/block/bio.c
>>>>> +++ b/block/bio.c
>>>>> @@ -828,6 +828,23 @@ int bio_add_page(struct bio *bio, struct page *page,
>>>>> }
>>>>> EXPORT_SYMBOL(bio_add_page);
>>>>>
>>>>> +static int __bio_iov_bvec_add_pages(struct bio *bio, struct iov_iter *iter)
>>>>> +{
>>>>> + const struct bio_vec *bv = iter->bvec;
>>>>> + unsigned int len;
>>>>> + size_t size;
>>>>> +
>>>>> + len = min_t(size_t, bv->bv_len, iter->count);
>>>>> + size = bio_add_page(bio, bv->bv_page, len,
>>>>> + bv->bv_offset + iter->iov_offset);
>>>>
>>>> iter->iov_offset needs to be subtracted from 'len', looks
>>>> the following delta change[1] is required, otherwise memory corruption
>>>> can be observed when running xfstests over loop/dio.
>>>
>>> Thanks, I folded this in.
>>>
>>> --
>>> Jens Axboe
>>>
>>
>> syzkaller started hitting a crash on linux-next starting with this commit, and
>> it still occurs even with your latest version that has Ming's fix folded in.
>> Specifically, commit a566653ab5ab80a from your io_uring branch with commit date
>> Sun Feb 24 08:20:53 2019 -0700.
>>
>> Reproducer:
>>
>> #define _GNU_SOURCE
>> #include <fcntl.h>
>> #include <linux/loop.h>
>> #include <sys/ioctl.h>
>> #include <sys/sendfile.h>
>> #include <sys/syscall.h>
>> #include <unistd.h>
>>
>> int main(void)
>> {
>> int memfd, loopfd;
>>
>> memfd = syscall(__NR_memfd_create, "foo", 0);
>>
>> pwrite(memfd, "\xa8", 1, 4096);
>>
>> loopfd = open("/dev/loop0", O_RDWR|O_DIRECT);
>>
>> ioctl(loopfd, LOOP_SET_FD, memfd);
>>
>> sendfile(loopfd, loopfd, NULL, 1000000);
>> }
>>
>>
>> Crash:
>>
>> page:ffffea0001a6aab8 count:0 mapcount:0 mapping:0000000000000000 index:0x0
>> flags: 0x100000000000000()
>> raw: 0100000000000000 ffffea0001ad2c50 ffff88807fca49d0 0000000000000000
>> raw: 0000000000000000 0000000000000000 00000000ffffffff
>> page dumped because: VM_BUG_ON_PAGE(page_ref_count(page) == 0)
>
> I see what this is, I'll cut a fix for this tomorrow.
Folded in a fix for this, it's in my current io_uring branch and my for-next
branch.
--
Jens Axboe
--
To unsubscribe, send a message with 'unsubscribe linux-aio' in
the body to majordomo@kvack.org. For more info on Linux AIO,
see: http://www.kvack.org/aio/
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>
^ permalink raw reply
* [PATCH] mm,mremap: Bail out earlier in mremap_to under map pressure
From: Oscar Salvador @ 2019-02-26 9:13 UTC (permalink / raw)
To: akpm
Cc: linux-mm, linux-kernel, linux-api, hughd, kirill, vbabka, joel,
jglisse, yang.shi, mgorman, Oscar Salvador
When using mremap() syscall in addition to MREMAP_FIXED flag,
mremap() calls mremap_to() which does the following:
1) unmaps the destination region where we are going to move the map
2) If the new region is going to be smaller, we unmap the last part
of the old region
Then, we will eventually call move_vma() to do the actual move.
move_vma() checks whether we are at least 4 maps below max_map_count
before going further, otherwise it bails out with -ENOMEM.
The problem is that we might have already unmapped the vma's in steps
1) and 2), so it is not possible for userspace to figure out the state
of the vma's after it gets -ENOMEM, and it gets tricky for userspace
to clean up properly on error path.
While it is true that we can return -ENOMEM for more reasons
(e.g: see may_expand_vm() or move_page_tables()), I think that we can
avoid this scenario in concret if we check early in mremap_to() if the
operation has high chances to succeed map-wise.
Should not be that the case, we can bail out before we even try to unmap
anything, so we make sure the vma's are left untouched in case we are likely
to be short of maps.
The thumb-rule now is to rely on the worst-scenario case we can have.
That is when both vma's (old region and new region) are going to be split
in 3, so we get two more maps to the ones we already hold (one per each).
If current map count + 2 maps still leads us to 4 maps below the threshold,
we are going to pass the check in move_vma().
Of course, this is not free, as it might generate false positives when it is
true that we are tight map-wise, but the unmap operation can release several
vma's leading us to a good state.
Another approach was also investigated [1], but it may be too much hassle
for what it brings.
[1] https://lore.kernel.org/lkml/20190219155320.tkfkwvqk53tfdojt@d104.suse.de/
Signed-off-by: Oscar Salvador <osalvador@suse.de>
Acked-by: Vlastimil Babka <vbabka@suse.cz>
Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
---
mm/mremap.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/mm/mremap.c b/mm/mremap.c
index 3320616ed93f..e3edef6b7a12 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -516,6 +516,23 @@ static unsigned long mremap_to(unsigned long addr, unsigned long old_len,
if (addr + old_len > new_addr && new_addr + new_len > addr)
goto out;
+ /*
+ * move_vma() need us to stay 4 maps below the threshold, otherwise
+ * it will bail out at the very beginning.
+ * That is a problem if we have already unmaped the regions here
+ * (new_addr, and old_addr), because userspace will not know the
+ * state of the vma's after it gets -ENOMEM.
+ * So, to avoid such scenario we can pre-compute if the whole
+ * operation has high chances to success map-wise.
+ * Worst-scenario case is when both vma's (new_addr and old_addr) get
+ * split in 3 before unmaping it.
+ * That means 2 more maps (1 for each) to the ones we already hold.
+ * Check whether current map count plus 2 still leads us to 4 maps below
+ * the threshold, otherwise return -ENOMEM here to be more safe.
+ */
+ if ((mm->map_count + 2) >= sysctl_max_map_count - 3)
+ return -ENOMEM;
+
ret = do_munmap(mm, new_addr, new_len, uf_unmap_early);
if (ret)
goto out;
--
2.13.7
^ permalink raw reply related
* Re: [PATCH 1/3] bpf: add helper to check for a valid SYN cookie
From: Martin Lau @ 2019-02-26 5:37 UTC (permalink / raw)
To: Lorenz Bauer
Cc: ast@kernel.org, daniel@iogearbox.net, netdev@vger.kernel.org,
linux-api@vger.kernel.org
In-Reply-To: <CACAyw9_smq+c8rUt3ONk+J28CzPefuEOgs8at3q9_5s3zN0_1w@mail.gmail.com>
On Mon, Feb 25, 2019 at 06:26:42PM +0000, Lorenz Bauer wrote:
> On Sat, 23 Feb 2019 at 00:44, Martin Lau <kafai@fb.com> wrote:
> >
> > On Fri, Feb 22, 2019 at 09:50:55AM +0000, Lorenz Bauer wrote:
> > > Using bpf_sk_lookup_tcp it's possible to ascertain whether a packet belongs
> > > to a known connection. However, there is one corner case: no sockets are
> > > created if SYN cookies are active. This means that the final ACK in the
> > > 3WHS is misclassified.
> > >
> > > Using the helper, we can look up the listening socket via bpf_sk_lookup_tcp
> > > and then check whether a packet is a valid SYN cookie ACK.
> > >
> > > Signed-off-by: Lorenz Bauer <lmb@cloudflare.com>
> > > ---
> > > include/uapi/linux/bpf.h | 18 ++++++++++-
> > > net/core/filter.c | 68 ++++++++++++++++++++++++++++++++++++++++
> > > 2 files changed, 85 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > > index bcdd2474eee7..bc2af87e9621 100644
> > > --- a/include/uapi/linux/bpf.h
> > > +++ b/include/uapi/linux/bpf.h
> > > @@ -2359,6 +2359,21 @@ union bpf_attr {
> > > * Return
> > > * A **struct bpf_tcp_sock** pointer on success, or NULL in
> > > * case of failure.
> > > + *
> > > + * int bpf_sk_check_syncookie(struct bpf_sock *sk, void *iph, u32 iph_len, struct tcphdr *th, u32 th_len)
> > > + * Description
> > > + * Check whether iph and th contain a valid SYN cookie ACK for
> > > + * the listening socket in sk.
> > > + *
> > > + * iph points to the start of the IPv4 or IPv6 header, while
> > > + * iph_len contains sizeof(struct iphdr) or sizeof(struct ip6hdr).
> > > + *
> > > + * th points to the start of the TCP header, while th_len contains
> > > + * sizeof(struct tcphdr).
> > > + *
> > > + * Return
> > > + * 0 if iph and th are a valid SYN cookie ACK, or a negative error
> > > + * otherwise.
> > > */
> > > #define __BPF_FUNC_MAPPER(FN) \
> > > FN(unspec), \
> > > @@ -2457,7 +2472,8 @@ union bpf_attr {
> > > FN(spin_lock), \
> > > FN(spin_unlock), \
> > > FN(sk_fullsock), \
> > > - FN(tcp_sock),
> > > + FN(tcp_sock), \
> > > + FN(sk_check_syncookie),
> > >
> > > /* integer value in 'imm' field of BPF_CALL instruction selects which helper
> > > * function eBPF program intends to call
> > > diff --git a/net/core/filter.c b/net/core/filter.c
> > > index 85749f6ec789..9e68897cc7ed 100644
> > > --- a/net/core/filter.c
> > > +++ b/net/core/filter.c
> > > @@ -5426,6 +5426,70 @@ static const struct bpf_func_proto bpf_tcp_sock_proto = {
> > > .arg1_type = ARG_PTR_TO_SOCK_COMMON,
> > > };
> > >
> > > +BPF_CALL_5(bpf_sk_check_syncookie, struct sock *, sk, void *, iph, u32, iph_len,
> > s/bpf_sk_check_syncookie/bpf_tcp_check_syncookie/>
> >
> > > + struct tcphdr *, th, u32, th_len)
> > > +{
> > > +#if IS_ENABLED(CONFIG_SYN_COOKIES)
> > nit. "#ifdef CONFIG_SYN_COOKIES" such that it is clear it is a bool kconfig.
> >
> > > + u32 cookie;
> > > + int ret;
> > > +
> > > + if (unlikely(th_len < sizeof(*th)))
> > > + return -EINVAL;
> > > +
> > > + /* sk_listener() allows TCP_NEW_SYN_RECV, which makes no sense here. */
> > > + if (sk->sk_protocol != IPPROTO_TCP || sk->sk_state != TCP_LISTEN)
> > From the test program in patch 3, the "sk" here is obtained from
> > bpf_sk_lookup_tcp() which does a sk_to_full_sk() before returning.
> > AFAICT, meaning bpf_sk_lookup_tcp() will return the listening sk
> > even if there is a request_sock. Does it make sense to check
> > syncookie if there is already a request_sock?
>
> No, that doesn't make a lot of sense. I hadn't realised that
> sk_lookup_tcp only returns full sockets.
> This means we need a way to detect that there is a request sock for a
> given tuple.
>
> * adding a reqsk_exists(tuple) helper means we have to pay the lookup cost twice
> * drop the sk argument and do the necessary lookups in the helper
> itself, but that also
> wastes a call to __inet_lookup_listener
> * skip sk_to_full_sk() in a helper and return RET_PTR_TO_SOCK_COMMON,
> but that violates a bunch of assumptions (e.g. calling bpf_sk_release on them)
How about creating a new lookup helper, bpf_sk"c"_lookup_tcp,
that does not call sk_to_full_sk() before returning.
Its ".ret_type" will be RET_PTR_TO_SOCK_COMMON_OR_NULL which its
reference(-counting) state has to be tracked in the verifier also.
Mainly in check_helper_call(), iirc.
The bpf_prog can then check bpf_sock->state for TCP_LISTEN,
call bpf_tcp_sock() to get the TCP listener sock and pass to
the bpf_tcp_check_syncookie()
>
> For context: ultimately we want use this to answer the question: does
> this (encapsulated)
> packet contain a payload destined to a local socket? Amongst the edge
> cases we need to
> handle are ICMP Packet Too Big messages and SYN cookies. A solution
> would be to hide
> all this in an "uber" helper that takes pointers to the L3 / L4
> headers and returns a verdict,
> but that seems a bit gross.
Please include this use case in the commit message.
It is useful.
>
> >
> > > + return -EINVAL;
> > > +
> > > + if (!sock_net(sk)->ipv4.sysctl_tcp_syncookies)
> > Should tcp_synq_no_recent_overflow(tp) be checked also?
> >
>
> Yes, not sure how that slipped out.
>
> > > + return -EINVAL;
> > > +
> > > + if (!th->ack || th->rst)
> > How about th->syn?
> >
>
> Yes, I missed the fact that the callers in tcp_ipv{4,6}.c check this.
>
> > > + return -ENOENT;
> > > +
> > > + cookie = ntohl(th->ack_seq) - 1;
> > > +
> > > + switch (sk->sk_family) {
> > > + case AF_INET:
> > > + if (unlikely(iph_len < sizeof(struct iphdr)))
> > > + return -EINVAL;
> > > +
> > > + ret = __cookie_v4_check((struct iphdr *)iph, th, cookie);
> > > + break;
> > > +
> > > +#if IS_ENABLED(CONFIG_IPV6)
> > > + case AF_INET6:
> > > + if (unlikely(iph_len < sizeof(struct ipv6hdr)))
> > > + return -EINVAL;
> > > +
> > > + ret = __cookie_v6_check((struct ipv6hdr *)iph, th, cookie);
> > > + break;
> > > +#endif /* CONFIG_IPV6 */
> > > +
> > > + default:
> > > + return -EPROTONOSUPPORT;
> > > + }
> > > +
> > > + if (ret > 0)
> > > + return 0;
> > > +
> > > + return -ENOENT;
> > > +#else
> > > + return -ENOTSUP;
> > > +#endif
> > > +}
> > > +
> > > +static const struct bpf_func_proto bpf_sk_check_syncookie_proto = {
> > > + .func = bpf_sk_check_syncookie,
> > > + .gpl_only = true,
> > > + .pkt_access = true,
> > > + .ret_type = RET_INTEGER,
> > > + .arg1_type = ARG_PTR_TO_SOCKET,
> > I think it should be ARG_PTR_TO_TCP_SOCK
> >
> > > + .arg2_type = ARG_PTR_TO_MEM,
> > > + .arg3_type = ARG_CONST_SIZE,
> > > + .arg4_type = ARG_PTR_TO_MEM,
> > > + .arg5_type = ARG_CONST_SIZE,
> > > +};
> > > +
> > > #endif /* CONFIG_INET */
>
>
>
> --
> Lorenz Bauer | Systems Engineer
> 25 Lavington St., London SE1 0NZ
>
> https://urldefense.proofpoint.com/v2/url?u=http-3A__www.cloudflare.com&d=DwIBaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=VQnoQ7LvghIj0gVEaiQSUw&m=xhDwvX3iD-mbqSrx-L8XQNaZiYFZzMWNo_2Y38Z9j34&s=I4Ag3HflabFppFv7UtMp8WnMVSqCDW0W28ziWIvuwDE&e=
^ permalink raw reply
* Re: [PATCH 11/19] block: implement bio helper to add iter bvec pages to bio
From: Jens Axboe @ 2019-02-26 4:34 UTC (permalink / raw)
To: Eric Biggers
Cc: Ming Lei, linux-aio, linux-block, linux-api, hch, jmoyer, avi,
jannh, viro
In-Reply-To: <20190226034613.GA676@sol.localdomain>
On 2/25/19 8:46 PM, Eric Biggers wrote:
> Hi Jens,
>
> On Thu, Feb 21, 2019 at 10:45:27AM -0700, Jens Axboe wrote:
>> On 2/20/19 3:58 PM, Ming Lei wrote:
>>> On Mon, Feb 11, 2019 at 12:00:41PM -0700, Jens Axboe wrote:
>>>> For an ITER_BVEC, we can just iterate the iov and add the pages
>>>> to the bio directly. This requires that the caller doesn't releases
>>>> the pages on IO completion, we add a BIO_NO_PAGE_REF flag for that.
>>>>
>>>> The current two callers of bio_iov_iter_get_pages() are updated to
>>>> check if they need to release pages on completion. This makes them
>>>> work with bvecs that contain kernel mapped pages already.
>>>>
>>>> Reviewed-by: Hannes Reinecke <hare@suse.com>
>>>> Reviewed-by: Christoph Hellwig <hch@lst.de>
>>>> Signed-off-by: Jens Axboe <axboe@kernel.dk>
>>>> ---
>>>> block/bio.c | 59 ++++++++++++++++++++++++++++++++-------
>>>> fs/block_dev.c | 5 ++--
>>>> fs/iomap.c | 5 ++--
>>>> include/linux/blk_types.h | 1 +
>>>> 4 files changed, 56 insertions(+), 14 deletions(-)
>>>>
>>>> diff --git a/block/bio.c b/block/bio.c
>>>> index 4db1008309ed..330df572cfb8 100644
>>>> --- a/block/bio.c
>>>> +++ b/block/bio.c
>>>> @@ -828,6 +828,23 @@ int bio_add_page(struct bio *bio, struct page *page,
>>>> }
>>>> EXPORT_SYMBOL(bio_add_page);
>>>>
>>>> +static int __bio_iov_bvec_add_pages(struct bio *bio, struct iov_iter *iter)
>>>> +{
>>>> + const struct bio_vec *bv = iter->bvec;
>>>> + unsigned int len;
>>>> + size_t size;
>>>> +
>>>> + len = min_t(size_t, bv->bv_len, iter->count);
>>>> + size = bio_add_page(bio, bv->bv_page, len,
>>>> + bv->bv_offset + iter->iov_offset);
>>>
>>> iter->iov_offset needs to be subtracted from 'len', looks
>>> the following delta change[1] is required, otherwise memory corruption
>>> can be observed when running xfstests over loop/dio.
>>
>> Thanks, I folded this in.
>>
>> --
>> Jens Axboe
>>
>
> syzkaller started hitting a crash on linux-next starting with this commit, and
> it still occurs even with your latest version that has Ming's fix folded in.
> Specifically, commit a566653ab5ab80a from your io_uring branch with commit date
> Sun Feb 24 08:20:53 2019 -0700.
>
> Reproducer:
>
> #define _GNU_SOURCE
> #include <fcntl.h>
> #include <linux/loop.h>
> #include <sys/ioctl.h>
> #include <sys/sendfile.h>
> #include <sys/syscall.h>
> #include <unistd.h>
>
> int main(void)
> {
> int memfd, loopfd;
>
> memfd = syscall(__NR_memfd_create, "foo", 0);
>
> pwrite(memfd, "\xa8", 1, 4096);
>
> loopfd = open("/dev/loop0", O_RDWR|O_DIRECT);
>
> ioctl(loopfd, LOOP_SET_FD, memfd);
>
> sendfile(loopfd, loopfd, NULL, 1000000);
> }
>
>
> Crash:
>
> page:ffffea0001a6aab8 count:0 mapcount:0 mapping:0000000000000000 index:0x0
> flags: 0x100000000000000()
> raw: 0100000000000000 ffffea0001ad2c50 ffff88807fca49d0 0000000000000000
> raw: 0000000000000000 0000000000000000 00000000ffffffff
> page dumped because: VM_BUG_ON_PAGE(page_ref_count(page) == 0)
I see what this is, I'll cut a fix for this tomorrow.
--
Jens Axboe
--
To unsubscribe, send a message with 'unsubscribe linux-aio' in
the body to majordomo@kvack.org. For more info on Linux AIO,
see: http://www.kvack.org/aio/
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>
^ permalink raw reply
* Re: [PATCH 11/19] block: implement bio helper to add iter bvec pages to bio
From: Eric Biggers @ 2019-02-26 3:46 UTC (permalink / raw)
To: Jens Axboe
Cc: Ming Lei, linux-aio, linux-block, linux-api, hch, jmoyer, avi,
jannh, viro
In-Reply-To: <b143e8c3-33d5-5f09-c441-98b3bf326d81@kernel.dk>
Hi Jens,
On Thu, Feb 21, 2019 at 10:45:27AM -0700, Jens Axboe wrote:
> On 2/20/19 3:58 PM, Ming Lei wrote:
> > On Mon, Feb 11, 2019 at 12:00:41PM -0700, Jens Axboe wrote:
> >> For an ITER_BVEC, we can just iterate the iov and add the pages
> >> to the bio directly. This requires that the caller doesn't releases
> >> the pages on IO completion, we add a BIO_NO_PAGE_REF flag for that.
> >>
> >> The current two callers of bio_iov_iter_get_pages() are updated to
> >> check if they need to release pages on completion. This makes them
> >> work with bvecs that contain kernel mapped pages already.
> >>
> >> Reviewed-by: Hannes Reinecke <hare@suse.com>
> >> Reviewed-by: Christoph Hellwig <hch@lst.de>
> >> Signed-off-by: Jens Axboe <axboe@kernel.dk>
> >> ---
> >> block/bio.c | 59 ++++++++++++++++++++++++++++++++-------
> >> fs/block_dev.c | 5 ++--
> >> fs/iomap.c | 5 ++--
> >> include/linux/blk_types.h | 1 +
> >> 4 files changed, 56 insertions(+), 14 deletions(-)
> >>
> >> diff --git a/block/bio.c b/block/bio.c
> >> index 4db1008309ed..330df572cfb8 100644
> >> --- a/block/bio.c
> >> +++ b/block/bio.c
> >> @@ -828,6 +828,23 @@ int bio_add_page(struct bio *bio, struct page *page,
> >> }
> >> EXPORT_SYMBOL(bio_add_page);
> >>
> >> +static int __bio_iov_bvec_add_pages(struct bio *bio, struct iov_iter *iter)
> >> +{
> >> + const struct bio_vec *bv = iter->bvec;
> >> + unsigned int len;
> >> + size_t size;
> >> +
> >> + len = min_t(size_t, bv->bv_len, iter->count);
> >> + size = bio_add_page(bio, bv->bv_page, len,
> >> + bv->bv_offset + iter->iov_offset);
> >
> > iter->iov_offset needs to be subtracted from 'len', looks
> > the following delta change[1] is required, otherwise memory corruption
> > can be observed when running xfstests over loop/dio.
>
> Thanks, I folded this in.
>
> --
> Jens Axboe
>
syzkaller started hitting a crash on linux-next starting with this commit, and
it still occurs even with your latest version that has Ming's fix folded in.
Specifically, commit a566653ab5ab80a from your io_uring branch with commit date
Sun Feb 24 08:20:53 2019 -0700.
Reproducer:
#define _GNU_SOURCE
#include <fcntl.h>
#include <linux/loop.h>
#include <sys/ioctl.h>
#include <sys/sendfile.h>
#include <sys/syscall.h>
#include <unistd.h>
int main(void)
{
int memfd, loopfd;
memfd = syscall(__NR_memfd_create, "foo", 0);
pwrite(memfd, "\xa8", 1, 4096);
loopfd = open("/dev/loop0", O_RDWR|O_DIRECT);
ioctl(loopfd, LOOP_SET_FD, memfd);
sendfile(loopfd, loopfd, NULL, 1000000);
}
Crash:
page:ffffea0001a6aab8 count:0 mapcount:0 mapping:0000000000000000 index:0x0
flags: 0x100000000000000()
raw: 0100000000000000 ffffea0001ad2c50 ffff88807fca49d0 0000000000000000
raw: 0000000000000000 0000000000000000 00000000ffffffff
page dumped because: VM_BUG_ON_PAGE(page_ref_count(page) == 0)
------------[ cut here ]------------
kernel BUG at include/linux/mm.h:546!
invalid opcode: 0000 [#1] SMP
CPU: 1 PID: 173 Comm: syz_mm Not tainted 5.0.0-rc6-00007-ga566653ab5ab8 #22
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-20181126_142135-anatol 04/01/2014
RIP: 0010:put_page_testzero include/linux/mm.h:546 [inline]
RIP: 0010:put_page include/linux/mm.h:992 [inline]
RIP: 0010:generic_pipe_buf_release+0x37/0x40 fs/pipe.c:225
Code: 50 ff a8 01 48 0f 45 fa 8b 47 34 85 c0 74 0f f0 ff 4f 34 74 02 5d c3 e8 c7 1b fa ff 5d c3 48 c7 c6 60 aa b1 81 e8 59 25 fc ff <0f> 0b 0f 1f 80 00 00 00 00 55 48 89 e5 41 56 41 55 41 54 53 e8 a0
RSP: 0018:ffffc90000783cb0 EFLAGS: 00010246
RAX: 000000000000003e RBX: ffff88807c358800 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000001 RDI: ffff88807fc95420
RBP: ffffc90000783cb0 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000001000
R13: 0000000000001000 R14: 0000000000000000 R15: ffff88807c0b6e00
FS: 00007fd858adb240(0000) GS:ffff88807fc80000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000055dc13859000 CR3: 000000007a96b000 CR4: 00000000003406e0
Call Trace:
pipe_buf_release include/linux/pipe_fs_i.h:136 [inline]
iter_file_splice_write+0x2df/0x3f0 fs/splice.c:763
do_splice_from fs/splice.c:851 [inline]
direct_splice_actor+0x31/0x40 fs/splice.c:1023
splice_direct_to_actor+0xff/0x240 fs/splice.c:978
do_splice_direct+0x92/0xc0 fs/splice.c:1066
do_sendfile+0x1be/0x390 fs/read_write.c:1436
__do_sys_sendfile64 fs/read_write.c:1497 [inline]
__se_sys_sendfile64+0xa6/0xc0 fs/read_write.c:1483
__x64_sys_sendfile64+0x19/0x20 fs/read_write.c:1483
do_syscall_64+0x4a/0x180 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x7fd858bd224e
Code: 89 ce 5b e9 b4 fd ff ff 0f 1f 40 00 31 c0 5b c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 f3 0f 1e fa 49 89 ca b8 28 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d e2 cb 0c 00 f7 d8 64 89 01 48
RSP: 002b:00007fffc517d148 EFLAGS: 00000206 ORIG_RAX: 0000000000000028
RAX: ffffffffffffffda RBX: 0000000000000004 RCX: 00007fd858bd224e
RDX: 0000000000000000 RSI: 0000000000000004 RDI: 0000000000000004
RBP: 0000000000000003 R08: 00007fd858ca0be0 R09: 00007fffc517d240
R10: 00000000000f4240 R11: 0000000000000206 R12: 000055dc13858100
R13: 00007fffc517d240 R14: 0000000000000000 R15: 0000000000000000
---[ end trace 1d878656972e4a26 ]---
RIP: 0010:put_page_testzero include/linux/mm.h:546 [inline]
RIP: 0010:put_page include/linux/mm.h:992 [inline]
RIP: 0010:generic_pipe_buf_release+0x37/0x40 fs/pipe.c:225
Code: 50 ff a8 01 48 0f 45 fa 8b 47 34 85 c0 74 0f f0 ff 4f 34 74 02 5d c3 e8 c7 1b fa ff 5d c3 48 c7 c6 60 aa b1 81 e8 59 25 fc ff <0f> 0b 0f 1f 80 00 00 00 00 55 48 89 e5 41 56 41 55 41 54 53 e8 a0
RSP: 0018:ffffc90000783cb0 EFLAGS: 00010246
RAX: 000000000000003e RBX: ffff88807c358800 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000001 RDI: ffff88807fc95420
RBP: ffffc90000783cb0 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000001000
R13: 0000000000001000 R14: 0000000000000000 R15: ffff88807c0b6e00
FS: 00007fd858adb240(0000) GS:ffff88807fc80000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000055dc13859000 CR3: 000000007a96b000 CR4: 00000000003406e0
- Eric
--
To unsubscribe, send a message with 'unsubscribe linux-aio' in
the body to majordomo@kvack.org. For more info on Linux AIO,
see: http://www.kvack.org/aio/
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>
^ permalink raw reply
* Re: [PATCHv6 07/10] acpi/hmat: Register processor domain to its memory
From: Rafael J. Wysocki @ 2019-02-25 22:30 UTC (permalink / raw)
To: Keith Busch
Cc: Rafael J. Wysocki, Linux Kernel Mailing List,
ACPI Devel Maling List, Linux Memory Management List, Linux API,
Greg Kroah-Hartman, Dave Hansen, Dan Williams
In-Reply-To: <20190225165118.GK10237@localhost.localdomain>
On Mon, Feb 25, 2019 at 5:51 PM Keith Busch <keith.busch@intel.com> wrote:
>
> On Sun, Feb 24, 2019 at 08:59:45PM +0100, Rafael J. Wysocki wrote:
> > On Fri, Feb 22, 2019 at 7:48 PM Keith Busch <keith.busch@intel.com> wrote:
> > > If I do it the other way around, that's going to make HMEM_REPORTING
> > > complicated if a non-ACPI implementation wants to report HMEM
> > > properties.
> >
> > But the mitigations that Dave was talking about get in the way, don't they?
> >
> > Say there is another Kconfig option,CACHE_MITIGATIONS, to enable them.
> > Then you want ACPI_HMAT to be set when that it set and you also want
> > ACPI_HMAT to be set when HMEM_REPORTING and ACPI_NUMA are both set.
> >
> > OTOH, you may not want HMEM_REPORTING to be set when CACHE_MITIGATIONS
> > is set, but that causes ACPI_HMAT to be set and which means that
> > ACPI_HMAT alone will not be sufficient to determine the
> > HMEM_REPORTING value.
>
> I can't think of when we'd want to suppress reporting these attributes
> to user space, but I can split HMAT enabling so it doesn't depend on
> HMEM_REPORTING just in case there really is an in-kernel user that
> definitely does not want the same attributes exported.
I'd rather simplify HMAT enabling than make it more complicated, so
splitting it would be worse than what you have already IMO.
> > Now, if you prompt for HMEM_REPORTING and make it depend on ACPI_NUMA,
> > then ACPI_HMAT can be selected by that (regardless of the
> > CACHE_MITIGATIONS value).
> >
> > And if someone wants to use HMEM_REPORTING without ACPI_NUMA, it can
> > be made depend on whatever new option is there for that non-ACPI
> > mechanism.
> >
> > There might be a problem if someone wanted to enable the alternative
> > way of HMEM_REPORTING if ACPI_NUMA was set (in which case HMAT would
> > have to be ignored even if it was present), but in that case there
> > would need to be an explicit way to choose between HMAT and non-HMAT
> > anyway.
> >
> > In any case, I prefer providers to be selected by consumers and not
> > the other way around, in case there are multiple consumers for one
> > provider.
>
> Well, the HMEM_REPORTING fundamentally has no dependency on any of these
> things and I've put some effort into making this part provider agnostic.
Which I agree with.
> I will change it if this concern is gating acceptance, but I don't
> think it's as intuitive for generic interfaces to be the selector for
> implementation specific providers.
That is sort of a chicken-and-egg issue about what is more fundamental
that could be discussed forever. :-)
My original point was that if you regard ACPI_HMAT as the more
fundamental thing, then you should prompt for it and select
HMEM_REPORTING automatically from there. Or the other way around if
you regard HMEM_REPORTING as more fundamental. Prompting for both of
them may lead to issues.
As long as that is taken into account, I'm basically fine with any of
the two choices.
^ permalink raw reply
* [GIT PULL] y2038: additional syscall ABI cleanup
From: Arnd Bergmann @ 2019-02-25 20:03 UTC (permalink / raw)
To: Thomas Gleixner
Cc: y2038 Mailman List, linux-riscv, Linux API,
Linux Kernel Mailing List, linux-arch, Palmer Dabbelt
The following changes since commit 48166e6ea47d23984f0b481ca199250e1ce0730a:
y2038: add 64-bit time_t syscalls to all 32-bit architectures
(2019-02-07 00:13:28 +0100)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground.git
tags/y2038-syscall-abi
for you to fetch changes up to d4c08b9776b392e20efc6198ebe1bc8ec1911d9b:
riscv: Use latest system call ABI (2019-02-25 20:53:52 +0100)
----------------------------------------------------------------
y2038: additional syscall ABI cleanup
This is a follow-up to the y2038 syscall patches already merged in the tip
tree. As the final 32-bit RISC-V syscall ABI is still being decided on,
this is the last chance to make a few corrections to leave out interfaces
based on 32-bit time_t along with the old off_t and rlimit types.
The series achieves this in a few steps:
- A couple of bug fixes for minor regressions I introduced
in the original series
- A couple of older patches from Yury Norov that I had never
merged in the past, these fix up the openat/open_by_handle_at and
getrlimit/setrlimit syscalls to disallow the old versions of off_t
and rlimit.
- Hiding the deprecated system calls behind an #ifdef in
include/uapi/asm-generic/unistd.h
- Change arch/riscv to drop all these ABIs.
Originally, the plan was to also leave these out on C-Sky, but that now
has a glibc port that uses the older interfaces, so we need to leave
them in place.
----------------------------------------------------------------
Arnd Bergmann (4):
asm-generic: Make time32 syscall numbers optional
unicore32: Fix __ARCH_WANT_STAT64 definition
checksyscalls: fix up mq_timedreceive and stat exceptions
riscv: Use latest system call ABI
Yury Norov (3):
compat ABI: use non-compat openat and open_by_handle_at variants
32-bit userspace ABI: introduce ARCH_32BIT_OFF_T config option
asm-generic: Drop getrlimit and setrlimit syscalls from default list
arch/Kconfig | 10 ++++++++++
arch/arc/Kconfig | 1 +
arch/arc/include/uapi/asm/unistd.h | 2 ++
arch/arm/Kconfig | 1 +
arch/arm64/include/uapi/asm/unistd.h | 2 ++
arch/c6x/Kconfig | 1 +
arch/c6x/include/uapi/asm/unistd.h | 2 ++
arch/csky/Kconfig | 1 +
arch/csky/include/uapi/asm/unistd.h | 2 ++
arch/h8300/Kconfig | 1 +
arch/h8300/include/uapi/asm/unistd.h | 2 ++
arch/hexagon/Kconfig | 1 +
arch/hexagon/include/uapi/asm/unistd.h | 2 ++
arch/m68k/Kconfig | 1 +
arch/microblaze/Kconfig | 1 +
arch/mips/Kconfig | 1 +
arch/nds32/Kconfig | 1 +
arch/nds32/include/uapi/asm/unistd.h | 2 ++
arch/nios2/Kconfig | 1 +
arch/nios2/include/uapi/asm/unistd.h | 2 ++
arch/openrisc/Kconfig | 1 +
arch/openrisc/include/uapi/asm/unistd.h | 2 ++
arch/parisc/Kconfig | 1 +
arch/powerpc/Kconfig | 1 +
arch/riscv/include/uapi/asm/unistd.h | 1 +
arch/riscv/kernel/vdso/Makefile | 2 ++
arch/sh/Kconfig | 1 +
arch/sparc/Kconfig | 1 +
arch/unicore32/Kconfig | 1 +
arch/unicore32/include/uapi/asm/unistd.h | 4 +++-
arch/x86/Kconfig | 1 +
arch/x86/um/Kconfig | 1 +
arch/xtensa/Kconfig | 1 +
include/linux/fcntl.h | 2 +-
include/uapi/asm-generic/unistd.h | 46
+++++++++++++++++++++++++++++++++++++++++++---
scripts/checksyscalls.sh | 15 ++++++++++++---
36 files changed, 110 insertions(+), 8 deletions(-)
^ permalink raw reply
* Re: [PATCH 8/8] riscv: Use latest system call ABI
From: Palmer Dabbelt @ 2019-02-25 19:19 UTC (permalink / raw)
To: Arnd Bergmann
Cc: linux-arch, uclinux-h8-devel, yury.norov, y2038, linux-api,
linux-kernel, linux-riscv, Vineet Gupta, Guo Ren, Greentime Hu,
linux-hexagon, Thomas Gleixner, Guan Xuetao, Stafford Horne,
linux-arm-kernel
In-Reply-To: <20190218210712.3503891-9-arnd@arndb.de>
On Mon, Feb 18, 2019 at 1:07 PM Arnd Bergmann <arnd@arndb.de> wrote:
> We don't yet have an upstream glibc port for riscv, so there is no user
> space for the existing ABI, and we can remove the definitions for 32-bit
> time_t, off_t and struct resource and system calls based on them,
> including the vdso.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> arch/riscv/Kconfig | 1 -
> arch/riscv/include/uapi/asm/unistd.h | 5 +----
> arch/riscv/kernel/vdso/Makefile | 2 ++
> 3 files changed, 3 insertions(+), 5 deletions(-)
>
> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> index 09fa3a87bf30..feeeaa60697c 100644
> --- a/arch/riscv/Kconfig
> +++ b/arch/riscv/Kconfig
> @@ -11,7 +11,6 @@ config 32BIT
>
> config RISCV
> def_bool y
> - select ARCH_32BIT_OFF_T if !64BIT
> # even on 32-bit, physical (and DMA) addresses are > 32-bits
> select PHYS_ADDR_T_64BIT
> select OF
> diff --git a/arch/riscv/include/uapi/asm/unistd.h
> b/arch/riscv/include/uapi/asm/unistd.h
> index 486a288b454c..0e2eeeb1fd27 100644
> --- a/arch/riscv/include/uapi/asm/unistd.h
> +++ b/arch/riscv/include/uapi/asm/unistd.h
> @@ -17,11 +17,8 @@
>
> #ifdef __LP64__
> #define __ARCH_WANT_NEW_STAT
> -#endif /* __LP64__ */
> #define __ARCH_WANT_SET_GET_RLIMIT
> -#ifndef __LP64__
> -#define __ARCH_WANT_TIME32_SYSCALLS
> -#endif
> +#endif /* __LP64__ */
>
> #include <asm-generic/unistd.h>
>
> diff --git a/arch/riscv/kernel/vdso/Makefile
> b/arch/riscv/kernel/vdso/Makefile
> index eed1c137f618..fec62b24df89 100644
> --- a/arch/riscv/kernel/vdso/Makefile
> +++ b/arch/riscv/kernel/vdso/Makefile
> @@ -2,9 +2,11 @@
>
> # Symbols present in the vdso
> vdso-syms = rt_sigreturn
> +ifdef CONFIG_64BIT
> vdso-syms += gettimeofday
> vdso-syms += clock_gettime
> vdso-syms += clock_getres
> +endif
> vdso-syms += getcpu
> vdso-syms += flush_icache
>
> --
> 2.20.0
>
Reviewed-by: Palmer Dabbelt <palmer@sifive.com>
_______________________________________________
Y2038 mailing list
Y2038@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/y2038
^ permalink raw reply
* Re: [PATCH 1/3] bpf: add helper to check for a valid SYN cookie
From: Lorenz Bauer @ 2019-02-25 18:26 UTC (permalink / raw)
To: Martin Lau
Cc: ast@kernel.org, daniel@iogearbox.net, netdev@vger.kernel.org,
linux-api@vger.kernel.org
In-Reply-To: <20190223004431.osqrn3u3lp7a6zww@kafai-mbp.dhcp.thefacebook.com>
On Sat, 23 Feb 2019 at 00:44, Martin Lau <kafai@fb.com> wrote:
>
> On Fri, Feb 22, 2019 at 09:50:55AM +0000, Lorenz Bauer wrote:
> > Using bpf_sk_lookup_tcp it's possible to ascertain whether a packet belongs
> > to a known connection. However, there is one corner case: no sockets are
> > created if SYN cookies are active. This means that the final ACK in the
> > 3WHS is misclassified.
> >
> > Using the helper, we can look up the listening socket via bpf_sk_lookup_tcp
> > and then check whether a packet is a valid SYN cookie ACK.
> >
> > Signed-off-by: Lorenz Bauer <lmb@cloudflare.com>
> > ---
> > include/uapi/linux/bpf.h | 18 ++++++++++-
> > net/core/filter.c | 68 ++++++++++++++++++++++++++++++++++++++++
> > 2 files changed, 85 insertions(+), 1 deletion(-)
> >
> > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > index bcdd2474eee7..bc2af87e9621 100644
> > --- a/include/uapi/linux/bpf.h
> > +++ b/include/uapi/linux/bpf.h
> > @@ -2359,6 +2359,21 @@ union bpf_attr {
> > * Return
> > * A **struct bpf_tcp_sock** pointer on success, or NULL in
> > * case of failure.
> > + *
> > + * int bpf_sk_check_syncookie(struct bpf_sock *sk, void *iph, u32 iph_len, struct tcphdr *th, u32 th_len)
> > + * Description
> > + * Check whether iph and th contain a valid SYN cookie ACK for
> > + * the listening socket in sk.
> > + *
> > + * iph points to the start of the IPv4 or IPv6 header, while
> > + * iph_len contains sizeof(struct iphdr) or sizeof(struct ip6hdr).
> > + *
> > + * th points to the start of the TCP header, while th_len contains
> > + * sizeof(struct tcphdr).
> > + *
> > + * Return
> > + * 0 if iph and th are a valid SYN cookie ACK, or a negative error
> > + * otherwise.
> > */
> > #define __BPF_FUNC_MAPPER(FN) \
> > FN(unspec), \
> > @@ -2457,7 +2472,8 @@ union bpf_attr {
> > FN(spin_lock), \
> > FN(spin_unlock), \
> > FN(sk_fullsock), \
> > - FN(tcp_sock),
> > + FN(tcp_sock), \
> > + FN(sk_check_syncookie),
> >
> > /* integer value in 'imm' field of BPF_CALL instruction selects which helper
> > * function eBPF program intends to call
> > diff --git a/net/core/filter.c b/net/core/filter.c
> > index 85749f6ec789..9e68897cc7ed 100644
> > --- a/net/core/filter.c
> > +++ b/net/core/filter.c
> > @@ -5426,6 +5426,70 @@ static const struct bpf_func_proto bpf_tcp_sock_proto = {
> > .arg1_type = ARG_PTR_TO_SOCK_COMMON,
> > };
> >
> > +BPF_CALL_5(bpf_sk_check_syncookie, struct sock *, sk, void *, iph, u32, iph_len,
> s/bpf_sk_check_syncookie/bpf_tcp_check_syncookie/>
>
> > + struct tcphdr *, th, u32, th_len)
> > +{
> > +#if IS_ENABLED(CONFIG_SYN_COOKIES)
> nit. "#ifdef CONFIG_SYN_COOKIES" such that it is clear it is a bool kconfig.
>
> > + u32 cookie;
> > + int ret;
> > +
> > + if (unlikely(th_len < sizeof(*th)))
> > + return -EINVAL;
> > +
> > + /* sk_listener() allows TCP_NEW_SYN_RECV, which makes no sense here. */
> > + if (sk->sk_protocol != IPPROTO_TCP || sk->sk_state != TCP_LISTEN)
> From the test program in patch 3, the "sk" here is obtained from
> bpf_sk_lookup_tcp() which does a sk_to_full_sk() before returning.
> AFAICT, meaning bpf_sk_lookup_tcp() will return the listening sk
> even if there is a request_sock. Does it make sense to check
> syncookie if there is already a request_sock?
No, that doesn't make a lot of sense. I hadn't realised that
sk_lookup_tcp only returns full sockets.
This means we need a way to detect that there is a request sock for a
given tuple.
* adding a reqsk_exists(tuple) helper means we have to pay the lookup cost twice
* drop the sk argument and do the necessary lookups in the helper
itself, but that also
wastes a call to __inet_lookup_listener
* skip sk_to_full_sk() in a helper and return RET_PTR_TO_SOCK_COMMON,
but that violates a bunch of assumptions (e.g. calling bpf_sk_release on them)
For context: ultimately we want use this to answer the question: does
this (encapsulated)
packet contain a payload destined to a local socket? Amongst the edge
cases we need to
handle are ICMP Packet Too Big messages and SYN cookies. A solution
would be to hide
all this in an "uber" helper that takes pointers to the L3 / L4
headers and returns a verdict,
but that seems a bit gross.
>
> > + return -EINVAL;
> > +
> > + if (!sock_net(sk)->ipv4.sysctl_tcp_syncookies)
> Should tcp_synq_no_recent_overflow(tp) be checked also?
>
Yes, not sure how that slipped out.
> > + return -EINVAL;
> > +
> > + if (!th->ack || th->rst)
> How about th->syn?
>
Yes, I missed the fact that the callers in tcp_ipv{4,6}.c check this.
> > + return -ENOENT;
> > +
> > + cookie = ntohl(th->ack_seq) - 1;
> > +
> > + switch (sk->sk_family) {
> > + case AF_INET:
> > + if (unlikely(iph_len < sizeof(struct iphdr)))
> > + return -EINVAL;
> > +
> > + ret = __cookie_v4_check((struct iphdr *)iph, th, cookie);
> > + break;
> > +
> > +#if IS_ENABLED(CONFIG_IPV6)
> > + case AF_INET6:
> > + if (unlikely(iph_len < sizeof(struct ipv6hdr)))
> > + return -EINVAL;
> > +
> > + ret = __cookie_v6_check((struct ipv6hdr *)iph, th, cookie);
> > + break;
> > +#endif /* CONFIG_IPV6 */
> > +
> > + default:
> > + return -EPROTONOSUPPORT;
> > + }
> > +
> > + if (ret > 0)
> > + return 0;
> > +
> > + return -ENOENT;
> > +#else
> > + return -ENOTSUP;
> > +#endif
> > +}
> > +
> > +static const struct bpf_func_proto bpf_sk_check_syncookie_proto = {
> > + .func = bpf_sk_check_syncookie,
> > + .gpl_only = true,
> > + .pkt_access = true,
> > + .ret_type = RET_INTEGER,
> > + .arg1_type = ARG_PTR_TO_SOCKET,
> I think it should be ARG_PTR_TO_TCP_SOCK
>
> > + .arg2_type = ARG_PTR_TO_MEM,
> > + .arg3_type = ARG_CONST_SIZE,
> > + .arg4_type = ARG_PTR_TO_MEM,
> > + .arg5_type = ARG_CONST_SIZE,
> > +};
> > +
> > #endif /* CONFIG_INET */
--
Lorenz Bauer | Systems Engineer
25 Lavington St., London SE1 0NZ
www.cloudflare.com
^ permalink raw reply
* Re: [PATCHv6 07/10] acpi/hmat: Register processor domain to its memory
From: Keith Busch @ 2019-02-25 16:51 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Linux Kernel Mailing List, ACPI Devel Maling List,
Linux Memory Management List, Linux API, Greg Kroah-Hartman,
Dave Hansen, Dan Williams
In-Reply-To: <CAJZ5v0hfQ5HWT0kfaOxSbpJvdqotsMWVBCZ6wiL4Tnuy+O5O7Q@mail.gmail.com>
On Sun, Feb 24, 2019 at 08:59:45PM +0100, Rafael J. Wysocki wrote:
> On Fri, Feb 22, 2019 at 7:48 PM Keith Busch <keith.busch@intel.com> wrote:
> > If I do it the other way around, that's going to make HMEM_REPORTING
> > complicated if a non-ACPI implementation wants to report HMEM
> > properties.
>
> But the mitigations that Dave was talking about get in the way, don't they?
>
> Say there is another Kconfig option,CACHE_MITIGATIONS, to enable them.
> Then you want ACPI_HMAT to be set when that it set and you also want
> ACPI_HMAT to be set when HMEM_REPORTING and ACPI_NUMA are both set.
>
> OTOH, you may not want HMEM_REPORTING to be set when CACHE_MITIGATIONS
> is set, but that causes ACPI_HMAT to be set and which means that
> ACPI_HMAT alone will not be sufficient to determine the
> HMEM_REPORTING value.
I can't think of when we'd want to suppress reporting these attributes
to user space, but I can split HMAT enabling so it doesn't depend on
HMEM_REPORTING just in case there really is an in-kernel user that
definitely does not want the same attributes exported.
> Now, if you prompt for HMEM_REPORTING and make it depend on ACPI_NUMA,
> then ACPI_HMAT can be selected by that (regardless of the
> CACHE_MITIGATIONS value).
>
> And if someone wants to use HMEM_REPORTING without ACPI_NUMA, it can
> be made depend on whatever new option is there for that non-ACPI
> mechanism.
>
> There might be a problem if someone wanted to enable the alternative
> way of HMEM_REPORTING if ACPI_NUMA was set (in which case HMAT would
> have to be ignored even if it was present), but in that case there
> would need to be an explicit way to choose between HMAT and non-HMAT
> anyway.
>
> In any case, I prefer providers to be selected by consumers and not
> the other way around, in case there are multiple consumers for one
> provider.
Well, the HMEM_REPORTING fundamentally has no dependency on any of these
things and I've put some effort into making this part provider agnostic.
I will change it if this concern is gating acceptance, but I don't
think it's as intuitive for generic interfaces to be the selector for
implementation specific providers.
^ permalink raw reply
* Re: [PATCH] mmap.2: describe the 5level paging hack
From: Jann Horn @ 2019-02-25 15:02 UTC (permalink / raw)
To: Michael Kerrisk (man-pages)
Cc: linux-arch, linux-man, Catalin Marinas, Linux-MM, Peter Zijlstra,
Benjamin Herrenschmidt, Will Deacon, linuxppc-dev,
Andy Lutomirski, Dave Hansen, Paul Mackerras, linux-arm-kernel,
Michael Ellerman, Andrew Morton, Linux API, Linus Torvalds,
Thomas Gleixner, Kirill A . Shutemov
In-Reply-To: <f89de711-d73b-96be-75b6-0e9054022708@gmail.com>
On Mon, Feb 25, 2019 at 3:55 PM Michael Kerrisk (man-pages)
<mtk.manpages@gmail.com> wrote:
> On 2/11/19 5:36 PM, Jann Horn wrote:
> > The manpage is missing information about the compatibility hack for
> > 5-level paging that went in in 4.14, around commit ee00f4a32a76 ("x86/mm:
> > Allow userspace have mappings above 47-bit"). Add some information about
> > that.
> >
> > While I don't think any hardware supporting this is shipping yet (?), I
> > think it's useful to try to write a manpage for this API, partly to
> > figure out how usable that API actually is, and partly because when this
> > hardware does ship, it'd be nice if distro manpages had information about
> > how to use it.
> >
> > Signed-off-by: Jann Horn <jannh@google.com>
> > ---
> > This patch goes on top of the patch "[PATCH] mmap.2: fix description of
> > treatment of the hint" that I just sent, but I'm not sending them in a
> > series because I want the first one to go in, and I think this one might
> > be a bit more controversial.
> >
> > It would be nice if the architecture maintainers and mm folks could have
> > a look at this and check that what I wrote is right - I only looked at
> > the source for this, I haven't tried it.
> >
> > man2/mmap.2 | 15 +++++++++++++++
> > 1 file changed, 15 insertions(+)
> >
> > diff --git a/man2/mmap.2 b/man2/mmap.2
> > index 8556bbfeb..977782fa8 100644
> > --- a/man2/mmap.2
> > +++ b/man2/mmap.2
> > @@ -67,6 +67,8 @@ is NULL,
> > then the kernel chooses the (page-aligned) address
> > at which to create the mapping;
> > this is the most portable method of creating a new mapping.
> > +On Linux, in this case, the kernel may limit the maximum address that can be
> > +used for allocations to a legacy limit for compatibility reasons.
> > If
> > .I addr
> > is not NULL,
> > @@ -77,6 +79,19 @@ or equal to the value specified by
> > and attempt to create the mapping there.
> > If another mapping already exists there, the kernel picks a new
> > address, independent of the hint.
> > +However, if a hint above the architecture's legacy address limit is provided
> > +(on x86-64: above 0x7ffffffff000, on arm64: above 0x1000000000000, on ppc64 with
> > +book3s: above 0x7fffffffffff or 0x3fffffffffff, depending on page size), the
> > +kernel is permitted to allocate mappings beyond the architecture's legacy
> > +address limit. The availability of such addresses is hardware-dependent.
> > +Therefore, if you want to be able to use the full virtual address space of
> > +hardware that supports addresses beyond the legacy range, you need to specify an
> > +address above that limit; however, for security reasons, you should avoid
> > +specifying a fixed valid address outside the compatibility range,
> > +since that would reduce the value of userspace address space layout
> > +randomization. Therefore, it is recommended to specify an address
> > +.I beyond
> > +the end of the userspace address space.
> > .\" Before Linux 2.6.24, the address was rounded up to the next page
> > .\" boundary; since 2.6.24, it is rounded down!
> > The address of the new mapping is returned as the result of the call.
> >
>
> Hi Jann,
>
> A few comments came in on this patch. Is there anything from
> those comments that should be rolled into the text?
Hi!
Yeah, I think all the feedback on the patch were good points, and I'll
have to integrate that into my patch.
^ permalink raw reply
* Re: [PATCH] mmap.2: describe the 5level paging hack
From: Michael Kerrisk (man-pages) @ 2019-02-25 14:55 UTC (permalink / raw)
To: Jann Horn
Cc: linux-arch, linux-man, Catalin Marinas, Dave Hansen,
Peter Zijlstra, Benjamin Herrenschmidt, Will Deacon, linuxppc-dev,
Andy Lutomirski, linux-mm, Paul Mackerras, mtk.manpages,
Michael Ellerman, Andrew Morton, linux-api, Linus Torvalds,
Thomas Gleixner, Kirill A . Shutemov, linux-arm-kernel
In-Reply-To: <20190211163653.97742-1-jannh@google.com>
On 2/11/19 5:36 PM, Jann Horn wrote:
> The manpage is missing information about the compatibility hack for
> 5-level paging that went in in 4.14, around commit ee00f4a32a76 ("x86/mm:
> Allow userspace have mappings above 47-bit"). Add some information about
> that.
>
> While I don't think any hardware supporting this is shipping yet (?), I
> think it's useful to try to write a manpage for this API, partly to
> figure out how usable that API actually is, and partly because when this
> hardware does ship, it'd be nice if distro manpages had information about
> how to use it.
>
> Signed-off-by: Jann Horn <jannh@google.com>
> ---
> This patch goes on top of the patch "[PATCH] mmap.2: fix description of
> treatment of the hint" that I just sent, but I'm not sending them in a
> series because I want the first one to go in, and I think this one might
> be a bit more controversial.
>
> It would be nice if the architecture maintainers and mm folks could have
> a look at this and check that what I wrote is right - I only looked at
> the source for this, I haven't tried it.
>
> man2/mmap.2 | 15 +++++++++++++++
> 1 file changed, 15 insertions(+)
>
> diff --git a/man2/mmap.2 b/man2/mmap.2
> index 8556bbfeb..977782fa8 100644
> --- a/man2/mmap.2
> +++ b/man2/mmap.2
> @@ -67,6 +67,8 @@ is NULL,
> then the kernel chooses the (page-aligned) address
> at which to create the mapping;
> this is the most portable method of creating a new mapping.
> +On Linux, in this case, the kernel may limit the maximum address that can be
> +used for allocations to a legacy limit for compatibility reasons.
> If
> .I addr
> is not NULL,
> @@ -77,6 +79,19 @@ or equal to the value specified by
> and attempt to create the mapping there.
> If another mapping already exists there, the kernel picks a new
> address, independent of the hint.
> +However, if a hint above the architecture's legacy address limit is provided
> +(on x86-64: above 0x7ffffffff000, on arm64: above 0x1000000000000, on ppc64 with
> +book3s: above 0x7fffffffffff or 0x3fffffffffff, depending on page size), the
> +kernel is permitted to allocate mappings beyond the architecture's legacy
> +address limit. The availability of such addresses is hardware-dependent.
> +Therefore, if you want to be able to use the full virtual address space of
> +hardware that supports addresses beyond the legacy range, you need to specify an
> +address above that limit; however, for security reasons, you should avoid
> +specifying a fixed valid address outside the compatibility range,
> +since that would reduce the value of userspace address space layout
> +randomization. Therefore, it is recommended to specify an address
> +.I beyond
> +the end of the userspace address space.
> .\" Before Linux 2.6.24, the address was rounded up to the next page
> .\" boundary; since 2.6.24, it is rounded down!
> The address of the new mapping is returned as the result of the call.
>
Hi Jann,
A few comments came in on this patch. Is there anything from
those comments that should be rolled into the text?
Thanks,
Michael
--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
^ permalink raw reply
* Re: [RFC PATCH] mm,mremap: Bail out earlier in mremap_to under map pressure
From: Kirill A. Shutemov @ 2019-02-25 12:16 UTC (permalink / raw)
To: Vlastimil Babka
Cc: Oscar Salvador, linux-mm, linux-kernel, linux-api, hughd, joel,
jglisse, yang.shi, mgorman
In-Reply-To: <cfc53e5a-a403-a732-69d2-1f96b8416f6d@suse.cz>
On Mon, Feb 25, 2019 at 12:46:46PM +0100, Vlastimil Babka wrote:
> On 2/22/19 2:01 PM, Kirill A. Shutemov wrote:
> > On Thu, Feb 21, 2019 at 09:54:06AM +0100, Oscar Salvador wrote:
> >> When using mremap() syscall in addition to MREMAP_FIXED flag,
> >> mremap() calls mremap_to() which does the following:
> >>
> >> 1) unmaps the destination region where we are going to move the map
> >> 2) If the new region is going to be smaller, we unmap the last part
> >> of the old region
> >>
> >> Then, we will eventually call move_vma() to do the actual move.
> >>
> >> move_vma() checks whether we are at least 4 maps below max_map_count
> >> before going further, otherwise it bails out with -ENOMEM.
> >> The problem is that we might have already unmapped the vma's in steps
> >> 1) and 2), so it is not possible for userspace to figure out the state
> >> of the vma's after it gets -ENOMEM, and it gets tricky for userspace
> >> to clean up properly on error path.
> >>
> >> While it is true that we can return -ENOMEM for more reasons
> >> (e.g: see may_expand_vm() or move_page_tables()), I think that we can
> >> avoid this scenario in concret if we check early in mremap_to() if the
> >> operation has high chances to succeed map-wise.
> >>
> >> Should not be that the case, we can bail out before we even try to unmap
> >> anything, so we make sure the vma's are left untouched in case we are likely
> >> to be short of maps.
> >>
> >> The thumb-rule now is to rely on the worst-scenario case we can have.
> >> That is when both vma's (old region and new region) are going to be split
> >> in 3, so we get two more maps to the ones we already hold (one per each).
> >> If current map count + 2 maps still leads us to 4 maps below the threshold,
> >> we are going to pass the check in move_vma().
> >>
> >> Of course, this is not free, as it might generate false positives when it is
> >> true that we are tight map-wise, but the unmap operation can release several
> >> vma's leading us to a good state.
> >>
> >> Because of that I am sending this as a RFC.
> >> Another approach was also investigated [1], but it may be too much hassle
> >> for what it brings.
> >
> > I believe we don't need the check in move_vma() with this patch. Or do we?
>
> move_vma() can be also called directly from SYSCALL_DEFINE5(mremap) for
> the non-MMAP_FIXED case. So unless there's further refactoring, the
> check is still needed.
Okay, makes sense.
> >>
> >> [1] https://lore.kernel.org/lkml/20190219155320.tkfkwvqk53tfdojt@d104.suse.de/
> >>
> >> Signed-off-by: Oscar Salvador <osalvador@suse.de>
>
> Acked-by: Vlastimil Babka <vbabka@suse.cz>
Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
--
Kirill A. Shutemov
^ permalink raw reply
* Re: [RFC PATCH] mm,mremap: Bail out earlier in mremap_to under map pressure
From: Vlastimil Babka @ 2019-02-25 11:46 UTC (permalink / raw)
To: Kirill A. Shutemov, Oscar Salvador
Cc: linux-mm, linux-kernel, linux-api, hughd, joel, jglisse, yang.shi,
mgorman
In-Reply-To: <20190222130125.apa2ysnahgfuj2vx@kshutemo-mobl1>
On 2/22/19 2:01 PM, Kirill A. Shutemov wrote:
> On Thu, Feb 21, 2019 at 09:54:06AM +0100, Oscar Salvador wrote:
>> When using mremap() syscall in addition to MREMAP_FIXED flag,
>> mremap() calls mremap_to() which does the following:
>>
>> 1) unmaps the destination region where we are going to move the map
>> 2) If the new region is going to be smaller, we unmap the last part
>> of the old region
>>
>> Then, we will eventually call move_vma() to do the actual move.
>>
>> move_vma() checks whether we are at least 4 maps below max_map_count
>> before going further, otherwise it bails out with -ENOMEM.
>> The problem is that we might have already unmapped the vma's in steps
>> 1) and 2), so it is not possible for userspace to figure out the state
>> of the vma's after it gets -ENOMEM, and it gets tricky for userspace
>> to clean up properly on error path.
>>
>> While it is true that we can return -ENOMEM for more reasons
>> (e.g: see may_expand_vm() or move_page_tables()), I think that we can
>> avoid this scenario in concret if we check early in mremap_to() if the
>> operation has high chances to succeed map-wise.
>>
>> Should not be that the case, we can bail out before we even try to unmap
>> anything, so we make sure the vma's are left untouched in case we are likely
>> to be short of maps.
>>
>> The thumb-rule now is to rely on the worst-scenario case we can have.
>> That is when both vma's (old region and new region) are going to be split
>> in 3, so we get two more maps to the ones we already hold (one per each).
>> If current map count + 2 maps still leads us to 4 maps below the threshold,
>> we are going to pass the check in move_vma().
>>
>> Of course, this is not free, as it might generate false positives when it is
>> true that we are tight map-wise, but the unmap operation can release several
>> vma's leading us to a good state.
>>
>> Because of that I am sending this as a RFC.
>> Another approach was also investigated [1], but it may be too much hassle
>> for what it brings.
>
> I believe we don't need the check in move_vma() with this patch. Or do we?
move_vma() can be also called directly from SYSCALL_DEFINE5(mremap) for
the non-MMAP_FIXED case. So unless there's further refactoring, the
check is still needed.
>>
>> [1] https://lore.kernel.org/lkml/20190219155320.tkfkwvqk53tfdojt@d104.suse.de/
>>
>> Signed-off-by: Oscar Salvador <osalvador@suse.de>
Acked-by: Vlastimil Babka <vbabka@suse.cz>
^ permalink raw reply
* Re: [PATCHv6 07/10] acpi/hmat: Register processor domain to its memory
From: Rafael J. Wysocki @ 2019-02-24 20:07 UTC (permalink / raw)
To: Dan Williams
Cc: Keith Busch, Rafael J. Wysocki, Linux Kernel Mailing List,
ACPI Devel Maling List, Linux Memory Management List, Linux API,
Greg Kroah-Hartman, Dave Hansen
In-Reply-To: <CAPcyv4jpP0CP-QxWDc_E1QwL736PLwh8ZPrnKJzVnYrAk++93g@mail.gmail.com>
On Fri, Feb 22, 2019 at 8:21 PM Dan Williams <dan.j.williams@intel.com> wrote:
>
> On Fri, Feb 22, 2019 at 10:48 AM Keith Busch <keith.busch@intel.com> wrote:
> >
> > On Wed, Feb 20, 2019 at 11:02:01PM +0100, Rafael J. Wysocki wrote:
> > > On Thu, Feb 14, 2019 at 6:10 PM Keith Busch <keith.busch@intel.com> wrote:
> > > > config ACPI_HMAT
> > > > bool "ACPI Heterogeneous Memory Attribute Table Support"
> > > > depends on ACPI_NUMA
> > > > + select HMEM_REPORTING
> > >
> > > If you want to do this here, I'm not sure that defining HMEM_REPORTING
> > > as a user-selectable option is a good idea. In particular, I don't
> > > really think that setting ACPI_HMAT without it makes a lot of sense.
> > > Apart from this, the patch looks reasonable to me.
> >
> > I'm trying to implement based on the feedback, but I'm a little confused.
> >
> > As I have it at the moment, HMEM_REPORTING is not user-prompted, so
> > another option needs to turn it on. I have ACPI_HMAT do that here.
> >
> > So when you say it's a bad idea to make HMEM_REPORTING user selectable,
> > isn't it already not user selectable?
> >
> > If I do it the other way around, that's going to make HMEM_REPORTING
> > complicated if a non-ACPI implementation wants to report HMEM
> > properties.
>
> Agree. If a platform supports these HMEM properties then they should
> be reported.
Well, I'm not sure if everybody is in agreement on that.
> ACPI_HMAT is that opt-in for ACPI based platforms, and
> other archs can do something similar. It's not clear that one would
> ever want to opt-in to HMAT support and opt-out of reporting any of it
> to userspace.
In my view, ACPI_HMAT need not be an opt-in in the first place. The
only reason to avoid compiling HMAT parsing it would be if there were
no users of it in the kernel IMO.
^ permalink raw reply
* Re: [PATCHv6 07/10] acpi/hmat: Register processor domain to its memory
From: Rafael J. Wysocki @ 2019-02-24 19:59 UTC (permalink / raw)
To: Keith Busch
Cc: Rafael J. Wysocki, Linux Kernel Mailing List,
ACPI Devel Maling List, Linux Memory Management List, Linux API,
Greg Kroah-Hartman, Dave Hansen, Dan Williams
In-Reply-To: <20190222184831.GF10237@localhost.localdomain>
On Fri, Feb 22, 2019 at 7:48 PM Keith Busch <keith.busch@intel.com> wrote:
>
> On Wed, Feb 20, 2019 at 11:02:01PM +0100, Rafael J. Wysocki wrote:
> > On Thu, Feb 14, 2019 at 6:10 PM Keith Busch <keith.busch@intel.com> wrote:
> > > config ACPI_HMAT
> > > bool "ACPI Heterogeneous Memory Attribute Table Support"
> > > depends on ACPI_NUMA
> > > + select HMEM_REPORTING
> >
> > If you want to do this here, I'm not sure that defining HMEM_REPORTING
> > as a user-selectable option is a good idea. In particular, I don't
> > really think that setting ACPI_HMAT without it makes a lot of sense.
> > Apart from this, the patch looks reasonable to me.
>
> I'm trying to implement based on the feedback, but I'm a little confused.
>
> As I have it at the moment, HMEM_REPORTING is not user-prompted, so
> another option needs to turn it on. I have ACPI_HMAT do that here.
>
> So when you say it's a bad idea to make HMEM_REPORTING user selectable,
> isn't it already not user selectable?
I thought that HMEM_REPORTING was user-prompted initially, by bad if it wasn't.
> If I do it the other way around, that's going to make HMEM_REPORTING
> complicated if a non-ACPI implementation wants to report HMEM
> properties.
But the mitigations that Dave was talking about get in the way, don't they?
Say there is another Kconfig option,CACHE_MITIGATIONS, to enable them.
Then you want ACPI_HMAT to be set when that it set and you also want
ACPI_HMAT to be set when HMEM_REPORTING and ACPI_NUMA are both set.
OTOH, you may not want HMEM_REPORTING to be set when CACHE_MITIGATIONS
is set, but that causes ACPI_HMAT to be set and which means that
ACPI_HMAT alone will not be sufficient to determine the
HMEM_REPORTING value.
Now, if you prompt for HMEM_REPORTING and make it depend on ACPI_NUMA,
then ACPI_HMAT can be selected by that (regardless of the
CACHE_MITIGATIONS value).
And if someone wants to use HMEM_REPORTING without ACPI_NUMA, it can
be made depend on whatever new option is there for that non-ACPI
mechanism.
There might be a problem if someone wanted to enable the alternative
way of HMEM_REPORTING if ACPI_NUMA was set (in which case HMAT would
have to be ignored even if it was present), but in that case there
would need to be an explicit way to choose between HMAT and non-HMAT
anyway.
In any case, I prefer providers to be selected by consumers and not
the other way around, in case there are multiple consumers for one
provider.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox