kernel - Fix pty clone vnode leak
authorMatthew Dillon <dillon@apollo.backplane.com>
Fri, 13 Aug 2010 01:20:41 +0000 (18:20 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Fri, 13 Aug 2010 01:20:41 +0000 (18:20 -0700)
* Any cloned devfs device (vn, tap, ptmx primarily) was leaving an extra
  vref on the related vnode, preventing the vnode from being recycled.

  This was due to devfs called vop_stdopen() but forgetting that
  vop_stdopen() will load the file pointer (fp), which devfs was also
  loading.  All devfs really needs to do is to replace fp->f_ops.

Reported-by: swildner
sys/vfs/devfs/devfs_vnops.c

index 9d6272e..9fb5ced 100644 (file)
@@ -975,18 +975,23 @@ devfs_spec_open(struct vop_open_args *ap)
                nanotime(&node->atime);
 #endif
 
+       /*
+        * If we replaced the vp the vop_stdopen() call will have loaded
+        * it into fp->f_data and vref()d the vp, giving us two refs.  So
+        * instead of just unlocking it here we have to vput() it.
+        */
        if (orig_vp)
-               vn_unlock(vp);
+               vput(vp);
 
        /* Ugly pty magic, to make pty devices appear once they are opened */
        if (node && (node->flags & DEVFS_PTY) == DEVFS_PTY)
                node->flags &= ~DEVFS_INVISIBLE;
 
        if (ap->a_fp) {
-               ap->a_fp->f_type = DTYPE_VNODE;
-               ap->a_fp->f_flag = ap->a_mode & FMASK;
+               KKASSERT(ap->a_fp->f_type == DTYPE_VNODE);
+               KKASSERT(ap->a_fp->f_flag == (ap->a_mode & FMASK));
                ap->a_fp->f_ops = &devfs_dev_fileops;
-               ap->a_fp->f_data = vp;
+               KKASSERT(ap->a_fp->f_data == (void *)vp);
        }
 
        return 0;