2 * Copyright (c) 2011-2018 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@dragonflybsd.org>
6 * by Venkatesh Srinivas <vsrinivas@dragonflybsd.org>
7 * by Daniel Flores (GSOC 2013 - mentored by Matthew Dillon, compression)
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
19 * 3. Neither the name of The DragonFly Project nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific, prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
31 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * Per-node backend for kernel filesystem interface.
39 * This executes a VOP concurrently on multiple nodes, each node via its own
40 * thread, and competes to advance the original request. The original
41 * request is retired the moment all requirements are met, even if the
42 * operation is still in-progress on some nodes.
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
47 #include <sys/fcntl.h>
50 #include <sys/mount.h>
51 #include <sys/vnode.h>
52 #include <sys/mountctl.h>
53 #include <sys/dirent.h>
55 #include <sys/objcache.h>
56 #include <sys/event.h>
58 #include <vfs/fifofs/fifo.h>
63 * Determine if the specified directory is empty.
65 * Returns 0 on success.
67 * Returns HAMMER_ERROR_EAGAIN if caller must re-lookup the entry and
68 * retry. (occurs if we race a ripup on oparent or ochain).
70 * Or returns a permanent HAMMER2_ERROR_* error mask.
72 * The caller must pass in an exclusively locked oparent and ochain. This
73 * function will handle the case where the chain is a directory entry or
74 * the inode itself. The original oparent,ochain will be locked upon return.
76 * This function will unlock the underlying oparent,ochain temporarily when
77 * doing an inode lookup to avoid deadlocks. The caller MUST handle the EAGAIN
78 * result as this means that oparent is no longer the parent of ochain, or
79 * that ochain was destroyed while it was unlocked.
83 checkdirempty(hammer2_chain_t *oparent, hammer2_chain_t *ochain, int clindex)
85 hammer2_chain_t *parent;
86 hammer2_chain_t *chain;
87 hammer2_key_t key_next;
96 * Find the inode, set it up as a locked 'chain'. ochain can be the
97 * inode itself, or it can be a directory entry.
99 if (ochain->bref.type == HAMMER2_BREF_TYPE_DIRENT) {
100 inum = ochain->bref.embed.dirent.inum;
101 hammer2_chain_unlock(ochain);
102 hammer2_chain_unlock(oparent);
106 error = hammer2_chain_inode_find(ochain->pmp, inum,
110 hammer2_chain_unlock(parent);
111 hammer2_chain_drop(parent);
116 * The directory entry *is* the directory inode
118 chain = hammer2_chain_lookup_init(ochain, 0);
122 * Determine if the directory is empty or not by checking its
123 * visible namespace (the area which contains directory entries).
129 chain = hammer2_chain_lookup(&parent, &key_next,
130 HAMMER2_DIRHASH_VISIBLE,
135 error = HAMMER2_ERROR_ENOTEMPTY;
136 hammer2_chain_unlock(chain);
137 hammer2_chain_drop(chain);
139 hammer2_chain_lookup_done(parent);
143 hammer2_chain_lock(oparent, HAMMER2_RESOLVE_ALWAYS);
144 hammer2_chain_lock(ochain, HAMMER2_RESOLVE_ALWAYS);
145 if ((ochain->flags & HAMMER2_CHAIN_DELETED) ||
146 (oparent->flags & HAMMER2_CHAIN_DELETED) ||
147 ochain->parent != oparent) {
148 kprintf("hammer2: debug: CHECKDIR inum %jd RETRY\n",
150 error = HAMMER2_ERROR_EAGAIN;
157 * Backend for hammer2_vfs_root()
159 * This is called when a newly mounted PFS has not yet synchronized
160 * to the inode_tid and modify_tid.
163 hammer2_xop_ipcluster(hammer2_xop_t *arg, void *scratch, int clindex)
165 hammer2_xop_ipcluster_t *xop = &arg->xop_ipcluster;
166 hammer2_chain_t *chain;
169 chain = hammer2_inode_chain(xop->head.ip1, clindex,
170 HAMMER2_RESOLVE_ALWAYS |
171 HAMMER2_RESOLVE_SHARED);
173 error = chain->error;
175 error = HAMMER2_ERROR_EIO;
177 hammer2_xop_feed(&xop->head, chain, clindex, error);
179 hammer2_chain_unlock(chain);
180 hammer2_chain_drop(chain);
185 * Backend for hammer2_vop_readdir()
188 hammer2_xop_readdir(hammer2_xop_t *arg, void *scratch, int clindex)
190 hammer2_xop_readdir_t *xop = &arg->xop_readdir;
191 hammer2_chain_t *parent;
192 hammer2_chain_t *chain;
193 hammer2_key_t key_next;
198 if (hammer2_debug & 0x0020)
199 kprintf("xop_readdir %p lkey=%016jx\n", xop, lkey);
202 * The inode's chain is the iterator. If we cannot acquire it our
203 * contribution ends here.
205 parent = hammer2_inode_chain(xop->head.ip1, clindex,
206 HAMMER2_RESOLVE_ALWAYS |
207 HAMMER2_RESOLVE_SHARED);
208 if (parent == NULL) {
209 kprintf("xop_readdir: NULL parent\n");
214 * Directory scan [re]start and loop, the feed inherits the chain's
215 * lock so do not unlock it on the iteration.
217 chain = hammer2_chain_lookup(&parent, &key_next, lkey, lkey,
218 &error, HAMMER2_LOOKUP_SHARED);
220 chain = hammer2_chain_lookup(&parent, &key_next,
221 lkey, HAMMER2_KEY_MAX,
222 &error, HAMMER2_LOOKUP_SHARED);
225 error = hammer2_xop_feed(&xop->head, chain, clindex, 0);
228 chain = hammer2_chain_next(&parent, chain, &key_next,
229 key_next, HAMMER2_KEY_MAX,
230 &error, HAMMER2_LOOKUP_SHARED);
234 hammer2_chain_unlock(chain);
235 hammer2_chain_drop(chain);
237 hammer2_chain_unlock(parent);
238 hammer2_chain_drop(parent);
240 hammer2_xop_feed(&xop->head, NULL, clindex, error);
244 * Backend for hammer2_vop_nresolve()
247 hammer2_xop_nresolve(hammer2_xop_t *arg, void *scratch, int clindex)
249 hammer2_xop_nresolve_t *xop = &arg->xop_nresolve;
250 hammer2_chain_t *parent;
251 hammer2_chain_t *chain;
254 hammer2_key_t key_next;
258 parent = hammer2_inode_chain(xop->head.ip1, clindex,
259 HAMMER2_RESOLVE_ALWAYS |
260 HAMMER2_RESOLVE_SHARED);
261 if (parent == NULL) {
262 kprintf("xop_nresolve: NULL parent\n");
264 error = HAMMER2_ERROR_EIO;
267 name = xop->head.name1;
268 name_len = xop->head.name1_len;
271 * Lookup the directory entry
273 lhc = hammer2_dirhash(name, name_len);
274 chain = hammer2_chain_lookup(&parent, &key_next,
275 lhc, lhc + HAMMER2_DIRHASH_LOMASK,
277 HAMMER2_LOOKUP_ALWAYS |
278 HAMMER2_LOOKUP_SHARED);
280 if (hammer2_chain_dirent_test(chain, name, name_len))
282 chain = hammer2_chain_next(&parent, chain, &key_next,
284 lhc + HAMMER2_DIRHASH_LOMASK,
286 HAMMER2_LOOKUP_ALWAYS |
287 HAMMER2_LOOKUP_SHARED);
291 * Locate the target inode for a directory entry
293 if (chain && chain->error == 0) {
294 if (chain->bref.type == HAMMER2_BREF_TYPE_DIRENT) {
295 lhc = chain->bref.embed.dirent.inum;
296 error = hammer2_chain_inode_find(chain->pmp,
299 HAMMER2_LOOKUP_SHARED,
303 } else if (chain && error == 0) {
304 error = chain->error;
307 error = hammer2_xop_feed(&xop->head, chain, clindex, error);
309 hammer2_chain_unlock(chain);
310 hammer2_chain_drop(chain);
313 hammer2_chain_unlock(parent);
314 hammer2_chain_drop(parent);
319 * Backend for hammer2_vop_nremove(), hammer2_vop_nrmdir(), and
320 * backend for pfs_delete.
322 * This function locates and removes a directory entry, and will lookup
323 * and return the underlying inode. For directory entries the underlying
324 * inode is not removed. If the directory entry is the actual inode itself,
325 * it may be conditonally removed and returned.
327 * WARNING! Any target inode's nlinks may not be synchronized to the
328 * in-memory inode. The frontend's hammer2_inode_unlink_finisher()
329 * is responsible for the final disposition of the actual inode.
332 hammer2_xop_unlink(hammer2_xop_t *arg, void *scratch, int clindex)
334 hammer2_xop_unlink_t *xop = &arg->xop_unlink;
335 hammer2_chain_t *parent;
336 hammer2_chain_t *chain;
339 hammer2_key_t key_next;
345 * Requires exclusive lock
347 parent = hammer2_inode_chain(xop->head.ip1, clindex,
348 HAMMER2_RESOLVE_ALWAYS);
350 if (parent == NULL) {
351 kprintf("xop_nresolve: NULL parent\n");
352 error = HAMMER2_ERROR_EIO;
355 name = xop->head.name1;
356 name_len = xop->head.name1_len;
359 * Lookup the directory entry
361 lhc = hammer2_dirhash(name, name_len);
362 chain = hammer2_chain_lookup(&parent, &key_next,
363 lhc, lhc + HAMMER2_DIRHASH_LOMASK,
364 &error, HAMMER2_LOOKUP_ALWAYS);
366 if (hammer2_chain_dirent_test(chain, name, name_len))
368 chain = hammer2_chain_next(&parent, chain, &key_next,
370 lhc + HAMMER2_DIRHASH_LOMASK,
371 &error, HAMMER2_LOOKUP_ALWAYS);
375 * The directory entry will either be a BREF_TYPE_DIRENT or a
376 * BREF_TYPE_INODE. We always permanently delete DIRENTs, but
377 * must go by xop->dopermanent for BREF_TYPE_INODE.
379 * Note that the target chain's nlinks may not be synchronized with
380 * the in-memory hammer2_inode_t structure, so we don't try to do
381 * anything fancy here. The frontend deals with nlinks
384 if (chain && chain->error == 0) {
385 int dopermanent = xop->dopermanent & H2DOPERM_PERMANENT;
386 int doforce = xop->dopermanent & H2DOPERM_FORCE;
390 * If the directory entry is the actual inode then use its
391 * type for the directory typing tests, otherwise if it is
392 * a directory entry, pull the type field from the entry.
394 * Directory entries are always permanently deleted
395 * (because they aren't the actual inode).
397 if (chain->bref.type == HAMMER2_BREF_TYPE_DIRENT) {
398 type = chain->bref.embed.dirent.type;
399 dopermanent |= HAMMER2_DELETE_PERMANENT;
401 type = chain->data->ipdata.meta.type;
405 * Check directory typing and delete the entry. Note that
406 * nlinks adjustments are made on the real inode by the
407 * frontend, not here.
409 * Unfortunately, checkdirempty() may have to unlock (parent).
410 * If it no longer matches chain->parent after re-locking,
411 * EAGAIN is returned.
413 if (type == HAMMER2_OBJTYPE_DIRECTORY && doforce) {
415 * If doforce then execute the operation even if
416 * the directory is not empty or errored. We
417 * ignore chain->error here, allowing an errored
418 * chain (aka directory entry) to still be deleted.
420 error = hammer2_chain_delete(parent, chain,
421 xop->head.mtid, dopermanent);
422 } else if (type == HAMMER2_OBJTYPE_DIRECTORY &&
424 error = HAMMER2_ERROR_EISDIR;
425 } else if (type == HAMMER2_OBJTYPE_DIRECTORY &&
426 (error = checkdirempty(parent, chain, clindex)) != 0) {
428 * error may be EAGAIN or ENOTEMPTY
430 if (error == HAMMER2_ERROR_EAGAIN) {
431 hammer2_chain_unlock(chain);
432 hammer2_chain_drop(chain);
433 hammer2_chain_unlock(parent);
434 hammer2_chain_drop(parent);
437 } else if (type != HAMMER2_OBJTYPE_DIRECTORY &&
439 error = HAMMER2_ERROR_ENOTDIR;
442 * Delete the directory entry. chain might also
443 * be a directly-embedded inode.
445 * Allow the deletion to proceed even if the chain
446 * is errored. Give priority to error-on-delete over
449 error = hammer2_chain_delete(parent, chain,
453 error = chain->error;
456 if (chain && error == 0)
457 error = chain->error;
461 * If chain is a directory entry we must resolve it. We do not try
462 * to manipulate the contents as it might not be synchronized with
463 * the frontend hammer2_inode_t, nor do we try to lookup the
464 * frontend hammer2_inode_t here (we are the backend!).
466 if (chain && chain->bref.type == HAMMER2_BREF_TYPE_DIRENT &&
467 (xop->dopermanent & H2DOPERM_IGNINO) == 0) {
470 lhc = chain->bref.embed.dirent.inum;
472 error2 = hammer2_chain_inode_find(chain->pmp, lhc,
476 kprintf("inode_find: %016jx %p failed\n",
478 error2 = 0; /* silently ignore */
485 * Return the inode target for further action. Typically used by
486 * hammer2_inode_unlink_finisher().
489 hammer2_xop_feed(&xop->head, chain, clindex, error);
491 hammer2_chain_unlock(chain);
492 hammer2_chain_drop(chain);
496 hammer2_chain_unlock(parent);
497 hammer2_chain_drop(parent);
503 * Backend for hammer2_vop_nrename()
505 * This handles the backend rename operation. Typically this renames
506 * directory entries but can also be used to rename embedded inodes.
508 * NOTE! The frontend is responsible for updating the inode meta-data in
509 * the file being renamed and for decrementing the target-replaced
510 * inode's nlinks, if present.
513 hammer2_xop_nrename(hammer2_xop_t *arg, void *scratch, int clindex)
515 hammer2_xop_nrename_t *xop = &arg->xop_nrename;
517 hammer2_chain_t *parent;
518 hammer2_chain_t *chain;
519 hammer2_chain_t *tmp;
521 hammer2_key_t key_next;
525 * We need the precise parent chain to issue the deletion.
527 * If this is a directory entry we must locate the underlying
528 * inode. If it is an embedded inode we can act directly on it.
535 if (xop->ip_key & HAMMER2_DIRHASH_VISIBLE) {
537 * Find ip's direct parent chain.
539 chain = hammer2_inode_chain(ip, clindex,
540 HAMMER2_RESOLVE_ALWAYS);
542 error = HAMMER2_ERROR_EIO;
546 if (ip->flags & HAMMER2_INODE_CREATING) {
549 parent = hammer2_chain_getparent(chain,
550 HAMMER2_RESOLVE_ALWAYS);
551 if (parent == NULL) {
552 error = HAMMER2_ERROR_EIO;
558 * The directory entry for the head.ip1 inode
559 * is in fdip, do a namespace search.
565 parent = hammer2_inode_chain(xop->head.ip1, clindex,
566 HAMMER2_RESOLVE_ALWAYS);
567 if (parent == NULL) {
568 kprintf("xop_nrename: NULL parent\n");
569 error = HAMMER2_ERROR_EIO;
572 name = xop->head.name1;
573 name_len = xop->head.name1_len;
576 * Lookup the directory entry
578 lhc = hammer2_dirhash(name, name_len);
579 chain = hammer2_chain_lookup(&parent, &key_next,
580 lhc, lhc + HAMMER2_DIRHASH_LOMASK,
581 &error, HAMMER2_LOOKUP_ALWAYS);
583 if (hammer2_chain_dirent_test(chain, name, name_len))
585 chain = hammer2_chain_next(&parent, chain, &key_next,
587 lhc + HAMMER2_DIRHASH_LOMASK,
589 HAMMER2_LOOKUP_ALWAYS);
594 /* XXX shouldn't happen, but does under fsstress */
595 kprintf("hammer2_xop_nrename: \"%s\" -> \"%s\" ENOENT\n",
599 error = HAMMER2_ERROR_ENOENT;
604 error = chain->error;
609 * Delete it, then create it in the new namespace.
611 * An error can occur if the chain being deleted requires
612 * modification and the media is full.
614 error = hammer2_chain_delete(parent, chain, xop->head.mtid, 0);
615 hammer2_chain_unlock(parent);
616 hammer2_chain_drop(parent);
617 parent = NULL; /* safety */
622 * Adjust fields in the deleted chain appropriate for the rename
625 * NOTE! For embedded inodes, the frontend will officially replicate
626 * the field adjustments, but we also do it here to maintain
627 * consistency in case of a crash.
629 if (chain->bref.key != xop->lhc ||
630 xop->head.name1_len != xop->head.name2_len ||
631 bcmp(xop->head.name1, xop->head.name2, xop->head.name1_len) != 0) {
632 if (chain->bref.type == HAMMER2_BREF_TYPE_INODE) {
633 hammer2_inode_data_t *wipdata;
635 error = hammer2_chain_modify(chain, xop->head.mtid,
638 wipdata = &chain->data->ipdata;
640 bzero(wipdata->filename,
641 sizeof(wipdata->filename));
642 bcopy(xop->head.name2,
644 xop->head.name2_len);
645 wipdata->meta.name_key = xop->lhc;
646 wipdata->meta.name_len = xop->head.name2_len;
649 if (chain->bref.type == HAMMER2_BREF_TYPE_DIRENT) {
650 if (xop->head.name2_len <=
651 sizeof(chain->bref.check.buf)) {
653 * Remove any related data buffer, we can
654 * embed the filename in the bref itself.
656 error = hammer2_chain_resize(
657 chain, xop->head.mtid, 0, 0, 0);
659 error = hammer2_chain_modify(
660 chain, xop->head.mtid,
664 bzero(chain->bref.check.buf,
665 sizeof(chain->bref.check.buf));
666 bcopy(xop->head.name2,
667 chain->bref.check.buf,
668 xop->head.name2_len);
672 * Associate a data buffer with the bref.
673 * Zero it for consistency. Note that the
674 * data buffer is not 64KB so use chain->bytes
675 * instead of sizeof().
677 error = hammer2_chain_resize(
678 chain, xop->head.mtid, 0,
679 hammer2_getradix(HAMMER2_ALLOC_MIN), 0);
681 error = hammer2_chain_modify(
682 chain, xop->head.mtid,
686 bzero(chain->data->buf, chain->bytes);
687 bcopy(xop->head.name2,
689 xop->head.name2_len);
693 chain->bref.embed.dirent.namlen =
700 * The frontend will replicate this operation and is the real final
701 * authority, but adjust the inode's iparent field too if the inode
702 * is embedded in the directory.
704 if (chain->bref.type == HAMMER2_BREF_TYPE_INODE &&
705 chain->data->ipdata.meta.iparent != xop->head.ip3->meta.inum) {
706 hammer2_inode_data_t *wipdata;
708 error = hammer2_chain_modify(chain, xop->head.mtid, 0, 0);
710 wipdata = &chain->data->ipdata;
711 wipdata->meta.iparent = xop->head.ip3->meta.inum;
716 * Destroy any matching target(s) before creating the new entry.
717 * This will result in some ping-ponging of the directory key
718 * iterator but that is ok.
720 parent = hammer2_inode_chain(xop->head.ip3, clindex,
721 HAMMER2_RESOLVE_ALWAYS);
722 if (parent == NULL) {
723 error = HAMMER2_ERROR_EIO;
728 * Delete all matching directory entries. That is, get rid of
729 * multiple duplicates if present, as a self-healing mechanism.
732 tmp = hammer2_chain_lookup(&parent, &key_next,
733 xop->lhc & ~HAMMER2_DIRHASH_LOMASK,
734 xop->lhc | HAMMER2_DIRHASH_LOMASK,
736 HAMMER2_LOOKUP_ALWAYS);
739 if (hammer2_chain_dirent_test(tmp, xop->head.name2,
740 xop->head.name2_len)) {
741 e2 = hammer2_chain_delete(parent, tmp,
743 if (error == 0 && e2)
746 tmp = hammer2_chain_next(&parent, tmp, &key_next,
749 HAMMER2_DIRHASH_LOMASK,
751 HAMMER2_LOOKUP_ALWAYS);
756 * A relookup is required before the create to properly
757 * position the parent chain.
759 tmp = hammer2_chain_lookup(&parent, &key_next,
762 KKASSERT(tmp == NULL);
763 error = hammer2_chain_create(&parent, &chain, NULL, pmp,
764 HAMMER2_METH_DEFAULT,
766 HAMMER2_BREF_TYPE_INODE,
768 xop->head.mtid, 0, 0);
771 hammer2_xop_feed(&xop->head, NULL, clindex, error);
773 hammer2_chain_unlock(parent);
774 hammer2_chain_drop(parent);
777 hammer2_chain_unlock(chain);
778 hammer2_chain_drop(chain);
783 * Directory collision resolver scan helper (backend, threaded).
785 * Used by the inode create code to locate an unused lhc.
788 hammer2_xop_scanlhc(hammer2_xop_t *arg, void *scratch, int clindex)
790 hammer2_xop_scanlhc_t *xop = &arg->xop_scanlhc;
791 hammer2_chain_t *parent;
792 hammer2_chain_t *chain;
793 hammer2_key_t key_next;
796 parent = hammer2_inode_chain(xop->head.ip1, clindex,
797 HAMMER2_RESOLVE_ALWAYS |
798 HAMMER2_RESOLVE_SHARED);
799 if (parent == NULL) {
800 kprintf("xop_nresolve: NULL parent\n");
802 error = HAMMER2_ERROR_EIO;
807 * Lookup all possibly conflicting directory entries, the feed
808 * inherits the chain's lock so do not unlock it on the iteration.
810 chain = hammer2_chain_lookup(&parent, &key_next,
812 xop->lhc + HAMMER2_DIRHASH_LOMASK,
814 HAMMER2_LOOKUP_ALWAYS |
815 HAMMER2_LOOKUP_SHARED);
817 error = hammer2_xop_feed(&xop->head, chain, clindex, 0);
819 hammer2_chain_unlock(chain);
820 hammer2_chain_drop(chain);
821 chain = NULL; /* safety */
824 chain = hammer2_chain_next(&parent, chain, &key_next,
826 xop->lhc + HAMMER2_DIRHASH_LOMASK,
828 HAMMER2_LOOKUP_ALWAYS |
829 HAMMER2_LOOKUP_SHARED);
832 hammer2_xop_feed(&xop->head, NULL, clindex, error);
834 hammer2_chain_unlock(parent);
835 hammer2_chain_drop(parent);
840 * Generic lookup of a specific key.
843 hammer2_xop_lookup(hammer2_xop_t *arg, void *scratch, int clindex)
845 hammer2_xop_scanlhc_t *xop = &arg->xop_scanlhc;
846 hammer2_chain_t *parent;
847 hammer2_chain_t *chain;
848 hammer2_key_t key_next;
851 parent = hammer2_inode_chain(xop->head.ip1, clindex,
852 HAMMER2_RESOLVE_ALWAYS |
853 HAMMER2_RESOLVE_SHARED);
855 if (parent == NULL) {
856 error = HAMMER2_ERROR_EIO;
861 * Lookup all possibly conflicting directory entries, the feed
862 * inherits the chain's lock so do not unlock it on the iteration.
864 chain = hammer2_chain_lookup(&parent, &key_next,
867 HAMMER2_LOOKUP_ALWAYS |
868 HAMMER2_LOOKUP_SHARED);
871 error = chain->error;
873 error = HAMMER2_ERROR_ENOENT;
875 hammer2_xop_feed(&xop->head, chain, clindex, error);
879 hammer2_chain_unlock(chain);
880 hammer2_chain_drop(chain);
883 hammer2_chain_unlock(parent);
884 hammer2_chain_drop(parent);
889 hammer2_xop_delete(hammer2_xop_t *arg, void *scratch, int clindex)
891 hammer2_xop_scanlhc_t *xop = &arg->xop_scanlhc;
892 hammer2_chain_t *parent;
893 hammer2_chain_t *chain;
894 hammer2_key_t key_next;
897 parent = hammer2_inode_chain(xop->head.ip1, clindex,
898 HAMMER2_RESOLVE_ALWAYS);
900 if (parent == NULL) {
901 error = HAMMER2_ERROR_EIO;
906 * Lookup all possibly conflicting directory entries, the feed
907 * inherits the chain's lock so do not unlock it on the iteration.
909 chain = hammer2_chain_lookup(&parent, &key_next,
912 HAMMER2_LOOKUP_NODATA);
915 error = chain->error;
917 error = HAMMER2_ERROR_ENOENT;
920 error = hammer2_chain_delete(parent, chain, xop->head.mtid,
921 HAMMER2_DELETE_PERMANENT);
923 hammer2_xop_feed(&xop->head, NULL, clindex, error);
927 hammer2_chain_unlock(chain);
928 hammer2_chain_drop(chain);
931 hammer2_chain_unlock(parent);
932 hammer2_chain_drop(parent);
939 * WARNING! Fed chains must be locked shared so ownership can be transfered
940 * and to prevent frontend/backend stalls that would occur with an
941 * exclusive lock. The shared lock also allows chain->data to be
945 hammer2_xop_scanall(hammer2_xop_t *arg, void *scratch, int clindex)
947 hammer2_xop_scanall_t *xop = &arg->xop_scanall;
948 hammer2_chain_t *parent;
949 hammer2_chain_t *chain;
950 hammer2_key_t key_next;
954 * Assert required flags.
956 KKASSERT(xop->resolve_flags & HAMMER2_RESOLVE_SHARED);
957 KKASSERT(xop->lookup_flags & HAMMER2_LOOKUP_SHARED);
960 * The inode's chain is the iterator. If we cannot acquire it our
961 * contribution ends here.
963 parent = hammer2_inode_chain(xop->head.ip1, clindex,
965 if (parent == NULL) {
966 kprintf("xop_readdir: NULL parent\n");
971 * Generic scan of exact records. Note that indirect blocks are
972 * automatically recursed and will not be returned.
974 chain = hammer2_chain_lookup(&parent, &key_next,
975 xop->key_beg, xop->key_end,
976 &error, xop->lookup_flags);
978 error = hammer2_xop_feed(&xop->head, chain, clindex, 0);
981 chain = hammer2_chain_next(&parent, chain, &key_next,
982 key_next, xop->key_end,
983 &error, xop->lookup_flags);
987 hammer2_chain_unlock(chain);
988 hammer2_chain_drop(chain);
990 hammer2_chain_unlock(parent);
991 hammer2_chain_drop(parent);
993 hammer2_xop_feed(&xop->head, NULL, clindex, error);
996 /************************************************************************
998 ************************************************************************
1002 * Helper to create a directory entry.
1005 hammer2_xop_inode_mkdirent(hammer2_xop_t *arg, void *scratch, int clindex)
1007 hammer2_xop_mkdirent_t *xop = &arg->xop_mkdirent;
1008 hammer2_chain_t *parent;
1009 hammer2_chain_t *chain;
1010 hammer2_key_t key_next;
1014 if (hammer2_debug & 0x0001)
1015 kprintf("dirent_create lhc %016jx clindex %d\n",
1018 parent = hammer2_inode_chain(xop->head.ip1, clindex,
1019 HAMMER2_RESOLVE_ALWAYS);
1020 if (parent == NULL) {
1021 error = HAMMER2_ERROR_EIO;
1025 chain = hammer2_chain_lookup(&parent, &key_next,
1029 error = HAMMER2_ERROR_EEXIST;
1034 * We may be able to embed the directory entry directly in the
1037 if (xop->dirent.namlen <= sizeof(chain->bref.check.buf))
1040 data_len = HAMMER2_ALLOC_MIN;
1042 error = hammer2_chain_create(&parent, &chain, NULL, xop->head.ip1->pmp,
1043 HAMMER2_METH_DEFAULT,
1045 HAMMER2_BREF_TYPE_DIRENT,
1047 xop->head.mtid, 0, 0);
1050 * WARNING: chain->data->buf is sized to chain->bytes,
1051 * do not use sizeof(chain->data->buf), which
1052 * will be much larger.
1054 error = hammer2_chain_modify(chain, xop->head.mtid, 0, 0);
1056 chain->bref.embed.dirent = xop->dirent;
1057 if (xop->dirent.namlen <= sizeof(chain->bref.check.buf))
1058 bcopy(xop->head.name1, chain->bref.check.buf,
1059 xop->dirent.namlen);
1061 bcopy(xop->head.name1, chain->data->buf,
1062 xop->dirent.namlen);
1067 hammer2_chain_unlock(parent);
1068 hammer2_chain_drop(parent);
1070 hammer2_xop_feed(&xop->head, chain, clindex, error);
1072 hammer2_chain_unlock(chain);
1073 hammer2_chain_drop(chain);
1078 * Inode create helper (threaded, backend)
1080 * Used by ncreate, nmknod, nsymlink, nmkdir.
1081 * Used by nlink and rename to create HARDLINK pointers.
1083 * Frontend holds the parent directory ip locked exclusively. We
1084 * create the inode and feed the exclusively locked chain to the
1088 hammer2_xop_inode_create(hammer2_xop_t *arg, void *scratch, int clindex)
1090 hammer2_xop_create_t *xop = &arg->xop_create;
1091 hammer2_chain_t *parent;
1092 hammer2_chain_t *chain;
1093 hammer2_key_t key_next;
1096 if (hammer2_debug & 0x0001)
1097 kprintf("inode_create lhc %016jx clindex %d\n",
1100 parent = hammer2_inode_chain(xop->head.ip1, clindex,
1101 HAMMER2_RESOLVE_ALWAYS);
1102 if (parent == NULL) {
1103 error = HAMMER2_ERROR_EIO;
1107 chain = hammer2_chain_lookup(&parent, &key_next,
1111 error = HAMMER2_ERROR_EEXIST;
1115 error = hammer2_chain_create(&parent, &chain, NULL, xop->head.ip1->pmp,
1116 HAMMER2_METH_DEFAULT,
1118 HAMMER2_BREF_TYPE_INODE,
1119 HAMMER2_INODE_BYTES,
1120 xop->head.mtid, 0, xop->flags);
1122 error = hammer2_chain_modify(chain, xop->head.mtid, 0, 0);
1124 chain->data->ipdata.meta = xop->meta;
1125 if (xop->head.name1) {
1126 bcopy(xop->head.name1,
1127 chain->data->ipdata.filename,
1128 xop->head.name1_len);
1129 chain->data->ipdata.meta.name_len =
1130 xop->head.name1_len;
1132 chain->data->ipdata.meta.name_key = xop->lhc;
1137 hammer2_chain_unlock(parent);
1138 hammer2_chain_drop(parent);
1140 hammer2_xop_feed(&xop->head, chain, clindex, error);
1142 hammer2_chain_unlock(chain);
1143 hammer2_chain_drop(chain);
1148 * Create inode as above but leave it detached from the hierarchy.
1151 hammer2_xop_inode_create_det(hammer2_xop_t *arg, void *scratch, int clindex)
1153 hammer2_xop_create_t *xop = &arg->xop_create;
1154 hammer2_chain_t *parent;
1155 hammer2_chain_t *chain;
1156 hammer2_chain_t *null_parent;
1157 hammer2_key_t key_next;
1158 hammer2_inode_t *pip;
1159 hammer2_inode_t *iroot;
1162 if (hammer2_debug & 0x0001)
1163 kprintf("inode_create_det lhc %016jx clindex %d\n",
1166 pip = xop->head.ip1;
1167 iroot = pip->pmp->iroot;
1169 parent = hammer2_inode_chain(iroot, clindex, HAMMER2_RESOLVE_ALWAYS);
1171 if (parent == NULL) {
1172 error = HAMMER2_ERROR_EIO;
1176 chain = hammer2_chain_lookup(&parent, &key_next,
1180 error = HAMMER2_ERROR_EEXIST;
1185 * Create as a detached chain with no parent. We must specify
1189 error = hammer2_chain_create(&null_parent, &chain,
1190 parent->hmp, pip->pmp,
1191 HAMMER2_ENC_COMP(pip->meta.comp_algo) +
1192 HAMMER2_ENC_CHECK(pip->meta.check_algo),
1194 HAMMER2_BREF_TYPE_INODE,
1195 HAMMER2_INODE_BYTES,
1196 xop->head.mtid, 0, xop->flags);
1198 error = hammer2_chain_modify(chain, xop->head.mtid, 0, 0);
1200 chain->data->ipdata.meta = xop->meta;
1201 if (xop->head.name1) {
1202 bcopy(xop->head.name1,
1203 chain->data->ipdata.filename,
1204 xop->head.name1_len);
1205 chain->data->ipdata.meta.name_len =
1206 xop->head.name1_len;
1208 chain->data->ipdata.meta.name_key = xop->lhc;
1213 hammer2_chain_unlock(parent);
1214 hammer2_chain_drop(parent);
1216 hammer2_xop_feed(&xop->head, chain, clindex, error);
1218 hammer2_chain_unlock(chain);
1219 hammer2_chain_drop(chain);
1224 * Take a detached chain and insert it into the topology
1227 hammer2_xop_inode_create_ins(hammer2_xop_t *arg, void *scratch, int clindex)
1229 hammer2_xop_create_t *xop = &arg->xop_create;
1230 hammer2_chain_t *parent;
1231 hammer2_chain_t *chain;
1232 hammer2_key_t key_next;
1235 if (hammer2_debug & 0x0001)
1236 kprintf("inode_create_ins lhc %016jx clindex %d\n",
1240 * (parent) will be the insertion point for inode under iroot
1242 parent = hammer2_inode_chain(xop->head.ip1->pmp->iroot, clindex,
1243 HAMMER2_RESOLVE_ALWAYS);
1244 if (parent == NULL) {
1245 error = HAMMER2_ERROR_EIO;
1249 chain = hammer2_chain_lookup(&parent, &key_next,
1253 error = HAMMER2_ERROR_EEXIST;
1258 * (chain) is the detached inode that is being inserted
1260 chain = hammer2_inode_chain(xop->head.ip1, clindex,
1261 HAMMER2_RESOLVE_ALWAYS);
1262 if (chain == NULL) {
1263 error = HAMMER2_ERROR_EIO;
1269 * This create call will insert the non-NULL chain into parent.
1270 * Most of the auxillary fields are ignored since the chain already
1273 error = hammer2_chain_create(&parent, &chain, NULL, xop->head.ip1->pmp,
1274 HAMMER2_METH_DEFAULT,
1276 HAMMER2_BREF_TYPE_INODE,
1277 HAMMER2_INODE_BYTES,
1278 xop->head.mtid, 0, xop->flags);
1281 error = hammer2_chain_modify(chain, xop->head.mtid, 0, 0);
1283 chain->data->ipdata.meta = xop->meta;
1284 if (xop->head.name1) {
1285 bcopy(xop->head.name1,
1286 chain->data->ipdata.filename,
1287 xop->head.name1_len);
1288 chain->data->ipdata.meta.name_len =
1289 xop->head.name1_len;
1291 chain->data->ipdata.meta.name_key = xop->lhc;
1297 hammer2_chain_unlock(parent);
1298 hammer2_chain_drop(parent);
1300 hammer2_xop_feed(&xop->head, chain, clindex, error);
1302 hammer2_chain_unlock(chain);
1303 hammer2_chain_drop(chain);
1308 * Inode delete helper (backend, threaded)
1310 * Generally used by hammer2_run_sideq()
1313 hammer2_xop_inode_destroy(hammer2_xop_t *arg, void *scratch, int clindex)
1315 hammer2_xop_destroy_t *xop = &arg->xop_destroy;
1317 hammer2_chain_t *parent;
1318 hammer2_chain_t *chain;
1319 hammer2_inode_t *ip;
1323 * We need the precise parent chain to issue the deletion.
1328 chain = hammer2_inode_chain(ip, clindex, HAMMER2_RESOLVE_ALWAYS);
1329 if (chain == NULL) {
1331 error = HAMMER2_ERROR_EIO;
1335 if (ip->flags & HAMMER2_INODE_CREATING) {
1337 * Inode's chains are not linked into the media topology
1338 * because it is a new inode (which is now being destroyed).
1343 * Inode's chains are linked into the media topology
1345 parent = hammer2_chain_getparent(chain, HAMMER2_RESOLVE_ALWAYS);
1346 if (parent == NULL) {
1347 error = HAMMER2_ERROR_EIO;
1351 KKASSERT(chain->parent == parent);
1354 * We have the correct parent, we can issue the deletion.
1356 hammer2_chain_delete(parent, chain, xop->head.mtid, 0);
1359 hammer2_xop_feed(&xop->head, NULL, clindex, error);
1361 hammer2_chain_unlock(parent);
1362 hammer2_chain_drop(parent);
1365 hammer2_chain_unlock(chain);
1366 hammer2_chain_drop(chain);
1371 hammer2_xop_inode_unlinkall(hammer2_xop_t *arg, void *scratch, int clindex)
1373 hammer2_xop_unlinkall_t *xop = &arg->xop_unlinkall;
1374 hammer2_chain_t *parent;
1375 hammer2_chain_t *chain;
1376 hammer2_key_t key_next;
1380 * We need the precise parent chain to issue the deletion.
1382 parent = hammer2_inode_chain(xop->head.ip1, clindex,
1383 HAMMER2_RESOLVE_ALWAYS);
1385 if (parent == NULL) {
1389 chain = hammer2_chain_lookup(&parent, &key_next,
1390 xop->key_beg, xop->key_end,
1391 &error, HAMMER2_LOOKUP_ALWAYS);
1393 hammer2_chain_delete(parent, chain,
1394 xop->head.mtid, HAMMER2_DELETE_PERMANENT);
1395 hammer2_xop_feed(&xop->head, chain, clindex, chain->error);
1396 /* depend on function to unlock the shared lock */
1397 chain = hammer2_chain_next(&parent, chain, &key_next,
1398 key_next, xop->key_end,
1400 HAMMER2_LOOKUP_ALWAYS);
1404 error = HAMMER2_ERROR_ENOENT;
1405 hammer2_xop_feed(&xop->head, NULL, clindex, error);
1407 hammer2_chain_unlock(parent);
1408 hammer2_chain_drop(parent);
1411 hammer2_chain_unlock(chain);
1412 hammer2_chain_drop(chain);
1417 hammer2_xop_inode_connect(hammer2_xop_t *arg, void *scratch, int clindex)
1419 hammer2_xop_connect_t *xop = &arg->xop_connect;
1420 hammer2_inode_data_t *wipdata;
1421 hammer2_chain_t *parent;
1422 hammer2_chain_t *chain;
1424 hammer2_key_t key_dummy;
1428 * Get directory, then issue a lookup to prime the parent chain
1429 * for the create. The lookup is expected to fail.
1431 pmp = xop->head.ip1->pmp;
1432 parent = hammer2_inode_chain(xop->head.ip1, clindex,
1433 HAMMER2_RESOLVE_ALWAYS);
1434 if (parent == NULL) {
1436 error = HAMMER2_ERROR_EIO;
1439 chain = hammer2_chain_lookup(&parent, &key_dummy,
1443 hammer2_chain_unlock(chain);
1444 hammer2_chain_drop(chain);
1446 error = HAMMER2_ERROR_EEXIST;
1453 * Adjust the filename in the inode, set the name key.
1455 * NOTE: Frontend must also adjust ip2->meta on success, we can't
1458 chain = hammer2_inode_chain(xop->head.ip2, clindex,
1459 HAMMER2_RESOLVE_ALWAYS);
1460 error = hammer2_chain_modify(chain, xop->head.mtid, 0, 0);
1464 wipdata = &chain->data->ipdata;
1466 hammer2_inode_modify(xop->head.ip2);
1467 if (xop->head.name1) {
1468 bzero(wipdata->filename, sizeof(wipdata->filename));
1469 bcopy(xop->head.name1, wipdata->filename, xop->head.name1_len);
1470 wipdata->meta.name_len = xop->head.name1_len;
1472 wipdata->meta.name_key = xop->lhc;
1475 * Reconnect the chain to the new parent directory
1477 error = hammer2_chain_create(&parent, &chain, NULL, pmp,
1478 HAMMER2_METH_DEFAULT,
1480 HAMMER2_BREF_TYPE_INODE,
1481 HAMMER2_INODE_BYTES,
1482 xop->head.mtid, 0, 0);
1488 hammer2_xop_feed(&xop->head, NULL, clindex, error);
1490 hammer2_chain_unlock(parent);
1491 hammer2_chain_drop(parent);
1494 hammer2_chain_unlock(chain);
1495 hammer2_chain_drop(chain);
1500 * Synchronize the in-memory inode with the chain. This does not flush
1501 * the chain to disk. Instead, it makes front-end inode changes visible
1502 * in the chain topology, thus visible to the backend. This is done in an
1503 * ad-hoc manner outside of the filesystem vfs_sync, and in a controlled
1504 * manner inside the vfs_sync.
1507 hammer2_xop_inode_chain_sync(hammer2_xop_t *arg, void *scratch, int clindex)
1509 hammer2_xop_fsync_t *xop = &arg->xop_fsync;
1510 hammer2_chain_t *parent;
1511 hammer2_chain_t *chain;
1514 parent = hammer2_inode_chain(xop->head.ip1, clindex,
1515 HAMMER2_RESOLVE_ALWAYS);
1517 if (parent == NULL) {
1518 error = HAMMER2_ERROR_EIO;
1521 if (parent->error) {
1522 error = parent->error;
1528 if ((xop->ipflags & HAMMER2_INODE_RESIZED) == 0) {
1529 /* osize must be ignored */
1530 } else if (xop->meta.size < xop->osize) {
1532 * We must delete any chains beyond the EOF. The chain
1533 * straddling the EOF will be pending in the bioq.
1535 hammer2_key_t lbase;
1536 hammer2_key_t key_next;
1538 lbase = (xop->meta.size + HAMMER2_PBUFMASK64) &
1539 ~HAMMER2_PBUFMASK64;
1540 chain = hammer2_chain_lookup(&parent, &key_next,
1541 lbase, HAMMER2_KEY_MAX,
1543 HAMMER2_LOOKUP_NODATA |
1544 HAMMER2_LOOKUP_NODIRECT);
1547 * Degenerate embedded case, nothing to loop on
1549 switch (chain->bref.type) {
1550 case HAMMER2_BREF_TYPE_DIRENT:
1551 case HAMMER2_BREF_TYPE_INODE:
1554 case HAMMER2_BREF_TYPE_DATA:
1555 hammer2_chain_delete(parent, chain,
1557 HAMMER2_DELETE_PERMANENT);
1560 chain = hammer2_chain_next(&parent, chain, &key_next,
1561 key_next, HAMMER2_KEY_MAX,
1563 HAMMER2_LOOKUP_NODATA |
1564 HAMMER2_LOOKUP_NODIRECT);
1568 * Reset to point at inode for following code, if necessary.
1570 if (parent->bref.type != HAMMER2_BREF_TYPE_INODE) {
1571 hammer2_chain_unlock(parent);
1572 hammer2_chain_drop(parent);
1573 parent = hammer2_inode_chain(xop->head.ip1,
1575 HAMMER2_RESOLVE_ALWAYS);
1576 kprintf("hammer2: TRUNCATE RESET on '%s'\n",
1577 parent->data->ipdata.filename);
1582 * Sync the inode meta-data, potentially clear the blockset area
1583 * of direct data so it can be used for blockrefs.
1586 error = hammer2_chain_modify(parent, xop->head.mtid, 0, 0);
1588 parent->data->ipdata.meta = xop->meta;
1589 if (xop->clear_directdata) {
1590 bzero(&parent->data->ipdata.u.blockset,
1591 sizeof(parent->data->ipdata.u.blockset));
1597 hammer2_chain_unlock(chain);
1598 hammer2_chain_drop(chain);
1601 hammer2_chain_unlock(parent);
1602 hammer2_chain_drop(parent);
1604 hammer2_xop_feed(&xop->head, NULL, clindex, error);