Re: [PATCH V3 10/10] md/raid1: introduce wait_for_serialization

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





On 1/4/20 12:15 AM, Song Liu wrote:
On Mon, Dec 23, 2019 at 1:49 AM <jgq516@xxxxxxxxx> wrote:
From: Guoqing Jiang <guoqing.jiang@xxxxxxxxxxxxxxx>

Previously, we call check_and_add_serial when serialization is
enabled for write IO, but it could allocate and free memory
back and forth.

Now, let's just get an element from memory pool with the new
function, then insert node to rb tree if no collision happens.

Signed-off-by: Guoqing Jiang <guoqing.jiang@xxxxxxxxxxxxxxx>
---
  drivers/md/raid1.c | 41 ++++++++++++++++++++++-------------------
  1 file changed, 22 insertions(+), 19 deletions(-)

diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 48d553d7989a..cd810e195086 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -56,32 +56,43 @@ static void lower_barrier(struct r1conf *conf, sector_t sector_nr);
  INTERVAL_TREE_DEFINE(struct serial_info, node, sector_t, _subtree_last,
                      START, LAST, static inline, raid1_rb);

-static int check_and_add_serial(struct md_rdev *rdev, sector_t lo, sector_t hi)
+static int check_and_add_serial(struct md_rdev *rdev, struct r1bio *r1_bio,
+                               struct serial_info *si, int idx)
  {
-       struct serial_info *si;
         unsigned long flags;
         int ret = 0;
-       struct mddev *mddev = rdev->mddev;
-       int idx = sector_to_idx(lo);
+       sector_t lo = r1_bio->sector;
+       sector_t hi = lo + r1_bio->sectors;
         struct serial_in_rdev *serial = &rdev->serial[idx];

-       si = mempool_alloc(mddev->serial_info_pool, GFP_NOIO);
-
         spin_lock_irqsave(&serial->serial_lock, flags);
         /* collision happened */
         if (raid1_rb_iter_first(&serial->serial_rb, lo, hi))
                 ret = -EBUSY;
-       if (!ret) {
+       else {
                 si->start = lo;
                 si->last = hi;
                 raid1_rb_insert(si, &serial->serial_rb);
-       } else
-               mempool_free(si, mddev->serial_info_pool);
+       }
         spin_unlock_irqrestore(&serial->serial_lock, flags);

         return ret;
  }

+static void wait_for_serialization(struct md_rdev *rdev, struct r1bio *r1_bio)
+{
+       struct mddev *mddev = rdev->mddev;
+       struct serial_info *si;
+       int idx = sector_to_idx(r1_bio->sector);
+       struct serial_in_rdev *serial = &rdev->serial[idx];
+
+       if (WARN_ON(!mddev->serial_info_pool))
+               return;
+       si = mempool_alloc(mddev->serial_info_pool, GFP_NOIO);
+       wait_event(serial->serial_io_wait,
+                  check_and_add_serial(rdev, r1_bio, si, idx) == 0);
Are we leaking si when raid1_rb_iter_first() failed?

In that case, we just waiting for the disappear of collision, and si will be
used when no collision happen, remove_serial frees the memory finally.

Or do I misunderstanding your question?

Thanks,
Guoqing



[Index of Archives]     [Linux RAID Wiki]     [ATA RAID]     [Linux SCSI Target Infrastructure]     [Linux Block]     [Linux IDE]     [Linux SCSI]     [Linux Hams]     [Device Mapper]     [Device Mapper Cryptographics]     [Kernel]     [Linux Admin]     [Linux Net]     [GFS]     [RPM]     [git]     [Yosemite Forum]


  Powered by Linux