p9fs: implement basic pathconf support
This is needed for various pjdfstest tests which fail with syntax errors if pathconf _PC_NAME_MAX/_PC_PATH_MAX return -1. For NAME_MAX we can use the 9P2000.L Tstatfs call to get namelen from the host. While this could theoretically be different for nested filesystems in the shared mount it is a much better guess than just returning 255. There does not seem to be a way to get the host PATH_MAX, so we just return the conservative kernel default. Found while fixing https://github.com/CTSRD-CHERI/cheribsd/issues/2617. Reviewed by: markj, kib MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D56493
This commit is contained in:
@@ -154,6 +154,7 @@ struct p9fs_session {
|
||||
struct mtx p9fs_mtx; /* mutex used for guarding the chain.*/
|
||||
STAILQ_HEAD( ,p9fs_node) virt_node_list; /* list of p9fs nodes in this session*/
|
||||
struct p9_fid *mnt_fid; /* to save nobody 's fid for unmounting as root user */
|
||||
unsigned int name_max; /* cached max filename length */
|
||||
};
|
||||
|
||||
struct p9fs_mount {
|
||||
|
||||
@@ -37,10 +37,12 @@
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/priv.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/rwlock.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syslimits.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/vmmeter.h>
|
||||
#include <sys/vnode.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_extern.h>
|
||||
@@ -2248,6 +2250,72 @@ p9fs_delayed_setsize(struct vop_delayed_setsize_args *ap)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
p9fs_get_name_max(struct p9fs_node *np)
|
||||
{
|
||||
struct p9fs_session *vses = np->p9fs_ses;
|
||||
struct p9_statfs statfs;
|
||||
struct p9_fid *vfid;
|
||||
unsigned int name_max;
|
||||
int error = 0;
|
||||
|
||||
name_max = atomic_load_int(&vses->name_max);
|
||||
if (name_max != 0)
|
||||
return (name_max);
|
||||
|
||||
P9_DEBUG(VOPS, "%s: querying _PC_NAME_MAX\n", __func__);
|
||||
vfid = p9fs_get_fid(vses->clnt, np, NULL, VFID, -1, &error);
|
||||
if (vfid != NULL) {
|
||||
error = p9_client_statfs(vfid, &statfs);
|
||||
if (error == 0) {
|
||||
/*
|
||||
* Note that this is not strictly correct if you have
|
||||
* nested mounts on the host (e.g. when using qemu with
|
||||
* multidevs=remap), but is a better estimate than just
|
||||
* returning 255.
|
||||
*/
|
||||
name_max = statfs.namelen;
|
||||
}
|
||||
}
|
||||
P9_DEBUG(VOPS, "%s: max_name=%u error=%d\n", __func__, name_max, error);
|
||||
if (error != 0 || name_max == 0) {
|
||||
printf("p9fs: warning: failed to query name_max (error %d), "
|
||||
"using fallback %d\n", error, NAME_MAX);
|
||||
name_max = NAME_MAX; /* fallback and prevent retrying */
|
||||
}
|
||||
atomic_store_int(&vses->name_max, name_max);
|
||||
return (name_max);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return POSIX pathconf information applicable to p9fs filesystems.
|
||||
*/
|
||||
static int
|
||||
p9fs_pathconf(struct vop_pathconf_args *ap)
|
||||
{
|
||||
int error = 0;
|
||||
struct vnode *vp = ap->a_vp;
|
||||
struct p9fs_node *np = P9FS_VTON(vp);
|
||||
|
||||
switch (ap->a_name) {
|
||||
case _PC_NAME_MAX:
|
||||
*ap->a_retval = p9fs_get_name_max(np);
|
||||
break;
|
||||
case _PC_SYMLINK_MAX:
|
||||
case _PC_PATH_MAX:
|
||||
/*
|
||||
* These are conservative estimates, the real value depends on
|
||||
* the host file system.
|
||||
*/
|
||||
*ap->a_retval = MAXPATHLEN;
|
||||
break;
|
||||
default:
|
||||
error = vop_stdpathconf(ap);
|
||||
break;
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
struct vop_vector p9fs_vnops = {
|
||||
.vop_default = &default_vnodeops,
|
||||
.vop_lookup = p9fs_lookup,
|
||||
@@ -2257,6 +2325,7 @@ struct vop_vector p9fs_vnops = {
|
||||
.vop_delayed_setsize = p9fs_delayed_setsize,
|
||||
.vop_getattr = p9fs_getattr_dotl,
|
||||
.vop_setattr = p9fs_setattr_dotl,
|
||||
.vop_pathconf = p9fs_pathconf,
|
||||
.vop_reclaim = p9fs_reclaim,
|
||||
.vop_inactive = p9fs_inactive,
|
||||
.vop_readdir = p9fs_readdir,
|
||||
|
||||
Reference in New Issue
Block a user