| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: ops.c,v 1.6 2010/09/02 08:58:06 manu Exp $ */ | | 1 | /* $NetBSD: ops.c,v 1.7 2010/09/03 07:15:18 manu Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved. | | 4 | * Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved. |
5 | * | | 5 | * |
6 | * Redistribution and use in source and binary forms, with or without | | 6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions | | 7 | * modification, are permitted provided that the following conditions |
8 | * are met: | | 8 | * are met: |
9 | * 1. Redistributions of source code must retain the above copyright | | 9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. | | 10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright | | 11 | * 2. Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the | | 12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. | | 13 | * documentation and/or other materials provided with the distribution. |
14 | * | | 14 | * |
| @@ -31,26 +31,27 @@ | | | @@ -31,26 +31,27 @@ |
31 | #include <libgen.h> | | 31 | #include <libgen.h> |
32 | #include <errno.h> | | 32 | #include <errno.h> |
33 | #include <err.h> | | 33 | #include <err.h> |
34 | #include <sysexits.h> | | 34 | #include <sysexits.h> |
35 | #include <syslog.h> | | 35 | #include <syslog.h> |
36 | #include <puffs.h> | | 36 | #include <puffs.h> |
37 | #include <sys/vnode.h> | | 37 | #include <sys/vnode.h> |
38 | #include <sys/socket.h> | | 38 | #include <sys/socket.h> |
39 | #include <machine/vmparam.h> | | 39 | #include <machine/vmparam.h> |
40 | | | 40 | |
41 | #include "perfuse_priv.h" | | 41 | #include "perfuse_priv.h" |
42 | #include "fuse.h" | | 42 | #include "fuse.h" |
43 | | | 43 | |
| | | 44 | static int node_close_common(struct puffs_usermount *, puffs_cookie_t, int); |
44 | static int no_access(puffs_cookie_t, const struct puffs_cred *, mode_t); | | 45 | static int no_access(puffs_cookie_t, const struct puffs_cred *, mode_t); |
45 | static void fuse_attr_to_vap(struct perfuse_state *, | | 46 | static void fuse_attr_to_vap(struct perfuse_state *, |
46 | struct vattr *, struct fuse_attr *); | | 47 | struct vattr *, struct fuse_attr *); |
47 | static int node_lookup_dir_nodot(struct puffs_usermount *, | | 48 | static int node_lookup_dir_nodot(struct puffs_usermount *, |
48 | puffs_cookie_t, char *, size_t, struct puffs_node **); | | 49 | puffs_cookie_t, char *, size_t, struct puffs_node **); |
49 | static int node_lookup_common(struct puffs_usermount *, puffs_cookie_t, | | 50 | static int node_lookup_common(struct puffs_usermount *, puffs_cookie_t, |
50 | const char*, struct puffs_node **); | | 51 | const char*, struct puffs_node **); |
51 | static int node_mk_common(struct puffs_usermount *, puffs_cookie_t, | | 52 | static int node_mk_common(struct puffs_usermount *, puffs_cookie_t, |
52 | struct puffs_newinfo *, const struct puffs_cn *pcn, perfuse_msg_t *); | | 53 | struct puffs_newinfo *, const struct puffs_cn *pcn, perfuse_msg_t *); |
53 | static const char *basename_r(const char *); | | 54 | static const char *basename_r(const char *); |
54 | static ssize_t fuse_to_dirent(struct puffs_usermount *, puffs_cookie_t, | | 55 | static ssize_t fuse_to_dirent(struct puffs_usermount *, puffs_cookie_t, |
55 | struct fuse_dirent *, size_t); | | 56 | struct fuse_dirent *, size_t); |
56 | static int readdir_buffered(struct perfuse_state *, puffs_cookie_t, | | 57 | static int readdir_buffered(struct perfuse_state *, puffs_cookie_t, |
| @@ -64,42 +65,111 @@ static void dequeue_requests(struct perf | | | @@ -64,42 +65,111 @@ static void dequeue_requests(struct perf |
64 | | | 65 | |
65 | /* | | 66 | /* |
66 | * From <sys/vnode>, inside #ifdef _KERNEL section | | 67 | * From <sys/vnode>, inside #ifdef _KERNEL section |
67 | */ | | 68 | */ |
68 | #define IO_SYNC (0x40|IO_DSYNC) | | 69 | #define IO_SYNC (0x40|IO_DSYNC) |
69 | #define IO_DSYNC 0x00200 | | 70 | #define IO_DSYNC 0x00200 |
70 | #define IO_DIRECT 0x02000 | | 71 | #define IO_DIRECT 0x02000 |
71 | | | 72 | |
72 | /* | | 73 | /* |
73 | * From <fcntl>, inside #ifdef _KERNEL section | | 74 | * From <fcntl>, inside #ifdef _KERNEL section |
74 | */ | | 75 | */ |
75 | #define F_WAIT 0x010 | | 76 | #define F_WAIT 0x010 |
76 | #define F_FLOCK 0x020 | | 77 | #define F_FLOCK 0x020 |
| | | 78 | #define OFLAGS(fflags) ((fflags) - 1) |
77 | | | 79 | |
78 | /* | | 80 | /* |
79 | * Borrowed from src/sys/kern/vfs_subr.c and src/sys/sys/vnode.h | | 81 | * Borrowed from src/sys/kern/vfs_subr.c and src/sys/sys/vnode.h |
80 | */ | | 82 | */ |
81 | const enum vtype iftovt_tab[16] = { | | 83 | const enum vtype iftovt_tab[16] = { |
82 | VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON, | | 84 | VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON, |
83 | VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD, | | 85 | VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD, |
84 | }; | | 86 | }; |
85 | const int vttoif_tab[9] = { | | 87 | const int vttoif_tab[9] = { |
86 | 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, | | 88 | 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, |
87 | S_IFSOCK, S_IFIFO, S_IFMT, | | 89 | S_IFSOCK, S_IFIFO, S_IFMT, |
88 | }; | | 90 | }; |
89 | | | 91 | |
90 | #define IFTOVT(mode) (iftovt_tab[((mode) & S_IFMT) >> 12]) | | 92 | #define IFTOVT(mode) (iftovt_tab[((mode) & S_IFMT) >> 12]) |
91 | #define VTTOIF(indx) (vttoif_tab[(int)(indx)]) | | 93 | #define VTTOIF(indx) (vttoif_tab[(int)(indx)]) |
92 | | | 94 | |
| | | 95 | static int |
| | | 96 | node_close_common(pu, opc, mode) |
| | | 97 | struct puffs_usermount *pu; |
| | | 98 | puffs_cookie_t opc; |
| | | 99 | int mode; |
| | | 100 | { |
| | | 101 | struct perfuse_state *ps; |
| | | 102 | perfuse_msg_t *pm; |
| | | 103 | int op; |
| | | 104 | uint64_t fh; |
| | | 105 | struct fuse_release_in *fri; |
| | | 106 | struct perfuse_node_data *pnd; |
| | | 107 | struct puffs_node *pn; |
| | | 108 | int error; |
| | | 109 | |
| | | 110 | ps = puffs_getspecific(pu); |
| | | 111 | pn = (struct puffs_node *)opc; |
| | | 112 | pnd = PERFUSE_NODE_DATA(pn); |
| | | 113 | |
| | | 114 | if (puffs_pn_getvap(pn)->va_type == VDIR) { |
| | | 115 | op = FUSE_RELEASEDIR; |
| | | 116 | mode = FREAD; |
| | | 117 | } else { |
| | | 118 | op = FUSE_RELEASE; |
| | | 119 | } |
| | | 120 | |
| | | 121 | /* |
| | | 122 | * Destroy the filehandle before sending the |
| | | 123 | * request to the FUSE filesystem, otherwise |
| | | 124 | * we may get a second close() while we wait |
| | | 125 | * for the reply, and we would end up closing |
| | | 126 | * the same fh twice instead of closng both. |
| | | 127 | */ |
| | | 128 | fh = perfuse_get_fh(opc, mode); |
| | | 129 | perfuse_destroy_fh(pn, fh); |
| | | 130 | |
| | | 131 | /* |
| | | 132 | * release_flags may be set to FUSE_RELEASE_FLUSH |
| | | 133 | * to flush locks. lock_owner must be set in that case |
| | | 134 | */ |
| | | 135 | pm = ps->ps_new_msg(pu, opc, op, sizeof(*fri), NULL); |
| | | 136 | fri = GET_INPAYLOAD(ps, pm, fuse_release_in); |
| | | 137 | fri->fh = fh; |
| | | 138 | fri->flags = 0; |
| | | 139 | fri->release_flags = 0; |
| | | 140 | fri->lock_owner = pnd->pnd_lock_owner; |
| | | 141 | fri->flags = (fri->lock_owner != 0) ? FUSE_RELEASE_FLUSH : 0; |
| | | 142 | |
| | | 143 | #ifdef PERFUSE_DEBUG |
| | | 144 | if (perfuse_diagflags & PDF_FH) |
| | | 145 | DPRINTF("%s: opc = %p, ino = %"PRId64", fh = 0x%"PRIx64"\n", |
| | | 146 | __func__, (void *)opc, pnd->pnd_ino, fri->fh); |
| | | 147 | #endif |
| | | 148 | |
| | | 149 | if ((error = XCHG_MSG(ps, pu, pm, NO_PAYLOAD_REPLY_LEN)) != 0) |
| | | 150 | goto out; |
| | | 151 | |
| | | 152 | ps->ps_destroy_msg(pm); |
| | | 153 | |
| | | 154 | error = 0; |
| | | 155 | |
| | | 156 | out: |
| | | 157 | if (error != 0) |
| | | 158 | DERRX(EX_SOFTWARE, "%s: freed fh = 0x%"PRIx64" but filesystem " |
| | | 159 | "returned error = %d", __func__, fh, error); |
| | | 160 | |
| | | 161 | return error; |
| | | 162 | } |
93 | | | 163 | |
94 | static int | | 164 | static int |
95 | no_access(opc, pcr, mode) | | 165 | no_access(opc, pcr, mode) |
96 | puffs_cookie_t opc; | | 166 | puffs_cookie_t opc; |
97 | const struct puffs_cred *pcr; | | 167 | const struct puffs_cred *pcr; |
98 | mode_t mode; | | 168 | mode_t mode; |
99 | { | | 169 | { |
100 | struct puffs_node *pn; | | 170 | struct puffs_node *pn; |
101 | struct vattr *va; | | 171 | struct vattr *va; |
102 | | | 172 | |
103 | pn = (struct puffs_node *)opc; | | 173 | pn = (struct puffs_node *)opc; |
104 | va = puffs_pn_getvap(pn); | | 174 | va = puffs_pn_getvap(pn); |
105 | | | 175 | |
| @@ -792,26 +862,39 @@ perfuse_fs_suspend(pu, status) | | | @@ -792,26 +862,39 @@ perfuse_fs_suspend(pu, status) |
792 | | | 862 | |
793 | | | 863 | |
794 | int | | 864 | int |
795 | perfuse_node_lookup(pu, opc, pni, pcn) | | 865 | perfuse_node_lookup(pu, opc, pni, pcn) |
796 | struct puffs_usermount *pu; | | 866 | struct puffs_usermount *pu; |
797 | puffs_cookie_t opc; | | 867 | puffs_cookie_t opc; |
798 | struct puffs_newinfo *pni; | | 868 | struct puffs_newinfo *pni; |
799 | const struct puffs_cn *pcn; | | 869 | const struct puffs_cn *pcn; |
800 | { | | 870 | { |
801 | struct puffs_node *pn; | | 871 | struct puffs_node *pn; |
802 | int error; | | 872 | int error; |
803 | | | 873 | |
804 | /* | | 874 | /* |
| | | 875 | * Special case for .. |
| | | 876 | */ |
| | | 877 | if (PCNISDOTDOT(pcn)) { |
| | | 878 | pn = PERFUSE_NODE_DATA(opc)->pnd_parent; |
| | | 879 | PERFUSE_NODE_DATA(pn)->pnd_flags &= ~PND_RECLAIMED; |
| | | 880 | |
| | | 881 | puffs_newinfo_setcookie(pni, pn); |
| | | 882 | puffs_newinfo_setvtype(pni, VDIR); |
| | | 883 | |
| | | 884 | return 0; |
| | | 885 | } |
| | | 886 | |
| | | 887 | /* |
805 | * XXX This is borrowed from librefuse, | | 888 | * XXX This is borrowed from librefuse, |
806 | * and __UNCONST is said to be fixed. | | 889 | * and __UNCONST is said to be fixed. |
807 | */ | | 890 | */ |
808 | pn = puffs_pn_nodewalk(pu, puffs_path_walkcmp, | | 891 | pn = puffs_pn_nodewalk(pu, puffs_path_walkcmp, |
809 | __UNCONST(&pcn->pcn_po_full)); | | 892 | __UNCONST(&pcn->pcn_po_full)); |
810 | | | 893 | |
811 | if (pn == NULL) { | | 894 | if (pn == NULL) { |
812 | error = node_lookup_common(pu, opc, (char *)PCNPATH(pcn), &pn); | | 895 | error = node_lookup_common(pu, opc, (char *)PCNPATH(pcn), &pn); |
813 | if (error != 0) | | 896 | if (error != 0) |
814 | return error; | | 897 | return error; |
815 | } | | 898 | } |
816 | | | 899 | |
817 | /* | | 900 | /* |
| @@ -856,26 +939,32 @@ perfuse_node_create(pu, opc, pni, pcn, v | | | @@ -856,26 +939,32 @@ perfuse_node_create(pu, opc, pni, pcn, v |
856 | * If create is unimplemented: Check that it does not | | 939 | * If create is unimplemented: Check that it does not |
857 | * already exists, and if not, do mknod and open | | 940 | * already exists, and if not, do mknod and open |
858 | */ | | 941 | */ |
859 | ps = puffs_getspecific(pu); | | 942 | ps = puffs_getspecific(pu); |
860 | if (ps->ps_flags & PS_NO_CREAT) { | | 943 | if (ps->ps_flags & PS_NO_CREAT) { |
861 | error = node_lookup_common(pu, opc, (char*)PCNPATH(pcn), &pn); | | 944 | error = node_lookup_common(pu, opc, (char*)PCNPATH(pcn), &pn); |
862 | if (error == 0) | | 945 | if (error == 0) |
863 | return EEXIST; | | 946 | return EEXIST; |
864 | | | 947 | |
865 | error = perfuse_node_mknod(pu, opc, pni, pcn, vap); | | 948 | error = perfuse_node_mknod(pu, opc, pni, pcn, vap); |
866 | if (error != 0) | | 949 | if (error != 0) |
867 | return error; | | 950 | return error; |
868 | | | 951 | |
| | | 952 | error = node_lookup_common(pu, opc, (char*)PCNPATH(pcn), &pn); |
| | | 953 | if (error != 0) |
| | | 954 | return error; |
| | | 955 | |
| | | 956 | opc = (puffs_cookie_t)pn; |
| | | 957 | |
869 | error = perfuse_node_open(pu, opc, FREAD|FWRITE, pcn->pcn_cred); | | 958 | error = perfuse_node_open(pu, opc, FREAD|FWRITE, pcn->pcn_cred); |
870 | if (error != 0) | | 959 | if (error != 0) |
871 | return error; | | 960 | return error; |
872 | | | 961 | |
873 | return 0; | | 962 | return 0; |
874 | } | | 963 | } |
875 | | | 964 | |
876 | name = basename_r((char *)PCNPATH(pcn)); | | 965 | name = basename_r((char *)PCNPATH(pcn)); |
877 | namelen = strlen(name) + 1; | | 966 | namelen = strlen(name) + 1; |
878 | len = sizeof(*fci) + namelen; | | 967 | len = sizeof(*fci) + namelen; |
879 | | | 968 | |
880 | pm = ps->ps_new_msg(pu, opc, FUSE_CREATE, len, pcn->pcn_cred); | | 969 | pm = ps->ps_new_msg(pu, opc, FUSE_CREATE, len, pcn->pcn_cred); |
881 | fci = GET_INPAYLOAD(ps, pm, fuse_create_in); | | 970 | fci = GET_INPAYLOAD(ps, pm, fuse_create_in); |
| @@ -888,32 +977,46 @@ perfuse_node_create(pu, opc, pni, pcn, v | | | @@ -888,32 +977,46 @@ perfuse_node_create(pu, opc, pni, pcn, v |
888 | if ((error = XCHG_MSG(ps, pu, pm, len)) != 0) | | 977 | if ((error = XCHG_MSG(ps, pu, pm, len)) != 0) |
889 | goto out; | | 978 | goto out; |
890 | | | 979 | |
891 | feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out); | | 980 | feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out); |
892 | foo = (struct fuse_open_out *)(void *)(feo + 1); | | 981 | foo = (struct fuse_open_out *)(void *)(feo + 1); |
893 | if (feo->nodeid == PERFUSE_UNKNOWN_INO) | | 982 | if (feo->nodeid == PERFUSE_UNKNOWN_INO) |
894 | DERRX(EX_SOFTWARE, "%s: no ino", __func__); | | 983 | DERRX(EX_SOFTWARE, "%s: no ino", __func__); |
895 | | | 984 | |
896 | /* | | 985 | /* |
897 | * Save the file handle and inode in node private data | | 986 | * Save the file handle and inode in node private data |
898 | * so that we can reuse it later | | 987 | * so that we can reuse it later |
899 | */ | | 988 | */ |
900 | pn = perfuse_new_pn(pu, opc); | | 989 | pn = perfuse_new_pn(pu, opc); |
901 | perfuse_new_fh((puffs_cookie_t)pn, foo->fh); | | 990 | perfuse_new_fh((puffs_cookie_t)pn, foo->fh, FWRITE); |
902 | PERFUSE_NODE_DATA(pn)->pnd_ino = feo->nodeid; | | 991 | PERFUSE_NODE_DATA(pn)->pnd_ino = feo->nodeid; |
903 | | | 992 | |
| | | 993 | #ifdef PERFUSE_DEBUG |
| | | 994 | if (perfuse_diagflags & PDF_FH) |
| | | 995 | DPRINTF("%s: opc = %p, file = \"%s\", " |
| | | 996 | "ino = %"PRId64", rfh = 0x%"PRIx64"\n", |
| | | 997 | __func__, (void *)pn, (char *)PCNPATH(pcn), |
| | | 998 | feo->nodeid, foo->fh); |
| | | 999 | #endif |
| | | 1000 | |
904 | fuse_attr_to_vap(ps, &pn->pn_va, &feo->attr); | | 1001 | fuse_attr_to_vap(ps, &pn->pn_va, &feo->attr); |
905 | puffs_newinfo_setcookie(pni, pn); | | 1002 | puffs_newinfo_setcookie(pni, pn); |
906 | | | 1003 | |
| | | 1004 | /* |
| | | 1005 | * It seems we need to do this so that glusterfs gets fully |
| | | 1006 | * aware that the file was created. If we do not do it, we |
| | | 1007 | * get "SETATTR (null) (fuse_loc_fill() failed)" |
| | | 1008 | */ |
| | | 1009 | (void)node_lookup_common(pu, opc, (char*)PCNPATH(pcn), NULL); |
907 | out: | | 1010 | out: |
908 | ps->ps_destroy_msg(pm); | | 1011 | ps->ps_destroy_msg(pm); |
909 | | | 1012 | |
910 | /* | | 1013 | /* |
911 | * create is unimplmented, remember it for later, | | 1014 | * create is unimplmented, remember it for later, |
912 | * and start over using mknod and open instead. | | 1015 | * and start over using mknod and open instead. |
913 | */ | | 1016 | */ |
914 | if (error == ENOSYS) { | | 1017 | if (error == ENOSYS) { |
915 | ps->ps_flags |= PS_NO_CREAT; | | 1018 | ps->ps_flags |= PS_NO_CREAT; |
916 | return perfuse_node_create(pu, opc, pni, pcn, vap); | | 1019 | return perfuse_node_create(pu, opc, pni, pcn, vap); |
917 | } | | 1020 | } |
918 | | | 1021 | |
919 | return error; | | 1022 | return error; |
| @@ -969,205 +1072,154 @@ perfuse_node_mknod(pu, opc, pni, pcn, va | | | @@ -969,205 +1072,154 @@ perfuse_node_mknod(pu, opc, pni, pcn, va |
969 | | | 1072 | |
970 | return node_mk_common(pu, opc, pni, pcn, pm); | | 1073 | return node_mk_common(pu, opc, pni, pcn, pm); |
971 | } | | 1074 | } |
972 | | | 1075 | |
973 | | | 1076 | |
974 | int | | 1077 | int |
975 | perfuse_node_open(pu, opc, mode, pcr) | | 1078 | perfuse_node_open(pu, opc, mode, pcr) |
976 | struct puffs_usermount *pu; | | 1079 | struct puffs_usermount *pu; |
977 | puffs_cookie_t opc; | | 1080 | puffs_cookie_t opc; |
978 | int mode; | | 1081 | int mode; |
979 | const struct puffs_cred *pcr; | | 1082 | const struct puffs_cred *pcr; |
980 | { | | 1083 | { |
981 | struct perfuse_state *ps; | | 1084 | struct perfuse_state *ps; |
| | | 1085 | struct perfuse_node_data *pnd; |
982 | perfuse_msg_t *pm; | | 1086 | perfuse_msg_t *pm; |
983 | mode_t pmode; | | 1087 | mode_t pmode; |
| | | 1088 | mode_t fmode; |
984 | int op; | | 1089 | int op; |
985 | struct fuse_open_in *foi; | | 1090 | struct fuse_open_in *foi; |
986 | struct fuse_open_out *foo; | | 1091 | struct fuse_open_out *foo; |
987 | struct puffs_node *pn; | | 1092 | struct puffs_node *pn; |
988 | int error; | | 1093 | int error; |
989 | | | 1094 | |
990 | ps = puffs_getspecific(pu); | | 1095 | ps = puffs_getspecific(pu); |
| | | 1096 | pnd = PERFUSE_NODE_DATA(opc); |
991 | | | 1097 | |
992 | pn = (struct puffs_node *)opc; | | 1098 | pn = (struct puffs_node *)opc; |
993 | if (puffs_pn_getvap(pn)->va_type == VDIR) { | | 1099 | if (puffs_pn_getvap(pn)->va_type == VDIR) { |
994 | op = FUSE_OPENDIR; | | 1100 | op = FUSE_OPENDIR; |
995 | pmode = PUFFS_VREAD|PUFFS_VEXEC; | | 1101 | pmode = PUFFS_VREAD|PUFFS_VEXEC; |
996 | } else { | | 1102 | } else { |
997 | op = FUSE_OPEN; | | 1103 | op = FUSE_OPEN; |
998 | if (mode & (O_RDWR|O_WRONLY)) | | 1104 | if (mode & FWRITE) |
999 | pmode = PUFFS_VWRITE; | | 1105 | pmode = PUFFS_VWRITE|PUFFS_VREAD; |
1000 | else | | 1106 | else |
1001 | pmode = PUFFS_VREAD; | | 1107 | pmode = PUFFS_VREAD; |
1002 | } | | 1108 | } |
1003 | | | 1109 | |
1004 | /* | | 1110 | /* |
1005 | * Opening a directory require R-X on the directory | | 1111 | * Opening a directory require R-X on the directory |
1006 | * Opening a file requires R-- for reading, -W- for writing | | 1112 | * Opening a file requires R-- for reading, -W- for writing |
1007 | * In both cases, --X is required on the parent. | | 1113 | * In both cases, --X is required on the parent. |
1008 | */ | | 1114 | */ |
1009 | if (no_access((puffs_cookie_t)PERFUSE_NODE_DATA(opc)->pnd_parent, | | 1115 | if (no_access((puffs_cookie_t)pnd->pnd_parent, pcr, PUFFS_VEXEC)) |
1010 | pcr, PUFFS_VEXEC)) | | | |
1011 | return EACCES; | | 1116 | return EACCES; |
1012 | | | 1117 | |
1013 | if (no_access(opc, pcr, pmode)) | | 1118 | if (no_access(opc, pcr, pmode)) |
1014 | return EACCES; | | 1119 | return EACCES; |
1015 | | | 1120 | |
1016 | /* | | 1121 | /* |
1017 | * libfuse docs say O_CREAT should not be set. | | 1122 | * libfuse docs say O_CREAT should not be set. |
1018 | */ | | 1123 | */ |
1019 | mode &= ~O_CREAT; | | 1124 | mode &= ~O_CREAT; |
1020 | | | 1125 | |
| | | 1126 | /* |
| | | 1127 | * Do not open twice, and do not reopen for reading |
| | | 1128 | * if we already have write handle. |
| | | 1129 | * Directories are always open with read access only, |
| | | 1130 | * whatever flags we get. |
| | | 1131 | */ |
| | | 1132 | if (op == FUSE_OPENDIR) |
| | | 1133 | mode = (mode & ~(FREAD|FWRITE)) | FREAD; |
| | | 1134 | if ((mode & FREAD) && (pnd->pnd_flags & PND_RFH)) |
| | | 1135 | return 0; |
| | | 1136 | if ((mode & FWRITE) && (pnd->pnd_flags & PND_WFH)) |
| | | 1137 | return 0; |
| | | 1138 | |
| | | 1139 | /* |
| | | 1140 | * Convert PUFFS mode to FUSE mode: convert FREAD/FWRITE |
| | | 1141 | * to O_RDONLY/O_WRONLY while perserving the other options. |
| | | 1142 | */ |
| | | 1143 | fmode = mode & ~(FREAD|FWRITE); |
| | | 1144 | fmode |= (mode & FWRITE) ? O_RDWR : O_RDONLY; |
| | | 1145 | |
1021 | pm = ps->ps_new_msg(pu, opc, op, sizeof(*foi), pcr); | | 1146 | pm = ps->ps_new_msg(pu, opc, op, sizeof(*foi), pcr); |
1022 | foi = GET_INPAYLOAD(ps, pm, fuse_open_in); | | 1147 | foi = GET_INPAYLOAD(ps, pm, fuse_open_in); |
1023 | foi->flags = mode & ~O_ACCMODE; | | 1148 | foi->flags = fmode; |
1024 | switch (mode & (FREAD|FWRITE)) { | | | |
1025 | case FREAD|FWRITE: | | | |
1026 | foi->flags |= O_RDWR; | | | |
1027 | break; | | | |
1028 | case FREAD: | | | |
1029 | foi->flags |= O_RDONLY; | | | |
1030 | break; | | | |
1031 | case FWRITE: | | | |
1032 | foi->flags |= O_WRONLY; | | | |
1033 | break; | | | |
1034 | default: | | | |
1035 | break; | | | |
1036 | } | | | |
1037 | foi->unused = 0; | | 1149 | foi->unused = 0; |
1038 | | | 1150 | |
1039 | if ((error = XCHG_MSG(ps, pu, pm, sizeof(*foo))) != 0) | | 1151 | if ((error = XCHG_MSG(ps, pu, pm, sizeof(*foo))) != 0) |
1040 | goto out; | | 1152 | goto out; |
1041 | | | 1153 | |
1042 | foo = GET_OUTPAYLOAD(ps, pm, fuse_open_out); | | 1154 | foo = GET_OUTPAYLOAD(ps, pm, fuse_open_out); |
1043 | | | 1155 | |
1044 | /* | | 1156 | /* |
1045 | * Save the file handle in node private data | | 1157 | * Save the file handle in node private data |
1046 | * so that we can reuse it later | | 1158 | * so that we can reuse it later |
1047 | */ | | 1159 | */ |
1048 | perfuse_new_fh((puffs_cookie_t)pn, foo->fh); | | 1160 | perfuse_new_fh((puffs_cookie_t)pn, foo->fh, mode); |
1049 | | | 1161 | |
1050 | #ifdef PERFUSE_DEBUG | | 1162 | #ifdef PERFUSE_DEBUG |
1051 | if (perfuse_diagflags & PDF_FH) | | 1163 | if (perfuse_diagflags & PDF_FH) |
1052 | DPRINTF("%s: opc = %p, file = \"%s\", " | | 1164 | DPRINTF("%s: opc = %p, file = \"%s\", " |
1053 | "ino = %"PRId64", fh = 0x%"PRIx64"\n", | | 1165 | "ino = %"PRId64", %s%sfh = 0x%"PRIx64"\n", |
1054 | __func__, (void *)opc, | | 1166 | __func__, (void *)opc, |
1055 | (char *)PNPATH((struct puffs_node *)opc), | | 1167 | (char *)PNPATH((struct puffs_node *)opc), |
1056 | PERFUSE_NODE_DATA(opc)->pnd_ino, foo->fh); | | 1168 | pnd->pnd_ino, mode & FREAD ? "r" : "", |
| | | 1169 | mode & FWRITE ? "w" : "", foo->fh); |
1057 | #endif | | 1170 | #endif |
1058 | out: | | 1171 | out: |
1059 | ps->ps_destroy_msg(pm); | | 1172 | ps->ps_destroy_msg(pm); |
1060 | | | 1173 | |
1061 | return error; | | 1174 | return error; |
1062 | } | | 1175 | } |
1063 | | | 1176 | |
1064 | /* ARGSUSED2 */ | | 1177 | /* ARGSUSED0 */ |
1065 | int | | 1178 | int |
1066 | perfuse_node_close(pu, opc, flags, pcr) | | 1179 | perfuse_node_close(pu, opc, flags, pcr) |
1067 | struct puffs_usermount *pu; | | 1180 | struct puffs_usermount *pu; |
1068 | puffs_cookie_t opc; | | 1181 | puffs_cookie_t opc; |
1069 | int flags; | | 1182 | int flags; |
1070 | const struct puffs_cred *pcr; | | 1183 | const struct puffs_cred *pcr; |
1071 | { | | 1184 | { |
1072 | struct perfuse_state *ps; | | | |
1073 | perfuse_msg_t *pm; | | | |
1074 | int op; | | | |
1075 | uint64_t fh; | | | |
1076 | struct perfuse_node_data *pnd; | | | |
1077 | struct fuse_release_in *fri; | | | |
1078 | struct puffs_node *pn; | | 1185 | struct puffs_node *pn; |
1079 | int error; | | 1186 | struct perfuse_node_data *pnd; |
1080 | | | | |
1081 | ps = puffs_getspecific(pu); | | | |
1082 | pn = (struct puffs_node *)opc; | | | |
1083 | pnd = PERFUSE_NODE_DATA(pn); | | | |
1084 | | | 1187 | |
1085 | if (puffs_pn_getvap(pn)->va_type == VDIR) | | 1188 | pn = (struct puffs_node *)opc; |
1086 | op = FUSE_RELEASEDIR; | | 1189 | pnd = PERFUSE_NODE_DATA(opc); |
1087 | else | | | |
1088 | op = FUSE_RELEASE; | | | |
1089 | | | 1190 | |
1090 | if (!(pnd->pnd_flags & PND_OPEN)) | | 1191 | if (!(pnd->pnd_flags & PND_OPEN)) |
1091 | return EBADF; | | 1192 | return EBADF; |
1092 | | | 1193 | |
1093 | fh = perfuse_get_fh(opc); | | | |
1094 | | | | |
1095 | /* | | 1194 | /* |
1096 | * Sync before close for files | | 1195 | * Make sure all operation are finished |
1097 | */ | | 1196 | * There can be an ongoing write, or queued operations |
1098 | if ((op == FUSE_RELEASE) && (pnd->pnd_flags & PND_DIRTY)) { | | 1197 | * XXX perhaps deadlock. Use requeue_request |
1099 | #ifdef PERFUSE_DEBUG | | 1198 | */ |
1100 | if (perfuse_diagflags & PDF_SYNC) | | 1199 | while ((pnd->pnd_flags & PND_BUSY) || |
1101 | DPRINTF("%s: SYNC opc = %p, file = \"%s\"\n", | | 1200 | !TAILQ_EMPTY(&pnd->pnd_pcq)) |
1102 | __func__, (void*)opc, (char *)PNPATH(pn)); | | 1201 | puffs_cc_yield(puffs_cc_getcc(pu)); |
1103 | #endif | | | |
1104 | if ((error = perfuse_node_fsync(pu, opc, pcr, 0, 0, 0)) != 0) | | | |
1105 | return error; | | | |
1106 | | | | |
1107 | pnd->pnd_flags &= ~PND_DIRTY; | | | |
1108 | | | | |
1109 | #ifdef PERFUSE_DEBUG | | | |
1110 | if (perfuse_diagflags & PDF_SYNC) | | | |
1111 | DPRINTF("%s: CLEAR opc = %p, file = \"%s\"\n", | | | |
1112 | __func__, (void*)opc, (char *)PNPATH((pn))); | | | |
1113 | #endif | | | |
1114 | } | | | |
1115 | | | | |
1116 | /* | | | |
1117 | * Destroy the filehandle before sending the | | | |
1118 | * request to the FUSE filesystem, otherwise | | | |
1119 | * we may get a second close() while we wait | | | |
1120 | * for the reply, and we would end up closing | | | |
1121 | * the same fh twice instead of closng both. | | | |
1122 | */ | | | |
1123 | perfuse_destroy_fh(pn, fh); | | | |
1124 | | | | |
1125 | #ifdef PERFUSE_DEBUG | | | |
1126 | if (perfuse_diagflags & PDF_FH) | | | |
1127 | DPRINTF("%s: opc = %p, ino = %"PRId64", fh = 0x%"PRIx64"\n", | | | |
1128 | __func__, (void *)opc, pnd->pnd_ino, fh); | | | |
1129 | #endif | | | |
1130 | | | 1202 | |
1131 | /* | | 1203 | /* |
1132 | * release_flags may be set to FUSE_RELEASE_FLUSH | | 1204 | * The NetBSD kernel will send sync and setattr(mtime, ctime) |
1133 | * to flush locks. lock_owner must be set in that case | | 1205 | * afer a close on a regular file. Some FUSE filesystem will |
| | | 1206 | * assume theses operations are performed on open files. We |
| | | 1207 | * therefore postpone the close operation at reclaim time. |
1134 | */ | | 1208 | */ |
1135 | pm = ps->ps_new_msg(pu, opc, op, sizeof(*fri), NULL); | | 1209 | if (puffs_pn_getvap(pn)->va_type != VREG) |
1136 | fri = GET_INPAYLOAD(ps, pm, fuse_release_in); | | 1210 | return node_close_common(pu, opc, flags); |
1137 | fri->fh = fh; | | | |
1138 | fri->flags = 0; | | | |
1139 | fri->release_flags = 0; | | | |
1140 | fri->lock_owner = PERFUSE_NODE_DATA(pn)->pnd_lock_owner; | | | |
1141 | fri->flags = (fri->lock_owner != 0) ? FUSE_RELEASE_FLUSH : 0; | | | |
1142 | | | | |
1143 | #ifdef PERFUSE_DEBUG | | | |
1144 | if (perfuse_diagflags & PDF_FH) | | | |
1145 | DPRINTF("%s: opc = %p, ino = %"PRId64", fh = 0x%"PRIx64"\n", | | | |
1146 | __func__, (void *)opc, pnd->pnd_ino, fri->fh); | | | |
1147 | #endif | | | |
1148 | | | | |
1149 | if ((error = XCHG_MSG(ps, pu, pm, NO_PAYLOAD_REPLY_LEN)) != 0) | | | |
1150 | goto out; | | | |
1151 | | | | |
1152 | out: | | | |
1153 | if (error != 0) | | | |
1154 | DWARNX("%s: freed fh = 0x%"PRIx64" but filesystem " | | | |
1155 | "returned error = %d", | | | |
1156 | __func__, fh, error); | | | |
1157 | | | 1211 | |
1158 | ps->ps_destroy_msg(pm); | | 1212 | return 0; |
1159 | | | | |
1160 | return error; | | | |
1161 | } | | 1213 | } |
1162 | | | 1214 | |
1163 | int | | 1215 | int |
1164 | perfuse_node_access(pu, opc, mode, pcr) | | 1216 | perfuse_node_access(pu, opc, mode, pcr) |
1165 | struct puffs_usermount *pu; | | 1217 | struct puffs_usermount *pu; |
1166 | puffs_cookie_t opc; | | 1218 | puffs_cookie_t opc; |
1167 | int mode; | | 1219 | int mode; |
1168 | const struct puffs_cred *pcr; | | 1220 | const struct puffs_cred *pcr; |
1169 | { | | 1221 | { |
1170 | perfuse_msg_t *pm; | | 1222 | perfuse_msg_t *pm; |
1171 | struct perfuse_state *ps; | | 1223 | struct perfuse_state *ps; |
1172 | struct fuse_access_in *fai; | | 1224 | struct fuse_access_in *fai; |
1173 | int error; | | 1225 | int error; |
| @@ -1190,27 +1242,27 @@ perfuse_node_access(pu, opc, mode, pcr) | | | @@ -1190,27 +1242,27 @@ perfuse_node_access(pu, opc, mode, pcr) |
1190 | } | | 1242 | } |
1191 | | | 1243 | |
1192 | if (error == ENOSYS) { | | 1244 | if (error == ENOSYS) { |
1193 | struct fuse_getattr_in *fgi; | | 1245 | struct fuse_getattr_in *fgi; |
1194 | struct fuse_attr_out *fao; | | 1246 | struct fuse_attr_out *fao; |
1195 | | | 1247 | |
1196 | ps->ps_flags |= PS_NO_ACCESS; | | 1248 | ps->ps_flags |= PS_NO_ACCESS; |
1197 | | | 1249 | |
1198 | pm = ps->ps_new_msg(pu, opc, FUSE_GETATTR, | | 1250 | pm = ps->ps_new_msg(pu, opc, FUSE_GETATTR, |
1199 | sizeof(*fgi), NULL); | | 1251 | sizeof(*fgi), NULL); |
1200 | fgi = GET_INPAYLOAD(ps, pm, fuse_getattr_in); | | 1252 | fgi = GET_INPAYLOAD(ps, pm, fuse_getattr_in); |
1201 | fgi->getattr_flags = 0; | | 1253 | fgi->getattr_flags = 0; |
1202 | fgi->dummy = 0; | | 1254 | fgi->dummy = 0; |
1203 | fgi->fh = perfuse_get_fh(opc); | | 1255 | fgi->fh = perfuse_get_fh(opc, FREAD); |
1204 | | | 1256 | |
1205 | #ifdef PERFUSE_DEBUG | | 1257 | #ifdef PERFUSE_DEBUG |
1206 | if (perfuse_diagflags & PDF_FH) | | 1258 | if (perfuse_diagflags & PDF_FH) |
1207 | DPRINTF("%s: opc = %p, ino = %"PRId64", " | | 1259 | DPRINTF("%s: opc = %p, ino = %"PRId64", " |
1208 | "fh = 0x%"PRIx64"\n", __func__, (void *)opc, | | 1260 | "fh = 0x%"PRIx64"\n", __func__, (void *)opc, |
1209 | PERFUSE_NODE_DATA(opc)->pnd_ino, fgi->fh); | | 1261 | PERFUSE_NODE_DATA(opc)->pnd_ino, fgi->fh); |
1210 | #endif | | 1262 | #endif |
1211 | if ((error = XCHG_MSG(ps, pu, pm, sizeof(*fao))) != 0) { | | 1263 | if ((error = XCHG_MSG(ps, pu, pm, sizeof(*fao))) != 0) { |
1212 | ps->ps_destroy_msg(pm); | | 1264 | ps->ps_destroy_msg(pm); |
1213 | goto out; | | 1265 | goto out; |
1214 | } | | 1266 | } |
1215 | | | 1267 | |
1216 | fao = GET_OUTPAYLOAD(ps, pm, fuse_attr_out); | | 1268 | fao = GET_OUTPAYLOAD(ps, pm, fuse_attr_out); |
| @@ -1278,35 +1330,40 @@ out: | | | @@ -1278,35 +1330,40 @@ out: |
1278 | return error; | | 1330 | return error; |
1279 | } | | 1331 | } |
1280 | | | 1332 | |
1281 | int | | 1333 | int |
1282 | perfuse_node_setattr(pu, opc, vap, pcr) | | 1334 | perfuse_node_setattr(pu, opc, vap, pcr) |
1283 | struct puffs_usermount *pu; | | 1335 | struct puffs_usermount *pu; |
1284 | puffs_cookie_t opc; | | 1336 | puffs_cookie_t opc; |
1285 | const struct vattr *vap; | | 1337 | const struct vattr *vap; |
1286 | const struct puffs_cred *pcr; | | 1338 | const struct puffs_cred *pcr; |
1287 | { | | 1339 | { |
1288 | perfuse_msg_t *pm; | | 1340 | perfuse_msg_t *pm; |
1289 | uint64_t fh; | | 1341 | uint64_t fh; |
1290 | struct perfuse_state *ps; | | 1342 | struct perfuse_state *ps; |
| | | 1343 | struct perfuse_node_data *pnd; |
1291 | struct fuse_setattr_in *fsi; | | 1344 | struct fuse_setattr_in *fsi; |
1292 | int error; | | 1345 | int error; |
| | | 1346 | int open_self; |
1293 | struct vattr *old_va; | | 1347 | struct vattr *old_va; |
1294 | | | 1348 | |
| | | 1349 | open_self = 0; |
| | | 1350 | ps = puffs_getspecific(pu); |
| | | 1351 | pnd = PERFUSE_NODE_DATA(opc); |
| | | 1352 | |
1295 | /* | | 1353 | /* |
1296 | * setattr requires --X on the parent directory | | 1354 | * setattr requires --X on the parent directory |
1297 | */ | | 1355 | */ |
1298 | if (no_access((puffs_cookie_t)PERFUSE_NODE_DATA(opc)->pnd_parent, | | 1356 | if (no_access((puffs_cookie_t)pnd->pnd_parent, pcr, PUFFS_VEXEC)) |
1299 | pcr, PUFFS_VEXEC)) | | | |
1300 | return EACCES; | | 1357 | return EACCES; |
1301 | | | 1358 | |
1302 | old_va = puffs_pn_getvap((struct puffs_node *)opc); | | 1359 | old_va = puffs_pn_getvap((struct puffs_node *)opc); |
1303 | | | 1360 | |
1304 | /* | | 1361 | /* |
1305 | * Check for permission to change size | | 1362 | * Check for permission to change size |
1306 | */ | | 1363 | */ |
1307 | if ((vap->va_size != (u_quad_t)PUFFS_VNOVAL) && | | 1364 | if ((vap->va_size != (u_quad_t)PUFFS_VNOVAL) && |
1308 | no_access(opc, pcr, PUFFS_VWRITE)) | | 1365 | no_access(opc, pcr, PUFFS_VWRITE)) |
1309 | return EACCES; | | 1366 | return EACCES; |
1310 | | | 1367 | |
1311 | /* | | 1368 | /* |
1312 | * Check for permission to change dates | | 1369 | * Check for permission to change dates |
| @@ -1321,41 +1378,58 @@ perfuse_node_setattr(pu, opc, vap, pcr) | | | @@ -1321,41 +1378,58 @@ perfuse_node_setattr(pu, opc, vap, pcr) |
1321 | * Check for permission to change owner and group | | 1378 | * Check for permission to change owner and group |
1322 | */ | | 1379 | */ |
1323 | if (((vap->va_uid != (uid_t)PUFFS_VNOVAL) || | | 1380 | if (((vap->va_uid != (uid_t)PUFFS_VNOVAL) || |
1324 | (vap->va_gid != (gid_t)PUFFS_VNOVAL)) && | | 1381 | (vap->va_gid != (gid_t)PUFFS_VNOVAL)) && |
1325 | (puffs_access_chown(old_va->va_uid, old_va->va_gid, | | 1382 | (puffs_access_chown(old_va->va_uid, old_va->va_gid, |
1326 | vap->va_uid, vap->va_gid, pcr)) != 0) | | 1383 | vap->va_uid, vap->va_gid, pcr)) != 0) |
1327 | return EACCES; | | 1384 | return EACCES; |
1328 | | | 1385 | |
1329 | /* | | 1386 | /* |
1330 | * Check for permission to change permissions | | 1387 | * Check for permission to change permissions |
1331 | */ | | 1388 | */ |
1332 | if ((vap->va_mode != (mode_t)PUFFS_VNOVAL) && | | 1389 | if ((vap->va_mode != (mode_t)PUFFS_VNOVAL) && |
1333 | (puffs_access_chmod(old_va->va_uid, old_va->va_gid, | | 1390 | (puffs_access_chmod(old_va->va_uid, old_va->va_gid, |
1334 | old_va->va_type, vap->va_mode, pcr)) != 0) | | 1391 | old_va->va_type, vap->va_mode, pcr)) != 0) |
1335 | return EACCES; | | 1392 | return EACCES; |
1336 | | | 1393 | |
| | | 1394 | /* |
| | | 1395 | * setattr(mtime, ctime) require an open file, |
| | | 1396 | * at least for glusterfs. |
| | | 1397 | */ |
| | | 1398 | if (((vap->va_atime.tv_sec != (time_t)PUFFS_VNOVAL) || |
| | | 1399 | (vap->va_mtime.tv_sec != (time_t)PUFFS_VNOVAL)) && |
| | | 1400 | !(pnd->pnd_flags & PND_WFH)) { |
| | | 1401 | if ((error = perfuse_node_open(pu, opc, FWRITE, pcr)) != 0) |
| | | 1402 | return error; |
| | | 1403 | open_self = 1; |
| | | 1404 | } |
| | | 1405 | /* |
| | | 1406 | * It seems troublesome to resize a file while |
| | | 1407 | * a write is just beeing done. Wait for |
| | | 1408 | * it to finish. |
| | | 1409 | */ |
| | | 1410 | if (vap->va_size != (u_quad_t)PUFFS_VNOVAL) |
| | | 1411 | while (pnd->pnd_flags & PND_INWRITE) |
| | | 1412 | requeue_request(pu, opc, PCQ_AFTERWRITE); |
1337 | | | 1413 | |
1338 | ps = puffs_getspecific(pu); | | | |
1339 | | | 1414 | |
1340 | pm = ps->ps_new_msg(pu, opc, FUSE_SETATTR, sizeof(*fsi), pcr); | | 1415 | pm = ps->ps_new_msg(pu, opc, FUSE_SETATTR, sizeof(*fsi), pcr); |
1341 | fsi = GET_INPAYLOAD(ps, pm, fuse_setattr_in); | | 1416 | fsi = GET_INPAYLOAD(ps, pm, fuse_setattr_in); |
1342 | fsi->valid = 0; | | 1417 | fsi->valid = 0; |
1343 | | | 1418 | |
1344 | if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_OPEN) { | | 1419 | if (pnd->pnd_flags & PND_WFH) { |
1345 | fh = perfuse_get_fh(opc); | | 1420 | fh = perfuse_get_fh(opc, FWRITE); |
1346 | fsi->fh = fh; | | 1421 | fsi->fh = fh; |
1347 | if (fh != FUSE_UNKNOWN_FH) | | 1422 | fsi->valid |= FUSE_FATTR_FH; |
1348 | fsi->valid |= FUSE_FATTR_FH; | | | |
1349 | } | | 1423 | } |
1350 | | | 1424 | |
1351 | if (vap->va_size != (u_quad_t)PUFFS_VNOVAL) { | | 1425 | if (vap->va_size != (u_quad_t)PUFFS_VNOVAL) { |
1352 | fsi->size = vap->va_size; | | 1426 | fsi->size = vap->va_size; |
1353 | fsi->valid |= FUSE_FATTR_SIZE; | | 1427 | fsi->valid |= FUSE_FATTR_SIZE; |
1354 | } | | 1428 | } |
1355 | | | 1429 | |
1356 | if (vap->va_atime.tv_sec != (time_t)PUFFS_VNOVAL) { | | 1430 | if (vap->va_atime.tv_sec != (time_t)PUFFS_VNOVAL) { |
1357 | fsi->atime = vap->va_atime.tv_sec;; | | 1431 | fsi->atime = vap->va_atime.tv_sec;; |
1358 | fsi->atimensec = (uint32_t)vap->va_atime.tv_nsec;; | | 1432 | fsi->atimensec = (uint32_t)vap->va_atime.tv_nsec;; |
1359 | fsi->valid |= (FUSE_FATTR_ATIME|FUSE_FATTR_ATIME_NOW); | | 1433 | fsi->valid |= (FUSE_FATTR_ATIME|FUSE_FATTR_ATIME_NOW); |
1360 | } | | 1434 | } |
1361 | | | 1435 | |
| @@ -1370,60 +1444,63 @@ perfuse_node_setattr(pu, opc, vap, pcr) | | | @@ -1370,60 +1444,63 @@ perfuse_node_setattr(pu, opc, vap, pcr) |
1370 | fsi->valid |= FUSE_FATTR_MODE; | | 1444 | fsi->valid |= FUSE_FATTR_MODE; |
1371 | } | | 1445 | } |
1372 | | | 1446 | |
1373 | if (vap->va_uid != (uid_t)PUFFS_VNOVAL) { | | 1447 | if (vap->va_uid != (uid_t)PUFFS_VNOVAL) { |
1374 | fsi->uid = vap->va_uid; | | 1448 | fsi->uid = vap->va_uid; |
1375 | fsi->valid |= FUSE_FATTR_UID; | | 1449 | fsi->valid |= FUSE_FATTR_UID; |
1376 | } | | 1450 | } |
1377 | | | 1451 | |
1378 | if (vap->va_gid != (gid_t)PUFFS_VNOVAL) { | | 1452 | if (vap->va_gid != (gid_t)PUFFS_VNOVAL) { |
1379 | fsi->gid = vap->va_gid; | | 1453 | fsi->gid = vap->va_gid; |
1380 | fsi->valid |= FUSE_FATTR_GID; | | 1454 | fsi->valid |= FUSE_FATTR_GID; |
1381 | } | | 1455 | } |
1382 | | | 1456 | |
1383 | if (PERFUSE_NODE_DATA(opc)->pnd_lock_owner != 0) { | | 1457 | if (pnd->pnd_lock_owner != 0) { |
1384 | fsi->lock_owner = PERFUSE_NODE_DATA(opc)->pnd_lock_owner; | | 1458 | fsi->lock_owner = pnd->pnd_lock_owner; |
1385 | fsi->valid |= FUSE_FATTR_LOCKOWNER; | | 1459 | fsi->valid |= FUSE_FATTR_LOCKOWNER; |
1386 | } | | 1460 | } |
1387 | | | 1461 | |
1388 | /* | | 1462 | /* |
1389 | * A fuse_attr_out is returned, but we ignore it. | | 1463 | * A fuse_attr_out is returned, but we ignore it. |
1390 | */ | | 1464 | */ |
1391 | error = XCHG_MSG(ps, pu, pm, sizeof(struct fuse_attr_out)); | | 1465 | error = XCHG_MSG(ps, pu, pm, sizeof(struct fuse_attr_out)); |
1392 | | | 1466 | |
1393 | ps->ps_destroy_msg(pm); | | 1467 | ps->ps_destroy_msg(pm); |
1394 | | | 1468 | |
| | | 1469 | if (open_self) |
| | | 1470 | (void)perfuse_node_close(pu, opc, FWRITE, pcr); |
| | | 1471 | |
1395 | return error; | | 1472 | return error; |
1396 | } | | 1473 | } |
1397 | | | 1474 | |
1398 | int | | 1475 | int |
1399 | perfuse_node_poll(pu, opc, events) | | 1476 | perfuse_node_poll(pu, opc, events) |
1400 | struct puffs_usermount *pu; | | 1477 | struct puffs_usermount *pu; |
1401 | puffs_cookie_t opc; | | 1478 | puffs_cookie_t opc; |
1402 | int *events; | | 1479 | int *events; |
1403 | { | | 1480 | { |
1404 | struct perfuse_state *ps; | | 1481 | struct perfuse_state *ps; |
1405 | perfuse_msg_t *pm; | | 1482 | perfuse_msg_t *pm; |
1406 | struct fuse_poll_in *fpi; | | 1483 | struct fuse_poll_in *fpi; |
1407 | struct fuse_poll_out *fpo; | | 1484 | struct fuse_poll_out *fpo; |
1408 | int error; | | 1485 | int error; |
1409 | | | 1486 | |
1410 | ps = puffs_getspecific(pu); | | 1487 | ps = puffs_getspecific(pu); |
1411 | /* | | 1488 | /* |
1412 | * kh is set if FUSE_POLL_SCHEDULE_NOTIFY is set. | | 1489 | * kh is set if FUSE_POLL_SCHEDULE_NOTIFY is set. |
1413 | */ | | 1490 | */ |
1414 | pm = ps->ps_new_msg(pu, opc, FUSE_POLL, sizeof(*fpi), NULL); | | 1491 | pm = ps->ps_new_msg(pu, opc, FUSE_POLL, sizeof(*fpi), NULL); |
1415 | fpi = GET_INPAYLOAD(ps, pm, fuse_poll_in); | | 1492 | fpi = GET_INPAYLOAD(ps, pm, fuse_poll_in); |
1416 | fpi->fh = perfuse_get_fh(opc); | | 1493 | fpi->fh = perfuse_get_fh(opc, FREAD); |
1417 | fpi->kh = 0; | | 1494 | fpi->kh = 0; |
1418 | fpi->flags = 0; | | 1495 | fpi->flags = 0; |
1419 | | | 1496 | |
1420 | #ifdef PERFUSE_DEBUG | | 1497 | #ifdef PERFUSE_DEBUG |
1421 | if (perfuse_diagflags & PDF_FH) | | 1498 | if (perfuse_diagflags & PDF_FH) |
1422 | DPRINTF("%s: opc = %p, ino = %"PRId64", fh = 0x%"PRIx64"\n", | | 1499 | DPRINTF("%s: opc = %p, ino = %"PRId64", fh = 0x%"PRIx64"\n", |
1423 | __func__, (void *)opc, | | 1500 | __func__, (void *)opc, |
1424 | PERFUSE_NODE_DATA(opc)->pnd_ino, fpi->fh); | | 1501 | PERFUSE_NODE_DATA(opc)->pnd_ino, fpi->fh); |
1425 | #endif | | 1502 | #endif |
1426 | if ((error = XCHG_MSG(ps, pu, pm, sizeof(*fpo))) != 0) | | 1503 | if ((error = XCHG_MSG(ps, pu, pm, sizeof(*fpo))) != 0) |
1427 | goto out; | | 1504 | goto out; |
1428 | | | 1505 | |
1429 | fpo = GET_OUTPAYLOAD(ps, pm, fuse_poll_out); | | 1506 | fpo = GET_OUTPAYLOAD(ps, pm, fuse_poll_out); |
| @@ -1469,51 +1546,51 @@ perfuse_node_fsync(pu, opc, pcr, flags, | | | @@ -1469,51 +1546,51 @@ perfuse_node_fsync(pu, opc, pcr, flags, |
1469 | pm = NULL; | | 1546 | pm = NULL; |
1470 | open_self = 0; | | 1547 | open_self = 0; |
1471 | | | 1548 | |
1472 | /* | | 1549 | /* |
1473 | * If we previously detected it as unimplemented, | | 1550 | * If we previously detected it as unimplemented, |
1474 | * skip the call to the filesystem. | | 1551 | * skip the call to the filesystem. |
1475 | */ | | 1552 | */ |
1476 | ps = puffs_getspecific(pu); | | 1553 | ps = puffs_getspecific(pu); |
1477 | if (ps->ps_flags == PS_NO_FSYNC) | | 1554 | if (ps->ps_flags == PS_NO_FSYNC) |
1478 | return ENOSYS; | | 1555 | return ENOSYS; |
1479 | | | 1556 | |
1480 | /* | | 1557 | /* |
1481 | * Do not sync if there are no change to sync | | 1558 | * Do not sync if there are no change to sync |
1482 | * XXX remove that testif we implement mmap | | 1559 | * XXX remove that test if we implement mmap |
1483 | */ | | 1560 | */ |
1484 | pnd = PERFUSE_NODE_DATA(opc); | | 1561 | pnd = PERFUSE_NODE_DATA(opc); |
1485 | #ifdef PERFUSE_DEBUG | | 1562 | #ifdef PERFUSE_DEBUG |
1486 | if (perfuse_diagflags & PDF_SYNC) | | 1563 | if (perfuse_diagflags & PDF_SYNC) |
1487 | DPRINTF("%s: TEST opc = %p, file = \"%s\" is %sdirty\n", | | 1564 | DPRINTF("%s: TEST opc = %p, file = \"%s\" is %sdirty\n", |
1488 | __func__, (void*)opc, | | 1565 | __func__, (void*)opc, |
1489 | (char *)PNPATH((struct puffs_node *)opc), | | 1566 | (char *)PNPATH((struct puffs_node *)opc), |
1490 | pnd->pnd_flags & PND_DIRTY ? "" : "not "); | | 1567 | pnd->pnd_flags & PND_DIRTY ? "" : "not "); |
1491 | #endif | | 1568 | #endif |
1492 | if (!(pnd->pnd_flags & PND_DIRTY)) | | 1569 | if (!(pnd->pnd_flags & PND_DIRTY)) |
1493 | return 0; | | 1570 | return 0; |
1494 | | | 1571 | |
1495 | /* | | 1572 | /* |
1496 | * It seems NetBSD can call fsync without open first | | 1573 | * It seems NetBSD can call fsync without open first |
1497 | * glusterfs complain in such a situation: | | 1574 | * glusterfs complain in such a situation: |
1498 | * "FSYNC() ERR => -1 (Invalid argument)" | | 1575 | * "FSYNC() ERR => -1 (Invalid argument)" |
1499 | */ | | 1576 | */ |
1500 | if (!(pnd->pnd_flags & PND_OPEN)) { | | 1577 | if (!(pnd->pnd_flags & PND_OPEN)) { |
1501 | if ((error = perfuse_node_open(pu, opc, FREAD, pcr)) != 0) | | 1578 | if ((error = perfuse_node_open(pu, opc, FWRITE, pcr)) != 0) |
1502 | goto out; | | 1579 | goto out; |
1503 | open_self = 1; | | 1580 | open_self = 1; |
1504 | } | | 1581 | } |
1505 | | | 1582 | |
1506 | fh = perfuse_get_fh(opc); | | 1583 | fh = perfuse_get_fh(opc, FWRITE); |
1507 | | | 1584 | |
1508 | /* | | 1585 | /* |
1509 | * If fsync_flags is set, meta data should not be flushed. | | 1586 | * If fsync_flags is set, meta data should not be flushed. |
1510 | */ | | 1587 | */ |
1511 | pm = ps->ps_new_msg(pu, opc, FUSE_FSYNC, sizeof(*ffi), NULL); | | 1588 | pm = ps->ps_new_msg(pu, opc, FUSE_FSYNC, sizeof(*ffi), NULL); |
1512 | ffi = GET_INPAYLOAD(ps, pm, fuse_fsync_in); | | 1589 | ffi = GET_INPAYLOAD(ps, pm, fuse_fsync_in); |
1513 | ffi->fh = fh; | | 1590 | ffi->fh = fh; |
1514 | ffi->fsync_flags = (flags & FFILESYNC) ? 0 : 1; | | 1591 | ffi->fsync_flags = (flags & FFILESYNC) ? 0 : 1; |
1515 | | | 1592 | |
1516 | #ifdef PERFUSE_DEBUG | | 1593 | #ifdef PERFUSE_DEBUG |
1517 | if (perfuse_diagflags & PDF_FH) | | 1594 | if (perfuse_diagflags & PDF_FH) |
1518 | DPRINTF("%s: opc = %p, ino = %"PRId64", fh = 0x%"PRIx64"\n", | | 1595 | DPRINTF("%s: opc = %p, ino = %"PRId64", fh = 0x%"PRIx64"\n", |
1519 | __func__, (void *)opc, | | 1596 | __func__, (void *)opc, |
| @@ -1533,28 +1610,28 @@ perfuse_node_fsync(pu, opc, pcr, flags, | | | @@ -1533,28 +1610,28 @@ perfuse_node_fsync(pu, opc, pcr, flags, |
1533 | if (perfuse_diagflags & PDF_SYNC) | | 1610 | if (perfuse_diagflags & PDF_SYNC) |
1534 | DPRINTF("%s: CLEAR opc = %p, file = \"%s\"\n", | | 1611 | DPRINTF("%s: CLEAR opc = %p, file = \"%s\"\n", |
1535 | __func__, (void*)opc, | | 1612 | __func__, (void*)opc, |
1536 | (char *)PNPATH((struct puffs_node *)opc)); | | 1613 | (char *)PNPATH((struct puffs_node *)opc)); |
1537 | #endif | | 1614 | #endif |
1538 | | | 1615 | |
1539 | out: | | 1616 | out: |
1540 | if (error == ENOSYS) | | 1617 | if (error == ENOSYS) |
1541 | ps->ps_flags |= PS_NO_FSYNC; | | 1618 | ps->ps_flags |= PS_NO_FSYNC; |
1542 | | | 1619 | |
1543 | if (pm != NULL) | | 1620 | if (pm != NULL) |
1544 | ps->ps_destroy_msg(pm); | | 1621 | ps->ps_destroy_msg(pm); |
1545 | | | 1622 | |
1546 | if (open_self) | | 1623 | if (open_self) |
1547 | (void)perfuse_node_close(pu, opc, 0, pcr); | | 1624 | (void)node_close_common(pu, opc, FWRITE); |
1548 | | | 1625 | |
1549 | return error; | | 1626 | return error; |
1550 | } | | 1627 | } |
1551 | | | 1628 | |
1552 | /* ARGSUSED0 */ | | 1629 | /* ARGSUSED0 */ |
1553 | int | | 1630 | int |
1554 | perfuse_node_seek(pu, opc, oldoff, newoff, pcr) | | 1631 | perfuse_node_seek(pu, opc, oldoff, newoff, pcr) |
1555 | struct puffs_usermount *pu; | | 1632 | struct puffs_usermount *pu; |
1556 | puffs_cookie_t opc; | | 1633 | puffs_cookie_t opc; |
1557 | off_t oldoff; | | 1634 | off_t oldoff; |
1558 | off_t newoff; | | 1635 | off_t newoff; |
1559 | const struct puffs_cred *pcr; | | 1636 | const struct puffs_cred *pcr; |
1560 | { | | 1637 | { |
| @@ -1566,63 +1643,62 @@ perfuse_node_seek(pu, opc, oldoff, newof | | | @@ -1566,63 +1643,62 @@ perfuse_node_seek(pu, opc, oldoff, newof |
1566 | PERFUSE_NODE_DATA(opc)->pnd_offset = newoff; | | 1643 | PERFUSE_NODE_DATA(opc)->pnd_offset = newoff; |
1567 | | | 1644 | |
1568 | return 0; | | 1645 | return 0; |
1569 | } | | 1646 | } |
1570 | | | 1647 | |
1571 | int | | 1648 | int |
1572 | perfuse_node_remove(pu, opc, targ, pcn) | | 1649 | perfuse_node_remove(pu, opc, targ, pcn) |
1573 | struct puffs_usermount *pu; | | 1650 | struct puffs_usermount *pu; |
1574 | puffs_cookie_t opc; | | 1651 | puffs_cookie_t opc; |
1575 | puffs_cookie_t targ; | | 1652 | puffs_cookie_t targ; |
1576 | const struct puffs_cn *pcn; | | 1653 | const struct puffs_cn *pcn; |
1577 | { | | 1654 | { |
1578 | struct perfuse_state *ps; | | 1655 | struct perfuse_state *ps; |
1579 | perfuse_msg_t *pm; | | | |
1580 | struct puffs_node *pn; | | 1656 | struct puffs_node *pn; |
| | | 1657 | struct perfuse_node_data *pnd; |
| | | 1658 | perfuse_msg_t *pm; |
1581 | char *path; | | 1659 | char *path; |
1582 | const char *name; | | 1660 | const char *name; |
1583 | size_t len; | | 1661 | size_t len; |
1584 | int error; | | 1662 | int error; |
1585 | | | 1663 | |
| | | 1664 | pnd = PERFUSE_NODE_DATA(opc); |
| | | 1665 | |
1586 | /* | | 1666 | /* |
1587 | * remove requires -WX on the parent directory | | 1667 | * remove requires -WX on the parent directory |
1588 | * no right required on the object. | | 1668 | * no right required on the object. |
1589 | */ | | 1669 | */ |
1590 | if (no_access((puffs_cookie_t)PERFUSE_NODE_DATA(opc)->pnd_parent, | | 1670 | if (no_access((puffs_cookie_t)pnd->pnd_parent, |
1591 | pcn->pcn_cred, PUFFS_VWRITE|PUFFS_VEXEC)) | | 1671 | pcn->pcn_cred, PUFFS_VWRITE|PUFFS_VEXEC)) |
1592 | return EACCES; | | 1672 | return EACCES; |
1593 | | | 1673 | |
1594 | ps = puffs_getspecific(pu); | | | |
1595 | | | | |
1596 | if (targ == NULL) | | 1674 | if (targ == NULL) |
1597 | DERRX(EX_SOFTWARE, "%s: targ is NULL", __func__); | | 1675 | DERRX(EX_SOFTWARE, "%s: targ is NULL", __func__); |
1598 | | | 1676 | |
| | | 1677 | ps = puffs_getspecific(pu); |
1599 | pn = (struct puffs_node *)targ; | | 1678 | pn = (struct puffs_node *)targ; |
1600 | name = basename_r((char *)PNPATH(pn)); | | 1679 | name = basename_r((char *)PNPATH(pn)); |
1601 | len = strlen(name) + 1; | | 1680 | len = strlen(name) + 1; |
1602 | | | 1681 | |
1603 | pm = ps->ps_new_msg(pu, opc, FUSE_UNLINK, len, pcn->pcn_cred); | | 1682 | pm = ps->ps_new_msg(pu, opc, FUSE_UNLINK, len, pcn->pcn_cred); |
1604 | path = _GET_INPAYLOAD(ps, pm, char *); | | 1683 | path = _GET_INPAYLOAD(ps, pm, char *); |
1605 | (void)strlcpy(path, name, len); | | 1684 | (void)strlcpy(path, name, len); |
1606 | | | 1685 | |
1607 | if ((error = XCHG_MSG(ps, pu, pm, UNSPEC_REPLY_LEN)) != 0) | | 1686 | if ((error = XCHG_MSG(ps, pu, pm, UNSPEC_REPLY_LEN)) != 0) |
1608 | goto out; | | 1687 | goto out; |
1609 | | | 1688 | |
1610 | if (puffs_inval_namecache_dir(pu, opc) != 0) | | 1689 | if (puffs_inval_namecache_dir(pu, opc) != 0) |
1611 | DERR(EX_OSERR, "puffs_inval_namecache_dir failed"); | | 1690 | DERR(EX_OSERR, "puffs_inval_namecache_dir failed"); |
1612 | | | 1691 | |
1613 | if (puffs_inval_pagecache_node(pu, (puffs_cookie_t)pn) != 0) | | | |
1614 | DERR(EX_OSERR, "puffs_inval_namecache_node failed"); | | | |
1615 | | | | |
1616 | puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N2); | | 1692 | puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N2); |
1617 | | | 1693 | |
1618 | /* | | 1694 | /* |
1619 | * Reclaim should take care of decreasing pnd_childcount | | 1695 | * Reclaim should take care of decreasing pnd_childcount |
1620 | */ | | 1696 | */ |
1621 | out: | | 1697 | out: |
1622 | ps->ps_destroy_msg(pm); | | 1698 | ps->ps_destroy_msg(pm); |
1623 | | | 1699 | |
1624 | return error; | | 1700 | return error; |
1625 | } | | 1701 | } |
1626 | | | 1702 | |
1627 | int | | 1703 | int |
1628 | perfuse_node_link(pu, opc, targ, pcn) | | 1704 | perfuse_node_link(pu, opc, targ, pcn) |
| @@ -1757,59 +1833,59 @@ perfuse_node_mkdir(pu, opc, pni, pcn, va | | | @@ -1757,59 +1833,59 @@ perfuse_node_mkdir(pu, opc, pni, pcn, va |
1757 | | | 1833 | |
1758 | return node_mk_common(pu, opc, pni, pcn, pm); | | 1834 | return node_mk_common(pu, opc, pni, pcn, pm); |
1759 | } | | 1835 | } |
1760 | | | 1836 | |
1761 | | | 1837 | |
1762 | int | | 1838 | int |
1763 | perfuse_node_rmdir(pu, opc, targ, pcn) | | 1839 | perfuse_node_rmdir(pu, opc, targ, pcn) |
1764 | struct puffs_usermount *pu; | | 1840 | struct puffs_usermount *pu; |
1765 | puffs_cookie_t opc; | | 1841 | puffs_cookie_t opc; |
1766 | puffs_cookie_t targ; | | 1842 | puffs_cookie_t targ; |
1767 | const struct puffs_cn *pcn; | | 1843 | const struct puffs_cn *pcn; |
1768 | { | | 1844 | { |
1769 | struct perfuse_state *ps; | | 1845 | struct perfuse_state *ps; |
| | | 1846 | struct perfuse_node_data *pnd; |
1770 | perfuse_msg_t *pm; | | 1847 | perfuse_msg_t *pm; |
1771 | struct puffs_node *pn; | | 1848 | struct puffs_node *pn; |
1772 | char *path; | | 1849 | char *path; |
1773 | const char *name; | | 1850 | const char *name; |
1774 | size_t len; | | 1851 | size_t len; |
1775 | int error; | | 1852 | int error; |
1776 | | | 1853 | |
| | | 1854 | pnd = PERFUSE_NODE_DATA(opc); |
| | | 1855 | |
1777 | /* | | 1856 | /* |
1778 | * remove requires -WX on the parent directory | | 1857 | * remove requires -WX on the parent directory |
1779 | * no right required on the object. | | 1858 | * no right required on the object. |
1780 | */ | | 1859 | */ |
1781 | if (no_access((puffs_cookie_t)PERFUSE_NODE_DATA(opc)->pnd_parent, | | 1860 | if (no_access((puffs_cookie_t)pnd->pnd_parent, |
1782 | pcn->pcn_cred, PUFFS_VWRITE|PUFFS_VEXEC)) | | 1861 | pcn->pcn_cred, PUFFS_VWRITE|PUFFS_VEXEC)) |
1783 | return EACCES; | | 1862 | return EACCES; |
1784 | | | 1863 | |
1785 | ps = puffs_getspecific(pu); | | 1864 | ps = puffs_getspecific(pu); |
1786 | pn = (struct puffs_node *)targ; | | 1865 | pn = (struct puffs_node *)targ; |
1787 | name = basename_r((char *)PNPATH(pn)); | | 1866 | name = basename_r((char *)PNPATH(pn)); |
1788 | len = strlen(name) + 1; | | 1867 | len = strlen(name) + 1; |
1789 | | | 1868 | |
1790 | pm = ps->ps_new_msg(pu, opc, FUSE_RMDIR, len, pcn->pcn_cred); | | 1869 | pm = ps->ps_new_msg(pu, opc, FUSE_RMDIR, len, pcn->pcn_cred); |
1791 | path = _GET_INPAYLOAD(ps, pm, char *); | | 1870 | path = _GET_INPAYLOAD(ps, pm, char *); |
1792 | (void)strlcpy(path, name, len); | | 1871 | (void)strlcpy(path, name, len); |
1793 | | | 1872 | |
1794 | if ((error = XCHG_MSG(ps, pu, pm, UNSPEC_REPLY_LEN)) != 0) | | 1873 | if ((error = XCHG_MSG(ps, pu, pm, UNSPEC_REPLY_LEN)) != 0) |
1795 | goto out; | | 1874 | goto out; |
1796 | | | 1875 | |
1797 | if (puffs_inval_namecache_dir(pu, opc) != 0) | | 1876 | if (puffs_inval_namecache_dir(pu, opc) != 0) |
1798 | DERR(EX_OSERR, "puffs_inval_namecache_dir failed"); | | 1877 | DERR(EX_OSERR, "puffs_inval_namecache_dir failed"); |
1799 | | | 1878 | |
1800 | if (puffs_inval_pagecache_node(pu, (puffs_cookie_t)pn) != 0) | | | |
1801 | DERR(EX_OSERR, "puffs_inval_namecache_node failed"); | | | |
1802 | | | | |
1803 | puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N2); | | 1879 | puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N2); |
1804 | | | 1880 | |
1805 | out: | | 1881 | out: |
1806 | ps->ps_destroy_msg(pm); | | 1882 | ps->ps_destroy_msg(pm); |
1807 | | | 1883 | |
1808 | return error; | | 1884 | return error; |
1809 | } | | 1885 | } |
1810 | | | 1886 | |
1811 | /* vap is unused */ | | 1887 | /* vap is unused */ |
1812 | /* ARGSUSED4 */ | | 1888 | /* ARGSUSED4 */ |
1813 | int | | 1889 | int |
1814 | perfuse_node_symlink(pu, opc, pni, pcn_src, vap, link_target) | | 1890 | perfuse_node_symlink(pu, opc, pni, pcn_src, vap, link_target) |
1815 | struct puffs_usermount *pu; | | 1891 | struct puffs_usermount *pu; |
| @@ -1895,37 +1971,37 @@ perfuse_node_readdir(pu, opc, dent, read | | | @@ -1895,37 +1971,37 @@ perfuse_node_readdir(pu, opc, dent, read |
1895 | __func__, (void *)opc); | | 1971 | __func__, (void *)opc); |
1896 | #endif | | 1972 | #endif |
1897 | /* | | 1973 | /* |
1898 | * Do we already have the data bufered? | | 1974 | * Do we already have the data bufered? |
1899 | */ | | 1975 | */ |
1900 | if (pnd->pnd_dirent != NULL) | | 1976 | if (pnd->pnd_dirent != NULL) |
1901 | goto out; | | 1977 | goto out; |
1902 | pnd->pnd_dirent_len = 0; | | 1978 | pnd->pnd_dirent_len = 0; |
1903 | | | 1979 | |
1904 | /* | | 1980 | /* |
1905 | * It seems NetBSD can call readdir without open first | | 1981 | * It seems NetBSD can call readdir without open first |
1906 | * libfuse will crash if it is done that way, hence open first. | | 1982 | * libfuse will crash if it is done that way, hence open first. |
1907 | */ | | 1983 | */ |
1908 | if (!(PERFUSE_NODE_DATA(opc)->pnd_flags & PND_OPEN)) { | | 1984 | if (!(pnd->pnd_flags & PND_OPEN)) { |
1909 | if ((error = perfuse_node_open(pu, opc, FREAD, pcr)) != 0) | | 1985 | if ((error = perfuse_node_open(pu, opc, FREAD, pcr)) != 0) |
1910 | goto out; | | 1986 | goto out; |
1911 | open_self = 1; | | 1987 | open_self = 1; |
1912 | } | | 1988 | } |
1913 | | | 1989 | |
1914 | fh = perfuse_get_fh(opc); | | 1990 | fh = perfuse_get_fh(opc, FREAD); |
1915 | | | 1991 | |
1916 | #ifdef PERFUSE_DEBUG | | 1992 | #ifdef PERFUSE_DEBUG |
1917 | if (perfuse_diagflags & PDF_FH) | | 1993 | if (perfuse_diagflags & PDF_FH) |
1918 | DPRINTF("%s: opc = %p, ino = %"PRId64", fh = 0x%"PRIx64"\n", | | 1994 | DPRINTF("%s: opc = %p, ino = %"PRId64", rfh = 0x%"PRIx64"\n", |
1919 | __func__, (void *)opc, | | 1995 | __func__, (void *)opc, |
1920 | PERFUSE_NODE_DATA(opc)->pnd_ino, fh); | | 1996 | PERFUSE_NODE_DATA(opc)->pnd_ino, fh); |
1921 | #endif | | 1997 | #endif |
1922 | | | 1998 | |
1923 | pnd->pnd_all_fd = NULL; | | 1999 | pnd->pnd_all_fd = NULL; |
1924 | pnd->pnd_all_fd_len = 0; | | 2000 | pnd->pnd_all_fd_len = 0; |
1925 | fd_offset = 0; | | 2001 | fd_offset = 0; |
1926 | | | 2002 | |
1927 | do { | | 2003 | do { |
1928 | size_t fd_len; | | 2004 | size_t fd_len; |
1929 | char *afdp; | | 2005 | char *afdp; |
1930 | | | 2006 | |
1931 | pm = ps->ps_new_msg(pu, opc, FUSE_READDIR, sizeof(*fri), pcr); | | 2007 | pm = ps->ps_new_msg(pu, opc, FUSE_READDIR, sizeof(*fri), pcr); |
| @@ -2003,27 +2079,27 @@ out: | | | @@ -2003,27 +2079,27 @@ out: |
2003 | free(pnd->pnd_all_fd); | | 2079 | free(pnd->pnd_all_fd); |
2004 | pnd->pnd_all_fd = NULL; | | 2080 | pnd->pnd_all_fd = NULL; |
2005 | pnd->pnd_all_fd_len = 0; | | 2081 | pnd->pnd_all_fd_len = 0; |
2006 | } | | 2082 | } |
2007 | | | 2083 | |
2008 | if (pm != NULL) | | 2084 | if (pm != NULL) |
2009 | ps->ps_destroy_msg(pm); | | 2085 | ps->ps_destroy_msg(pm); |
2010 | | | 2086 | |
2011 | /* | | 2087 | /* |
2012 | * If we opened the directory ourselves, close now | | 2088 | * If we opened the directory ourselves, close now |
2013 | * errors are ignored. | | 2089 | * errors are ignored. |
2014 | */ | | 2090 | */ |
2015 | if (open_self) | | 2091 | if (open_self) |
2016 | (void)perfuse_node_close(pu, opc, 0, pcr); | | 2092 | (void)perfuse_node_close(pu, opc, FWRITE, pcr); |
2017 | | | 2093 | |
2018 | if (error == 0) | | 2094 | if (error == 0) |
2019 | error = readdir_buffered(ps, opc, dent, readoff, | | 2095 | error = readdir_buffered(ps, opc, dent, readoff, |
2020 | reslen, pcr, eofflag, cookies, ncookies); | | 2096 | reslen, pcr, eofflag, cookies, ncookies); |
2021 | | | 2097 | |
2022 | /* | | 2098 | /* |
2023 | * Schedule queued readdir requests | | 2099 | * Schedule queued readdir requests |
2024 | */ | | 2100 | */ |
2025 | dequeue_requests(ps, opc, PCQ_READDIR, DEQUEUE_ALL); | | 2101 | dequeue_requests(ps, opc, PCQ_READDIR, DEQUEUE_ALL); |
2026 | pnd->pnd_flags &= ~PND_INREADDIR; | | 2102 | pnd->pnd_flags &= ~PND_INREADDIR; |
2027 | | | 2103 | |
2028 | #ifdef PERFUSE_DEBUG | | 2104 | #ifdef PERFUSE_DEBUG |
2029 | if (perfuse_diagflags & PDF_READDIR) | | 2105 | if (perfuse_diagflags & PDF_READDIR) |
| @@ -2082,77 +2158,99 @@ perfuse_node_reclaim(pu, opc) | | | @@ -2082,77 +2158,99 @@ perfuse_node_reclaim(pu, opc) |
2082 | puffs_cookie_t opc; | | 2158 | puffs_cookie_t opc; |
2083 | { | | 2159 | { |
2084 | struct perfuse_state *ps; | | 2160 | struct perfuse_state *ps; |
2085 | perfuse_msg_t *pm; | | 2161 | perfuse_msg_t *pm; |
2086 | struct perfuse_node_data *pnd; | | 2162 | struct perfuse_node_data *pnd; |
2087 | struct fuse_forget_in *ffi; | | 2163 | struct fuse_forget_in *ffi; |
2088 | struct puffs_node *pn; | | 2164 | struct puffs_node *pn; |
2089 | struct puffs_node *pn_root; | | 2165 | struct puffs_node *pn_root; |
2090 | | | 2166 | |
2091 | ps = puffs_getspecific(pu); | | 2167 | ps = puffs_getspecific(pu); |
2092 | pnd = PERFUSE_NODE_DATA(opc); | | 2168 | pnd = PERFUSE_NODE_DATA(opc); |
2093 | | | 2169 | |
2094 | /* | | 2170 | /* |
2095 | * Make sure open files are properly closed when reclaimed. | | | |
2096 | */ | | | |
2097 | while (pnd->pnd_flags & PND_OPEN) | | | |
2098 | (void)perfuse_node_close(pu, opc, 0, NULL); | | | |
2099 | | | | |
2100 | /* | | | |
2101 | * Never forget the root. | | 2171 | * Never forget the root. |
2102 | */ | | 2172 | */ |
2103 | if (pnd->pnd_ino == FUSE_ROOT_ID) | | 2173 | if (pnd->pnd_ino == FUSE_ROOT_ID) |
2104 | return 0; | | 2174 | return 0; |
2105 | | | 2175 | |
2106 | pnd->pnd_flags |= PND_RECLAIMED; | | 2176 | pnd->pnd_flags |= PND_RECLAIMED; |
2107 | | | 2177 | |
2108 | #ifdef PERFUSE_DEBUG | | 2178 | #ifdef PERFUSE_DEBUG |
2109 | if (perfuse_diagflags & PDF_RECLAIM) | | 2179 | if (perfuse_diagflags & PDF_RECLAIM) |
2110 | DPRINTF("%s (nodeid %"PRId64") reclaimed\n", | | 2180 | DPRINTF("%s (nodeid %"PRId64") reclaimed\n", |
2111 | (char *)PNPATH((struct puffs_node *)opc), pnd->pnd_ino); | | 2181 | (char *)PNPATH((struct puffs_node *)opc), pnd->pnd_ino); |
2112 | #endif | | 2182 | #endif |
2113 | | | 2183 | |
2114 | pn_root = puffs_getroot(pu); | | 2184 | pn_root = puffs_getroot(pu); |
2115 | pn = (struct puffs_node *)opc; | | 2185 | pn = (struct puffs_node *)opc; |
2116 | while (pn != pn_root) { | | 2186 | while (pn != pn_root) { |
2117 | struct puffs_node *parent_pn; | | 2187 | struct puffs_node *parent_pn; |
2118 | | | 2188 | |
2119 | pnd = PERFUSE_NODE_DATA(pn); | | 2189 | pnd = PERFUSE_NODE_DATA(pn); |
2120 | | | 2190 | |
2121 | #ifdef PERFUSE_DEBUG | | 2191 | #ifdef PERFUSE_DEBUG |
2122 | if (perfuse_diagflags & PDF_RECLAIM) | | 2192 | if (perfuse_diagflags & PDF_RECLAIM) |
2123 | DPRINTF("%s (nodeid %"PRId64") is %sreclaimed, " | | 2193 | DPRINTF("%s (nodeid %"PRId64") is %sreclaimed, " |
2124 | "has childcount %d, %sopen\n", | | 2194 | "has childcount %d %s%s%s, pending ops:%s%s%s%s\n", |
2125 | (char *)PNPATH(pn), pnd->pnd_ino, | | 2195 | (char *)PNPATH(pn), pnd->pnd_ino, |
2126 | pnd->pnd_flags & PND_RECLAIMED ? "" : "not ", | | 2196 | pnd->pnd_flags & PND_RECLAIMED ? "" : "not ", |
2127 | pnd->pnd_childcount, | | 2197 | pnd->pnd_childcount, |
2128 | pnd->pnd_flags & PND_OPEN ? "" : "not "); | | 2198 | pnd->pnd_flags & PND_OPEN ? "open " : "not open", |
2129 | | | 2199 | pnd->pnd_flags & PND_RFH ? "r" : "", |
2130 | if (pnd->pnd_flags & PND_OPEN) | | 2200 | pnd->pnd_flags & PND_WFH ? "w" : "", |
2131 | DWARNX("%s: (nodeid %"PRId64") %s is still open", | | 2201 | pnd->pnd_flags & PND_INREADDIR ? " readdir" : "", |
2132 | __func__, pnd->pnd_ino, (char *)PNPATH(pn)); | | 2202 | pnd->pnd_flags & PND_INREAD ? " read" : "", |
| | | 2203 | pnd->pnd_flags & PND_INWRITE ? " write" : "", |
| | | 2204 | pnd->pnd_flags & PND_BUSY ? "" : " none"); |
2133 | #endif | | 2205 | #endif |
2134 | | | 2206 | |
2135 | if (!(pnd->pnd_flags & PND_RECLAIMED) || | | 2207 | if (!(pnd->pnd_flags & PND_RECLAIMED) || |
2136 | (pnd->pnd_childcount != 0)) | | 2208 | (pnd->pnd_childcount != 0)) |
2137 | return 0; | | 2209 | return 0; |
2138 | | | 2210 | |
2139 | /* | | 2211 | /* |
2140 | * If the file is still open, close all file handles | | 2212 | * Make sure all operation are finished |
2141 | * XXX no pcr arguement to send. | | 2213 | * There can be an ongoing write, or queued operations |
2142 | */ | | 2214 | */ |
2143 | while(pnd->pnd_flags & PND_OPEN) | | 2215 | while (pnd->pnd_flags & PND_INWRITE) { |
2144 | (void)perfuse_node_close(pu, opc, 0, NULL); | | 2216 | requeue_request(pu, opc, PCQ_AFTERWRITE); |
| | | 2217 | |
| | | 2218 | /* |
| | | 2219 | * It may have been cancelled in the meantime |
| | | 2220 | */ |
| | | 2221 | if (!(pnd->pnd_flags & PND_RECLAIMED)) |
| | | 2222 | return 0; |
| | | 2223 | } |
| | | 2224 | |
| | | 2225 | #ifdef PERFUSE_DEBUG |
| | | 2226 | if ((pnd->pnd_flags & PND_BUSY) || |
| | | 2227 | !TAILQ_EMPTY(&pnd->pnd_pcq)) |
| | | 2228 | DERRX(EX_SOFTWARE, "%s: opc = %p: ongoing operations", |
| | | 2229 | __func__, (void *)opc); |
| | | 2230 | #endif |
2145 | | | 2231 | |
| | | 2232 | /* |
| | | 2233 | * Close open files |
| | | 2234 | */ |
| | | 2235 | if (pnd->pnd_flags & PND_WFH) |
| | | 2236 | (void)node_close_common(pu, opc, FREAD); |
| | | 2237 | |
| | | 2238 | if (pnd->pnd_flags & PND_RFH) |
| | | 2239 | (void)node_close_common(pu, opc, FWRITE); |
| | | 2240 | |
| | | 2241 | /* |
| | | 2242 | * And send the FORGET message |
| | | 2243 | */ |
2146 | pm = ps->ps_new_msg(pu, (puffs_cookie_t)pn, FUSE_FORGET, | | 2244 | pm = ps->ps_new_msg(pu, (puffs_cookie_t)pn, FUSE_FORGET, |
2147 | sizeof(*ffi), NULL); | | 2245 | sizeof(*ffi), NULL); |
2148 | ffi = GET_INPAYLOAD(ps, pm, fuse_forget_in); | | 2246 | ffi = GET_INPAYLOAD(ps, pm, fuse_forget_in); |
2149 | ffi->nlookup = pnd->pnd_nlookup; | | 2247 | ffi->nlookup = pnd->pnd_nlookup; |
2150 | | | 2248 | |
2151 | /* | | 2249 | /* |
2152 | * No reply is expected, pm is freed in XCHG_MSG | | 2250 | * No reply is expected, pm is freed in XCHG_MSG |
2153 | */ | | 2251 | */ |
2154 | (void)XCHG_MSG_NOREPLY(ps, pu, pm, UNSPEC_REPLY_LEN); | | 2252 | (void)XCHG_MSG_NOREPLY(ps, pu, pm, UNSPEC_REPLY_LEN); |
2155 | | | 2253 | |
2156 | parent_pn = pnd->pnd_parent; | | 2254 | parent_pn = pnd->pnd_parent; |
2157 | | | 2255 | |
2158 | perfuse_destroy_pn(pn); | | 2256 | perfuse_destroy_pn(pn); |
| @@ -2213,27 +2311,27 @@ perfuse_node_advlock(pu, opc, id, op, fl | | | @@ -2213,27 +2311,27 @@ perfuse_node_advlock(pu, opc, id, op, fl |
2213 | struct fuse_lk_in *fli; | | 2311 | struct fuse_lk_in *fli; |
2214 | struct fuse_lk_out *flo; | | 2312 | struct fuse_lk_out *flo; |
2215 | int error; | | 2313 | int error; |
2216 | | | 2314 | |
2217 | ps = puffs_getspecific(pu); | | 2315 | ps = puffs_getspecific(pu); |
2218 | | | 2316 | |
2219 | if (op == F_GETLK) | | 2317 | if (op == F_GETLK) |
2220 | fop = FUSE_GETLK; | | 2318 | fop = FUSE_GETLK; |
2221 | else | | 2319 | else |
2222 | fop = (flags & F_WAIT) ? FUSE_SETLKW : FUSE_SETLK; | | 2320 | fop = (flags & F_WAIT) ? FUSE_SETLKW : FUSE_SETLK; |
2223 | | | 2321 | |
2224 | pm = ps->ps_new_msg(pu, opc, fop, sizeof(*fli), NULL); | | 2322 | pm = ps->ps_new_msg(pu, opc, fop, sizeof(*fli), NULL); |
2225 | fli = GET_INPAYLOAD(ps, pm, fuse_lk_in); | | 2323 | fli = GET_INPAYLOAD(ps, pm, fuse_lk_in); |
2226 | fli->fh = perfuse_get_fh(opc); | | 2324 | fli->fh = perfuse_get_fh(opc, FWRITE); |
2227 | fli->owner = fl->l_pid; | | 2325 | fli->owner = fl->l_pid; |
2228 | fli->lk.start = fl->l_start; | | 2326 | fli->lk.start = fl->l_start; |
2229 | fli->lk.end = fl->l_start + fl->l_len; | | 2327 | fli->lk.end = fl->l_start + fl->l_len; |
2230 | fli->lk.type = fl->l_type; | | 2328 | fli->lk.type = fl->l_type; |
2231 | fli->lk.pid = fl->l_pid; | | 2329 | fli->lk.pid = fl->l_pid; |
2232 | fli->lk_flags = (flags & F_FLOCK) ? FUSE_LK_FLOCK : 0; | | 2330 | fli->lk_flags = (flags & F_FLOCK) ? FUSE_LK_FLOCK : 0; |
2233 | | | 2331 | |
2234 | #ifdef PERFUSE_DEBUG | | 2332 | #ifdef PERFUSE_DEBUG |
2235 | if (perfuse_diagflags & PDF_FH) | | 2333 | if (perfuse_diagflags & PDF_FH) |
2236 | DPRINTF("%s: opc = %p, ino = %"PRId64", fh = 0x%"PRIx64"\n", | | 2334 | DPRINTF("%s: opc = %p, ino = %"PRId64", fh = 0x%"PRIx64"\n", |
2237 | __func__, (void *)opc, | | 2335 | __func__, (void *)opc, |
2238 | PERFUSE_NODE_DATA(opc)->pnd_ino, fli->fh); | | 2336 | PERFUSE_NODE_DATA(opc)->pnd_ino, fli->fh); |
2239 | #endif | | 2337 | #endif |
| @@ -2269,67 +2367,73 @@ out: | | | @@ -2269,67 +2367,73 @@ out: |
2269 | } | | 2367 | } |
2270 | | | 2368 | |
2271 | int | | 2369 | int |
2272 | perfuse_node_read(pu, opc, buf, offset, resid, pcr, ioflag) | | 2370 | perfuse_node_read(pu, opc, buf, offset, resid, pcr, ioflag) |
2273 | struct puffs_usermount *pu; | | 2371 | struct puffs_usermount *pu; |
2274 | puffs_cookie_t opc; | | 2372 | puffs_cookie_t opc; |
2275 | uint8_t *buf; | | 2373 | uint8_t *buf; |
2276 | off_t offset; | | 2374 | off_t offset; |
2277 | size_t *resid; | | 2375 | size_t *resid; |
2278 | const struct puffs_cred *pcr; | | 2376 | const struct puffs_cred *pcr; |
2279 | int ioflag; | | 2377 | int ioflag; |
2280 | { | | 2378 | { |
2281 | struct perfuse_state *ps; | | 2379 | struct perfuse_state *ps; |
| | | 2380 | struct perfuse_node_data *pnd; |
2282 | perfuse_msg_t *pm; | | 2381 | perfuse_msg_t *pm; |
2283 | struct fuse_read_in *fri; | | 2382 | struct fuse_read_in *fri; |
2284 | struct fuse_out_header *foh; | | 2383 | struct fuse_out_header *foh; |
2285 | size_t readen; | | 2384 | size_t readen; |
2286 | size_t requested; | | 2385 | size_t requested; |
2287 | int error; | | 2386 | int error; |
2288 | | | 2387 | |
2289 | ps = puffs_getspecific(pu); | | 2388 | ps = puffs_getspecific(pu); |
| | | 2389 | pnd = PERFUSE_NODE_DATA(opc); |
2290 | pm = NULL; | | 2390 | pm = NULL; |
2291 | | | 2391 | |
| | | 2392 | if (puffs_pn_getvap((struct puffs_node *)opc)->va_type == VDIR) |
| | | 2393 | return EBADF; |
| | | 2394 | |
| | | 2395 | pnd->pnd_flags |= PND_INREAD; |
| | | 2396 | |
2292 | requested = *resid; | | 2397 | requested = *resid; |
2293 | if ((ps->ps_readahead + requested) > ps->ps_max_readahead) { | | 2398 | if ((ps->ps_readahead + requested) > ps->ps_max_readahead) { |
2294 | if (perfuse_diagflags & PDF_REQUEUE) | | 2399 | if (perfuse_diagflags & PDF_REQUEUE) |
2295 | DPRINTF("readahead = %zd\n", ps->ps_readahead); | | 2400 | DPRINTF("readahead = %zd\n", ps->ps_readahead); |
2296 | requeue_request(pu, opc, PCQ_READ); | | 2401 | requeue_request(pu, opc, PCQ_READ); |
2297 | } | | 2402 | } |
2298 | ps->ps_readahead += requested; | | 2403 | ps->ps_readahead += requested; |
2299 | | | 2404 | |
2300 | do { | | 2405 | do { |
2301 | /* | | 2406 | /* |
2302 | * flags may be set to FUSE_READ_LOCKOWNER | | 2407 | * flags may be set to FUSE_READ_LOCKOWNER |
2303 | * if lock_owner is provided. | | 2408 | * if lock_owner is provided. |
2304 | * | | 2409 | * |
2305 | * XXX See comment about fri->size in perfuse_node_readdir | | 2410 | * XXX See comment about fri->size in perfuse_node_readdir |
2306 | * We encounter the same bug here. | | 2411 | * We encounter the same bug here. |
2307 | */ | | 2412 | */ |
2308 | pm = ps->ps_new_msg(pu, opc, FUSE_READ, sizeof(*fri), pcr); | | 2413 | pm = ps->ps_new_msg(pu, opc, FUSE_READ, sizeof(*fri), pcr); |
2309 | fri = GET_INPAYLOAD(ps, pm, fuse_read_in); | | 2414 | fri = GET_INPAYLOAD(ps, pm, fuse_read_in); |
2310 | fri->fh = perfuse_get_fh(opc); | | 2415 | fri->fh = perfuse_get_fh(opc, FREAD); |
2311 | fri->offset = offset; | | 2416 | fri->offset = offset; |
2312 | fri->size = (uint32_t)MIN(*resid, PAGE_SIZE - sizeof(*foh)); | | 2417 | fri->size = (uint32_t)MIN(*resid, PAGE_SIZE - sizeof(*foh)); |
2313 | fri->read_flags = 0; /* XXX Unused by libfuse? */ | | 2418 | fri->read_flags = 0; /* XXX Unused by libfuse? */ |
2314 | fri->lock_owner = PERFUSE_NODE_DATA(opc)->pnd_lock_owner; | | 2419 | fri->lock_owner = pnd->pnd_lock_owner; |
2315 | fri->flags = 0; | | 2420 | fri->flags = 0; |
2316 | fri->flags |= (fri->lock_owner != 0) ? FUSE_READ_LOCKOWNER : 0; | | 2421 | fri->flags |= (fri->lock_owner != 0) ? FUSE_READ_LOCKOWNER : 0; |
2317 | | | 2422 | |
2318 | #ifdef PERFUSE_DEBUG | | 2423 | #ifdef PERFUSE_DEBUG |
2319 | if (perfuse_diagflags & PDF_FH) | | 2424 | if (perfuse_diagflags & PDF_FH) |
2320 | DPRINTF("%s: opc = %p, ino = %"PRId64", fh = 0x%"PRIx64"\n", | | 2425 | DPRINTF("%s: opc = %p, ino = %"PRId64", fh = 0x%"PRIx64"\n", |
2321 | __func__, (void *)opc, | | 2426 | __func__, (void *)opc, pnd->pnd_ino, fri->fh); |
2322 | PERFUSE_NODE_DATA(opc)->pnd_ino, fri->fh); | | | |
2323 | #endif | | 2427 | #endif |
2324 | error = XCHG_MSG(ps, pu, pm, UNSPEC_REPLY_LEN); | | 2428 | error = XCHG_MSG(ps, pu, pm, UNSPEC_REPLY_LEN); |
2325 | | | 2429 | |
2326 | if (error != 0) | | 2430 | if (error != 0) |
2327 | goto out; | | 2431 | goto out; |
2328 | | | 2432 | |
2329 | foh = GET_OUTHDR(ps, pm); | | 2433 | foh = GET_OUTHDR(ps, pm); |
2330 | readen = foh->len - sizeof(*foh); | | 2434 | readen = foh->len - sizeof(*foh); |
2331 | | | 2435 | |
2332 | (void)memcpy(buf, _GET_OUTPAYLOAD(ps, pm, char *), readen); | | 2436 | (void)memcpy(buf, _GET_OUTPAYLOAD(ps, pm, char *), readen); |
2333 | | | 2437 | |
2334 | buf += readen; | | 2438 | buf += readen; |
2335 | offset += readen; | | 2439 | offset += readen; |
| @@ -2341,93 +2445,102 @@ perfuse_node_read(pu, opc, buf, offset, | | | @@ -2341,93 +2445,102 @@ perfuse_node_read(pu, opc, buf, offset, |
2341 | | | 2445 | |
2342 | if (ioflag & (IO_SYNC|IO_DSYNC)) | | 2446 | if (ioflag & (IO_SYNC|IO_DSYNC)) |
2343 | ps->ps_syncreads++; | | 2447 | ps->ps_syncreads++; |
2344 | else | | 2448 | else |
2345 | ps->ps_asyncreads++; | | 2449 | ps->ps_asyncreads++; |
2346 | | | 2450 | |
2347 | out: | | 2451 | out: |
2348 | if (pm != NULL) | | 2452 | if (pm != NULL) |
2349 | ps->ps_destroy_msg(pm); | | 2453 | ps->ps_destroy_msg(pm); |
2350 | | | 2454 | |
2351 | ps->ps_readahead -= requested; | | 2455 | ps->ps_readahead -= requested; |
2352 | dequeue_requests(ps, opc, PCQ_READ, 1); | | 2456 | dequeue_requests(ps, opc, PCQ_READ, 1); |
2353 | | | 2457 | |
| | | 2458 | pnd->pnd_flags &= ~PND_INREAD; |
| | | 2459 | |
2354 | return error; | | 2460 | return error; |
2355 | } | | 2461 | } |
2356 | | | 2462 | |
2357 | int | | 2463 | int |
2358 | perfuse_node_write(pu, opc, buf, offset, resid, pcr, ioflag) | | 2464 | perfuse_node_write(pu, opc, buf, offset, resid, pcr, ioflag) |
2359 | struct puffs_usermount *pu; | | 2465 | struct puffs_usermount *pu; |
2360 | puffs_cookie_t opc; | | 2466 | puffs_cookie_t opc; |
2361 | uint8_t *buf; | | 2467 | uint8_t *buf; |
2362 | off_t offset; | | 2468 | off_t offset; |
2363 | size_t *resid; | | 2469 | size_t *resid; |
2364 | const struct puffs_cred *pcr; | | 2470 | const struct puffs_cred *pcr; |
2365 | int ioflag; | | 2471 | int ioflag; |
2366 | { | | 2472 | { |
2367 | struct perfuse_state *ps; | | 2473 | struct perfuse_state *ps; |
| | | 2474 | struct perfuse_node_data *pnd; |
2368 | perfuse_msg_t *pm; | | 2475 | perfuse_msg_t *pm; |
2369 | struct fuse_write_in *fwi; | | 2476 | struct fuse_write_in *fwi; |
2370 | struct fuse_write_out *fwo; | | 2477 | struct fuse_write_out *fwo; |
2371 | size_t data_len; | | 2478 | size_t data_len; |
2372 | size_t payload_len; | | 2479 | size_t payload_len; |
2373 | size_t written; | | 2480 | size_t written; |
2374 | size_t requested; | | 2481 | size_t requested; |
2375 | int error; | | 2482 | int error; |
2376 | | | 2483 | |
2377 | ps = puffs_getspecific(pu); | | 2484 | ps = puffs_getspecific(pu); |
| | | 2485 | pnd = PERFUSE_NODE_DATA(opc); |
2378 | pm = NULL; | | 2486 | pm = NULL; |
2379 | written = 0; | | 2487 | written = 0; |
2380 | | | 2488 | |
| | | 2489 | if (puffs_pn_getvap((struct puffs_node *)opc)->va_type == VDIR) |
| | | 2490 | return EBADF; |
| | | 2491 | |
| | | 2492 | DPRINTF("%s ENTER\n", __func__); |
| | | 2493 | pnd->pnd_flags |= PND_INWRITE; |
| | | 2494 | |
2381 | requested = *resid; | | 2495 | requested = *resid; |
2382 | if ((ps->ps_write + requested) > ps->ps_max_write) { | | 2496 | if ((ps->ps_write + requested) > ps->ps_max_write) { |
2383 | if (perfuse_diagflags & PDF_REQUEUE) | | 2497 | if (perfuse_diagflags & PDF_REQUEUE) |
2384 | DPRINTF("write = %zd\n", ps->ps_write); | | 2498 | DPRINTF("write = %zd\n", ps->ps_write); |
2385 | requeue_request(pu, opc, PCQ_WRITE); | | 2499 | requeue_request(pu, opc, PCQ_WRITE); |
2386 | } | | 2500 | } |
2387 | ps->ps_write += requested; | | 2501 | ps->ps_write += requested; |
2388 | | | 2502 | |
2389 | do { | | 2503 | do { |
2390 | /* | | 2504 | /* |
2391 | * It seems libfuse does not expects big chunks, so | | 2505 | * It seems libfuse does not expects big chunks, so |
2392 | * send it page per page. The writepage feature is | | 2506 | * send it page per page. The writepage feature is |
2393 | * probably there to minmize data movement. | | 2507 | * probably there to minmize data movement. |
2394 | * XXX use ps->ps_maxwrite? | | 2508 | * XXX use ps->ps_maxwrite? |
2395 | */ | | 2509 | */ |
2396 | data_len = MIN(*resid, PAGE_SIZE); | | 2510 | data_len = MIN(*resid, PAGE_SIZE); |
2397 | payload_len = data_len + sizeof(*fwi); | | 2511 | payload_len = data_len + sizeof(*fwi); |
2398 | | | 2512 | |
2399 | /* | | 2513 | /* |
2400 | * flags may be set to FUSE_WRITE_CACHE (XXX usage?) | | 2514 | * flags may be set to FUSE_WRITE_CACHE (XXX usage?) |
2401 | * or FUSE_WRITE_LOCKOWNER, if lock_owner is provided. | | 2515 | * or FUSE_WRITE_LOCKOWNER, if lock_owner is provided. |
2402 | * write_flags is set to 1 for writepage. | | 2516 | * write_flags is set to 1 for writepage. |
2403 | */ | | 2517 | */ |
2404 | pm = ps->ps_new_msg(pu, opc, FUSE_WRITE, payload_len, pcr); | | 2518 | pm = ps->ps_new_msg(pu, opc, FUSE_WRITE, payload_len, pcr); |
2405 | fwi = GET_INPAYLOAD(ps, pm, fuse_write_in); | | 2519 | fwi = GET_INPAYLOAD(ps, pm, fuse_write_in); |
2406 | fwi->fh = perfuse_get_fh(opc); | | 2520 | fwi->fh = perfuse_get_fh(opc, FWRITE); |
2407 | fwi->offset = offset; | | 2521 | fwi->offset = offset; |
2408 | fwi->size = (uint32_t)data_len; | | 2522 | fwi->size = (uint32_t)data_len; |
2409 | fwi->write_flags = (fwi->size % PAGE_SIZE) ? 0 : 1; | | 2523 | fwi->write_flags = (fwi->size % PAGE_SIZE) ? 0 : 1; |
2410 | fwi->lock_owner = PERFUSE_NODE_DATA(opc)->pnd_lock_owner; | | 2524 | fwi->lock_owner = pnd->pnd_lock_owner; |
2411 | fwi->flags = 0; | | 2525 | fwi->flags = 0; |
2412 | fwi->flags |= (fwi->lock_owner != 0) ? FUSE_WRITE_LOCKOWNER : 0; | | 2526 | fwi->flags |= (fwi->lock_owner != 0) ? FUSE_WRITE_LOCKOWNER : 0; |
2413 | fwi->flags |= (ioflag & IO_DIRECT) ? 0 : FUSE_WRITE_CACHE; | | 2527 | fwi->flags |= (ioflag & IO_DIRECT) ? 0 : FUSE_WRITE_CACHE; |
2414 | (void)memcpy((fwi + 1), buf + written, data_len); | | 2528 | (void)memcpy((fwi + 1), buf + written, data_len); |
2415 | | | 2529 | |
2416 | #ifdef PERFUSE_DEBUG | | 2530 | #ifdef PERFUSE_DEBUG |
2417 | if (perfuse_diagflags & PDF_FH) | | 2531 | if (perfuse_diagflags & PDF_FH) |
2418 | DPRINTF("%s: opc = %p, ino = %"PRId64", fh = 0x%"PRIx64"\n", | | 2532 | DPRINTF("%s: opc = %p, ino = %"PRId64", fh = 0x%"PRIx64"\n", |
2419 | __func__, (void *)opc, | | 2533 | __func__, (void *)opc, pnd->pnd_ino, fwi->fh); |
2420 | PERFUSE_NODE_DATA(opc)->pnd_ino, fwi->fh); | | | |
2421 | #endif | | 2534 | #endif |
2422 | if ((error = XCHG_MSG(ps, pu, pm, sizeof(*fwo))) != 0) | | 2535 | if ((error = XCHG_MSG(ps, pu, pm, sizeof(*fwo))) != 0) |
2423 | goto out; | | 2536 | goto out; |
2424 | | | 2537 | |
2425 | fwo = GET_OUTPAYLOAD(ps, pm, fuse_write_out); | | 2538 | fwo = GET_OUTPAYLOAD(ps, pm, fuse_write_out); |
2426 | written = fwo->size; | | 2539 | written = fwo->size; |
2427 | *resid -= written; | | 2540 | *resid -= written; |
2428 | offset += written; | | 2541 | offset += written; |
2429 | buf += written; | | 2542 | buf += written; |
2430 | | | 2543 | |
2431 | ps->ps_destroy_msg(pm); | | 2544 | ps->ps_destroy_msg(pm); |
2432 | pm = NULL; | | 2545 | pm = NULL; |
2433 | } while (*resid != 0); | | 2546 | } while (*resid != 0); |
| @@ -2437,41 +2550,48 @@ perfuse_node_write(pu, opc, buf, offset, | | | @@ -2437,41 +2550,48 @@ perfuse_node_write(pu, opc, buf, offset, |
2437 | * "everything must be written or an error will be generated" | | 2550 | * "everything must be written or an error will be generated" |
2438 | */ | | 2551 | */ |
2439 | if (*resid != 0) | | 2552 | if (*resid != 0) |
2440 | error = EFBIG; | | 2553 | error = EFBIG; |
2441 | | | 2554 | |
2442 | if (ioflag & (IO_SYNC|IO_DSYNC)) | | 2555 | if (ioflag & (IO_SYNC|IO_DSYNC)) |
2443 | ps->ps_syncwrites++; | | 2556 | ps->ps_syncwrites++; |
2444 | else | | 2557 | else |
2445 | ps->ps_asyncwrites++; | | 2558 | ps->ps_asyncwrites++; |
2446 | | | 2559 | |
2447 | /* | | 2560 | /* |
2448 | * Remember to sync the file | | 2561 | * Remember to sync the file |
2449 | */ | | 2562 | */ |
2450 | PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY; | | 2563 | pnd->pnd_flags |= PND_DIRTY; |
2451 | | | 2564 | |
2452 | #ifdef PERFUSE_DEBUG | | 2565 | #ifdef PERFUSE_DEBUG |
2453 | if (perfuse_diagflags & PDF_SYNC) | | 2566 | if (perfuse_diagflags & PDF_SYNC) |
2454 | DPRINTF("%s: DIRTY opc = %p, file = \"%s\"\n", | | 2567 | DPRINTF("%s: DIRTY opc = %p, file = \"%s\"\n", |
2455 | __func__, (void*)opc, | | 2568 | __func__, (void*)opc, |
2456 | (char *)PNPATH((struct puffs_node *)opc)); | | 2569 | (char *)PNPATH((struct puffs_node *)opc)); |
2457 | #endif | | 2570 | #endif |
2458 | out: | | 2571 | out: |
2459 | if (pm != NULL) | | 2572 | if (pm != NULL) |
2460 | ps->ps_destroy_msg(pm); | | 2573 | ps->ps_destroy_msg(pm); |
2461 | | | 2574 | |
2462 | ps->ps_write -= requested; | | 2575 | ps->ps_write -= requested; |
2463 | dequeue_requests(ps, opc, PCQ_WRITE, 1); | | 2576 | dequeue_requests(ps, opc, PCQ_WRITE, 1); |
2464 | | | 2577 | |
| | | 2578 | pnd->pnd_flags &= ~PND_INWRITE; |
| | | 2579 | |
| | | 2580 | /* |
| | | 2581 | * Dequeue operation that were waiting for write to complete |
| | | 2582 | */ |
| | | 2583 | dequeue_requests(ps, opc, PCQ_AFTERWRITE, DEQUEUE_ALL); |
| | | 2584 | |
2465 | return error; | | 2585 | return error; |
2466 | } | | 2586 | } |
2467 | | | 2587 | |
2468 | /* ARGSUSED0 */ | | 2588 | /* ARGSUSED0 */ |
2469 | void | | 2589 | void |
2470 | perfuse_cache_write(pu, opc, size, runs) | | 2590 | perfuse_cache_write(pu, opc, size, runs) |
2471 | struct puffs_usermount *pu; | | 2591 | struct puffs_usermount *pu; |
2472 | puffs_cookie_t opc; | | 2592 | puffs_cookie_t opc; |
2473 | size_t size; | | 2593 | size_t size; |
2474 | struct puffs_cacherun *runs; | | 2594 | struct puffs_cacherun *runs; |
2475 | { | | 2595 | { |
2476 | return; | | 2596 | return; |
2477 | } | | 2597 | } |