2 * Copyright (c) 2011-2013 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>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
18 * 3. Neither the name of The DragonFly Project nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific, prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <sys/cdefs.h>
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/types.h>
45 * Adding a ref to an inode is only legal if the inode already has at least
49 hammer2_inode_ref(hammer2_inode_t *ip)
51 atomic_add_int(&ip->refs, 1);
55 * Drop an inode reference, freeing the inode when the last reference goes
59 hammer2_inode_drop(hammer2_inode_t *ip)
63 hammer2_chain_t *chain;
70 if (atomic_cmpset_int(&ip->refs, 1, 0)) {
71 KKASSERT(ip->topo_cst.count == 0);
80 hammer2_chain_drop(chain);
83 * We have to drop pip (if non-NULL) to
84 * dispose of our implied reference from
85 * ip->pip. We can simply loop on it.
87 kfree(ip, hmp->minode);
89 /* continue with pip (can be NULL) */
92 if (atomic_cmpset_int(&ip->refs, refs, refs - 1))
99 * Get the vnode associated with the given inode, allocating the vnode if
100 * necessary. The vnode will be returned exclusively locked.
102 * The caller must lock the inode (shared or exclusive).
104 * Great care must be taken to avoid deadlocks and vnode acquisition/reclaim
108 hammer2_igetv(hammer2_inode_t *ip, int *errorp)
110 hammer2_inode_data_t *ipdata;
111 hammer2_pfsmount_t *pmp;
116 KKASSERT(pmp != NULL);
118 ipdata = &ip->chain->data->ipdata;
122 * Attempt to reuse an existing vnode assignment. It is
123 * possible to race a reclaim so the vget() may fail. The
124 * inode must be unlocked during the vget() to avoid a
125 * deadlock against a reclaim.
130 * Inode must be unlocked during the vget() to avoid
131 * possible deadlocks, but leave the ip ref intact.
133 * vnode is held to prevent destruction during the
134 * vget(). The vget() can still fail if we lost
135 * a reclaim race on the vnode.
137 vhold_interlocked(vp);
138 ostate = hammer2_inode_lock_temp_release(ip);
139 if (vget(vp, LK_EXCLUSIVE)) {
141 hammer2_inode_lock_restore(ip, ostate);
144 hammer2_inode_lock_restore(ip, ostate);
146 /* vp still locked and ref from vget */
148 kprintf("hammer2: igetv race %p/%p\n",
158 * No vnode exists, allocate a new vnode. Beware of
159 * allocation races. This function will return an
160 * exclusively locked and referenced vnode.
162 *errorp = getnewvnode(VT_HAMMER2, pmp->mp, &vp, 0, 0);
164 kprintf("hammer2: igetv getnewvnode failed %d\n",
171 * Lock the inode and check for an allocation race.
173 ostate = hammer2_inode_lock_upgrade(ip);
174 if (ip->vp != NULL) {
177 hammer2_inode_lock_restore(ip, ostate);
181 switch (ipdata->type) {
182 case HAMMER2_OBJTYPE_DIRECTORY:
185 case HAMMER2_OBJTYPE_REGFILE:
187 vinitvmio(vp, ipdata->size,
189 (int)ipdata->size & HAMMER2_LBUFMASK);
191 case HAMMER2_OBJTYPE_SOFTLINK:
193 * XXX for now we are using the generic file_read
194 * and file_write code so we need a buffer cache
198 vinitvmio(vp, ipdata->size,
200 (int)ipdata->size & HAMMER2_LBUFMASK);
204 panic("hammer2: unhandled objtype %d", ipdata->type);
208 if (ip == pmp->iroot)
209 vsetflags(vp, VROOT);
213 hammer2_inode_ref(ip); /* vp association */
214 hammer2_inode_lock_restore(ip, ostate);
219 * Return non-NULL vp and *errorp == 0, or NULL vp and *errorp != 0.
221 if (hammer2_debug & 0x0002) {
222 kprintf("igetv vp %p refs %d aux %d\n",
223 vp, vp->v_sysref.refcnt, vp->v_auxrefs);
229 * The passed-in chain must be locked and the returned inode will also be
230 * locked. A ref is added to both the chain and the inode.
232 * The hammer2_inode structure regulates the interface between the high level
233 * kernel VNOPS API and the filesystem backend (the chains).
235 * NOTE! This routine allocates the hammer2_inode structure
236 * unconditionally, and thus there might be several which
237 * are associated with the same chain. Particularly for hardlinks
238 * but this can also happen temporarily for normal files and
241 * WARNING! This routine sucks up the chain's lock (makes it part of the
242 * inode lock from the point of view of the inode lock API),
243 * so callers need to be careful.
245 * WARNING! The mount code is allowed to pass dip == NULL for iroot and
246 * is allowed to pass pmp == NULL and dip == NULL for sroot.
249 hammer2_inode_get(hammer2_mount_t *hmp, hammer2_pfsmount_t *pmp,
250 hammer2_inode_t *dip, hammer2_chain_t *chain)
252 hammer2_inode_t *nip;
254 KKASSERT(chain->bref.type == HAMMER2_BREF_TYPE_INODE);
256 nip = kmalloc(sizeof(*nip), hmp->minode, M_WAITOK | M_ZERO);
259 hammer2_chain_ref(chain); /* nip->chain */
260 nip->pip = dip; /* can be NULL */
262 hammer2_inode_ref(dip); /* ref dip for nip->pip */
268 * ref and lock on nip gives it state compatible to after a
269 * hammer2_inode_lock_ex() call.
272 ccms_cst_init(&nip->topo_cst, &nip->chain);
273 ccms_thread_lock(&nip->topo_cst, CCMS_STATE_EXCLUSIVE);
274 /* combination of thread lock and chain lock == inode lock */
280 * Put away an inode, unlocking it and disconnecting it from its chain.
282 * The inode must be exclusively locked on call and non-recursed, with
283 * at least 2 refs (one belonging to the exclusive lock, and one additional
284 * ref belonging to the caller).
286 * Upon return the inode typically has one ref remaining which the caller
290 hammer2_inode_put(hammer2_inode_t *ip)
292 hammer2_inode_t *pip;
293 hammer2_chain_t *chain;
296 * Disconnect and unlock chain
298 KKASSERT(ip->refs >= 2);
299 KKASSERT(ip->topo_cst.count == -1); /* one excl lock allowed */
300 if ((chain = ip->chain) != NULL) {
302 hammer2_inode_unlock_ex(ip);
303 hammer2_chain_unlock(chain); /* because ip->chain now NULL */
304 hammer2_chain_drop(chain); /* from *_get() */
310 if ((pip = ip->pip) != NULL) {
312 hammer2_inode_drop(pip);
317 * Create a new inode in the specified directory using the vattr to
318 * figure out the type of inode.
320 * If no error occurs the new inode with its chain locked is returned in
321 * *nipp, otherwise an error is returned and *nipp is set to NULL.
323 * If vap and/or cred are NULL the related fields are not set and the
324 * inode type defaults to a directory. This is used when creating PFSs
325 * under the super-root, so the inode number is set to 1 in this case.
327 * dip is not locked on entry.
330 hammer2_inode_create(hammer2_trans_t *trans, hammer2_inode_t *dip,
331 struct vattr *vap, struct ucred *cred,
332 const uint8_t *name, size_t name_len,
335 hammer2_inode_data_t *dipdata;
336 hammer2_inode_data_t *nipdata;
337 hammer2_mount_t *hmp;
338 hammer2_chain_t *chain;
339 hammer2_chain_t *parent;
340 hammer2_inode_t *nip;
349 lhc = hammer2_dirhash(name, name_len);
353 * Locate the inode or indirect block to create the new
354 * entry in. At the same time check for key collisions
355 * and iterate until we don't get one.
358 hammer2_inode_lock_ex(dip);
359 dipdata = &dip->chain->data->ipdata;
360 dip_uid = dipdata->uid;
361 dip_gid = dipdata->gid;
362 dip_mode = dipdata->mode;
364 parent = hammer2_chain_lookup_init(dip->chain, 0);
367 chain = hammer2_chain_lookup(&parent, lhc, lhc, 0);
370 if ((lhc & HAMMER2_DIRHASH_VISIBLE) == 0)
372 if ((lhc & HAMMER2_DIRHASH_LOMASK) == HAMMER2_DIRHASH_LOMASK)
374 hammer2_chain_unlock(chain);
379 error = hammer2_chain_create(trans, parent, &chain,
381 HAMMER2_BREF_TYPE_INODE,
382 HAMMER2_INODE_BYTES);
386 * Cleanup and handle retries.
388 if (error == EAGAIN) {
389 hammer2_chain_ref(parent);
390 hammer2_chain_lookup_done(parent);
391 hammer2_inode_unlock_ex(dip);
392 hammer2_chain_wait(parent);
393 hammer2_chain_drop(parent);
396 hammer2_chain_lookup_done(parent);
397 hammer2_inode_unlock_ex(dip);
400 KKASSERT(chain == NULL);
406 * Set up the new inode.
408 * NOTE: *_get() integrates chain's lock into the inode lock.
410 * NOTE: Only one new inode can currently be created per
411 * transaction. If the need arises we can adjust
412 * hammer2_trans_init() to allow more.
414 nip = hammer2_inode_get(dip->hmp, dip->pmp, dip, chain);
415 nipdata = &chain->data->ipdata;
418 KKASSERT(trans->inodes_created == 0);
419 nipdata->type = hammer2_get_obj_type(vap->va_type);
420 nipdata->inum = trans->sync_tid;
421 ++trans->inodes_created;
423 nipdata->type = HAMMER2_OBJTYPE_DIRECTORY;
426 nipdata->version = HAMMER2_INODE_VERSION_ONE;
427 hammer2_update_time(&nipdata->ctime);
428 nipdata->mtime = nipdata->ctime;
430 nipdata->mode = vap->va_mode;
434 xuid = hammer2_to_unix_xid(&dip_uid);
435 xuid = vop_helper_create_uid(dip->pmp->mp,
443 if (vap->va_vaflags & VA_UID_UUID_VALID)
444 nipdata->uid = vap->va_uid_uuid;
445 else if (vap->va_uid != (uid_t)VNOVAL)
446 hammer2_guid_to_uuid(&nipdata->uid, vap->va_uid);
448 hammer2_guid_to_uuid(&nipdata->uid, xuid);
450 if (vap->va_vaflags & VA_GID_UUID_VALID)
451 nipdata->gid = vap->va_gid_uuid;
452 else if (vap->va_gid != (gid_t)VNOVAL)
453 hammer2_guid_to_uuid(&nipdata->gid, vap->va_gid);
455 nipdata->gid = dip_gid;
459 * Regular files and softlinks allow a small amount of data to be
460 * directly embedded in the inode. This flag will be cleared if
461 * the size is extended past the embedded limit.
463 if (nipdata->type == HAMMER2_OBJTYPE_REGFILE ||
464 nipdata->type == HAMMER2_OBJTYPE_SOFTLINK) {
465 nipdata->op_flags |= HAMMER2_OPFLAG_DIRECTDATA;
468 KKASSERT(name_len < HAMMER2_INODE_MAXNAME);
469 bcopy(name, nipdata->filename, name_len);
470 nipdata->name_key = lhc;
471 nipdata->name_len = name_len;
477 * Create a duplicate of (ochain) in the specified target directory (dip).
478 * ochain must represent an inode. The new chain is returned locked and
479 * referenced and its filename is changed to a representation of the
480 * inode number "0xBLAH", as a hidden directory entry.
483 hammer2_inode_duplicate(hammer2_trans_t *trans, hammer2_chain_t *ochain,
484 hammer2_inode_t *dip, int *errorp)
486 hammer2_inode_data_t *nipdata;
487 hammer2_mount_t *hmp;
488 hammer2_chain_t *parent;
489 hammer2_chain_t *chain;
490 hammer2_chain_t *tmpchain;
492 hammer2_blockref_t bref;
496 lhc = ochain->data->ipdata.inum;
497 KKASSERT((lhc & HAMMER2_DIRHASH_VISIBLE) == 0);
500 * Locate the inode or indirect block to create the new
501 * entry in. lhc represents the inode number so there is
502 * no collision iteration.
504 * There should be no key collisions with invisible inode keys.
507 parent = hammer2_chain_lookup_init(dip->chain, 0);
508 chain = hammer2_chain_lookup(&parent, lhc, lhc, 0);
510 hammer2_chain_unlock(chain);
516 * Create entry in common parent directory.
519 KKASSERT(chain == NULL);
520 *errorp = hammer2_chain_create(trans, parent, &chain,
522 HAMMER2_BREF_TYPE_INODE,/* n/a */
523 HAMMER2_INODE_BYTES); /* n/a */
527 * Cleanup and handle retries.
529 if (*errorp == EAGAIN) {
530 hammer2_chain_ref(parent);
531 hammer2_chain_lookup_done(parent);
532 hammer2_chain_wait(parent);
533 hammer2_chain_drop(parent);
538 * Handle the error case
541 KKASSERT(chain == NULL);
542 hammer2_chain_lookup_done(parent);
547 * Use chain as a placeholder for our duplication.
549 * Gain a second lock on ochain for the duplication function to
550 * unlock, maintain the original lock across the calls.
552 * This is a bit messy.
554 hammer2_chain_delete(trans, parent, chain);
555 hammer2_chain_lock(ochain, HAMMER2_RESOLVE_ALWAYS);
557 bref = tmpchain->bref;
558 bref.key = lhc; /* key for create placeholder must match */
560 hammer2_chain_duplicate(trans, parent, chain->index, &tmpchain, &bref);
561 hammer2_chain_lookup_done(parent);
563 hammer2_chain_unlock(chain);
565 tmpchain = NULL; /* safety */
568 * Directory entries are inodes but this is a hidden hardlink
569 * target. The name isn't used but to ease debugging give it
570 * a name after its inode number.
572 hammer2_chain_modify(trans, chain, 0);
573 nipdata = &chain->data->ipdata;
574 ksnprintf(nipdata->filename, sizeof(nipdata->filename),
575 "0x%016jx", (intmax_t)nipdata->inum);
576 nipdata->name_len = strlen(nipdata->filename);
577 nipdata->name_key = lhc;
583 * Connect the target inode to the media topology at (dip, name, len).
584 * This function creates a directory entry and replace (*chainp).
586 * The caller usually holds the related inode exclusive locked through this
587 * call and is also responsible for replacing ip->chain after we return.
589 * If (*chainp) was marked DELETED then it represents a terminus inode
590 * with no other nlinks, we can simply duplicate the chain (in-memory
591 * chain structures cannot be moved within the in-memory topology, only
592 * duplicated, but the duplicate uses the same bref).
594 * if (*chainp) is not marked DELETED then it represents a hardlink
595 * terminus which still has a non-zero nlink count. Instead of duplicating
596 * it (which would be like a snapshot), we need to create a
597 * OBJTYPE_HARDLINK directory entry which references (*chainp)'s inode
598 * number and bump (*chainp)'s nlinks. In this situation we return
599 * the terminus as *chainp.
601 * (*chainp) is adjusted if necessary and returned locked. If different,
602 * the original (*chainp) is unlocked. Note that the (*chainp) that is
603 * returned is always the hardlink terminus (the actual inode), which
604 * might reside in some parent directory. It will not be the
605 * OBJTYPE_HARDLINK pointer.
607 * WARNING! The caller is likely holding ip/ip->chain locked exclusively.
608 * Replacing ip->chain here would create confusion so we leave
609 * it to the caller to do that.
611 * (The caller is expected to hold the related inode exclusively)
614 hammer2_inode_connect(hammer2_trans_t *trans, hammer2_inode_t *dip,
615 hammer2_chain_t **chainp,
616 const uint8_t *name, size_t name_len)
618 hammer2_inode_data_t *ipdata;
619 hammer2_mount_t *hmp;
620 hammer2_chain_t *nchain;
621 hammer2_chain_t *parent;
622 hammer2_chain_t *ochain;
632 * Since ochain is either disconnected from the topology or represents
633 * a hardlink terminus which is always a parent of or equal to dip,
634 * we should be able to safely lock dip->chain for our setup.
636 parent = hammer2_chain_lookup_init(dip->chain, 0);
638 lhc = hammer2_dirhash(name, name_len);
639 hlink = ((ochain->flags & HAMMER2_CHAIN_DELETED) == 0);
640 kprintf("reconnect hlink=%d name=%*.*s\n",
641 hlink, (int)name_len, (int)name_len, name);
644 * In fake mode flush oip so we can just snapshot it downbelow.
645 * A flush is not otherwise needed as the new chain inherits
646 * all active children of the old chain (they will share the same
649 if (hlink && hammer2_hardlink_enable < 0)
650 hammer2_chain_flush(trans, ochain);
653 * Locate the inode or indirect block to create the new
654 * entry in. At the same time check for key collisions
655 * and iterate until we don't get one.
659 nchain = hammer2_chain_lookup(&parent, lhc, lhc, 0);
662 if ((lhc & HAMMER2_DIRHASH_LOMASK) == HAMMER2_DIRHASH_LOMASK)
664 hammer2_chain_unlock(nchain);
670 * Passing a non-NULL chain to hammer2_chain_create() reconnects the
671 * existing chain instead of creating a new one. The chain's bref
672 * will be properly updated.
677 * Hardlink pointer needed, create totally fresh
680 KKASSERT(nchain == NULL);
681 error = hammer2_chain_create(trans, parent, &nchain,
683 HAMMER2_BREF_TYPE_INODE,
684 HAMMER2_INODE_BYTES);
687 * Original inode reconnected, duplicate as a
688 * new directory entry, leave unconnected and
689 * then call chain_create() to connect it.
693 hammer2_chain_duplicate(trans, NULL, -1, &nchain, NULL);
694 error = hammer2_chain_create(trans, parent, &nchain,
696 HAMMER2_BREF_TYPE_INODE,
697 HAMMER2_INODE_BYTES);
704 KKASSERT(error != EAGAIN);
705 hammer2_chain_lookup_done(parent);
709 * nchain should be NULL on error, leave ochain (== *chainp) alone.
712 KKASSERT(nchain == NULL);
717 * Directory entries are inodes so if the name has changed we have
718 * to update the inode.
720 * When creating an OBJTYPE_HARDLINK entry remember to unlock the
721 * chain, the caller will access the hardlink via the actual hardlink
722 * target file and not the hardlink pointer entry, so we must still
725 if (hlink && hammer2_hardlink_enable >= 0) {
727 * Create the HARDLINK pointer. oip represents the hardlink
728 * target in this situation.
730 * We will return ochain (the hardlink target).
732 hammer2_chain_modify(trans, nchain, 0);
733 KKASSERT(name_len < HAMMER2_INODE_MAXNAME);
734 ipdata = &nchain->data->ipdata;
735 bcopy(name, ipdata->filename, name_len);
736 ipdata->name_key = lhc;
737 ipdata->name_len = name_len;
738 ipdata->target_type = ochain->data->ipdata.type;
739 ipdata->type = HAMMER2_OBJTYPE_HARDLINK;
740 ipdata->inum = ochain->data->ipdata.inum;
742 kprintf("created hardlink %*.*s\n",
743 (int)name_len, (int)name_len, name);
744 hammer2_chain_unlock(nchain);
747 } else if (hlink && hammer2_hardlink_enable < 0) {
749 * Create a snapshot (hardlink fake mode for debugging).
750 * (ochain already flushed above so we can just copy the
753 * Since this is a snapshot we return nchain in the fake
756 hammer2_chain_modify(trans, nchain, 0);
757 KKASSERT(name_len < HAMMER2_INODE_MAXNAME);
758 ipdata = &nchain->data->ipdata;
759 *ipdata = ochain->data->ipdata;
760 bcopy(name, ipdata->filename, name_len);
761 ipdata->name_key = lhc;
762 ipdata->name_len = name_len;
763 kprintf("created fake hardlink %*.*s\n",
764 (int)name_len, (int)name_len, name);
767 * We are reconnecting a previously DELETED node in a new
768 * location. nchain is a duplication of the deleted node.
770 * We must fixup the name stored in oip.
772 hammer2_chain_modify(trans, nchain, 0);
773 ipdata = &nchain->data->ipdata;
775 if (ipdata->name_len != name_len ||
776 bcmp(ipdata->filename, name, name_len) != 0) {
777 KKASSERT(name_len < HAMMER2_INODE_MAXNAME);
778 bcopy(name, ipdata->filename, name_len);
779 ipdata->name_key = lhc;
780 ipdata->name_len = name_len;
786 * We are replacing ochain with nchain, unlock ochain. In the
787 * case where ochain is left unchanged the code above sets
788 * nchain to ochain and ochain to NULL, resulting in a NOP here.
791 hammer2_chain_unlock(ochain);
798 * Caller must hold exactly ONE exclusive lock on the inode. *nchainp
799 * must be exclusive locked (its own exclusive lock even if it is the
800 * same as ip->chain).
802 * This function replaces ip->chain. The exclusive lock on the passed
803 * nchain is inherited by the inode and the caller becomes responsible
804 * for unlocking it when the caller unlocks the inode.
806 * ochain was locked by the caller indirectly via the inode lock. Since
807 * ip->chain is being repointed, we become responsible for cleaning up
810 * Return *nchainp = NULL as a safety.
813 hammer2_inode_repoint(hammer2_inode_t *ip, hammer2_inode_t *pip,
814 hammer2_chain_t *nchain)
816 hammer2_chain_t *ochain;
817 hammer2_inode_t *opip;
820 * ip->chain points to the hardlink target, not the hardlink psuedo
821 * inode. Do not repoint nchain to the pseudo-node.
823 if (nchain->data->ipdata.type == HAMMER2_OBJTYPE_HARDLINK)
827 * Repoint ip->chain if necessary.
829 * (Inode must be locked exclusively by parent)
832 if (ochain != nchain) {
833 hammer2_chain_ref(nchain); /* for ip->chain */
836 hammer2_chain_unlock(ochain);
837 hammer2_chain_drop(ochain); /* for ip->chain */
839 /* replace locked chain in ip (additional lock) */
840 hammer2_chain_lock(nchain, HAMMER2_RESOLVE_ALWAYS);
842 if (ip->pip != pip) {
845 hammer2_inode_ref(pip);
848 hammer2_inode_drop(opip);
853 * Unlink the file from the specified directory inode. The directory inode
854 * does not need to be locked. The caller should pass a non-NULL (ip)
855 * representing the object being removed only if the related vnode is
856 * potentially inactive (not referenced in the caller's active path),
857 * so we can vref/vrele it to trigger the VOP_INACTIVE path and properly
860 * isdir determines whether a directory/non-directory check should be made.
861 * No check is made if isdir is set to -1.
863 * NOTE! This function does not prevent the underlying file from still
864 * being used if it has other refs (such as from an inode, or if it's
865 * chain is manually held). However, the caller is responsible for
866 * fixing up ip->chain if e.g. a rename occurs (see chain_duplicate()).
869 hammer2_unlink_file(hammer2_trans_t *trans, hammer2_inode_t *dip,
870 const uint8_t *name, size_t name_len, int isdir)
872 hammer2_inode_data_t *ipdata;
873 hammer2_mount_t *hmp;
874 hammer2_chain_t *parent;
875 hammer2_chain_t *ochain;
876 hammer2_chain_t *chain;
877 hammer2_chain_t *dparent;
878 hammer2_chain_t *dchain;
888 lhc = hammer2_dirhash(name, name_len);
891 * Search for the filename in the directory
893 hammer2_inode_lock_ex(dip);
895 parent = hammer2_chain_lookup_init(dip->chain, 0);
896 chain = hammer2_chain_lookup(&parent,
897 lhc, lhc + HAMMER2_DIRHASH_LOMASK,
900 if (chain->bref.type == HAMMER2_BREF_TYPE_INODE &&
901 name_len == chain->data->ipdata.name_len &&
902 bcmp(name, chain->data->ipdata.filename, name_len) == 0) {
905 chain = hammer2_chain_next(&parent, chain,
906 lhc, lhc + HAMMER2_DIRHASH_LOMASK,
909 hammer2_inode_unlock_ex(dip); /* retain parent */
912 * Not found or wrong type (isdir < 0 disables the type check).
913 * If a hardlink pointer, type checks use the hardlink target.
919 if ((type = chain->data->ipdata.type) == HAMMER2_OBJTYPE_HARDLINK)
920 type = chain->data->ipdata.target_type;
922 if (type == HAMMER2_OBJTYPE_DIRECTORY && isdir == 0) {
926 if (type != HAMMER2_OBJTYPE_DIRECTORY && isdir == 1) {
932 * Hardlink must be resolved. We can't hold parent locked while we
933 * do this or we could deadlock.
935 * On success chain will be adjusted to point at the hardlink target
936 * and ochain will point to the hardlink pointer in the original
937 * directory. Otherwise chain remains pointing to the original.
939 if (chain->data->ipdata.type == HAMMER2_OBJTYPE_HARDLINK) {
940 KKASSERT(parent_ref == 0);
941 hammer2_chain_unlock(parent);
943 error = hammer2_hardlink_find(dip, &chain, &ochain);
947 * If this is a directory the directory must be empty. However, if
948 * isdir < 0 we are doing a rename and the directory does not have
951 * NOTE: We check the full key range here which covers both visible
952 * and invisible entries. Theoretically there should be no
953 * invisible (hardlink target) entries if there are no visible
956 if (type == HAMMER2_OBJTYPE_DIRECTORY && isdir >= 0) {
957 dparent = hammer2_chain_lookup_init(chain, 0);
958 dchain = hammer2_chain_lookup(&dparent,
959 0, (hammer2_key_t)-1,
960 HAMMER2_LOOKUP_NODATA);
962 hammer2_chain_unlock(dchain);
963 hammer2_chain_lookup_done(dparent);
967 hammer2_chain_lookup_done(dparent);
973 * Ok, we can now unlink the chain. We always decrement nlinks even
974 * if the entry can be deleted in case someone has the file open and
977 * The chain itself will no longer be in the on-media topology but
978 * can still be flushed to the media (e.g. if an open descriptor
979 * remains). When the last vnode/ip ref goes away the chain will
980 * be marked unmodified, avoiding any further (now unnecesary) I/O.
982 * A non-NULL ochain indicates a hardlink.
986 * Delete the original hardlink pointer.
988 * NOTE: parent from above is NULL when ochain != NULL
989 * so we can reuse it.
991 hammer2_chain_lock(ochain, HAMMER2_RESOLVE_ALWAYS);
994 parent = ochain->parent;
995 hammer2_chain_ref(parent);
996 hammer2_chain_unlock(ochain);
997 hammer2_chain_lock(parent, HAMMER2_RESOLVE_ALWAYS);
998 hammer2_chain_lock(ochain, HAMMER2_RESOLVE_ALWAYS);
999 if (ochain->parent == parent)
1001 hammer2_chain_unlock(parent);
1002 hammer2_chain_drop(parent);
1005 hammer2_chain_delete(trans, parent, ochain);
1006 hammer2_chain_unlock(ochain);
1007 hammer2_chain_unlock(parent);
1008 hammer2_chain_drop(parent);
1012 * Then decrement nlinks on hardlink target, deleting
1013 * the target when nlinks drops to 0.
1015 if (chain->data->ipdata.nlinks == 1) {
1016 dparent = chain->parent;
1017 hammer2_chain_ref(chain);
1018 hammer2_chain_unlock(chain);
1019 hammer2_chain_lock(dparent, HAMMER2_RESOLVE_ALWAYS);
1020 hammer2_chain_lock(chain, HAMMER2_RESOLVE_ALWAYS);
1021 hammer2_chain_drop(chain);
1022 hammer2_chain_modify(trans, chain, 0);
1023 --chain->data->ipdata.nlinks;
1024 hammer2_chain_delete(trans, dparent, chain);
1025 hammer2_chain_unlock(dparent);
1027 hammer2_chain_modify(trans, chain, 0);
1028 --chain->data->ipdata.nlinks;
1032 * Otherwise this was not a hardlink and we can just
1033 * remove the entry and decrement nlinks.
1035 * NOTE: *_get() integrates chain's lock into the inode lock.
1037 ipdata = &chain->data->ipdata;
1038 hammer2_chain_modify(trans, chain, 0);
1040 hammer2_chain_delete(trans, parent, chain);
1046 hammer2_chain_unlock(chain);
1048 hammer2_chain_lookup_done(parent);
1050 hammer2_chain_drop(parent);
1053 hammer2_chain_drop(ochain);
1059 * Calculate the allocation size for the file fragment straddling EOF
1062 hammer2_inode_calc_alloc(hammer2_key_t filesize)
1064 int frag = (int)filesize & HAMMER2_PBUFMASK;
1069 for (radix = HAMMER2_MINALLOCRADIX; frag > (1 << radix); ++radix)
1075 * Given an exclusively locked inode we consolidate its chain for hardlink
1076 * creation, adding (nlinks) to the file's link count and potentially
1077 * relocating the inode to a directory common to ip->pip and tdip.
1079 * Returns a locked chain in (*chainp) (the chain's lock is in addition to
1080 * any lock it might already have due to the inode being locked). *chainp
1081 * is set unconditionally and its previous contents can be garbage.
1083 * The caller is responsible for replacing ip->chain, not us. For certain
1084 * operations such as renames the caller may do additional manipulation
1085 * of the chain before replacing ip->chain.
1088 hammer2_hardlink_consolidate(hammer2_trans_t *trans, hammer2_inode_t *ip,
1089 hammer2_chain_t **chainp,
1090 hammer2_inode_t *tdip, int nlinks)
1092 hammer2_inode_data_t *ipdata;
1093 hammer2_mount_t *hmp;
1094 hammer2_inode_t *fdip;
1095 hammer2_inode_t *cdip;
1096 hammer2_chain_t *chain;
1097 hammer2_chain_t *nchain;
1098 hammer2_chain_t *parent;
1102 * Extra lock on chain so it can be returned locked.
1107 error = hammer2_chain_lock(chain, HAMMER2_RESOLVE_ALWAYS);
1108 KKASSERT(error == 0);
1110 if (nlinks == 0 && /* no hardlink needed */
1111 (chain->data->ipdata.name_key & HAMMER2_DIRHASH_VISIBLE)) {
1115 if (hammer2_hardlink_enable < 0) { /* fake hardlinks */
1120 if (hammer2_hardlink_enable == 0) { /* disallow hardlinks */
1121 hammer2_chain_unlock(chain);
1127 * cdip will be returned with a ref, but not locked.
1130 cdip = hammer2_inode_common_parent(fdip, tdip);
1133 * If no change in the hardlink's target directory is required and
1134 * this is already a hardlink target, all we need to do is adjust
1138 (chain->data->ipdata.name_key & HAMMER2_DIRHASH_VISIBLE) == 0) {
1140 hammer2_chain_modify(trans, chain, 0);
1141 chain->data->ipdata.nlinks += nlinks;
1149 * We either have to move an existing hardlink target or we have
1150 * to create a fresh hardlink target.
1152 * Hardlink targets are hidden inodes in a parent directory common
1153 * to all directory entries referencing the hardlink.
1155 nchain = hammer2_inode_duplicate(trans, chain, cdip, &error);
1159 * Bump nlinks on duplicated hidden inode, repoint
1162 hammer2_chain_modify(trans, nchain, 0);
1163 nchain->data->ipdata.nlinks += nlinks;
1164 hammer2_inode_repoint(ip, cdip, nchain);
1167 * If the old chain is not a hardlink target then replace
1168 * it with a OBJTYPE_HARDLINK pointer.
1170 * If the old chain IS a hardlink target then delete it.
1172 if (chain->data->ipdata.name_key & HAMMER2_DIRHASH_VISIBLE) {
1173 hammer2_chain_modify(trans, chain, 0);
1174 ipdata = &chain->data->ipdata;
1175 ipdata->target_type = ipdata->type;
1176 ipdata->type = HAMMER2_OBJTYPE_HARDLINK;
1184 bzero(&ipdata->uid, sizeof(ipdata->uid));
1185 bzero(&ipdata->gid, sizeof(ipdata->gid));
1186 ipdata->op_flags = HAMMER2_OPFLAG_DIRECTDATA;
1187 ipdata->cap_flags = 0;
1191 ipdata->iparent = 0; /* XXX */
1192 ipdata->pfs_type = 0;
1193 ipdata->pfs_inum = 0;
1194 bzero(&ipdata->pfs_clid, sizeof(ipdata->pfs_clid));
1195 bzero(&ipdata->pfs_fsid, sizeof(ipdata->pfs_fsid));
1196 ipdata->data_quota = 0;
1197 ipdata->data_count = 0;
1198 ipdata->inode_quota = 0;
1199 ipdata->inode_count = 0;
1200 ipdata->attr_tid = 0;
1201 ipdata->dirent_tid = 0;
1202 bzero(&ipdata->u, sizeof(ipdata->u));
1203 /* XXX transaction ids */
1205 kprintf("DELETE INVISIBLE\n");
1207 parent = chain->parent;
1208 hammer2_chain_ref(parent);
1209 hammer2_chain_ref(chain);
1210 hammer2_chain_unlock(chain);
1211 hammer2_chain_lock(parent,
1212 HAMMER2_RESOLVE_ALWAYS);
1213 hammer2_chain_lock(chain,
1214 HAMMER2_RESOLVE_ALWAYS);
1215 hammer2_chain_drop(chain);
1216 if (chain->parent == parent)
1218 hammer2_chain_unlock(parent);
1219 hammer2_chain_drop(parent);
1221 hammer2_chain_delete(trans, parent, chain);
1222 hammer2_chain_unlock(parent);
1223 hammer2_chain_drop(parent);
1227 * Return the new chain.
1229 hammer2_chain_unlock(chain);
1235 hammer2_chain_unlock(chain);
1240 * Cleanup, chain/nchain already dealt with.
1243 hammer2_inode_drop(cdip);
1249 * If (*ochainp) is non-NULL it points to the forward OBJTYPE_HARDLINK
1250 * inode while (*chainp) points to the resolved (hidden hardlink
1251 * target) inode. In this situation when nlinks is 1 we wish to
1252 * deconsolidate the hardlink, moving it back to the directory that now
1253 * represents the only remaining link.
1256 hammer2_hardlink_deconsolidate(hammer2_trans_t *trans,
1257 hammer2_inode_t *dip,
1258 hammer2_chain_t **chainp,
1259 hammer2_chain_t **ochainp)
1261 if (*ochainp == NULL)
1268 * The caller presents a locked *chainp pointing to a HAMMER2_BREF_TYPE_INODE
1269 * with an obj_type of HAMMER2_OBJTYPE_HARDLINK. This routine will gobble
1270 * the *chainp and return a new locked *chainp representing the file target
1271 * (the original *chainp will be unlocked).
1273 * When a match is found the chain representing the original HARDLINK
1274 * will be returned in *ochainp with a ref, but not locked.
1276 * When no match is found *chainp is set to NULL and EIO is returned.
1277 * (*ochainp) will still be set to the original chain with a ref but not
1281 hammer2_hardlink_find(hammer2_inode_t *dip, hammer2_chain_t **chainp,
1282 hammer2_chain_t **ochainp)
1284 hammer2_chain_t *chain = *chainp;
1285 hammer2_chain_t *parent;
1286 hammer2_inode_t *ip;
1287 hammer2_inode_t *pip;
1291 hammer2_inode_ref(pip); /* for loop */
1292 hammer2_chain_ref(chain); /* for (*ochainp) */
1297 * Locate the hardlink. pip is referenced and not locked,
1302 lhc = chain->data->ipdata.inum;
1303 hammer2_chain_unlock(chain);
1306 while ((ip = pip) != NULL) {
1307 hammer2_inode_lock_ex(ip);
1308 parent = hammer2_chain_lookup_init(ip->chain, 0);
1309 hammer2_inode_drop(ip); /* loop */
1310 KKASSERT(parent->bref.type == HAMMER2_BREF_TYPE_INODE);
1311 chain = hammer2_chain_lookup(&parent, lhc, lhc, 0);
1312 hammer2_chain_lookup_done(parent);
1315 pip = ip->pip; /* safe, ip held locked */
1317 hammer2_inode_ref(pip); /* loop */
1318 hammer2_inode_unlock_ex(ip);
1322 * chain is locked, ip is locked. Unlock ip, return the locked
1323 * chain. *ipp is already set w/a ref count and not locked.
1325 * (parent is already unlocked).
1328 hammer2_inode_unlock_ex(ip);
1331 KKASSERT(chain->bref.type == HAMMER2_BREF_TYPE_INODE);
1332 /* already locked */
1340 * Find the directory common to both fdip and tdip, hold and return
1344 hammer2_inode_common_parent(hammer2_inode_t *fdip, hammer2_inode_t *tdip)
1346 hammer2_inode_t *scan1;
1347 hammer2_inode_t *scan2;
1350 * We used to have a depth field but it complicated matters too
1351 * much for directory renames. So now its ugly. Check for
1352 * simple cases before giving up and doing it the expensive way.
1354 * XXX need a bottom-up topology stability lock
1356 if (fdip == tdip || fdip == tdip->pip) {
1357 hammer2_inode_ref(fdip);
1360 if (fdip->pip == tdip) {
1361 hammer2_inode_ref(tdip);
1368 for (scan1 = fdip; scan1->pmp == fdip->pmp; scan1 = scan1->pip) {
1370 while (scan2->pmp == tdip->pmp) {
1371 if (scan1 == scan2) {
1372 hammer2_inode_ref(scan1);
1378 panic("hammer2_inode_common_parent: no common parent %p %p\n",