| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: ops.c,v 1.18 2010/09/29 08:01:10 manu Exp $ */ | | 1 | /* $NetBSD: ops.c,v 1.19 2010/10/03 05:46:47 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 | * |
| @@ -174,51 +174,59 @@ xchg_msg(pu, opc, pm, len, wait) | | | @@ -174,51 +174,59 @@ xchg_msg(pu, opc, pm, len, wait) |
174 | { | | 174 | { |
175 | struct perfuse_state *ps; | | 175 | struct perfuse_state *ps; |
176 | struct perfuse_node_data *pnd; | | 176 | struct perfuse_node_data *pnd; |
177 | int error; | | 177 | int error; |
178 | | | 178 | |
179 | ps = puffs_getspecific(pu); | | 179 | ps = puffs_getspecific(pu); |
180 | pnd = NULL; | | 180 | pnd = NULL; |
181 | if ((struct puffs_node *)opc != NULL) | | 181 | if ((struct puffs_node *)opc != NULL) |
182 | pnd = PERFUSE_NODE_DATA(opc); | | 182 | pnd = PERFUSE_NODE_DATA(opc); |
183 | | | 183 | |
184 | #ifdef PERFUSE_DEBUG | | 184 | #ifdef PERFUSE_DEBUG |
185 | if ((perfuse_diagflags & PDF_FILENAME) && (opc != 0)) | | 185 | if ((perfuse_diagflags & PDF_FILENAME) && (opc != 0)) |
186 | DPRINTF("file = \"%s\" flags = 0x%x\n", | | 186 | DPRINTF("file = \"%s\" flags = 0x%x\n", |
187 | (char *)PNPATH((struct puffs_node *)opc), | | 187 | perfuse_node_path(opc), |
188 | PERFUSE_NODE_DATA(opc)->pnd_flags); | | 188 | PERFUSE_NODE_DATA(opc)->pnd_flags); |
189 | #endif | | 189 | #endif |
190 | if (pnd) | | 190 | if (pnd) |
191 | pnd->pnd_flags |= PND_INXCHG; | | 191 | pnd->pnd_flags |= PND_INXCHG; |
192 | | | 192 | |
193 | error = ps->ps_xchg_msg(pu, pm, len, wait); | | 193 | error = ps->ps_xchg_msg(pu, pm, len, wait); |
194 | | | 194 | |
195 | if (pnd) { | | 195 | if (pnd) { |
196 | pnd->pnd_flags &= ~PND_INXCHG; | | 196 | pnd->pnd_flags &= ~PND_INXCHG; |
197 | (void)dequeue_requests(ps, opc, PCQ_AFTERXCHG, DEQUEUE_ALL); | | 197 | (void)dequeue_requests(ps, opc, PCQ_AFTERXCHG, DEQUEUE_ALL); |
198 | } | | 198 | } |
199 | | | 199 | |
200 | return error; | | 200 | return error; |
201 | } | | 201 | } |
202 | | | 202 | |
203 | static int | | 203 | static int |
204 | no_access(opc, pcr, mode) | | 204 | no_access(opc, pcr, mode) |
205 | puffs_cookie_t opc; | | 205 | puffs_cookie_t opc; |
206 | const struct puffs_cred *pcr; | | 206 | const struct puffs_cred *pcr; |
207 | mode_t mode; | | 207 | mode_t mode; |
208 | { | | 208 | { |
209 | struct puffs_node *pn; | | 209 | struct puffs_node *pn; |
210 | struct vattr *va; | | 210 | struct vattr *va; |
211 | | | 211 | |
| | | 212 | /* |
| | | 213 | * pcr is NULL for self open through fsync or readdir. |
| | | 214 | * In both case, access control is useless, as it was |
| | | 215 | * done before, at open time. |
| | | 216 | */ |
| | | 217 | if (pcr == NULL) |
| | | 218 | return 0; |
| | | 219 | |
212 | pn = (struct puffs_node *)opc; | | 220 | pn = (struct puffs_node *)opc; |
213 | va = puffs_pn_getvap(pn); | | 221 | va = puffs_pn_getvap(pn); |
214 | | | 222 | |
215 | return puffs_access(va->va_type, va->va_mode, | | 223 | return puffs_access(va->va_type, va->va_mode, |
216 | va->va_uid, va->va_gid, | | 224 | va->va_uid, va->va_gid, |
217 | mode, pcr); | | 225 | mode, pcr); |
218 | } | | 226 | } |
219 | | | 227 | |
220 | static void | | 228 | static void |
221 | fuse_attr_to_vap(ps, vap, fa) | | 229 | fuse_attr_to_vap(ps, vap, fa) |
222 | struct perfuse_state *ps; | | 230 | struct perfuse_state *ps; |
223 | struct vattr *vap; | | 231 | struct vattr *vap; |
224 | struct fuse_attr *fa; | | 232 | struct fuse_attr *fa; |
| @@ -281,62 +289,93 @@ node_lookup_dir_nodot(pu, opc, name, nam | | | @@ -281,62 +289,93 @@ node_lookup_dir_nodot(pu, opc, name, nam |
281 | *pnp = (struct puffs_node *)opc; | | 289 | *pnp = (struct puffs_node *)opc; |
282 | return 0; | | 290 | return 0; |
283 | } | | 291 | } |
284 | | | 292 | |
285 | /* | | 293 | /* |
286 | * For .. we just forget the name part | | 294 | * For .. we just forget the name part |
287 | */ | | 295 | */ |
288 | if (strncmp(name, "..", namelen) == 0) | | 296 | if (strncmp(name, "..", namelen) == 0) |
289 | namelen = 0; | | 297 | namelen = 0; |
290 | | | 298 | |
291 | namelen = PNPLEN(dpn) + 1 + namelen + 1; | | 299 | namelen = PNPLEN(dpn) + 1 + namelen + 1; |
292 | if ((path = malloc(namelen)) == NULL) | | 300 | if ((path = malloc(namelen)) == NULL) |
293 | DERR(EX_OSERR, "malloc failed"); | | 301 | DERR(EX_OSERR, "malloc failed"); |
294 | (void)snprintf(path, namelen, "%s/%s", (char *)PNPATH(dpn), name); | | 302 | (void)snprintf(path, namelen, "%s/%s", |
| | | 303 | perfuse_node_path((puffs_cookie_t)dpn), name); |
295 | | | 304 | |
296 | error = node_lookup_common(pu, opc, path, pnp); | | 305 | error = node_lookup_common(pu, opc, path, pnp); |
297 | | | 306 | |
298 | free(path); | | 307 | free(path); |
299 | | | 308 | |
300 | return error; | | 309 | return error; |
301 | } | | 310 | } |
302 | | | 311 | |
303 | static int | | 312 | static int |
304 | node_lookup_common(pu, opc, path, pnp) | | 313 | node_lookup_common(pu, opc, path, pnp) |
305 | struct puffs_usermount *pu; | | 314 | struct puffs_usermount *pu; |
306 | puffs_cookie_t opc; | | 315 | puffs_cookie_t opc; |
307 | const char *path; | | 316 | const char *path; |
308 | struct puffs_node **pnp; | | 317 | struct puffs_node **pnp; |
309 | { | | 318 | { |
310 | struct perfuse_state *ps; | | 319 | struct perfuse_state *ps; |
| | | 320 | struct perfuse_node_data *pnd; |
311 | perfuse_msg_t *pm; | | 321 | perfuse_msg_t *pm; |
312 | struct fuse_entry_out *feo; | | 322 | struct fuse_entry_out *feo; |
313 | struct puffs_node *pn; | | 323 | struct puffs_node *pn; |
314 | size_t len; | | 324 | size_t len; |
315 | int error; | | 325 | int error; |
316 | | | 326 | |
317 | ps = puffs_getspecific(pu); | | 327 | ps = puffs_getspecific(pu); |
318 | | | 328 | |
| | | 329 | #ifdef PERFUSE_DEBUG |
| | | 330 | if (perfuse_diagflags & PDF_FILENAME) |
| | | 331 | DPRINTF("%s: opc = %p, file = \"%s\" looking up \"%s\"\n", |
| | | 332 | __func__, (void *)opc, perfuse_node_path(opc), path); |
| | | 333 | #endif |
| | | 334 | /* |
| | | 335 | * Is the node already known? |
| | | 336 | */ |
| | | 337 | TAILQ_FOREACH(pnd, &PERFUSE_NODE_DATA(opc)->pnd_children, pnd_next) { |
| | | 338 | if ((pnd->pnd_flags & PND_REMOVED) || |
| | | 339 | (strcmp(pnd->pnd_name, path) != 0)) |
| | | 340 | continue; |
| | | 341 | |
| | | 342 | /* |
| | | 343 | * We have a match |
| | | 344 | */ |
| | | 345 | if (pnp != NULL) |
| | | 346 | *pnp = (struct puffs_node *)(pnd->pnd_pn); |
| | | 347 | |
| | | 348 | #ifdef PERFUSE_DEBUG |
| | | 349 | if (perfuse_diagflags & PDF_FILENAME) |
| | | 350 | DPRINTF("%s: opc = %p, file = \"%s\" found " |
| | | 351 | "cookie = %p, ino = %"PRId64" for \"%s\"\n", |
| | | 352 | __func__, (void *)opc, perfuse_node_path(opc), |
| | | 353 | (void *)pnd->pnd_pn, pnd->pnd_ino, path); |
| | | 354 | #endif |
| | | 355 | return 0; |
| | | 356 | } |
| | | 357 | |
319 | len = strlen(path) + 1; | | 358 | len = strlen(path) + 1; |
320 | | | 359 | |
321 | pm = ps->ps_new_msg(pu, opc, FUSE_LOOKUP, len, NULL); | | 360 | pm = ps->ps_new_msg(pu, opc, FUSE_LOOKUP, len, NULL); |
322 | (void)strlcpy(_GET_INPAYLOAD(ps, pm, char *), path, len); | | 361 | (void)strlcpy(_GET_INPAYLOAD(ps, pm, char *), path, len); |
323 | | | 362 | |
324 | if ((error = xchg_msg(pu, opc, pm, sizeof(*feo), wait_reply)) != 0) | | 363 | if ((error = xchg_msg(pu, opc, pm, sizeof(*feo), wait_reply)) != 0) |
325 | goto out; | | 364 | goto out; |
326 | | | 365 | |
327 | feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out); | | 366 | feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out); |
328 | | | 367 | |
329 | pn = perfuse_new_pn(pu, opc); | | 368 | pn = perfuse_new_pn(pu, path, opc); |
330 | PERFUSE_NODE_DATA(pn)->pnd_ino = feo->nodeid; | | 369 | PERFUSE_NODE_DATA(pn)->pnd_ino = feo->nodeid; |
331 | | | 370 | |
332 | fuse_attr_to_vap(ps, &pn->pn_va, &feo->attr); | | 371 | fuse_attr_to_vap(ps, &pn->pn_va, &feo->attr); |
333 | | | 372 | |
334 | if (pnp != NULL) | | 373 | if (pnp != NULL) |
335 | *pnp = pn; | | 374 | *pnp = pn; |
336 | | | 375 | |
337 | #ifdef PERFUSE_DEBUG | | 376 | #ifdef PERFUSE_DEBUG |
338 | if (perfuse_diagflags & PDF_FILENAME) | | 377 | if (perfuse_diagflags & PDF_FILENAME) |
339 | DPRINTF("%s: opc = %p, looked up opc = %p, ino = %"PRId64" " | | 378 | DPRINTF("%s: opc = %p, looked up opc = %p, ino = %"PRId64" " |
340 | "file = \"%s\"\n", __func__, (void *)opc, pn, | | 379 | "file = \"%s\"\n", __func__, (void *)opc, pn, |
341 | feo->nodeid, path); | | 380 | feo->nodeid, path); |
342 | #endif | | 381 | #endif |
| @@ -366,56 +405,65 @@ node_mk_common(pu, opc, pni, pcn, pm) | | | @@ -366,56 +405,65 @@ node_mk_common(pu, opc, pni, pcn, pm) |
366 | struct fuse_entry_out *feo; | | 405 | struct fuse_entry_out *feo; |
367 | struct fuse_setattr_in *fsi; | | 406 | struct fuse_setattr_in *fsi; |
368 | int error; | | 407 | int error; |
369 | | | 408 | |
370 | ps = puffs_getspecific(pu); | | 409 | ps = puffs_getspecific(pu); |
371 | | | 410 | |
372 | if ((error = xchg_msg(pu, opc, pm, sizeof(*feo), wait_reply)) != 0) | | 411 | if ((error = xchg_msg(pu, opc, pm, sizeof(*feo), wait_reply)) != 0) |
373 | goto out; | | 412 | goto out; |
374 | | | 413 | |
375 | feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out); | | 414 | feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out); |
376 | if (feo->nodeid == PERFUSE_UNKNOWN_INO) | | 415 | if (feo->nodeid == PERFUSE_UNKNOWN_INO) |
377 | DERRX(EX_SOFTWARE, "%s: no ino", __func__); | | 416 | DERRX(EX_SOFTWARE, "%s: no ino", __func__); |
378 | | | 417 | |
379 | pn = perfuse_new_pn(pu, opc); | | 418 | pn = perfuse_new_pn(pu, pcn->pcn_name, opc); |
380 | PERFUSE_NODE_DATA(pn)->pnd_ino = feo->nodeid; | | 419 | PERFUSE_NODE_DATA(pn)->pnd_ino = feo->nodeid; |
381 | | | 420 | |
382 | fuse_attr_to_vap(ps, &pn->pn_va, &feo->attr); | | 421 | fuse_attr_to_vap(ps, &pn->pn_va, &feo->attr); |
383 | puffs_newinfo_setcookie(pni, pn); | | 422 | puffs_newinfo_setcookie(pni, pn); |
| | | 423 | |
| | | 424 | #ifdef PERFUSE_DEBUG |
| | | 425 | if (perfuse_diagflags & PDF_FILENAME) |
| | | 426 | DPRINTF("%s: opc = %p, file = \"%s\", flags = 0x%x " |
| | | 427 | "ino = %"PRId64"\n", |
| | | 428 | __func__, (void *)pn, pcn->pcn_name, |
| | | 429 | PERFUSE_NODE_DATA(pn)->pnd_flags, feo->nodeid); |
| | | 430 | #endif |
384 | ps->ps_destroy_msg(pm); | | 431 | ps->ps_destroy_msg(pm); |
385 | | | 432 | |
386 | /* | | 433 | /* |
387 | * Set owner and group | | 434 | * Set owner and group |
388 | */ | | 435 | */ |
389 | (void)puffs_cred_getuid(pcn->pcn_cred, &pn->pn_va.va_uid); | | 436 | (void)puffs_cred_getuid(pcn->pcn_cred, &pn->pn_va.va_uid); |
390 | (void)puffs_cred_getgid(pcn->pcn_cred, &pn->pn_va.va_gid); | | 437 | (void)puffs_cred_getgid(pcn->pcn_cred, &pn->pn_va.va_gid); |
391 | | | 438 | |
392 | pm = ps->ps_new_msg(pu, (puffs_cookie_t)pn, | | 439 | pm = ps->ps_new_msg(pu, (puffs_cookie_t)pn, |
393 | FUSE_SETATTR, sizeof(*fsi), NULL); | | 440 | FUSE_SETATTR, sizeof(*fsi), NULL); |
394 | fsi = GET_INPAYLOAD(ps, pm, fuse_setattr_in); | | 441 | fsi = GET_INPAYLOAD(ps, pm, fuse_setattr_in); |
395 | fsi->uid = pn->pn_va.va_uid; | | 442 | fsi->uid = pn->pn_va.va_uid; |
396 | fsi->gid = pn->pn_va.va_gid; | | 443 | fsi->gid = pn->pn_va.va_gid; |
397 | fsi->valid = FUSE_FATTR_UID|FUSE_FATTR_GID; | | 444 | fsi->valid = FUSE_FATTR_UID|FUSE_FATTR_GID; |
398 | | | 445 | |
399 | /* | | 446 | /* |
400 | * A fuse_attr_out is returned, but we ignore it. | | 447 | * A fuse_attr_out is returned, but we ignore it. |
401 | */ | | 448 | */ |
402 | error = xchg_msg(pu, (puffs_cookie_t)pn, | | 449 | error = xchg_msg(pu, (puffs_cookie_t)pn, |
403 | pm, sizeof(struct fuse_attr_out), wait_reply); | | 450 | pm, sizeof(struct fuse_attr_out), wait_reply); |
404 | | | 451 | |
405 | /* | | 452 | /* |
406 | * The parent directory needs a sync | | 453 | * The parent directory needs a sync |
407 | */ | | 454 | */ |
408 | PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY; | | 455 | PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY; |
| | | 456 | |
409 | out: | | 457 | out: |
410 | ps->ps_destroy_msg(pm); | | 458 | ps->ps_destroy_msg(pm); |
411 | | | 459 | |
412 | return error; | | 460 | return error; |
413 | } | | 461 | } |
414 | | | 462 | |
415 | static ssize_t | | 463 | static ssize_t |
416 | fuse_to_dirent(pu, opc, fd, fd_len) | | 464 | fuse_to_dirent(pu, opc, fd, fd_len) |
417 | struct puffs_usermount *pu; | | 465 | struct puffs_usermount *pu; |
418 | puffs_cookie_t opc; | | 466 | puffs_cookie_t opc; |
419 | struct fuse_dirent *fd; | | 467 | struct fuse_dirent *fd; |
420 | size_t fd_len; | | 468 | size_t fd_len; |
421 | { | | 469 | { |
| @@ -985,27 +1033,27 @@ perfuse_node_create(pu, opc, pni, pcn, v | | | @@ -985,27 +1033,27 @@ perfuse_node_create(pu, opc, pni, pcn, v |
985 | len = sizeof(*feo) + sizeof(*foo); | | 1033 | len = sizeof(*feo) + sizeof(*foo); |
986 | if ((error = xchg_msg(pu, opc, pm, len, wait_reply)) != 0) | | 1034 | if ((error = xchg_msg(pu, opc, pm, len, wait_reply)) != 0) |
987 | goto out; | | 1035 | goto out; |
988 | | | 1036 | |
989 | feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out); | | 1037 | feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out); |
990 | foo = (struct fuse_open_out *)(void *)(feo + 1); | | 1038 | foo = (struct fuse_open_out *)(void *)(feo + 1); |
991 | if (feo->nodeid == PERFUSE_UNKNOWN_INO) | | 1039 | if (feo->nodeid == PERFUSE_UNKNOWN_INO) |
992 | DERRX(EX_SOFTWARE, "%s: no ino", __func__); | | 1040 | DERRX(EX_SOFTWARE, "%s: no ino", __func__); |
993 | | | 1041 | |
994 | /* | | 1042 | /* |
995 | * Save the file handle and inode in node private data | | 1043 | * Save the file handle and inode in node private data |
996 | * so that we can reuse it later | | 1044 | * so that we can reuse it later |
997 | */ | | 1045 | */ |
998 | pn = perfuse_new_pn(pu, opc); | | 1046 | pn = perfuse_new_pn(pu, name, opc); |
999 | perfuse_new_fh((puffs_cookie_t)pn, foo->fh, FWRITE); | | 1047 | perfuse_new_fh((puffs_cookie_t)pn, foo->fh, FWRITE); |
1000 | PERFUSE_NODE_DATA(pn)->pnd_ino = feo->nodeid; | | 1048 | PERFUSE_NODE_DATA(pn)->pnd_ino = feo->nodeid; |
1001 | | | 1049 | |
1002 | fuse_attr_to_vap(ps, &pn->pn_va, &feo->attr); | | 1050 | fuse_attr_to_vap(ps, &pn->pn_va, &feo->attr); |
1003 | puffs_newinfo_setcookie(pni, pn); | | 1051 | puffs_newinfo_setcookie(pni, pn); |
1004 | | | 1052 | |
1005 | /* | | 1053 | /* |
1006 | * The parent directory needs a sync | | 1054 | * The parent directory needs a sync |
1007 | */ | | 1055 | */ |
1008 | PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY; | | 1056 | PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY; |
1009 | | | 1057 | |
1010 | #ifdef PERFUSE_DEBUG | | 1058 | #ifdef PERFUSE_DEBUG |
1011 | if (perfuse_diagflags & (PDF_FH|PDF_FILENAME)) | | 1059 | if (perfuse_diagflags & (PDF_FH|PDF_FILENAME)) |
| @@ -1105,35 +1153,26 @@ perfuse_node_open(pu, opc, mode, pcr) | | | @@ -1105,35 +1153,26 @@ perfuse_node_open(pu, opc, mode, pcr) |
1105 | struct fuse_open_out *foo; | | 1153 | struct fuse_open_out *foo; |
1106 | struct puffs_node *pn; | | 1154 | struct puffs_node *pn; |
1107 | int error; | | 1155 | int error; |
1108 | | | 1156 | |
1109 | ps = puffs_getspecific(pu); | | 1157 | ps = puffs_getspecific(pu); |
1110 | pn = (struct puffs_node *)opc; | | 1158 | pn = (struct puffs_node *)opc; |
1111 | pnd = PERFUSE_NODE_DATA(opc); | | 1159 | pnd = PERFUSE_NODE_DATA(opc); |
1112 | pm = NULL; | | 1160 | pm = NULL; |
1113 | error = 0; | | 1161 | error = 0; |
1114 | | | 1162 | |
1115 | if (pnd->pnd_flags & PND_REMOVED) | | 1163 | if (pnd->pnd_flags & PND_REMOVED) |
1116 | return ENOENT; | | 1164 | return ENOENT; |
1117 | | | 1165 | |
1118 | /* | | | |
1119 | * Queue open on a node so that we do not open | | | |
1120 | * twice. This would be better with read and | | | |
1121 | * write distinguished. | | | |
1122 | */ | | | |
1123 | while (pnd->pnd_flags & PND_INOPEN) | | | |
1124 | requeue_request(pu, opc, PCQ_OPEN); | | | |
1125 | pnd->pnd_flags |= PND_INOPEN; | | | |
1126 | | | | |
1127 | if (puffs_pn_getvap(pn)->va_type == VDIR) { | | 1166 | if (puffs_pn_getvap(pn)->va_type == VDIR) { |
1128 | op = FUSE_OPENDIR; | | 1167 | op = FUSE_OPENDIR; |
1129 | pmode = PUFFS_VREAD|PUFFS_VEXEC; | | 1168 | pmode = PUFFS_VREAD|PUFFS_VEXEC; |
1130 | } else { | | 1169 | } else { |
1131 | op = FUSE_OPEN; | | 1170 | op = FUSE_OPEN; |
1132 | if (mode & FWRITE) | | 1171 | if (mode & FWRITE) |
1133 | pmode = PUFFS_VWRITE|PUFFS_VREAD; | | 1172 | pmode = PUFFS_VWRITE|PUFFS_VREAD; |
1134 | else | | 1173 | else |
1135 | pmode = PUFFS_VREAD; | | 1174 | pmode = PUFFS_VREAD; |
1136 | } | | 1175 | } |
1137 | | | 1176 | |
1138 | /* | | 1177 | /* |
1139 | * Opening a directory require R-X on the directory | | 1178 | * Opening a directory require R-X on the directory |
| @@ -1156,54 +1195,62 @@ perfuse_node_open(pu, opc, mode, pcr) | | | @@ -1156,54 +1195,62 @@ perfuse_node_open(pu, opc, mode, pcr) |
1156 | * if we already have write handle. Just ask for | | 1195 | * if we already have write handle. Just ask for |
1157 | * inactive, in case the node was open by a create | | 1196 | * inactive, in case the node was open by a create |
1158 | * operation (we are not allowed to call puffs_setback | | 1197 | * operation (we are not allowed to call puffs_setback |
1159 | * at create time, puffs interface forbids it) | | 1198 | * at create time, puffs interface forbids it) |
1160 | */ | | 1199 | */ |
1161 | if (((mode & FREAD) && (pnd->pnd_flags & PND_RFH)) || | | 1200 | if (((mode & FREAD) && (pnd->pnd_flags & PND_RFH)) || |
1162 | ((mode & FREAD) && (pnd->pnd_flags & PND_WFH)) || | | 1201 | ((mode & FREAD) && (pnd->pnd_flags & PND_WFH)) || |
1163 | ((mode & FWRITE) && (pnd->pnd_flags & PND_WFH))) { | | 1202 | ((mode & FWRITE) && (pnd->pnd_flags & PND_WFH))) { |
1164 | error = 0; | | 1203 | error = 0; |
1165 | goto out; | | 1204 | goto out; |
1166 | } | | 1205 | } |
1167 | | | 1206 | |
1168 | /* | | 1207 | /* |
| | | 1208 | * Queue open on a node so that we do not open |
| | | 1209 | * twice. This would be better with read and |
| | | 1210 | * write distinguished. |
| | | 1211 | */ |
| | | 1212 | while (pnd->pnd_flags & PND_INOPEN) |
| | | 1213 | requeue_request(pu, opc, PCQ_OPEN); |
| | | 1214 | pnd->pnd_flags |= PND_INOPEN; |
| | | 1215 | |
| | | 1216 | /* |
1169 | * Convert PUFFS mode to FUSE mode: convert FREAD/FWRITE | | 1217 | * Convert PUFFS mode to FUSE mode: convert FREAD/FWRITE |
1170 | * to O_RDONLY/O_WRONLY while perserving the other options. | | 1218 | * to O_RDONLY/O_WRONLY while perserving the other options. |
1171 | */ | | 1219 | */ |
1172 | fmode = mode & ~(FREAD|FWRITE); | | 1220 | fmode = mode & ~(FREAD|FWRITE); |
1173 | fmode |= (mode & FWRITE) ? O_RDWR : O_RDONLY; | | 1221 | fmode |= (mode & FWRITE) ? O_RDWR : O_RDONLY; |
1174 | | | 1222 | |
1175 | pm = ps->ps_new_msg(pu, opc, op, sizeof(*foi), pcr); | | 1223 | pm = ps->ps_new_msg(pu, opc, op, sizeof(*foi), pcr); |
1176 | foi = GET_INPAYLOAD(ps, pm, fuse_open_in); | | 1224 | foi = GET_INPAYLOAD(ps, pm, fuse_open_in); |
1177 | foi->flags = fmode; | | 1225 | foi->flags = fmode; |
1178 | foi->unused = 0; | | 1226 | foi->unused = 0; |
1179 | | | 1227 | |
1180 | if ((error = xchg_msg(pu, opc, pm, sizeof(*foo), wait_reply)) != 0) | | 1228 | if ((error = xchg_msg(pu, opc, pm, sizeof(*foo), wait_reply)) != 0) |
1181 | goto out; | | 1229 | goto out; |
1182 | | | 1230 | |
1183 | foo = GET_OUTPAYLOAD(ps, pm, fuse_open_out); | | 1231 | foo = GET_OUTPAYLOAD(ps, pm, fuse_open_out); |
1184 | | | 1232 | |
1185 | /* | | 1233 | /* |
1186 | * Save the file handle in node private data | | 1234 | * Save the file handle in node private data |
1187 | * so that we can reuse it later | | 1235 | * so that we can reuse it later |
1188 | */ | | 1236 | */ |
1189 | perfuse_new_fh(opc, foo->fh, mode); | | 1237 | perfuse_new_fh(opc, foo->fh, mode); |
1190 | | | 1238 | |
1191 | #ifdef PERFUSE_DEBUG | | 1239 | #ifdef PERFUSE_DEBUG |
1192 | if (perfuse_diagflags & (PDF_FH|PDF_FILENAME)) | | 1240 | if (perfuse_diagflags & (PDF_FH|PDF_FILENAME)) |
1193 | DPRINTF("%s: opc = %p, file = \"%s\", " | | 1241 | DPRINTF("%s: opc = %p, file = \"%s\", " |
1194 | "ino = %"PRId64", %s%sfh = 0x%"PRIx64"\n", | | 1242 | "ino = %"PRId64", %s%sfh = 0x%"PRIx64"\n", |
1195 | __func__, (void *)opc, | | 1243 | __func__, (void *)opc, perfuse_node_path(opc), |
1196 | (char *)PNPATH((struct puffs_node *)opc), | | | |
1197 | pnd->pnd_ino, mode & FREAD ? "r" : "", | | 1244 | pnd->pnd_ino, mode & FREAD ? "r" : "", |
1198 | mode & FWRITE ? "w" : "", foo->fh); | | 1245 | mode & FWRITE ? "w" : "", foo->fh); |
1199 | #endif | | 1246 | #endif |
1200 | | | 1247 | |
1201 | out: | | 1248 | out: |
1202 | if (pm != NULL) | | 1249 | if (pm != NULL) |
1203 | ps->ps_destroy_msg(pm); | | 1250 | ps->ps_destroy_msg(pm); |
1204 | | | 1251 | |
1205 | pnd->pnd_flags &= ~PND_INOPEN; | | 1252 | pnd->pnd_flags &= ~PND_INOPEN; |
1206 | (void)dequeue_requests(ps, opc, PCQ_OPEN, DEQUEUE_ALL); | | 1253 | (void)dequeue_requests(ps, opc, PCQ_OPEN, DEQUEUE_ALL); |
1207 | | | 1254 | |
1208 | return error; | | 1255 | return error; |
1209 | } | | 1256 | } |
| @@ -1631,28 +1678,27 @@ perfuse_node_fsync(pu, opc, pcr, flags, | | | @@ -1631,28 +1678,27 @@ perfuse_node_fsync(pu, opc, pcr, flags, |
1631 | | | 1678 | |
1632 | if (puffs_pn_getvap((struct puffs_node *)opc)->va_type == VDIR) | | 1679 | if (puffs_pn_getvap((struct puffs_node *)opc)->va_type == VDIR) |
1633 | op = FUSE_FSYNCDIR; | | 1680 | op = FUSE_FSYNCDIR; |
1634 | else /* VREG but also other types such as VLNK */ | | 1681 | else /* VREG but also other types such as VLNK */ |
1635 | op = FUSE_FSYNC; | | 1682 | op = FUSE_FSYNC; |
1636 | | | 1683 | |
1637 | /* | | 1684 | /* |
1638 | * Do not sync if there are no change to sync | | 1685 | * Do not sync if there are no change to sync |
1639 | * XXX remove that test on files if we implement mmap | | 1686 | * XXX remove that test on files if we implement mmap |
1640 | */ | | 1687 | */ |
1641 | #ifdef PERFUSE_DEBUG | | 1688 | #ifdef PERFUSE_DEBUG |
1642 | if (perfuse_diagflags & PDF_SYNC) | | 1689 | if (perfuse_diagflags & PDF_SYNC) |
1643 | DPRINTF("%s: TEST opc = %p, file = \"%s\" is %sdirty\n", | | 1690 | DPRINTF("%s: TEST opc = %p, file = \"%s\" is %sdirty\n", |
1644 | __func__, (void*)opc, | | 1691 | __func__, (void*)opc, perfuse_node_path(opc), |
1645 | (char *)PNPATH((struct puffs_node *)opc), | | | |
1646 | pnd->pnd_flags & PND_DIRTY ? "" : "not "); | | 1692 | pnd->pnd_flags & PND_DIRTY ? "" : "not "); |
1647 | #endif | | 1693 | #endif |
1648 | if (!(pnd->pnd_flags & PND_DIRTY)) | | 1694 | if (!(pnd->pnd_flags & PND_DIRTY)) |
1649 | return 0; | | 1695 | return 0; |
1650 | | | 1696 | |
1651 | /* | | 1697 | /* |
1652 | * It seems NetBSD can call fsync without open first | | 1698 | * It seems NetBSD can call fsync without open first |
1653 | * glusterfs complain in such a situation: | | 1699 | * glusterfs complain in such a situation: |
1654 | * "FSYNC() ERR => -1 (Invalid argument)" | | 1700 | * "FSYNC() ERR => -1 (Invalid argument)" |
1655 | * The file will be closed at inactive time. | | 1701 | * The file will be closed at inactive time. |
1656 | * | | 1702 | * |
1657 | * We open the directory for reading in order to sync. | | 1703 | * We open the directory for reading in order to sync. |
1658 | * This sounds rather counterintuitive, but it works. | | 1704 | * This sounds rather counterintuitive, but it works. |
| @@ -1685,28 +1731,27 @@ perfuse_node_fsync(pu, opc, pcr, flags, | | | @@ -1685,28 +1731,27 @@ perfuse_node_fsync(pu, opc, pcr, flags, |
1685 | if ((error = xchg_msg(pu, opc, pm, | | 1731 | if ((error = xchg_msg(pu, opc, pm, |
1686 | NO_PAYLOAD_REPLY_LEN, wait_reply)) != 0) | | 1732 | NO_PAYLOAD_REPLY_LEN, wait_reply)) != 0) |
1687 | goto out; | | 1733 | goto out; |
1688 | | | 1734 | |
1689 | /* | | 1735 | /* |
1690 | * No reply beyond fuse_out_header: nothing to do on success | | 1736 | * No reply beyond fuse_out_header: nothing to do on success |
1691 | * just clear the dirty flag | | 1737 | * just clear the dirty flag |
1692 | */ | | 1738 | */ |
1693 | pnd->pnd_flags &= ~PND_DIRTY; | | 1739 | pnd->pnd_flags &= ~PND_DIRTY; |
1694 | | | 1740 | |
1695 | #ifdef PERFUSE_DEBUG | | 1741 | #ifdef PERFUSE_DEBUG |
1696 | if (perfuse_diagflags & PDF_SYNC) | | 1742 | if (perfuse_diagflags & PDF_SYNC) |
1697 | DPRINTF("%s: CLEAR opc = %p, file = \"%s\"\n", | | 1743 | DPRINTF("%s: CLEAR opc = %p, file = \"%s\"\n", |
1698 | __func__, (void*)opc, | | 1744 | __func__, (void*)opc, perfuse_node_path(opc)); |
1699 | (char *)PNPATH((struct puffs_node *)opc)); | | | |
1700 | #endif | | 1745 | #endif |
1701 | | | 1746 | |
1702 | out: | | 1747 | out: |
1703 | /* | | 1748 | /* |
1704 | * ENOSYS is not returned to kernel, | | 1749 | * ENOSYS is not returned to kernel, |
1705 | */ | | 1750 | */ |
1706 | if (error == ENOSYS) | | 1751 | if (error == ENOSYS) |
1707 | error = 0; | | 1752 | error = 0; |
1708 | | | 1753 | |
1709 | if (pm != NULL) | | 1754 | if (pm != NULL) |
1710 | ps->ps_destroy_msg(pm); | | 1755 | ps->ps_destroy_msg(pm); |
1711 | | | 1756 | |
1712 | return error; | | 1757 | return error; |
| @@ -1762,40 +1807,39 @@ perfuse_node_remove(pu, opc, targ, pcn) | | | @@ -1762,40 +1807,39 @@ perfuse_node_remove(pu, opc, targ, pcn) |
1762 | */ | | 1807 | */ |
1763 | if (no_access((puffs_cookie_t)pnd->pnd_parent, | | 1808 | if (no_access((puffs_cookie_t)pnd->pnd_parent, |
1764 | pcn->pcn_cred, PUFFS_VWRITE|PUFFS_VEXEC)) | | 1809 | pcn->pcn_cred, PUFFS_VWRITE|PUFFS_VEXEC)) |
1765 | return EACCES; | | 1810 | return EACCES; |
1766 | | | 1811 | |
1767 | #ifdef PERFUSE_DEBUG | | 1812 | #ifdef PERFUSE_DEBUG |
1768 | if (targ == NULL) | | 1813 | if (targ == NULL) |
1769 | DERRX(EX_SOFTWARE, "%s: targ is NULL", __func__); | | 1814 | DERRX(EX_SOFTWARE, "%s: targ is NULL", __func__); |
1770 | | | 1815 | |
1771 | if (perfuse_diagflags & (PDF_FH|PDF_FILENAME)) | | 1816 | if (perfuse_diagflags & (PDF_FH|PDF_FILENAME)) |
1772 | DPRINTF("%s: opc = %p, remove opc = %p, file = \"%s\"\n", | | 1817 | DPRINTF("%s: opc = %p, remove opc = %p, file = \"%s\"\n", |
1773 | __func__, (void *)opc, (void *)targ, pcn->pcn_name); | | 1818 | __func__, (void *)opc, (void *)targ, pcn->pcn_name); |
1774 | #endif | | 1819 | #endif |
1775 | | | | |
1776 | ps = puffs_getspecific(pu); | | | |
1777 | pnd = PERFUSE_NODE_DATA(opc); | | | |
1778 | name = pcn->pcn_name; | | | |
1779 | len = pcn->pcn_namelen + 1; | | | |
1780 | | | | |
1781 | /* | | 1820 | /* |
1782 | * Await for all operations on the deleted node to drain, | | 1821 | * Await for all operations on the deleted node to drain, |
1783 | * as the filesystem may be confused to have it deleted | | 1822 | * as the filesystem may be confused to have it deleted |
1784 | * during a getattr | | 1823 | * during a getattr |
1785 | */ | | 1824 | */ |
1786 | while (PERFUSE_NODE_DATA(targ)->pnd_flags & PND_INXCHG) | | 1825 | while (PERFUSE_NODE_DATA(targ)->pnd_flags & PND_INXCHG) |
1787 | requeue_request(pu, targ, PCQ_AFTERXCHG); | | 1826 | requeue_request(pu, targ, PCQ_AFTERXCHG); |
1788 | | | 1827 | |
| | | 1828 | ps = puffs_getspecific(pu); |
| | | 1829 | pnd = PERFUSE_NODE_DATA(opc); |
| | | 1830 | name = pcn->pcn_name; |
| | | 1831 | len = pcn->pcn_namelen + 1; |
| | | 1832 | |
1789 | pm = ps->ps_new_msg(pu, opc, FUSE_UNLINK, len, pcn->pcn_cred); | | 1833 | pm = ps->ps_new_msg(pu, opc, FUSE_UNLINK, len, pcn->pcn_cred); |
1790 | path = _GET_INPAYLOAD(ps, pm, char *); | | 1834 | path = _GET_INPAYLOAD(ps, pm, char *); |
1791 | (void)strlcpy(path, name, len); | | 1835 | (void)strlcpy(path, name, len); |
1792 | | | 1836 | |
1793 | if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0) | | 1837 | if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0) |
1794 | goto out; | | 1838 | goto out; |
1795 | | | 1839 | |
1796 | PERFUSE_NODE_DATA(targ)->pnd_flags |= PND_REMOVED; | | 1840 | PERFUSE_NODE_DATA(targ)->pnd_flags |= PND_REMOVED; |
1797 | if (!(PERFUSE_NODE_DATA(targ)->pnd_flags & PND_OPEN)) | | 1841 | if (!(PERFUSE_NODE_DATA(targ)->pnd_flags & PND_OPEN)) |
1798 | puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N2); | | 1842 | puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N2); |
1799 | | | 1843 | |
1800 | /* | | 1844 | /* |
1801 | * The parent directory needs a sync | | 1845 | * The parent directory needs a sync |
| @@ -1910,68 +1954,62 @@ perfuse_node_rename(pu, opc, src, pcn_sr | | | @@ -1910,68 +1954,62 @@ perfuse_node_rename(pu, opc, src, pcn_sr |
1910 | | | 1954 | |
1911 | len = sizeof(*fri) + oldname_len + newname_len; | | 1955 | len = sizeof(*fri) + oldname_len + newname_len; |
1912 | pm = ps->ps_new_msg(pu, opc, FUSE_RENAME, len, pcn_src->pcn_cred); | | 1956 | pm = ps->ps_new_msg(pu, opc, FUSE_RENAME, len, pcn_src->pcn_cred); |
1913 | fri = GET_INPAYLOAD(ps, pm, fuse_rename_in); | | 1957 | fri = GET_INPAYLOAD(ps, pm, fuse_rename_in); |
1914 | fri->newdir = PERFUSE_NODE_DATA(targ_dir)->pnd_ino; | | 1958 | fri->newdir = PERFUSE_NODE_DATA(targ_dir)->pnd_ino; |
1915 | np = (char *)(void *)(fri + 1); | | 1959 | np = (char *)(void *)(fri + 1); |
1916 | (void)strlcpy(np, oldname, oldname_len); | | 1960 | (void)strlcpy(np, oldname, oldname_len); |
1917 | np += oldname_len; | | 1961 | np += oldname_len; |
1918 | (void)strlcpy(np, newname, newname_len); | | 1962 | (void)strlcpy(np, newname, newname_len); |
1919 | | | 1963 | |
1920 | if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0) | | 1964 | if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0) |
1921 | goto out; | | 1965 | goto out; |
1922 | | | 1966 | |
1923 | PERFUSE_NODE_DATA(opc)->pnd_childcount--; | | 1967 | if (opc != targ_dir) { |
1924 | PERFUSE_NODE_DATA(targ_dir)->pnd_childcount++; | | 1968 | struct perfuse_node_data *srcdir_pnd; |
| | | 1969 | struct perfuse_node_data *dstdir_pnd; |
| | | 1970 | struct perfuse_node_data *src_pnd; |
| | | 1971 | |
| | | 1972 | srcdir_pnd = PERFUSE_NODE_DATA(opc); |
| | | 1973 | dstdir_pnd = PERFUSE_NODE_DATA(targ_dir); |
| | | 1974 | src_pnd = PERFUSE_NODE_DATA(src); |
1925 | | | 1975 | |
1926 | PERFUSE_NODE_DATA(src)->pnd_parent = targ_dir; | | 1976 | TAILQ_REMOVE(&srcdir_pnd->pnd_children, src_pnd, pnd_next); |
| | | 1977 | TAILQ_INSERT_TAIL(&dstdir_pnd->pnd_children, src_pnd, pnd_next); |
1927 | | | 1978 | |
1928 | PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY; | | 1979 | srcdir_pnd->pnd_childcount--; |
1929 | PERFUSE_NODE_DATA(targ_dir)->pnd_flags |= PND_DIRTY; | | 1980 | dstdir_pnd->pnd_childcount++; |
1930 | | | 1981 | |
1931 | if ((struct puffs_node *)targ != NULL) { | | 1982 | src_pnd->pnd_parent = targ_dir; |
1932 | struct perfuse_node_data *targ_pnd; | | | |
1933 | struct perfuse_node_data *src_pnd; | | | |
1934 | | | 1983 | |
1935 | /* | | 1984 | PERFUSE_NODE_DATA(targ_dir)->pnd_flags |= PND_DIRTY; |
1936 | * We overwrite a node. src must be freed, as it | | | |
1937 | * is associated in kernel with the old path. We | | | |
1938 | * therefore have to transfer perfuse_node_data | | | |
1939 | * from src to targ. | | | |
1940 | * | | | |
1941 | * src cannot be destroyed here as setback is not | | | |
1942 | * allowed in rename operation. The node is tagged | | | |
1943 | * with PND_REMOVED, it will be disposed at inactive | | | |
1944 | * time. | | | |
1945 | */ | | | |
1946 | targ_pnd = PERFUSE_NODE_DATA(targ); | | | |
1947 | src_pnd = PERFUSE_NODE_DATA(src); | | | |
1948 | puffs_pn_setpriv((struct puffs_node *)targ, src_pnd); | | | |
1949 | puffs_pn_setpriv((struct puffs_node *)src, targ_pnd); | | | |
1950 | | | | |
1951 | PERFUSE_NODE_DATA(src)->pnd_flags |= PND_REMOVED; | | | |
1952 | } | | 1985 | } |
1953 | | | 1986 | |
| | | 1987 | (void)strlcpy(PERFUSE_NODE_DATA(src)->pnd_name, newname, MAXPATHLEN); |
| | | 1988 | |
| | | 1989 | PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY; |
| | | 1990 | |
| | | 1991 | if ((struct puffs_node *)targ != NULL) |
| | | 1992 | PERFUSE_NODE_DATA(targ)->pnd_flags |= PND_REMOVED; |
| | | 1993 | |
1954 | #ifdef PERFUSE_DEBUG | | 1994 | #ifdef PERFUSE_DEBUG |
1955 | if (perfuse_diagflags & PDF_FILENAME) | | 1995 | if (perfuse_diagflags & PDF_FILENAME) |
1956 | DPRINTF("%s: nodeid = %"PRId64" file = \"%s\" renamed \"%s\" " | | 1996 | DPRINTF("%s: nodeid = %"PRId64" file = \"%s\" renamed \"%s\" " |
1957 | "from nodeid = %"PRId64" \"%s\" " | | 1997 | "nodeid = %"PRId64" -> nodeid = %"PRId64" \"%s\"\n", |
1958 | "to nodeid = %"PRId64" \"%s\"\n", | | 1998 | __func__, PERFUSE_NODE_DATA(src)->pnd_ino, |
1959 | __func__, | | 1999 | pcn_src->pcn_name, pcn_targ->pcn_name, |
1960 | PERFUSE_NODE_DATA(src)->pnd_ino, pcn_src->pcn_name, | | 2000 | PERFUSE_NODE_DATA(opc)->pnd_ino, |
1961 | pcn_targ->pcn_name, PERFUSE_NODE_DATA(opc)->pnd_ino, | | | |
1962 | (char *)PNPATH((struct puffs_node *)targ_dir), | | | |
1963 | PERFUSE_NODE_DATA(targ_dir)->pnd_ino, | | 2001 | PERFUSE_NODE_DATA(targ_dir)->pnd_ino, |
1964 | (char *)PNPATH((struct puffs_node *)opc)); | | 2002 | perfuse_node_path(targ_dir)); |
1965 | #endif | | 2003 | #endif |
1966 | | | 2004 | |
1967 | out: | | 2005 | out: |
1968 | if (pm != NULL) | | 2006 | if (pm != NULL) |
1969 | ps->ps_destroy_msg(pm); | | 2007 | ps->ps_destroy_msg(pm); |
1970 | | | 2008 | |
1971 | return error; | | 2009 | return error; |
1972 | } | | 2010 | } |
1973 | | | 2011 | |
1974 | int | | 2012 | int |
1975 | perfuse_node_mkdir(pu, opc, pni, pcn, vap) | | 2013 | perfuse_node_mkdir(pu, opc, pni, pcn, vap) |
1976 | struct puffs_usermount *pu; | | 2014 | struct puffs_usermount *pu; |
1977 | puffs_cookie_t opc; | | 2015 | puffs_cookie_t opc; |
| @@ -2034,52 +2072,51 @@ perfuse_node_rmdir(pu, opc, targ, pcn) | | | @@ -2034,52 +2072,51 @@ perfuse_node_rmdir(pu, opc, targ, pcn) |
2034 | */ | | 2072 | */ |
2035 | if (no_access((puffs_cookie_t)pnd->pnd_parent, | | 2073 | if (no_access((puffs_cookie_t)pnd->pnd_parent, |
2036 | pcn->pcn_cred, PUFFS_VWRITE|PUFFS_VEXEC)) | | 2074 | pcn->pcn_cred, PUFFS_VWRITE|PUFFS_VEXEC)) |
2037 | return EACCES; | | 2075 | return EACCES; |
2038 | | | 2076 | |
2039 | /* | | 2077 | /* |
2040 | * Await for all operations on the deleted node to drain, | | 2078 | * Await for all operations on the deleted node to drain, |
2041 | * as the filesystem may be confused to have it deleted | | 2079 | * as the filesystem may be confused to have it deleted |
2042 | * during a getattr | | 2080 | * during a getattr |
2043 | */ | | 2081 | */ |
2044 | while (PERFUSE_NODE_DATA(targ)->pnd_flags & PND_INXCHG) | | 2082 | while (PERFUSE_NODE_DATA(targ)->pnd_flags & PND_INXCHG) |
2045 | requeue_request(pu, targ, PCQ_AFTERXCHG); | | 2083 | requeue_request(pu, targ, PCQ_AFTERXCHG); |
2046 | | | 2084 | |
2047 | | | | |
2048 | ps = puffs_getspecific(pu); | | 2085 | ps = puffs_getspecific(pu); |
2049 | name = pcn->pcn_name; | | 2086 | name = pcn->pcn_name; |
2050 | len = pcn->pcn_namelen + 1; | | 2087 | len = pcn->pcn_namelen + 1; |
2051 | | | 2088 | |
2052 | pm = ps->ps_new_msg(pu, opc, FUSE_RMDIR, len, pcn->pcn_cred); | | 2089 | pm = ps->ps_new_msg(pu, opc, FUSE_RMDIR, len, pcn->pcn_cred); |
2053 | path = _GET_INPAYLOAD(ps, pm, char *); | | 2090 | path = _GET_INPAYLOAD(ps, pm, char *); |
2054 | (void)strlcpy(path, name, len); | | 2091 | (void)strlcpy(path, name, len); |
2055 | | | 2092 | |
2056 | if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0) | | 2093 | if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0) |
2057 | goto out; | | 2094 | goto out; |
2058 | | | 2095 | |
2059 | PERFUSE_NODE_DATA(targ)->pnd_flags |= PND_REMOVED; | | 2096 | PERFUSE_NODE_DATA(targ)->pnd_flags |= PND_REMOVED; |
2060 | if (!(PERFUSE_NODE_DATA(targ)->pnd_flags & PND_OPEN)) | | 2097 | if (!(PERFUSE_NODE_DATA(targ)->pnd_flags & PND_OPEN)) |
2061 | puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N2); | | 2098 | puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N2); |
2062 | | | 2099 | |
2063 | /* | | 2100 | /* |
2064 | * The parent directory needs a sync | | 2101 | * The parent directory needs a sync |
2065 | */ | | 2102 | */ |
2066 | PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY; | | 2103 | PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY; |
2067 | | | 2104 | |
2068 | #ifdef PERFUSE_DEBUG | | 2105 | #ifdef PERFUSE_DEBUG |
2069 | if (perfuse_diagflags & PDF_FILENAME) | | 2106 | if (perfuse_diagflags & PDF_FILENAME) |
2070 | DPRINTF("%s: remove nodeid = %"PRId64" file = \"%s\"\n", | | 2107 | DPRINTF("%s: remove nodeid = %"PRId64" file = \"%s\"\n", |
2071 | __func__, PERFUSE_NODE_DATA(targ)->pnd_ino, | | 2108 | __func__, PERFUSE_NODE_DATA(targ)->pnd_ino, |
2072 | (char *)PNPATH((struct puffs_node *)targ)); | | 2109 | perfuse_node_path(targ)); |
2073 | #endif | | 2110 | #endif |
2074 | out: | | 2111 | out: |
2075 | ps->ps_destroy_msg(pm); | | 2112 | ps->ps_destroy_msg(pm); |
2076 | | | 2113 | |
2077 | return error; | | 2114 | return error; |
2078 | } | | 2115 | } |
2079 | | | 2116 | |
2080 | /* vap is unused */ | | 2117 | /* vap is unused */ |
2081 | /* ARGSUSED4 */ | | 2118 | /* ARGSUSED4 */ |
2082 | int | | 2119 | int |
2083 | perfuse_node_symlink(pu, opc, pni, pcn_src, vap, link_target) | | 2120 | perfuse_node_symlink(pu, opc, pni, pcn_src, vap, link_target) |
2084 | struct puffs_usermount *pu; | | 2121 | struct puffs_usermount *pu; |
2085 | puffs_cookie_t opc; | | 2122 | puffs_cookie_t opc; |
| @@ -2359,41 +2396,41 @@ perfuse_node_reclaim(pu, opc) | | | @@ -2359,41 +2396,41 @@ perfuse_node_reclaim(pu, opc) |
2359 | pnd = PERFUSE_NODE_DATA(opc); | | 2396 | pnd = PERFUSE_NODE_DATA(opc); |
2360 | | | 2397 | |
2361 | /* | | 2398 | /* |
2362 | * Never forget the root. | | 2399 | * Never forget the root. |
2363 | */ | | 2400 | */ |
2364 | if (pnd->pnd_ino == FUSE_ROOT_ID) | | 2401 | if (pnd->pnd_ino == FUSE_ROOT_ID) |
2365 | return 0; | | 2402 | return 0; |
2366 | | | 2403 | |
2367 | pnd->pnd_flags |= PND_RECLAIMED; | | 2404 | pnd->pnd_flags |= PND_RECLAIMED; |
2368 | | | 2405 | |
2369 | #ifdef PERFUSE_DEBUG | | 2406 | #ifdef PERFUSE_DEBUG |
2370 | if (perfuse_diagflags & PDF_RECLAIM) | | 2407 | if (perfuse_diagflags & PDF_RECLAIM) |
2371 | DPRINTF("%s (nodeid %"PRId64") reclaimed\n", | | 2408 | DPRINTF("%s (nodeid %"PRId64") reclaimed\n", |
2372 | (char *)PNPATH((struct puffs_node *)opc), pnd->pnd_ino); | | 2409 | perfuse_node_path(opc), pnd->pnd_ino); |
2373 | #endif | | 2410 | #endif |
2374 | | | 2411 | |
2375 | pn_root = puffs_getroot(pu); | | 2412 | pn_root = puffs_getroot(pu); |
2376 | pn = (struct puffs_node *)opc; | | 2413 | pn = (struct puffs_node *)opc; |
2377 | while (pn != pn_root) { | | 2414 | while (pn != pn_root) { |
2378 | struct puffs_node *parent_pn; | | 2415 | struct puffs_node *parent_pn; |
2379 | | | 2416 | |
2380 | pnd = PERFUSE_NODE_DATA(pn); | | 2417 | pnd = PERFUSE_NODE_DATA(pn); |
2381 | | | 2418 | |
2382 | #ifdef PERFUSE_DEBUG | | 2419 | #ifdef PERFUSE_DEBUG |
2383 | if (perfuse_diagflags & PDF_RECLAIM) | | 2420 | if (perfuse_diagflags & PDF_RECLAIM) |
2384 | DPRINTF("%s (nodeid %"PRId64") is %sreclaimed, " | | 2421 | DPRINTF("%s (nodeid %"PRId64") is %sreclaimed, " |
2385 | "has childcount %d %s%s%s%s, pending ops:%s%s%s\n", | | 2422 | "has childcount %d %s%s%s%s, pending ops:%s%s%s\n", |
2386 | (char *)PNPATH(pn), pnd->pnd_ino, | | 2423 | perfuse_node_path((puffs_cookie_t)pn), pnd->pnd_ino, |
2387 | pnd->pnd_flags & PND_RECLAIMED ? "" : "not ", | | 2424 | pnd->pnd_flags & PND_RECLAIMED ? "" : "not ", |
2388 | pnd->pnd_childcount, | | 2425 | pnd->pnd_childcount, |
2389 | pnd->pnd_flags & PND_OPEN ? "open " : "not open", | | 2426 | pnd->pnd_flags & PND_OPEN ? "open " : "not open", |
2390 | pnd->pnd_flags & PND_RFH ? "r" : "", | | 2427 | pnd->pnd_flags & PND_RFH ? "r" : "", |
2391 | pnd->pnd_flags & PND_WFH ? "w" : "", | | 2428 | pnd->pnd_flags & PND_WFH ? "w" : "", |
2392 | pnd->pnd_flags & PND_BUSY ? "" : " none", | | 2429 | pnd->pnd_flags & PND_BUSY ? "" : " none", |
2393 | pnd->pnd_flags & PND_INREADDIR ? " readdir" : "", | | 2430 | pnd->pnd_flags & PND_INREADDIR ? " readdir" : "", |
2394 | pnd->pnd_flags & PND_INWRITE ? " write" : "", | | 2431 | pnd->pnd_flags & PND_INWRITE ? " write" : "", |
2395 | pnd->pnd_flags & PND_INOPEN ? " open" : ""); | | 2432 | pnd->pnd_flags & PND_INOPEN ? " open" : ""); |
2396 | #endif | | 2433 | #endif |
2397 | | | 2434 | |
2398 | if (!(pnd->pnd_flags & PND_RECLAIMED) || | | 2435 | if (!(pnd->pnd_flags & PND_RECLAIMED) || |
2399 | (pnd->pnd_childcount != 0)) | | 2436 | (pnd->pnd_childcount != 0)) |
| @@ -2430,28 +2467,30 @@ perfuse_node_reclaim(pu, opc) | | | @@ -2430,28 +2467,30 @@ perfuse_node_reclaim(pu, opc) |
2430 | perfuse_destroy_pn(pu, pn); | | 2467 | perfuse_destroy_pn(pu, pn); |
2431 | | | 2468 | |
2432 | pn = parent_pn; | | 2469 | pn = parent_pn; |
2433 | } | | 2470 | } |
2434 | | | 2471 | |
2435 | return 0; | | 2472 | return 0; |
2436 | } | | 2473 | } |
2437 | | | 2474 | |
2438 | int | | 2475 | int |
2439 | perfuse_node_inactive(pu, opc) | | 2476 | perfuse_node_inactive(pu, opc) |
2440 | struct puffs_usermount *pu; | | 2477 | struct puffs_usermount *pu; |
2441 | puffs_cookie_t opc; | | 2478 | puffs_cookie_t opc; |
2442 | { | | 2479 | { |
| | | 2480 | struct perfuse_state *ps; |
2443 | struct perfuse_node_data *pnd; | | 2481 | struct perfuse_node_data *pnd; |
2444 | | | 2482 | |
| | | 2483 | ps = puffs_getspecific(pu); |
2445 | pnd = PERFUSE_NODE_DATA(opc); | | 2484 | pnd = PERFUSE_NODE_DATA(opc); |
2446 | | | 2485 | |
2447 | if (!(pnd->pnd_flags & (PND_OPEN|PND_REMOVED))) | | 2486 | if (!(pnd->pnd_flags & (PND_OPEN|PND_REMOVED))) |
2448 | return 0; | | 2487 | return 0; |
2449 | | | 2488 | |
2450 | /* | | 2489 | /* |
2451 | * Make sure all operation are finished | | 2490 | * Make sure all operation are finished |
2452 | * There can be an ongoing write. Other | | 2491 | * There can be an ongoing write. Other |
2453 | * operation wait for all data before | | 2492 | * operation wait for all data before |
2454 | * the close/inactive. | | 2493 | * the close/inactive. |
2455 | */ | | 2494 | */ |
2456 | while (pnd->pnd_flags & PND_INWRITE) | | 2495 | while (pnd->pnd_flags & PND_INWRITE) |
2457 | requeue_request(pu, opc, PCQ_AFTERWRITE); | | 2496 | requeue_request(pu, opc, PCQ_AFTERWRITE); |
| @@ -2471,31 +2510,38 @@ perfuse_node_inactive(pu, opc) | | | @@ -2471,31 +2510,38 @@ perfuse_node_inactive(pu, opc) |
2471 | */ | | 2510 | */ |
2472 | if (pnd->pnd_flags & PND_DIRTY) | | 2511 | if (pnd->pnd_flags & PND_DIRTY) |
2473 | (void)perfuse_node_fsync(pu, opc, NULL, 0, 0, 0); | | 2512 | (void)perfuse_node_fsync(pu, opc, NULL, 0, 0, 0); |
2474 | | | 2513 | |
2475 | /* | | 2514 | /* |
2476 | * Close handles | | 2515 | * Close handles |
2477 | */ | | 2516 | */ |
2478 | if (pnd->pnd_flags & PND_WFH) | | 2517 | if (pnd->pnd_flags & PND_WFH) |
2479 | (void)perfuse_node_close_common(pu, opc, FWRITE); | | 2518 | (void)perfuse_node_close_common(pu, opc, FWRITE); |
2480 | | | 2519 | |
2481 | if (pnd->pnd_flags & PND_RFH) | | 2520 | if (pnd->pnd_flags & PND_RFH) |
2482 | (void)perfuse_node_close_common(pu, opc, FREAD); | | 2521 | (void)perfuse_node_close_common(pu, opc, FREAD); |
2483 | | | 2522 | |
2484 | pnd->pnd_flags &= ~PND_INOPEN; | | 2523 | /* |
2485 | | | 2524 | * This will cause a reclaim to be sent |
| | | 2525 | */ |
2486 | if (pnd->pnd_flags & PND_REMOVED) | | 2526 | if (pnd->pnd_flags & PND_REMOVED) |
2487 | puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N1); | | 2527 | puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N1); |
2488 | | | 2528 | |
| | | 2529 | /* |
| | | 2530 | * Schedule awaiting operations |
| | | 2531 | */ |
| | | 2532 | pnd->pnd_flags &= ~PND_INOPEN; |
| | | 2533 | (void)dequeue_requests(ps, opc, PCQ_OPEN, DEQUEUE_ALL); |
| | | 2534 | |
2489 | return 0; | | 2535 | return 0; |
2490 | } | | 2536 | } |
2491 | | | 2537 | |
2492 | | | 2538 | |
2493 | /* ARGSUSED0 */ | | 2539 | /* ARGSUSED0 */ |
2494 | int | | 2540 | int |
2495 | perfuse_node_print(pu, opc) | | 2541 | perfuse_node_print(pu, opc) |
2496 | struct puffs_usermount *pu; | | 2542 | struct puffs_usermount *pu; |
2497 | puffs_cookie_t opc; | | 2543 | puffs_cookie_t opc; |
2498 | { | | 2544 | { |
2499 | DERRX(EX_SOFTWARE, "%s: UNIMPLEMENTED (FATAL)", __func__); | | 2545 | DERRX(EX_SOFTWARE, "%s: UNIMPLEMENTED (FATAL)", __func__); |
2500 | return 0; | | 2546 | return 0; |
2501 | } | | 2547 | } |
| @@ -2804,28 +2850,27 @@ perfuse_node_write(pu, opc, buf, offset, | | | @@ -2804,28 +2850,27 @@ perfuse_node_write(pu, opc, buf, offset, |
2804 | if (ioflag & (IO_SYNC|IO_DSYNC)) | | 2850 | if (ioflag & (IO_SYNC|IO_DSYNC)) |
2805 | ps->ps_syncwrites++; | | 2851 | ps->ps_syncwrites++; |
2806 | else | | 2852 | else |
2807 | ps->ps_asyncwrites++; | | 2853 | ps->ps_asyncwrites++; |
2808 | | | 2854 | |
2809 | /* | | 2855 | /* |
2810 | * Remember to sync the file | | 2856 | * Remember to sync the file |
2811 | */ | | 2857 | */ |
2812 | pnd->pnd_flags |= PND_DIRTY; | | 2858 | pnd->pnd_flags |= PND_DIRTY; |
2813 | | | 2859 | |
2814 | #ifdef PERFUSE_DEBUG | | 2860 | #ifdef PERFUSE_DEBUG |
2815 | if (perfuse_diagflags & PDF_SYNC) | | 2861 | if (perfuse_diagflags & PDF_SYNC) |
2816 | DPRINTF("%s: DIRTY opc = %p, file = \"%s\"\n", | | 2862 | DPRINTF("%s: DIRTY opc = %p, file = \"%s\"\n", |
2817 | __func__, (void*)opc, | | 2863 | __func__, (void*)opc, perfuse_node_path(opc)); |
2818 | (char *)PNPATH((struct puffs_node *)opc)); | | | |
2819 | #endif | | 2864 | #endif |
2820 | out: | | 2865 | out: |
2821 | if (pm != NULL) | | 2866 | if (pm != NULL) |
2822 | ps->ps_destroy_msg(pm); | | 2867 | ps->ps_destroy_msg(pm); |
2823 | | | 2868 | |
2824 | /* | | 2869 | /* |
2825 | * If there are no more queued write, we can resume | | 2870 | * If there are no more queued write, we can resume |
2826 | * an operation awaiting write completion. | | 2871 | * an operation awaiting write completion. |
2827 | */ | | 2872 | */ |
2828 | pnd->pnd_flags &= ~PND_INWRITE; | | 2873 | pnd->pnd_flags &= ~PND_INWRITE; |
2829 | if (dequeue_requests(ps, opc, PCQ_WRITE, 1) == 0) | | 2874 | if (dequeue_requests(ps, opc, PCQ_WRITE, 1) == 0) |
2830 | (void)dequeue_requests(ps, opc, PCQ_AFTERWRITE, DEQUEUE_ALL); | | 2875 | (void)dequeue_requests(ps, opc, PCQ_AFTERWRITE, DEQUEUE_ALL); |
2831 | | | 2876 | |