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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BE61DC678D5 for ; Tue, 7 Mar 2023 23:28:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229895AbjCGX2D (ORCPT ); Tue, 7 Mar 2023 18:28:03 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35956 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229876AbjCGX16 (ORCPT ); Tue, 7 Mar 2023 18:27:58 -0500 Received: from mail-lj1-x22c.google.com (mail-lj1-x22c.google.com [IPv6:2a00:1450:4864:20::22c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6E873CA01 for ; Tue, 7 Mar 2023 15:27:56 -0800 (PST) Received: by mail-lj1-x22c.google.com with SMTP id z5so14884761ljc.8 for ; Tue, 07 Mar 2023 15:27:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; t=1678231675; 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=dgM5UWACpA1ziJGubEWxyksAdshP8CY52eV8GhV8Gkg=; b=TGT2yqt1nWpJRPljNttb9FcVv36E/Jt8A84ByzTR4qfutxQ7fHbpdB+EgF/6Hu8QEA lGav8SrhhYCem9wRNTeicDzl5ewmc3qyFq1vE8KfXRp3zg47pIamj2eOLTILU7cqykpP eIRethLM6K4/tMKQANyi6ZEnJZjZRMB/OCTP+DWXQsvO2zKmMTsPyQD8swSXLVTS2D5g zpu9uzYUHyfgWtbbJ7XEYTACwoPmJeHTPKHV/ad884DyulUXcTRi/oc/IJ8NR/H3zqZs tKa1AESMTbEZ0h1SvjwaE/87vK4azcWvVNgcCANUEXMYEwcMUPSMOuu0EJJvRrTgBIy/ aRPg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1678231675; 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=dgM5UWACpA1ziJGubEWxyksAdshP8CY52eV8GhV8Gkg=; b=Xib6mP721MmydsCFAeHE/ct4Virqnga7yGzyC+cvCdktBZCMfB+6in0Tnt5NLbzLPd S1RW1zQJgJ803YG6lZRQCl98wte9slyTc3syeHn4VIiVEBAIfIdUzarJyVDA0DcbR6RN 7gZu+YS0ClESuoJB79t2xErfvpUYUEoY+Vux39iqP5dEtt+zhlLa2YWeI5Z4rG3/A5kq rdInOhvhHmMINseZf/uxg9/SAs4DDtJzmhDD4sEESOIGb1fuv1fCg7AGjXNAy+NyEtI+ jdEBGcYvkEOhzlNXAp/IQoa1+8TmI5lwjHlXnBQiWg1m/yMg1XsWA7gQ0jB8rMF1axt7 hhlA== X-Gm-Message-State: AO0yUKWo6aihQlQDf0IdcuBRp6YPUr2rK2KWFnMuoTEPDejYqkIKjdp/ WVnk5wgznRal4XnPM412ldMwo9EIkIjc3I39le7xjZG7yinyAOFU2KU= X-Google-Smtp-Source: AK7set9qzhTKfHxML+MgHqsSuJRnPMnUneATXidb0+SUYjXa+h00K/U7lnIkoXpbPJNdsASUF+bM31GH9FkDBDE6CkE= X-Received: by 2002:a05:651c:11c6:b0:295:d460:5a2d with SMTP id z6-20020a05651c11c600b00295d4605a2dmr4907216ljo.2.1678231674431; Tue, 07 Mar 2023 15:27:54 -0800 (PST) MIME-Version: 1.0 References: <20230306225024.264858-1-axelrasmussen@google.com> <20230306225024.264858-4-axelrasmussen@google.com> In-Reply-To: From: Axel Rasmussen Date: Tue, 7 Mar 2023 15:27:17 -0800 Message-ID: Subject: Re: [PATCH v3 3/5] mm: userfaultfd: combine 'mode' and 'wp_copy' arguments To: Peter Xu Cc: Alexander Viro , Andrew Morton , Hugh Dickins , Jan Kara , "Liam R. Howlett" , Matthew Wilcox , Mike Kravetz , Mike Rapoport , Muchun Song , Nadav Amit , Shuah Khan , James Houghton , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-kselftest@vger.kernel.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Mon, Mar 6, 2023 at 5:00=E2=80=AFPM Peter Xu wrote: > > On Mon, Mar 06, 2023 at 02:50:22PM -0800, Axel Rasmussen wrote: > > Many userfaultfd ioctl functions take both a 'mode' and a 'wp_copy' > > argument. In future commits we plan to plumb the flags through to more > > places, so we'd be proliferating the very long argument list even > > further. > > > > Let's take the time to simplify the argument list. Combine the two > > arguments into one - and generalize, so when we add more flags in the > > future, it doesn't imply more function arguments. > > > > Since the modes (copy, zeropage, continue) are mutually exclusive, stor= e > > them as an integer value (0, 1, 2) in the low bits. Place combine-able > > flag bits in the high bits. > > > > This is quite similar to an earlier patch proposed by Nadav Amit > > ("userfaultfd: introduce uffd_flags" - for some reason Lore no longer > > has a copy of the patch). The main difference is that patch only handle= d > > Lore has. :) > > https://lore.kernel.org/all/20220619233449.181323-2-namit@vmware.com > > And btw sorry to review late. > > > flags, whereas this patch *also* combines the "mode" argument into the > > same type to shorten the argument list. > > > > Acked-by: James Houghton > > Signed-off-by: Axel Rasmussen > > Mostly good to me, a few nitpicks below. > > [...] > > > +/* A combined operation mode + behavior flags. */ > > +typedef unsigned int __bitwise uffd_flags_t; > > + > > +/* Mutually exclusive modes of operation. */ > > +enum mfill_atomic_mode { > > + MFILL_ATOMIC_COPY =3D (__force uffd_flags_t) 0, > > + MFILL_ATOMIC_ZEROPAGE =3D (__force uffd_flags_t) 1, > > + MFILL_ATOMIC_CONTINUE =3D (__force uffd_flags_t) 2, > > + NR_MFILL_ATOMIC_MODES, > > }; > > I never used enum like this. I had a feeling that this will enforce > setting the enum entries but would the enforce applied to later > assignments? I'm not sure. > > I had a quick test and actually I found sparse already complains about > calculating the last enum entry: > > ---8<--- > $ cat a.c > typedef unsigned int __attribute__((bitwise)) flags_t; > > enum { > FLAG1 =3D (__attribute__((force)) flags_t) 0, > FLAG_NUM, > }; > > void main(void) > { > uffd_flags_t flags =3D FLAG1; > } > $ sparse a.c > a.c:5:5: error: can't increment the last enum member > ---8<--- > > Maybe just use the simple "#define"s? Agreed, if sparse isn't happy with this then using the force macros is pointless. The enum is valuable because it lets us get the # of modes; assuming we agree that's useful below ... > > > > > +#define MFILL_ATOMIC_MODE_BITS (const_ilog2(NR_MFILL_ATOMIC_MODES - 1)= + 1) > > Here IIUC it should be "const_ilog2(NR_MFILL_ATOMIC_MODES) + 1", but > maybe.. we don't bother and define every bit explicitly? If my reading of const_ilog2's definition is correct, then: const_ilog2(4) =3D 2 const_ilog2(3) =3D 1 const_ilog2(2) =3D 1 For either 3 or 4 modes, we need 2 bits to represent them (0, 1, 2, 3), i.e. we want MFILL_ATOMIC_MODE_BITS =3D 2. I think this is correct as is, because const_ilog2(4 - 1) + 1 =3D 2, and const_ilog2(3 - 1) + 1 =3D 2. In other words, I think const_ilog2 is defined as floor(log2()), whereas what we want is ceil(log2()). The benefit of doing this vs. just doing defines with fixed values is, if we ever added a new mode, we wouldn't have to do bit twiddling and update the mask, flag bits, etc. - it would happen "automatically". I prefer it this way, but I agree it is a matter of opinion / taste. :) If you or others feel strongly this is overcomplicated, I can take the other approach. > > > +#define MFILL_ATOMIC_BIT(nr) ((__force uffd_flags_t) BIT(MFILL_ATOMIC_= MODE_BITS + (nr))) > > +#define MFILL_ATOMIC_MODE_MASK (MFILL_ATOMIC_BIT(0) - 1) > > + > > +/* Flags controlling behavior. */ > > +#define MFILL_ATOMIC_WP MFILL_ATOMIC_BIT(0) > > [...] > > > @@ -312,9 +312,9 @@ static __always_inline ssize_t mfill_atomic_hugetlb= ( > > unsigned long dst_start, > > unsigned long src_start, > > unsigned long len, > > - enum mcopy_atomic_mode mode= , > > - bool wp_copy) > > + uffd_flags_t flags) > > { > > + int mode =3D flags & MFILL_ATOMIC_MODE_MASK; > > struct mm_struct *dst_mm =3D dst_vma->vm_mm; > > int vm_shared =3D dst_vma->vm_flags & VM_SHARED; > > ssize_t err; > > @@ -333,7 +333,7 @@ static __always_inline ssize_t mfill_atomic_hugetlb= ( > > * by THP. Since we can not reliably insert a zero page, this > > * feature is not supported. > > */ > > - if (mode =3D=3D MCOPY_ATOMIC_ZEROPAGE) { > > + if (mode =3D=3D MFILL_ATOMIC_ZEROPAGE) { > > The mode comes from "& MFILL_ATOMIC_MODE_MASK" but it doesn't quickly tel= l > whether there's a shift for the mask. > > Would it look better we just have a helper to fetch the mode? The functi= on > tells that whatever it returns must be the mode: > > if (uffd_flags_get_mode(flags) =3D=3D MFILL_ATOMIC_ZEROPAGE) > > We also avoid quite a few "mode" variables. All the rest bits will be fi= ne > to use "flags & FLAG1" if it's a boolean (so only this "mode" is slightly > tricky). Agreed, this is simpler. I'll make this change. > > What do you think? > > Thanks, > > -- > Peter Xu >