diff options
author | Michael Olbrich <m.olbrich@pengutronix.de> | 2020-03-20 16:47:52 +0100 |
---|---|---|
committer | Michael Olbrich <m.olbrich@pengutronix.de> | 2020-03-27 08:32:41 +0100 |
commit | eecbf425c64810f6b535a9c8d7e5c0a0a9d22a97 (patch) | |
tree | db7662c6a17a38bd92afad084b5ed52561675615 /patches | |
parent | 6f18951323894560aee5cab2a18c686215d19576 (diff) | |
download | ptxdist-eecbf425c64810f6b535a9c8d7e5c0a0a9d22a97.tar.gz ptxdist-eecbf425c64810f6b535a9c8d7e5c0a0a9d22a97.tar.xz |
unfs3: add initial support for virtfs
Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
Diffstat (limited to 'patches')
-rw-r--r-- | patches/unfs3-0.9.22/0006-initial-virtfs-support.patch | 685 | ||||
-rw-r--r-- | patches/unfs3-0.9.22/series | 3 |
2 files changed, 687 insertions, 1 deletions
diff --git a/patches/unfs3-0.9.22/0006-initial-virtfs-support.patch b/patches/unfs3-0.9.22/0006-initial-virtfs-support.patch new file mode 100644 index 000000000..e04160d4f --- /dev/null +++ b/patches/unfs3-0.9.22/0006-initial-virtfs-support.patch @@ -0,0 +1,685 @@ +From: Michael Olbrich <m.olbrich@pengutronix.de> +Date: Wed, 30 Jan 2019 08:26:07 +0100 +Subject: [PATCH] initial virtfs support + +This adds support for the 'mapped-file' security model as implemented by +the qemu 9p backend. This works like this: + +For every file or directory 'foo' there is a extra file +'.virtfs_metadata/foo' with contents like this: +--------------------->8------------------------ +virtfs.uid=0 +virtfs.gid=0 +virtfs.mode=16877 +--------------------->8------------------------ +These values replace 'st_uid', 'st_gid' and 'st_mode' from 'struct stat'. +All special files (device nodes, sockets, etc. are replaced by empty files. +In this case there is a special key 'virtfs.rdev' for 'st_rdev'. + +Missing features: + +Multi user setup: +Currently all new files are owned by the user that runs unfsd. +Without virtfs, unfsd switches to the user that makes the request. +With virtfs, the idea is to switch to the owner of the directory so that +each user can own their own subtree. + +Permission checks: +unfsd relies on the underlying filesystem to perform any permission checks. +With virtfs, all files belong to the same user, so this does not work. +So right now all users can do everything. +Note: A unfsd running as a non-root user has basically the same problem. +The only difference is, that it ignores any atempts to change ownership +of files. + +Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de> +--- + Makefile.in | 6 +- + attr.c | 11 ++++ + daemon.c | 7 ++- + daemon.h | 1 + + fh.c | 7 ++- + fh_cache.c | 3 + + locate.c | 2 + + nfs.c | 27 ++++++++- + readdir.c | 9 +-- + user.c | 8 ++- + user.h | 1 + + virtfs.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + virtfs.h | 26 +++++++++ + 13 files changed, 288 insertions(+), 11 deletions(-) + create mode 100644 virtfs.c + create mode 100644 virtfs.h + +diff --git a/Makefile.in b/Makefile.in +index 551aa2232024..84318d038c7b 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -7,9 +7,9 @@ RM = rm -f + MAKE = make + + SOURCES = attr.c daemon.c error.c fd_cache.c fh.c fh_cache.c locate.c \ +- md5.c mount.c nfs.c password.c readdir.c user.c xdr.c winsupport.c ++ md5.c mount.c nfs.c password.c readdir.c user.c xdr.c winsupport.c virtfs.c + OBJS = attr.o daemon.o error.o fd_cache.o fh.o fh_cache.o locate.o \ +- md5.o mount.o nfs.o password.o readdir.o user.o xdr.o winsupport.o ++ md5.o mount.o nfs.o password.o readdir.o user.o xdr.o winsupport.o virtfs.o + CONFOBJ = Config/lib.a + EXTRAOBJ = @EXTRAOBJ@ + LDFLAGS = @LDFLAGS@ @LIBS@ @LEXLIB@ +@@ -152,6 +152,8 @@ unfs3-$(VERSION).tar.gz: + unfs3-$(VERSION)/configure.ac \ + unfs3-$(VERSION)/mount.h \ + unfs3-$(VERSION)/readdir.c \ ++ unfs3-$(VERSION)/virtfs.c \ ++ unfs3-$(VERSION)/virtfs.h \ + unfs3-$(VERSION)/user.h) + rm -rf /tmp/unfs3-make-dist-dir + +diff --git a/attr.c b/attr.c +index 2a13441179a0..4ae09e1f9955 100644 +--- a/attr.c ++++ b/attr.c +@@ -26,6 +26,7 @@ + #include "fh_cache.h" + #include "daemon.h" + #include "user.h" ++#include "virtfs.h" + #include "Config/exports.h" + + /* +@@ -230,6 +231,8 @@ static post_op_attr get_post_ll(const char *path, uint32 dev, uint64 ino, + if (dev != buf.st_dev || ino != buf.st_ino) + return error_attr; + ++ virtfs_fixup(path, &buf); ++ + return get_post_buf(buf, req); + } + +@@ -328,6 +331,10 @@ static nfsstat3 set_attr_unsafe(const char *path, nfs_fh3 nfh, sattr3 new) + if (buf.st_dev != fh->dev || buf.st_ino != fh->ino) + return NFS3ERR_STALE; + ++ res = virtfs_update(path, buf, &new); ++ if (res == -1) ++ return setattr_err(); ++ + /* set file size */ + if (new.size.set_it == TRUE) { + res = backend_truncate(path, new.size.set_size3_u.size); +@@ -418,6 +425,10 @@ nfsstat3 set_attr(const char *path, nfs_fh3 nfh, sattr3 new) + return NFS3ERR_STALE; + } + ++ res = virtfs_update(path, buf, &new); ++ if (res == -1) ++ return setattr_err(); ++ + /* set file size */ + if (new.size.set_it == TRUE) { + res = backend_ftruncate(fd, new.size.set_size3_u.size); +diff --git a/daemon.c b/daemon.c +index fbd901f5e19d..5172b9cca2fa 100644 +--- a/daemon.c ++++ b/daemon.c +@@ -72,6 +72,7 @@ unsigned int opt_mount_port = NFS_PORT; + int opt_singleuser = FALSE; + int opt_brute_force = FALSE; + int opt_testconfig = FALSE; ++int opt_virtfs = FALSE; + struct in_addr opt_bind_addr; + int opt_readable_executables = FALSE; + char *opt_pid_file = NULL; +@@ -202,7 +203,7 @@ static void remove_pid_file(void) + static void parse_options(int argc, char **argv) + { + int opt = 0; +- char *optstring = "bcC:de:hl:m:n:prstTuwi:"; ++ char *optstring = "bcC:de:hl:m:n:prstTuVwi:"; + + while (opt != -1) { + opt = getopt(argc, argv, optstring); +@@ -257,6 +258,7 @@ static void parse_options(int argc, char **argv) + printf + ("\t-r report unreadable executables as readable\n"); + printf("\t-T test exports file and exit\n"); ++ printf("\t-V use virtfs owner/group/mode mappings\n"); + exit(0); + break; + case 'l': +@@ -307,6 +309,9 @@ static void parse_options(int argc, char **argv) + opt_nfs_port = 0; + opt_mount_port = 0; + break; ++ case 'V': ++ opt_virtfs = TRUE; ++ break; + case 'i': + opt_pid_file = optarg; + break; +diff --git a/daemon.h b/daemon.h +index 13b20afd36d3..4bbe2488d53a 100644 +--- a/daemon.h ++++ b/daemon.h +@@ -45,5 +45,6 @@ extern char *opt_cluster_path; + extern int opt_singleuser; + extern int opt_brute_force; + extern int opt_readable_executables; ++extern int opt_virtfs; + + #endif +diff --git a/fh.c b/fh.c +index 46c66cdb0ce5..f76d2d0c70ed 100644 +--- a/fh.c ++++ b/fh.c +@@ -36,6 +36,7 @@ + #include "daemon.h" + #include "fh.h" + #include "backend.h" ++#include "virtfs.h" + #include "Config/exports.h" + + /* +@@ -334,6 +335,7 @@ post_op_fh3 fh_extend_type(nfs_fh3 fh, const char *path, unsigned int type) + return result; + } + ++ virtfs_fixup(path, &buf); + st_cache_valid = TRUE; + st_cache = buf; + +@@ -390,7 +392,7 @@ static int fh_rec(const unfs3_fh_t * fh, int pos, const char *lead, + if (!search) + return FALSE; + +- entry = backend_readdir(search); ++ entry = virtfs_readdir(search); + + while (entry) { + if (strlen(lead) + strlen(entry->d_name) + 1 < NFS_MAXPATHLEN) { +@@ -407,6 +409,7 @@ static int fh_rec(const unfs3_fh_t * fh, int pos, const char *lead, + /* found the object */ + sprintf(result, "%s/%s", lead + 1, entry->d_name); + /* update stat cache */ ++ virtfs_fixup(obj, &buf); + st_cache_valid = TRUE; + st_cache = buf; + matches++; +@@ -430,7 +433,7 @@ static int fh_rec(const unfs3_fh_t * fh, int pos, const char *lead, + } + } + } +- entry = backend_readdir(search); ++ entry = virtfs_readdir(search); + } + + backend_closedir(search); +diff --git a/fh_cache.c b/fh_cache.c +index b41146971d26..148c09f9c788 100644 +--- a/fh_cache.c ++++ b/fh_cache.c +@@ -26,6 +26,7 @@ + #include "Config/exports.h" + #include "readdir.h" + #include "backend.h" ++#include "virtfs.h" + + /* number of entries in fh cache */ + #define CACHE_ENTRIES 4096 +@@ -180,6 +181,7 @@ static char *fh_cache_lookup(uint32 dev, uint64 ino) + /* cache hit, update time on cache entry */ + fh_cache[i].use = fh_cache_next(); + ++ virtfs_fixup(fh_cache[i].path, &buf); + /* update stat cache */ + st_cache_valid = TRUE; + st_cache = buf; +@@ -246,6 +248,7 @@ char *fh_decomp(nfs_fh3 fh) + st_cache.st_blksize = 512; + if (st_cache.st_blocks == 0) + st_cache.st_blocks = 8; ++ virtfs_fixup(result, &st_cache); + } + + st_cache.st_dev = obj->dev; +diff --git a/locate.c b/locate.c +index c5ed21937fa5..2f8c719ca7a2 100644 +--- a/locate.c ++++ b/locate.c +@@ -27,6 +27,7 @@ + #include "nfs.h" + #include "fh.h" + #include "daemon.h" ++#include "virtfs.h" + + /* + * these are the brute-force file searching routines that are used +@@ -69,6 +70,7 @@ static int locate_pfx(const char *pfx, uint32 dev, uint64 ino, char *result) + /* check for matching object */ + if (buf.st_dev == dev && buf.st_ino == ino) { + strcpy(result, path); ++ virtfs_fixup(path, &buf); + st_cache = buf; + st_cache_valid = TRUE; + closedir(search); +diff --git a/nfs.c b/nfs.c +index 5d99bf86c373..708dc3e9ed3b 100644 +--- a/nfs.c ++++ b/nfs.c +@@ -46,6 +46,7 @@ + #include "fd_cache.h" + #include "daemon.h" + #include "backend.h" ++#include "virtfs.h" + #include "Config/exports.h" + #include "Extras/cluster.h" + +@@ -203,6 +204,7 @@ LOOKUP3res *nfsproc3_lookup_3_svc(LOOKUP3args * argp, struct svc_req * rqstp) + if (res == -1) + result.status = lookup_err(); + else { ++ virtfs_fixup(obj, &buf); + if (strcmp(argp->what.name, ".") == 0 || + strcmp(argp->what.name, "..") == 0) { + fh = fh_comp_ptr(obj, rqstp, 0); +@@ -512,6 +514,7 @@ CREATE3res *nfsproc3_create_3_svc(CREATE3args * argp, struct svc_req * rqstp) + } + + if (fd != -1) { ++ virtfs_create(obj, rqstp, S_IFREG | create_mode(new_attr), 0); + /* Successful open */ + res = backend_fstat(fd, &buf); + if (res != -1) { +@@ -605,6 +608,7 @@ MKDIR3res *nfsproc3_mkdir_3_svc(MKDIR3args * argp, struct svc_req * rqstp) + if (res == -1) + result.status = mkdir_err(); + else { ++ virtfs_create(obj, rqstp, S_IFDIR | create_mode(argp->attributes), 0); + result.MKDIR3res_u.resok.obj = + fh_extend_type(argp->where.dir, obj, S_IFDIR); + result.MKDIR3res_u.resok.obj_attributes = get_post_cached(rqstp); +@@ -655,6 +659,7 @@ SYMLINK3res *nfsproc3_symlink_3_svc(SYMLINK3args * argp, + if (res == -1) + result.status = symlink_err(); + else { ++ virtfs_create(obj, rqstp, S_IFLNK | new_mode, 0); + result.SYMLINK3res_u.resok.obj = + fh_extend_type(argp->where.dir, obj, S_IFLNK); + result.SYMLINK3res_u.resok.obj_attributes = +@@ -764,7 +769,20 @@ MKNOD3res *nfsproc3_mknod_3_svc(MKNOD3args * argp, struct svc_req * rqstp) + cluster_create(obj, rqstp, &result.status); + + if (result.status == NFS3_OK) { +- if (argp->what.type == NF3CHR || argp->what.type == NF3BLK) ++ if (opt_virtfs) { ++ int flags = O_RDWR | O_CREAT | O_TRUNC | O_NONBLOCK | O_EXCL; ++ if (argp->what.type == NF3CHR) ++ virtfs_create(obj, rqstp, S_IFCHR | new_mode, dev); ++ else if (argp->what.type == NF3BLK) ++ virtfs_create(obj, rqstp, S_IFBLK | new_mode, dev); ++ else if (argp->what.type == NF3FIFO) ++ virtfs_create(obj, rqstp, S_IFIFO | new_mode, 0); ++ else ++ virtfs_create(obj, rqstp, S_IFSOCK | new_mode, 0); ++ res = backend_open_create(obj, flags, 0666); ++ if (res >= 0) ++ close(res); ++ } else if (argp->what.type == NF3CHR || argp->what.type == NF3BLK) + res = backend_mknod(obj, new_mode, dev); /* device */ + else if (argp->what.type == NF3FIFO) + res = backend_mkfifo(obj, new_mode); /* FIFO */ +@@ -808,6 +826,8 @@ REMOVE3res *nfsproc3_remove_3_svc(REMOVE3args * argp, struct svc_req * rqstp) + res = backend_remove(obj); + if (res == -1) + result.status = remove_err(); ++ else ++ virtfs_remove(obj); + } + + /* overlaps with resfail */ +@@ -835,6 +855,8 @@ RMDIR3res *nfsproc3_rmdir_3_svc(RMDIR3args * argp, struct svc_req * rqstp) + res = backend_rmdir(obj); + if (res == -1) + result.status = rmdir_err(); ++ else ++ virtfs_remove(obj); + } + + /* overlaps with resfail */ +@@ -876,6 +898,8 @@ RENAME3res *nfsproc3_rename_3_svc(RENAME3args * argp, struct svc_req * rqstp) + res = backend_rename(from_obj, to_obj); + if (res == -1) + result.status = rename_err(); ++ else ++ virtfs_rename(from_obj, to_obj); + } + } + +@@ -911,6 +935,7 @@ LINK3res *nfsproc3_link_3_svc(LINK3args * argp, struct svc_req * rqstp) + result.status = exports_compat(old, rqstp); + + if (result.status == NFS3_OK) { ++ virtfs_link(old, obj); + res = backend_link(old, obj); + if (res == -1) + result.status = link_err(); +diff --git a/readdir.c b/readdir.c +index 53b0bfc9e7dd..1ec923dbbf0c 100644 +--- a/readdir.c ++++ b/readdir.c +@@ -25,6 +25,7 @@ + #include "Config/exports.h" + #include "daemon.h" + #include "error.h" ++#include "virtfs.h" + + /* + * maximum number of entries in readdir results +@@ -66,7 +67,7 @@ uint32 directory_hash(const char *path) + return 0; + } + +- while ((this = backend_readdir(search)) != NULL) { ++ while ((this = virtfs_readdir(search)) != NULL) { + hval = fnv1a_32(this->d_name, hval); + } + +@@ -137,12 +138,12 @@ READDIR3res read_dir(const char *path, cookie3 cookie, cookieverf3 verf, + } + } + +- this = backend_readdir(search); ++ this = virtfs_readdir(search); + /* We cannot use telldir()/seekdir(), since the value from telldir() is + not valid after closedir(). */ + for (i = 0; i < cookie; i++) + if (this) +- this = backend_readdir(search); ++ this = virtfs_readdir(search); + + i = 0; + entry[0].name = NULL; +@@ -184,7 +185,7 @@ READDIR3res read_dir(const char *path, cookie3 cookie, cookieverf3 verf, + entry[i - 1].nextentry = NULL; + else { + /* advance to next entry */ +- this = backend_readdir(search); ++ this = virtfs_readdir(search); + } + + i++; +diff --git a/user.c b/user.c +index 241da1ed3160..e412332875e7 100644 +--- a/user.c ++++ b/user.c +@@ -112,7 +112,7 @@ int get_uid(struct svc_req *req) + /* + * return group id of a request + */ +-static int get_gid(struct svc_req *req) ++int get_gid(struct svc_req *req) + { + struct authunix_parms *auth = (void *) req->rq_clntcred; + int squash = squash_gid; +@@ -163,6 +163,9 @@ void switch_to_root() + if (!can_switch) + return; + ++ if (opt_virtfs /* FIXME */) ++ return; ++ + backend_setegid(0); + backend_seteuid(0); + } +@@ -194,6 +197,9 @@ void switch_user(struct svc_req *req) + if (!can_switch) + return; + ++ if (opt_virtfs /* FIXME */) ++ return; ++ + if (opt_singleuser || (backend_getuid() != 0)) { + /* + * have uid/gid functions behave correctly by squashing +diff --git a/user.h b/user.h +index 0109d255eadc..cef5f8370129 100644 +--- a/user.h ++++ b/user.h +@@ -10,6 +10,7 @@ + #include "backend.h" + + int get_uid(struct svc_req *req); ++int get_gid(struct svc_req *req); + + int mangle_uid(int id); + int mangle_gid(int id); +diff --git a/virtfs.c b/virtfs.c +new file mode 100644 +index 000000000000..85d1b2c8a815 +--- /dev/null ++++ b/virtfs.c +@@ -0,0 +1,191 @@ ++/* ++ * UNFS3 low-level filehandle routines ++ * (C) 2020, Pengutronix, Michael Olbrich <m.olbrich@pengutronix.de> ++ * see file LICENSE for license details ++ */ ++ ++#include "config.h" ++ ++#include <dirent.h> ++#include <errno.h> ++#include <fcntl.h> ++#include <libgen.h> ++#include <unistd.h> ++#include <rpc/rpc.h> ++#include <sys/stat.h> ++ ++#include "nfs.h" ++#include "backend.h" ++#include "attr.h" ++#include "daemon.h" ++#include "user.h" ++ ++struct dirent *virtfs_readdir(DIR *dirp) ++{ ++ struct dirent *d = readdir(dirp); ++ if (!opt_virtfs) ++ return d; ++ ++ if (d && (strcmp(d->d_name, ".virtfs_metadata") == 0)) ++ d = readdir(dirp); ++ return d; ++} ++ ++static void virtfs_meta(const char *path, char *dir, char *meta) ++{ ++ char n[PATH_MAX]; ++ char *p; ++ ++ strncpy(dir, path, PATH_MAX); ++ p = dirname(dir); ++ strcat(p, "/.virtfs_metadata/"); ++ strncpy(meta, dir, PATH_MAX); ++ strncpy(n, path, PATH_MAX); ++ strcat(meta, basename(n)); ++} ++ ++void virtfs_fixup(const char *path, backend_statstruct *buf) ++{ ++ char dir[PATH_MAX], meta[PATH_MAX], data[200]; ++ char *tmp, *tok, *p; ++ ssize_t size; ++ int fd; ++ ++ if (!opt_virtfs) ++ return; ++ ++ virtfs_meta(path, dir, meta); ++ fd = backend_open(meta, O_RDONLY); ++ if (fd < 0) ++ return; ++ size = read(fd, data, 100); ++ close(fd); ++ if (size == 200) ++ return; ++ ++ data[size] = '\0'; ++ tok = strtok_r(data, "\n", &tmp); ++ while (tok) { ++ char *tmp2, *key, *value; ++ unsigned long long ivalue; ++ key = strtok_r(tok, "=", &tmp2); ++ value = strtok_r(NULL, "=", &tmp2); ++ if (!value) { ++ fprintf(stderr, "invalid syntax for '%s'\n", key); ++ continue; ++ } ++ ivalue = strtoull(value, NULL, 0); ++ if (!strcmp(key, "virtfs.uid")) ++ buf->st_uid = ivalue; ++ else if (!strcmp(key, "virtfs.gid")) ++ buf->st_gid = ivalue; ++ else if (!strcmp(key, "virtfs.mode")) ++ buf->st_mode = ivalue; ++ else if (!strcmp(key, "virtfs.rdev")) ++ buf->st_rdev = ivalue; ++ else ++ fprintf(stderr, "unkown virtfs key '%s'\n", key); ++ tok = strtok_r(NULL, "\n", &tmp); ++ } ++} ++ ++static int virtfs_write(const char *path, uid_t uid, gid_t gid, mode_t mode, unsigned long long rdev) ++{ ++ char dir[PATH_MAX], meta[PATH_MAX]; ++ int fd; ++ ++ virtfs_meta(path, dir, meta); ++ backend_mkdir(dir, 0755); ++ fd = backend_open(meta, O_WRONLY|O_CREAT|O_TRUNC, 0644); ++ if (fd < 0) ++ return -1; ++ dprintf(fd, "virtfs.uid=%u\nvirtfs.gid=%u\nvirtfs.mode=%u\n", ++ (unsigned)uid, (unsigned)gid, (unsigned)mode); ++ if (rdev) ++ dprintf(fd, "virtfs.rdev=%llu\n", rdev); ++ close(fd); ++ ++ return 0; ++} ++ ++int virtfs_update(const char *path, backend_statstruct buf, sattr3 *new) ++{ ++ uid_t uid, user; ++ gid_t gid; ++ mode_t mode; ++ int ret; ++ ++ if (!opt_virtfs) ++ return 0; ++ ++ virtfs_fixup(path, &buf); ++ ++ if (new->uid.set_it == TRUE) ++ uid = new->uid.set_uid3_u.uid; ++ else ++ uid = buf.st_uid; ++ ++ if (new->gid.set_it == TRUE) ++ gid = new->gid.set_gid3_u.gid; ++ else ++ gid = buf.st_gid; ++ ++ mode = buf.st_mode; ++ if (new->mode.set_it == TRUE) ++ mode = mode & ~0777 | new->mode.set_mode3_u.mode; ++ ++ new->uid.set_it = FALSE; ++ new->gid.set_it = FALSE; ++ new->mode.set_it = FALSE; ++ return virtfs_write(path, uid, gid, mode, buf.st_rdev); ++} ++ ++int virtfs_create(const char *path, struct svc_req *req, mode_t mode, unsigned long long rdev) ++{ ++ struct authunix_parms *auth = (void *) req->rq_clntcred; ++ ++ if (!opt_virtfs) ++ return 0; ++ ++ return virtfs_write(path, auth->aup_uid, auth->aup_gid, mode, rdev); ++} ++ ++void virtfs_remove(const char *path) ++{ ++ char dir[PATH_MAX], meta[PATH_MAX]; ++ ++ if (!opt_virtfs) ++ return; ++ ++ virtfs_meta(path, dir, meta); ++ backend_remove(meta); ++ backend_remove(dir); ++} ++ ++void virtfs_link(const char *src, const char *dst) ++{ ++ char dir[PATH_MAX], src_meta[PATH_MAX], dst_meta[PATH_MAX]; ++ ++ if (!opt_virtfs) ++ return; ++ ++ virtfs_meta(src, dir, src_meta); ++ virtfs_meta(dst, dir, dst_meta); ++ backend_mkdir(dir, 0755); ++ backend_link(src_meta, dst_meta); ++} ++ ++void virtfs_rename(const char *src, const char *dst) ++{ ++ char dir[PATH_MAX], src_meta[PATH_MAX], dst_meta[PATH_MAX]; ++ ++ if (!opt_virtfs) ++ return; ++ ++ virtfs_meta(dst, dir, dst_meta); ++ backend_mkdir(dir, 0755); ++ virtfs_meta(src, dir, src_meta); ++ backend_rename(src_meta, dst_meta); ++ backend_remove(dir); ++} ++ +diff --git a/virtfs.h b/virtfs.h +new file mode 100644 +index 000000000000..5747a3a474a9 +--- /dev/null ++++ b/virtfs.h +@@ -0,0 +1,26 @@ ++/* ++ * UNFS3 low-level filehandle routines ++ * (C) 2020, Pengutronix, Michael Olbrich <m.olbrich@pengutronix.de> ++ * see file LICENSE for license details ++ */ ++ ++#ifndef UNFS3_VIRTFS_H ++#define UNFS3_VIRTFS_H ++ ++#include <dirent.h> ++#include <rpc/rpc.h> ++ ++#include "backend.h" ++ ++struct dirent *virtfs_readdir(DIR *dirp); ++ ++void virtfs_fixup(const char *path, backend_statstruct *buf); ++ ++int virtfs_create(const char *path, struct svc_req *req, mode_t mode, unsigned long long rdev); ++int virtfs_update(const char *path, backend_statstruct buf, sattr3 *attr); ++ ++void virtfs_link(const char *src, const char *dst); ++void virtfs_rename(const char *src, const char *dst); ++void virtfs_remove(const char *path); ++ ++#endif diff --git a/patches/unfs3-0.9.22/series b/patches/unfs3-0.9.22/series index 3257be13d..76b9cb8a5 100644 --- a/patches/unfs3-0.9.22/series +++ b/patches/unfs3-0.9.22/series @@ -5,4 +5,5 @@ 0003-64-bit-fixes-don-t-assume-that-long-is-the-same-size.patch 0004-use-libtirpc-if-found.patch 0005-attr-handle-symlinks-correctly.patch -# b2dd04f9dcebab8f3f969f165662a798 - git-ptx-patches magic +0006-initial-virtfs-support.patch +# a8ac7f2ac55ce5a54417780b74564a66 - git-ptx-patches magic |