aboutsummaryrefslogtreecommitdiff
path: root/sys/sys/filedesc.h
diff options
context:
space:
mode:
authorMateusz Guzik <mjg@FreeBSD.org>2020-03-08 00:23:36 +0000
committerMateusz Guzik <mjg@FreeBSD.org>2020-03-08 00:23:36 +0000
commitd2222aa0e949cbab3c322b4c2956130acb01e7c2 (patch)
tree36ad02fca88ba5468f66aeb58013dbdfe23bc9a0 /sys/sys/filedesc.h
parenta6924f5db3cba5306b316b813094753841c5e6ba (diff)
downloadsrc-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.h47
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 */