Re: proposed libc interface and man page for statmount(2)

Christian Brauner
2023-11-20T15:38:11Z

On Mon, Nov 20, 2023 at 12:55:17PM +0100, Miklos Szeredi wrote:
> 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?

Sure. We can also add a size argument to struct mnt_id_req then you can
version it by size and extend it easily later (see sched_{g,s}etattr()
that do similar things):

struct mnt_id_req {
__u32 size;
__u64 mnt_id;
__u64 request_mask;
union {
__u64 request_mask;
__u64 last_mnt_id;
};
};

foo(struct mnt_id_req __user *ureq)
{
u32 size;
struct mnt_id_req kreq;

ret = get_user(size, &ureq->size);
if (ret)
return ret;

if (size < MNT_ID_REQ_SIZE_VER0 || size > PAGE_SIZE)
return -EINVAL;

ret = copy_struct_from_user(&kreq, sizeof(kreq), ureq, size);
if (ret)
return ret;
}