From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-ej1-x62b.google.com (mail-ej1-x62b.google.com [IPv6:2a00:1450:4864:20::62b]) by sourceware.org (Postfix) with ESMTPS id 9C9943858D33 for ; Mon, 20 Nov 2023 11:55:26 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 9C9943858D33 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=szeredi.hu Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=szeredi.hu ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 9C9943858D33 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::62b ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1700481329; cv=none; b=LXUogtDcWvX79bb9l0R8rDeYte/uN4dW9sJ4hS86MGA3XL03Nj88C7vyzsnYqAqUQ0/rv2aZGGqPrvtJVJsLGIOnsRsquH/MMDtuEXaOlpLHJ96s3dFLDYZ3c7pHa434rW7kyCiB8KYbGKgpK2R4cZdAIigZ8GETvUG7Y08y4pw= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1700481329; c=relaxed/simple; bh=tCvz5rmOHPQd5JBcrnHL15AouBJe2ZtdW+wqYaZlGec=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=iLL4MT4kcprIQ3LR0MAGZCJV+E6kYcas1cGtUZL7HXMMFEhkJuJMJMV7VHWPijMutDntAEA8orvDo3YflG1gXqDDGYTtxIMo8WuebE7m7/FAuxO/zZYB2spK1UO+Y1ZHdrB8LQVvir9xHEbYTnAjomTAyTd5DPMrQq7GKS6S4Ao= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-ej1-x62b.google.com with SMTP id a640c23a62f3a-9fa2714e828so264992966b.1 for ; Mon, 20 Nov 2023 03:55:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=szeredi.hu; s=google; t=1700481325; x=1701086125; darn=sourceware.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=z3vsvlrcGrEGBTtA0AP5aKKnvlKyJhXO+Stjh5B7q6E=; b=Ep0v8Xc22JeBUibahdIiRhcehq8r7Jl2uOniTJon5Xjv2iKW7khJYHxOJ2EXNA9stD pAQk60Gx4hUeYoXDQ1CqTT+GT6VMN3MIBt8Ye39jM4qwUZn45WFdkHJNI/qW4hH3GUvM JV9+lR4NWLr36a0JxpYrOcAIsCat48IMHT85c= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700481325; x=1701086125; 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=z3vsvlrcGrEGBTtA0AP5aKKnvlKyJhXO+Stjh5B7q6E=; b=Z+2mLdrIY4PvqhapEbXVi4TJUYoaN4r4x2TmKYHz3NU5wDE2ctq1Xg0RFkjqtYaPLX QIZza7XVJkIL4Z7WSggOMKm5v9xV6cohpmiZ2P/Z4DiWU1SdGruhTjmT5CIhLXmVwT6/ hjOuuf5nxj4nCUy5Pdr+jXOpQDQ8/KVtWhcdnlfDDV+2JAC5Biq1dc6OJZaFUZzDWXpq IZcx5OmaO0CinZ2Xe4zz5BpkWPRjUI8MxwsNg+quNHX8my8+Hl3qUqDt7nnJGQazEcXu q6kglTozXNj7RpkzDcfsEtMqASShJj3Rk+NfuqXNYLdkFrRnDohzk4t/9V79EAPLpeQm wkWg== X-Gm-Message-State: AOJu0YwwTn9GkTwjSRQYGi68oqWCz+2/OJstiIKrlqrJnZMWclwb77fg O7GSK3ybwellCa7/aRbe5oowaQ== X-Google-Smtp-Source: AGHT+IHRK6NFPlWpLc2M9qeLs7fvIv/FO+aj2+Cw07fK4WT3xRJbJ7ajVhN90FoD6icsE0y5IMV/Fw== X-Received: by 2002:a17:906:4a50:b0:9c2:a072:78bf with SMTP id a16-20020a1709064a5000b009c2a07278bfmr5239895ejv.26.1700481325269; Mon, 20 Nov 2023 03:55:25 -0800 (PST) Received: from maszat.piliscsaba.szeredi.hu (91-82-181-165.pool.digikabel.hu. [91.82.181.165]) by smtp.gmail.com with ESMTPSA id dk26-20020a170906f0da00b009fc0c42098csm1963955ejb.173.2023.11.20.03.55.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 20 Nov 2023 03:55:24 -0800 (PST) Date: Mon, 20 Nov 2023 12:55:17 +0100 From: Miklos Szeredi To: Florian Weimer Cc: libc-alpha@sourceware.org, linux-man , Alejandro Colomar , Linux API , linux-fsdevel@vger.kernel.org, Karel Zak , Ian Kent , David Howells , Christian Brauner , Amir Goldstein , Arnd Bergmann Subject: Re: proposed libc interface and man page for statmount(2) Message-ID: References: <87fs15qvu4.fsf@oldenburg.str.redhat.com> <87leawphcj.fsf@oldenburg.str.redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: X-Spam-Status: No, score=0.3 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_BARRACUDACENTRAL,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On Fri, Nov 17, 2023 at 04:50:25PM +0100, Miklos Szeredi wrote: > I wonder... Is there a reason this shouldn't be done statelessly by > adding an "continue after this ID" argument to listmount(2)? The > caller will just need to pass the last mount ID received in the array > to the next listmount(2) call and iterate until a short count is > returned. No comments so far... maybe more explanation is needed. New signature of listmount() would be: ssize_t listmount(uint64_t mnt_id, uint64_t last_mnt_id, uint64_t *buf, size_t bufsize, unsigned int flags); And the usage would be: for (last = 0; nres == bufsize; last = buf[bufsize-1]) { nres = listmount(parent, last, buf, bufsize, flags); for (i = 0; i < nres; i++) { /* process buf[i] */ } } Here's a kernel patch against the version in Christian's tree. The syscall signature doesn't need changing, since we have a spare u64 in the mnt_id_req for listmount. The major difference is in the order that the mount ID's are listed, which is now strictly increasing. Doing the recursive listing in DFS order is nicer, but I don't think it's important enough. Comments? Thanks, Miklos --- fs/namespace.c | 41 +++++++++++++++++++++++++---------------- include/uapi/linux/mount.h | 5 ++++- 2 files changed, 29 insertions(+), 17 deletions(-) --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1009,7 +1009,7 @@ void mnt_change_mountpoint(struct mount static inline struct mount *node_to_mount(struct rb_node *node) { - return rb_entry(node, struct mount, mnt_node); + return node ? rb_entry(node, struct mount, mnt_node) : NULL; } static void mnt_add_to_ns(struct mnt_namespace *ns, struct mount *mnt) @@ -4960,21 +4960,22 @@ SYSCALL_DEFINE4(statmount, const struct return ret; } -static struct mount *listmnt_first(struct mount *root) +static struct mount *listmnt_next(struct mount *curr) { - return list_first_entry_or_null(&root->mnt_mounts, struct mount, mnt_child); + return node_to_mount(rb_next(&curr->mnt_node)); } -static struct mount *listmnt_next(struct mount *curr, struct mount *root, bool recurse) +static bool is_submount(struct mount *sub, struct mount *mnt) { - if (recurse) - return next_mnt(curr, root); - if (!list_is_head(curr->mnt_child.next, &root->mnt_mounts)) - return list_next_entry(curr, mnt_child); - return NULL; + for (; sub != mnt; sub = sub->mnt_parent) { + if (sub->mnt_parent == sub) + return false; + } + return true; } -static long do_listmount(struct vfsmount *mnt, u64 __user *buf, size_t bufsize, +static long do_listmount(struct vfsmount *mnt, struct mount *last, + u64 __user *buf, size_t bufsize, const struct path *root, unsigned int flags) { struct mount *r, *m = real_mount(mnt); @@ -5000,13 +5001,16 @@ static long do_listmount(struct vfsmount if (err) return err; - for (r = listmnt_first(m); r; r = listmnt_next(r, m, recurse)) { + for (r = last; (r = listmnt_next(r)) != NULL && ctr < bufsize;) { + if (recurse && !is_submount(r, m)) + continue; + if (!recurse && r->mnt_parent != m) + continue; + if (reachable_only && !is_path_reachable(r, r->mnt.mnt_root, root)) continue; - if (ctr >= bufsize) - return -EOVERFLOW; if (put_user(r->mnt_id_unique, buf + ctr)) return -EFAULT; ctr++; @@ -5021,6 +5025,7 @@ SYSCALL_DEFINE4(listmount, const struct { struct mnt_id_req kreq; struct vfsmount *mnt; + struct mount *last; struct path root; u64 mnt_id; long err; @@ -5030,8 +5035,6 @@ SYSCALL_DEFINE4(listmount, const struct if (copy_from_user(&kreq, req, sizeof(kreq))) return -EFAULT; - if (kreq.request_mask != 0) - return -EINVAL; mnt_id = kreq.mnt_id; down_read(&namespace_sem); @@ -5040,13 +5043,19 @@ SYSCALL_DEFINE4(listmount, const struct else mnt = lookup_mnt_in_ns(mnt_id, current->nsproxy->mnt_ns); + if (!kreq.last_mnt_id) { + last = real_mount(mnt); + } else { + last = mnt_find_id_at(current->nsproxy->mnt_ns, kreq.last_mnt_id); + } + err = -ENOENT; if (mnt) { get_fs_root(current->fs, &root); /* Skip unreachable for LSMT_ROOT */ if (mnt_id == LSMT_ROOT && !(flags & LISTMOUNT_UNREACHABLE)) mnt = root.mnt; - err = do_listmount(mnt, buf, bufsize, &root, flags); + err = do_listmount(mnt, last, buf, bufsize, &root, flags); path_put(&root); } up_read(&namespace_sem); --- a/include/uapi/linux/mount.h +++ b/include/uapi/linux/mount.h @@ -178,7 +178,10 @@ struct statmount { struct mnt_id_req { __u64 mnt_id; - __u64 request_mask; + union { + __u64 request_mask; + __u64 last_mnt_id; + }; }; /*