Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F103039775
D27488.id80553.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
20 KB
Referenced Files
None
Subscribers
None
D27488.id80553.diff
View Options
Index: sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_znode_impl.h
===================================================================
--- sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_znode_impl.h
+++ sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_znode_impl.h
@@ -52,6 +52,7 @@
#define ZNODE_OS_FIELDS \
struct zfsvfs *z_zfsvfs; \
vnode_t *z_vnode; \
+ char *z_cached_symlink; \
uint64_t z_uid; \
uint64_t z_gid; \
uint64_t z_gen; \
Index: sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops.c
===================================================================
--- sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops.c
+++ sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops.c
@@ -5273,6 +5273,27 @@
}
#endif
+#if __FreeBSD_version >= 1300132
+static int
+zfs_freebsd_fplookup_symlink(struct vop_fplookup_symlink_args *v)
+{
+ vnode_t *vp;
+ znode_t *zp;
+ char *target;
+
+ vp = v->a_vp;
+ zp = VTOZ_SMR(vp);
+ if (__predict_false(zp == NULL)) {
+ return (EAGAIN);
+ }
+ target = atomic_load_ptr(&zp->z_cached_symlink);
+ if (target == NULL) {
+ return (EAGAIN);
+ }
+ return (cache_symlink_resolve(v->a_fpl, target, strlen(target)));
+}
+#endif
+
#ifndef _SYS_SYSPROTO_H_
struct vop_access_args {
struct vnode *a_vp;
@@ -5759,6 +5780,8 @@
struct componentname *cnp = ap->a_cnp;
vattr_t *vap = ap->a_vap;
znode_t *zp = NULL;
+ char *symlink;
+ size_t symlink_len;
int rc;
ASSERT(cnp->cn_flags & SAVENAME);
@@ -5769,8 +5792,18 @@
rc = zfs_symlink(VTOZ(ap->a_dvp), cnp->cn_nameptr, vap,
ap->a_target, &zp, cnp->cn_cred, 0 /* flags */);
- if (rc == 0)
+ if (rc == 0) {
*ap->a_vpp = ZTOV(zp);
+ ASSERT_VOP_ELOCKED(ZTOV(zp), __func__);
+ MPASS(zp->z_cached_symlink == NULL);
+ symlink_len = strlen(ap->a_target);
+ symlink = cache_symlink_alloc(symlink_len, M_WAITOK);
+ if (symlink != NULL) {
+ memcpy(symlink, ap->a_target, symlink_len);
+ atomic_store_rel_ptr((uintptr_t *)&zp->z_cached_symlink,
+ (uintptr_t)symlink);
+ }
+ }
return (rc);
}
@@ -5785,8 +5818,35 @@
static int
zfs_freebsd_readlink(struct vop_readlink_args *ap)
{
-
- return (zfs_readlink(ap->a_vp, ap->a_uio, ap->a_cred, NULL));
+ znode_t *zp = VTOZ(ap->a_vp);
+ struct uio *auio;
+ char *symlink, *base;
+ size_t symlink_len;
+ int error;
+ bool trycache;
+
+ auio = ap->a_uio;
+ trycache = false;
+ if (auio->uio_segflg == UIO_SYSSPACE && auio->uio_iovcnt == 1) {
+ base = auio->uio_iov->iov_base;
+ symlink_len = auio->uio_iov->iov_len;
+ trycache = true;
+ }
+ error = zfs_readlink(ap->a_vp, auio, ap->a_cred, NULL);
+ if (atomic_load_ptr(&zp->z_cached_symlink) != NULL ||
+ error != 0 || !trycache) {
+ return (error);
+ }
+ symlink_len -= auio->uio_resid;
+ symlink = cache_symlink_alloc(symlink_len, M_WAITOK);
+ if (symlink != NULL) {
+ memcpy(symlink, base, symlink_len);
+ if (!atomic_cmpset_rel_ptr((uintptr_t *)&zp->z_cached_symlink,
+ (uintptr_t)NULL, (uintptr_t)symlink)) {
+ cache_symlink_free(symlink);
+ }
+ }
+ return (error);
}
#ifndef _SYS_SYSPROTO_H_
@@ -6532,6 +6592,9 @@
.vop_reclaim = zfs_freebsd_reclaim,
#if __FreeBSD_version >= 1300102
.vop_fplookup_vexec = zfs_freebsd_fplookup_vexec,
+#endif
+#if __FreeBSD_version >= 1300132
+ .vop_fplookup_symlink = zfs_freebsd_fplookup_symlink,
#endif
.vop_access = zfs_freebsd_access,
.vop_allocate = VOP_EINVAL,
@@ -6581,6 +6644,9 @@
.vop_fsync = zfs_freebsd_fsync,
#if __FreeBSD_version >= 1300102
.vop_fplookup_vexec = zfs_freebsd_fplookup_vexec,
+#endif
+#if __FreeBSD_version >= 1300132
+ .vop_fplookup_symlink = zfs_freebsd_fplookup_symlink,
#endif
.vop_access = zfs_freebsd_access,
.vop_getattr = zfs_freebsd_getattr,
@@ -6605,6 +6671,7 @@
#if __FreeBSD_version >= 1300121
.vop_fplookup_vexec = VOP_EAGAIN,
#endif
+ .vop_fplookup_symlink = VOP_EAGAIN,
.vop_access = zfs_freebsd_access,
.vop_inactive = zfs_freebsd_inactive,
.vop_reclaim = zfs_freebsd_reclaim,
Index: sys/contrib/openzfs/module/os/freebsd/zfs/zfs_znode.c
===================================================================
--- sys/contrib/openzfs/module/os/freebsd/zfs/zfs_znode.c
+++ sys/contrib/openzfs/module/os/freebsd/zfs/zfs_znode.c
@@ -447,6 +447,7 @@
zp->z_blksz = blksz;
zp->z_seq = 0x7A4653;
zp->z_sync_cnt = 0;
+ atomic_store_ptr((uintptr_t *)&zp->z_cached_symlink, (uintptr_t)NULL);
vp = ZTOV(zp);
@@ -1240,6 +1241,7 @@
zfs_znode_free(znode_t *zp)
{
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+ char *symlink;
ASSERT(zp->z_sa_hdl == NULL);
zp->z_vnode = NULL;
@@ -1248,6 +1250,11 @@
list_remove(&zfsvfs->z_all_znodes, zp);
zfsvfs->z_nr_znodes--;
mutex_exit(&zfsvfs->z_znodes_lock);
+ symlink = atomic_load_ptr(&zp->z_cached_symlink);
+ if (symlink != NULL) {
+ atomic_store_rel_ptr((uintptr_t *)&zp->z_cached_symlink, (uintptr_t)NULL);
+ cache_symlink_free(symlink);
+ }
if (zp->z_acl_cached) {
zfs_acl_free(zp->z_acl_cached);
Index: sys/fs/deadfs/dead_vnops.c
===================================================================
--- sys/fs/deadfs/dead_vnops.c
+++ sys/fs/deadfs/dead_vnops.c
@@ -80,6 +80,7 @@
.vop_unset_text = dead_unset_text,
.vop_write = dead_write,
.vop_fplookup_vexec = VOP_EOPNOTSUPP,
+ .vop_fplookup_symlink = VOP_EAGAIN,
};
VFS_VOP_VECTOR_REGISTER(dead_vnodeops);
Index: sys/fs/tmpfs/tmpfs.h
===================================================================
--- sys/fs/tmpfs/tmpfs.h
+++ sys/fs/tmpfs/tmpfs.h
@@ -278,7 +278,10 @@
/* Valid when tn_type == VLNK. */
/* The link's target, allocated from a string pool. */
- char * tn_link; /* (c) */
+ struct tn_link {
+ char * tn_link_target; /* (c) */
+ bool tn_link_smr; /* (c) */
+ } tn_link;
/* Valid when tn_type == VREG. */
struct tn_reg {
@@ -301,7 +304,8 @@
#define tn_rdev tn_spec.tn_rdev
#define tn_dir tn_spec.tn_dir
-#define tn_link tn_spec.tn_link
+#define tn_link_target tn_spec.tn_link.tn_link_target
+#define tn_link_smr tn_spec.tn_link.tn_link_smr
#define tn_reg tn_spec.tn_reg
#define tn_fifo tn_spec.tn_fifo
Index: sys/fs/tmpfs/tmpfs_subr.c
===================================================================
--- sys/fs/tmpfs/tmpfs_subr.c
+++ sys/fs/tmpfs/tmpfs_subr.c
@@ -252,6 +252,8 @@
{
struct tmpfs_node *nnode;
vm_object_t obj;
+ char *symlink;
+ bool symlink_smr;
/* If the root directory of the 'tmp' file system is not yet
* allocated, this must be the request to do it. */
@@ -327,9 +329,42 @@
case VLNK:
MPASS(strlen(target) < MAXPATHLEN);
nnode->tn_size = strlen(target);
- nnode->tn_link = malloc(nnode->tn_size, M_TMPFSNAME,
- M_WAITOK);
- memcpy(nnode->tn_link, target, nnode->tn_size);
+
+ symlink = NULL;
+ if (!tmp->tm_nonc) {
+ symlink = cache_symlink_alloc(nnode->tn_size + 1,
+ M_WAITOK | M_ZERO);
+ symlink_smr = true;
+ }
+ if (symlink == NULL) {
+ symlink = malloc(nnode->tn_size + 1, M_TMPFSNAME,
+ M_WAITOK | M_ZERO);
+ symlink_smr = false;
+ }
+ memcpy(symlink, target, nnode->tn_size);
+ /*
+ * Allow safe symlink resolving for lockless lookup.
+ * tmpfs_fplookup_symlink references this comment.
+ *
+ * 1. nnode is not yet visible to the world.
+ * 2. store release of tn_link_smr guarantees that tn_link_target
+ * is set and the buffer it points to fully populated
+ * 3. tn_link_target content is immutable until node destruction,
+ * where the pointer gets set to NULL
+ * 4. tn_link_smr is never changed once set
+ *
+ * As a result anyone obtaining nnode pointer past this point
+ * and issuing a data dependency barrier is is guaranteed to
+ * always see either the correct buffer or NULL. The
+ * tn_link_smr flag may be set to true despite being stale, but
+ * it will never be set incorrectly if the buffer is present.
+ *
+ * Since data dependency barrier is a nop on all supported
+ * architectures, consumers just load the pointer.
+ */
+ atomic_store_ptr((uintptr_t *)&nnode->tn_link_target,
+ (uintptr_t)symlink);
+ atomic_store_rel_char((char *)&nnode->tn_link_smr, symlink_smr);
break;
case VREG:
@@ -382,6 +417,7 @@
bool detach)
{
vm_object_t uobj;
+ char *symlink;
bool last;
TMPFS_MP_ASSERT_LOCKED(tmp);
@@ -417,7 +453,13 @@
break;
case VLNK:
- free(node->tn_link, M_TMPFSNAME);
+ symlink = node->tn_link_target;
+ atomic_store_ptr((uintptr_t *)&node->tn_link_target,
+ (uintptr_t)NULL);
+ if (atomic_load_char(&node->tn_link_smr))
+ cache_symlink_free(symlink);
+ else
+ free(symlink, M_TMPFSNAME);
break;
case VREG:
Index: sys/fs/tmpfs/tmpfs_vnops.c
===================================================================
--- sys/fs/tmpfs/tmpfs_vnops.c
+++ sys/fs/tmpfs/tmpfs_vnops.c
@@ -1443,13 +1443,39 @@
node = VP_TO_TMPFS_NODE(vp);
- error = uiomove(node->tn_link, MIN(node->tn_size, uio->uio_resid),
+ error = uiomove(node->tn_link_target, MIN(node->tn_size, uio->uio_resid),
uio);
tmpfs_set_accessed(VFS_TO_TMPFS(vp->v_mount), node);
return (error);
}
+/*
+ * VOP_FPLOOKUP_SYMLINK routines are subject to special circumstances, see
+ * the comment above cache_fplookup for details.
+ *
+ * Check tmpfs_alloc_node for tmpfs-specific synchronisation notes.
+ */
+static int
+tmpfs_fplookup_symlink(struct vop_fplookup_symlink_args *v)
+{
+ struct vnode *vp;
+ struct tmpfs_node *node;
+ char *symlink;
+
+ vp = v->a_vp;
+ node = VP_TO_TMPFS_NODE_SMR(vp);
+ if (__predict_false(node == NULL))
+ return (EAGAIN);
+ if (!atomic_load_char(&node->tn_link_smr))
+ return (EAGAIN);
+ symlink = atomic_load_ptr(&node->tn_link_target);
+ if (symlink == NULL)
+ return (EAGAIN);
+
+ return (cache_symlink_resolve(v->a_fpl, symlink, node->tn_size));
+}
+
static int
tmpfs_inactive(struct vop_inactive_args *v)
{
@@ -1781,6 +1807,7 @@
.vop_open = tmpfs_open,
.vop_close = tmpfs_close,
.vop_fplookup_vexec = tmpfs_fplookup_vexec,
+ .vop_fplookup_symlink = tmpfs_fplookup_symlink,
.vop_access = tmpfs_access,
.vop_stat = tmpfs_stat,
.vop_getattr = tmpfs_getattr,
Index: sys/kern/vfs_cache.c
===================================================================
--- sys/kern/vfs_cache.c
+++ sys/kern/vfs_cache.c
@@ -548,6 +548,41 @@
static uma_zone_t __read_mostly cache_zone_large;
static uma_zone_t __read_mostly cache_zone_large_ts;
+char *
+cache_symlink_alloc(size_t size, int flags)
+{
+
+ if (size < CACHE_ZONE_SMALL_SIZE) {
+ return (uma_zalloc_smr(cache_zone_small, flags));
+ }
+ if (size < CACHE_ZONE_LARGE_SIZE) {
+ return (uma_zalloc_smr(cache_zone_large, flags));
+ }
+ return (NULL);
+}
+
+void
+cache_symlink_free(char *string)
+{
+ size_t size;
+
+ MPASS(string != NULL);
+ /*
+ * XXXMJG
+ */
+ size = strlen(string);
+
+ if (size < CACHE_ZONE_SMALL_SIZE) {
+ uma_zfree_smr(cache_zone_small, string);
+ return;
+ }
+ if (size < CACHE_ZONE_LARGE_SIZE) {
+ uma_zfree_smr(cache_zone_large, string);
+ return;
+ }
+ __assert_unreachable();
+}
+
static struct namecache *
cache_alloc_uma(int len, bool ts)
{
@@ -3722,6 +3757,13 @@
#define cache_fpl_handled(x, e) cache_fpl_handled_impl((x), (e), __LINE__)
+static bool
+cache_fpl_terminated(struct cache_fpl *fpl)
+{
+
+ return (fpl->status != CACHE_FPL_STATUS_UNSET);
+}
+
#define CACHE_FPL_SUPPORTED_CN_FLAGS \
(NC_NOMAKEENTRY | NC_KEEPPOSENTRY | LOCKLEAF | LOCKPARENT | WANTPARENT | \
FOLLOW | LOCKSHARED | SAVENAME | SAVESTART | WILLBEDIR | ISOPEN | \
@@ -3807,13 +3849,6 @@
return (0);
}
-static bool
-cache_fplookup_vnode_supported(struct vnode *vp)
-{
-
- return (vp->v_type != VLNK);
-}
-
static int __noinline
cache_fplookup_negative_promote(struct cache_fpl *fpl, struct namecache *oncp,
uint32_t hash)
@@ -4010,8 +4045,6 @@
dvp_seqc = fpl->dvp_seqc;
tvp = fpl->tvp;
- VNPASS(cache_fplookup_vnode_supported(dvp), dvp);
-
if (cnp->cn_nameiop != LOOKUP) {
return (cache_fplookup_final_modifying(fpl));
}
@@ -4158,6 +4191,91 @@
return (cache_fpl_handled(fpl, ENOENT));
}
+/*
+ * Resolve a symlink. Called by filesystem-specific routines.
+ *
+ * Code flow is:
+ * ... -> cache_fplookup_symlink -> VOP_FPLOOKUP_SYMLINK -> cache_symlink_resolve
+ */
+int
+cache_symlink_resolve(struct cache_fpl *fpl, const char *string, size_t len)
+{
+ struct nameidata *ndp;
+ struct componentname *cnp;
+
+ ndp = fpl->ndp;
+ cnp = fpl->cnp;
+
+ if (len == 0) {
+ return (ENOENT);
+ }
+
+ if (len + ndp->ni_pathlen > MAXPATHLEN) {
+ return (ENAMETOOLONG);
+ }
+
+ if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
+ return (ELOOP);
+ }
+
+ if (ndp->ni_pathlen > 1) {
+ bcopy(ndp->ni_next, cnp->cn_pnbuf + len, ndp->ni_pathlen);
+ } else {
+ cnp->cn_pnbuf[len] = '\0';
+ }
+ bcopy(string, cnp->cn_pnbuf, len);
+
+ ndp->ni_pathlen += len;
+ cnp->cn_nameptr = cnp->cn_pnbuf;
+
+ return (0);
+}
+
+static int __noinline
+cache_fplookup_symlink(struct cache_fpl *fpl)
+{
+ struct nameidata *ndp;
+ struct componentname *cnp;
+ struct vnode *dvp, *tvp;
+ int error;
+
+ ndp = fpl->ndp;
+ cnp = fpl->cnp;
+ dvp = fpl->dvp;
+ tvp = fpl->tvp;
+
+ if (cache_fpl_islastcn(ndp)) {
+ if ((cnp->cn_flags & FOLLOW) == 0) {
+ return (cache_fplookup_final(fpl));
+ }
+ }
+
+ error = VOP_FPLOOKUP_SYMLINK(tvp, fpl);
+ if (__predict_false(error != 0)) {
+ switch (error) {
+ case EAGAIN:
+ return (cache_fpl_partial(fpl));
+ case ENOENT:
+ case ENAMETOOLONG:
+ case ELOOP:
+ cache_fpl_smr_exit(fpl);
+ return (cache_fpl_handled(fpl, error));
+ default:
+ return (cache_fpl_aborted(fpl));
+ }
+ }
+
+ if (*(cnp->cn_nameptr) == '/') {
+ cache_fpl_handle_root(ndp, &fpl->dvp);
+ fpl->dvp_seqc = vn_seqc_read_any(tvp);
+ if (seqc_in_modify(fpl->dvp_seqc)) {
+ return (cache_fpl_aborted(fpl));
+ }
+ }
+
+ return (0);
+}
+
static int
cache_fplookup_next(struct cache_fpl *fpl)
{
@@ -4207,10 +4325,6 @@
return (cache_fpl_partial(fpl));
}
- if (!cache_fplookup_vnode_supported(tvp)) {
- return (cache_fpl_partial(fpl));
- }
-
counter_u64_add(numposhits, 1);
SDT_PROBE3(vfs, namecache, lookup, hit, dvp, ncp->nc_name, tvp);
return (0);
@@ -4519,16 +4633,12 @@
goto out;
}
- VNPASS(cache_fplookup_vnode_supported(fpl->dvp), fpl->dvp);
-
for (;;) {
error = cache_fplookup_parse(fpl);
if (__predict_false(error != 0)) {
break;
}
- VNPASS(cache_fplookup_vnode_supported(fpl->dvp), fpl->dvp);
-
error = VOP_FPLOOKUP_VEXEC(fpl->dvp, cnp->cn_cred);
if (__predict_false(error != 0)) {
error = cache_fplookup_failed_vexec(fpl, error);
@@ -4558,24 +4668,33 @@
VNPASS(!seqc_in_modify(fpl->tvp_seqc), fpl->tvp);
- if (cache_fpl_islastcn(ndp)) {
- error = cache_fplookup_final(fpl);
- break;
- }
+ if (fpl->tvp->v_type == VLNK) {
+ error = cache_fplookup_symlink(fpl);
+ if (cache_fpl_terminated(fpl)) {
+ break;
+ }
+ } else {
+ if (cache_fpl_islastcn(ndp)) {
+ error = cache_fplookup_final(fpl);
+ break;
+ }
- if (!vn_seqc_consistent(fpl->dvp, fpl->dvp_seqc)) {
- error = cache_fpl_aborted(fpl);
- break;
- }
+ if (!vn_seqc_consistent(fpl->dvp, fpl->dvp_seqc)) {
+ error = cache_fpl_aborted(fpl);
+ break;
+ }
- fpl->dvp = fpl->tvp;
- fpl->dvp_seqc = fpl->tvp_seqc;
+ fpl->dvp = fpl->tvp;
+ fpl->dvp_seqc = fpl->tvp_seqc;
+ cache_fplookup_parse_advance(fpl);
+ }
- cache_fplookup_parse_advance(fpl);
+ VNPASS(!seqc_in_modify(fpl->dvp_seqc), fpl->dvp);
cache_fpl_checkpoint(fpl, &fpl->snd);
}
out:
switch (fpl->status) {
+ case CACHE_FPL_STATUS_DESTROYED:
case CACHE_FPL_STATUS_UNSET:
__assert_unreachable();
break;
@@ -4738,10 +4857,9 @@
error = cache_fplookup_impl(dvp, &fpl);
out:
cache_fpl_smr_assert_not_entered(&fpl);
- SDT_PROBE3(vfs, fplookup, lookup, done, ndp, fpl.line, fpl.status);
- *status = fpl.status;
switch (fpl.status) {
+ case CACHE_FPL_STATUS_DESTROYED:
case CACHE_FPL_STATUS_UNSET:
__assert_unreachable();
break;
@@ -4757,7 +4875,17 @@
break;
case CACHE_FPL_STATUS_ABORTED:
cache_fpl_restore_abort(&fpl, &orig);
+ /*
+ * Resolving symlinks overwrites data passed by the caller.
+ * Let namei know.
+ */
+ if (ndp->ni_loopcnt > 0) {
+ fpl.status = CACHE_FPL_STATUS_DESTROYED;
+ cache_fpl_cleanup_cnp(cnp);
+ }
break;
}
+ SDT_PROBE3(vfs, fplookup, lookup, done, ndp, fpl.line, fpl.status);
+ *status = fpl.status;
return (error);
}
Index: sys/kern/vfs_lookup.c
===================================================================
--- sys/kern/vfs_lookup.c
+++ sys/kern/vfs_lookup.c
@@ -567,6 +567,7 @@
ndp->ni_startdir->v_type == VBAD);
ndp->ni_lcf = 0;
+ ndp->ni_loopcnt = 0;
ndp->ni_vp = NULL;
error = namei_getpath(ndp);
@@ -600,8 +601,16 @@
TAILQ_INIT(&ndp->ni_cap_tracker);
dp = ndp->ni_startdir;
break;
+ case CACHE_FPL_STATUS_DESTROYED:
+ ndp->ni_loopcnt = 0;
+ error = namei_getpath(ndp);
+ if (__predict_false(error != 0)) {
+ return (error);
+ }
+ /* FALLTHROUGH */
case CACHE_FPL_STATUS_ABORTED:
TAILQ_INIT(&ndp->ni_cap_tracker);
+ MPASS(ndp->ni_lcf == 0);
error = namei_setup(ndp, &dp, &pwd);
if (error != 0) {
namei_cleanup_cnp(cnp);
@@ -610,8 +619,6 @@
break;
}
- ndp->ni_loopcnt = 0;
-
/*
* Locked lookup.
*/
Index: sys/kern/vfs_subr.c
===================================================================
--- sys/kern/vfs_subr.c
+++ sys/kern/vfs_subr.c
@@ -5446,6 +5446,19 @@
VFS_SMR_ASSERT_ENTERED();
}
+void
+vop_fplookup_symlink_debugpre(void *ap __unused)
+{
+
+ VFS_SMR_ASSERT_ENTERED();
+}
+
+void
+vop_fplookup_symlink_debugpost(void *ap __unused, int rc __unused)
+{
+
+ VFS_SMR_ASSERT_ENTERED();
+}
void
vop_strategy_debugpre(void *ap)
{
Index: sys/kern/vnode_if.src
===================================================================
--- sys/kern/vnode_if.src
+++ sys/kern/vnode_if.src
@@ -156,6 +156,16 @@
};
+%% fplookup_symlink vp - - -
+%! fplookup_symlink debugpre vop_fplookup_symlink_debugpre
+%! fplookup_symlink debugpost vop_fplookup_symlink_debugpost
+
+vop_fplookup_symlink {
+ IN struct vnode *vp;
+ IN struct cache_fpl *fpl;
+};
+
+
%% access vp L L L
vop_access {
Index: sys/sys/namei.h
===================================================================
--- sys/sys/namei.h
+++ sys/sys/namei.h
@@ -116,8 +116,8 @@
#ifdef _KERNEL
-enum cache_fpl_status { CACHE_FPL_STATUS_ABORTED, CACHE_FPL_STATUS_PARTIAL,
- CACHE_FPL_STATUS_HANDLED, CACHE_FPL_STATUS_UNSET };
+enum cache_fpl_status { CACHE_FPL_STATUS_DESTROYED, CACHE_FPL_STATUS_ABORTED,
+ CACHE_FPL_STATUS_PARTIAL, CACHE_FPL_STATUS_HANDLED, CACHE_FPL_STATUS_UNSET };
int cache_fplookup(struct nameidata *ndp, enum cache_fpl_status *status,
struct pwd **pwdp);
Index: sys/sys/param.h
===================================================================
--- sys/sys/param.h
+++ sys/sys/param.h
@@ -60,7 +60,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1300131 /* Master, propagated to newvers */
+#define __FreeBSD_version 1300132 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
Index: sys/sys/vnode.h
===================================================================
--- sys/sys/vnode.h
+++ sys/sys/vnode.h
@@ -66,6 +66,7 @@
*/
struct namecache;
+struct cache_fpl;
struct vpollinfo {
struct mtx vpi_lock; /* lock to protect below */
@@ -644,6 +645,10 @@
void cache_purge_vgone(struct vnode *vp);
void cache_purge_negative(struct vnode *vp);
void cache_purgevfs(struct mount *mp);
+char *cache_symlink_alloc(size_t size, int flags);
+void cache_symlink_free(char *string);
+int cache_symlink_resolve(struct cache_fpl *fpl, const char *string,
+ size_t len);
void cache_vop_rename(struct vnode *fdvp, struct vnode *fvp, struct vnode *tdvp,
struct vnode *tvp, struct componentname *fcnp, struct componentname *tcnp);
void cache_vop_rmdir(struct vnode *dvp, struct vnode *vp);
@@ -888,6 +893,8 @@
#ifdef DEBUG_VFS_LOCKS
void vop_fplookup_vexec_debugpre(void *a);
void vop_fplookup_vexec_debugpost(void *a, int rc);
+void vop_fplookup_symlink_debugpre(void *a);
+void vop_fplookup_symlink_debugpost(void *a, int rc);
void vop_strategy_debugpre(void *a);
void vop_lock_debugpre(void *a);
void vop_lock_debugpost(void *a, int rc);
@@ -898,6 +905,8 @@
#else
#define vop_fplookup_vexec_debugpre(x) do { } while (0)
#define vop_fplookup_vexec_debugpost(x, y) do { } while (0)
+#define vop_fplookup_symlink_debugpre(x) do { } while (0)
+#define vop_fplookup_symlink_debugpost(x, y) do { } while (0)
#define vop_strategy_debugpre(x) do { } while (0)
#define vop_lock_debugpre(x) do { } while (0)
#define vop_lock_debugpost(x, y) do { } while (0)
Index: sys/ufs/ufs/ufs_vnops.c
===================================================================
--- sys/ufs/ufs/ufs_vnops.c
+++ sys/ufs/ufs/ufs_vnops.c
@@ -2965,6 +2965,7 @@
.vop_accessx = ufs_accessx,
.vop_bmap = ufs_bmap,
.vop_fplookup_vexec = ufs_fplookup_vexec,
+ .vop_fplookup_symlink = VOP_EAGAIN,
.vop_cachedlookup = ufs_lookup,
.vop_close = ufs_close,
.vop_create = ufs_create,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Nov 21, 3:49 AM (10 h, 22 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14753754
Default Alt Text
D27488.id80553.diff (20 KB)
Attached To
Mode
D27488: symlink support for lockless lookup
Attached
Detach File
Event Timeline
Log In to Comment