From 1ff80a3400f426648e820a87225361e1366ef95e Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Fri, 7 Aug 2020 19:36:08 +0000 Subject: [PATCH 1/7] vfs: release the interlock after failing to set VHOLD_NO_SMR While here add more comments. Diagnosed by: markj Reported by: pho Fixes: r362827 ("vfs: protect vnodes with smr") --- sys/kern/vfs_subr.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 5c25ab86cf9d..fb245cb6e3d2 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -3683,19 +3683,24 @@ vdropl(struct vnode *vp) } if (!VN_IS_DOOMED(vp)) { vdrop_deactivate(vp); + /* + * Also unlocks the interlock. We can't assert on it as we + * released our hold and by now the vnode might have been + * freed. + */ return; } /* - * We may be racing against vhold_smr. + * Set the VHOLD_NO_SMR flag. * - * If they win we can just pretend we never got this far, they will - * vdrop later. + * We may be racing against vhold_smr. If they win we can just pretend + * we never got this far, they will vdrop later. */ if (!atomic_cmpset_int(&vp->v_holdcnt, 0, VHOLD_NO_SMR)) { + VI_UNLOCK(vp); /* - * We lost the aforementioned race. Note that any subsequent - * access is invalid as they might have managed to vdropl on - * their own. + * We lost the aforementioned race. Any subsequent access is + * invalid as they might have managed to vdropl on their own. */ return; } From 1e5d733503521375eb5372079366329936365f6f Mon Sep 17 00:00:00 2001 From: "Bjoern A. Zeeb" Date: Fri, 7 Aug 2020 19:58:16 +0000 Subject: [PATCH 2/7] mmc_da: fix memory leak in sddaregister() In case we are failing to allocate mmcdata, we are returning with a softc allocated but not attached to anything and thus leak the memory. Reviewed by: scottl MFC after: 2 weeks X-MFC: only if we also mfc other mmccam changes? Differential Revision: https://reviews.freebsd.org/D25987 --- sys/cam/mmc/mmc_da.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/cam/mmc/mmc_da.c b/sys/cam/mmc/mmc_da.c index a603dabf9351..7d78685c81df 100644 --- a/sys/cam/mmc/mmc_da.c +++ b/sys/cam/mmc/mmc_da.c @@ -789,7 +789,6 @@ sddaregister(struct cam_periph *periph, void *arg) softc = (struct sdda_softc *)malloc(sizeof(*softc), M_DEVBUF, M_NOWAIT|M_ZERO); - if (softc == NULL) { printf("sddaregister: Unable to probe new device. " "Unable to allocate softc\n"); @@ -802,6 +801,7 @@ sddaregister(struct cam_periph *periph, void *arg) if (softc->mmcdata == NULL) { printf("sddaregister: Unable to probe new device. " "Unable to allocate mmcdata\n"); + free(softc, M_DEVBUF); return (CAM_REQ_CMP_ERR); } periph->softc = softc; From 51ea7bea910148ae6cf40c57de0cd3b120d542e3 Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Fri, 7 Aug 2020 23:06:40 +0000 Subject: [PATCH 3/7] vfs: add VOP_STAT The current scheme of calling VOP_GETATTR adds avoidable overhead. An example with tmpfs doing fstat (ops/s): before: 7488958 after: 7913833 Reviewed by: kib (previous version) Differential Revision: https://reviews.freebsd.org/D25910 --- share/man/man9/Makefile | 3 +- share/man/man9/VOP_ATTRIB.9 | 45 ++++++- sys/compat/linuxkpi/common/src/linux_compat.c | 2 +- sys/kern/vfs_default.c | 113 ++++++++++++++++++ sys/kern/vfs_syscalls.c | 6 +- sys/kern/vfs_vnops.c | 113 +----------------- sys/kern/vnode_if.src | 11 ++ sys/security/audit/audit_arg.c | 2 +- sys/sys/vnode.h | 18 ++- 9 files changed, 189 insertions(+), 124 deletions(-) diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index 01aaed947fa1..33e162d5fae0 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -2308,7 +2308,8 @@ MLINKS+=vm_page_insert.9 vm_page_remove.9 MLINKS+=vm_page_wire.9 vm_page_unwire.9 MLINKS+=VOP_ACCESS.9 VOP_ACCESSX.9 MLINKS+=VOP_ATTRIB.9 VOP_GETATTR.9 \ - VOP_ATTRIB.9 VOP_SETATTR.9 + VOP_ATTRIB.9 VOP_SETATTR.9 \ + VOP_ATTRIB.9 VOP_STAT.9 MLINKS+=VOP_CREATE.9 VOP_MKDIR.9 \ VOP_CREATE.9 VOP_MKNOD.9 \ VOP_CREATE.9 VOP_SYMLINK.9 diff --git a/share/man/man9/VOP_ATTRIB.9 b/share/man/man9/VOP_ATTRIB.9 index e48e4eb9a254..45f1e2f1652a 100644 --- a/share/man/man9/VOP_ATTRIB.9 +++ b/share/man/man9/VOP_ATTRIB.9 @@ -28,7 +28,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 29, 2008 +.Dd August 8, 2020 .Dt VOP_ATTRIB 9 .Os .Sh NAME @@ -42,19 +42,49 @@ .Fn VOP_GETATTR "struct vnode *vp" "struct vattr *vap" "struct ucred *cred" .Ft int .Fn VOP_SETATTR "struct vnode *vp" "struct vattr *vap" "struct ucred *cred" +.Ft int +.Fn VOP_STAT "struct vnode *vp" "struct stat *sb" "struct ucred *active_cred" \ +"struct ucred *file_cred" "struct thread *td" .Sh DESCRIPTION These entry points manipulate various attributes of a file or directory, including file permissions, owner, group, size, access time and modification time. .Pp -The arguments are: +.Fn VOP_STAT +returns data in a format suitable for the +.Xr stat 2 +system call and by default is implemented as a wrapper around +.Fn VOP_GETATTR . +Filesystems may want to implement their own variant for performance reasons. +.Pp +For +.Fn VOP_GETATTR +and +.Fn VOP_SETATTR +the arguments are: .Bl -tag -width cred .It Fa vp The vnode of the file. .It Fa vap The attributes of the file. .It Fa cred -The user credentials of the calling process. +The user credentials of the calling thread. +.El +.Pp +For +.Fn VOP_STAT +the arguments are: +.Bl -tag -width active_cred +.It Fa vp +The vnode of the file. +.It Fa sb +The attributes of the file. +.It Fa active_cred +The user credentials of the calling thread. +.It Fa file_cred +The credentials installed on the file description pointing to the vnode or NOCRED. +.It Fa td +The calling thread. .El .Pp Attributes which are not being modified by @@ -67,8 +97,11 @@ the contents of .Fa *vap prior to setting specific values. .Sh LOCKS +Both .Fn VOP_GETATTR -expects the vnode to be locked on entry and will leave the vnode locked on +and +.Fn VOP_STAT +expect the vnode to be locked on entry and will leave the vnode locked on return. The lock type can be either shared or exclusive. .Pp @@ -84,6 +117,10 @@ otherwise an appropriate error is returned. .Fn VOP_SETATTR returns zero if the attributes were changed successfully, otherwise an appropriate error is returned. +.Fn VOP_STAT +returns 0 if it was able to retrieve the attribute data +.Fa *sb , +otherwise an appropriate error is returned. .Sh ERRORS .Bl -tag -width Er .It Bq Er EPERM diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c b/sys/compat/linuxkpi/common/src/linux_compat.c index 385dbc89b977..0d5e14b9d027 100644 --- a/sys/compat/linuxkpi/common/src/linux_compat.c +++ b/sys/compat/linuxkpi/common/src/linux_compat.c @@ -1691,7 +1691,7 @@ linux_file_stat(struct file *fp, struct stat *sb, struct ucred *active_cred, vp = filp->f_vnode; vn_lock(vp, LK_SHARED | LK_RETRY); - error = vn_stat(vp, sb, td->td_ucred, NOCRED, td); + error = VOP_STAT(vp, sb, td->td_ucred, NOCRED, td); VOP_UNLOCK(vp); return (error); diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index f67bc9bf3ef0..57465506d7d8 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -57,6 +57,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include +#include #include @@ -87,6 +90,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_stdgetpages_async(struct vop_getpages_async_args *ap); +static int vop_stdstat(struct vop_stat_args *ap); /* * This vnode table stores what we want to do if the filesystem doesn't @@ -114,6 +118,7 @@ struct vop_vector default_vnodeops = { .vop_bmap = vop_stdbmap, .vop_close = VOP_NULL, .vop_fsync = VOP_NULL, + .vop_stat = vop_stdstat, .vop_fdatasync = vop_stdfdatasync, .vop_getpages = vop_stdgetpages, .vop_getpages_async = vop_stdgetpages_async, @@ -1461,3 +1466,111 @@ vop_sigdefer(struct vop_vector *vop, struct vop_generic_args *a) sigallowstop(prev_stops); return (rc); } + +static int +vop_stdstat(struct vop_stat_args *a) +{ + struct vattr vattr; + struct vattr *vap; + struct vnode *vp; + struct stat *sb; + int error; + u_short mode; + + vp = a->a_vp; + sb = a->a_sb; + + error = vop_stat_helper_pre(a); + if (error != 0) + return (error); + + vap = &vattr; + + /* + * Initialize defaults for new and unusual fields, so that file + * systems which don't support these fields don't need to know + * about them. + */ + vap->va_birthtime.tv_sec = -1; + vap->va_birthtime.tv_nsec = 0; + vap->va_fsid = VNOVAL; + vap->va_rdev = NODEV; + + error = VOP_GETATTR(vp, vap, a->a_active_cred); + if (error) + goto out; + + /* + * Zero the spare stat fields + */ + bzero(sb, sizeof *sb); + + /* + * Copy from vattr table + */ + if (vap->va_fsid != VNOVAL) + sb->st_dev = vap->va_fsid; + else + sb->st_dev = vp->v_mount->mnt_stat.f_fsid.val[0]; + sb->st_ino = vap->va_fileid; + mode = vap->va_mode; + switch (vap->va_type) { + case VREG: + mode |= S_IFREG; + break; + case VDIR: + mode |= S_IFDIR; + break; + case VBLK: + mode |= S_IFBLK; + break; + case VCHR: + mode |= S_IFCHR; + break; + case VLNK: + mode |= S_IFLNK; + break; + case VSOCK: + mode |= S_IFSOCK; + break; + case VFIFO: + mode |= S_IFIFO; + break; + default: + error = EBADF; + goto out; + } + sb->st_mode = mode; + sb->st_nlink = vap->va_nlink; + sb->st_uid = vap->va_uid; + sb->st_gid = vap->va_gid; + sb->st_rdev = vap->va_rdev; + if (vap->va_size > OFF_MAX) { + error = EOVERFLOW; + goto out; + } + sb->st_size = vap->va_size; + sb->st_atim.tv_sec = vap->va_atime.tv_sec; + sb->st_atim.tv_nsec = vap->va_atime.tv_nsec; + sb->st_mtim.tv_sec = vap->va_mtime.tv_sec; + sb->st_mtim.tv_nsec = vap->va_mtime.tv_nsec; + sb->st_ctim.tv_sec = vap->va_ctime.tv_sec; + sb->st_ctim.tv_nsec = vap->va_ctime.tv_nsec; + sb->st_birthtim.tv_sec = vap->va_birthtime.tv_sec; + sb->st_birthtim.tv_nsec = vap->va_birthtime.tv_nsec; + + /* + * According to www.opengroup.org, the meaning of st_blksize is + * "a filesystem-specific preferred I/O block size for this + * object. In some filesystem types, this may vary from file + * to file" + * Use minimum/default of PAGE_SIZE (e.g. for VCHR). + */ + + sb->st_blksize = max(PAGE_SIZE, vap->va_blocksize); + sb->st_flags = vap->va_flags; + sb->st_blocks = vap->va_bytes / S_BLKSIZE; + sb->st_gen = vap->va_gen; +out: + return (vop_stat_helper_post(a, error)); +} diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 9e9c53d3327c..69a6be798208 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1867,7 +1867,7 @@ kern_funlinkat(struct thread *td, int dfd, const char *path, int fd, if (vp->v_type == VDIR && oldinum == 0) { error = EPERM; /* POSIX */ } else if (oldinum != 0 && - ((error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td)) == 0) && + ((error = VOP_STAT(vp, &sb, td->td_ucred, NOCRED, td)) == 0) && sb.st_ino != oldinum) { error = EIDRM; /* Identifier removed */ } else if (fp != NULL && fp->f_vnode != vp) { @@ -2381,7 +2381,7 @@ kern_statat(struct thread *td, int flag, int fd, const char *path, if ((error = namei(&nd)) != 0) return (error); - error = vn_stat(nd.ni_vp, sbp, td->td_ucred, NOCRED, td); + error = VOP_STAT(nd.ni_vp, sbp, td->td_ucred, NOCRED, td); if (error == 0) { SDT_PROBE2(vfs, , stat, mode, path, sbp->st_mode); if (S_ISREG(sbp->st_mode)) @@ -4566,7 +4566,7 @@ kern_fhstat(struct thread *td, struct fhandle fh, struct stat *sb) vfs_unbusy(mp); if (error != 0) return (error); - error = vn_stat(vp, sb, td->td_ucred, NOCRED, td); + error = VOP_STAT(vp, sb, td->td_ucred, NOCRED, td); vput(vp); return (error); } diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index eb1a7c28ddfe..a0dd9fd2436b 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -1455,123 +1455,12 @@ vn_statfile(struct file *fp, struct stat *sb, struct ucred *active_cred, int error; vn_lock(vp, LK_SHARED | LK_RETRY); - error = vn_stat(vp, sb, active_cred, fp->f_cred, td); + error = VOP_STAT(vp, sb, active_cred, fp->f_cred, td); VOP_UNLOCK(vp); return (error); } -/* - * Stat a vnode; implementation for the stat syscall - */ -int -vn_stat(struct vnode *vp, struct stat *sb, struct ucred *active_cred, - struct ucred *file_cred, struct thread *td) -{ - struct vattr vattr; - struct vattr *vap; - int error; - u_short mode; - - AUDIT_ARG_VNODE1(vp); -#ifdef MAC - error = mac_vnode_check_stat(active_cred, file_cred, vp); - if (error) - return (error); -#endif - - vap = &vattr; - - /* - * Initialize defaults for new and unusual fields, so that file - * systems which don't support these fields don't need to know - * about them. - */ - vap->va_birthtime.tv_sec = -1; - vap->va_birthtime.tv_nsec = 0; - vap->va_fsid = VNOVAL; - vap->va_rdev = NODEV; - - error = VOP_GETATTR(vp, vap, active_cred); - if (error) - return (error); - - /* - * Zero the spare stat fields - */ - bzero(sb, sizeof *sb); - - /* - * Copy from vattr table - */ - if (vap->va_fsid != VNOVAL) - sb->st_dev = vap->va_fsid; - else - sb->st_dev = vp->v_mount->mnt_stat.f_fsid.val[0]; - sb->st_ino = vap->va_fileid; - mode = vap->va_mode; - switch (vap->va_type) { - case VREG: - mode |= S_IFREG; - break; - case VDIR: - mode |= S_IFDIR; - break; - case VBLK: - mode |= S_IFBLK; - break; - case VCHR: - mode |= S_IFCHR; - break; - case VLNK: - mode |= S_IFLNK; - break; - case VSOCK: - mode |= S_IFSOCK; - break; - case VFIFO: - mode |= S_IFIFO; - break; - default: - return (EBADF); - } - sb->st_mode = mode; - sb->st_nlink = vap->va_nlink; - sb->st_uid = vap->va_uid; - sb->st_gid = vap->va_gid; - sb->st_rdev = vap->va_rdev; - if (vap->va_size > OFF_MAX) - return (EOVERFLOW); - sb->st_size = vap->va_size; - sb->st_atim.tv_sec = vap->va_atime.tv_sec; - sb->st_atim.tv_nsec = vap->va_atime.tv_nsec; - sb->st_mtim.tv_sec = vap->va_mtime.tv_sec; - sb->st_mtim.tv_nsec = vap->va_mtime.tv_nsec; - sb->st_ctim.tv_sec = vap->va_ctime.tv_sec; - sb->st_ctim.tv_nsec = vap->va_ctime.tv_nsec; - sb->st_birthtim.tv_sec = vap->va_birthtime.tv_sec; - sb->st_birthtim.tv_nsec = vap->va_birthtime.tv_nsec; - - /* - * According to www.opengroup.org, the meaning of st_blksize is - * "a filesystem-specific preferred I/O block size for this - * object. In some filesystem types, this may vary from file - * to file" - * Use minimum/default of PAGE_SIZE (e.g. for VCHR). - */ - - sb->st_blksize = max(PAGE_SIZE, vap->va_blocksize); - - sb->st_flags = vap->va_flags; - if (priv_check_cred_vfs_generation(td->td_ucred)) - sb->st_gen = 0; - else - sb->st_gen = vap->va_gen; - - sb->st_blocks = vap->va_bytes / S_BLKSIZE; - return (0); -} - /* * File table vnode ioctl routine. */ diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src index e5a7b389fb30..10bca613606d 100644 --- a/sys/kern/vnode_if.src +++ b/sys/kern/vnode_if.src @@ -177,6 +177,17 @@ vop_accessx { }; +%% stat vp L L L + +vop_stat { + IN struct vnode *vp; + OUT struct stat *sb; + IN struct ucred *active_cred; + IN struct ucred *file_cred; + IN struct thread *td; +}; + + %% getattr vp L L L vop_getattr { diff --git a/sys/security/audit/audit_arg.c b/sys/security/audit/audit_arg.c index fc5318750e3e..44b17e36c8ea 100644 --- a/sys/security/audit/audit_arg.c +++ b/sys/security/audit/audit_arg.c @@ -854,7 +854,7 @@ audit_arg_upath2_canon(char *upath) * It is assumed that the caller will hold any vnode locks necessary to * perform a VOP_GETATTR() on the passed vnode. * - * XXX: The attr code is very similar to vfs_vnops.c:vn_stat(), but always + * XXX: The attr code is very similar to vfs_default.c:vop_stdstat(), but always * provides access to the generation number as we need that to construct the * BSM file ID. * diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 5d9e3496d12e..87c01a962064 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -737,8 +737,6 @@ int vn_rdwr_inchunks(enum uio_rw rw, struct vnode *vp, void *base, struct thread *td); int vn_rlimit_fsize(const struct vnode *vn, const struct uio *uio, struct thread *td); -int vn_stat(struct vnode *vp, struct stat *sb, struct ucred *active_cred, - struct ucred *file_cred, struct thread *td); int vn_start_write(struct vnode *vp, struct mount **mpp, int flags); int vn_start_secondary_write(struct vnode *vp, struct mount **mpp, int flags); @@ -893,6 +891,22 @@ void vop_need_inactive_debugpost(void *a, int rc); void vop_rename_fail(struct vop_rename_args *ap); +#define vop_stat_helper_pre(ap) ({ \ + int _error; \ + AUDIT_ARG_VNODE1(ap->a_vp); \ + _error = mac_vnode_check_stat(ap->a_active_cred, ap->a_file_cred, ap->a_vp);\ + if (__predict_true(_error == 0)) \ + bzero(ap->a_sb, sizeof(*ap->a_sb)); \ + _error; \ +}) + +#define vop_stat_helper_post(ap, error) ({ \ + int _error = (error); \ + if (priv_check_cred_vfs_generation(ap->a_td->td_ucred)) \ + ap->a_sb->st_gen = 0; \ + _error; \ +}) + #define VOP_WRITE_PRE(ap) \ struct vattr va; \ int error; \ From 9a14439f2fbb67c3ef0421a24ce4d9a0eaa9f61f Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Fri, 7 Aug 2020 23:07:47 +0000 Subject: [PATCH 4/7] tmpfs: add VOP_STAT handler --- sys/fs/tmpfs/tmpfs_vnops.c | 49 ++++++++++++++++++++++++++++++++++++++ sys/fs/tmpfs/tmpfs_vnops.h | 1 + 2 files changed, 50 insertions(+) diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c index 0e414a46c701..5d4606c3ed6b 100644 --- a/sys/fs/tmpfs/tmpfs_vnops.c +++ b/sys/fs/tmpfs/tmpfs_vnops.c @@ -56,6 +56,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include #include @@ -405,6 +407,52 @@ tmpfs_access(struct vop_access_args *v) return error; } +int +tmpfs_stat(struct vop_stat_args *v) +{ + struct vnode *vp = v->a_vp; + struct stat *sb = v->a_sb; + vm_object_t obj; + struct tmpfs_node *node; + int error; + + node = VP_TO_TMPFS_NODE(vp); + + tmpfs_update_getattr(vp); + + error = vop_stat_helper_pre(v); + if (__predict_false(error)) + return (error); + + sb->st_dev = vp->v_mount->mnt_stat.f_fsid.val[0]; + sb->st_ino = node->tn_id; + sb->st_mode = node->tn_mode | VTTOIF(vp->v_type); + sb->st_nlink = node->tn_links; + sb->st_uid = node->tn_uid; + sb->st_gid = node->tn_gid; + sb->st_rdev = (vp->v_type == VBLK || vp->v_type == VCHR) ? + node->tn_rdev : NODEV; + sb->st_size = node->tn_size; + sb->st_atim.tv_sec = node->tn_atime.tv_sec; + sb->st_atim.tv_nsec = node->tn_atime.tv_nsec; + sb->st_mtim.tv_sec = node->tn_mtime.tv_sec; + sb->st_mtim.tv_nsec = node->tn_mtime.tv_nsec; + sb->st_ctim.tv_sec = node->tn_ctime.tv_sec; + sb->st_ctim.tv_nsec = node->tn_ctime.tv_nsec; + sb->st_birthtim.tv_sec = node->tn_birthtime.tv_sec; + sb->st_birthtim.tv_nsec = node->tn_birthtime.tv_nsec; + sb->st_blksize = PAGE_SIZE; + sb->st_flags = node->tn_flags; + sb->st_gen = node->tn_gen; + if (vp->v_type == VREG) { + obj = node->tn_reg.tn_aobj; + sb->st_blocks = (u_quad_t)obj->resident_page_count * PAGE_SIZE; + } else + sb->st_blocks = node->tn_size; + sb->st_blocks /= S_BLKSIZE; + return (vop_stat_helper_post(v, error)); +} + int tmpfs_getattr(struct vop_getattr_args *v) { @@ -1675,6 +1723,7 @@ struct vop_vector tmpfs_vnodeop_entries = { .vop_close = tmpfs_close, .vop_fplookup_vexec = tmpfs_fplookup_vexec, .vop_access = tmpfs_access, + .vop_stat = tmpfs_stat, .vop_getattr = tmpfs_getattr, .vop_setattr = tmpfs_setattr, .vop_read = tmpfs_read, diff --git a/sys/fs/tmpfs/tmpfs_vnops.h b/sys/fs/tmpfs/tmpfs_vnops.h index 0fa9739c0bc6..267697701191 100644 --- a/sys/fs/tmpfs/tmpfs_vnops.h +++ b/sys/fs/tmpfs/tmpfs_vnops.h @@ -50,6 +50,7 @@ extern struct vop_vector tmpfs_vnodeop_nonc_entries; vop_access_t tmpfs_access; vop_fplookup_vexec_t tmpfs_fplookup_vexec; +vop_stat_t tmpfs_stat; vop_getattr_t tmpfs_getattr; vop_setattr_t tmpfs_setattr; vop_pathconf_t tmpfs_pathconf; From 76dc5d3224a6058e71641fc94fb7bf2f5a723f71 Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Fri, 7 Aug 2020 23:08:17 +0000 Subject: [PATCH 5/7] ufs: add VOP_STAT handler --- sys/ufs/ufs/ufs_vnops.c | 62 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index 25c75e1d584f..087c64bd9671 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include /* XXX */ @@ -107,6 +108,7 @@ static int ufs_chmod(struct vnode *, int, struct ucred *, struct thread *); static int ufs_chown(struct vnode *, uid_t, gid_t, struct ucred *, struct thread *); static vop_close_t ufs_close; static vop_create_t ufs_create; +static vop_stat_t ufs_stat; static vop_getattr_t ufs_getattr; static vop_ioctl_t ufs_ioctl; static vop_link_t ufs_link; @@ -465,6 +467,65 @@ ufs_fplookup_vexec(ap) return (vaccess_vexec_smr(mode, ip->i_uid, ip->i_gid, cred)); } +/* ARGSUSED */ +static int +ufs_stat(struct vop_stat_args *ap) +{ + struct vnode *vp = ap->a_vp; + struct inode *ip = VTOI(vp); + struct stat *sb = ap->a_sb; + int error; + + error = vop_stat_helper_pre(ap); + if (__predict_false(error)) + return (error); + + VI_LOCK(vp); + ufs_itimes_locked(vp); + if (I_IS_UFS1(ip)) { + sb->st_atim.tv_sec = ip->i_din1->di_atime; + sb->st_atim.tv_nsec = ip->i_din1->di_atimensec; + } else { + sb->st_atim.tv_sec = ip->i_din2->di_atime; + sb->st_atim.tv_nsec = ip->i_din2->di_atimensec; + } + VI_UNLOCK(vp); + + sb->st_dev = vp->v_mount->mnt_stat.f_fsid.val[0]; + sb->st_ino = ip->i_number; + sb->st_mode = (ip->i_mode & ~IFMT) | VTTOIF(vp->v_type); + sb->st_nlink = ip->i_effnlink; + sb->st_uid = ip->i_uid; + sb->st_gid = ip->i_gid; + if (I_IS_UFS1(ip)) { + sb->st_rdev = ip->i_din1->di_rdev; + sb->st_size = ip->i_din1->di_size; + sb->st_mtim.tv_sec = ip->i_din1->di_mtime; + sb->st_mtim.tv_nsec = ip->i_din1->di_mtimensec; + sb->st_ctim.tv_sec = ip->i_din1->di_ctime; + sb->st_ctim.tv_nsec = ip->i_din1->di_ctimensec; + sb->st_birthtim.tv_sec = -1; + sb->st_birthtim.tv_nsec = 0; + sb->st_blocks = dbtob((u_quad_t)ip->i_din1->di_blocks) / S_BLKSIZE; + } else { + sb->st_rdev = ip->i_din2->di_rdev; + sb->st_size = ip->i_din2->di_size; + sb->st_mtim.tv_sec = ip->i_din2->di_mtime; + sb->st_mtim.tv_nsec = ip->i_din2->di_mtimensec; + sb->st_ctim.tv_sec = ip->i_din2->di_ctime; + sb->st_ctim.tv_nsec = ip->i_din2->di_ctimensec; + sb->st_birthtim.tv_sec = ip->i_din2->di_birthtime; + sb->st_birthtim.tv_nsec = ip->i_din2->di_birthnsec; + sb->st_blocks = dbtob((u_quad_t)ip->i_din2->di_blocks) / S_BLKSIZE; + } + + sb->st_blksize = max(PAGE_SIZE, vp->v_mount->mnt_stat.f_iosize); + sb->st_flags = ip->i_flags; + sb->st_gen = ip->i_gen; + + return (vop_stat_helper_post(ap, error)); +} + /* ARGSUSED */ static int ufs_getattr(ap) @@ -2822,6 +2883,7 @@ struct vop_vector ufs_vnodeops = { .vop_cachedlookup = ufs_lookup, .vop_close = ufs_close, .vop_create = ufs_create, + .vop_stat = ufs_stat, .vop_getattr = ufs_getattr, .vop_inactive = ufs_inactive, .vop_ioctl = ufs_ioctl, From dfb98e350cd4d018417efa772a203229fe0bc1d0 Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Sat, 8 Aug 2020 10:05:27 +0000 Subject: [PATCH 6/7] Fix i386 build of chpass after r363992 My change to allow bootstrapping pwd_mkdb (r363992) resulted in i386 build failures because the bootstrap header was being included in non-bootstrap chpass. Dropping the no longer required pwd_mkdb include path from chpass fixes the build, but to be certain that the failure doesn't get re-introduced, I've also moved the bootstrap pwd.h into a subdirectory so that adding -I${SRCTOP}/usr.sbin/pwd_mkdb doesn't pull it in. Reported by: mjg --- usr.bin/chpass/Makefile | 4 ++-- usr.sbin/pwd_mkdb/Makefile | 2 +- usr.sbin/pwd_mkdb/{ => bootstrap}/pwd.h | 0 3 files changed, 3 insertions(+), 3 deletions(-) rename usr.sbin/pwd_mkdb/{ => bootstrap}/pwd.h (100%) diff --git a/usr.bin/chpass/Makefile b/usr.bin/chpass/Makefile index fb70df886ee2..bd5baa3c4d07 100644 --- a/usr.bin/chpass/Makefile +++ b/usr.bin/chpass/Makefile @@ -3,7 +3,7 @@ .include -.PATH: ${SRCTOP}/usr.sbin/pwd_mkdb ${SRCTOP}/lib/libc/gen +.PATH: ${SRCTOP}/lib/libc/gen PROG= chpass SRCS= chpass.c edit.c field.c pw_scan.c table.c util.c @@ -15,7 +15,7 @@ CFLAGS+= -DYP .endif #Some people need this, uncomment to activate #CFLAGS+=-DRESTRICT_FULLNAME_CHANGE -CFLAGS+=-I${SRCTOP}/usr.sbin/pwd_mkdb -I${SRCTOP}/lib/libc/gen -I. +CFLAGS+=-I${SRCTOP}/lib/libc/gen -I. LIBADD= crypt util .if ${MK_NIS} != "no" diff --git a/usr.sbin/pwd_mkdb/Makefile b/usr.sbin/pwd_mkdb/Makefile index 4fea2f33796d..f8a2b20ef10b 100644 --- a/usr.sbin/pwd_mkdb/Makefile +++ b/usr.sbin/pwd_mkdb/Makefile @@ -10,7 +10,7 @@ SRCS= pw_scan.c pwd_mkdb.c CFLAGS+= -I${SRCTOP}/lib/libc/gen # for pw_scan.h .if defined(BOOTSTRAPPING) -CFLAGS+=-I${.CURDIR} +CFLAGS+=-I${.CURDIR}/bootstrap .endif .include diff --git a/usr.sbin/pwd_mkdb/pwd.h b/usr.sbin/pwd_mkdb/bootstrap/pwd.h similarity index 100% rename from usr.sbin/pwd_mkdb/pwd.h rename to usr.sbin/pwd_mkdb/bootstrap/pwd.h From 967348a96644639381fdabe38351c7666f800a4d Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sat, 8 Aug 2020 11:06:27 +0000 Subject: [PATCH 7/7] Use static inline for iface_{setup,delete}_addr in tests/sys/net/routing. This fixes possible link errors, similar to: ld: error: undefined symbol: iface_setup_addr >>> referenced by test_rtsock_l3.c:111 (tests/sys/net/routing/test_rtsock_l3.c:111) >>> test_rtsock_l3.o:(presetup_ipv4) >>> referenced by test_rtsock_l3.c:79 (tests/sys/net/routing/test_rtsock_l3.c:79) >>> test_rtsock_l3.o:(presetup_ipv6) >>> referenced by test_rtsock_l3.c:512 (tests/sys/net/routing/test_rtsock_l3.c:512) >>> test_rtsock_l3.o:(atfu_rtm_change_v4_gw_success_body) >>> referenced 10 more times In C (not C++), 'naked' inline is almost always a mistake. Either use static inline (this is appropriate for most cases), or extern inline. MFC after: 3 days --- tests/sys/net/routing/rtsock_common.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/sys/net/routing/rtsock_common.h b/tests/sys/net/routing/rtsock_common.h index bad72400941f..7da88e0eb512 100644 --- a/tests/sys/net/routing/rtsock_common.h +++ b/tests/sys/net/routing/rtsock_common.h @@ -204,7 +204,7 @@ iface_open(char *ifname) * Sets primary IPv4 addr. * Returns 0 on success. */ -inline int +static inline int iface_setup_addr(char *ifname, char *addr, int plen) { char cmd[512]; @@ -225,7 +225,7 @@ iface_setup_addr(char *ifname, char *addr, int plen) * Removes primary IPv4 prefix. * Returns 0 on success. */ -inline int +static inline int iface_delete_addr(char *ifname, char *addr) { char cmd[512];