2 * Copyright (c) 2011-2012 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 hammer2_chain_ref(ip->hmp, &ip->chain);
55 * Drop an inode reference, freeing the inode when the last reference goes
59 hammer2_inode_drop(hammer2_inode_t *ip)
61 hammer2_chain_drop(ip->hmp, &ip->chain);
65 * Get the vnode associated with the given inode, allocating the vnode if
68 * Great care must be taken to avoid deadlocks and vnode acquisition/reclaim
71 * The vnode will be returned exclusively locked and referenced. The
72 * reference on the vnode prevents it from being reclaimed.
74 * The inode (ip) must be referenced by the caller and not locked to avoid
75 * it getting ripped out from under us or deadlocked.
78 hammer2_igetv(hammer2_inode_t *ip, int *errorp)
81 hammer2_pfsmount_t *pmp;
84 KKASSERT(pmp != NULL);
89 * Attempt to reuse an existing vnode assignment. It is
90 * possible to race a reclaim so the vget() may fail. The
91 * inode must be unlocked during the vget() to avoid a
92 * deadlock against a reclaim.
97 * Lock the inode and check for a reclaim race
99 hammer2_inode_lock_ex(ip);
101 hammer2_inode_unlock_ex(ip);
106 * Inode must be unlocked during the vget() to avoid
107 * possible deadlocks, vnode is held to prevent
108 * destruction during the vget(). The vget() can
109 * still fail if we lost a reclaim race on the vnode.
111 vhold_interlocked(vp);
112 hammer2_inode_unlock_ex(ip);
113 if (vget(vp, LK_EXCLUSIVE)) {
118 /* vp still locked and ref from vget */
124 * No vnode exists, allocate a new vnode. Beware of
125 * allocation races. This function will return an
126 * exclusively locked and referenced vnode.
128 *errorp = getnewvnode(VT_HAMMER2, pmp->mp, &vp, 0, 0);
135 * Lock the inode and check for an allocation race.
137 hammer2_inode_lock_ex(ip);
138 if (ip->vp != NULL) {
141 hammer2_inode_unlock_ex(ip);
145 switch (ip->ip_data.type) {
146 case HAMMER2_OBJTYPE_DIRECTORY:
149 case HAMMER2_OBJTYPE_REGFILE:
151 vinitvmio(vp, ip->ip_data.size,
153 (int)ip->ip_data.size & HAMMER2_LBUFMASK);
155 case HAMMER2_OBJTYPE_SOFTLINK:
157 * XXX for now we are using the generic file_read
158 * and file_write code so we need a buffer cache
162 vinitvmio(vp, ip->ip_data.size,
164 (int)ip->ip_data.size & HAMMER2_LBUFMASK);
168 panic("hammer2: unhandled objtype %d",
173 if (ip == pmp->iroot)
174 vsetflags(vp, VROOT);
178 hammer2_chain_ref(ip->hmp, &ip->chain); /* vp association */
179 hammer2_inode_unlock_ex(ip);
184 * Return non-NULL vp and *errorp == 0, or NULL vp and *errorp != 0.
186 if (hammer2_debug & 0x0002) {
187 kprintf("igetv vp %p refs %d aux %d\n",
188 vp, vp->v_sysref.refcnt, vp->v_auxrefs);
194 * Create a new inode in the specified directory using the vattr to
195 * figure out the type of inode.
197 * If no error occurs the new inode with its chain locked is returned in
198 * *nipp, otherwise an error is returned and *nipp is set to NULL.
200 * If vap and/or cred are NULL the related fields are not set and the
201 * inode type defaults to a directory. This is used when creating PFSs
202 * under the super-root, so the inode number is set to 1 in this case.
205 hammer2_inode_create(hammer2_inode_t *dip,
206 struct vattr *vap, struct ucred *cred,
207 const uint8_t *name, size_t name_len,
208 hammer2_inode_t **nipp)
210 hammer2_mount_t *hmp = dip->hmp;
211 hammer2_chain_t *chain;
212 hammer2_chain_t *parent;
213 hammer2_inode_t *nip;
218 lhc = hammer2_dirhash(name, name_len);
221 * Locate the inode or indirect block to create the new
222 * entry in. At the same time check for key collisions
223 * and iterate until we don't get one.
225 parent = &dip->chain;
226 hammer2_chain_lock(hmp, parent, HAMMER2_RESOLVE_ALWAYS);
230 chain = hammer2_chain_lookup(hmp, &parent, lhc, lhc, 0);
233 if ((lhc & HAMMER2_DIRHASH_VISIBLE) == 0)
235 if ((lhc & HAMMER2_DIRHASH_LOMASK) == HAMMER2_DIRHASH_LOMASK)
237 hammer2_chain_unlock(hmp, chain);
242 chain = hammer2_chain_create(hmp, parent, NULL, lhc, 0,
243 HAMMER2_BREF_TYPE_INODE,
244 HAMMER2_INODE_BYTES);
248 hammer2_chain_unlock(hmp, parent);
251 * Handle the error case
254 KKASSERT(chain == NULL);
260 * Set up the new inode
265 hammer2_voldata_lock(hmp);
267 nip->ip_data.type = hammer2_get_obj_type(vap->va_type);
268 nip->ip_data.inum = hmp->voldata.alloc_tid++;
269 /* XXX modify/lock */
271 nip->ip_data.type = HAMMER2_OBJTYPE_DIRECTORY;
272 nip->ip_data.inum = 1;
274 hammer2_voldata_unlock(hmp);
275 nip->ip_data.version = HAMMER2_INODE_VERSION_ONE;
276 hammer2_update_time(&nip->ip_data.ctime);
277 nip->ip_data.mtime = nip->ip_data.ctime;
279 nip->ip_data.mode = vap->va_mode;
280 nip->ip_data.nlinks = 1;
283 xuid = hammer2_to_unix_xid(&dip->ip_data.uid);
284 xuid = vop_helper_create_uid(dip->pmp->mp,
292 if (vap->va_vaflags & VA_UID_UUID_VALID)
293 nip->ip_data.uid = vap->va_uid_uuid;
294 else if (vap->va_uid != (uid_t)VNOVAL)
295 hammer2_guid_to_uuid(&nip->ip_data.uid, vap->va_uid);
297 hammer2_guid_to_uuid(&nip->ip_data.uid, xuid);
299 if (vap->va_vaflags & VA_GID_UUID_VALID)
300 nip->ip_data.gid = vap->va_gid_uuid;
301 else if (vap->va_gid != (gid_t)VNOVAL)
302 hammer2_guid_to_uuid(&nip->ip_data.gid, vap->va_gid);
304 nip->ip_data.gid = dip->ip_data.gid;
308 * Regular files and softlinks allow a small amount of data to be
309 * directly embedded in the inode. This flag will be cleared if
310 * the size is extended past the embedded limit.
312 if (nip->ip_data.type == HAMMER2_OBJTYPE_REGFILE ||
313 nip->ip_data.type == HAMMER2_OBJTYPE_SOFTLINK) {
314 nip->ip_data.op_flags |= HAMMER2_OPFLAG_DIRECTDATA;
317 KKASSERT(name_len < HAMMER2_INODE_MAXNAME);
318 bcopy(name, nip->ip_data.filename, name_len);
319 nip->ip_data.name_key = lhc;
320 nip->ip_data.name_len = name_len;
326 * Duplicate the specified existing inode in the specified target directory.
327 * If name is NULL the inode is duplicated as a hidden directory entry.
329 * Returns the new inode. The old inode is left alone.
332 hammer2_inode_duplicate(hammer2_inode_t *dip, hammer2_inode_t *oip,
333 hammer2_inode_t **nipp,
334 const uint8_t *name, size_t name_len)
336 hammer2_mount_t *hmp = dip->hmp;
337 hammer2_inode_t *nip;
338 hammer2_chain_t *parent;
339 hammer2_chain_t *chain;
340 hammer2_chain_t *scan;
345 lhc = hammer2_dirhash(name, name_len);
347 lhc = oip->ip_data.inum;
348 KKASSERT((lhc & HAMMER2_DIRHASH_VISIBLE) == 0);
352 * Locate the inode or indirect block to create the new
353 * entry in. At the same time check for key collisions
354 * and iterate until we don't get one.
357 parent = &dip->chain;
358 hammer2_chain_lock(hmp, parent, HAMMER2_RESOLVE_ALWAYS);
362 chain = hammer2_chain_lookup(hmp, &parent, lhc, lhc, 0);
365 if ((lhc & HAMMER2_DIRHASH_LOMASK) == HAMMER2_DIRHASH_LOMASK)
367 hammer2_chain_unlock(hmp, chain);
373 * Passing a non-NULL chain to hammer2_chain_create() reconnects the
374 * existing chain instead of creating a new one. The chain's bref
375 * will be properly updated.
378 chain = hammer2_chain_create(hmp, parent, NULL, lhc, 0,
379 HAMMER2_BREF_TYPE_INODE /* n/a */,
380 HAMMER2_INODE_BYTES); /* n/a */
384 hammer2_chain_unlock(hmp, parent);
387 * Handle the error case
390 KKASSERT(chain == NULL);
394 hammer2_chain_modify(hmp, chain, 0);
395 nip->ip_data = oip->ip_data;
398 * XXX This is currently a horrible hack. Well, if we wanted to
399 * duplicate a file, i.e. as in a snapshot, we definitely
400 * would have to flush it first.
402 * For hardlink target generation we can theoretically move any
403 * active chain structures without flushing, but that gets really
404 * iffy for code which follows chain->parent and ip->pip links.
406 * XXX only works with files. Duplicating a directory hierarchy
407 * requires a flush but doesn't deal with races post-flush.
408 * Well, it would work I guess, but you might catch some files
411 * We cannot leave oip with any in-memory chains because (for a
412 * hardlink), oip will become a OBJTYPE_HARDLINK which is just a
413 * pointer to the real hardlink's inum and can't have any sub-chains.
415 hammer2_inode_lock_ex(oip);
416 hammer2_chain_flush(hmp, &oip->chain, 0);
417 hammer2_inode_unlock_ex(oip);
418 KKASSERT(SPLAY_EMPTY(&oip->chain.shead));
422 * Directory entries are inodes so if the name has changed
423 * we have to update the inode.
425 KKASSERT(name_len < HAMMER2_INODE_MAXNAME);
426 bcopy(name, nip->ip_data.filename, name_len);
427 nip->ip_data.name_key = lhc;
428 nip->ip_data.name_len = name_len;
431 * Directory entries are inodes but this is a hidden hardlink
432 * target. The name isn't used but to ease debugging give it
433 * a name after its inode number.
435 ksnprintf(nip->ip_data.filename, sizeof(nip->ip_data.filename),
436 "0x%016jx", (intmax_t)nip->ip_data.inum);
437 nip->ip_data.name_len = strlen(nip->ip_data.filename);
438 nip->ip_data.name_key = lhc;
447 * Connect inode (oip) to the specified directory using the specified name.
448 * (oip) must be locked.
450 * If (oip) is not currently connected we simply connect it up.
452 * If (oip) is already connected we create a OBJTYPE_HARDLINK entry which
453 * points to (oip)'s inode number. (oip) is expected to be the terminus of
454 * the hardlink sitting as a hidden file in a common parent directory
455 * in this situation (thus the lock order is correct).
458 hammer2_inode_connect(hammer2_inode_t *dip, hammer2_inode_t *oip,
459 const uint8_t *name, size_t name_len)
461 hammer2_mount_t *hmp = dip->hmp;
462 hammer2_chain_t *chain;
463 hammer2_chain_t *parent;
464 hammer2_inode_t *nip;
469 lhc = hammer2_dirhash(name, name_len);
470 hlink = ((oip->chain.flags & HAMMER2_CHAIN_DELETED) == 0);
473 * Locate the inode or indirect block to create the new
474 * entry in. At the same time check for key collisions
475 * and iterate until we don't get one.
477 parent = &dip->chain;
478 hammer2_chain_lock(hmp, parent, HAMMER2_RESOLVE_ALWAYS);
482 chain = hammer2_chain_lookup(hmp, &parent, lhc, lhc, 0);
485 if ((lhc & HAMMER2_DIRHASH_LOMASK) == HAMMER2_DIRHASH_LOMASK)
487 hammer2_chain_unlock(hmp, chain);
493 * Passing a non-NULL chain to hammer2_chain_create() reconnects the
494 * existing chain instead of creating a new one. The chain's bref
495 * will be properly updated.
499 chain = hammer2_chain_create(hmp, parent,
501 HAMMER2_BREF_TYPE_INODE,
502 HAMMER2_INODE_BYTES);
504 chain = hammer2_chain_create(hmp, parent,
506 HAMMER2_BREF_TYPE_INODE,
507 HAMMER2_INODE_BYTES);
509 KKASSERT(chain == &oip->chain);
514 hammer2_chain_unlock(hmp, parent);
517 * Handle the error case
520 KKASSERT(chain == NULL);
525 * Directory entries are inodes so if the name has changed we have
526 * to update the inode.
528 * When creating an OBJTYPE_HARDLINK entry remember to unlock the
529 * chain, the caller will access the hardlink via the actual hardlink
530 * target file and not the hardlink pointer entry.
534 * Create the HARDLINK pointer. oip represents the hardlink
535 * target in this situation.
538 hammer2_chain_modify(hmp, chain, 0);
539 KKASSERT(name_len < HAMMER2_INODE_MAXNAME);
540 bcopy(name, nip->ip_data.filename, name_len);
541 nip->ip_data.name_key = lhc;
542 nip->ip_data.name_len = name_len;
543 nip->ip_data.target_type = oip->ip_data.type;
544 nip->ip_data.type = HAMMER2_OBJTYPE_HARDLINK;
545 nip->ip_data.inum = oip->ip_data.inum;
546 nip->ip_data.nlinks = 1;
547 kprintf("created hardlink %*.*s\n",
548 (int)name_len, (int)name_len, name);
549 hammer2_chain_unlock(hmp, chain);
552 * The name may have changed on reconnect, adjust oip.
554 * We are using oip as chain, already locked by caller,
557 hammer2_chain_modify(hmp, chain, 0);
558 if (oip->ip_data.name_len != name_len ||
559 bcmp(oip->ip_data.filename, name, name_len) != 0) {
560 KKASSERT(name_len < HAMMER2_INODE_MAXNAME);
561 bcopy(name, oip->ip_data.filename, name_len);
562 oip->ip_data.name_key = lhc;
563 oip->ip_data.name_len = name_len;
565 oip->ip_data.nlinks = 1;
572 * Unlink the file from the specified directory inode. The directory inode
573 * does not need to be locked.
575 * isdir determines whether a directory/non-directory check should be made.
576 * No check is made if isdir is set to -1.
579 hammer2_unlink_file(hammer2_inode_t *dip,
580 const uint8_t *name, size_t name_len, int isdir)
582 hammer2_mount_t *hmp;
583 hammer2_chain_t *parent;
584 hammer2_chain_t *chain;
585 hammer2_chain_t *dparent;
586 hammer2_chain_t *dchain;
589 hammer2_inode_t *oip;
596 lhc = hammer2_dirhash(name, name_len);
599 * Search for the filename in the directory
601 parent = &dip->chain;
602 hammer2_chain_lock(hmp, parent, HAMMER2_RESOLVE_ALWAYS);
603 chain = hammer2_chain_lookup(hmp, &parent,
604 lhc, lhc + HAMMER2_DIRHASH_LOMASK,
607 if (chain->bref.type == HAMMER2_BREF_TYPE_INODE &&
609 name_len == chain->data->ipdata.name_len &&
610 bcmp(name, chain->data->ipdata.filename, name_len) == 0) {
613 chain = hammer2_chain_next(hmp, &parent, chain,
614 lhc, lhc + HAMMER2_DIRHASH_LOMASK,
619 * Not found or wrong type (isdir < 0 disables the type check).
622 hammer2_chain_unlock(hmp, parent);
625 if ((type = chain->data->ipdata.type) == HAMMER2_OBJTYPE_HARDLINK)
626 type = chain->data->ipdata.target_type;
628 if (type == HAMMER2_OBJTYPE_DIRECTORY && isdir == 0) {
632 if (type != HAMMER2_OBJTYPE_DIRECTORY && isdir == 1) {
638 * Hardlink must be resolved. We can't hold parent locked while we
639 * do this or we could deadlock.
641 if (chain->data->ipdata.type == HAMMER2_OBJTYPE_HARDLINK) {
642 hammer2_chain_unlock(hmp, parent);
644 error = hammer2_hardlink_find(dip, &chain, &oip);
648 * If this is a directory the directory must be empty. However, if
649 * isdir < 0 we are doing a rename and the directory does not have
652 if (type == HAMMER2_OBJTYPE_DIRECTORY && isdir >= 0) {
654 hammer2_chain_lock(hmp, dparent, HAMMER2_RESOLVE_ALWAYS);
655 dchain = hammer2_chain_lookup(hmp, &dparent,
656 0, (hammer2_key_t)-1,
657 HAMMER2_LOOKUP_NODATA);
659 hammer2_chain_unlock(hmp, dchain);
660 hammer2_chain_unlock(hmp, dparent);
664 hammer2_chain_unlock(hmp, dparent);
670 * Ok, we can now unlink the chain. We always decrement nlinks even
671 * if the entry can be deleted in case someone has the file open and
674 * The chain itself will no longer have a media reference. When the
675 * last vnode/ip ref goes away the chain will be marked unmodified,
676 * avoiding unnecessary I/O.
680 * If this was a hardlink we first delete the hardlink
683 parent = oip->chain.parent;
684 hammer2_chain_lock(hmp, parent, HAMMER2_RESOLVE_ALWAYS);
685 hammer2_chain_lock(hmp, &oip->chain, HAMMER2_RESOLVE_ALWAYS);
686 hammer2_chain_delete(hmp, parent, &oip->chain);
687 hammer2_chain_unlock(hmp, &oip->chain);
688 hammer2_chain_unlock(hmp, parent);
692 * Then decrement nlinks on hardlink target.
695 if (ip->ip_data.nlinks == 1) {
696 dparent = chain->parent;
697 hammer2_chain_ref(hmp, chain);
698 hammer2_chain_unlock(hmp, chain);
699 hammer2_chain_lock(hmp, dparent,
700 HAMMER2_RESOLVE_ALWAYS);
701 hammer2_chain_lock(hmp, chain, HAMMER2_RESOLVE_ALWAYS);
702 hammer2_chain_drop(hmp, chain);
703 hammer2_chain_modify(hmp, chain, 0);
704 --ip->ip_data.nlinks;
705 hammer2_chain_delete(hmp, dparent, chain);
706 hammer2_chain_unlock(hmp, dparent);
708 hammer2_chain_modify(hmp, chain, 0);
709 --ip->ip_data.nlinks;
713 * Otherwise this was not a hardlink and we can just
714 * remove the entry and decrement nlinks.
717 hammer2_chain_modify(hmp, chain, 0);
718 --ip->ip_data.nlinks;
719 hammer2_chain_delete(hmp, parent, chain);
726 hammer2_chain_unlock(hmp, chain);
728 hammer2_chain_unlock(hmp, parent);
730 hammer2_chain_drop(oip->hmp, &oip->chain);
736 * Calculate the allocation size for the file fragment straddling EOF
739 hammer2_inode_calc_alloc(hammer2_key_t filesize)
741 int frag = (int)filesize & HAMMER2_PBUFMASK;
746 for (radix = HAMMER2_MINALLOCRADIX; frag > (1 << radix); ++radix)
752 hammer2_inode_lock_nlinks(hammer2_inode_t *ip)
754 hammer2_chain_ref(ip->hmp, &ip->chain);
758 hammer2_inode_unlock_nlinks(hammer2_inode_t *ip)
760 hammer2_chain_drop(ip->hmp, &ip->chain);
764 * Consolidate for hard link creation. This moves the specified terminal
765 * hardlink inode to a directory common to its current directory and tdip
766 * if necessary, replacing *ipp with the new inode chain element and
767 * modifying the original inode chain element to OBJTYPE_HARDLINK.
769 * If the original inode chain element was a prior incarnation of a hidden
770 * inode it can simply be deleted instead of converted.
772 * (*ipp)'s nlinks field is locked on entry and the new (*ipp)'s nlinks
773 * field will be locked on return (with the original's unlocked).
775 * The link count is bumped if requested.
778 hammer2_hardlink_consolidate(hammer2_inode_t **ipp, hammer2_inode_t *tdip)
780 hammer2_mount_t *hmp;
781 hammer2_inode_t *oip = *ipp;
782 hammer2_inode_t *nip = NULL;
783 hammer2_inode_t *fdip;
784 hammer2_chain_t *parent;
789 if (hammer2_hardlink_enable < 0)
791 if (hammer2_hardlink_enable == 0)
795 * Find the common parent directory
798 while (fdip->depth > tdip->depth) {
800 KKASSERT(fdip != NULL);
802 while (tdip->depth > fdip->depth) {
804 KKASSERT(tdip != NULL);
806 while (fdip != tdip) {
809 KKASSERT(fdip != NULL);
810 KKASSERT(tdip != NULL);
814 * Nothing to do (except bump the link count) if the hardlink has
815 * already been consolidated in the correct place.
817 if (oip->pip == fdip &&
818 (oip->ip_data.name_key & HAMMER2_DIRHASH_VISIBLE) == 0) {
819 kprintf("hardlink already consolidated correctly\n");
821 hammer2_inode_lock_ex(nip);
822 hammer2_chain_modify(hmp, &nip->chain, 0);
823 ++nip->ip_data.nlinks;
824 hammer2_inode_unlock_ex(nip);
829 * Create a hidden inode directory entry in the parent, copying
830 * (*oip)'s state. Then replace oip with OBJTYPE_HARDLINK.
832 * The duplication function will either flush or move any chains
833 * under oip to the new hardlink target inode, retiring all chains
834 * related to oip before returning. XXX vp->ip races.
836 error = hammer2_inode_duplicate(fdip, oip, &nip, NULL, 0);
839 * Bump nlinks on duplicated hidden inode.
841 kprintf("hardlink consolidation success in parent dir %s\n",
842 fdip->ip_data.filename);
843 hammer2_inode_lock_nlinks(nip);
844 hammer2_inode_unlock_nlinks(oip);
845 hammer2_chain_modify(hmp, &nip->chain, 0);
846 ++nip->ip_data.nlinks;
847 hammer2_inode_unlock_ex(nip);
849 if (oip->ip_data.name_key & HAMMER2_DIRHASH_VISIBLE) {
851 * Replace the old inode with an OBJTYPE_HARDLINK
854 hammer2_inode_lock_ex(oip);
855 hammer2_chain_modify(hmp, &oip->chain, 0);
856 oip->ip_data.target_type = oip->ip_data.type;
857 oip->ip_data.type = HAMMER2_OBJTYPE_HARDLINK;
858 oip->ip_data.uflags = 0;
859 oip->ip_data.rmajor = 0;
860 oip->ip_data.rminor = 0;
861 oip->ip_data.ctime = 0;
862 oip->ip_data.mtime = 0;
863 oip->ip_data.atime = 0;
864 oip->ip_data.btime = 0;
865 bzero(&oip->ip_data.uid, sizeof(oip->ip_data.uid));
866 bzero(&oip->ip_data.gid, sizeof(oip->ip_data.gid));
867 oip->ip_data.op_flags = HAMMER2_OPFLAG_DIRECTDATA;
868 oip->ip_data.cap_flags = 0;
869 oip->ip_data.mode = 0;
870 oip->ip_data.size = 0;
871 oip->ip_data.nlinks = 1;
872 oip->ip_data.iparent = 0; /* XXX */
873 oip->ip_data.pfs_type = 0;
874 oip->ip_data.pfs_inum = 0;
875 bzero(&oip->ip_data.pfs_id,
876 sizeof(oip->ip_data.pfs_id));
877 bzero(&oip->ip_data.pfs_fsid,
878 sizeof(oip->ip_data.pfs_fsid));
879 oip->ip_data.data_quota = 0;
880 oip->ip_data.data_count = 0;
881 oip->ip_data.inode_quota = 0;
882 oip->ip_data.inode_count = 0;
883 oip->ip_data.attr_tid = 0;
884 oip->ip_data.dirent_tid = 0;
885 bzero(&oip->ip_data.u, sizeof(oip->ip_data.u));
886 /* XXX transaction ids */
888 hammer2_inode_unlock_ex(oip);
891 * The old inode was a hardlink target, which we
892 * have now moved. We must delete it so the new
893 * hardlink target at a higher directory level
894 * becomes the only hardlink target for this inode.
896 kprintf("DELETE INVISIBLE\n");
897 parent = oip->chain.parent;
898 hammer2_chain_lock(hmp, parent,
899 HAMMER2_RESOLVE_ALWAYS);
900 hammer2_chain_lock(hmp, &oip->chain,
901 HAMMER2_RESOLVE_ALWAYS);
902 hammer2_chain_delete(hmp, parent, &oip->chain);
903 hammer2_chain_unlock(hmp, &oip->chain);
904 hammer2_chain_unlock(hmp, parent);
908 KKASSERT(nip == NULL);
915 * If (*ipp) is non-NULL it points to the forward OBJTYPE_HARDLINK inode while
916 * (*chainp) points to the resolved (hidden hardlink target) inode. In this
917 * situation when nlinks is 1 we wish to deconsolidate the hardlink, moving
918 * it back to the directory that now represents the only remaining link.
921 hammer2_hardlink_deconsolidate(hammer2_inode_t *dip, hammer2_chain_t **chainp,
922 hammer2_inode_t **ipp)
931 * When presented with a (*chainp) representing an inode of type
932 * OBJTYPE_HARDLINK this code will save the original inode (with a ref)
933 * in (*ipp), and then locate the hidden hardlink target in (dip) or
934 * any parent directory above (dip). The locked (*chainp) is replaced
935 * with a new locked (*chainp) representing the hardlink target.
938 hammer2_hardlink_find(hammer2_inode_t *dip, hammer2_chain_t **chainp,
939 hammer2_inode_t **ipp)
941 hammer2_mount_t *hmp = dip->hmp;
942 hammer2_chain_t *chain = *chainp;
943 hammer2_chain_t *parent;
944 hammer2_inode_t *pip;
948 hammer2_inode_ref(chain->u.ip);
949 lhc = chain->u.ip->ip_data.inum;
951 hammer2_inode_unlock_ex(chain->u.ip);
952 pip = chain->u.ip->pip;
956 parent = &pip->chain;
957 KKASSERT(parent->bref.type == HAMMER2_BREF_TYPE_INODE);
959 hammer2_chain_lock(hmp, parent, HAMMER2_RESOLVE_ALWAYS);
960 chain = hammer2_chain_lookup(hmp, &parent, lhc, lhc, 0);
962 kprintf("found hardlink in dir %s\n",
963 pip->ip_data.filename);
965 hammer2_chain_unlock(hmp, parent);
972 KKASSERT(chain->bref.type == HAMMER2_BREF_TYPE_INODE);