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 089B0C3600C for ; Thu, 3 Apr 2025 20:39:36 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id BE25D280004; Thu, 3 Apr 2025 16:39:35 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id B9173280001; Thu, 3 Apr 2025 16:39:35 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id A5BD5280004; Thu, 3 Apr 2025 16:39:35 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0010.hostedemail.com [216.40.44.10]) by kanga.kvack.org (Postfix) with ESMTP id 844AF280001 for ; Thu, 3 Apr 2025 16:39:35 -0400 (EDT) Received: from smtpin04.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay02.hostedemail.com (Postfix) with ESMTP id 941F312124F for ; Thu, 3 Apr 2025 20:39:35 +0000 (UTC) X-FDA: 83293898310.04.9867689 Received: from mail-qt1-f174.google.com (mail-qt1-f174.google.com [209.85.160.174]) by imf29.hostedemail.com (Postfix) with ESMTP id B40F012000E for ; Thu, 3 Apr 2025 20:39:33 +0000 (UTC) Authentication-Results: imf29.hostedemail.com; dkim=pass header.d=google.com header.s=20230601 header.b=rJJ53RDl; dmarc=pass (policy=reject) header.from=google.com; spf=pass (imf29.hostedemail.com: domain of bgeffon@google.com designates 209.85.160.174 as permitted sender) smtp.mailfrom=bgeffon@google.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1743712773; a=rsa-sha256; cv=none; b=kc78BshLLLGu+HPOM/MP4YM8GCzlsmO6yOQpiORCUeChnxdFGMB1A2Mw99A4GwWIVIul4n ug0SpAfQPtohMl68Vh7pOYJlFbP/sMfAKkRK5F5d0TJhyLqtnVblj46X3jIK8HK+2+oTrS +nuM0xdzXmEO9GKDNL5fbCXsRc4B3nw= ARC-Authentication-Results: i=1; imf29.hostedemail.com; dkim=pass header.d=google.com header.s=20230601 header.b=rJJ53RDl; dmarc=pass (policy=reject) header.from=google.com; spf=pass (imf29.hostedemail.com: domain of bgeffon@google.com designates 209.85.160.174 as permitted sender) smtp.mailfrom=bgeffon@google.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1743712773; 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: in-reply-to:in-reply-to:references:references:dkim-signature; bh=9gzKoe90ZfM4o/7GbmHUnknhoKPfawda3x0icnfdTpk=; b=HQ3Z5+orGB6ovBIZMYeJpd0SGFRSyv2DW8yzyXwzdO3PjPuGRSMixMjY2FFDi6Sh4i6f/N Aq6HfEmmYKhyKdnt0S4yrZPtks7i1zpuKHqdLV4A+iAAW2oY6BAiMsW4lPXb+N9PIKdGlu unEcVyqKc09bnbsuUPR/jskiZcNXimg= Received: by mail-qt1-f174.google.com with SMTP id d75a77b69052e-47666573242so118211cf.0 for ; Thu, 03 Apr 2025 13:39:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1743712773; x=1744317573; darn=kvack.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=9gzKoe90ZfM4o/7GbmHUnknhoKPfawda3x0icnfdTpk=; b=rJJ53RDlGq8wTzMNDkUDe2WanzE5Zr76gZVCrAFf1B/iLoOlvoEtmD06x82vAm8oYu csVf+cn6NX80WBZmeNo1D2bu/mr7CUKDNYD7aWEtXMd2JUmbMh3u5xwBvS2JQP9ftK9X VikXYHdsW9tY85VyR7TQF7IbzjDp0FbkmORjwufurEPn9KK6AIuLTPwmkN77FyOOkX0M pV+0cuQGlSolJfkLWH//M6gOVAx9lC1v3O0HmmOO1b241tLeNaw6xD8O7KX4yLO/KNDO 2GdUB3s/58EoDcQSrLUexun1KWUMuiVrWsfsgYykgcNZ9Q4gz7p2dTYyUecZm3q6pKHb LofA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1743712773; x=1744317573; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=9gzKoe90ZfM4o/7GbmHUnknhoKPfawda3x0icnfdTpk=; b=oUsxWNfF8Rvaw7lQTaSTBEvEfHRHxNSLOq6+nl+FHahusajGt32g/cMcuM3PCXh3rT BTvsdJ/HqR6gHhEhrmvQpqVsH+iCpmhBH+tiHewD0IMMi5P+Te9KMOkBeOqLQ97f4fE1 3nAYAdkaIrs4651dXGVxAXPIPzhjuJfk2PWUOoWph65WMGHA5AMJXwEl/YT6+SjGq5/R eFoMz8usPcsuuCD1HX8tlAk/HNmnyGsNm08OG/AD8VBDubPgwArWUdYluU8aXL3dr5VI f+VCFEVE/bcsoUkjfrIN2BYii5kLCcivococzJbz45lhyUq5MTbK+m3JjIF3+XN5zLaZ ugNg== X-Forwarded-Encrypted: i=1; AJvYcCVKd74zgF1GbucSEHIKCg4dRq/hNiCaXE3et3/MgsfQTbIedmUw6WEubki2SHrgitHdEuDmt/vtbQ==@kvack.org X-Gm-Message-State: AOJu0Yzv31m/EfsM/LCcNBy3HxaFo+pOV9uQ6oWxpvIBhnsXsm23Mnk5 eQMTy23Pv7XKzC8ygmCq6Pwjg0mkwfAuk4sDlatiuBHGlQiJzOqU57w/fDeAig== X-Gm-Gg: ASbGnct812996oFMF5Yr7wjlce0eJcbT8ZLl2QH2wdzHha/AhVokjicZxL/OlkDsAdZ 6cdgFT0YCng2/ZB9ptmNYWq9CaEHveIq3qMn3yef+JwkO/FCTdmosDXWZfslFZVp9MbLZ/ly9iS oI/F4gw7lRUsPxd6Cd+gV4km/C0vBQ3mrwWoh3fhKwljWV580XAhDKrt+5pYSCHpqzT77qHL+PQ P/LnrnnKJb0GvmSNEb6hqfejHbGIX8NRpbNatQPimhKH/CR8mJ93Pz9mRc/H9xPGSxbM7F4VozH 0Bn/Lz+OFVMiCjopg5NnXGDG0gXoT/BYNoXd9/JdYvy4t31MeDJ4VHDHSV4FJKCfMLKWLDBe5Qq aqx8= X-Google-Smtp-Source: AGHT+IHNyJ7vs36NQlUP+/ypTWRilwDQLm735Q4Rad62mUsm20rDamhxTRr00Zy4tOacBCXmKpd0yA== X-Received: by 2002:ac8:59c3:0:b0:476:77be:9102 with SMTP id d75a77b69052e-47926715486mr32371cf.7.1743712772527; Thu, 03 Apr 2025 13:39:32 -0700 (PDT) Received: from google.com (154.75.48.34.bc.googleusercontent.com. [34.48.75.154]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-4791b071b86sm12031601cf.28.2025.04.03.13.39.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Apr 2025 13:39:32 -0700 (PDT) Date: Thu, 3 Apr 2025 20:39:29 +0000 From: Brian Geffon To: Sergey Senozhatsky Cc: Andrew Morton , Richard Chang , Minchan Kim , linux-mm@kvack.org, linux-kernel@vger.kernel.org, sawlani@google.com Subject: Re: [PATCHv2] zram: modernize writeback interface Message-ID: References: <20250327015818.4148660-1-senozhatsky@chromium.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20250327015818.4148660-1-senozhatsky@chromium.org> X-Rspamd-Server: rspam04 X-Rspamd-Queue-Id: B40F012000E X-Stat-Signature: ct1to9x989948sgybbdyirm4u6a9sx4m X-Rspam-User: X-HE-Tag: 1743712773-883559 X-HE-Meta: U2FsdGVkX19NWt2OBS3YrtwDAhbre4DpIWfBJzESGyexmMYWsKTGFA4sA7FG0ckxoPTCwB5Hjq6xokFNtTn9eiRQsR8bcFBZe2mSXTGF1AjFQvHMgorGCt5lNAnCZr5nnR/9AQDyEQHRFaq3qNd3KaMIPcBkjvt/wY30CC/mj589nbgaqyCZsnC6lq3zmCtrgxQK+rFs8EX8OWt2rKYoTN0emFpBoQO2pkPRuZpKf7+NStb6wG4Rxe1xY8xiaJIAlvvkqXA/Fgzfu+JDzuKPEMEtPAZEmcoeFmPIMAlm0hqDpVhx5qYQtki5LyMJkSJiMRkIauHCVVgFOTFl12PzQX/dwD7xPt34dgAxmoDdLD59GAqAW8o4JyAx0d9hyhTcznC2Q+GVOws6v7GST5l5IXw3p81IzdFLmU9LitVKIMOOmNIrD0XXF6EdMTz4HG2RNPFcz5URfYEGXvCt35Plt1kDFN9zHvzdsusvWgH+3aobnl06R/7ylhUAjp5vA/1p6cd4ytQ7lfyWFEpwnVoSAGr6Z1TblOok39uT+x31zL2XvjT0L1dkceSn8ZhuJ0jMgNyLpQ2Zj+H7MKplv7ZLAdOD45hUmsWJGVoyDc0ix/IG5e8vL94LjfqSdFTVEKyhehhTsm3IOb9db05GzRF0oBF8y5yQuIqc0EyWDLdBSI5NlDe68/zPufZ6TIQ7RenWNP0I7mEO/jcrkvB3aKsk+bdEbqYUDOf14TJHlkzqFF1gs2Ns1NcaBYwcqS5p++bI6J1wHNWr7X+weYy86bzdomDpPY0fGfuaqdPus/qqGdjygAn3Frfy78r84I0NW4t8VwqXOr52y0aZUsE7xWF0Pi71LRQ3A7RhnirSlNC3gnuQNYVmREyNqqa41p2+Pg9Itt2c4O+yzY9Q7RL3/4fpA/kitOnn0YxAMNNPUUpjejCsXPY4YpJwL2R6aFa3KYv2BhD015+qNoHWM5t+Y2q 6MCIchDV 3J2TabY13PpGVWkzK/D+Mvt6irseSny6RxjgzRUKBDsa0LrYSh1tMNn1dTXYFYCsNxhvFseoUrsw5xHDL91M3kW+vHO9C9yYYLXTYedGbz6R4V/9pgW1PM962Ij176+lB+BYpJ+7g5vNBLyTqk/qFwB5AJARAbmZ37TF53pUry50xDhJsP9cIyNjtFt+0SrZ7vgLdGvfnXkgh+dQbIBdBNnNVrGcyGZkfNEyIyAc/tC1BwfDZ2JfF+ffQSWWKfddBgJc1wEJtbFUVi26Qe1ApIh6CplXg4VOGTRBuphkX3n/3Vs6RuDeIamSDoLthebYHteVIVaiZ6TvkJP4L2o/mEHEYpMIi53igECyWTuR3VZ7mzRDoBrZXqySYpg== 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 Thu, Mar 27, 2025 at 10:58:09AM +0900, Sergey Senozhatsky wrote: > The writeback interface supports a page_index=N parameter which > performs writeback of the given page. Since we rarely need to > writeback just one single page, the typical use case involves > a number of writeback calls, each performing writeback of one > page: > > echo page_index=100 > zram0/writeback > ... > echo page_index=200 > zram0/writeback > echo page_index=500 > zram0/writeback > ... > echo page_index=700 > zram0/writeback > > One obvious downside of this is that it increases the number of > syscalls. Less obvious, but a significantly more important downside, > is that when given only one page to post-process zram cannot perform > an optimal target selection. This becomes a critical limitation > when writeback_limit is enabled, because under writeback_limit we > want to guarantee the highest memory savings hence we first need > to writeback pages that release the highest amount of zsmalloc pool > memory. > > This patch adds page_indexes=LOW-HIGH parameter to the writeback > interface: > > echo page_indexes=100-200 page_indexes=500-700 > zram0/writeback > > This gives zram a chance to apply an optimal target selection > strategy on each iteration of the writeback loop. > > We also now permit multiple page_index parameters per call (previously > zram would recognize only one page_index) and a mix or single pages and > page ranges: > > echo page_index=42 page_index=99 page_indexes=100-200 \ > page_indexes=500-700 > zram0/writeback > > Apart from that the patch also unifies parameters passing and resembles > other "modern" zram device attributes (e.g. recompression), while the > old interface used a mixed scheme: values-less parameters for mode and > a key=value format for page_index. We still support the "old" value-less > format for compatibility reasons. > > Signed-off-by: Sergey Senozhatsky Reviewed-by: Brian Geffon > --- > Documentation/admin-guide/blockdev/zram.rst | 17 ++ > drivers/block/zram/zram_drv.c | 320 +++++++++++++------- > 2 files changed, 232 insertions(+), 105 deletions(-) > > diff --git a/Documentation/admin-guide/blockdev/zram.rst b/Documentation/admin-guide/blockdev/zram.rst > index 9bdb30901a93..b8d36134a151 100644 > --- a/Documentation/admin-guide/blockdev/zram.rst > +++ b/Documentation/admin-guide/blockdev/zram.rst > @@ -369,6 +369,23 @@ they could write a page index into the interface:: > > echo "page_index=1251" > /sys/block/zramX/writeback > > +In Linux 6.16 this interface underwent some rework. First, the interface > +now supports `key=value` format for all of its parameters (`type=huge_idle`, > +etc.) Second, the support for `page_indexes` was introduced, which specify > +`LOW-HIGH` range (or ranges) of pages to be written-back. This reduces the > +number of syscalls, but more importantly this enables optimal post-processing > +target selection strategy. Usage example:: > + > + echo "type=idle" > /sys/block/zramX/writeback > + echo "page_indexes=1-100 page_indexes=200-300" > \ > + /sys/block/zramX/writeback > + > +We also now permit multiple page_index params per call and a mix of > +single pages and page ranges:: > + > + echo page_index=42 page_index=99 page_indexes=100-200 \ > + page_indexes=500-700 > /sys/block/zramX/writeback > + This new interface will be very useful, thanks for adding it Sergey! > If there are lots of write IO with flash device, potentially, it has > flash wearout problem so that admin needs to design write limitation > to guarantee storage health for entire product life. > diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c > index fda7d8624889..9e8ed1bf308b 100644 > --- a/drivers/block/zram/zram_drv.c > +++ b/drivers/block/zram/zram_drv.c > @@ -734,114 +734,19 @@ static void read_from_bdev_async(struct zram *zram, struct page *page, > submit_bio(bio); > } > > -#define PAGE_WB_SIG "page_index=" > - > -#define PAGE_WRITEBACK 0 > -#define HUGE_WRITEBACK (1<<0) > -#define IDLE_WRITEBACK (1<<1) > -#define INCOMPRESSIBLE_WRITEBACK (1<<2) > - > -static int scan_slots_for_writeback(struct zram *zram, u32 mode, > - unsigned long nr_pages, > - unsigned long index, > - struct zram_pp_ctl *ctl) > +static int zram_writeback_slots(struct zram *zram, struct zram_pp_ctl *ctl) > { > - for (; nr_pages != 0; index++, nr_pages--) { > - bool ok = true; > - > - zram_slot_lock(zram, index); > - if (!zram_allocated(zram, index)) > - goto next; > - > - if (zram_test_flag(zram, index, ZRAM_WB) || > - zram_test_flag(zram, index, ZRAM_SAME)) > - goto next; > - > - if (mode & IDLE_WRITEBACK && > - !zram_test_flag(zram, index, ZRAM_IDLE)) > - goto next; > - if (mode & HUGE_WRITEBACK && > - !zram_test_flag(zram, index, ZRAM_HUGE)) > - goto next; > - if (mode & INCOMPRESSIBLE_WRITEBACK && > - !zram_test_flag(zram, index, ZRAM_INCOMPRESSIBLE)) > - goto next; > - > - ok = place_pp_slot(zram, ctl, index); > -next: > - zram_slot_unlock(zram, index); > - if (!ok) > - break; > - } > - > - return 0; > -} > - > -static ssize_t writeback_store(struct device *dev, > - struct device_attribute *attr, const char *buf, size_t len) > -{ > - struct zram *zram = dev_to_zram(dev); > - unsigned long nr_pages = zram->disksize >> PAGE_SHIFT; > - struct zram_pp_ctl *ctl = NULL; > + unsigned long blk_idx = 0; > + struct page *page = NULL; > struct zram_pp_slot *pps; > - unsigned long index = 0; > - struct bio bio; > struct bio_vec bio_vec; > - struct page *page = NULL; > - ssize_t ret = len; > - int mode, err; > - unsigned long blk_idx = 0; > - > - if (sysfs_streq(buf, "idle")) > - mode = IDLE_WRITEBACK; > - else if (sysfs_streq(buf, "huge")) > - mode = HUGE_WRITEBACK; > - else if (sysfs_streq(buf, "huge_idle")) > - mode = IDLE_WRITEBACK | HUGE_WRITEBACK; > - else if (sysfs_streq(buf, "incompressible")) > - mode = INCOMPRESSIBLE_WRITEBACK; > - else { > - if (strncmp(buf, PAGE_WB_SIG, sizeof(PAGE_WB_SIG) - 1)) > - return -EINVAL; > - > - if (kstrtol(buf + sizeof(PAGE_WB_SIG) - 1, 10, &index) || > - index >= nr_pages) > - return -EINVAL; > - > - nr_pages = 1; > - mode = PAGE_WRITEBACK; > - } > - > - down_read(&zram->init_lock); > - if (!init_done(zram)) { > - ret = -EINVAL; > - goto release_init_lock; > - } > - > - /* Do not permit concurrent post-processing actions. */ > - if (atomic_xchg(&zram->pp_in_progress, 1)) { > - up_read(&zram->init_lock); > - return -EAGAIN; > - } > - > - if (!zram->backing_dev) { > - ret = -ENODEV; > - goto release_init_lock; > - } > + struct bio bio; > + int ret, err; > + u32 index; > > page = alloc_page(GFP_KERNEL); > - if (!page) { > - ret = -ENOMEM; > - goto release_init_lock; > - } > - > - ctl = init_pp_ctl(); > - if (!ctl) { > - ret = -ENOMEM; > - goto release_init_lock; > - } > - > - scan_slots_for_writeback(zram, mode, nr_pages, index, ctl); > + if (!page) > + return -ENOMEM; > > while ((pps = select_pp_slot(ctl))) { > spin_lock(&zram->wb_limit_lock); > @@ -929,10 +834,215 @@ static ssize_t writeback_store(struct device *dev, > > if (blk_idx) > free_block_bdev(zram, blk_idx); > - > -release_init_lock: > if (page) > __free_page(page); > + > + return ret; > +} > + > +#define PAGE_WRITEBACK 0 > +#define HUGE_WRITEBACK (1 << 0) > +#define IDLE_WRITEBACK (1 << 1) > +#define INCOMPRESSIBLE_WRITEBACK (1 << 2) > + > +static int parse_page_index(char *val, unsigned long nr_pages, > + unsigned long *lo, unsigned long *hi) > +{ > + int ret; > + > + ret = kstrtoul(val, 10, lo); > + if (ret) > + return ret; > + *hi = *lo + 1; > + if (*lo >= nr_pages || *hi > nr_pages) I think you can do just: if (*lo >= nr_pages) The *hi > nr_pages check seems superfluous given the assignment directly above this. > + return -ERANGE; > + return 0; > +} > + > +static int parse_page_indexes(char *val, unsigned long nr_pages, > + unsigned long *lo, unsigned long *hi) > +{ > + char *delim; > + int ret; > + > + delim = strchr(val, '-'); > + if (!delim) > + return -EINVAL; > + > + *delim = 0x00; > + ret = kstrtoul(val, 10, lo); > + if (ret) > + return ret; > + if (*lo >= nr_pages) > + return -ERANGE; > + > + ret = kstrtoul(delim + 1, 10, hi); > + if (ret) > + return ret; > + if (*hi >= nr_pages || *lo > *hi) > + return -ERANGE; > + *hi += 1; > + return 0; > +} > + > +static int parse_mode(char *val, u32 *mode) > +{ > + *mode = 0; > + > + if (!strcmp(val, "idle")) > + *mode = IDLE_WRITEBACK; > + if (!strcmp(val, "huge")) > + *mode = HUGE_WRITEBACK; > + if (!strcmp(val, "huge_idle")) > + *mode = IDLE_WRITEBACK | HUGE_WRITEBACK; > + if (!strcmp(val, "incompressible")) > + *mode = INCOMPRESSIBLE_WRITEBACK; > + > + if (*mode == 0) > + return -EINVAL; > + return 0; > +} > + > +static int scan_slots_for_writeback(struct zram *zram, u32 mode, > + unsigned long lo, unsigned long hi, > + struct zram_pp_ctl *ctl) > +{ > + u32 index = lo; > + > + while (index < hi) { > + bool ok = true; > + > + zram_slot_lock(zram, index); > + if (!zram_allocated(zram, index)) > + goto next; > + > + if (zram_test_flag(zram, index, ZRAM_WB) || > + zram_test_flag(zram, index, ZRAM_SAME)) > + goto next; > + > + if (mode & IDLE_WRITEBACK && > + !zram_test_flag(zram, index, ZRAM_IDLE)) > + goto next; > + if (mode & HUGE_WRITEBACK && > + !zram_test_flag(zram, index, ZRAM_HUGE)) > + goto next; > + if (mode & INCOMPRESSIBLE_WRITEBACK && > + !zram_test_flag(zram, index, ZRAM_INCOMPRESSIBLE)) > + goto next; > + > + ok = place_pp_slot(zram, ctl, index); > +next: > + zram_slot_unlock(zram, index); > + if (!ok) > + break; > + index++; > + } > + > + return 0; > +} > + > +static ssize_t writeback_store(struct device *dev, > + struct device_attribute *attr, > + const char *buf, size_t len) > +{ > + struct zram *zram = dev_to_zram(dev); > + u64 nr_pages = zram->disksize >> PAGE_SHIFT; > + unsigned long lo = 0, hi = nr_pages; > + struct zram_pp_ctl *ctl = NULL; > + char *args, *param, *val; > + ssize_t ret = len; > + int err, mode = 0; > + > + down_read(&zram->init_lock); > + if (!init_done(zram)) { > + up_read(&zram->init_lock); > + return -EINVAL; > + } > + > + /* Do not permit concurrent post-processing actions. */ > + if (atomic_xchg(&zram->pp_in_progress, 1)) { > + up_read(&zram->init_lock); > + return -EAGAIN; > + } > + > + if (!zram->backing_dev) { > + ret = -ENODEV; > + goto release_init_lock; > + } > + > + ctl = init_pp_ctl(); > + if (!ctl) { > + ret = -ENOMEM; > + goto release_init_lock; > + } > + > + args = skip_spaces(buf); > + while (*args) { > + args = next_arg(args, ¶m, &val); > + > + /* > + * Workaround to support the old writeback interface. > + * > + * The old writeback interface has a minor inconsistency and > + * requires key=value only for page_index parameter, while the > + * writeback mode is a valueless parameter. > + * > + * This is not the case anymore and now all parameters are > + * required to have values, however, we need to support the > + * legacy writeback interface format so we check if we can > + * recognize a valueless parameter as the (legacy) writeback > + * mode. > + */ > + if (!val || !*val) { > + err = parse_mode(param, &mode); > + if (err) { > + ret = err; > + goto release_init_lock; > + } > + > + scan_slots_for_writeback(zram, mode, lo, hi, ctl); > + break; > + } > + > + if (!strcmp(param, "type")) { > + err = parse_mode(val, &mode); > + if (err) { > + ret = err; > + goto release_init_lock; > + } > + > + scan_slots_for_writeback(zram, mode, lo, hi, ctl); > + break; > + } > + > + if (!strcmp(param, "page_index")) { > + err = parse_page_index(val, nr_pages, &lo, &hi); > + if (err) { > + ret = err; > + goto release_init_lock; > + } > + > + scan_slots_for_writeback(zram, mode, lo, hi, ctl); > + continue; > + } > + > + if (!strcmp(param, "page_indexes")) { > + err = parse_page_indexes(val, nr_pages, &lo, &hi); > + if (err) { > + ret = err; > + goto release_init_lock; > + } > + > + scan_slots_for_writeback(zram, mode, lo, hi, ctl); > + continue; > + } > + } > + > + err = zram_writeback_slots(zram, ctl); > + if (err) > + ret = err; > + > +release_init_lock: > release_pp_ctl(zram, ctl); > atomic_set(&zram->pp_in_progress, 0); > up_read(&zram->init_lock); > -- > 2.49.0.395.g12beb8f557-goog >