From: Matthew Dillon Date: Tue, 14 Jul 2009 06:02:21 +0000 (-0700) Subject: MPSAFE - Implement sysctl vfs.getattr_mpsafe, make fstat() MPSAFE X-Git-Tag: v2.4.0~451 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/2ad080fe705c7b50570830438fa2eb4fef08f89e MPSAFE - Implement sysctl vfs.getattr_mpsafe, make fstat() MPSAFE Make fstat() MPSAFE. Adjust fileops->fo_stat functions to be MPSAFE as necessary (uipc socket stat mainly). --- diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c index 0cc3b7803a..1ed9ac877c 100644 --- a/sys/kern/sys_socket.c +++ b/sys/kern/sys_socket.c @@ -201,7 +201,7 @@ soo_poll(struct file *fp, int events, struct ucred *cred) } /* - * MPALMOSTSAFE - acquires mplock + * MPSAFE - acquires mplock */ int soo_stat(struct file *fp, struct stat *ub, struct ucred *cred) @@ -211,8 +211,8 @@ soo_stat(struct file *fp, struct stat *ub, struct ucred *cred) bzero((caddr_t)ub, sizeof (*ub)); ub->st_mode = S_IFSOCK; - get_mplock(); so = (struct socket *)fp->f_data; + /* * If SS_CANTRCVMORE is set, but there's still data left in the * receive buffer, the socket is still readable. @@ -226,7 +226,6 @@ soo_stat(struct file *fp, struct stat *ub, struct ucred *cred) ub->st_uid = so->so_cred->cr_uid; ub->st_gid = so->so_cred->cr_gid; error = so_pru_sense(so, ub); - rel_mplock(); return (error); } diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 747ab013f2..3b2672e7d5 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -647,7 +647,7 @@ 473 MPSAFE STD BSD { int get_tls_area(int which, struct tls_info *info, size_t infosize); } 474 MPSAFE STD BSD { int closefrom(int fd); } 475 STD POSIX { int stat(const char *path, struct stat *ub); } -476 STD POSIX { int fstat(int fd, struct stat *sb); } +476 MPSAFE STD POSIX { int fstat(int fd, struct stat *sb); } 477 STD POSIX { int lstat(const char *path, struct stat *ub); } 478 STD BSD { int fhstat(const struct fhandle *u_fhp, struct stat *sb); } 479 STD BSD { int getdirentries(int fd, char *buf, u_int count, \ diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index b51c9b9a89..7d7b0957fb 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -76,7 +76,8 @@ static struct unp_head unp_shead, unp_dhead; * lock pushdown */ static struct sockaddr sun_noname = { sizeof(sun_noname), AF_LOCAL }; -static ino_t unp_ino; /* prototype for fake inode numbers */ +static ino_t unp_ino = 1; /* prototype for fake inode numbers */ +static struct spinlock unp_ino_spin = SPINLOCK_INITIALIZER(&unp_ino_spin); static int unp_attach (struct socket *, struct pru_attach_info *); static void unp_detach (struct unpcb *); @@ -403,6 +404,9 @@ release: return error; } +/* + * MPSAFE + */ static int uipc_sense(struct socket *so, struct stat *sb) { @@ -412,8 +416,11 @@ uipc_sense(struct socket *so, struct stat *sb) return EINVAL; sb->st_blksize = so->so_snd.ssb_hiwat; sb->st_dev = NOUDEV; - if (unp->unp_ino == 0) /* make up a non-zero inode number */ - unp->unp_ino = (++unp_ino == 0) ? ++unp_ino : unp_ino; + if (unp->unp_ino == 0) { /* make up a non-zero inode number */ + spin_lock_wr(&unp_ino_spin); + unp->unp_ino = unp_ino++; + spin_unlock_wr(&unp_ino_spin); + } sb->st_ino = unp->unp_ino; return (0); } diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index de7d0f1b02..7b4b7df0fb 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -2063,6 +2063,8 @@ vn_todev(struct vnode *vp) /* * Check if vnode represents a disk device. The vnode does not need to be * opened. + * + * MPALMOSTSAFE */ int vn_isdisk(struct vnode *vp, int *errp) @@ -2075,8 +2077,11 @@ vn_isdisk(struct vnode *vp, int *errp) return (0); } - if ((dev = vp->v_rdev) == NULL) + if ((dev = vp->v_rdev) == NULL) { + get_mplock(); dev = get_dev(vp->v_umajor, vp->v_uminor); + rel_mplock(); + } if (dev == NULL) { if (errp != NULL) diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 357e2b26f0..8b8ac24249 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -908,7 +908,7 @@ done: } /* - * MPALMOSTSAFE - acquires mplock + * MPSAFE */ static int vn_statfile(struct file *fp, struct stat *sb, struct ucred *cred) @@ -916,13 +916,14 @@ vn_statfile(struct file *fp, struct stat *sb, struct ucred *cred) struct vnode *vp; int error; - get_mplock(); vp = (struct vnode *)fp->f_data; error = vn_stat(vp, sb, cred); - rel_mplock(); return (error); } +/* + * MPSAFE (if vnode has VMP_GETATTR) + */ int vn_stat(struct vnode *vp, struct stat *sb, struct ucred *cred) { @@ -933,7 +934,13 @@ vn_stat(struct vnode *vp, struct stat *sb, struct ucred *cred) cdev_t dev; vap = &vattr; - error = VOP_GETATTR(vp, vap); + if (getattr_mpsafe && (vp->v_flag & VMP_GETATTR)) { + error = VOP_GETATTR(vp, vap); + } else { + get_mplock(); + error = VOP_GETATTR(vp, vap); + rel_mplock(); + } if (error) return (error); @@ -1035,7 +1042,9 @@ vn_stat(struct vnode *vp, struct stat *sb, struct ucred *cred) */ dev = vp->v_rdev; if (dev == NULL && vp->v_type == VCHR) { + get_mplock(); dev = get_dev(vp->v_umajor, vp->v_uminor); + rel_mplock(); } sb->st_blksize = dev->si_bsize_best; if (sb->st_blksize < dev->si_bsize_phys)