Index: sys/fs/tmpfs/tmpfs_vnops.h =================================================================== --- sys/fs/tmpfs/tmpfs_vnops.h +++ sys/fs/tmpfs/tmpfs_vnops.h @@ -51,6 +51,7 @@ vop_access_t tmpfs_access; vop_fplookup_vexec_t tmpfs_fplookup_vexec; vop_stat_t tmpfs_stat; +vop_getattr_lite_t tmpfs_getattr_lite; vop_getattr_t tmpfs_getattr; vop_setattr_t tmpfs_setattr; vop_pathconf_t tmpfs_pathconf; Index: sys/fs/tmpfs/tmpfs_vnops.c =================================================================== --- sys/fs/tmpfs/tmpfs_vnops.c +++ sys/fs/tmpfs/tmpfs_vnops.c @@ -453,6 +453,37 @@ return (vop_stat_helper_post(v, error)); } +int +tmpfs_getattr_lite(struct vop_getattr_lite_args *v) +{ + struct vnode *vp = v->a_vp; + struct vattr_lite *lvap = v->a_lvap; + int locked = ap->a_locked; + struct tmpfs_node *node; + + node = VP_TO_TMPFS_NODE(vp); + if (locked == LA_UNLOCKED) { + vfs_smr_enter(); + node = VP_TO_TMPFS_NODE_SMR(vp); + if (__predict_false(node == NULL)) { + vfs_smr_exit(); + return (ENOENT); + } + } + + lvap->va_size = node->tn_size; + lvap->va_nlink = node->tn_links; + lvap->va_type = vp->v_type; + lvap->va_mode = node->tn_mode; + lvap->va_uid = node->tn_uid; + lvap->va_gid = node->tn_gid; + + if (locked == LA_UNLOCKED) { + vfs_smr_exit(); + } + return (0); +} + int tmpfs_getattr(struct vop_getattr_args *v) { @@ -1724,6 +1755,7 @@ .vop_fplookup_vexec = tmpfs_fplookup_vexec, .vop_access = tmpfs_access, .vop_stat = tmpfs_stat, + .vop_getattr_lite = tmpfs_getattr_lite, .vop_getattr = tmpfs_getattr, .vop_setattr = tmpfs_setattr, .vop_read = tmpfs_read, Index: sys/kern/vfs_default.c =================================================================== --- sys/kern/vfs_default.c +++ sys/kern/vfs_default.c @@ -89,6 +89,7 @@ static int vop_stdadd_writecount(struct vop_add_writecount_args *ap); static int vop_stdcopy_file_range(struct vop_copy_file_range_args *ap); static int vop_stdfdatasync(struct vop_fdatasync_args *ap); +static int vop_stdgetattr_lite(struct vop_getattr_lite_args *ap); static int vop_stdgetpages_async(struct vop_getpages_async_args *ap); static int vop_stdstat(struct vop_stat_args *ap); @@ -120,6 +121,7 @@ .vop_fsync = VOP_NULL, .vop_stat = vop_stdstat, .vop_fdatasync = vop_stdfdatasync, + .vop_getattr_lite = vop_stdgetattr_lite, .vop_getpages = vop_stdgetpages, .vop_getpages_async = vop_stdgetpages_async, .vop_getwritemount = vop_stdgetwritemount, @@ -749,6 +751,36 @@ return (vn_fsync_buf(ap->a_vp, MNT_WAIT)); } +int +vop_stdgetattr_lite(struct vop_getattr_lite_args *ap) +{ + struct vnode *vp; + struct ucred *cred; + struct vattr vattr; + struct vattr_lite *lvap; + int locked, error; + + vp = ap->a_vp; + cred = ap->a_cred; + locked = ap->a_locked; + if (locked == LK_UNLOCKED) + VOP_LOCK(vp, LK_SHARED | LK_RETRY); + error = VOP_GETATTR(vp, &vattr, cred); + if (locked == LK_UNLOCKED) + VOP_UNLOCK(vp); + if (error != 0) + return (error); + + lvap = ap->a_lvap; + lvap->va_size = vattr.va_size; + lvap->va_nlink = vattr.va_nlink; + lvap->va_type = vattr.va_type; + lvap->va_mode = vattr.va_mode; + lvap->va_uid = vattr.va_uid; + lvap->va_gid = vattr.va_gid; + return (0); +} + /* XXX Needs good comment and more info in the manpage (VOP_GETPAGES(9)). */ int vop_stdgetpages(ap) Index: sys/kern/vfs_subr.c =================================================================== --- sys/kern/vfs_subr.c +++ sys/kern/vfs_subr.c @@ -5669,6 +5669,66 @@ ASSERT_VI_LOCKED(a->a_vp, "VOP_NEED_INACTIVE"); } + +void +vop_getattr_lite_debugpre(void *ap) +{ + struct vop_getattr_lite_args *a; + struct vnode *vp; + struct vattr_lite *lvap; + int locked; + + a = ap; + vp = a->a_vp; + lvap = a->a_lvap; + locked = a->a_locked; + + switch (locked) { + case LA_UNLOCKED: + case LA_XLOCKED: + case LA_SLOCKED: + case LA_LOCKED: + break; + default: + panic("%s: invalid lock status %d\n", __func__, locked); + } + if (locked != LA_UNLOCKED) + ASSERT_VOP_LOCKED(vp, __func__); + + lvap->va_size = VNOVAL; + lvap->va_nlink = VNOVAL; + lvap->va_type = VNON; + lvap->va_mode = 0xffff; + lvap->va_uid = VNOVAL; + lvap->va_gid = VNOVAL; +} + +void +vop_getattr_lite_debugpost(void *ap, int rc) +{ + struct vop_getattr_lite_args *a; + struct vnode *vp; + struct vattr_lite *lvap; + int locked; + + a = ap; + vp = a->a_vp; + lvap = a->a_lvap; + locked = a->a_locked; + + if (locked != LA_UNLOCKED) + ASSERT_VOP_LOCKED(vp, __func__); + + if (lvap->va_size == VNOVAL || + lvap->va_nlink == VNOVAL || + lvap->va_type == VNON || + lvap->va_mode == 0xffff || + lvap->va_uid == VNOVAL || + lvap->va_gid == VNOVAL) { + VNASSERT(0, vp, + ("some fields got left unitialized in vlvap_lite")); + } +} #endif void Index: sys/kern/vfs_vnops.c =================================================================== --- sys/kern/vfs_vnops.c +++ sys/kern/vfs_vnops.c @@ -2250,7 +2250,7 @@ { struct ucred *cred; struct vnode *vp; - struct vattr vattr; + struct vattr_lite vattr; off_t foffset, size; int error, noneg; @@ -2270,9 +2270,7 @@ offset += foffset; break; case L_XTND: - vn_lock(vp, LK_SHARED | LK_RETRY); - error = VOP_GETATTR(vp, &vattr, cred); - VOP_UNLOCK(vp); + error = VOP_GETATTR_LITE(vp, &vattr, cred, LA_UNLOCKED); if (error) break; Index: sys/kern/vnode_if.src =================================================================== --- sys/kern/vnode_if.src +++ sys/kern/vnode_if.src @@ -188,6 +188,18 @@ }; +%% getattr_lite vp - - - +%! getattr_lite debugpre vop_getattr_lite_debugpre +%! getattr_lite debugpost vop_getattr_lite_debugpost + +vop_getattr_lite { + IN struct vnode *vp; + OUT struct vattr_lite *lvap; + IN struct ucred *cred; + IN int locked; +}; + + %% getattr vp L L L vop_getattr { Index: sys/sys/vnode.h =================================================================== --- sys/sys/vnode.h +++ sys/sys/vnode.h @@ -296,6 +296,19 @@ long va_spare; /* remain quad aligned */ }; +/* + * If you add fields to this structure make sure to update sanity checks + * in vop_getattr_lite_debug* + */ +struct vattr_lite { + u_quad_t va_size; /* file size in bytes */ + nlink_t va_nlink; /* number of references to file */ + enum vtype va_type; /* vnode type (for create) */ + u_short va_mode; /* files access mode and type */ + uid_t va_uid; /* owner user id */ + gid_t va_gid; /* owner group id */ +}; + /* * Flags for va_vaflags. */ @@ -878,6 +891,8 @@ void vop_unlock_debugpre(void *a); void vop_need_inactive_debugpre(void *a); void vop_need_inactive_debugpost(void *a, int rc); +void vop_getattr_lite_debugpre(void *a); +void vop_getattr_lite_debugpost(void *a, int rc); #else #define vop_fplookup_vexec_debugpre(x) do { } while (0) #define vop_fplookup_vexec_debugpost(x, y) do { } while (0) @@ -887,6 +902,8 @@ #define vop_unlock_debugpre(x) do { } while (0) #define vop_need_inactive_debugpre(x) do { } while (0) #define vop_need_inactive_debugpost(x, y) do { } while (0) +#define vop_getattr_lite_debugpre(x) do { } while (0) +#define vop_getattr_lite_debugpost(x, y) do { } while (0) #endif void vop_rename_fail(struct vop_rename_args *ap);