| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: p2k.c,v 1.50 2011/01/07 10:18:06 pooka Exp $ */ | | 1 | /* $NetBSD: p2k.c,v 1.51 2011/01/07 11:15:30 pooka Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2007, 2008, 2009 Antti Kantee. All Rights Reserved. | | 4 | * Copyright (c) 2007, 2008, 2009 Antti Kantee. All Rights Reserved. |
5 | * | | 5 | * |
6 | * Development of this software was supported by the | | 6 | * Development of this software was supported by the |
7 | * Finnish Cultural Foundation. | | 7 | * Finnish Cultural Foundation. |
8 | * | | 8 | * |
9 | * Redistribution and use in source and binary forms, with or without | | 9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions | | 10 | * modification, are permitted provided that the following conditions |
11 | * are met: | | 11 | * are met: |
12 | * 1. Redistributions of source code must retain the above copyright | | 12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. | | 13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright | | 14 | * 2. Redistributions in binary form must reproduce the above copyright |
| @@ -75,36 +75,26 @@ struct p2k_mount { | | | @@ -75,36 +75,26 @@ struct p2k_mount { |
75 | struct vnode *p2m_rvp; | | 75 | struct vnode *p2m_rvp; |
76 | struct puffs_usermount *p2m_pu; | | 76 | struct puffs_usermount *p2m_pu; |
77 | struct ukfs *p2m_ukfs; | | 77 | struct ukfs *p2m_ukfs; |
78 | struct p2k_vp_hash p2m_vphash[NHASHBUCK]; | | 78 | struct p2k_vp_hash p2m_vphash[NHASHBUCK]; |
79 | struct mount *p2m_mp; | | 79 | struct mount *p2m_mp; |
80 | int p2m_nvnodes; | | 80 | int p2m_nvnodes; |
81 | int p2m_imtmpfsman; | | 81 | int p2m_imtmpfsman; |
82 | bool p2m_hasdebug; | | 82 | bool p2m_hasdebug; |
83 | }; | | 83 | }; |
84 | | | 84 | |
85 | struct p2k_node { | | 85 | struct p2k_node { |
86 | struct vnode *p2n_vp; | | 86 | struct vnode *p2n_vp; |
87 | | | 87 | |
88 | /* | | | |
89 | * Ok, then, uhm, we need .. *drumroll*.. two componentname | | | |
90 | * storages for rename. This is because the source dir is | | | |
91 | * unlocked after the first lookup, and someone else might | | | |
92 | * race in here. However, we know it's not another rename | | | |
93 | * because of the kernel rename lock. And we need two since | | | |
94 | * srcdir and targdir might be the same. It's a wonderful world. | | | |
95 | */ | | | |
96 | struct componentname *p2n_cn_ren_src, *p2n_cn_ren_targ; | | | |
97 | | | | |
98 | LIST_ENTRY(p2k_node) p2n_entries; | | 88 | LIST_ENTRY(p2k_node) p2n_entries; |
99 | }; | | 89 | }; |
100 | | | 90 | |
101 | #define OPC2VP(opc) (((struct p2k_node *)opc)->p2n_vp) | | 91 | #define OPC2VP(opc) (((struct p2k_node *)opc)->p2n_vp) |
102 | | | 92 | |
103 | static int haswizard; | | 93 | static int haswizard; |
104 | static uid_t wizarduid; | | 94 | static uid_t wizarduid; |
105 | | | 95 | |
106 | static struct kauth_cred * | | 96 | static struct kauth_cred * |
107 | cred_create(const struct puffs_cred *pcr) | | 97 | cred_create(const struct puffs_cred *pcr) |
108 | { | | 98 | { |
109 | gid_t groups[NGROUPS]; | | 99 | gid_t groups[NGROUPS]; |
110 | uid_t uid; | | 100 | uid_t uid; |
| @@ -294,27 +284,26 @@ p2k_init(uint32_t puffs_flags) | | | @@ -294,27 +284,26 @@ p2k_init(uint32_t puffs_flags) |
294 | PUFFSOP_SET(pops, p2k, node, rename); | | 284 | PUFFSOP_SET(pops, p2k, node, rename); |
295 | PUFFSOP_SET(pops, p2k, node, mkdir); | | 285 | PUFFSOP_SET(pops, p2k, node, mkdir); |
296 | PUFFSOP_SET(pops, p2k, node, rmdir); | | 286 | PUFFSOP_SET(pops, p2k, node, rmdir); |
297 | PUFFSOP_SET(pops, p2k, node, symlink); | | 287 | PUFFSOP_SET(pops, p2k, node, symlink); |
298 | PUFFSOP_SET(pops, p2k, node, readdir); | | 288 | PUFFSOP_SET(pops, p2k, node, readdir); |
299 | PUFFSOP_SET(pops, p2k, node, readlink); | | 289 | PUFFSOP_SET(pops, p2k, node, readlink); |
300 | PUFFSOP_SET(pops, p2k, node, read); | | 290 | PUFFSOP_SET(pops, p2k, node, read); |
301 | PUFFSOP_SET(pops, p2k, node, write); | | 291 | PUFFSOP_SET(pops, p2k, node, write); |
302 | | | 292 | |
303 | PUFFSOP_SET(pops, p2k, node, pathconf); | | 293 | PUFFSOP_SET(pops, p2k, node, pathconf); |
304 | | | 294 | |
305 | PUFFSOP_SET(pops, p2k, node, inactive); | | 295 | PUFFSOP_SET(pops, p2k, node, inactive); |
306 | PUFFSOP_SET(pops, p2k, node, reclaim); | | 296 | PUFFSOP_SET(pops, p2k, node, reclaim); |
307 | PUFFSOP_SET(pops, p2k, node, abortop); | | | |
308 | | | 297 | |
309 | PUFFSOP_SET(pops, p2k, node, getextattr); | | 298 | PUFFSOP_SET(pops, p2k, node, getextattr); |
310 | PUFFSOP_SET(pops, p2k, node, setextattr); | | 299 | PUFFSOP_SET(pops, p2k, node, setextattr); |
311 | PUFFSOP_SET(pops, p2k, node, listextattr); | | 300 | PUFFSOP_SET(pops, p2k, node, listextattr); |
312 | PUFFSOP_SET(pops, p2k, node, deleteextattr); | | 301 | PUFFSOP_SET(pops, p2k, node, deleteextattr); |
313 | | | 302 | |
314 | dodaemon = true; | | 303 | dodaemon = true; |
315 | hasdebug = false; | | 304 | hasdebug = false; |
316 | | | 305 | |
317 | if (getenv("P2K_DEBUG") != NULL) { | | 306 | if (getenv("P2K_DEBUG") != NULL) { |
318 | puffs_flags |= PUFFS_FLAG_OPDUMP; | | 307 | puffs_flags |= PUFFS_FLAG_OPDUMP; |
319 | dodaemon = false; | | 308 | dodaemon = false; |
320 | hasdebug = true; | | 309 | hasdebug = true; |
| @@ -667,77 +656,38 @@ p2k_node_lookup(struct puffs_usermount * | | | @@ -667,77 +656,38 @@ p2k_node_lookup(struct puffs_usermount * |
667 | struct p2k_mount *p2m = puffs_getspecific(pu); | | 656 | struct p2k_mount *p2m = puffs_getspecific(pu); |
668 | struct p2k_node *p2n_dir = opc, *p2n; | | 657 | struct p2k_node *p2n_dir = opc, *p2n; |
669 | struct componentname *cn; | | 658 | struct componentname *cn; |
670 | struct vnode *dvp = p2n_dir->p2n_vp, *vp; | | 659 | struct vnode *dvp = p2n_dir->p2n_vp, *vp; |
671 | enum vtype vtype; | | 660 | enum vtype vtype; |
672 | voff_t vsize; | | 661 | voff_t vsize; |
673 | uint64_t rdev; /* XXX: uint64_t because of stack overwrite in compat */ | | 662 | uint64_t rdev; /* XXX: uint64_t because of stack overwrite in compat */ |
674 | int rv; | | 663 | int rv; |
675 | | | 664 | |
676 | cn = makecn(pcn); | | 665 | cn = makecn(pcn); |
677 | RUMP_VOP_LOCK(dvp, LK_EXCLUSIVE); | | 666 | RUMP_VOP_LOCK(dvp, LK_EXCLUSIVE); |
678 | rv = RUMP_VOP_LOOKUP(dvp, &vp, cn); | | 667 | rv = RUMP_VOP_LOOKUP(dvp, &vp, cn); |
679 | RUMP_VOP_UNLOCK(dvp); | | 668 | RUMP_VOP_UNLOCK(dvp); |
680 | | | 669 | freecn(cn); |
681 | /* | | | |
682 | * XXX the rename lookup protocol is currently horribly | | | |
683 | * broken. We get 1) DELETE 2) DELETE with INRELOOKUP | | | |
684 | * 3) RENAME. Hold on to this like | | | |
685 | * it were the absolute truth for now. However, do | | | |
686 | * not sprinkle asserts based on this due to abovementioned | | | |
687 | * brokenness -- some file system drivers might not | | | |
688 | * even issue ABORT properly, so just free resources | | | |
689 | * on the fly and hope for the best. PR kern/42348 | | | |
690 | */ | | | |
691 | if (pcn->pcn_flags & RUMP_NAMEI_INRENAME) { | | | |
692 | if (pcn->pcn_nameiop == RUMP_NAMEI_DELETE) { | | | |
693 | /* save path from the first lookup */ | | | |
694 | if ((pcn->pcn_flags & RUMP_NAMEI_INRELOOKUP) == 0) { | | | |
695 | if (p2n_dir->p2n_cn_ren_src) | | | |
696 | freecn(p2n_dir->p2n_cn_ren_src); | | | |
697 | p2n_dir->p2n_cn_ren_src = cn; | | | |
698 | } else { | | | |
699 | freecn(cn); | | | |
700 | cn = NULL; | | | |
701 | } | | | |
702 | } else { | | | |
703 | assert(pcn->pcn_nameiop == RUMP_NAMEI_RENAME); | | | |
704 | if (p2n_dir->p2n_cn_ren_targ) | | | |
705 | freecn(p2n_dir->p2n_cn_ren_targ); | | | |
706 | p2n_dir->p2n_cn_ren_targ = cn; | | | |
707 | } | | | |
708 | } else { | | | |
709 | freecn(cn); | | | |
710 | } | | | |
711 | | | 670 | |
712 | if (rv) { | | 671 | if (rv) { |
713 | if (rv == EJUSTRETURN) { | | 672 | if (rv == EJUSTRETURN) { |
714 | rv = ENOENT; | | 673 | rv = ENOENT; |
715 | } | | 674 | } |
716 | return rv; | | 675 | return rv; |
717 | } | | 676 | } |
718 | RUMP_VOP_UNLOCK(vp); | | 677 | RUMP_VOP_UNLOCK(vp); |
719 | | | 678 | |
720 | p2n = getp2n(p2m, vp, false, NULL); | | 679 | p2n = getp2n(p2m, vp, false, NULL); |
721 | if (p2n == NULL) { | | 680 | if (p2n == NULL) { |
722 | if (pcn->pcn_flags & RUMP_NAMEI_INRENAME) { | | | |
723 | if (pcn->pcn_nameiop == RUMP_NAMEI_DELETE) { | | | |
724 | p2n_dir->p2n_cn_ren_src = NULL; | | | |
725 | } else { | | | |
726 | p2n_dir->p2n_cn_ren_targ = NULL; | | | |
727 | } | | | |
728 | | | | |
729 | RUMP_VOP_ABORTOP(dvp, cn); | | | |
730 | } | | | |
731 | return ENOMEM; | | 681 | return ENOMEM; |
732 | } | | 682 | } |
733 | | | 683 | |
734 | puffs_newinfo_setcookie(pni, p2n); | | 684 | puffs_newinfo_setcookie(pni, p2n); |
735 | rump_pub_getvninfo(vp, &vtype, &vsize, (void *)&rdev); | | 685 | rump_pub_getvninfo(vp, &vtype, &vsize, (void *)&rdev); |
736 | puffs_newinfo_setvtype(pni, vtype); | | 686 | puffs_newinfo_setvtype(pni, vtype); |
737 | puffs_newinfo_setsize(pni, vsize); | | 687 | puffs_newinfo_setsize(pni, vsize); |
738 | /* LINTED: yea, it'll lose accuracy, but that's life */ | | 688 | /* LINTED: yea, it'll lose accuracy, but that's life */ |
739 | puffs_newinfo_setrdev(pni, rdev); | | 689 | puffs_newinfo_setrdev(pni, rdev); |
740 | | | 690 | |
741 | return 0; | | 691 | return 0; |
742 | } | | 692 | } |
743 | | | 693 | |
| @@ -993,46 +943,26 @@ p2k_node_seek(struct puffs_usermount *pu | | | @@ -993,46 +943,26 @@ p2k_node_seek(struct puffs_usermount *pu |
993 | struct vnode *vp = OPC2VP(opc); | | 943 | struct vnode *vp = OPC2VP(opc); |
994 | struct kauth_cred *cred; | | 944 | struct kauth_cred *cred; |
995 | int rv; | | 945 | int rv; |
996 | | | 946 | |
997 | cred = cred_create(pcr); | | 947 | cred = cred_create(pcr); |
998 | RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); | | 948 | RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); |
999 | rv = RUMP_VOP_SEEK(vp, oldoff, newoff, cred); | | 949 | rv = RUMP_VOP_SEEK(vp, oldoff, newoff, cred); |
1000 | RUMP_VOP_UNLOCK(vp); | | 950 | RUMP_VOP_UNLOCK(vp); |
1001 | cred_destroy(cred); | | 951 | cred_destroy(cred); |
1002 | | | 952 | |
1003 | return rv; | | 953 | return rv; |
1004 | } | | 954 | } |
1005 | | | 955 | |
1006 | /*ARGSUSED*/ | | | |
1007 | int | | | |
1008 | p2k_node_abortop(struct puffs_usermount *pu, puffs_cookie_t opc, | | | |
1009 | const struct puffs_cn *pcn) | | | |
1010 | { | | | |
1011 | struct p2k_node *p2n_dir = opc; | | | |
1012 | struct componentname *cnp; | | | |
1013 | | | | |
1014 | if ((cnp = p2n_dir->p2n_cn_ren_src) != NULL) { | | | |
1015 | freecn(cnp); | | | |
1016 | p2n_dir->p2n_cn_ren_src = NULL; | | | |
1017 | } | | | |
1018 | if ((cnp = p2n_dir->p2n_cn_ren_targ) != NULL) { | | | |
1019 | freecn(cnp); | | | |
1020 | p2n_dir->p2n_cn_ren_targ = NULL; | | | |
1021 | } | | | |
1022 | | | | |
1023 | return 0; | | | |
1024 | } | | | |
1025 | | | | |
1026 | static int | | 956 | static int |
1027 | do_nukenode(struct p2k_node *p2n_dir, struct p2k_node *p2n, | | 957 | do_nukenode(struct p2k_node *p2n_dir, struct p2k_node *p2n, |
1028 | const struct puffs_cn *pcn, | | 958 | const struct puffs_cn *pcn, |
1029 | int (*nukefn)(struct vnode *, struct vnode *, struct componentname *)) | | 959 | int (*nukefn)(struct vnode *, struct vnode *, struct componentname *)) |
1030 | { | | 960 | { |
1031 | struct vnode *dvp = p2n_dir->p2n_vp, *vp = p2n->p2n_vp; | | 961 | struct vnode *dvp = p2n_dir->p2n_vp, *vp = p2n->p2n_vp; |
1032 | struct componentname *cn; | | 962 | struct componentname *cn; |
1033 | int rv; | | 963 | int rv; |
1034 | | | 964 | |
1035 | cn = makecn(pcn); | | 965 | cn = makecn(pcn); |
1036 | RUMP_VOP_LOCK(dvp, LK_EXCLUSIVE); | | 966 | RUMP_VOP_LOCK(dvp, LK_EXCLUSIVE); |
1037 | rump_pub_vp_incref(dvp); | | 967 | rump_pub_vp_incref(dvp); |
1038 | RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); | | 968 | RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); |
| @@ -1071,44 +1001,32 @@ p2k_node_link(struct puffs_usermount *pu | | | @@ -1071,44 +1001,32 @@ p2k_node_link(struct puffs_usermount *pu |
1071 | freecn(cn); | | 1001 | freecn(cn); |
1072 | | | 1002 | |
1073 | return rv; | | 1003 | return rv; |
1074 | } | | 1004 | } |
1075 | | | 1005 | |
1076 | /*ARGSUSED*/ | | 1006 | /*ARGSUSED*/ |
1077 | int | | 1007 | int |
1078 | p2k_node_rename(struct puffs_usermount *pu, | | 1008 | p2k_node_rename(struct puffs_usermount *pu, |
1079 | puffs_cookie_t src_dir, puffs_cookie_t src, | | 1009 | puffs_cookie_t src_dir, puffs_cookie_t src, |
1080 | const struct puffs_cn *pcn_src, | | 1010 | const struct puffs_cn *pcn_src, |
1081 | puffs_cookie_t targ_dir, puffs_cookie_t targ, | | 1011 | puffs_cookie_t targ_dir, puffs_cookie_t targ, |
1082 | const struct puffs_cn *pcn_targ) | | 1012 | const struct puffs_cn *pcn_targ) |
1083 | { | | 1013 | { |
1084 | struct p2k_node *p2n_srcdir = src_dir, *p2n_targdir = targ_dir; | | | |
1085 | struct vnode *dvp, *vp, *tdvp, *tvp = NULL; | | 1014 | struct vnode *dvp, *vp, *tdvp, *tvp = NULL; |
1086 | struct componentname *cn_src, *cn_targ; | | 1015 | struct componentname *cn_src, *cn_targ; |
1087 | int rv; | | 1016 | int rv; |
1088 | | | 1017 | |
1089 | if (p2n_srcdir->p2n_cn_ren_src) { | | 1018 | cn_src = makecn(pcn_src); |
1090 | cn_src = p2n_srcdir->p2n_cn_ren_src; | | 1019 | cn_targ = makecn(pcn_targ); |
1091 | p2n_srcdir->p2n_cn_ren_src = NULL; | | | |
1092 | } else { | | | |
1093 | cn_src = makecn(pcn_src); | | | |
1094 | } | | | |
1095 | | | | |
1096 | if (p2n_targdir->p2n_cn_ren_targ) { | | | |
1097 | cn_targ = p2n_targdir->p2n_cn_ren_targ; | | | |
1098 | p2n_targdir->p2n_cn_ren_targ = NULL; | | | |
1099 | } else { | | | |
1100 | cn_targ = makecn(pcn_targ); | | | |
1101 | } | | | |
1102 | | | 1020 | |
1103 | dvp = OPC2VP(src_dir); | | 1021 | dvp = OPC2VP(src_dir); |
1104 | vp = OPC2VP(src); | | 1022 | vp = OPC2VP(src); |
1105 | tdvp = OPC2VP(targ_dir); | | 1023 | tdvp = OPC2VP(targ_dir); |
1106 | if (targ) { | | 1024 | if (targ) { |
1107 | tvp = OPC2VP(targ); | | 1025 | tvp = OPC2VP(targ); |
1108 | } | | 1026 | } |
1109 | | | 1027 | |
1110 | rump_pub_vp_incref(dvp); | | 1028 | rump_pub_vp_incref(dvp); |
1111 | rump_pub_vp_incref(vp); | | 1029 | rump_pub_vp_incref(vp); |
1112 | RUMP_VOP_LOCK(tdvp, LK_EXCLUSIVE); | | 1030 | RUMP_VOP_LOCK(tdvp, LK_EXCLUSIVE); |
1113 | rump_pub_vp_incref(tdvp); | | 1031 | rump_pub_vp_incref(tdvp); |
1114 | if (tvp) { | | 1032 | if (tvp) { |