From owner-svn-src-all@FreeBSD.ORG Mon Dec 24 13:01:08 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id D979AEC4; Mon, 24 Dec 2012 13:01:08 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id B5B8D8FC0A; Mon, 24 Dec 2012 13:01:08 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id qBOD18Ma008929; Mon, 24 Dec 2012 13:01:08 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id qBOD18Xh008926; Mon, 24 Dec 2012 13:01:08 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <201212241301.qBOD18Xh008926@svn.freebsd.org> From: Konstantin Belousov Date: Mon, 24 Dec 2012 13:01:08 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r244652 - in stable/9/sys: kern sys X-SVN-Group: stable-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 24 Dec 2012 13:01:08 -0000 Author: kib Date: Mon Dec 24 13:01:07 2012 New Revision: 244652 URL: http://svnweb.freebsd.org/changeset/base/244652 Log: MFC r240284: Add a facility for vgone() to inform the set of subscribed mounts about vnode reclamation. Typical use is for the bypass mounts like nullfs to get a notification about lower vnode going away. MFC r241225 (by avg): mount.h: MNTK_VGONE_UPPER and MNTK_VGONE_WAITER were supposed to be different Modified: stable/9/sys/kern/vfs_mount.c stable/9/sys/kern/vfs_subr.c stable/9/sys/sys/mount.h Directory Properties: stable/9/sys/ (props changed) Modified: stable/9/sys/kern/vfs_mount.c ============================================================================== --- stable/9/sys/kern/vfs_mount.c Mon Dec 24 12:54:12 2012 (r244651) +++ stable/9/sys/kern/vfs_mount.c Mon Dec 24 13:01:07 2012 (r244652) @@ -479,6 +479,7 @@ vfs_mount_alloc(struct vnode *vp, struct mac_mount_create(cred, mp); #endif arc4rand(&mp->mnt_hashseed, sizeof mp->mnt_hashseed, 0); + TAILQ_INIT(&mp->mnt_uppers); return (mp); } @@ -512,6 +513,7 @@ vfs_mount_destroy(struct mount *mp) vprint("", vp); panic("unmount: dangling vnode"); } + KASSERT(TAILQ_EMPTY(&mp->mnt_uppers), ("mnt_uppers")); if (mp->mnt_nvnodelistsize != 0) panic("vfs_mount_destroy: nonzero nvnodelistsize"); if (mp->mnt_activevnodelistsize != 0) @@ -1259,7 +1261,8 @@ dounmount(mp, flags, td) } MNT_ILOCK(mp); - if (mp->mnt_kern_flag & MNTK_UNMOUNT) { + if ((mp->mnt_kern_flag & MNTK_UNMOUNT) != 0 || + !TAILQ_EMPTY(&mp->mnt_uppers)) { MNT_IUNLOCK(mp); if (coveredvp) VOP_UNLOCK(coveredvp, 0); Modified: stable/9/sys/kern/vfs_subr.c ============================================================================== --- stable/9/sys/kern/vfs_subr.c Mon Dec 24 12:54:12 2012 (r244651) +++ stable/9/sys/kern/vfs_subr.c Mon Dec 24 13:01:07 2012 (r244652) @@ -2741,6 +2741,58 @@ vgone(struct vnode *vp) VI_UNLOCK(vp); } +static void +vgonel_reclaim_lowervp_vfs(struct mount *mp __unused, + struct vnode *lowervp __unused) +{ +} + +/* + * Notify upper mounts about reclaimed vnode. + */ +static void +vgonel_reclaim_lowervp(struct vnode *vp) +{ + static struct vfsops vgonel_vfsops = { + .vfs_reclaim_lowervp = vgonel_reclaim_lowervp_vfs + }; + struct mount *mp, *ump, *mmp; + + mp = vp->v_mount; + if (mp == NULL) + return; + + MNT_ILOCK(mp); + if (TAILQ_EMPTY(&mp->mnt_uppers)) + goto unlock; + MNT_IUNLOCK(mp); + mmp = malloc(sizeof(struct mount), M_TEMP, M_WAITOK | M_ZERO); + mmp->mnt_op = &vgonel_vfsops; + mmp->mnt_kern_flag |= MNTK_MARKER; + MNT_ILOCK(mp); + mp->mnt_kern_flag |= MNTK_VGONE_UPPER; + for (ump = TAILQ_FIRST(&mp->mnt_uppers); ump != NULL;) { + if ((ump->mnt_kern_flag & MNTK_MARKER) != 0) { + ump = TAILQ_NEXT(ump, mnt_upper_link); + continue; + } + TAILQ_INSERT_AFTER(&mp->mnt_uppers, ump, mmp, mnt_upper_link); + MNT_IUNLOCK(mp); + VFS_RECLAIM_LOWERVP(ump, vp); + MNT_ILOCK(mp); + ump = TAILQ_NEXT(mmp, mnt_upper_link); + TAILQ_REMOVE(&mp->mnt_uppers, mmp, mnt_upper_link); + } + free(mmp, M_TEMP); + mp->mnt_kern_flag &= ~MNTK_VGONE_UPPER; + if ((mp->mnt_kern_flag & MNTK_VGONE_WAITER) != 0) { + mp->mnt_kern_flag &= ~MNTK_VGONE_WAITER; + wakeup(&mp->mnt_uppers); + } +unlock: + MNT_IUNLOCK(mp); +} + /* * vgone, with the vp interlock held. */ @@ -2765,6 +2817,7 @@ vgonel(struct vnode *vp) if (vp->v_iflag & VI_DOOMED) return; vp->v_iflag |= VI_DOOMED; + /* * Check to see if the vnode is in use. If so, we have to call * VOP_CLOSE() and VOP_INACTIVE(). @@ -2772,6 +2825,8 @@ vgonel(struct vnode *vp) active = vp->v_usecount; oweinact = (vp->v_iflag & VI_OWEINACT); VI_UNLOCK(vp); + vgonel_reclaim_lowervp(vp); + /* * Clean out any buffers associated with the vnode. * If the flush fails, just toss the buffers. Modified: stable/9/sys/sys/mount.h ============================================================================== --- stable/9/sys/sys/mount.h Mon Dec 24 12:54:12 2012 (r244651) +++ stable/9/sys/sys/mount.h Mon Dec 24 13:01:07 2012 (r244652) @@ -189,6 +189,8 @@ struct mount { #define mnt_endzero mnt_gjprovider char *mnt_gjprovider; /* gjournal provider name */ struct lock mnt_explock; /* vfs_export walkers lock */ + TAILQ_ENTRY(mount) mnt_upper_link; /* (m) we in the all uppers */ + TAILQ_HEAD(, mount) mnt_uppers; /* (m) upper mounts over us*/ }; /* @@ -369,7 +371,10 @@ void __mnt_vnode_markerfree(str #define MNTK_NO_IOPF 0x00000100 /* Disallow page faults during reads and writes. Filesystem shall properly handle i/o state on EFAULT. */ +#define MNTK_VGONE_UPPER 0x00000200 +#define MNTK_VGONE_WAITER 0x00000400 #define MNTK_LOOKUP_EXCL_DOTDOT 0x00000800 +#define MNTK_MARKER 0x00001000 #define MNTK_NOASYNC 0x00800000 /* disable async */ #define MNTK_UNMOUNT 0x01000000 /* unmount in progress */ #define MNTK_MWAIT 0x02000000 /* waiting for unmount to finish */ @@ -625,6 +630,7 @@ typedef int vfs_mount_t(struct mount *mp typedef int vfs_sysctl_t(struct mount *mp, fsctlop_t op, struct sysctl_req *req); typedef void vfs_susp_clean_t(struct mount *mp); +typedef void vfs_reclaim_lowervp_t(struct mount *mp, struct vnode *lowervp); struct vfsops { vfs_mount_t *vfs_mount; @@ -642,6 +648,7 @@ struct vfsops { vfs_extattrctl_t *vfs_extattrctl; vfs_sysctl_t *vfs_sysctl; vfs_susp_clean_t *vfs_susp_clean; + vfs_reclaim_lowervp_t *vfs_reclaim_lowervp; }; vfs_statfs_t __vfs_statfs; @@ -667,6 +674,9 @@ vfs_statfs_t __vfs_statfs; #define VFS_SUSP_CLEAN(MP) \ ({if (*(MP)->mnt_op->vfs_susp_clean != NULL) \ (*(MP)->mnt_op->vfs_susp_clean)(MP); }) +#define VFS_RECLAIM_LOWERVP(MP, VP) \ + ({if (*(MP)->mnt_op->vfs_reclaim_lowervp != NULL) \ + (*(MP)->mnt_op->vfs_reclaim_lowervp)((MP), (VP)); }) #define VFS_NEEDSGIANT_(MP) \ ((MP) != NULL && ((MP)->mnt_kern_flag & MNTK_MPSAFE) == 0)