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/namei.h>
51 #include <sys/mount.h>
52 #include <sys/vnode.h>
53 #include <sys/mountctl.h>
54 #include <sys/dirent.h>
56 #include <sys/objcache.h>
57 #include <sys/event.h>
59 #include <vfs/fifofs/fifo.h>
64 * Determine if the specified directory is empty.
66 * Returns 0 on success.
68 * Returns HAMMER_ERROR_EAGAIN if caller must re-lookup the entry and
69 * retry. (occurs if we race a ripup on oparent or ochain).
71 * Or returns a permanent HAMMER2_ERROR_* error mask.
73 * The caller must pass in an exclusively locked oparent and ochain. This
74 * function will handle the case where the chain is a directory entry or
75 * the inode itself. The original oparent,ochain will be locked upon return.
77 * This function will unlock the underlying oparent,ochain temporarily when
78 * doing an inode lookup to avoid deadlocks. The caller MUST handle the EAGAIN
79 * result as this means that oparent is no longer the parent of ochain, or
80 * that ochain was destroyed while it was unlocked.
84 checkdirempty(hammer2_chain_t *oparent, hammer2_chain_t *ochain, int clindex)
86 hammer2_chain_t *parent;
87 hammer2_chain_t *chain;
88 hammer2_key_t key_next;
97 * Find the inode, set it up as a locked 'chain'. ochain can be the
98 * inode itself, or it can be a directory entry.
100 if (ochain->bref.type == HAMMER2_BREF_TYPE_DIRENT) {
101 inum = ochain->bref.embed.dirent.inum;
102 hammer2_chain_unlock(ochain);
103 hammer2_chain_unlock(oparent);
107 error = hammer2_chain_inode_find(ochain->pmp, inum,
111 hammer2_chain_unlock(parent);
112 hammer2_chain_drop(parent);
117 * The directory entry *is* the directory inode
119 chain = hammer2_chain_lookup_init(ochain, 0);
123 * Determine if the directory is empty or not by checking its
124 * visible namespace (the area which contains directory entries).
130 chain = hammer2_chain_lookup(&parent, &key_next,
131 HAMMER2_DIRHASH_VISIBLE,
136 error = HAMMER2_ERROR_ENOTEMPTY;
137 hammer2_chain_unlock(chain);
138 hammer2_chain_drop(chain);
140 hammer2_chain_lookup_done(parent);
144 hammer2_chain_lock(oparent, HAMMER2_RESOLVE_ALWAYS);
145 hammer2_chain_lock(ochain, HAMMER2_RESOLVE_ALWAYS);
146 if ((ochain->flags & HAMMER2_CHAIN_DELETED) ||
147 (oparent->flags & HAMMER2_CHAIN_DELETED) ||
148 ochain->parent != oparent) {
149 kprintf("hammer2: debug: CHECKDIR inum %jd RETRY\n",
151 error = HAMMER2_ERROR_EAGAIN;
158 * Backend for hammer2_vfs_root()
160 * This is called when a newly mounted PFS has not yet synchronized
161 * to the inode_tid and modify_tid.
164 hammer2_xop_ipcluster(hammer2_xop_t *arg, void *scratch, int clindex)
166 hammer2_xop_ipcluster_t *xop = &arg->xop_ipcluster;
167 hammer2_chain_t *chain;
170 chain = hammer2_inode_chain(xop->head.ip1, clindex,
171 HAMMER2_RESOLVE_ALWAYS |
172 HAMMER2_RESOLVE_SHARED);
174 error = chain->error;
176 error = HAMMER2_ERROR_EIO;
178 hammer2_xop_feed(&xop->head, chain, clindex, error);
180 hammer2_chain_unlock(chain);
181 hammer2_chain_drop(chain);
186 * Backend for hammer2_vop_readdir()
189 hammer2_xop_readdir(hammer2_xop_t *arg, void *scratch, int clindex)
191 hammer2_xop_readdir_t *xop = &arg->xop_readdir;
192 hammer2_chain_t *parent;
193 hammer2_chain_t *chain;
194 hammer2_key_t key_next;
199 if (hammer2_debug & 0x0020)
200 kprintf("xop_readdir %p lkey=%016jx\n", xop, lkey);
203 * The inode's chain is the iterator. If we cannot acquire it our
204 * contribution ends here.
206 parent = hammer2_inode_chain(xop->head.ip1, clindex,
207 HAMMER2_RESOLVE_ALWAYS |
208 HAMMER2_RESOLVE_SHARED);
209 if (parent == NULL) {
210 kprintf("xop_readdir: NULL parent\n");
215 * Directory scan [re]start and loop, the feed inherits the chain's
216 * lock so do not unlock it on the iteration.
218 chain = hammer2_chain_lookup(&parent, &key_next, lkey, lkey,
219 &error, HAMMER2_LOOKUP_SHARED);
221 chain = hammer2_chain_lookup(&parent, &key_next,
222 lkey, HAMMER2_KEY_MAX,
223 &error, HAMMER2_LOOKUP_SHARED);
226 error = hammer2_xop_feed(&xop->head, chain, clindex, 0);
229 chain = hammer2_chain_next(&parent, chain, &key_next,
230 key_next, HAMMER2_KEY_MAX,
231 &error, HAMMER2_LOOKUP_SHARED);
235 hammer2_chain_unlock(chain);
236 hammer2_chain_drop(chain);
238 hammer2_chain_unlock(parent);
239 hammer2_chain_drop(parent);
241 hammer2_xop_feed(&xop->head, NULL, clindex, error);
245 * Backend for hammer2_vop_nresolve()
248 hammer2_xop_nresolve(hammer2_xop_t *arg, void *scratch, int clindex)
250 hammer2_xop_nresolve_t *xop = &arg->xop_nresolve;
251 hammer2_chain_t *parent;
252 hammer2_chain_t *chain;
255 hammer2_key_t key_next;
259 parent = hammer2_inode_chain(xop->head.ip1, clindex,
260 HAMMER2_RESOLVE_ALWAYS |
261 HAMMER2_RESOLVE_SHARED);
262 if (parent == NULL) {
263 kprintf("xop_nresolve: NULL parent\n");
265 error = HAMMER2_ERROR_EIO;
268 name = xop->head.name1;
269 name_len = xop->head.name1_len;
272 * Lookup the directory entry
274 lhc = hammer2_dirhash(name, name_len);
275 chain = hammer2_chain_lookup(&parent, &key_next,
276 lhc, lhc + HAMMER2_DIRHASH_LOMASK,
278 HAMMER2_LOOKUP_ALWAYS |
279 HAMMER2_LOOKUP_SHARED);
281 if (hammer2_chain_dirent_test(chain, name, name_len))
283 chain = hammer2_chain_next(&parent, chain, &key_next,
285 lhc + HAMMER2_DIRHASH_LOMASK,
287 HAMMER2_LOOKUP_ALWAYS |
288 HAMMER2_LOOKUP_SHARED);
292 * Locate the target inode for a directory entry
294 if (chain && chain->error == 0) {
295 if (chain->bref.type == HAMMER2_BREF_TYPE_DIRENT) {
296 lhc = chain->bref.embed.dirent.inum;
297 error = hammer2_chain_inode_find(chain->pmp,
300 HAMMER2_LOOKUP_SHARED,
304 } else if (chain && error == 0) {
305 error = chain->error;
308 error = hammer2_xop_feed(&xop->head, chain, clindex, error);
310 hammer2_chain_unlock(chain);
311 hammer2_chain_drop(chain);
314 hammer2_chain_unlock(parent);
315 hammer2_chain_drop(parent);
320 * Backend for hammer2_vop_nremove(), hammer2_vop_nrmdir(), and
321 * backend for pfs_delete.
323 * This function locates and removes a directory entry, and will lookup
324 * and return the underlying inode. For directory entries the underlying
325 * inode is not removed. If the directory entry is the actual inode itself,
326 * it may be conditonally removed and returned.
328 * WARNING! Any target inode's nlinks may not be synchronized to the
329 * in-memory inode. The frontend's hammer2_inode_unlink_finisher()
330 * is responsible for the final disposition of the actual inode.
333 hammer2_xop_unlink(hammer2_xop_t *arg, void *scratch, int clindex)
335 hammer2_xop_unlink_t *xop = &arg->xop_unlink;
336 hammer2_chain_t *parent;
337 hammer2_chain_t *chain;
340 hammer2_key_t key_next;
346 * Requires exclusive lock
348 parent = hammer2_inode_chain(xop->head.ip1, clindex,
349 HAMMER2_RESOLVE_ALWAYS);
351 if (parent == NULL) {
352 kprintf("xop_nresolve: NULL parent\n");
353 error = HAMMER2_ERROR_EIO;
356 name = xop->head.name1;
357 name_len = xop->head.name1_len;
360 * Lookup the directory entry
362 lhc = hammer2_dirhash(name, name_len);
363 chain = hammer2_chain_lookup(&parent, &key_next,
364 lhc, lhc + HAMMER2_DIRHASH_LOMASK,
365 &error, HAMMER2_LOOKUP_ALWAYS);
367 if (hammer2_chain_dirent_test(chain, name, name_len))
369 chain = hammer2_chain_next(&parent, chain, &key_next,
371 lhc + HAMMER2_DIRHASH_LOMASK,
372 &error, HAMMER2_LOOKUP_ALWAYS);
376 * The directory entry will either be a BREF_TYPE_DIRENT or a
377 * BREF_TYPE_INODE. We always permanently delete DIRENTs, but
378 * must go by xop->dopermanent for BREF_TYPE_INODE.
380 * Note that the target chain's nlinks may not be synchronized with
381 * the in-memory hammer2_inode_t structure, so we don't try to do
382 * anything fancy here. The frontend deals with nlinks
385 if (chain && chain->error == 0) {
386 int dopermanent = xop->dopermanent & H2DOPERM_PERMANENT;
387 int doforce = xop->dopermanent & H2DOPERM_FORCE;
391 * If the directory entry is the actual inode then use its
392 * type for the directory typing tests, otherwise if it is
393 * a directory entry, pull the type field from the entry.
395 * Directory entries are always permanently deleted
396 * (because they aren't the actual inode).
398 if (chain->bref.type == HAMMER2_BREF_TYPE_DIRENT) {
399 type = chain->bref.embed.dirent.type;
400 dopermanent |= HAMMER2_DELETE_PERMANENT;
402 type = chain->data->ipdata.meta.type;
406 * Check directory typing and delete the entry. Note that
407 * nlinks adjustments are made on the real inode by the
408 * frontend, not here.
410 * Unfortunately, checkdirempty() may have to unlock (parent).
411 * If it no longer matches chain->parent after re-locking,
412 * EAGAIN is returned.
414 if (type == HAMMER2_OBJTYPE_DIRECTORY && doforce) {
416 * If doforce then execute the operation even if
417 * the directory is not empty or errored. We
418 * ignore chain->error here, allowing an errored
419 * chain (aka directory entry) to still be deleted.
421 error = hammer2_chain_delete(parent, chain,
422 xop->head.mtid, dopermanent);
423 } else if (type == HAMMER2_OBJTYPE_DIRECTORY &&
425 error = HAMMER2_ERROR_EISDIR;
426 } else if (type == HAMMER2_OBJTYPE_DIRECTORY &&
427 (error = checkdirempty(parent, chain, clindex)) != 0) {
429 * error may be EAGAIN or ENOTEMPTY
431 if (error == HAMMER2_ERROR_EAGAIN) {
432 hammer2_chain_unlock(chain);
433 hammer2_chain_drop(chain);
434 hammer2_chain_unlock(parent);
435 hammer2_chain_drop(parent);
438 } else if (type != HAMMER2_OBJTYPE_DIRECTORY &&
440 error = HAMMER2_ERROR_ENOTDIR;
443 * Delete the directory entry. chain might also
444 * be a directly-embedded inode.
446 * Allow the deletion to proceed even if the chain
447 * is errored. Give priority to error-on-delete over
450 error = hammer2_chain_delete(parent, chain,
454 error = chain->error;
457 if (chain && error == 0)
458 error = chain->error;
462 * If chain is a directory entry we must resolve it. We do not try
463 * to manipulate the contents as it might not be synchronized with
464 * the frontend hammer2_inode_t, nor do we try to lookup the
465 * frontend hammer2_inode_t here (we are the backend!).
467 if (chain && chain->bref.type == HAMMER2_BREF_TYPE_DIRENT &&
468 (xop->dopermanent & H2DOPERM_IGNINO) == 0) {
471 lhc = chain->bref.embed.dirent.inum;
473 error2 = hammer2_chain_inode_find(chain->pmp, lhc,
477 kprintf("inode_find: %016jx %p failed\n",
479 error2 = 0; /* silently ignore */
486 * Return the inode target for further action. Typically used by
487 * hammer2_inode_unlink_finisher().
490 hammer2_xop_feed(&xop->head, chain, clindex, error);
492 hammer2_chain_unlock(chain);
493 hammer2_chain_drop(chain);
497 hammer2_chain_unlock(parent);
498 hammer2_chain_drop(parent);
504 * Backend for hammer2_vop_nrename()
506 * This handles the backend rename operation. Typically this renames
507 * directory entries but can also be used to rename embedded inodes.
509 * NOTE! The frontend is responsible for updating the inode meta-data in
510 * the file being renamed and for decrementing the target-replaced
511 * inode's nlinks, if present.
514 hammer2_xop_nrename(hammer2_xop_t *arg, void *scratch, int clindex)
516 hammer2_xop_nrename_t *xop = &arg->xop_nrename;
518 hammer2_chain_t *parent;
519 hammer2_chain_t *chain;
520 hammer2_chain_t *tmp;
522 hammer2_key_t key_next;
526 * We need the precise parent chain to issue the deletion.
528 * If this is a directory entry we must locate the underlying
529 * inode. If it is an embedded inode we can act directly on it.
536 if (xop->ip_key & HAMMER2_DIRHASH_VISIBLE) {
538 * Find ip's direct parent chain.
540 chain = hammer2_inode_chain(ip, clindex,
541 HAMMER2_RESOLVE_ALWAYS);
543 error = HAMMER2_ERROR_EIO;
547 if (ip->flags & HAMMER2_INODE_CREATING) {
550 parent = hammer2_chain_getparent(chain,
551 HAMMER2_RESOLVE_ALWAYS);
552 if (parent == NULL) {
553 error = HAMMER2_ERROR_EIO;
559 * The directory entry for the head.ip1 inode
560 * is in fdip, do a namespace search.
566 parent = hammer2_inode_chain(xop->head.ip1, clindex,
567 HAMMER2_RESOLVE_ALWAYS);
568 if (parent == NULL) {
569 kprintf("xop_nrename: NULL parent\n");
570 error = HAMMER2_ERROR_EIO;
573 name = xop->head.name1;
574 name_len = xop->head.name1_len;
577 * Lookup the directory entry
579 lhc = hammer2_dirhash(name, name_len);
580 chain = hammer2_chain_lookup(&parent, &key_next,
581 lhc, lhc + HAMMER2_DIRHASH_LOMASK,
582 &error, HAMMER2_LOOKUP_ALWAYS);
584 if (hammer2_chain_dirent_test(chain, name, name_len))
586 chain = hammer2_chain_next(&parent, chain, &key_next,
588 lhc + HAMMER2_DIRHASH_LOMASK,
590 HAMMER2_LOOKUP_ALWAYS);
595 /* XXX shouldn't happen, but does under fsstress */
596 kprintf("hammer2_xop_rename: \"%s\" -> \"%s\" ENOENT\n",
600 error = HAMMER2_ERROR_ENOENT;
605 error = chain->error;
610 * Delete it, then create it in the new namespace.
612 * An error can occur if the chain being deleted requires
613 * modification and the media is full.
615 error = hammer2_chain_delete(parent, chain, xop->head.mtid, 0);
616 hammer2_chain_unlock(parent);
617 hammer2_chain_drop(parent);
618 parent = NULL; /* safety */
623 * Adjust fields in the deleted chain appropriate for the rename
626 * NOTE! For embedded inodes, the frontend will officially replicate
627 * the field adjustments, but we also do it here to maintain
628 * consistency in case of a crash.
630 if (chain->bref.key != xop->lhc ||
631 xop->head.name1_len != xop->head.name2_len ||
632 bcmp(xop->head.name1, xop->head.name2, xop->head.name1_len) != 0) {
633 if (chain->bref.type == HAMMER2_BREF_TYPE_INODE) {
634 hammer2_inode_data_t *wipdata;
636 error = hammer2_chain_modify(chain, xop->head.mtid,
639 wipdata = &chain->data->ipdata;
641 bzero(wipdata->filename,
642 sizeof(wipdata->filename));
643 bcopy(xop->head.name2,
645 xop->head.name2_len);
646 wipdata->meta.name_key = xop->lhc;
647 wipdata->meta.name_len = xop->head.name2_len;
650 if (chain->bref.type == HAMMER2_BREF_TYPE_DIRENT) {
651 if (xop->head.name2_len <=
652 sizeof(chain->bref.check.buf)) {
654 * Remove any related data buffer, we can
655 * embed the filename in the bref itself.
657 error = hammer2_chain_resize(
658 chain, xop->head.mtid, 0, 0, 0);
660 error = hammer2_chain_modify(
661 chain, xop->head.mtid,
665 bzero(chain->bref.check.buf,
666 sizeof(chain->bref.check.buf));
667 bcopy(xop->head.name2,
668 chain->bref.check.buf,
669 xop->head.name2_len);
673 * Associate a data buffer with the bref.
674 * Zero it for consistency. Note that the
675 * data buffer is not 64KB so use chain->bytes
676 * instead of sizeof().
678 error = hammer2_chain_resize(
679 chain, xop->head.mtid, 0,
680 hammer2_getradix(HAMMER2_ALLOC_MIN), 0);
682 error = hammer2_chain_modify(
683 chain, xop->head.mtid,
687 bzero(chain->data->buf, chain->bytes);
688 bcopy(xop->head.name2,
690 xop->head.name2_len);
694 chain->bref.embed.dirent.namlen =
701 * The frontend will replicate this operation and is the real final
702 * authority, but adjust the inode's iparent field too if the inode
703 * is embedded in the directory.
705 if (chain->bref.type == HAMMER2_BREF_TYPE_INODE &&
706 chain->data->ipdata.meta.iparent != xop->head.ip3->meta.inum) {
707 hammer2_inode_data_t *wipdata;
709 error = hammer2_chain_modify(chain, xop->head.mtid, 0, 0);
711 wipdata = &chain->data->ipdata;
712 wipdata->meta.iparent = xop->head.ip3->meta.inum;
717 * Destroy any matching target(s) before creating the new entry.
718 * This will result in some ping-ponging of the directory key
719 * iterator but that is ok.
721 parent = hammer2_inode_chain(xop->head.ip3, clindex,
722 HAMMER2_RESOLVE_ALWAYS);
723 if (parent == NULL) {
724 error = HAMMER2_ERROR_EIO;
729 * Delete all matching directory entries. That is, get rid of
730 * multiple duplicates if present, as a self-healing mechanism.
733 tmp = hammer2_chain_lookup(&parent, &key_next,
734 xop->lhc & ~HAMMER2_DIRHASH_LOMASK,
735 xop->lhc | HAMMER2_DIRHASH_LOMASK,
737 HAMMER2_LOOKUP_ALWAYS);
740 if (hammer2_chain_dirent_test(tmp, xop->head.name2,
741 xop->head.name2_len)) {
742 e2 = hammer2_chain_delete(parent, tmp,
744 if (error == 0 && e2)
747 tmp = hammer2_chain_next(&parent, tmp, &key_next,
750 HAMMER2_DIRHASH_LOMASK,
752 HAMMER2_LOOKUP_ALWAYS);
757 * A relookup is required before the create to properly
758 * position the parent chain.
760 tmp = hammer2_chain_lookup(&parent, &key_next,
763 KKASSERT(tmp == NULL);
764 error = hammer2_chain_create(&parent, &chain, NULL, pmp,
765 HAMMER2_METH_DEFAULT,
767 HAMMER2_BREF_TYPE_INODE,
769 xop->head.mtid, 0, 0);
772 hammer2_xop_feed(&xop->head, NULL, clindex, error);
774 hammer2_chain_unlock(parent);
775 hammer2_chain_drop(parent);
778 hammer2_chain_unlock(chain);
779 hammer2_chain_drop(chain);
784 * Directory collision resolver scan helper (backend, threaded).
786 * Used by the inode create code to locate an unused lhc.
789 hammer2_xop_scanlhc(hammer2_xop_t *arg, void *scratch, int clindex)
791 hammer2_xop_scanlhc_t *xop = &arg->xop_scanlhc;
792 hammer2_chain_t *parent;
793 hammer2_chain_t *chain;
794 hammer2_key_t key_next;
797 parent = hammer2_inode_chain(xop->head.ip1, clindex,
798 HAMMER2_RESOLVE_ALWAYS |
799 HAMMER2_RESOLVE_SHARED);
800 if (parent == NULL) {
801 kprintf("xop_nresolve: NULL parent\n");
803 error = HAMMER2_ERROR_EIO;
808 * Lookup all possibly conflicting directory entries, the feed
809 * inherits the chain's lock so do not unlock it on the iteration.
811 chain = hammer2_chain_lookup(&parent, &key_next,
813 xop->lhc + HAMMER2_DIRHASH_LOMASK,
815 HAMMER2_LOOKUP_ALWAYS |
816 HAMMER2_LOOKUP_SHARED);
818 error = hammer2_xop_feed(&xop->head, chain, clindex, 0);
820 hammer2_chain_unlock(chain);
821 hammer2_chain_drop(chain);
822 chain = NULL; /* safety */
825 chain = hammer2_chain_next(&parent, chain, &key_next,
827 xop->lhc + HAMMER2_DIRHASH_LOMASK,
829 HAMMER2_LOOKUP_ALWAYS |
830 HAMMER2_LOOKUP_SHARED);
833 hammer2_xop_feed(&xop->head, NULL, clindex, error);
835 hammer2_chain_unlock(parent);
836 hammer2_chain_drop(parent);
841 * Generic lookup of a specific key.
844 hammer2_xop_lookup(hammer2_xop_t *arg, void *scratch, int clindex)
846 hammer2_xop_scanlhc_t *xop = &arg->xop_scanlhc;
847 hammer2_chain_t *parent;
848 hammer2_chain_t *chain;
849 hammer2_key_t key_next;
852 parent = hammer2_inode_chain(xop->head.ip1, clindex,
853 HAMMER2_RESOLVE_ALWAYS |
854 HAMMER2_RESOLVE_SHARED);
856 if (parent == NULL) {
857 error = HAMMER2_ERROR_EIO;
862 * Lookup all possibly conflicting directory entries, the feed
863 * inherits the chain's lock so do not unlock it on the iteration.
865 chain = hammer2_chain_lookup(&parent, &key_next,
868 HAMMER2_LOOKUP_ALWAYS |
869 HAMMER2_LOOKUP_SHARED);
872 error = chain->error;
874 error = HAMMER2_ERROR_ENOENT;
876 hammer2_xop_feed(&xop->head, chain, clindex, error);
880 hammer2_chain_unlock(chain);
881 hammer2_chain_drop(chain);
884 hammer2_chain_unlock(parent);
885 hammer2_chain_drop(parent);
890 hammer2_xop_delete(hammer2_xop_t *arg, void *scratch, int clindex)
892 hammer2_xop_scanlhc_t *xop = &arg->xop_scanlhc;
893 hammer2_chain_t *parent;
894 hammer2_chain_t *chain;
895 hammer2_key_t key_next;
898 parent = hammer2_inode_chain(xop->head.ip1, clindex,
899 HAMMER2_RESOLVE_ALWAYS);
901 if (parent == NULL) {
902 error = HAMMER2_ERROR_EIO;
907 * Lookup all possibly conflicting directory entries, the feed
908 * inherits the chain's lock so do not unlock it on the iteration.
910 chain = hammer2_chain_lookup(&parent, &key_next,
913 HAMMER2_LOOKUP_NODATA);
916 error = chain->error;
918 error = HAMMER2_ERROR_ENOENT;
921 error = hammer2_chain_delete(parent, chain, xop->head.mtid,
922 HAMMER2_DELETE_PERMANENT);
924 hammer2_xop_feed(&xop->head, NULL, clindex, error);
928 hammer2_chain_unlock(chain);
929 hammer2_chain_drop(chain);
932 hammer2_chain_unlock(parent);
933 hammer2_chain_drop(parent);
940 * WARNING! Fed chains must be locked shared so ownership can be transfered
941 * and to prevent frontend/backend stalls that would occur with an
942 * exclusive lock. The shared lock also allows chain->data to be
946 hammer2_xop_scanall(hammer2_xop_t *arg, void *scratch, int clindex)
948 hammer2_xop_scanall_t *xop = &arg->xop_scanall;
949 hammer2_chain_t *parent;
950 hammer2_chain_t *chain;
951 hammer2_key_t key_next;
955 * Assert required flags.
957 KKASSERT(xop->resolve_flags & HAMMER2_RESOLVE_SHARED);
958 KKASSERT(xop->lookup_flags & HAMMER2_LOOKUP_SHARED);
961 * The inode's chain is the iterator. If we cannot acquire it our
962 * contribution ends here.
964 parent = hammer2_inode_chain(xop->head.ip1, clindex,
966 if (parent == NULL) {
967 kprintf("xop_readdir: NULL parent\n");
972 * Generic scan of exact records. Note that indirect blocks are
973 * automatically recursed and will not be returned.
975 chain = hammer2_chain_lookup(&parent, &key_next,
976 xop->key_beg, xop->key_end,
977 &error, xop->lookup_flags);
979 error = hammer2_xop_feed(&xop->head, chain, clindex, 0);
982 chain = hammer2_chain_next(&parent, chain, &key_next,
983 key_next, xop->key_end,
984 &error, xop->lookup_flags);
988 hammer2_chain_unlock(chain);
989 hammer2_chain_drop(chain);
991 hammer2_chain_unlock(parent);
992 hammer2_chain_drop(parent);
994 hammer2_xop_feed(&xop->head, NULL, clindex, error);
997 /************************************************************************
999 ************************************************************************
1003 * Helper to create a directory entry.
1006 hammer2_xop_inode_mkdirent(hammer2_xop_t *arg, void *scratch, int clindex)
1008 hammer2_xop_mkdirent_t *xop = &arg->xop_mkdirent;
1009 hammer2_chain_t *parent;
1010 hammer2_chain_t *chain;
1011 hammer2_key_t key_next;
1015 if (hammer2_debug & 0x0001)
1016 kprintf("dirent_create lhc %016jx clindex %d\n",
1019 parent = hammer2_inode_chain(xop->head.ip1, clindex,
1020 HAMMER2_RESOLVE_ALWAYS);
1021 if (parent == NULL) {
1022 error = HAMMER2_ERROR_EIO;
1026 chain = hammer2_chain_lookup(&parent, &key_next,
1030 error = HAMMER2_ERROR_EEXIST;
1035 * We may be able to embed the directory entry directly in the
1038 if (xop->dirent.namlen <= sizeof(chain->bref.check.buf))
1041 data_len = HAMMER2_ALLOC_MIN;
1043 error = hammer2_chain_create(&parent, &chain, NULL, xop->head.ip1->pmp,
1044 HAMMER2_METH_DEFAULT,
1046 HAMMER2_BREF_TYPE_DIRENT,
1048 xop->head.mtid, 0, 0);
1051 * WARNING: chain->data->buf is sized to chain->bytes,
1052 * do not use sizeof(chain->data->buf), which
1053 * will be much larger.
1055 error = hammer2_chain_modify(chain, xop->head.mtid, 0, 0);
1057 chain->bref.embed.dirent = xop->dirent;
1058 if (xop->dirent.namlen <= sizeof(chain->bref.check.buf))
1059 bcopy(xop->head.name1, chain->bref.check.buf,
1060 xop->dirent.namlen);
1062 bcopy(xop->head.name1, chain->data->buf,
1063 xop->dirent.namlen);
1068 hammer2_chain_unlock(parent);
1069 hammer2_chain_drop(parent);
1071 hammer2_xop_feed(&xop->head, chain, clindex, error);
1073 hammer2_chain_unlock(chain);
1074 hammer2_chain_drop(chain);
1079 * Inode create helper (threaded, backend)
1081 * Used by ncreate, nmknod, nsymlink, nmkdir.
1082 * Used by nlink and rename to create HARDLINK pointers.
1084 * Frontend holds the parent directory ip locked exclusively. We
1085 * create the inode and feed the exclusively locked chain to the
1089 hammer2_xop_inode_create(hammer2_xop_t *arg, void *scratch, int clindex)
1091 hammer2_xop_create_t *xop = &arg->xop_create;
1092 hammer2_chain_t *parent;
1093 hammer2_chain_t *chain;
1094 hammer2_key_t key_next;
1097 if (hammer2_debug & 0x0001)
1098 kprintf("inode_create lhc %016jx clindex %d\n",
1101 parent = hammer2_inode_chain(xop->head.ip1, clindex,
1102 HAMMER2_RESOLVE_ALWAYS);
1103 if (parent == NULL) {
1104 error = HAMMER2_ERROR_EIO;
1108 chain = hammer2_chain_lookup(&parent, &key_next,
1112 error = HAMMER2_ERROR_EEXIST;
1116 error = hammer2_chain_create(&parent, &chain, NULL, xop->head.ip1->pmp,
1117 HAMMER2_METH_DEFAULT,
1119 HAMMER2_BREF_TYPE_INODE,
1120 HAMMER2_INODE_BYTES,
1121 xop->head.mtid, 0, xop->flags);
1123 error = hammer2_chain_modify(chain, xop->head.mtid, 0, 0);
1125 chain->data->ipdata.meta = xop->meta;
1126 if (xop->head.name1) {
1127 bcopy(xop->head.name1,
1128 chain->data->ipdata.filename,
1129 xop->head.name1_len);
1130 chain->data->ipdata.meta.name_len =
1131 xop->head.name1_len;
1133 chain->data->ipdata.meta.name_key = xop->lhc;
1138 hammer2_chain_unlock(parent);
1139 hammer2_chain_drop(parent);
1141 hammer2_xop_feed(&xop->head, chain, clindex, error);
1143 hammer2_chain_unlock(chain);
1144 hammer2_chain_drop(chain);
1149 * Create inode as above but leave it detached from the hierarchy.
1152 hammer2_xop_inode_create_det(hammer2_xop_t *arg, void *scratch, int clindex)
1154 hammer2_xop_create_t *xop = &arg->xop_create;
1155 hammer2_chain_t *parent;
1156 hammer2_chain_t *chain;
1157 hammer2_chain_t *null_parent;
1158 hammer2_key_t key_next;
1159 hammer2_inode_t *pip;
1160 hammer2_inode_t *iroot;
1163 if (hammer2_debug & 0x0001)
1164 kprintf("inode_create_det lhc %016jx clindex %d\n",
1167 pip = xop->head.ip1;
1168 iroot = pip->pmp->iroot;
1170 parent = hammer2_inode_chain(iroot, clindex, HAMMER2_RESOLVE_ALWAYS);
1172 if (parent == NULL) {
1173 error = HAMMER2_ERROR_EIO;
1177 chain = hammer2_chain_lookup(&parent, &key_next,
1181 error = HAMMER2_ERROR_EEXIST;
1186 * Create as a detached chain with no parent. We must specify
1190 error = hammer2_chain_create(&null_parent, &chain,
1191 parent->hmp, pip->pmp,
1192 HAMMER2_ENC_COMP(pip->meta.comp_algo) +
1193 HAMMER2_ENC_CHECK(pip->meta.check_algo),
1195 HAMMER2_BREF_TYPE_INODE,
1196 HAMMER2_INODE_BYTES,
1197 xop->head.mtid, 0, xop->flags);
1199 error = hammer2_chain_modify(chain, xop->head.mtid, 0, 0);
1201 chain->data->ipdata.meta = xop->meta;
1202 if (xop->head.name1) {
1203 bcopy(xop->head.name1,
1204 chain->data->ipdata.filename,
1205 xop->head.name1_len);
1206 chain->data->ipdata.meta.name_len =
1207 xop->head.name1_len;
1209 chain->data->ipdata.meta.name_key = xop->lhc;
1214 hammer2_chain_unlock(parent);
1215 hammer2_chain_drop(parent);
1217 hammer2_xop_feed(&xop->head, chain, clindex, error);
1219 hammer2_chain_unlock(chain);
1220 hammer2_chain_drop(chain);
1225 * Take a detached chain and insert it into the topology
1228 hammer2_xop_inode_create_ins(hammer2_xop_t *arg, void *scratch, int clindex)
1230 hammer2_xop_create_t *xop = &arg->xop_create;
1231 hammer2_chain_t *parent;
1232 hammer2_chain_t *chain;
1233 hammer2_key_t key_next;
1236 if (hammer2_debug & 0x0001)
1237 kprintf("inode_create_ins lhc %016jx clindex %d\n",
1241 * (parent) will be the insertion point for inode under iroot
1243 parent = hammer2_inode_chain(xop->head.ip1->pmp->iroot, clindex,
1244 HAMMER2_RESOLVE_ALWAYS);
1245 if (parent == NULL) {
1246 error = HAMMER2_ERROR_EIO;
1250 chain = hammer2_chain_lookup(&parent, &key_next,
1254 error = HAMMER2_ERROR_EEXIST;
1259 * (chain) is the detached inode that is being inserted
1261 chain = hammer2_inode_chain(xop->head.ip1, clindex,
1262 HAMMER2_RESOLVE_ALWAYS);
1263 if (chain == NULL) {
1264 error = HAMMER2_ERROR_EIO;
1270 * This create call will insert the non-NULL chain into parent.
1271 * Most of the auxillary fields are ignored since the chain already
1274 error = hammer2_chain_create(&parent, &chain, NULL, xop->head.ip1->pmp,
1275 HAMMER2_METH_DEFAULT,
1277 HAMMER2_BREF_TYPE_INODE,
1278 HAMMER2_INODE_BYTES,
1279 xop->head.mtid, 0, xop->flags);
1282 error = hammer2_chain_modify(chain, xop->head.mtid, 0, 0);
1284 chain->data->ipdata.meta = xop->meta;
1285 if (xop->head.name1) {
1286 bcopy(xop->head.name1,
1287 chain->data->ipdata.filename,
1288 xop->head.name1_len);
1289 chain->data->ipdata.meta.name_len =
1290 xop->head.name1_len;
1292 chain->data->ipdata.meta.name_key = xop->lhc;
1298 hammer2_chain_unlock(parent);
1299 hammer2_chain_drop(parent);
1301 hammer2_xop_feed(&xop->head, chain, clindex, error);
1303 hammer2_chain_unlock(chain);
1304 hammer2_chain_drop(chain);
1309 * Inode delete helper (backend, threaded)
1311 * Generally used by hammer2_run_sideq()
1314 hammer2_xop_inode_destroy(hammer2_xop_t *arg, void *scratch, int clindex)
1316 hammer2_xop_destroy_t *xop = &arg->xop_destroy;
1318 hammer2_chain_t *parent;
1319 hammer2_chain_t *chain;
1320 hammer2_inode_t *ip;
1324 * We need the precise parent chain to issue the deletion.
1329 chain = hammer2_inode_chain(ip, clindex, HAMMER2_RESOLVE_ALWAYS);
1330 if (chain == NULL) {
1332 error = HAMMER2_ERROR_EIO;
1336 if (ip->flags & HAMMER2_INODE_CREATING) {
1338 * Inode's chains are not linked into the media topology
1339 * because it is a new inode (which is now being destroyed).
1344 * Inode's chains are linked into the media topology
1346 parent = hammer2_chain_getparent(chain, HAMMER2_RESOLVE_ALWAYS);
1347 if (parent == NULL) {
1348 error = HAMMER2_ERROR_EIO;
1352 KKASSERT(chain->parent == parent);
1355 * We have the correct parent, we can issue the deletion.
1357 hammer2_chain_delete(parent, chain, xop->head.mtid, 0);
1360 hammer2_xop_feed(&xop->head, NULL, clindex, error);
1362 hammer2_chain_unlock(parent);
1363 hammer2_chain_drop(parent);
1366 hammer2_chain_unlock(chain);
1367 hammer2_chain_drop(chain);
1372 hammer2_xop_inode_unlinkall(hammer2_xop_t *arg, void *scratch, int clindex)
1374 hammer2_xop_unlinkall_t *xop = &arg->xop_unlinkall;
1375 hammer2_chain_t *parent;
1376 hammer2_chain_t *chain;
1377 hammer2_key_t key_next;
1381 * We need the precise parent chain to issue the deletion.
1383 parent = hammer2_inode_chain(xop->head.ip1, clindex,
1384 HAMMER2_RESOLVE_ALWAYS);
1386 if (parent == NULL) {
1390 chain = hammer2_chain_lookup(&parent, &key_next,
1391 xop->key_beg, xop->key_end,
1392 &error, HAMMER2_LOOKUP_ALWAYS);
1394 hammer2_chain_delete(parent, chain,
1395 xop->head.mtid, HAMMER2_DELETE_PERMANENT);
1396 hammer2_xop_feed(&xop->head, chain, clindex, chain->error);
1397 /* depend on function to unlock the shared lock */
1398 chain = hammer2_chain_next(&parent, chain, &key_next,
1399 key_next, xop->key_end,
1401 HAMMER2_LOOKUP_ALWAYS);
1405 error = HAMMER2_ERROR_ENOENT;
1406 hammer2_xop_feed(&xop->head, NULL, clindex, error);
1408 hammer2_chain_unlock(parent);
1409 hammer2_chain_drop(parent);
1412 hammer2_chain_unlock(chain);
1413 hammer2_chain_drop(chain);
1418 hammer2_xop_inode_connect(hammer2_xop_t *arg, void *scratch, int clindex)
1420 hammer2_xop_connect_t *xop = &arg->xop_connect;
1421 hammer2_inode_data_t *wipdata;
1422 hammer2_chain_t *parent;
1423 hammer2_chain_t *chain;
1425 hammer2_key_t key_dummy;
1429 * Get directory, then issue a lookup to prime the parent chain
1430 * for the create. The lookup is expected to fail.
1432 pmp = xop->head.ip1->pmp;
1433 parent = hammer2_inode_chain(xop->head.ip1, clindex,
1434 HAMMER2_RESOLVE_ALWAYS);
1435 if (parent == NULL) {
1437 error = HAMMER2_ERROR_EIO;
1440 chain = hammer2_chain_lookup(&parent, &key_dummy,
1444 hammer2_chain_unlock(chain);
1445 hammer2_chain_drop(chain);
1447 error = HAMMER2_ERROR_EEXIST;
1454 * Adjust the filename in the inode, set the name key.
1456 * NOTE: Frontend must also adjust ip2->meta on success, we can't
1459 chain = hammer2_inode_chain(xop->head.ip2, clindex,
1460 HAMMER2_RESOLVE_ALWAYS);
1461 error = hammer2_chain_modify(chain, xop->head.mtid, 0, 0);
1465 wipdata = &chain->data->ipdata;
1467 hammer2_inode_modify(xop->head.ip2);
1468 if (xop->head.name1) {
1469 bzero(wipdata->filename, sizeof(wipdata->filename));
1470 bcopy(xop->head.name1, wipdata->filename, xop->head.name1_len);
1471 wipdata->meta.name_len = xop->head.name1_len;
1473 wipdata->meta.name_key = xop->lhc;
1476 * Reconnect the chain to the new parent directory
1478 error = hammer2_chain_create(&parent, &chain, NULL, pmp,
1479 HAMMER2_METH_DEFAULT,
1481 HAMMER2_BREF_TYPE_INODE,
1482 HAMMER2_INODE_BYTES,
1483 xop->head.mtid, 0, 0);
1489 hammer2_xop_feed(&xop->head, NULL, clindex, error);
1491 hammer2_chain_unlock(parent);
1492 hammer2_chain_drop(parent);
1495 hammer2_chain_unlock(chain);
1496 hammer2_chain_drop(chain);
1501 * Synchronize the in-memory inode with the chain. This does not flush
1502 * the chain to disk. Instead, it makes front-end inode changes visible
1503 * in the chain topology, thus visible to the backend. This is done in an
1504 * ad-hoc manner outside of the filesystem vfs_sync, and in a controlled
1505 * manner inside the vfs_sync.
1508 hammer2_xop_inode_chain_sync(hammer2_xop_t *arg, void *scratch, int clindex)
1510 hammer2_xop_fsync_t *xop = &arg->xop_fsync;
1511 hammer2_chain_t *parent;
1512 hammer2_chain_t *chain;
1515 parent = hammer2_inode_chain(xop->head.ip1, clindex,
1516 HAMMER2_RESOLVE_ALWAYS);
1518 if (parent == NULL) {
1519 error = HAMMER2_ERROR_EIO;
1522 if (parent->error) {
1523 error = parent->error;
1529 if ((xop->ipflags & HAMMER2_INODE_RESIZED) == 0) {
1530 /* osize must be ignored */
1531 } else if (xop->meta.size < xop->osize) {
1533 * We must delete any chains beyond the EOF. The chain
1534 * straddling the EOF will be pending in the bioq.
1536 hammer2_key_t lbase;
1537 hammer2_key_t key_next;
1539 lbase = (xop->meta.size + HAMMER2_PBUFMASK64) &
1540 ~HAMMER2_PBUFMASK64;
1541 chain = hammer2_chain_lookup(&parent, &key_next,
1542 lbase, HAMMER2_KEY_MAX,
1544 HAMMER2_LOOKUP_NODATA |
1545 HAMMER2_LOOKUP_NODIRECT);
1548 * Degenerate embedded case, nothing to loop on
1550 switch (chain->bref.type) {
1551 case HAMMER2_BREF_TYPE_DIRENT:
1552 case HAMMER2_BREF_TYPE_INODE:
1555 case HAMMER2_BREF_TYPE_DATA:
1556 hammer2_chain_delete(parent, chain,
1558 HAMMER2_DELETE_PERMANENT);
1561 chain = hammer2_chain_next(&parent, chain, &key_next,
1562 key_next, HAMMER2_KEY_MAX,
1564 HAMMER2_LOOKUP_NODATA |
1565 HAMMER2_LOOKUP_NODIRECT);
1569 * Reset to point at inode for following code, if necessary.
1571 if (parent->bref.type != HAMMER2_BREF_TYPE_INODE) {
1572 hammer2_chain_unlock(parent);
1573 hammer2_chain_drop(parent);
1574 parent = hammer2_inode_chain(xop->head.ip1,
1576 HAMMER2_RESOLVE_ALWAYS);
1577 kprintf("hammer2: TRUNCATE RESET on '%s'\n",
1578 parent->data->ipdata.filename);
1583 * Sync the inode meta-data, potentially clear the blockset area
1584 * of direct data so it can be used for blockrefs.
1587 error = hammer2_chain_modify(parent, xop->head.mtid, 0, 0);
1589 parent->data->ipdata.meta = xop->meta;
1590 if (xop->clear_directdata) {
1591 bzero(&parent->data->ipdata.u.blockset,
1592 sizeof(parent->data->ipdata.u.blockset));
1598 hammer2_chain_unlock(chain);
1599 hammer2_chain_drop(chain);
1602 hammer2_chain_unlock(parent);
1603 hammer2_chain_drop(parent);
1605 hammer2_xop_feed(&xop->head, NULL, clindex, error);