* Allocate a vnode */
| 733 | * Allocate a vnode |
| 734 | */ |
| 735 | static int |
| 736 | mqfs_allocv(struct mount *mp, struct vnode **vpp, struct mqfs_node *pn) |
| 737 | { |
| 738 | struct mqfs_vdata *vd; |
| 739 | struct mqfs_info *mqfs; |
| 740 | struct vnode *newvpp; |
| 741 | int error; |
| 742 | |
| 743 | mqfs = pn->mn_info; |
| 744 | *vpp = NULL; |
| 745 | sx_xlock(&mqfs->mi_lock); |
| 746 | LIST_FOREACH(vd, &pn->mn_vnodes, mv_link) { |
| 747 | if (vd->mv_vnode->v_mount == mp) { |
| 748 | vhold(vd->mv_vnode); |
| 749 | break; |
| 750 | } |
| 751 | } |
| 752 | |
| 753 | if (vd != NULL) { |
| 754 | found: |
| 755 | *vpp = vd->mv_vnode; |
| 756 | sx_xunlock(&mqfs->mi_lock); |
| 757 | error = vget(*vpp, LK_RETRY | LK_EXCLUSIVE); |
| 758 | vdrop(*vpp); |
| 759 | return (error); |
| 760 | } |
| 761 | sx_xunlock(&mqfs->mi_lock); |
| 762 | |
| 763 | error = getnewvnode("mqueue", mp, &mqfs_vnodeops, &newvpp); |
| 764 | if (error) |
| 765 | return (error); |
| 766 | vn_lock(newvpp, LK_EXCLUSIVE | LK_RETRY); |
| 767 | error = insmntque(newvpp, mp); |
| 768 | if (error != 0) |
| 769 | return (error); |
| 770 | |
| 771 | sx_xlock(&mqfs->mi_lock); |
| 772 | /* |
| 773 | * Check if it has already been allocated |
| 774 | * while we were blocked. |
| 775 | */ |
| 776 | LIST_FOREACH(vd, &pn->mn_vnodes, mv_link) { |
| 777 | if (vd->mv_vnode->v_mount == mp) { |
| 778 | vhold(vd->mv_vnode); |
| 779 | sx_xunlock(&mqfs->mi_lock); |
| 780 | |
| 781 | vgone(newvpp); |
| 782 | vput(newvpp); |
| 783 | goto found; |
| 784 | } |
| 785 | } |
| 786 | |
| 787 | *vpp = newvpp; |
| 788 | |
| 789 | vd = uma_zalloc(mvdata_zone, M_WAITOK); |
| 790 | (*vpp)->v_data = vd; |
| 791 | vd->mv_vnode = *vpp; |
| 792 | vd->mv_node = pn; |
no test coverage detected