Add a custom VOP_PATHCONF method for fdescfs.
The method handles NAME_MAX and LINK_MAX explicitly. For all other pathconf variables, the method passes the request down to the underlying file descriptor. This requires splitting a kern_fpathconf() syscallsubr routine out of sys_fpathconf(). Also, to avoid lock order reversals with vnode locks, the fdescfs vnode is unlocked around the call to kern_fpathconf(), but with the usecount of the vnode bumped. MFC after: 1 month Sponsored by: Chelsio Communications
This commit is contained in:
parent
78fcf2de93
commit
dd688800e1
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=326986
@ -55,6 +55,8 @@
|
||||
#include <sys/namei.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscallsubr.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/vnode.h>
|
||||
|
||||
#include <fs/fdescfs/fdesc.h>
|
||||
@ -70,6 +72,7 @@ struct mtx fdesc_hashmtx;
|
||||
static vop_getattr_t fdesc_getattr;
|
||||
static vop_lookup_t fdesc_lookup;
|
||||
static vop_open_t fdesc_open;
|
||||
static vop_pathconf_t fdesc_pathconf;
|
||||
static vop_readdir_t fdesc_readdir;
|
||||
static vop_readlink_t fdesc_readlink;
|
||||
static vop_reclaim_t fdesc_reclaim;
|
||||
@ -82,7 +85,7 @@ static struct vop_vector fdesc_vnodeops = {
|
||||
.vop_getattr = fdesc_getattr,
|
||||
.vop_lookup = fdesc_lookup,
|
||||
.vop_open = fdesc_open,
|
||||
.vop_pathconf = vop_stdpathconf,
|
||||
.vop_pathconf = fdesc_pathconf,
|
||||
.vop_readdir = fdesc_readdir,
|
||||
.vop_readlink = fdesc_readlink,
|
||||
.vop_reclaim = fdesc_reclaim,
|
||||
@ -395,6 +398,33 @@ fdesc_open(struct vop_open_args *ap)
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
static int
|
||||
fdesc_pathconf(struct vop_pathconf_args *ap)
|
||||
{
|
||||
struct vnode *vp = ap->a_vp;
|
||||
int error;
|
||||
|
||||
switch (ap->a_name) {
|
||||
case _PC_NAME_MAX:
|
||||
*ap->a_retval = NAME_MAX;
|
||||
return (0);
|
||||
case _PC_LINK_MAX:
|
||||
if (VTOFDESC(vp)->fd_type == Froot)
|
||||
*ap->a_retval = 2;
|
||||
else
|
||||
*ap->a_retval = 1;
|
||||
return (0);
|
||||
default:
|
||||
vref(vp);
|
||||
VOP_UNLOCK(vp, 0);
|
||||
error = kern_fpathconf(curthread, VTOFDESC(vp)->fd_fd,
|
||||
ap->a_name);
|
||||
vn_lock(vp, LK_SHARED | LK_RETRY);
|
||||
vunref(vp);
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
fdesc_getattr(struct vop_getattr_args *ap)
|
||||
{
|
||||
|
@ -1417,27 +1417,34 @@ struct fpathconf_args {
|
||||
/* ARGSUSED */
|
||||
int
|
||||
sys_fpathconf(struct thread *td, struct fpathconf_args *uap)
|
||||
{
|
||||
|
||||
return (kern_fpathconf(td, uap->fd, uap->name));
|
||||
}
|
||||
|
||||
int
|
||||
kern_fpathconf(struct thread *td, int fd, int name)
|
||||
{
|
||||
struct file *fp;
|
||||
struct vnode *vp;
|
||||
cap_rights_t rights;
|
||||
int error;
|
||||
|
||||
error = fget(td, uap->fd, cap_rights_init(&rights, CAP_FPATHCONF), &fp);
|
||||
error = fget(td, fd, cap_rights_init(&rights, CAP_FPATHCONF), &fp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
if (uap->name == _PC_ASYNC_IO) {
|
||||
if (name == _PC_ASYNC_IO) {
|
||||
td->td_retval[0] = _POSIX_ASYNCHRONOUS_IO;
|
||||
goto out;
|
||||
}
|
||||
vp = fp->f_vnode;
|
||||
if (vp != NULL) {
|
||||
vn_lock(vp, LK_SHARED | LK_RETRY);
|
||||
error = VOP_PATHCONF(vp, uap->name, td->td_retval);
|
||||
error = VOP_PATHCONF(vp, name, td->td_retval);
|
||||
VOP_UNLOCK(vp, 0);
|
||||
} else if (fp->f_type == DTYPE_PIPE || fp->f_type == DTYPE_SOCKET) {
|
||||
if (uap->name != _PC_PIPE_BUF) {
|
||||
if (name != _PC_PIPE_BUF) {
|
||||
error = EINVAL;
|
||||
} else {
|
||||
td->td_retval[0] = PIPE_BUF;
|
||||
|
@ -111,6 +111,7 @@ int kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg);
|
||||
int kern_fcntl_freebsd(struct thread *td, int fd, int cmd, long arg);
|
||||
int kern_fhstat(struct thread *td, fhandle_t fh, struct stat *buf);
|
||||
int kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf);
|
||||
int kern_fpathconf(struct thread *td, int fd, int name);
|
||||
int kern_fstat(struct thread *td, int fd, struct stat *sbp);
|
||||
int kern_fstatfs(struct thread *td, int fd, struct statfs *buf);
|
||||
int kern_fsync(struct thread *td, int fd, bool fullsync);
|
||||
|
Loading…
Reference in New Issue
Block a user