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; }