Page MenuHomeFreeBSD

D27488.id80553.diff
No OneTemporary

D27488.id80553.diff

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

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)

Event Timeline