diff options
author | Mateusz Guzik <mjg@FreeBSD.org> | 2020-03-08 00:23:36 +0000 |
---|---|---|
committer | Mateusz Guzik <mjg@FreeBSD.org> | 2020-03-08 00:23:36 +0000 |
commit | d2222aa0e949cbab3c322b4c2956130acb01e7c2 (patch) | |
tree | 36ad02fca88ba5468f66aeb58013dbdfe23bc9a0 /sys/sys/filedesc.h | |
parent | a6924f5db3cba5306b316b813094753841c5e6ba (diff) | |
download | src-d2222aa0e949cbab3c322b4c2956130acb01e7c2.tar.gz src-d2222aa0e949cbab3c322b4c2956130acb01e7c2.zip |
fd: use smr for managing struct pwd
This has a side effect of eliminating filedesc slock/sunlock during path
lookup, which in turn removes contention vs concurrent modifications to the fd
table.
Reviewed by: markj, kib
Differential Revision: https://reviews.freebsd.org/D23889
Notes
Notes:
svn path=/head/; revision=358734
Diffstat (limited to 'sys/sys/filedesc.h')
-rw-r--r-- | sys/sys/filedesc.h | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h index 116649757de4..aa0a5770630f 100644 --- a/sys/sys/filedesc.h +++ b/sys/sys/filedesc.h @@ -42,6 +42,8 @@ #include <sys/priority.h> #include <sys/seqc.h> #include <sys/sx.h> +#include <sys/_smr.h> +#include <sys/smr_types.h> #include <machine/_limits.h> @@ -76,16 +78,23 @@ struct fdescenttbl { */ #define NDSLOTTYPE u_long +/* + * This struct is copy-on-write and allocated from an SMR zone. + * All fields are constant after initialization apart from the reference count. + * + * Check pwd_* routines for usage. + */ struct pwd { volatile u_int pwd_refcount; struct vnode *pwd_cdir; /* current directory */ struct vnode *pwd_rdir; /* root directory */ struct vnode *pwd_jdir; /* jail root directory */ }; +typedef SMR_POINTER(struct pwd *) smrpwd_t; struct filedesc { struct fdescenttbl *fd_files; /* open files table */ - struct pwd *fd_pwd; /* directories */ + smrpwd_t fd_pwd; /* directories */ NDSLOTTYPE *fd_map; /* bitmap of free fds */ int fd_lastfile; /* high-water mark of fd_ofiles */ int fd_freefile; /* approx. next free file */ @@ -141,6 +150,38 @@ struct filedesc_to_leader { SX_NOTRECURSED) #define FILEDESC_UNLOCK_ASSERT(fdp) sx_assert(&(fdp)->fd_sx, SX_UNLOCKED) +#define FILEDESC_LOCKED_LOAD_PWD(fdp) ({ \ + struct filedesc *_fdp = (fdp); \ + struct pwd *_pwd; \ + _pwd = smr_serialized_load(&(_fdp)->fd_pwd, \ + (FILEDESC_LOCK_ASSERT(_fdp), true)); \ + _pwd; \ +}) + +#define FILEDESC_XLOCKED_LOAD_PWD(fdp) ({ \ + struct filedesc *_fdp = (fdp); \ + struct pwd *_pwd; \ + _pwd = smr_serialized_load(&(_fdp)->fd_pwd, \ + (FILEDESC_XLOCK_ASSERT(_fdp), true)); \ + _pwd; \ +}) + +#else + +/* + * Accessor for libkvm et al. + */ +#define FILEDESC_KVM_LOAD_PWD(fdp) ({ \ + struct filedesc *_fdp = (fdp); \ + struct pwd *_pwd; \ + _pwd = smr_kvm_load(&(_fdp)->fd_pwd); \ + _pwd; \ +}) + +#endif + +#ifdef _KERNEL + /* Operation types for kern_dup(). */ enum { FDDUP_NORMAL, /* dup() behavior. */ @@ -265,8 +306,8 @@ static inline void pwd_set(struct filedesc *fdp, struct pwd *newpwd) { - FILEDESC_XLOCK_ASSERT(fdp); - fdp->fd_pwd = newpwd; + smr_serialized_store(&fdp->fd_pwd, newpwd, + (FILEDESC_XLOCK_ASSERT(fdp), true)); } #endif /* _KERNEL */ |