Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a generic file store that userspace can save/restore any open file descriptor. These file descriptors can be managed by different applications not just the same user space application. A possible use case is fuse fd passthrough being developed by Alessio Balsini [1] where underlying file system fd can be saved in this file store. Another possible use case is user space application live upgrade and failover (upon panic etc.). Currently during userspace live upgrade and failover, open file descriptors usually have to be saved seprately in a different management process with AF_UNIX sendmsg. But it causes chicken and egg problem and such management process needs to support live upgrade and failover as well. With a generic file store in the kernel, application live upgrade and failover no longer require such management process to hold reference for their open file descriptors. This is an RFC to see if the approach makes sense to upstream and it can be tested with the following C programe. Why FUSE? - Because we are trying to solve FUSE fd passthrough and FUSE daemon live upgrade. Why global IDR rather than per fuse connnection one? - Because for live upgrade new process, we don't have a valid fuse connection in the first place. Missing cleanup method in case user space messes up? - We can limit the number of saved FDs and hey it is RFC ;). [1] https://lore.kernel.org/lkml/20210125153057.3623715-1-balsini@android.com/ -------- /#include <sys/types.h> /#include <sys/stat.h> /#include <fcntl.h> /#include <unistd.h> /#include <stdlib.h> /#include <stdio.h> /#include <stdbool.h> /#include <string.h> /#include <sys/ioctl.h> /#include <stdint.h> /#define FUSE_DEV_IOC_SAVE_FD _IOWR(229, 1, uint32_t) /#define FUSE_DEV_IOC_RESTORE_FD _IOWR(229, 2, uint32_t) /#define FUSE_DEV_IOC_REMOVE_FD _IOW(229, 3, uint32_t) static const char *FUSEDEV = "/dev/fuse"; int fuse_fd; void show_help(char *pname) { fprintf(stdout, "%s [-sh] [-d <id>] [-f <filename>] [-r <id>]\n", pname); fprintf(stdout, "\t-s open <filename>(default foobar) and save its fd\n"); fprintf(stdout, "\t-r <id> restore fd identified by id\n"); fprintf(stdout, "\t-f <filename> set filename to save\n"); fprintf(stdout, "\t-d <id> delete id identified by id\n"); fprintf(stdout, "\t-h show this help\n"); } int open_save_fd(char *name) { int fd; fd = open(name, O_RDWR | O_CREAT, 0666); if (fd < 0) return fd; if (ioctl(fuse_fd, FUSE_DEV_IOC_SAVE_FD, &fd) < 0) return -1; return fd; } int restore_fd(int id) { if (ioctl(fuse_fd, FUSE_DEV_IOC_RESTORE_FD, &id) < 0) return -1; return id; } int delete_fd(int id) { return ioctl(fuse_fd, FUSE_DEV_IOC_REMOVE_FD, &id); } int read_file(int fd) { char buf[1024]; int ret; lseek(fd, 0, SEEK_SET); memset(buf, 0, sizeof(buf)); fprintf(stdout, "file content:\n"); while ((ret = read(fd, buf, sizeof(buf))) > 0) { fprintf(stdout, "%s", buf); } return 0; } int main(int argc, char *argv[]) { bool save = false, restore = false; int fd, opt, ret, id, restored_fd; char *name = "foobar"; fuse_fd = open(FUSEDEV, O_RDWR); if (fuse_fd < 0) { fprintf(stderr, "failed to open fuse device\n"); return -1; } while ((opt = getopt(argc, argv, "shd:f:r:")) != -1) { switch (opt) { case 's': save = true; break; case 'r': id = atoi(optarg); restored_fd = restore_fd(id); if (restored_fd < 0) fprintf(stderr, "failed to restore fd with id %d\n", id); else fprintf(stdout, "restored file fd %d with id %d\n", restored_fd, id); restore = true; break; case 'd': id = atoi(optarg); ret = delete_fd(id); if (ret < 0) fprintf(stderr, "failed to delete fd with id %d\n", id); else fprintf(stdout, "deleted file id %d\n", id); case 'f': name = strdup(optarg); break; case 'h': default: show_help(argv[0]); return 0; } } if (save) { ret = open_save_fd(name); if (ret < 0) fprintf(stderr, "failed to open save fd with filename %s\n", name); else fprintf(stdout, "saved file id %d\n", ret); } if (restore && restored_fd > 0) { ret = read_file(restored_fd); if (ret < 0) fprintf(stderr, "failed to read_file with fd %d\n", restored_fd); } return 0; } Signed-off-by: Peng Tao <tao.peng@linux.alibaba.com>
- Loading branch information