OCFS2-Devel Archive mirror
 help / color / mirror / Atom feed
From: Heming Zhao via Ocfs2-devel <ocfs2-devel@oss.oracle.com>
To: Joseph Qi <joseph.qi@linux.alibaba.com>, ocfs2-devel@lists.linux.dev
Cc: ocfs2-devel@oss.oracle.com
Subject: Re: [Ocfs2-devel] [PATCH] ocfs2: Fix wrong search logic in __ocfs2_resv_find_window
Date: Wed, 28 Jun 2023 11:09:55 +0800	[thread overview]
Message-ID: <f2b51fec-1e1b-6575-e5a0-c0222358b4c7@suse.com> (raw)
In-Reply-To: <b8f89579-118b-7697-f77b-dee588c3d3e0@suse.com>

ping ...

On 4/29/23 2:37 PM, Heming Zhao via Ocfs2-devel wrote:
> ping...
> 
> On 4/21/23 3:35 PM, Joseph Qi wrote:
>> Hi,
>> Could you please share a reproducer?
>>
>> Thanks,
>> Joseph
>>
>> On 4/6/23 11:40 PM, Heming Zhao wrote:
>>> ** problem **
>>>
>>> Current code triggers a defragfs bug [1]:
>>>
>>> ```
>>> tw-tst:~ # defragfs.ocfs2 /mnt/test_from_dd1
>>> defragfs.ocfs2 1.8.7
>>> [ERROR]Move extent failed:"/mnt/test_from_dd1" - No space left on device
>>> [ERROR]"/mnt/test_from_dd1":No space left on device
>>> ```
>>>
>>> I added some debug messages in relevant functions. When above error
>>> messages appeared, the la-window still had enough continuous bitmap
>>> to use, the -ENOSPC is wrong.
>>>
>>> ** analysis **
>>>
>>> __ocfs2_resv_find_window should use resv node from rb-tree to do linear
>>> search. But current code logic uses un-managered area between two resvs.
>>> The searching logic deviates from this func job, which should only focus
>>> on reservation areas (when rb_root is non NULL). Another issue of
>>> __ocfs2_resv_find_window is more inclined to generate inner fragment.
>>> It doesn't search & consume existing reservations but be apt to create
>>> new reservation item.
>>>
>>> This patch pulls this func (__ocfs2_resv_find_window) to do what it
>>> should do: search & consume resev. if this func fails to get suitable
>>> bitmap area, caller ocfs2_resv_find_window fallbacks to use oldest
>>> resv from LRU to do the final search.
>>>
>>> [1]: https://bugzilla.suse.com/show_bug.cgi?id=1131931
>>>
>>> Signed-off-by: Heming Zhao <heming.zhao@suse.com>
>>> ---
>>>   fs/ocfs2/reservations.c | 48 +++++++++++++++++++++++++++++------------
>>>   1 file changed, 34 insertions(+), 14 deletions(-)
>>>
>>> diff --git a/fs/ocfs2/reservations.c b/fs/ocfs2/reservations.c
>>> index a9d1296d736d..eda672622d1d 100644
>>> --- a/fs/ocfs2/reservations.c
>>> +++ b/fs/ocfs2/reservations.c
>>> @@ -458,10 +458,11 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap,
>>>   {
>>>       struct rb_root *root = &resmap->m_reservations;
>>>       unsigned int gap_start, gap_end, gap_len;
>>> -    struct ocfs2_alloc_reservation *prev_resv, *next_resv;
>>> +    struct ocfs2_alloc_reservation *prev_resv, *next_resv, *best_resv;
>>>       struct rb_node *prev, *next;
>>>       unsigned int cstart, clen;
>>>       unsigned int best_start = 0, best_len = 0;
>>> +    int create_new = 0;
>>>       /*
>>>        * Nasty cases to consider:
>>> @@ -540,8 +541,9 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap,
>>>           if (clen) {
>>>               best_len = clen;
>>>               best_start = cstart;
>>> +            create_new = 1;
>>>               if (best_len == wanted)
>>> -                goto out_insert;
>>> +                goto out_create;
>>>           }
>>>           prev_resv = next_resv;
>>> @@ -557,13 +559,9 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap,
>>>       while (1) {
>>>           next = rb_next(prev);
>>>           if (next) {
>>> -            next_resv = rb_entry(next,
>>> -                         struct ocfs2_alloc_reservation,
>>> -                         r_node);
>>> -
>>> -            gap_start = ocfs2_resv_end(prev_resv) + 1;
>>> -            gap_end = next_resv->r_start - 1;
>>> -            gap_len = gap_end - gap_start + 1;
>>> +            gap_start = prev_resv->r_start;
>>> +            gap_end = prev_resv->r_start + prev_resv->r_len - 1;
>>> +            gap_len = prev_resv->r_len;
>>>           } else {
>>>               /*
>>>                * We're at the rightmost edge of the
>>> @@ -575,8 +573,8 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap,
>>>               gap_end = resmap->m_bitmap_len - 1;
>>>           }
>>> -        trace_ocfs2_resv_find_window_next(next ? next_resv->r_start: -1,
>>> -                    next ? ocfs2_resv_end(next_resv) : -1);
>>> +        trace_ocfs2_resv_find_window_next(next ? prev_resv->r_start : -1,
>>> +                    next ? ocfs2_resv_end(prev_resv) : -1);
>>>           /*
>>>            * No need to check this gap if we have already found
>>>            * a larger region of free bits.
>>> @@ -589,10 +587,16 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap,
>>>           if (clen == wanted) {
>>>               best_len = clen;
>>>               best_start = cstart;
>>> -            goto out_insert;
>>> +            best_resv = prev_resv;
>>> +            if (!next)
>>> +                goto out_create;
>>> +            else
>>> +                goto out_insert;
>>>           } else if (clen > best_len) {
>>>               best_len = clen;
>>>               best_start = cstart;
>>> +            best_resv = prev_resv;
>>> +            create_new = 0;
>>>           }
>>>   next_resv:
>>> @@ -604,12 +608,28 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap,
>>>                        r_node);
>>>       }
>>> -out_insert:
>>> -    if (best_len) {
>>> +    if (!best_len)
>>> +        return;
>>> +
>>> +    if (create_new) {
>>> +out_create:
>>>           resv->r_start = best_start;
>>>           resv->r_len = best_len;
>>>           ocfs2_resv_insert(resmap, resv);
>>> +        return;
>>>       }
>>> +
>>> +out_insert:
>>> +    if (best_resv->r_len <= wanted) {
>>> +        resv->r_start = best_start;
>>> +        resv->r_len = best_len;
>>> +        __ocfs2_resv_discard(resmap, best_resv);
>>> +    } else {
>>> +        best_resv->r_len -= best_len;
>>> +        resv->r_start = ocfs2_resv_end(best_resv) + 1;
>>> +        resv->r_len = best_len;
>>> +    }
>>> +    ocfs2_resv_insert(resmap, resv);
>>>   }
>>>   static void ocfs2_cannibalize_resv(struct ocfs2_reservation_map *resmap,
> 
> 
> _______________________________________________
> Ocfs2-devel mailing list
> Ocfs2-devel@oss.oracle.com
> https://oss.oracle.com/mailman/listinfo/ocfs2-devel


_______________________________________________
Ocfs2-devel mailing list
Ocfs2-devel@oss.oracle.com
https://oss.oracle.com/mailman/listinfo/ocfs2-devel

WARNING: multiple messages have this Message-ID (diff)
From: Heming Zhao <heming.zhao@suse.com>
To: Joseph Qi <joseph.qi@linux.alibaba.com>, ocfs2-devel@lists.linux.dev
Cc: ocfs2-devel@oss.oracle.com
Subject: Re: [Ocfs2-devel] [PATCH] ocfs2: Fix wrong search logic in __ocfs2_resv_find_window
Date: Wed, 28 Jun 2023 11:09:55 +0800	[thread overview]
Message-ID: <f2b51fec-1e1b-6575-e5a0-c0222358b4c7@suse.com> (raw)
Message-ID: <20230628030955.uypVL2Ytd3czRqV4lUUB_g-Zw8G33ZHKAIL2S_bTN6o@z> (raw)
In-Reply-To: <b8f89579-118b-7697-f77b-dee588c3d3e0@suse.com>

ping ...

On 4/29/23 2:37 PM, Heming Zhao via Ocfs2-devel wrote:
> ping...
> 
> On 4/21/23 3:35 PM, Joseph Qi wrote:
>> Hi,
>> Could you please share a reproducer?
>>
>> Thanks,
>> Joseph
>>
>> On 4/6/23 11:40 PM, Heming Zhao wrote:
>>> ** problem **
>>>
>>> Current code triggers a defragfs bug [1]:
>>>
>>> ```
>>> tw-tst:~ # defragfs.ocfs2 /mnt/test_from_dd1
>>> defragfs.ocfs2 1.8.7
>>> [ERROR]Move extent failed:"/mnt/test_from_dd1" - No space left on device
>>> [ERROR]"/mnt/test_from_dd1":No space left on device
>>> ```
>>>
>>> I added some debug messages in relevant functions. When above error
>>> messages appeared, the la-window still had enough continuous bitmap
>>> to use, the -ENOSPC is wrong.
>>>
>>> ** analysis **
>>>
>>> __ocfs2_resv_find_window should use resv node from rb-tree to do linear
>>> search. But current code logic uses un-managered area between two resvs.
>>> The searching logic deviates from this func job, which should only focus
>>> on reservation areas (when rb_root is non NULL). Another issue of
>>> __ocfs2_resv_find_window is more inclined to generate inner fragment.
>>> It doesn't search & consume existing reservations but be apt to create
>>> new reservation item.
>>>
>>> This patch pulls this func (__ocfs2_resv_find_window) to do what it
>>> should do: search & consume resev. if this func fails to get suitable
>>> bitmap area, caller ocfs2_resv_find_window fallbacks to use oldest
>>> resv from LRU to do the final search.
>>>
>>> [1]: https://bugzilla.suse.com/show_bug.cgi?id=1131931
>>>
>>> Signed-off-by: Heming Zhao <heming.zhao@suse.com>
>>> ---
>>>   fs/ocfs2/reservations.c | 48 +++++++++++++++++++++++++++++------------
>>>   1 file changed, 34 insertions(+), 14 deletions(-)
>>>
>>> diff --git a/fs/ocfs2/reservations.c b/fs/ocfs2/reservations.c
>>> index a9d1296d736d..eda672622d1d 100644
>>> --- a/fs/ocfs2/reservations.c
>>> +++ b/fs/ocfs2/reservations.c
>>> @@ -458,10 +458,11 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap,
>>>   {
>>>       struct rb_root *root = &resmap->m_reservations;
>>>       unsigned int gap_start, gap_end, gap_len;
>>> -    struct ocfs2_alloc_reservation *prev_resv, *next_resv;
>>> +    struct ocfs2_alloc_reservation *prev_resv, *next_resv, *best_resv;
>>>       struct rb_node *prev, *next;
>>>       unsigned int cstart, clen;
>>>       unsigned int best_start = 0, best_len = 0;
>>> +    int create_new = 0;
>>>       /*
>>>        * Nasty cases to consider:
>>> @@ -540,8 +541,9 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap,
>>>           if (clen) {
>>>               best_len = clen;
>>>               best_start = cstart;
>>> +            create_new = 1;
>>>               if (best_len == wanted)
>>> -                goto out_insert;
>>> +                goto out_create;
>>>           }
>>>           prev_resv = next_resv;
>>> @@ -557,13 +559,9 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap,
>>>       while (1) {
>>>           next = rb_next(prev);
>>>           if (next) {
>>> -            next_resv = rb_entry(next,
>>> -                         struct ocfs2_alloc_reservation,
>>> -                         r_node);
>>> -
>>> -            gap_start = ocfs2_resv_end(prev_resv) + 1;
>>> -            gap_end = next_resv->r_start - 1;
>>> -            gap_len = gap_end - gap_start + 1;
>>> +            gap_start = prev_resv->r_start;
>>> +            gap_end = prev_resv->r_start + prev_resv->r_len - 1;
>>> +            gap_len = prev_resv->r_len;
>>>           } else {
>>>               /*
>>>                * We're at the rightmost edge of the
>>> @@ -575,8 +573,8 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap,
>>>               gap_end = resmap->m_bitmap_len - 1;
>>>           }
>>> -        trace_ocfs2_resv_find_window_next(next ? next_resv->r_start: -1,
>>> -                    next ? ocfs2_resv_end(next_resv) : -1);
>>> +        trace_ocfs2_resv_find_window_next(next ? prev_resv->r_start : -1,
>>> +                    next ? ocfs2_resv_end(prev_resv) : -1);
>>>           /*
>>>            * No need to check this gap if we have already found
>>>            * a larger region of free bits.
>>> @@ -589,10 +587,16 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap,
>>>           if (clen == wanted) {
>>>               best_len = clen;
>>>               best_start = cstart;
>>> -            goto out_insert;
>>> +            best_resv = prev_resv;
>>> +            if (!next)
>>> +                goto out_create;
>>> +            else
>>> +                goto out_insert;
>>>           } else if (clen > best_len) {
>>>               best_len = clen;
>>>               best_start = cstart;
>>> +            best_resv = prev_resv;
>>> +            create_new = 0;
>>>           }
>>>   next_resv:
>>> @@ -604,12 +608,28 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap,
>>>                        r_node);
>>>       }
>>> -out_insert:
>>> -    if (best_len) {
>>> +    if (!best_len)
>>> +        return;
>>> +
>>> +    if (create_new) {
>>> +out_create:
>>>           resv->r_start = best_start;
>>>           resv->r_len = best_len;
>>>           ocfs2_resv_insert(resmap, resv);
>>> +        return;
>>>       }
>>> +
>>> +out_insert:
>>> +    if (best_resv->r_len <= wanted) {
>>> +        resv->r_start = best_start;
>>> +        resv->r_len = best_len;
>>> +        __ocfs2_resv_discard(resmap, best_resv);
>>> +    } else {
>>> +        best_resv->r_len -= best_len;
>>> +        resv->r_start = ocfs2_resv_end(best_resv) + 1;
>>> +        resv->r_len = best_len;
>>> +    }
>>> +    ocfs2_resv_insert(resmap, resv);
>>>   }
>>>   static void ocfs2_cannibalize_resv(struct ocfs2_reservation_map *resmap,
> 
> 
> _______________________________________________
> Ocfs2-devel mailing list
> Ocfs2-devel@oss.oracle.com
> https://oss.oracle.com/mailman/listinfo/ocfs2-devel


  reply	other threads:[~2023-06-28  3:10 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-04-06 15:40 [Ocfs2-devel] [PATCH] ocfs2: Fix wrong search logic in __ocfs2_resv_find_window Heming Zhao via Ocfs2-devel
2023-04-07 15:42 ` Heming Zhao via Ocfs2-devel
2023-04-18  9:43 ` Joseph Qi via Ocfs2-devel
2023-04-21  7:35 ` Joseph Qi via Ocfs2-devel
2023-04-21  8:01   ` Heming Zhao via Ocfs2-devel
2023-04-21  8:43     ` Heming Zhao via Ocfs2-devel
2023-04-29  6:37   ` Heming Zhao via Ocfs2-devel
2023-06-28  3:09     ` Heming Zhao via Ocfs2-devel [this message]
2023-06-28  3:09       ` Heming Zhao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f2b51fec-1e1b-6575-e5a0-c0222358b4c7@suse.com \
    --to=ocfs2-devel@oss.oracle.com \
    --cc=heming.zhao@suse.com \
    --cc=joseph.qi@linux.alibaba.com \
    --cc=ocfs2-devel@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).