nfs: Support multiple mounts with the same path basename

NFSv4 mounts NFS file systems to the flat root of a pseudo file
system. This change allow the same basename to be used.
This commit is contained in:
Chris Johns 2023-07-21 14:40:16 +10:00
parent 1dfdee9ce9
commit f55a3dd32f
2 changed files with 37 additions and 26 deletions

View File

@ -830,8 +830,10 @@ rtems_nfs_initialize(
rtems_filesystem_mount_table_entry_t *mt_entry, const void *data) rtems_filesystem_mount_table_entry_t *mt_entry, const void *data)
{ {
struct nfs_args args; struct nfs_args args;
const char *fspath = NULL; static int mount_counter;
char fspath[NAME_MAX + 1];
char *at; char *at;
int len;
int error; int error;
if (RTEMS_DEBUG) { if (RTEMS_DEBUG) {
@ -923,15 +925,30 @@ rtems_nfs_initialize(
rtems_bsd_vfs_mount_init(mt_entry); rtems_bsd_vfs_mount_init(mt_entry);
fspath = mt_entry->target; at = mt_entry->target + strlen(mt_entry->target);
if (*fspath == '/') { len = 0;
++fspath; while (at != mt_entry->target && !rtems_filesystem_is_delimiter(at[-1])) {
at--;
len++;
} }
if (strchr(fspath, '/') != 0) {
/*
* Account for the mount number and leading `/`
*/
if (len >= sizeof(fspath) - (6 + 2)) {
error = EINVAL; error = EINVAL;
goto out; goto out;
} }
/*
* Append a unique number to the end of the path created in
* the FreeBSD root file system. All mounts are in the root
* directory of the root file system and so flat. A user could
* use different mount paths with the same end name. Without
* the counter appended they would clash.
*/
snprintf(fspath, sizeof(fspath), "/%s-%d", at, mount_counter++);
if (getnfsargs(mt_entry->dev, &args) < 0) { if (getnfsargs(mt_entry->dev, &args) < 0) {
if (RTEMS_DEBUG) if (RTEMS_DEBUG)
printf( printf(
@ -949,7 +966,7 @@ rtems_nfs_initialize(
* export then find the vnode and hold it. Make sure we find the root * export then find the vnode and hold it. Make sure we find the root
* node of the NFS share and the not the root file system's mount node. * node of the NFS share and the not the root file system's mount node.
*/ */
error = rtems_bsd_rootfs_mkdir(fspath); error = rtems_bsd_rootfs_mkdir(fspath + 1);
if (error == 0) { if (error == 0) {
struct addrinfo *ai; struct addrinfo *ai;
enum tryret tryret; enum tryret tryret;

View File

@ -889,6 +889,7 @@ rtems_bsd_sysgen_open_node(
struct vnode *cdir; struct vnode *cdir;
struct vnode *rdir; struct vnode *rdir;
const char *opath; const char *opath;
rtems_filesystem_location_info_t *rootloc;
int opathlen; int opathlen;
int fd; int fd;
int error; int error;
@ -902,6 +903,8 @@ rtems_bsd_sysgen_open_node(
fdp = td->td_proc->p_fd; fdp = td->td_proc->p_fd;
rootloc = &iop->pathinfo.mt_entry->mt_fs_root->location;
/* /*
* There is no easy or clean means to open a vnode and follow the * There is no easy or clean means to open a vnode and follow the
* POSIX open semantics. See `kern_openat`. You can open a vnode but * POSIX open semantics. See `kern_openat`. You can open a vnode but
@ -912,12 +915,17 @@ rtems_bsd_sysgen_open_node(
* parent directory vnode to position ourselves in the parent * parent directory vnode to position ourselves in the parent
* directory. The pathloc vnode points to the '.' or '..' directory. * directory. The pathloc vnode points to the '.' or '..' directory.
*/ */
if (rtems_bsd_libio_loc_to_vnode(&iop->pathinfo) ==
rtems_bsd_libio_loc_to_vnode(rootloc)) {
opath = ".";
} else {
opath = path + strlen(path); opath = path + strlen(path);
opathlen = 0; opathlen = 0;
while (opath != path && !rtems_filesystem_is_delimiter(opath[-1])) { while (opath != path && !rtems_filesystem_is_delimiter(opath[-1])) {
opath--; opath--;
opathlen++; opathlen++;
} }
}
if (rtems_filesystem_is_current_directory(opath, opathlen) || if (rtems_filesystem_is_current_directory(opath, opathlen) ||
rtems_filesystem_is_parent_directory(opath, opathlen)) { rtems_filesystem_is_parent_directory(opath, opathlen)) {
if (((oflag + 1) & _FWRITE) == _FWRITE) { if (((oflag + 1) & _FWRITE) == _FWRITE) {
@ -929,8 +937,6 @@ rtems_bsd_sysgen_open_node(
opath = "."; opath = ".";
cdir = rtems_bsd_libio_loc_to_vnode(&iop->pathinfo); cdir = rtems_bsd_libio_loc_to_vnode(&iop->pathinfo);
} else { } else {
rtems_filesystem_location_info_t *rootloc =
&iop->pathinfo.mt_entry->mt_fs_root->location;
/* /*
* We need the parent directory so open can find the * We need the parent directory so open can find the
* entry. If we are creating the file the pathinfo * entry. If we are creating the file the pathinfo
@ -943,18 +949,6 @@ rtems_bsd_sysgen_open_node(
} }
if (fdp->fd_cdir == NULL) { if (fdp->fd_cdir == NULL) {
cdir = rtems_bsd_libio_loc_to_vnode_dir(rootloc); cdir = rtems_bsd_libio_loc_to_vnode_dir(rootloc);
} else if (rtems_bsd_libio_loc_to_vnode(&iop->pathinfo) ==
rtems_bsd_libio_loc_to_vnode(rootloc)) {
/*
* If this is a directory and this is the root node of
* the mounted file system we need to move up the
* hidden pseudo file system node.
*/
if (isdir) {
cdir = rootvnode;
} else {
cdir = rtems_bsd_libio_loc_to_vnode(rootloc);
}
} }
} }