* Notify upper mounts about reclaimed or unlinked vnode. */
| 3871 | * Notify upper mounts about reclaimed or unlinked vnode. |
| 3872 | */ |
| 3873 | void |
| 3874 | vfs_notify_upper(struct vnode *vp, int event) |
| 3875 | { |
| 3876 | static struct vfsops vgonel_vfsops = { |
| 3877 | .vfs_reclaim_lowervp = notify_lowervp_vfs_dummy, |
| 3878 | .vfs_unlink_lowervp = notify_lowervp_vfs_dummy, |
| 3879 | }; |
| 3880 | struct mount *mp, *ump, *mmp; |
| 3881 | |
| 3882 | mp = vp->v_mount; |
| 3883 | if (mp == NULL) |
| 3884 | return; |
| 3885 | if (TAILQ_EMPTY(&mp->mnt_uppers)) |
| 3886 | return; |
| 3887 | |
| 3888 | mmp = malloc(sizeof(struct mount), M_TEMP, M_WAITOK | M_ZERO); |
| 3889 | mmp->mnt_op = &vgonel_vfsops; |
| 3890 | mmp->mnt_kern_flag |= MNTK_MARKER; |
| 3891 | MNT_ILOCK(mp); |
| 3892 | mp->mnt_kern_flag |= MNTK_VGONE_UPPER; |
| 3893 | for (ump = TAILQ_FIRST(&mp->mnt_uppers); ump != NULL;) { |
| 3894 | if ((ump->mnt_kern_flag & MNTK_MARKER) != 0) { |
| 3895 | ump = TAILQ_NEXT(ump, mnt_upper_link); |
| 3896 | continue; |
| 3897 | } |
| 3898 | TAILQ_INSERT_AFTER(&mp->mnt_uppers, ump, mmp, mnt_upper_link); |
| 3899 | MNT_IUNLOCK(mp); |
| 3900 | switch (event) { |
| 3901 | case VFS_NOTIFY_UPPER_RECLAIM: |
| 3902 | VFS_RECLAIM_LOWERVP(ump, vp); |
| 3903 | break; |
| 3904 | case VFS_NOTIFY_UPPER_UNLINK: |
| 3905 | VFS_UNLINK_LOWERVP(ump, vp); |
| 3906 | break; |
| 3907 | default: |
| 3908 | KASSERT(0, ("invalid event %d", event)); |
| 3909 | break; |
| 3910 | } |
| 3911 | MNT_ILOCK(mp); |
| 3912 | ump = TAILQ_NEXT(mmp, mnt_upper_link); |
| 3913 | TAILQ_REMOVE(&mp->mnt_uppers, mmp, mnt_upper_link); |
| 3914 | } |
| 3915 | free(mmp, M_TEMP); |
| 3916 | mp->mnt_kern_flag &= ~MNTK_VGONE_UPPER; |
| 3917 | if ((mp->mnt_kern_flag & MNTK_VGONE_WAITER) != 0) { |
| 3918 | mp->mnt_kern_flag &= ~MNTK_VGONE_WAITER; |
| 3919 | wakeup(&mp->mnt_uppers); |
| 3920 | } |
| 3921 | MNT_IUNLOCK(mp); |
| 3922 | } |
| 3923 | |
| 3924 | /* |
| 3925 | * vgone, with the vp interlock held. |
no test coverage detected