uipc_mqueue.c (b042e9760c883141a393d0346334e2b24e439776) | uipc_mqueue.c (fbc48e974efbca2b6b3eb52b581b97df5707e0d6) |
---|---|
1/*- 2 * Copyright (c) 2005 David Xu <davidxu@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 359 unchanged lines hidden (view full) --- 368mqnode_addref(struct mqfs_node *node) 369{ 370 atomic_fetchadd_int(&node->mn_refcount, 1); 371} 372 373static __inline void 374mqnode_release(struct mqfs_node *node) 375{ | 1/*- 2 * Copyright (c) 2005 David Xu <davidxu@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 359 unchanged lines hidden (view full) --- 368mqnode_addref(struct mqfs_node *node) 369{ 370 atomic_fetchadd_int(&node->mn_refcount, 1); 371} 372 373static __inline void 374mqnode_release(struct mqfs_node *node) 375{ |
376 struct mqfs_info *mqfs; |
|
376 int old, exp; 377 | 377 int old, exp; 378 |
379 mqfs = node->mn_info; |
|
378 old = atomic_fetchadd_int(&node->mn_refcount, -1); 379 if (node->mn_type == mqfstype_dir || 380 node->mn_type == mqfstype_root) 381 exp = 3; /* include . and .. */ 382 else 383 exp = 1; | 380 old = atomic_fetchadd_int(&node->mn_refcount, -1); 381 if (node->mn_type == mqfstype_dir || 382 node->mn_type == mqfstype_root) 383 exp = 3; /* include . and .. */ 384 else 385 exp = 1; |
384 if (old == exp) | 386 if (old == exp) { 387 int locked = sx_xlocked(&mqfs->mi_lock); 388 if (!locked) 389 sx_xlock(&mqfs->mi_lock); |
385 mqfs_destroy(node); | 390 mqfs_destroy(node); |
391 if (!locked) 392 sx_xunlock(&mqfs->mi_lock); 393 } |
|
386} 387 388/* 389 * Add a node to a directory 390 */ 391static int 392mqfs_add_node(struct mqfs_node *parent, struct mqfs_node *node) 393{ --- 18 unchanged lines hidden (view full) --- 412 int nodetype) 413{ 414 struct mqfs_node *node; 415 416 node = mqnode_alloc(); 417 strncpy(node->mn_name, name, namelen); 418 node->mn_type = nodetype; 419 node->mn_refcount = 1; | 394} 395 396/* 397 * Add a node to a directory 398 */ 399static int 400mqfs_add_node(struct mqfs_node *parent, struct mqfs_node *node) 401{ --- 18 unchanged lines hidden (view full) --- 420 int nodetype) 421{ 422 struct mqfs_node *node; 423 424 node = mqnode_alloc(); 425 strncpy(node->mn_name, name, namelen); 426 node->mn_type = nodetype; 427 node->mn_refcount = 1; |
420 getnanotime(&node->mn_birth); | 428 vfs_timestamp(&node->mn_birth); |
421 node->mn_ctime = node->mn_atime = node->mn_mtime 422 = node->mn_birth; 423 node->mn_uid = cred->cr_uid; 424 node->mn_gid = cred->cr_gid; 425 node->mn_mode = mode; 426 return (node); 427} 428 --- 167 unchanged lines hidden (view full) --- 596 */ 597static int 598mqfs_root(struct mount *mp, int flags, struct vnode **vpp, struct thread *td) 599{ 600 struct mqfs_info *mqfs; 601 int ret; 602 603 mqfs = VFSTOMQFS(mp); | 429 node->mn_ctime = node->mn_atime = node->mn_mtime 430 = node->mn_birth; 431 node->mn_uid = cred->cr_uid; 432 node->mn_gid = cred->cr_gid; 433 node->mn_mode = mode; 434 return (node); 435} 436 --- 167 unchanged lines hidden (view full) --- 604 */ 605static int 606mqfs_root(struct mount *mp, int flags, struct vnode **vpp, struct thread *td) 607{ 608 struct mqfs_info *mqfs; 609 int ret; 610 611 mqfs = VFSTOMQFS(mp); |
604 sx_xlock(&mqfs->mi_lock); | |
605 ret = mqfs_allocv(mp, vpp, mqfs->mi_root); | 612 ret = mqfs_allocv(mp, vpp, mqfs->mi_root); |
606 sx_xunlock(&mqfs->mi_lock); | |
607 return (ret); 608} 609 610/* 611 * Return filesystem stats 612 */ 613static int 614mqfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td) --- 76 unchanged lines hidden (view full) --- 691 692/* 693 * Allocate a vnode 694 */ 695static int 696mqfs_allocv(struct mount *mp, struct vnode **vpp, struct mqfs_node *pn) 697{ 698 struct mqfs_vdata *vd; | 613 return (ret); 614} 615 616/* 617 * Return filesystem stats 618 */ 619static int 620mqfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td) --- 76 unchanged lines hidden (view full) --- 697 698/* 699 * Allocate a vnode 700 */ 701static int 702mqfs_allocv(struct mount *mp, struct vnode **vpp, struct mqfs_node *pn) 703{ 704 struct mqfs_vdata *vd; |
705 struct mqfs_info *mqfs; 706 struct vnode *newvpp; |
|
699 int error; 700 | 707 int error; 708 |
709 mqfs = pn->mn_info; 710 *vpp = NULL; 711 sx_xlock(&mqfs->mi_lock); |
|
701 LIST_FOREACH(vd, &pn->mn_vnodes, mv_link) { | 712 LIST_FOREACH(vd, &pn->mn_vnodes, mv_link) { |
702 if (vd->mv_vnode->v_mount == mp) | 713 if (vd->mv_vnode->v_mount == mp) { 714 vhold(vd->mv_vnode); |
703 break; | 715 break; |
716 } |
|
704 } 705 706 if (vd != NULL) { | 717 } 718 719 if (vd != NULL) { |
720found: |
|
707 *vpp = vd->mv_vnode; | 721 *vpp = vd->mv_vnode; |
708 vget(*vpp, LK_RETRY | LK_EXCLUSIVE, curthread); 709 return (0); | 722 sx_xunlock(&mqfs->mi_lock); 723 error = vget(*vpp, LK_RETRY | LK_EXCLUSIVE, curthread); 724 vdrop(*vpp); 725 return (error); |
710 } | 726 } |
727 sx_xunlock(&mqfs->mi_lock); |
|
711 | 728 |
712 error = getnewvnode("mqueue", mp, &mqfs_vnodeops, vpp); | 729 error = getnewvnode("mqueue", mp, &mqfs_vnodeops, &newvpp); |
713 if (error) 714 return (error); | 730 if (error) 731 return (error); |
715 vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY); 716 error = insmntque(*vpp, mp); 717 if (error != 0) { 718 *vpp = NULLVP; | 732 vn_lock(newvpp, LK_EXCLUSIVE | LK_RETRY); 733 error = insmntque(newvpp, mp); 734 if (error != 0) |
719 return (error); | 735 return (error); |
736 737 sx_xlock(&mqfs->mi_lock); 738 /* 739 * Check if it has already been allocated 740 * while we were blocked. 741 */ 742 LIST_FOREACH(vd, &pn->mn_vnodes, mv_link) { 743 if (vd->mv_vnode->v_mount == mp) { 744 vhold(vd->mv_vnode); 745 sx_xunlock(&mqfs->mi_lock); 746 747 vgone(newvpp); 748 vput(newvpp); 749 goto found; 750 } |
|
720 } | 751 } |
752 753 *vpp = newvpp; 754 |
|
721 vd = uma_zalloc(mvdata_zone, M_WAITOK); 722 (*vpp)->v_data = vd; 723 vd->mv_vnode = *vpp; 724 vd->mv_node = pn; 725 TASK_INIT(&vd->mv_task, 0, do_recycle, *vpp); 726 LIST_INSERT_HEAD(&pn->mn_vnodes, vd, mv_link); 727 mqnode_addref(pn); 728 switch (pn->mn_type) { --- 11 unchanged lines hidden (view full) --- 740 case mqfstype_symlink: 741 (*vpp)->v_type = VLNK; 742 break; 743 case mqfstype_none: 744 KASSERT(0, ("mqfs_allocf called for null node\n")); 745 default: 746 panic("%s has unexpected type: %d", pn->mn_name, pn->mn_type); 747 } | 755 vd = uma_zalloc(mvdata_zone, M_WAITOK); 756 (*vpp)->v_data = vd; 757 vd->mv_vnode = *vpp; 758 vd->mv_node = pn; 759 TASK_INIT(&vd->mv_task, 0, do_recycle, *vpp); 760 LIST_INSERT_HEAD(&pn->mn_vnodes, vd, mv_link); 761 mqnode_addref(pn); 762 switch (pn->mn_type) { --- 11 unchanged lines hidden (view full) --- 774 case mqfstype_symlink: 775 (*vpp)->v_type = VLNK; 776 break; 777 case mqfstype_none: 778 KASSERT(0, ("mqfs_allocf called for null node\n")); 779 default: 780 panic("%s has unexpected type: %d", pn->mn_name, pn->mn_type); 781 } |
782 sx_xunlock(&mqfs->mi_lock); |
|
748 return (0); 749} 750 751/* 752 * Search a directory entry 753 */ 754static struct mqfs_node * 755mqfs_search(struct mqfs_node *pd, const char *name, int len) 756{ 757 struct mqfs_node *pn; 758 | 783 return (0); 784} 785 786/* 787 * Search a directory entry 788 */ 789static struct mqfs_node * 790mqfs_search(struct mqfs_node *pd, const char *name, int len) 791{ 792 struct mqfs_node *pn; 793 |
794 sx_assert(&pd->mn_info->mi_lock, SX_LOCKED); |
|
759 LIST_FOREACH(pn, &pd->mn_children, mn_sibling) { 760 if (strncmp(pn->mn_name, name, len) == 0) 761 return (pn); 762 } 763 return (NULL); 764} 765 766/* 767 * Look up a file or directory. 768 */ 769static int 770mqfs_lookupx(struct vop_cachedlookup_args *ap) 771{ 772 struct componentname *cnp; 773 struct vnode *dvp, **vpp; 774 struct mqfs_node *pd; 775 struct mqfs_node *pn; | 795 LIST_FOREACH(pn, &pd->mn_children, mn_sibling) { 796 if (strncmp(pn->mn_name, name, len) == 0) 797 return (pn); 798 } 799 return (NULL); 800} 801 802/* 803 * Look up a file or directory. 804 */ 805static int 806mqfs_lookupx(struct vop_cachedlookup_args *ap) 807{ 808 struct componentname *cnp; 809 struct vnode *dvp, **vpp; 810 struct mqfs_node *pd; 811 struct mqfs_node *pn; |
812 struct mqfs_info *mqfs; |
|
776 int nameiop, flags, error, namelen; 777 char *pname; 778 struct thread *td; 779 780 cnp = ap->a_cnp; 781 vpp = ap->a_vpp; 782 dvp = ap->a_dvp; 783 pname = cnp->cn_nameptr; 784 namelen = cnp->cn_namelen; 785 td = cnp->cn_thread; 786 flags = cnp->cn_flags; 787 nameiop = cnp->cn_nameiop; 788 pd = VTON(dvp); 789 pn = NULL; | 813 int nameiop, flags, error, namelen; 814 char *pname; 815 struct thread *td; 816 817 cnp = ap->a_cnp; 818 vpp = ap->a_vpp; 819 dvp = ap->a_dvp; 820 pname = cnp->cn_nameptr; 821 namelen = cnp->cn_namelen; 822 td = cnp->cn_thread; 823 flags = cnp->cn_flags; 824 nameiop = cnp->cn_nameiop; 825 pd = VTON(dvp); 826 pn = NULL; |
827 mqfs = pd->mn_info; |
|
790 *vpp = NULLVP; 791 792 if (dvp->v_type != VDIR) 793 return (ENOTDIR); 794 795 error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, cnp->cn_thread); 796 if (error) 797 return (error); --- 22 unchanged lines hidden (view full) --- 820 KASSERT(pd->mn_parent, ("non-root directory has no parent")); 821 pn = pd->mn_parent; 822 error = mqfs_allocv(dvp->v_mount, vpp, pn); 823 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); 824 return (error); 825 } 826 827 /* named node */ | 828 *vpp = NULLVP; 829 830 if (dvp->v_type != VDIR) 831 return (ENOTDIR); 832 833 error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, cnp->cn_thread); 834 if (error) 835 return (error); --- 22 unchanged lines hidden (view full) --- 858 KASSERT(pd->mn_parent, ("non-root directory has no parent")); 859 pn = pd->mn_parent; 860 error = mqfs_allocv(dvp->v_mount, vpp, pn); 861 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); 862 return (error); 863 } 864 865 /* named node */ |
866 sx_xlock(&mqfs->mi_lock); |
|
828 pn = mqfs_search(pd, pname, namelen); | 867 pn = mqfs_search(pd, pname, namelen); |
868 if (pn != NULL) 869 mqnode_addref(pn); 870 sx_xunlock(&mqfs->mi_lock); |
|
829 830 /* found */ 831 if (pn != NULL) { 832 /* DELETE */ 833 if (nameiop == DELETE && (flags & ISLASTCN)) { 834 error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td); | 871 872 /* found */ 873 if (pn != NULL) { 874 /* DELETE */ 875 if (nameiop == DELETE && (flags & ISLASTCN)) { 876 error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td); |
835 if (error) | 877 if (error) { 878 mqnode_release(pn); |
836 return (error); | 879 return (error); |
880 } |
|
837 if (*vpp == dvp) { 838 VREF(dvp); 839 *vpp = dvp; | 881 if (*vpp == dvp) { 882 VREF(dvp); 883 *vpp = dvp; |
884 mqnode_release(pn); |
|
840 return (0); 841 } 842 } 843 844 /* allocate vnode */ 845 error = mqfs_allocv(dvp->v_mount, vpp, pn); | 885 return (0); 886 } 887 } 888 889 /* allocate vnode */ 890 error = mqfs_allocv(dvp->v_mount, vpp, pn); |
891 mqnode_release(pn); |
|
846 if (error == 0 && cnp->cn_flags & MAKEENTRY) 847 cache_enter(dvp, *vpp, cnp); 848 return (error); 849 } 850 851 /* not found */ 852 853 /* will create a new entry in the directory ? */ --- 18 unchanged lines hidden (view full) --- 872#endif 873 874/* 875 * vnode lookup operation 876 */ 877static int 878mqfs_lookup(struct vop_cachedlookup_args *ap) 879{ | 892 if (error == 0 && cnp->cn_flags & MAKEENTRY) 893 cache_enter(dvp, *vpp, cnp); 894 return (error); 895 } 896 897 /* not found */ 898 899 /* will create a new entry in the directory ? */ --- 18 unchanged lines hidden (view full) --- 918#endif 919 920/* 921 * vnode lookup operation 922 */ 923static int 924mqfs_lookup(struct vop_cachedlookup_args *ap) 925{ |
880 struct mqfs_info *mqfs = VFSTOMQFS(ap->a_dvp->v_mount); | |
881 int rc; 882 | 926 int rc; 927 |
883 sx_xlock(&mqfs->mi_lock); | |
884 rc = mqfs_lookupx(ap); | 928 rc = mqfs_lookupx(ap); |
885 sx_xunlock(&mqfs->mi_lock); | |
886 return (rc); 887} 888 889#if 0 890struct vop_create_args { 891 struct vnode *a_dvp; 892 struct vnode **a_vpp; 893 struct componentname *a_cnp; --- 16 unchanged lines hidden (view full) --- 910 911 pd = VTON(ap->a_dvp); 912 if (pd->mn_type != mqfstype_root && pd->mn_type != mqfstype_dir) 913 return (ENOTDIR); 914 mq = mqueue_alloc(NULL); 915 if (mq == NULL) 916 return (EAGAIN); 917 sx_xlock(&mqfs->mi_lock); | 929 return (rc); 930} 931 932#if 0 933struct vop_create_args { 934 struct vnode *a_dvp; 935 struct vnode **a_vpp; 936 struct componentname *a_cnp; --- 16 unchanged lines hidden (view full) --- 953 954 pd = VTON(ap->a_dvp); 955 if (pd->mn_type != mqfstype_root && pd->mn_type != mqfstype_dir) 956 return (ENOTDIR); 957 mq = mqueue_alloc(NULL); 958 if (mq == NULL) 959 return (EAGAIN); 960 sx_xlock(&mqfs->mi_lock); |
918#if 0 919 /* named node */ 920 pn = mqfs_search(pd, cnp->cn_nameptr, cnp->cn_namelen); 921 if (pn != NULL) { 922 mqueue_free(mq); 923 sx_xunlock(&mqfs->mi_lock); 924 return (EEXIST); 925 } 926#else | |
927 if ((cnp->cn_flags & HASBUF) == 0) 928 panic("%s: no name", __func__); | 961 if ((cnp->cn_flags & HASBUF) == 0) 962 panic("%s: no name", __func__); |
929#endif | |
930 pn = mqfs_create_file(pd, cnp->cn_nameptr, cnp->cn_namelen, 931 cnp->cn_cred, ap->a_vap->va_mode); | 963 pn = mqfs_create_file(pd, cnp->cn_nameptr, cnp->cn_namelen, 964 cnp->cn_cred, ap->a_vap->va_mode); |
932 if (pn == NULL) | 965 if (pn == NULL) { 966 sx_xunlock(&mqfs->mi_lock); |
933 error = ENOSPC; | 967 error = ENOSPC; |
934 else { | 968 } else { 969 mqnode_addref(pn); 970 sx_xunlock(&mqfs->mi_lock); |
935 error = mqfs_allocv(ap->a_dvp->v_mount, ap->a_vpp, pn); | 971 error = mqfs_allocv(ap->a_dvp->v_mount, ap->a_vpp, pn); |
972 mqnode_release(pn); |
|
936 if (error) 937 mqfs_destroy(pn); 938 else 939 pn->mn_data = mq; 940 } | 973 if (error) 974 mqfs_destroy(pn); 975 else 976 pn->mn_data = mq; 977 } |
941 sx_xunlock(&mqfs->mi_lock); | |
942 if (error) 943 mqueue_free(mq); 944 return (error); 945} 946 947/* 948 * Remove an entry 949 */ --- 457 unchanged lines hidden (view full) --- 1407 struct componentname *cnp = ap->a_cnp; 1408 struct mqfs_node *pd = VTON(ap->a_dvp); 1409 struct mqfs_node *pn; 1410 int error; 1411 1412 if (pd->mn_type != mqfstype_root && pd->mn_type != mqfstype_dir) 1413 return (ENOTDIR); 1414 sx_xlock(&mqfs->mi_lock); | 978 if (error) 979 mqueue_free(mq); 980 return (error); 981} 982 983/* 984 * Remove an entry 985 */ --- 457 unchanged lines hidden (view full) --- 1443 struct componentname *cnp = ap->a_cnp; 1444 struct mqfs_node *pd = VTON(ap->a_dvp); 1445 struct mqfs_node *pn; 1446 int error; 1447 1448 if (pd->mn_type != mqfstype_root && pd->mn_type != mqfstype_dir) 1449 return (ENOTDIR); 1450 sx_xlock(&mqfs->mi_lock); |
1415#if 0 1416 /* named node */ 1417 pn = mqfs_search(pd, cnp->cn_nameptr, cnp->cn_namelen); 1418 if (pn != NULL) { 1419 sx_xunlock(&mqfs->mi_lock); 1420 return (EEXIST); 1421 } 1422#else | |
1423 if ((cnp->cn_flags & HASBUF) == 0) 1424 panic("%s: no name", __func__); | 1451 if ((cnp->cn_flags & HASBUF) == 0) 1452 panic("%s: no name", __func__); |
1425#endif | |
1426 pn = mqfs_create_dir(pd, cnp->cn_nameptr, cnp->cn_namelen, 1427 ap->a_vap->cn_cred, ap->a_vap->va_mode); | 1453 pn = mqfs_create_dir(pd, cnp->cn_nameptr, cnp->cn_namelen, 1454 ap->a_vap->cn_cred, ap->a_vap->va_mode); |
1428 if (pn == NULL) | 1455 if (pn != NULL) 1456 mqnode_addref(pn); 1457 sx_xunlock(&mqfs->mi_lock); 1458 if (pn == NULL) { |
1429 error = ENOSPC; | 1459 error = ENOSPC; |
1430 else | 1460 } else { |
1431 error = mqfs_allocv(ap->a_dvp->v_mount, ap->a_vpp, pn); | 1461 error = mqfs_allocv(ap->a_dvp->v_mount, ap->a_vpp, pn); |
1432 sx_xunlock(&mqfs->mi_lock); | 1462 mqnode_release(pn); 1463 } |
1433 return (error); 1434} 1435 1436#if 0 1437struct vop_rmdir_args { 1438 struct vnode *a_dvp; 1439 struct vnode *a_vp; 1440 struct componentname *a_cnp; --- 1045 unchanged lines hidden --- | 1464 return (error); 1465} 1466 1467#if 0 1468struct vop_rmdir_args { 1469 struct vnode *a_dvp; 1470 struct vnode *a_vp; 1471 struct componentname *a_cnp; --- 1045 unchanged lines hidden --- |