On Sat, Aug 29, 2020 at 08:40:42PM +0100, Al Viro wrote: > On Sat, Aug 29, 2020 at 08:17:51PM +0100, Matthew Wilcox wrote: > > > I probably have the wrong nomenclature for what I'm proposing. > > > > So here's a concrete API. What questions need to be answered? > > > > fd = open("real", O_RDWR); > > > > // fetch stream names > > sfd = open_stream(fd, NULL); > > read(sfd, names, length); > > 1) what does fstat() on sfd return? My strawman answers: - st_dev, st_ino, st_uid, st_gid, st_rdev, st_blksize are those of the containing file - st_mode: S_IFREG | parent & 0777 - st_nlink: 1 - st_size, st_blocks st_atime, st_mtime, st_ctime: as appropriate > 2) what does keeping it open do to underlying file? I don't have a solid answer here. Maybe it keeps a reference count on the underlying inode? Obviously we need to prevent the superblock from disappearing from under it. Maybe it needs to keep a refcount on the struct file it was spawned from. I haven't thought this through yet. > 3) what happens to it if that underlying file is unlinked? Unlinking a file necessarily unlinks all the streams. So the file remains in existance until all fds on it are closed, including all the streams. > 4) what does it do to underlying filesystem? Can it be unmounted? I think I covered that in the earlier answers. > > // create a new anonymous stream > > sfd = open_stream(fd, ""); > > write(sfd, buffer, buflen); > > // name it > > linkat(sfd, NULL, fd, "newstream", AT_EMPTY_PATH); > > Oh, lovely - so linkat() *CAN* get that for dirfd and must somehow tell > it from the normal case. With the semantics entirely unrelated to the normal > one. I'm open to just using a different syscall. link_stream(sfd, "newstream"); And, as you point out below, we need unlink_stream(fd, "stream"); > And on top of everything else, we have > 5) what are the permissions involved? When are they determined, BTW? If you can open a file, you can open its streams. So an O_PATH file descriptor can't be used to open streams. > > close(sfd); > > > > - Stream names are NUL terminated and may contain any other character. > > If you want to put a '/' in a stream name, that's fine, but there's > > no hierarchy. Ditto "//../././../../..//./." It's just a really > > oddly named stream. > > Er... Whatever for? Interoperability. If some other system creates a stream with a '/' in it, I don't want the filesystem to have to convert. Although, at least Windows doesn't permit '/' in stream names [1] [2]. Of course, individual filesystems could reject characters in names that they don't like. [1] https://docs.microsoft.com/en-us/windows/win32/fileio/file-streams [2] https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file > > - linkat() will fail if 'fd' does not match where 'sfd' was created. > > 6) "match" in the above being what, exactly? Referring to a different inode than the one it was created in. Although if we just go with the link_stream() proposal above, then this point is moot.