MPSAFE - Implement sysctl vfs.getattr_mpsafe, make fstat() MPSAFE
authorMatthew Dillon <dillon@apollo.backplane.com>
Tue, 14 Jul 2009 06:02:21 +0000 (23:02 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Tue, 14 Jul 2009 06:02:21 +0000 (23:02 -0700)
Make fstat() MPSAFE.  Adjust fileops->fo_stat functions to be MPSAFE as
necessary (uipc socket stat mainly).

sys/kern/sys_socket.c
sys/kern/syscalls.master
sys/kern/uipc_usrreq.c
sys/kern/vfs_subr.c
sys/kern/vfs_vnops.c

index 0cc3b78..1ed9ac8 100644 (file)
@@ -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);
 }
 
index 747ab01..3b2672e 100644 (file)
 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, \
index b51c9b9..7d7b095 100644 (file)
@@ -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);
 }
index de7d0f1..7b4b7df 100644 (file)
@@ -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)
index 357e2b2..8b8ac24 100644 (file)
@@ -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)