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>
48 #include <sys/mount.h>
53 * Determine if the specified directory is empty.
55 * Returns 0 on success.
57 * Returns HAMMER_ERROR_EAGAIN if caller must re-lookup the entry and
58 * retry. (occurs if we race a ripup on oparent or ochain).
60 * Or returns a permanent HAMMER2_ERROR_* error mask.
62 * The caller must pass in an exclusively locked oparent and ochain. This
63 * function will handle the case where the chain is a directory entry or
64 * the inode itself. The original oparent,ochain will be locked upon return.
66 * This function will unlock the underlying oparent,ochain temporarily when
67 * doing an inode lookup to avoid deadlocks. The caller MUST handle the EAGAIN
68 * result as this means that oparent is no longer the parent of ochain, or
69 * that ochain was destroyed while it was unlocked.
73 checkdirempty(hammer2_chain_t
*oparent
, hammer2_chain_t
*ochain
, int clindex
)
75 hammer2_chain_t
*parent
;
76 hammer2_chain_t
*chain
;
77 hammer2_key_t key_next
;
86 * Find the inode, set it up as a locked 'chain'. ochain can be the
87 * inode itself, or it can be a directory entry.
89 if (ochain
->bref
.type
== HAMMER2_BREF_TYPE_DIRENT
) {
90 inum
= ochain
->bref
.embed
.dirent
.inum
;
91 hammer2_chain_unlock(ochain
);
92 hammer2_chain_unlock(oparent
);
96 error
= hammer2_chain_inode_find(ochain
->pmp
, inum
,
100 hammer2_chain_unlock(parent
);
101 hammer2_chain_drop(parent
);
106 * The directory entry *is* the directory inode
108 chain
= hammer2_chain_lookup_init(ochain
, 0);
112 * Determine if the directory is empty or not by checking its
113 * visible namespace (the area which contains directory entries).
119 chain
= hammer2_chain_lookup(&parent
, &key_next
,
120 HAMMER2_DIRHASH_VISIBLE
,
125 error
= HAMMER2_ERROR_ENOTEMPTY
;
126 hammer2_chain_unlock(chain
);
127 hammer2_chain_drop(chain
);
129 hammer2_chain_lookup_done(parent
);
132 hammer2_chain_unlock(chain
);
133 hammer2_chain_drop(chain
);
134 chain
= NULL
; /* safety */
139 hammer2_chain_lock(oparent
, HAMMER2_RESOLVE_ALWAYS
);
140 hammer2_chain_lock(ochain
, HAMMER2_RESOLVE_ALWAYS
);
141 if ((ochain
->flags
& HAMMER2_CHAIN_DELETED
) ||
142 (oparent
->flags
& HAMMER2_CHAIN_DELETED
) ||
143 ochain
->parent
!= oparent
) {
144 kprintf("hammer2: debug: CHECKDIR inum %jd RETRY\n",
146 error
= HAMMER2_ERROR_EAGAIN
;
153 * Backend for hammer2_vfs_root()
155 * This is called when a newly mounted PFS has not yet synchronized
156 * to the inode_tid and modify_tid.
159 hammer2_xop_ipcluster(hammer2_xop_t
*arg
, void *scratch
, int clindex
)
161 hammer2_xop_ipcluster_t
*xop
= &arg
->xop_ipcluster
;
162 hammer2_chain_t
*chain
;
165 chain
= hammer2_inode_chain(xop
->head
.ip1
, clindex
,
166 HAMMER2_RESOLVE_ALWAYS
|
167 HAMMER2_RESOLVE_SHARED
);
169 error
= chain
->error
;
171 error
= HAMMER2_ERROR_EIO
;
173 hammer2_xop_feed(&xop
->head
, chain
, clindex
, error
);
175 hammer2_chain_unlock(chain
);
176 hammer2_chain_drop(chain
);
181 * Backend for hammer2_vop_readdir()
184 hammer2_xop_readdir(hammer2_xop_t
*arg
, void *scratch
, int clindex
)
186 hammer2_xop_readdir_t
*xop
= &arg
->xop_readdir
;
187 hammer2_chain_t
*parent
;
188 hammer2_chain_t
*chain
;
189 hammer2_key_t key_next
;
194 if (hammer2_debug
& 0x0020)
195 kprintf("xop_readdir: %p lkey=%016jx\n", xop
, lkey
);
198 * The inode's chain is the iterator. If we cannot acquire it our
199 * contribution ends here.
201 parent
= hammer2_inode_chain(xop
->head
.ip1
, clindex
,
202 HAMMER2_RESOLVE_ALWAYS
|
203 HAMMER2_RESOLVE_SHARED
);
204 if (parent
== NULL
) {
205 kprintf("xop_readdir: NULL parent\n");
210 * Directory scan [re]start and loop, the feed inherits the chain's
211 * lock so do not unlock it on the iteration.
213 chain
= hammer2_chain_lookup(&parent
, &key_next
, lkey
, lkey
,
214 &error
, HAMMER2_LOOKUP_SHARED
);
216 chain
= hammer2_chain_lookup(&parent
, &key_next
,
217 lkey
, HAMMER2_KEY_MAX
,
218 &error
, HAMMER2_LOOKUP_SHARED
);
221 error
= hammer2_xop_feed(&xop
->head
, chain
, clindex
, 0);
224 chain
= hammer2_chain_next(&parent
, chain
, &key_next
,
225 key_next
, HAMMER2_KEY_MAX
,
226 &error
, HAMMER2_LOOKUP_SHARED
);
230 hammer2_chain_unlock(chain
);
231 hammer2_chain_drop(chain
);
233 hammer2_chain_unlock(parent
);
234 hammer2_chain_drop(parent
);
236 hammer2_xop_feed(&xop
->head
, NULL
, clindex
, error
);
240 * Backend for hammer2_vop_nresolve()
243 hammer2_xop_nresolve(hammer2_xop_t
*arg
, void *scratch
, int clindex
)
245 hammer2_xop_nresolve_t
*xop
= &arg
->xop_nresolve
;
246 hammer2_chain_t
*parent
;
247 hammer2_chain_t
*chain
;
250 hammer2_key_t key_next
;
254 parent
= hammer2_inode_chain(xop
->head
.ip1
, clindex
,
255 HAMMER2_RESOLVE_ALWAYS
|
256 HAMMER2_RESOLVE_SHARED
);
257 if (parent
== NULL
) {
258 kprintf("xop_nresolve: NULL parent\n");
260 error
= HAMMER2_ERROR_EIO
;
263 name
= xop
->head
.name1
;
264 name_len
= xop
->head
.name1_len
;
267 * Lookup the directory entry
269 lhc
= hammer2_dirhash(name
, name_len
);
270 chain
= hammer2_chain_lookup(&parent
, &key_next
,
271 lhc
, lhc
+ HAMMER2_DIRHASH_LOMASK
,
273 HAMMER2_LOOKUP_ALWAYS
|
274 HAMMER2_LOOKUP_SHARED
);
276 if (hammer2_chain_dirent_test(chain
, name
, name_len
))
278 chain
= hammer2_chain_next(&parent
, chain
, &key_next
,
280 lhc
+ HAMMER2_DIRHASH_LOMASK
,
282 HAMMER2_LOOKUP_ALWAYS
|
283 HAMMER2_LOOKUP_SHARED
);
287 * Locate the target inode for a directory entry
289 if (chain
&& chain
->error
== 0) {
290 if (chain
->bref
.type
== HAMMER2_BREF_TYPE_DIRENT
) {
291 lhc
= chain
->bref
.embed
.dirent
.inum
;
292 error
= hammer2_chain_inode_find(chain
->pmp
,
295 HAMMER2_LOOKUP_SHARED
,
299 } else if (chain
&& error
== 0) {
300 error
= chain
->error
;
303 error
= hammer2_xop_feed(&xop
->head
, chain
, clindex
, error
);
305 hammer2_chain_unlock(chain
);
306 hammer2_chain_drop(chain
);
309 hammer2_chain_unlock(parent
);
310 hammer2_chain_drop(parent
);
315 * Backend for hammer2_vop_nremove(), hammer2_vop_nrmdir(), and
316 * backend for pfs_delete.
318 * This function locates and removes a directory entry, and will lookup
319 * and return the underlying inode. For directory entries the underlying
320 * inode is not removed. If the directory entry is the actual inode itself,
321 * it may be conditonally removed and returned.
323 * WARNING! Any target inode's nlinks may not be synchronized to the
324 * in-memory inode. The frontend's hammer2_inode_unlink_finisher()
325 * is responsible for the final disposition of the actual inode.
328 hammer2_xop_unlink(hammer2_xop_t
*arg
, void *scratch
, int clindex
)
330 hammer2_xop_unlink_t
*xop
= &arg
->xop_unlink
;
331 hammer2_chain_t
*parent
;
332 hammer2_chain_t
*chain
;
335 hammer2_key_t key_next
;
341 * Requires exclusive lock
343 parent
= hammer2_inode_chain(xop
->head
.ip1
, clindex
,
344 HAMMER2_RESOLVE_ALWAYS
);
346 if (parent
== NULL
) {
347 kprintf("xop_unlink: NULL parent\n");
348 error
= HAMMER2_ERROR_EIO
;
351 name
= xop
->head
.name1
;
352 name_len
= xop
->head
.name1_len
;
355 * Lookup the directory entry
357 lhc
= hammer2_dirhash(name
, name_len
);
358 chain
= hammer2_chain_lookup(&parent
, &key_next
,
359 lhc
, lhc
+ HAMMER2_DIRHASH_LOMASK
,
360 &error
, HAMMER2_LOOKUP_ALWAYS
);
362 if (hammer2_chain_dirent_test(chain
, name
, name_len
))
364 chain
= hammer2_chain_next(&parent
, chain
, &key_next
,
366 lhc
+ HAMMER2_DIRHASH_LOMASK
,
367 &error
, HAMMER2_LOOKUP_ALWAYS
);
371 * The directory entry will either be a BREF_TYPE_DIRENT or a
372 * BREF_TYPE_INODE. We always permanently delete DIRENTs, but
373 * must go by xop->dopermanent for BREF_TYPE_INODE.
375 * Note that the target chain's nlinks may not be synchronized with
376 * the in-memory hammer2_inode_t structure, so we don't try to do
377 * anything fancy here. The frontend deals with nlinks
380 if (chain
&& chain
->error
== 0) {
381 int dopermanent
= xop
->dopermanent
& H2DOPERM_PERMANENT
;
382 int doforce
= xop
->dopermanent
& H2DOPERM_FORCE
;
386 * If the directory entry is the actual inode then use its
387 * type for the directory typing tests, otherwise if it is
388 * a directory entry, pull the type field from the entry.
390 * Directory entries are always permanently deleted
391 * (because they aren't the actual inode).
393 if (chain
->bref
.type
== HAMMER2_BREF_TYPE_DIRENT
) {
394 type
= chain
->bref
.embed
.dirent
.type
;
395 dopermanent
|= HAMMER2_DELETE_PERMANENT
;
397 type
= chain
->data
->ipdata
.meta
.type
;
401 * Check directory typing and delete the entry. Note that
402 * nlinks adjustments are made on the real inode by the
403 * frontend, not here.
405 * Unfortunately, checkdirempty() may have to unlock (parent).
406 * If it no longer matches chain->parent after re-locking,
407 * EAGAIN is returned.
409 if (type
== HAMMER2_OBJTYPE_DIRECTORY
&& doforce
) {
411 * If doforce then execute the operation even if
412 * the directory is not empty or errored. We
413 * ignore chain->error here, allowing an errored
414 * chain (aka directory entry) to still be deleted.
416 error
= hammer2_chain_delete(parent
, chain
,
417 xop
->head
.mtid
, dopermanent
);
418 } else if (type
== HAMMER2_OBJTYPE_DIRECTORY
&&
420 error
= HAMMER2_ERROR_EISDIR
;
421 } else if (type
== HAMMER2_OBJTYPE_DIRECTORY
&&
422 (error
= checkdirempty(parent
, chain
, clindex
)) != 0) {
424 * error may be EAGAIN or ENOTEMPTY
426 if (error
== HAMMER2_ERROR_EAGAIN
) {
427 hammer2_chain_unlock(chain
);
428 hammer2_chain_drop(chain
);
429 hammer2_chain_unlock(parent
);
430 hammer2_chain_drop(parent
);
433 } else if (type
!= HAMMER2_OBJTYPE_DIRECTORY
&&
435 error
= HAMMER2_ERROR_ENOTDIR
;
438 * Delete the directory entry. chain might also
439 * be a directly-embedded inode.
441 * Allow the deletion to proceed even if the chain
442 * is errored. Give priority to error-on-delete over
445 error
= hammer2_chain_delete(parent
, chain
,
449 error
= chain
->error
;
452 if (chain
&& error
== 0)
453 error
= chain
->error
;
457 * If chain is a directory entry we must resolve it. We do not try
458 * to manipulate the contents as it might not be synchronized with
459 * the frontend hammer2_inode_t, nor do we try to lookup the
460 * frontend hammer2_inode_t here (we are the backend!).
462 if (chain
&& chain
->bref
.type
== HAMMER2_BREF_TYPE_DIRENT
&&
463 (xop
->dopermanent
& H2DOPERM_IGNINO
) == 0) {
466 lhc
= chain
->bref
.embed
.dirent
.inum
;
468 error2
= hammer2_chain_inode_find(chain
->pmp
, lhc
,
472 kprintf("xop_unlink: %016jx %p failed\n",
474 error2
= 0; /* silently ignore */
481 * Return the inode target for further action. Typically used by
482 * hammer2_inode_unlink_finisher().
485 hammer2_xop_feed(&xop
->head
, chain
, clindex
, error
);
487 hammer2_chain_unlock(chain
);
488 hammer2_chain_drop(chain
);
492 hammer2_chain_unlock(parent
);
493 hammer2_chain_drop(parent
);
499 * Backend for hammer2_vop_nrename()
501 * This handles the backend rename operation. Typically this renames
502 * directory entries but can also be used to rename embedded inodes.
504 * NOTE! The frontend is responsible for updating the inode meta-data in
505 * the file being renamed and for decrementing the target-replaced
506 * inode's nlinks, if present.
509 hammer2_xop_nrename(hammer2_xop_t
*arg
, void *scratch
, int clindex
)
511 hammer2_xop_nrename_t
*xop
= &arg
->xop_nrename
;
513 hammer2_chain_t
*parent
;
514 hammer2_chain_t
*chain
;
515 hammer2_chain_t
*tmp
;
517 hammer2_key_t key_next
;
521 * If ip4 is non-NULL we must check to see if the entry being
522 * overwritten is a non-empty directory.
528 chain
= hammer2_inode_chain(ip
, clindex
,
529 HAMMER2_RESOLVE_ALWAYS
);
531 error
= HAMMER2_ERROR_EIO
;
535 type
= chain
->data
->ipdata
.meta
.type
;
536 if (type
== HAMMER2_OBJTYPE_DIRECTORY
&&
537 (error
= checkdirempty(NULL
, chain
, clindex
)) != 0)
539 KKASSERT(error
!= HAMMER2_ERROR_EAGAIN
);
543 hammer2_chain_unlock(chain
);
544 hammer2_chain_drop(chain
);
548 * We need the precise parent chain to issue the deletion.
550 * If this is a directory entry we must locate the underlying
551 * inode. If it is an embedded inode we can act directly on it.
558 if (xop
->ip_key
& HAMMER2_DIRHASH_VISIBLE
) {
560 * Find ip's direct parent chain.
562 chain
= hammer2_inode_chain(ip
, clindex
,
563 HAMMER2_RESOLVE_ALWAYS
);
565 error
= HAMMER2_ERROR_EIO
;
569 if (ip
->flags
& HAMMER2_INODE_CREATING
) {
572 parent
= hammer2_chain_getparent(chain
,
573 HAMMER2_RESOLVE_ALWAYS
);
574 if (parent
== NULL
) {
575 error
= HAMMER2_ERROR_EIO
;
581 * The directory entry for the head.ip1 inode
582 * is in fdip, do a namespace search.
588 parent
= hammer2_inode_chain(xop
->head
.ip1
, clindex
,
589 HAMMER2_RESOLVE_ALWAYS
);
590 if (parent
== NULL
) {
591 kprintf("xop_nrename: NULL parent\n");
592 error
= HAMMER2_ERROR_EIO
;
595 name
= xop
->head
.name1
;
596 name_len
= xop
->head
.name1_len
;
599 * Lookup the directory entry
601 lhc
= hammer2_dirhash(name
, name_len
);
602 chain
= hammer2_chain_lookup(&parent
, &key_next
,
603 lhc
, lhc
+ HAMMER2_DIRHASH_LOMASK
,
604 &error
, HAMMER2_LOOKUP_ALWAYS
);
606 if (hammer2_chain_dirent_test(chain
, name
, name_len
))
608 chain
= hammer2_chain_next(&parent
, chain
, &key_next
,
610 lhc
+ HAMMER2_DIRHASH_LOMASK
,
612 HAMMER2_LOOKUP_ALWAYS
);
617 /* XXX shouldn't happen, but does under fsstress */
618 kprintf("xop_nrename: \"%s\" -> \"%s\" ENOENT\n",
622 error
= HAMMER2_ERROR_ENOENT
;
627 error
= chain
->error
;
632 * Delete it, then create it in the new namespace.
634 * An error can occur if the chain being deleted requires
635 * modification and the media is full.
637 error
= hammer2_chain_delete(parent
, chain
, xop
->head
.mtid
, 0);
639 hammer2_chain_unlock(parent
);
640 hammer2_chain_drop(parent
);
641 parent
= NULL
; /* safety */
643 kprintf("hammer2_xop_nrename() (debugging): parent was NULL\n");
650 * Adjust fields in the deleted chain appropriate for the rename
653 * NOTE! For embedded inodes, the frontend will officially replicate
654 * the field adjustments, but we also do it here to maintain
655 * consistency in case of a crash.
657 if (chain
->bref
.key
!= xop
->lhc
||
658 xop
->head
.name1_len
!= xop
->head
.name2_len
||
659 bcmp(xop
->head
.name1
, xop
->head
.name2
, xop
->head
.name1_len
) != 0) {
660 if (chain
->bref
.type
== HAMMER2_BREF_TYPE_INODE
) {
661 hammer2_inode_data_t
*wipdata
;
663 error
= hammer2_chain_modify(chain
, xop
->head
.mtid
,
666 wipdata
= &chain
->data
->ipdata
;
668 bzero(wipdata
->filename
,
669 sizeof(wipdata
->filename
));
670 bcopy(xop
->head
.name2
,
672 xop
->head
.name2_len
);
673 wipdata
->meta
.name_key
= xop
->lhc
;
674 wipdata
->meta
.name_len
= xop
->head
.name2_len
;
677 if (chain
->bref
.type
== HAMMER2_BREF_TYPE_DIRENT
) {
678 if (xop
->head
.name2_len
<=
679 sizeof(chain
->bref
.check
.buf
)) {
681 * Remove any related data buffer, we can
682 * embed the filename in the bref itself.
684 error
= hammer2_chain_resize(
685 chain
, xop
->head
.mtid
, 0, 0, 0);
687 error
= hammer2_chain_modify(
688 chain
, xop
->head
.mtid
,
692 bzero(chain
->bref
.check
.buf
,
693 sizeof(chain
->bref
.check
.buf
));
694 bcopy(xop
->head
.name2
,
695 chain
->bref
.check
.buf
,
696 xop
->head
.name2_len
);
700 * Associate a data buffer with the bref.
701 * Zero it for consistency. Note that the
702 * data buffer is not 64KB so use chain->bytes
703 * instead of sizeof().
705 error
= hammer2_chain_resize(
706 chain
, xop
->head
.mtid
, 0,
707 hammer2_getradix(HAMMER2_ALLOC_MIN
), 0);
709 error
= hammer2_chain_modify(
710 chain
, xop
->head
.mtid
,
714 bzero(chain
->data
->buf
, chain
->bytes
);
715 bcopy(xop
->head
.name2
,
717 xop
->head
.name2_len
);
721 chain
->bref
.embed
.dirent
.namlen
=
728 * The frontend will replicate this operation and is the real final
729 * authority, but adjust the inode's iparent field too if the inode
730 * is embedded in the directory.
732 if (chain
->bref
.type
== HAMMER2_BREF_TYPE_INODE
&&
733 chain
->data
->ipdata
.meta
.iparent
!= xop
->head
.ip3
->meta
.inum
) {
734 hammer2_inode_data_t
*wipdata
;
736 error
= hammer2_chain_modify(chain
, xop
->head
.mtid
, 0, 0);
738 wipdata
= &chain
->data
->ipdata
;
739 wipdata
->meta
.iparent
= xop
->head
.ip3
->meta
.inum
;
744 * Destroy any matching target(s) before creating the new entry.
745 * This will result in some ping-ponging of the directory key
746 * iterator but that is ok.
748 parent
= hammer2_inode_chain(xop
->head
.ip3
, clindex
,
749 HAMMER2_RESOLVE_ALWAYS
);
750 if (parent
== NULL
) {
751 error
= HAMMER2_ERROR_EIO
;
756 * Delete all matching directory entries. That is, get rid of
757 * multiple duplicates if present, as a self-healing mechanism.
760 tmp
= hammer2_chain_lookup(&parent
, &key_next
,
761 xop
->lhc
& ~HAMMER2_DIRHASH_LOMASK
,
762 xop
->lhc
| HAMMER2_DIRHASH_LOMASK
,
764 HAMMER2_LOOKUP_ALWAYS
);
767 if (hammer2_chain_dirent_test(tmp
, xop
->head
.name2
,
768 xop
->head
.name2_len
)) {
769 e2
= hammer2_chain_delete(parent
, tmp
,
771 if (error
== 0 && e2
)
774 tmp
= hammer2_chain_next(&parent
, tmp
, &key_next
,
777 HAMMER2_DIRHASH_LOMASK
,
779 HAMMER2_LOOKUP_ALWAYS
);
784 * A relookup is required before the create to properly
785 * position the parent chain.
787 tmp
= hammer2_chain_lookup(&parent
, &key_next
,
790 KKASSERT(tmp
== NULL
);
791 error
= hammer2_chain_create(&parent
, &chain
, NULL
, pmp
,
792 HAMMER2_METH_DEFAULT
,
794 HAMMER2_BREF_TYPE_INODE
,
796 xop
->head
.mtid
, 0, 0);
799 hammer2_xop_feed(&xop
->head
, NULL
, clindex
, error
);
801 hammer2_chain_unlock(parent
);
802 hammer2_chain_drop(parent
);
805 hammer2_chain_unlock(chain
);
806 hammer2_chain_drop(chain
);
811 * Directory collision resolver scan helper (backend, threaded).
813 * Used by the inode create code to locate an unused lhc.
816 hammer2_xop_scanlhc(hammer2_xop_t
*arg
, void *scratch
, int clindex
)
818 hammer2_xop_scanlhc_t
*xop
= &arg
->xop_scanlhc
;
819 hammer2_chain_t
*parent
;
820 hammer2_chain_t
*chain
;
821 hammer2_key_t key_next
;
824 parent
= hammer2_inode_chain(xop
->head
.ip1
, clindex
,
825 HAMMER2_RESOLVE_ALWAYS
|
826 HAMMER2_RESOLVE_SHARED
);
827 if (parent
== NULL
) {
828 kprintf("xop_scanlhc: NULL parent\n");
830 error
= HAMMER2_ERROR_EIO
;
835 * Lookup all possibly conflicting directory entries, the feed
836 * inherits the chain's lock so do not unlock it on the iteration.
838 chain
= hammer2_chain_lookup(&parent
, &key_next
,
840 xop
->lhc
+ HAMMER2_DIRHASH_LOMASK
,
842 HAMMER2_LOOKUP_ALWAYS
|
843 HAMMER2_LOOKUP_SHARED
);
845 error
= hammer2_xop_feed(&xop
->head
, chain
, clindex
, 0);
847 hammer2_chain_unlock(chain
);
848 hammer2_chain_drop(chain
);
849 chain
= NULL
; /* safety */
852 chain
= hammer2_chain_next(&parent
, chain
, &key_next
,
854 xop
->lhc
+ HAMMER2_DIRHASH_LOMASK
,
856 HAMMER2_LOOKUP_ALWAYS
|
857 HAMMER2_LOOKUP_SHARED
);
860 hammer2_xop_feed(&xop
->head
, NULL
, clindex
, error
);
862 hammer2_chain_unlock(parent
);
863 hammer2_chain_drop(parent
);
868 * Generic lookup of a specific key.
871 hammer2_xop_lookup(hammer2_xop_t
*arg
, void *scratch
, int clindex
)
873 hammer2_xop_lookup_t
*xop
= &arg
->xop_lookup
;
874 hammer2_chain_t
*parent
;
875 hammer2_chain_t
*chain
;
876 hammer2_key_t key_next
;
879 parent
= hammer2_inode_chain(xop
->head
.ip1
, clindex
,
880 HAMMER2_RESOLVE_ALWAYS
|
881 HAMMER2_RESOLVE_SHARED
);
883 if (parent
== NULL
) {
884 error
= HAMMER2_ERROR_EIO
;
889 * Lookup all possibly conflicting directory entries, the feed
890 * inherits the chain's lock so do not unlock it on the iteration.
892 chain
= hammer2_chain_lookup(&parent
, &key_next
,
895 HAMMER2_LOOKUP_ALWAYS
|
896 HAMMER2_LOOKUP_SHARED
);
899 error
= chain
->error
;
901 error
= HAMMER2_ERROR_ENOENT
;
903 hammer2_xop_feed(&xop
->head
, chain
, clindex
, error
);
907 hammer2_chain_unlock(chain
);
908 hammer2_chain_drop(chain
);
911 hammer2_chain_unlock(parent
);
912 hammer2_chain_drop(parent
);
917 hammer2_xop_delete(hammer2_xop_t
*arg
, void *scratch
, int clindex
)
919 hammer2_xop_lookup_t
*xop
= &arg
->xop_lookup
;
920 hammer2_chain_t
*parent
;
921 hammer2_chain_t
*chain
;
922 hammer2_key_t key_next
;
925 parent
= hammer2_inode_chain(xop
->head
.ip1
, clindex
,
926 HAMMER2_RESOLVE_ALWAYS
);
928 if (parent
== NULL
) {
929 error
= HAMMER2_ERROR_EIO
;
934 * Lookup all possibly conflicting directory entries, the feed
935 * inherits the chain's lock so do not unlock it on the iteration.
937 chain
= hammer2_chain_lookup(&parent
, &key_next
,
940 HAMMER2_LOOKUP_NODATA
);
943 error
= chain
->error
;
945 error
= HAMMER2_ERROR_ENOENT
;
948 error
= hammer2_chain_delete(parent
, chain
, xop
->head
.mtid
,
949 HAMMER2_DELETE_PERMANENT
);
951 hammer2_xop_feed(&xop
->head
, NULL
, clindex
, error
);
955 hammer2_chain_unlock(chain
);
956 hammer2_chain_drop(chain
);
959 hammer2_chain_unlock(parent
);
960 hammer2_chain_drop(parent
);
967 * WARNING! Fed chains must be locked shared so ownership can be transfered
968 * and to prevent frontend/backend stalls that would occur with an
969 * exclusive lock. The shared lock also allows chain->data to be
973 hammer2_xop_scanall(hammer2_xop_t
*arg
, void *scratch
, int clindex
)
975 hammer2_xop_scanall_t
*xop
= &arg
->xop_scanall
;
976 hammer2_chain_t
*parent
;
977 hammer2_chain_t
*chain
;
978 hammer2_key_t key_next
;
982 * Assert required flags.
984 KKASSERT(xop
->resolve_flags
& HAMMER2_RESOLVE_SHARED
);
985 KKASSERT(xop
->lookup_flags
& HAMMER2_LOOKUP_SHARED
);
988 * The inode's chain is the iterator. If we cannot acquire it our
989 * contribution ends here.
991 parent
= hammer2_inode_chain(xop
->head
.ip1
, clindex
,
993 if (parent
== NULL
) {
994 kprintf("xop_scanall: NULL parent\n");
999 * Generic scan of exact records. Note that indirect blocks are
1000 * automatically recursed and will not be returned.
1002 chain
= hammer2_chain_lookup(&parent
, &key_next
,
1003 xop
->key_beg
, xop
->key_end
,
1004 &error
, xop
->lookup_flags
);
1006 error
= hammer2_xop_feed(&xop
->head
, chain
, clindex
, 0);
1009 chain
= hammer2_chain_next(&parent
, chain
, &key_next
,
1010 key_next
, xop
->key_end
,
1011 &error
, xop
->lookup_flags
);
1015 hammer2_chain_unlock(chain
);
1016 hammer2_chain_drop(chain
);
1018 hammer2_chain_unlock(parent
);
1019 hammer2_chain_drop(parent
);
1021 hammer2_xop_feed(&xop
->head
, NULL
, clindex
, error
);
1024 /************************************************************************
1025 * INODE LAYER XOPS *
1026 ************************************************************************
1030 * Helper to create a directory entry.
1033 hammer2_xop_inode_mkdirent(hammer2_xop_t
*arg
, void *scratch
, int clindex
)
1035 hammer2_xop_mkdirent_t
*xop
= &arg
->xop_mkdirent
;
1036 hammer2_chain_t
*parent
;
1037 hammer2_chain_t
*chain
;
1038 hammer2_key_t key_next
;
1042 if (hammer2_debug
& 0x0001)
1043 kprintf("xop_inode_mkdirent: lhc %016jx clindex %d\n",
1046 parent
= hammer2_inode_chain(xop
->head
.ip1
, clindex
,
1047 HAMMER2_RESOLVE_ALWAYS
);
1048 if (parent
== NULL
) {
1049 error
= HAMMER2_ERROR_EIO
;
1053 chain
= hammer2_chain_lookup(&parent
, &key_next
,
1057 error
= HAMMER2_ERROR_EEXIST
;
1062 * We may be able to embed the directory entry directly in the
1065 if (xop
->dirent
.namlen
<= sizeof(chain
->bref
.check
.buf
))
1068 data_len
= HAMMER2_ALLOC_MIN
;
1070 error
= hammer2_chain_create(&parent
, &chain
, NULL
, xop
->head
.ip1
->pmp
,
1071 HAMMER2_METH_DEFAULT
,
1073 HAMMER2_BREF_TYPE_DIRENT
,
1075 xop
->head
.mtid
, 0, 0);
1078 * WARNING: chain->data->buf is sized to chain->bytes,
1079 * do not use sizeof(chain->data->buf), which
1080 * will be much larger.
1082 error
= hammer2_chain_modify(chain
, xop
->head
.mtid
, 0, 0);
1084 chain
->bref
.embed
.dirent
= xop
->dirent
;
1085 if (xop
->dirent
.namlen
<= sizeof(chain
->bref
.check
.buf
))
1086 bcopy(xop
->head
.name1
, chain
->bref
.check
.buf
,
1087 xop
->dirent
.namlen
);
1089 bcopy(xop
->head
.name1
, chain
->data
->buf
,
1090 xop
->dirent
.namlen
);
1095 hammer2_chain_unlock(parent
);
1096 hammer2_chain_drop(parent
);
1098 hammer2_xop_feed(&xop
->head
, chain
, clindex
, error
);
1100 hammer2_chain_unlock(chain
);
1101 hammer2_chain_drop(chain
);
1106 * Inode create helper (threaded, backend)
1108 * Used by ncreate, nmknod, nsymlink, nmkdir.
1109 * Used by nlink and rename to create HARDLINK pointers.
1111 * Frontend holds the parent directory ip locked exclusively. We
1112 * create the inode and feed the exclusively locked chain to the
1116 hammer2_xop_inode_create(hammer2_xop_t
*arg
, void *scratch
, int clindex
)
1118 hammer2_xop_create_t
*xop
= &arg
->xop_create
;
1119 hammer2_chain_t
*parent
;
1120 hammer2_chain_t
*chain
;
1121 hammer2_key_t key_next
;
1124 if (hammer2_debug
& 0x0001)
1125 kprintf("xop_inode_create: lhc %016jx clindex %d\n",
1128 parent
= hammer2_inode_chain(xop
->head
.ip1
, clindex
,
1129 HAMMER2_RESOLVE_ALWAYS
);
1130 if (parent
== NULL
) {
1131 error
= HAMMER2_ERROR_EIO
;
1135 chain
= hammer2_chain_lookup(&parent
, &key_next
,
1139 error
= HAMMER2_ERROR_EEXIST
;
1143 error
= hammer2_chain_create(&parent
, &chain
, NULL
, xop
->head
.ip1
->pmp
,
1144 HAMMER2_METH_DEFAULT
,
1146 HAMMER2_BREF_TYPE_INODE
,
1147 HAMMER2_INODE_BYTES
,
1148 xop
->head
.mtid
, 0, xop
->flags
);
1150 error
= hammer2_chain_modify(chain
, xop
->head
.mtid
, 0, 0);
1152 chain
->data
->ipdata
.meta
= xop
->meta
;
1153 if (xop
->head
.name1
) {
1154 bcopy(xop
->head
.name1
,
1155 chain
->data
->ipdata
.filename
,
1156 xop
->head
.name1_len
);
1157 chain
->data
->ipdata
.meta
.name_len
=
1158 xop
->head
.name1_len
;
1160 chain
->data
->ipdata
.meta
.name_key
= xop
->lhc
;
1165 hammer2_chain_unlock(parent
);
1166 hammer2_chain_drop(parent
);
1168 hammer2_xop_feed(&xop
->head
, chain
, clindex
, error
);
1170 hammer2_chain_unlock(chain
);
1171 hammer2_chain_drop(chain
);
1176 * Create inode as above but leave it detached from the hierarchy.
1179 hammer2_xop_inode_create_det(hammer2_xop_t
*arg
, void *scratch
, int clindex
)
1181 hammer2_xop_create_t
*xop
= &arg
->xop_create
;
1182 hammer2_chain_t
*parent
;
1183 hammer2_chain_t
*chain
;
1184 hammer2_chain_t
*null_parent
;
1185 hammer2_key_t key_next
;
1186 hammer2_inode_t
*pip
;
1187 hammer2_inode_t
*iroot
;
1190 if (hammer2_debug
& 0x0001)
1191 kprintf("xop_inode_create_det: lhc %016jx clindex %d\n",
1194 pip
= xop
->head
.ip1
;
1195 iroot
= pip
->pmp
->iroot
;
1197 parent
= hammer2_inode_chain(iroot
, clindex
, HAMMER2_RESOLVE_ALWAYS
);
1199 if (parent
== NULL
) {
1200 error
= HAMMER2_ERROR_EIO
;
1204 chain
= hammer2_chain_lookup(&parent
, &key_next
,
1208 error
= HAMMER2_ERROR_EEXIST
;
1213 * Create as a detached chain with no parent. We must specify
1217 error
= hammer2_chain_create(&null_parent
, &chain
,
1218 parent
->hmp
, pip
->pmp
,
1219 HAMMER2_ENC_COMP(pip
->meta
.comp_algo
) +
1220 HAMMER2_ENC_CHECK(pip
->meta
.check_algo
),
1222 HAMMER2_BREF_TYPE_INODE
,
1223 HAMMER2_INODE_BYTES
,
1224 xop
->head
.mtid
, 0, xop
->flags
);
1226 error
= hammer2_chain_modify(chain
, xop
->head
.mtid
, 0, 0);
1228 chain
->data
->ipdata
.meta
= xop
->meta
;
1229 if (xop
->head
.name1
) {
1230 bcopy(xop
->head
.name1
,
1231 chain
->data
->ipdata
.filename
,
1232 xop
->head
.name1_len
);
1233 chain
->data
->ipdata
.meta
.name_len
=
1234 xop
->head
.name1_len
;
1236 chain
->data
->ipdata
.meta
.name_key
= xop
->lhc
;
1241 hammer2_chain_unlock(parent
);
1242 hammer2_chain_drop(parent
);
1244 hammer2_xop_feed(&xop
->head
, chain
, clindex
, error
);
1246 hammer2_chain_unlock(chain
);
1247 hammer2_chain_drop(chain
);
1252 * Take a detached chain and insert it into the topology
1255 hammer2_xop_inode_create_ins(hammer2_xop_t
*arg
, void *scratch
, int clindex
)
1257 hammer2_xop_create_t
*xop
= &arg
->xop_create
;
1258 hammer2_chain_t
*parent
;
1259 hammer2_chain_t
*chain
;
1260 hammer2_key_t key_next
;
1263 if (hammer2_debug
& 0x0001)
1264 kprintf("xop_inode_create_ins: lhc %016jx clindex %d\n",
1268 * (parent) will be the insertion point for inode under iroot
1270 parent
= hammer2_inode_chain(xop
->head
.ip1
->pmp
->iroot
, clindex
,
1271 HAMMER2_RESOLVE_ALWAYS
);
1272 if (parent
== NULL
) {
1273 error
= HAMMER2_ERROR_EIO
;
1277 chain
= hammer2_chain_lookup(&parent
, &key_next
,
1281 error
= HAMMER2_ERROR_EEXIST
;
1286 * (chain) is the detached inode that is being inserted
1288 chain
= hammer2_inode_chain(xop
->head
.ip1
, clindex
,
1289 HAMMER2_RESOLVE_ALWAYS
);
1290 if (chain
== NULL
) {
1291 error
= HAMMER2_ERROR_EIO
;
1297 * This create call will insert the non-NULL chain into parent.
1298 * Most of the auxillary fields are ignored since the chain already
1301 error
= hammer2_chain_create(&parent
, &chain
, NULL
, xop
->head
.ip1
->pmp
,
1302 HAMMER2_METH_DEFAULT
,
1304 HAMMER2_BREF_TYPE_INODE
,
1305 HAMMER2_INODE_BYTES
,
1306 xop
->head
.mtid
, 0, xop
->flags
);
1309 error
= hammer2_chain_modify(chain
, xop
->head
.mtid
, 0, 0);
1311 chain
->data
->ipdata
.meta
= xop
->meta
;
1312 if (xop
->head
.name1
) {
1313 bcopy(xop
->head
.name1
,
1314 chain
->data
->ipdata
.filename
,
1315 xop
->head
.name1_len
);
1316 chain
->data
->ipdata
.meta
.name_len
=
1317 xop
->head
.name1_len
;
1319 chain
->data
->ipdata
.meta
.name_key
= xop
->lhc
;
1325 hammer2_chain_unlock(parent
);
1326 hammer2_chain_drop(parent
);
1328 hammer2_xop_feed(&xop
->head
, chain
, clindex
, error
);
1330 hammer2_chain_unlock(chain
);
1331 hammer2_chain_drop(chain
);
1336 * Inode delete helper (backend, threaded)
1338 * Generally used by hammer2_run_sideq()
1341 hammer2_xop_inode_destroy(hammer2_xop_t
*arg
, void *scratch
, int clindex
)
1343 hammer2_xop_destroy_t
*xop
= &arg
->xop_destroy
;
1344 hammer2_chain_t
*parent
;
1345 hammer2_chain_t
*chain
;
1346 hammer2_inode_t
*ip
;
1350 * We need the precise parent chain to issue the deletion.
1354 chain
= hammer2_inode_chain(ip
, clindex
, HAMMER2_RESOLVE_ALWAYS
);
1355 if (chain
== NULL
) {
1357 error
= HAMMER2_ERROR_EIO
;
1361 if (ip
->flags
& HAMMER2_INODE_CREATING
) {
1363 * Inode's chains are not linked into the media topology
1364 * because it is a new inode (which is now being destroyed).
1369 * Inode's chains are linked into the media topology
1371 parent
= hammer2_chain_getparent(chain
, HAMMER2_RESOLVE_ALWAYS
);
1372 if (parent
== NULL
) {
1373 error
= HAMMER2_ERROR_EIO
;
1377 KKASSERT(chain
->parent
== parent
);
1380 * We have the correct parent, we can issue the deletion.
1382 hammer2_chain_delete(parent
, chain
, xop
->head
.mtid
, 0);
1385 hammer2_xop_feed(&xop
->head
, NULL
, clindex
, error
);
1387 hammer2_chain_unlock(parent
);
1388 hammer2_chain_drop(parent
);
1391 hammer2_chain_unlock(chain
);
1392 hammer2_chain_drop(chain
);
1397 hammer2_xop_inode_unlinkall(hammer2_xop_t
*arg
, void *scratch
, int clindex
)
1399 hammer2_xop_unlinkall_t
*xop
= &arg
->xop_unlinkall
;
1400 hammer2_chain_t
*parent
;
1401 hammer2_chain_t
*chain
;
1402 hammer2_key_t key_next
;
1406 * We need the precise parent chain to issue the deletion.
1408 parent
= hammer2_inode_chain(xop
->head
.ip1
, clindex
,
1409 HAMMER2_RESOLVE_ALWAYS
);
1411 if (parent
== NULL
) {
1415 chain
= hammer2_chain_lookup(&parent
, &key_next
,
1416 xop
->key_beg
, xop
->key_end
,
1417 &error
, HAMMER2_LOOKUP_ALWAYS
);
1419 hammer2_chain_delete(parent
, chain
,
1420 xop
->head
.mtid
, HAMMER2_DELETE_PERMANENT
);
1421 hammer2_xop_feed(&xop
->head
, chain
, clindex
, chain
->error
);
1422 /* depend on function to unlock the shared lock */
1423 chain
= hammer2_chain_next(&parent
, chain
, &key_next
,
1424 key_next
, xop
->key_end
,
1426 HAMMER2_LOOKUP_ALWAYS
);
1430 error
= HAMMER2_ERROR_ENOENT
;
1431 hammer2_xop_feed(&xop
->head
, NULL
, clindex
, error
);
1433 hammer2_chain_unlock(parent
);
1434 hammer2_chain_drop(parent
);
1437 hammer2_chain_unlock(chain
);
1438 hammer2_chain_drop(chain
);
1443 hammer2_xop_inode_connect(hammer2_xop_t
*arg
, void *scratch
, int clindex
)
1445 hammer2_xop_connect_t
*xop
= &arg
->xop_connect
;
1446 hammer2_inode_data_t
*wipdata
;
1447 hammer2_chain_t
*parent
;
1448 hammer2_chain_t
*chain
;
1450 hammer2_key_t key_dummy
;
1454 * Get directory, then issue a lookup to prime the parent chain
1455 * for the create. The lookup is expected to fail.
1457 pmp
= xop
->head
.ip1
->pmp
;
1458 parent
= hammer2_inode_chain(xop
->head
.ip1
, clindex
,
1459 HAMMER2_RESOLVE_ALWAYS
);
1460 if (parent
== NULL
) {
1462 error
= HAMMER2_ERROR_EIO
;
1465 chain
= hammer2_chain_lookup(&parent
, &key_dummy
,
1469 hammer2_chain_unlock(chain
);
1470 hammer2_chain_drop(chain
);
1472 error
= HAMMER2_ERROR_EEXIST
;
1479 * Adjust the filename in the inode, set the name key.
1481 * NOTE: Frontend must also adjust ip2->meta on success, we can't
1484 chain
= hammer2_inode_chain(xop
->head
.ip2
, clindex
,
1485 HAMMER2_RESOLVE_ALWAYS
);
1486 error
= hammer2_chain_modify(chain
, xop
->head
.mtid
, 0, 0);
1490 wipdata
= &chain
->data
->ipdata
;
1492 hammer2_inode_modify(xop
->head
.ip2
);
1493 if (xop
->head
.name1
) {
1494 bzero(wipdata
->filename
, sizeof(wipdata
->filename
));
1495 bcopy(xop
->head
.name1
, wipdata
->filename
, xop
->head
.name1_len
);
1496 wipdata
->meta
.name_len
= xop
->head
.name1_len
;
1498 wipdata
->meta
.name_key
= xop
->lhc
;
1501 * Reconnect the chain to the new parent directory
1503 error
= hammer2_chain_create(&parent
, &chain
, NULL
, pmp
,
1504 HAMMER2_METH_DEFAULT
,
1506 HAMMER2_BREF_TYPE_INODE
,
1507 HAMMER2_INODE_BYTES
,
1508 xop
->head
.mtid
, 0, 0);
1514 hammer2_xop_feed(&xop
->head
, NULL
, clindex
, error
);
1516 hammer2_chain_unlock(parent
);
1517 hammer2_chain_drop(parent
);
1520 hammer2_chain_unlock(chain
);
1521 hammer2_chain_drop(chain
);
1526 * Synchronize the in-memory inode with the chain. This does not flush
1527 * the chain to disk. Instead, it makes front-end inode changes visible
1528 * in the chain topology, thus visible to the backend. This is done in an
1529 * ad-hoc manner outside of the filesystem vfs_sync, and in a controlled
1530 * manner inside the vfs_sync.
1533 hammer2_xop_inode_chain_sync(hammer2_xop_t
*arg
, void *scratch
, int clindex
)
1535 hammer2_xop_fsync_t
*xop
= &arg
->xop_fsync
;
1536 hammer2_chain_t
*parent
;
1537 hammer2_chain_t
*chain
;
1540 parent
= hammer2_inode_chain(xop
->head
.ip1
, clindex
,
1541 HAMMER2_RESOLVE_ALWAYS
);
1543 if (parent
== NULL
) {
1544 error
= HAMMER2_ERROR_EIO
;
1547 if (parent
->error
) {
1548 error
= parent
->error
;
1554 if ((xop
->ipflags
& HAMMER2_INODE_RESIZED
) == 0) {
1555 /* osize must be ignored */
1556 } else if (xop
->meta
.size
< xop
->osize
) {
1558 * We must delete any chains beyond the EOF. The chain
1559 * straddling the EOF will be pending in the bioq.
1561 hammer2_key_t lbase
;
1562 hammer2_key_t key_next
;
1564 lbase
= (xop
->meta
.size
+ HAMMER2_PBUFMASK64
) &
1565 ~HAMMER2_PBUFMASK64
;
1566 chain
= hammer2_chain_lookup(&parent
, &key_next
,
1567 lbase
, HAMMER2_KEY_MAX
,
1569 HAMMER2_LOOKUP_NODATA
|
1570 HAMMER2_LOOKUP_NODIRECT
);
1573 * Degenerate embedded case, nothing to loop on
1575 switch (chain
->bref
.type
) {
1576 case HAMMER2_BREF_TYPE_DIRENT
:
1577 case HAMMER2_BREF_TYPE_INODE
:
1580 case HAMMER2_BREF_TYPE_DATA
:
1581 hammer2_chain_delete(parent
, chain
,
1583 HAMMER2_DELETE_PERMANENT
);
1586 chain
= hammer2_chain_next(&parent
, chain
, &key_next
,
1587 key_next
, HAMMER2_KEY_MAX
,
1589 HAMMER2_LOOKUP_NODATA
|
1590 HAMMER2_LOOKUP_NODIRECT
);
1594 * Reset to point at inode for following code, if necessary.
1596 if (parent
->bref
.type
!= HAMMER2_BREF_TYPE_INODE
) {
1597 hammer2_chain_unlock(parent
);
1598 hammer2_chain_drop(parent
);
1599 parent
= hammer2_inode_chain(xop
->head
.ip1
,
1601 HAMMER2_RESOLVE_ALWAYS
);
1602 kprintf("xop_inode_chain_sync: TRUNCATE RESET on '%s'\n",
1603 parent
->data
->ipdata
.filename
);
1608 * Sync the inode meta-data, potentially clear the blockset area
1609 * of direct data so it can be used for blockrefs.
1612 error
= hammer2_chain_modify(parent
, xop
->head
.mtid
, 0, 0);
1614 parent
->data
->ipdata
.meta
= xop
->meta
;
1615 if (xop
->clear_directdata
) {
1616 bzero(&parent
->data
->ipdata
.u
.blockset
,
1617 sizeof(parent
->data
->ipdata
.u
.blockset
));
1623 hammer2_chain_unlock(chain
);
1624 hammer2_chain_drop(chain
);
1627 hammer2_chain_unlock(parent
);
1628 hammer2_chain_drop(parent
);
1630 hammer2_xop_feed(&xop
->head
, NULL
, clindex
, error
);