From: Andrei Tatar Date: Wed, 25 Sep 2024 15:30:36 +0000 (+0200) Subject: lib/posix-fdtab: Allow named files & partial open X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=5bee2af2ef9befd6a860158ec26be8c1c434915e;p=unikraft%2Funikraft.git lib/posix-fdtab: Allow named files & partial open This change expands the fdtab API, separating the action of creating a new open file description with that of associating it with an fd. This allows callers to perform additional initialization on the open file description before the fd goes live. One notable such init is filling in the `name` field of the ofile, which the API additions now support and take care to allocate space for. It was a conscious decision to not mandate that the fdtab fill in the name itself, as drivers may construct names in any manner of ways other than having a string on hand. Thus, to prevent a redundant memcpy, a driver can choose to fill in the field itself. Signed-off-by: Andrei Tatar Approved-by: Sergiu Moga Reviewed-by: Sergiu Moga GitHub-Closes: #1592 --- diff --git a/lib/posix-fdtab/fdtab.c b/lib/posix-fdtab/fdtab.c index 1a34e8f31..6a59b96fc 100644 --- a/lib/posix-fdtab/fdtab.c +++ b/lib/posix-fdtab/fdtab.c @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -130,12 +131,17 @@ static inline struct fdval fdtab_decode(void *p) /* struct uk_ofile allocation & refcounting */ static inline struct uk_ofile *ofile_new(struct uk_fdtab *tab, const struct uk_file *f, - unsigned int mode) + unsigned int mode, + size_t len) { - struct uk_ofile *of = uk_malloc(tab->alloc, sizeof(*of)); + struct uk_ofile *of; - if (of) + of = uk_malloc(tab->alloc, UKFD_OFILE_SIZE(len)); + if (of) { + if (len) + mode |= UKFD_O_NAMED; uk_ofile_init(of, f, mode); + } return of; } static inline void ofile_del(struct uk_fdtab *tab, struct uk_ofile *of) @@ -187,30 +193,57 @@ void file_rel(struct uk_fdtab *tab, void *p, int flags __maybe_unused) /* Ops */ -int uk_fdtab_open(const struct uk_file *f, unsigned int mode) +struct uk_ofile *uk_fdtab_new_desc(const struct uk_file *f, unsigned int mode, + size_t len) +{ + struct uk_ofile *of; + + of = ofile_new(active_fdtab, f, mode & ~O_CLOEXEC, len); + if (of) + uk_file_acquire(f); + return of; +} + +int uk_fdtab_open_desc(struct uk_ofile *of, unsigned int mode) +{ + int fd; + const void *entry = fdtab_encode(of, + (mode & O_CLOEXEC) ? UK_FDTAB_CLOEXEC : 0); + + fd = uk_fmap_put(&active_fdtab->fmap, entry, 0); + if (unlikely(fd >= UK_FDTAB_SIZE)) + return -ENFILE; + return fd; +} + +int uk_fdtab_open_named(const struct uk_file *f, unsigned int mode, + const char *name, size_t len) { struct uk_ofile *of; - int flags; - const void *entry; int fd; UK_ASSERT(f); + if (!name) + len = 0; - of = ofile_new(active_fdtab, f, mode & ~O_CLOEXEC); - if (!of) + of = uk_fdtab_new_desc(f, mode, len); + if (unlikely(!of)) return -ENOMEM; - uk_file_acquire(f); + if (len) { + memcpy(of->name, name, len); + of->name[len] = 0; + } + /* Place the file in fdtab */ - flags = (mode & O_CLOEXEC) ? UK_FDTAB_CLOEXEC : 0; - entry = fdtab_encode(of, flags); - fd = uk_fmap_put(&active_fdtab->fmap, entry, 0); - if (fd >= UK_FDTAB_SIZE) - goto err_out; + fd = uk_fdtab_open_desc(of, mode); + if (unlikely(fd < 0)) + ofile_rel(active_fdtab, of); return fd; -err_out: - /* Release open file & file ref */ - ofile_rel(active_fdtab, of); - return -ENFILE; +} + +int uk_fdtab_open(const struct uk_file *f, unsigned int mode) +{ + return uk_fdtab_open_named(f, mode, NULL, 0); } int uk_fdtab_setflags(int fd, int flags) diff --git a/lib/posix-fdtab/include/uk/posix-fdtab.h b/lib/posix-fdtab/include/uk/posix-fdtab.h index d7a74d551..3cc064e90 100644 --- a/lib/posix-fdtab/include/uk/posix-fdtab.h +++ b/lib/posix-fdtab/include/uk/posix-fdtab.h @@ -29,6 +29,68 @@ */ int uk_fdtab_open(const struct uk_file *f, unsigned int mode); +/** + * Open the file `f` with `mode` and `name` of length `len` and associate it + * with a file descriptor. + * + * The lifetime of `f` must cover the entirety of this function call. + * + * @param f + * File to open + * @param mode + * Mode flags to apply on the new open file description + * @param name + * If not NULL, a copy will become the new open file description's name + * @param len + * If name is supplied, the length of the string contained in name + * @return + * The newly allocated file descriptor. + */ +int uk_fdtab_open_named(const struct uk_file *f, unsigned int mode, + const char *name, size_t len); + +/** + * Create a new open file description for file `f` with `mode` and optional + * name, without associating it with a file descriptor. + * + * The caller is responsible for filling in the .name field of returned open + * file descriptions before use. + * The returned open file description must be released with `uk_fdtab_ret` when + * caller is finished with it. + * Open file descriptions created in this way may be used as-is, or later + * associated with an fd with `uk_fdtab_open_desc`. + * + * @param f + * File to open + * @param mode + * Mode flags to apply on the new open file description + * @param len + * If > 0, allocate space for a file name of length `len` (excluding NUL) + * @return + * The new open file description, or NULL if no memory is available + */ +struct uk_ofile *uk_fdtab_new_desc(const struct uk_file *f, unsigned int mode, + size_t len); + +/** + * Associate a file descriptor to an existing open file description. + * + * This call consumes the `of` reference. The caller MUST NOT use or release + * `of` after this call returns successfully. + * In case of error, the reference is left untouched. + * The open file description must have been opened by this fdtab, through either + * `uk_fdtab_new_desc` or `uk_fdtab_open*`. + * + * @param of + * Open file description to associate fd with + * @param mode + * If contains O_CLOEXEC, the opened fd will be close-on-exec + * @return + * >= 0: The newly allocated file descriptor + * < 0: Negative errno + */ +int uk_fdtab_open_desc(struct uk_ofile *of, unsigned int mode); + /** * Gets the open file description associated with descriptor `fd`. *