From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 68E00C3DA64 for ; Wed, 31 Jul 2024 08:20:43 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id F06976B0082; Wed, 31 Jul 2024 04:20:42 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id E8EEB6B0083; Wed, 31 Jul 2024 04:20:42 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id D088C6B0085; Wed, 31 Jul 2024 04:20:42 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id A99226B0082 for ; Wed, 31 Jul 2024 04:20:42 -0400 (EDT) Received: from smtpin28.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay02.hostedemail.com (Postfix) with ESMTP id 29EEA1201A6 for ; Wed, 31 Jul 2024 08:20:42 +0000 (UTC) X-FDA: 82399351524.28.74F741E Received: from mail-vs1-f49.google.com (mail-vs1-f49.google.com [209.85.217.49]) by imf23.hostedemail.com (Postfix) with ESMTP id 4DB4D140010 for ; Wed, 31 Jul 2024 08:20:40 +0000 (UTC) Authentication-Results: imf23.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=RAykKsxp; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf23.hostedemail.com: domain of 21cnbao@gmail.com designates 209.85.217.49 as permitted sender) smtp.mailfrom=21cnbao@gmail.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1722413978; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=4/BAqmiquwGwVLSBU9yNjvxBZUeZbafNdbdw4UrUMac=; b=KWopoaM5FXw+e72y2Xp3oXhB/hc3wgDUrXrahA8foncWNnmEfBkJtxH1vyccBIz3UkQyl7 qP4Uk5UdYxEP+zsAOlfqdismvDzigeVuxmekIoTyi9tW3YUVaXElp8sEWBjTZftwHVVy4k zS79wts/9j5/k6SJkVtQMlhiAbI9tuM= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1722413978; a=rsa-sha256; cv=none; b=cPR2ZtHLImoY7uuZh1ymA8w28tpa45pHQwq5zdEAbuebXwz4HEN1mPKsAzsS71XeTQXJG0 kHb5U0cxnsM0wV3x/ki6M9rakbmH6j4Ro1geVF+cWedWVDhqPWa+qXRqLTNRIbESagiMn4 X5WLUr/INdKCh+ZVguyWh1AZBjgM5e8= ARC-Authentication-Results: i=1; imf23.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=RAykKsxp; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf23.hostedemail.com: domain of 21cnbao@gmail.com designates 209.85.217.49 as permitted sender) smtp.mailfrom=21cnbao@gmail.com Received: by mail-vs1-f49.google.com with SMTP id ada2fe7eead31-49299323d71so1484923137.1 for ; Wed, 31 Jul 2024 01:20:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1722414039; x=1723018839; darn=kvack.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=4/BAqmiquwGwVLSBU9yNjvxBZUeZbafNdbdw4UrUMac=; b=RAykKsxp2enHUdlr1NjjHOvQVC8cRPl+4oQpTdwQH8Gy2sqOHy4Mi26IfOTho02mJ4 sIsoBVqqbCzGujwcY8xBUTsKGio3vfrq97yo0Izfq9dbV4C/5pEn+oofIH28XS0RhyXx u1Am5dXAFccG2igQsxNVMUXmAYcwhA4ZuwrvVYR1NxNQaZDa9PjOu/CJ0RxQUh9OvjQ1 dLoVgSPy08IxW71b87Q6OXVSP1n0jz/jy2Qad1MFfmcpl7Kq8hexyMh7EUd9BT4GDC4V eO/Enwuz8+FWw8sdRPiX6csL6gwuqROe/Ikz2XFbAcr7fPzMq6RZjht0sATD6r7mhlGo +IHg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1722414039; x=1723018839; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=4/BAqmiquwGwVLSBU9yNjvxBZUeZbafNdbdw4UrUMac=; b=reKlEpF9iB/6JzXHsJZjIBxF6nN+TfNrArNKpesNYbeD41QY+BxMhT2wrWO79xQQ6K Glp41a+cmdzarTaL8YwwZffQ+pcuEi331BkGvHCV49KzXqKIplNJI2asWVev0mkmux2o E6qn9ir9Fbr9O/R7g9joV1nYeG20cQ9/oaN032aFg1FjTFdUoiIIc3Ay3rS8feT2XfL3 W4cxhS5U1HEhraKQPdV90XjRaRqJvJqCSImZThkJKbNJ0BAWBxx442Z3+f20tZdQLUuR 6QAJ0ZDBNSs6yuEOSRw9PFxDbPOilFBYvO4q8+FI0MVcGAPGRaXqQ6/8i8JWbycoPs/3 4v1w== X-Forwarded-Encrypted: i=1; AJvYcCWpRCwMgoEetnwA9fkPwNl/Le7NKVKuYbY6Fjf+3HBB3Db+zTRP1gLZUB4Njc4zc6GAPk6ca/IoDeVcV/IF/MPXy8E= X-Gm-Message-State: AOJu0YxOsQaslqi925fqUE2fns3QtXXb0cbyoYIlXOMV9jkkujzU80Dg tUGnYN/w2O5YjipToCREST0Y7nS4Yj2CN0aIRSg0abdLElAGw2OwKpG2Ky76SfqXngmMBOWX1m7 7qffXa/TU8bhpYlbpVdANYDFupSA= X-Google-Smtp-Source: AGHT+IHs/QUnmAdWn8Wy9f0Cnq5XW8VOicp5WQdLKpKXpC/QONxvYSbzzKQ2YCHrgvquXaG6b3jsJNtgkwlFkxDwEOg= X-Received: by 2002:a05:6102:4194:b0:492:9adb:f4de with SMTP id ada2fe7eead31-493fa15f388mr17465382137.5.1722414039131; Wed, 31 Jul 2024 01:20:39 -0700 (PDT) MIME-Version: 1.0 References: <20240730071339.107447-1-21cnbao@gmail.com> <20240730071339.107447-2-21cnbao@gmail.com> <874j86oubf.fsf@yhuang6-desk2.ccr.corp.intel.com> In-Reply-To: <874j86oubf.fsf@yhuang6-desk2.ccr.corp.intel.com> From: Barry Song <21cnbao@gmail.com> Date: Wed, 31 Jul 2024 16:20:27 +0800 Message-ID: Subject: Re: [PATCH 1/1] mm: swap: add nr argument in swapcache_prepare and swapcache_clear to support large folios To: "Huang, Ying" Cc: akpm@linux-foundation.org, linux-mm@kvack.org, baolin.wang@linux.alibaba.com, chrisl@kernel.org, david@redhat.com, hannes@cmpxchg.org, hughd@google.com, kaleshsingh@google.com, kasong@tencent.com, linux-kernel@vger.kernel.org, mhocko@suse.com, minchan@kernel.org, nphamcs@gmail.com, ryan.roberts@arm.com, senozhatsky@chromium.org, shakeel.butt@linux.dev, shy828301@gmail.com, surenb@google.com, v-songbaohua@oppo.com, willy@infradead.org, xiang@kernel.org, yosryahmed@google.com Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Rspamd-Server: rspam07 X-Rspamd-Queue-Id: 4DB4D140010 X-Stat-Signature: 9w9uorhop7m9wrjxgr1gzfnezgb7531g X-Rspam-User: X-HE-Tag: 1722414040-504713 X-HE-Meta: U2FsdGVkX1/FAJZLXRpp9Mn166CffqRZeYHBFA9E17+J2IvMZsNio/tzo3en+e5nnKKZfY33VF6K4gbXGHrjiJg+/Uax0AJ6GZnf140BEWxVrT7rid4O067JV3LMUeELQYsKrpwDQSSv6uzntjSDCtQ5nBv2srbXfTHIteoxKh+k0aD0Wd57GEeKnIL6FCkvL86iKvax+MEKtp16gZZkqMR3OiLoc5DuERWCLDzqd6RSgV/PesaDQJiIxcYKxODDpwusnLj5kErrEv7YjEhDbdnbRh0KwOGsZsVItzj2tC3Fb1K+bUyfIFY7PihdG/vloyu+mqMqvpdiHrkliAWCgT2p8V3/Nfu4lqJYOz49dddxmnYGCv9EpqjNXP9/54T9ykE73IMkKsZSBRPLm8tEKP3o1LGtFjPfq21BSdShWhjIGnC547WlIJ7H9lFVSY69B+hdJ+P+tjWpzGIBPmcgvVsAdd0j+D27eQb9cuiAQQfgSC6DlytTKQjWrxdCDKNAFnpXr2CrXP2kchA/cUKgJ21S19uN57rOP673QZjAPSuS7AoM0gFxKUqp+D3IeKtzJqa49/qVGXhHFdtcWnaqDorpiQe3tUknd6NkHWcsPn9l1yPkMYEtHMMaUVieGIT6HRQZGW1cXIld08OgG+OdtGokasp9HEwPglizhtGZ/OidKpl5jLsIFoftB+1dFGVvv5okjXzlN7dEXvRPwaq8bUjm8JEWpG3Ynd1WStUgzUcVzcQmprpPPtq3rm1GUdUyI2S3Vogo9Q3kW7U6qR9kUd7qhhseeL8deM+ouhnypAxbbR3j1sty4Rc4yFqSE0xcs4qlwLdSV5sLhtu/kNDeYpyxZ0q1RBJ++sWtxOKXxQlPfyyThS5sw0OrCv7n9Y6ph48MBmPonTB3oZyn6tND2eY83jhzZ4is6yu7JUzjmPl50ddUAYRJMdQ2r0LZ4uTZIlieMbXafoxwvHjcAXs 2Q5ncej4 fE/Disal2rEkK9LxyDisKMcQi4ignmMdgNjqc8ElYDpxn53AI1Uu4vXM6pOoHZ4kv7xnbHMprsIXdMLp1ixshwdEikmwZOuZ5YOO8Df2k9O5BCiA0mfZwVM8+NSW0hbwDa6a1oBxRBPkaNNX2QuCYPsv2UuVsJHSVpzH8QbxGI4iz6dodYAu3TD4jjFaSBykfp1agzfhsD+ONm5aHfrJkvqpKMI0qH1G2rlkCDkjLtvshlcl/tKc0cRqt2eHYVN86cJp/Ll7to51qm0ga0kHvAe8ZdxFnxF10ZWSVuzJFfWp+VnujabvcR/q8MeHXnfAjn59Uqw4/7IpzMG7bvMkzV0xcErApAhJQJAdbmTSrXmsGEZks3xOZ4RVaIO10PfzyoEgUbcV7y07YLVXgKF3T/DYEFPvK+8OgF1UTqLsM5T21NSh55Du4tEYEnJbYv0g/tII/HA9mrjdOlU0NBcee0d9zgv4QO4ku2+eaPVXUx8AHJwn+XhWiukY/sQ== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: On Wed, Jul 31, 2024 at 4:14=E2=80=AFPM Huang, Ying = wrote: > > Hi, Barry, > > Barry Song <21cnbao@gmail.com> writes: > > > From: Barry Song > > > > Right now, swapcache_prepare() and swapcache_clear() supports one entry > > only, to support large folios, we need to handle multiple swap entries. > > > > To optimize stack usage, we iterate twice in __swap_duplicate(): the > > first time to verify that all entries are valid, and the second time > > to apply the modifications to the entries. > > > > Currently, we're using nr=3D1 for the existing users. > > > > Reviewed-by: Baolin Wang > > Signed-off-by: Barry Song > > --- > > include/linux/swap.h | 4 +- > > mm/memory.c | 6 +-- > > mm/swap.h | 5 ++- > > mm/swap_state.c | 2 +- > > mm/swapfile.c | 101 +++++++++++++++++++++++++------------------ > > 5 files changed, 68 insertions(+), 50 deletions(-) > > > > diff --git a/include/linux/swap.h b/include/linux/swap.h > > index ba7ea95d1c57..5b920fa2315b 100644 > > --- a/include/linux/swap.h > > +++ b/include/linux/swap.h > > @@ -480,7 +480,7 @@ extern int get_swap_pages(int n, swp_entry_t swp_en= tries[], int order); > > extern int add_swap_count_continuation(swp_entry_t, gfp_t); > > extern void swap_shmem_alloc(swp_entry_t); > > extern int swap_duplicate(swp_entry_t); > > -extern int swapcache_prepare(swp_entry_t); > > +extern int swapcache_prepare(swp_entry_t entry, int nr); > > extern void swap_free_nr(swp_entry_t entry, int nr_pages); > > extern void swapcache_free_entries(swp_entry_t *entries, int n); > > extern void free_swap_and_cache_nr(swp_entry_t entry, int nr); > > @@ -554,7 +554,7 @@ static inline int swap_duplicate(swp_entry_t swp) > > return 0; > > } > > > > -static inline int swapcache_prepare(swp_entry_t swp) > > +static inline int swapcache_prepare(swp_entry_t swp, int nr) > > { > > return 0; > > } > > diff --git a/mm/memory.c b/mm/memory.c > > index 833d2cad6eb2..b8675617a5e3 100644 > > --- a/mm/memory.c > > +++ b/mm/memory.c > > @@ -4081,7 +4081,7 @@ vm_fault_t do_swap_page(struct vm_fault *vmf) > > * reusing the same entry. It's undetectable as > > * pte_same() returns true due to entry reuse. > > */ > > - if (swapcache_prepare(entry)) { > > + if (swapcache_prepare(entry, 1)) { > > /* Relax a bit to prevent rapid repeated = page faults */ > > schedule_timeout_uninterruptible(1); > > goto out; > > @@ -4387,7 +4387,7 @@ vm_fault_t do_swap_page(struct vm_fault *vmf) > > out: > > /* Clear the swap cache pin for direct swapin after PTL unlock */ > > if (need_clear_cache) > > - swapcache_clear(si, entry); > > + swapcache_clear(si, entry, 1); > > if (si) > > put_swap_device(si); > > return ret; > > @@ -4403,7 +4403,7 @@ vm_fault_t do_swap_page(struct vm_fault *vmf) > > folio_put(swapcache); > > } > > if (need_clear_cache) > > - swapcache_clear(si, entry); > > + swapcache_clear(si, entry, 1); > > if (si) > > put_swap_device(si); > > return ret; > > diff --git a/mm/swap.h b/mm/swap.h > > index baa1fa946b34..7c6330561d84 100644 > > --- a/mm/swap.h > > +++ b/mm/swap.h > > @@ -59,7 +59,7 @@ void __delete_from_swap_cache(struct folio *folio, > > void delete_from_swap_cache(struct folio *folio); > > void clear_shadow_from_swap_cache(int type, unsigned long begin, > > unsigned long end); > > -void swapcache_clear(struct swap_info_struct *si, swp_entry_t entry); > > +void swapcache_clear(struct swap_info_struct *si, swp_entry_t entry, i= nt nr); > > struct folio *swap_cache_get_folio(swp_entry_t entry, > > struct vm_area_struct *vma, unsigned long addr); > > struct folio *filemap_get_incore_folio(struct address_space *mapping, > > @@ -120,7 +120,7 @@ static inline int swap_writepage(struct page *p, st= ruct writeback_control *wbc) > > return 0; > > } > > > > -static inline void swapcache_clear(struct swap_info_struct *si, swp_en= try_t entry) > > +static inline void swapcache_clear(struct swap_info_struct *si, swp_en= try_t entry, int nr) > > { > > } > > > > @@ -172,4 +172,5 @@ static inline unsigned int folio_swap_flags(struct = folio *folio) > > return 0; > > } > > #endif /* CONFIG_SWAP */ > > + > > NITPICK: Is it necessary to add a blank line here? But I don't think a > new version is necessary if this is the only change needed. No need to add a blank line; it was probably a mistake I made in Vim. > > > #endif /* _MM_SWAP_H */ > > diff --git a/mm/swap_state.c b/mm/swap_state.c > > index a1726e49a5eb..b06f2a054f5a 100644 > > --- a/mm/swap_state.c > > +++ b/mm/swap_state.c > > @@ -477,7 +477,7 @@ struct folio *__read_swap_cache_async(swp_entry_t e= ntry, gfp_t gfp_mask, > > /* > > * Swap entry may have been freed since our caller observ= ed it. > > */ > > - err =3D swapcache_prepare(entry); > > + err =3D swapcache_prepare(entry, 1); > > if (!err) > > break; > > > > diff --git a/mm/swapfile.c b/mm/swapfile.c > > index 5f73a8553371..757d38a86f56 100644 > > --- a/mm/swapfile.c > > +++ b/mm/swapfile.c > > @@ -3363,7 +3363,7 @@ void si_swapinfo(struct sysinfo *val) > > } > > > > /* > > - * Verify that a swap entry is valid and increment its swap map count. > > + * Verify that nr swap entries are valid and increment their swap map = counts. > > * > > * Returns error code in following case. > > * - success -> 0 > > @@ -3373,60 +3373,77 @@ void si_swapinfo(struct sysinfo *val) > > * - swap-cache reference is requested but the entry is not used. -> E= NOENT > > * - swap-mapped reference requested but needs continued swap count. -= > ENOMEM > > */ > > -static int __swap_duplicate(swp_entry_t entry, unsigned char usage) > > +static int __swap_duplicate(swp_entry_t entry, unsigned char usage, in= t nr) > > { > > struct swap_info_struct *p; > > struct swap_cluster_info *ci; > > unsigned long offset; > > unsigned char count; > > unsigned char has_cache; > > - int err; > > + int err, i; > > > > p =3D swp_swap_info(entry); > > > > offset =3D swp_offset(entry); > > + VM_WARN_ON(nr > SWAPFILE_CLUSTER - offset % SWAPFILE_CLUSTER); > > ci =3D lock_cluster_or_swap_info(p, offset); > > > > - count =3D p->swap_map[offset]; > > + err =3D 0; > > + for (i =3D 0; i < nr; i++) { > > + count =3D p->swap_map[offset + i]; > > > > - /* > > - * swapin_readahead() doesn't check if a swap entry is valid, so = the > > - * swap entry could be SWAP_MAP_BAD. Check here with lock held. > > - */ > > - if (unlikely(swap_count(count) =3D=3D SWAP_MAP_BAD)) { > > - err =3D -ENOENT; > > - goto unlock_out; > > - } > > + /* > > + * swapin_readahead() doesn't check if a swap entry is va= lid, so the > > + * swap entry could be SWAP_MAP_BAD. Check here with lock= held. > > + */ > > + if (unlikely(swap_count(count) =3D=3D SWAP_MAP_BAD)) { > > + err =3D -ENOENT; > > + goto unlock_out; > > + } > > > > - has_cache =3D count & SWAP_HAS_CACHE; > > - count &=3D ~SWAP_HAS_CACHE; > > - err =3D 0; > > + has_cache =3D count & SWAP_HAS_CACHE; > > + count &=3D ~SWAP_HAS_CACHE; > > > > - if (usage =3D=3D SWAP_HAS_CACHE) { > > + if (usage =3D=3D SWAP_HAS_CACHE) { > > + /* set SWAP_HAS_CACHE if there is no cache and en= try is used */ > > + if (!has_cache && count) > > + continue; > > + else if (has_cache) /* someone else a= dded cache */ > > + err =3D -EEXIST; > > + else /* no users remai= ning */ > > + err =3D -ENOENT; > > > > - /* set SWAP_HAS_CACHE if there is no cache and entry is u= sed */ > > - if (!has_cache && count) > > - has_cache =3D SWAP_HAS_CACHE; > > - else if (has_cache) /* someone else added cac= he */ > > - err =3D -EEXIST; > > - else /* no users remaining */ > > - err =3D -ENOENT; > > + } else if (count || has_cache) { > > > > - } else if (count || has_cache) { > > + if ((count & ~COUNT_CONTINUED) < SWAP_MAP_MAX) > > + continue; > > + else if ((count & ~COUNT_CONTINUED) > SWAP_MAP_MA= X) > > + err =3D -EINVAL; > > + else if (swap_count_continued(p, offset + i, coun= t)) > > + continue; > > IIUC, this will make the change to swap map directly instead of > verification. If the verification failed for some entry later, the > count will be wrong? Or I missed something? To avoid using a bitmap or a larger stack, we actually verify during the first iteration. This ensures that by the second iteration, we can safely commit the modification. I actually put some words in the changelog :-) To optimize stack usage, we iterate twice in __swap_duplicate(): the first time to verify that all entries are valid, and the second time to apply the modifications to the entries. > > > + else > > + err =3D -ENOMEM; > > + } else > > + err =3D -ENOENT; /* unused swap = entry */ > > > > - if ((count & ~COUNT_CONTINUED) < SWAP_MAP_MAX) > > + if (err) > > + goto unlock_out; > > + } > > + > > + for (i =3D 0; i < nr; i++) { > > + count =3D p->swap_map[offset + i]; > > + has_cache =3D count & SWAP_HAS_CACHE; > > + count &=3D ~SWAP_HAS_CACHE; > > + > > + if (usage =3D=3D SWAP_HAS_CACHE) > > + has_cache =3D SWAP_HAS_CACHE; > > + else if ((count & ~COUNT_CONTINUED) < SWAP_MAP_MAX) > > count +=3D usage; > > - else if ((count & ~COUNT_CONTINUED) > SWAP_MAP_MAX) > > - err =3D -EINVAL; > > - else if (swap_count_continued(p, offset, count)) > > - count =3D COUNT_CONTINUED; > > else > > - err =3D -ENOMEM; > > - } else > > - err =3D -ENOENT; /* unused swap entry */ > > + count =3D COUNT_CONTINUED; > > > > - if (!err) > > - WRITE_ONCE(p->swap_map[offset], count | has_cache); > > + WRITE_ONCE(p->swap_map[offset + i], count | has_cache); > > + } > > > > unlock_out: > > unlock_cluster_or_swap_info(p, ci); > > @@ -3439,7 +3456,7 @@ static int __swap_duplicate(swp_entry_t entry, un= signed char usage) > > */ > > void swap_shmem_alloc(swp_entry_t entry) > > { > > - __swap_duplicate(entry, SWAP_MAP_SHMEM); > > + __swap_duplicate(entry, SWAP_MAP_SHMEM, 1); > > } > > > > /* > > @@ -3453,29 +3470,29 @@ int swap_duplicate(swp_entry_t entry) > > { > > int err =3D 0; > > > > - while (!err && __swap_duplicate(entry, 1) =3D=3D -ENOMEM) > > + while (!err && __swap_duplicate(entry, 1, 1) =3D=3D -ENOMEM) > > err =3D add_swap_count_continuation(entry, GFP_ATOMIC); > > return err; > > } > > > > /* > > - * @entry: swap entry for which we allocate swap cache. > > + * @entry: first swap entry from which we allocate nr swap cache. > > * > > - * Called when allocating swap cache for existing swap entry, > > + * Called when allocating swap cache for existing swap entries, > > * This can return error codes. Returns 0 at success. > > * -EEXIST means there is a swap cache. > > * Note: return code is different from swap_duplicate(). > > */ > > -int swapcache_prepare(swp_entry_t entry) > > +int swapcache_prepare(swp_entry_t entry, int nr) > > { > > - return __swap_duplicate(entry, SWAP_HAS_CACHE); > > + return __swap_duplicate(entry, SWAP_HAS_CACHE, nr); > > } > > > > -void swapcache_clear(struct swap_info_struct *si, swp_entry_t entry) > > +void swapcache_clear(struct swap_info_struct *si, swp_entry_t entry, i= nt nr) > > { > > unsigned long offset =3D swp_offset(entry); > > > > - cluster_swap_free_nr(si, offset, 1, SWAP_HAS_CACHE); > > + cluster_swap_free_nr(si, offset, nr, SWAP_HAS_CACHE); > > } > > > > struct swap_info_struct *swp_swap_info(swp_entry_t entry) > > -- > Best Regards, > Huang, Ying Thanks Barry