xref: /dragonfly/sys/vfs/hammer2/hammer2_inode.c (revision cecb9aae)
1 /*
2  * Copyright (c) 2011-2012 The DragonFly Project.  All rights reserved.
3  *
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  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
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
17  *    distribution.
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.
21  *
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
33  * SUCH DAMAGE.
34  */
35 #include <sys/cdefs.h>
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/types.h>
39 #include <sys/lock.h>
40 #include <sys/uuid.h>
41 
42 #include "hammer2.h"
43 
44 /*
45  * Adding a ref to an inode is only legal if the inode already has at least
46  * one ref.
47  */
48 void
49 hammer2_inode_ref(hammer2_inode_t *ip)
50 {
51 	atomic_add_int(&ip->refs, 1);
52 }
53 
54 /*
55  * Drop an inode reference, freeing the inode when the last reference goes
56  * away.
57  */
58 void
59 hammer2_inode_drop(hammer2_inode_t *ip)
60 {
61 	hammer2_mount_t *hmp;
62 	hammer2_inode_t *pip;
63 	hammer2_chain_t *chain;
64 	u_int refs;
65 
66 	for (;;) {
67 		refs = ip->refs;
68 		cpu_ccfence();
69 		if (refs == 1) {
70 			if (atomic_cmpset_int(&ip->refs, 1, 0)) {
71 				KKASSERT(ip->topo_cst.count == 0);
72 
73 				hmp = ip->hmp;
74 				ip->hmp = NULL;
75 				pip = ip->pip;
76 				ip->pip = NULL;
77 				chain = ip->chain;
78 				ip->chain = NULL;
79 				if (chain)
80 					hammer2_chain_drop(hmp, chain);
81 
82 				/*
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.
86 				 */
87 				kfree(ip, hmp->minode);
88 				if (pip == NULL)
89 					break;
90 				ip = pip;
91 				/* continue */
92 			}
93 		} else {
94 			if (atomic_cmpset_int(&ip->refs, refs, refs - 1))
95 				break;
96 		}
97 	}
98 }
99 
100 /*
101  * Get the vnode associated with the given inode, allocating the vnode if
102  * necessary.  The vnode will be returned exclusively locked.
103  *
104  * The caller must lock the inode (shared or exclusive).
105  *
106  * Great care must be taken to avoid deadlocks and vnode acquisition/reclaim
107  * races.
108  */
109 struct vnode *
110 hammer2_igetv(hammer2_inode_t *ip, int *errorp)
111 {
112 	hammer2_inode_data_t *ipdata;
113 	hammer2_pfsmount_t *pmp;
114 	struct vnode *vp;
115 	ccms_state_t ostate;
116 
117 	pmp = ip->pmp;
118 	KKASSERT(pmp != NULL);
119 	*errorp = 0;
120 	ipdata = &ip->chain->data->ipdata;
121 
122 	for (;;) {
123 		/*
124 		 * Attempt to reuse an existing vnode assignment.  It is
125 		 * possible to race a reclaim so the vget() may fail.  The
126 		 * inode must be unlocked during the vget() to avoid a
127 		 * deadlock against a reclaim.
128 		 */
129 		vp = ip->vp;
130 		if (vp) {
131 			/*
132 			 * Inode must be unlocked during the vget() to avoid
133 			 * possible deadlocks, but leave the ip ref intact.
134 			 *
135 			 * vnode is held to prevent destruction during the
136 			 * vget().  The vget() can still fail if we lost
137 			 * a reclaim race on the vnode.
138 			 */
139 			vhold_interlocked(vp);
140 			ostate = hammer2_inode_lock_temp_release(ip);
141 			if (vget(vp, LK_EXCLUSIVE)) {
142 				vdrop(vp);
143 				hammer2_inode_lock_restore(ip, ostate);
144 				continue;
145 			}
146 			hammer2_inode_lock_restore(ip, ostate);
147 			vdrop(vp);
148 			/* vp still locked and ref from vget */
149 			if (ip->vp != vp) {
150 				kprintf("hammer2: igetv race %p/%p\n",
151 					ip->vp, vp);
152 				vput(vp);
153 				continue;
154 			}
155 			*errorp = 0;
156 			break;
157 		}
158 
159 		/*
160 		 * No vnode exists, allocate a new vnode.  Beware of
161 		 * allocation races.  This function will return an
162 		 * exclusively locked and referenced vnode.
163 		 */
164 		*errorp = getnewvnode(VT_HAMMER2, pmp->mp, &vp, 0, 0);
165 		if (*errorp) {
166 			kprintf("hammer2: igetv getnewvnode failed %d\n",
167 				*errorp);
168 			vp = NULL;
169 			break;
170 		}
171 
172 		/*
173 		 * Lock the inode and check for an allocation race.
174 		 */
175 		ostate = hammer2_inode_lock_upgrade(ip);
176 		if (ip->vp != NULL) {
177 			vp->v_type = VBAD;
178 			vx_put(vp);
179 			hammer2_inode_lock_restore(ip, ostate);
180 			continue;
181 		}
182 
183 		switch (ipdata->type) {
184 		case HAMMER2_OBJTYPE_DIRECTORY:
185 			vp->v_type = VDIR;
186 			break;
187 		case HAMMER2_OBJTYPE_REGFILE:
188 			vp->v_type = VREG;
189 			vinitvmio(vp, ipdata->size,
190 				  HAMMER2_LBUFSIZE,
191 				  (int)ipdata->size & HAMMER2_LBUFMASK);
192 			break;
193 		case HAMMER2_OBJTYPE_SOFTLINK:
194 			/*
195 			 * XXX for now we are using the generic file_read
196 			 * and file_write code so we need a buffer cache
197 			 * association.
198 			 */
199 			vp->v_type = VLNK;
200 			vinitvmio(vp, ipdata->size,
201 				  HAMMER2_LBUFSIZE,
202 				  (int)ipdata->size & HAMMER2_LBUFMASK);
203 			break;
204 		/* XXX FIFO */
205 		default:
206 			panic("hammer2: unhandled objtype %d", ipdata->type);
207 			break;
208 		}
209 
210 		if (ip == pmp->iroot)
211 			vsetflags(vp, VROOT);
212 
213 		vp->v_data = ip;
214 		ip->vp = vp;
215 		hammer2_inode_ref(ip);		/* vp association */
216 		hammer2_inode_lock_restore(ip, ostate);
217 		break;
218 	}
219 
220 	/*
221 	 * Return non-NULL vp and *errorp == 0, or NULL vp and *errorp != 0.
222 	 */
223 	if (hammer2_debug & 0x0002) {
224 		kprintf("igetv vp %p refs %d aux %d\n",
225 			vp, vp->v_sysref.refcnt, vp->v_auxrefs);
226 	}
227 	return (vp);
228 }
229 
230 /*
231  * The passed-in chain must be locked and the returned inode will also be
232  * locked.  A ref is added to both the chain and the inode.
233  *
234  * The hammer2_inode structure regulates the interface between the high level
235  * kernel VNOPS API and the filesystem backend (the chains).
236  *
237  * NOTE!     This routine allocates the hammer2_inode structure
238  *	     unconditionally, and thus there might be several which
239  *	     are associated with the same chain.  Particularly for hardlinks
240  *	     but this can also happen temporarily for normal files and
241  *	     directories.
242  *
243  * WARNING!  This routine sucks up the chain's lock (makes it part of the
244  *	     inode lock from the point of view of the inode lock API),
245  *	     so callers need to be careful.
246  *
247  * WARNING!  The mount code is allowed to pass dip == NULL for iroot and
248  *	     is allowed to pass pmp == NULL and dip == NULL for sroot.
249  */
250 hammer2_inode_t *
251 hammer2_inode_get(hammer2_mount_t *hmp, hammer2_pfsmount_t *pmp,
252 		  hammer2_inode_t *dip, hammer2_chain_t *chain)
253 {
254 	hammer2_inode_t *nip;
255 
256 	KKASSERT(chain->bref.type == HAMMER2_BREF_TYPE_INODE);
257 
258 	nip = kmalloc(sizeof(*nip), hmp->minode, M_WAITOK | M_ZERO);
259 
260 	nip->chain = chain;
261 	hammer2_chain_ref(hmp, chain);		/* nip->chain */
262 	nip->pip = dip;				/* can be NULL */
263 	if (dip)
264 		hammer2_inode_ref(dip);	/* ref dip for nip->pip */
265 
266 	nip->pmp = pmp;
267 	nip->hmp = hmp;
268 
269 	/*
270 	 * ref and lock on nip gives it state compatible to after a
271 	 * hammer2_inode_lock_ex() call.
272 	 */
273 	nip->refs = 1;
274 	ccms_cst_init(&nip->topo_cst, &nip->chain);
275 	ccms_thread_lock(&nip->topo_cst, CCMS_STATE_EXCLUSIVE);
276 	/* combination of thread lock and chain lock == inode lock */
277 
278 	return (nip);
279 }
280 
281 /*
282  * Put away an inode, disconnecting it from its chain.  The inode must be
283  * exclusively locked.
284  *
285  * The inode will be unlocked by this function.  Note however that any related
286  * chain returned by the hammer2_inode_lock_*() call will NOT be unlocked
287  * by this function.  The related chain is dropped to undo the ref that
288  * hammer2_inode_get() put on it.
289  *
290  * passed_chain is unlocked normally and does not have to be directly
291  * associated with (ip).  This is simply so the API works the same as
292  * the hammer2_inode_unlock_ex() API.  NULL is ok.
293  */
294 void
295 hammer2_inode_put(hammer2_inode_t *ip, hammer2_chain_t *passed_chain)
296 {
297 	hammer2_mount_t *hmp = ip->hmp;
298 	hammer2_inode_t *pip;
299 	hammer2_chain_t *chain;
300 
301 	/*
302 	 * Disconnect chain
303 	 */
304 	if ((chain = ip->chain) != NULL) {
305 		ip->chain = NULL;
306 		hammer2_chain_drop(hmp, chain);		/* from *_get() */
307 	}
308 	KKASSERT(ip->topo_cst.count == -1);	/* one excl lock allowed */
309 
310 	/*
311 	 * Disconnect pip
312 	 */
313 	if ((pip = ip->pip) != NULL) {
314 		ip->pip = NULL;
315 		hammer2_inode_drop(pip);
316 	}
317 
318 	/*
319 	 * clean up the ip, we use an inode_unlock_ex-compatible API.
320 	 */
321 	hammer2_inode_unlock_ex(ip, passed_chain);
322 }
323 
324 /*
325  * Create a new inode in the specified directory using the vattr to
326  * figure out the type of inode.
327  *
328  * If no error occurs the new inode with its chain locked is returned in
329  * *nipp, otherwise an error is returned and *nipp is set to NULL.
330  *
331  * If vap and/or cred are NULL the related fields are not set and the
332  * inode type defaults to a directory.  This is used when creating PFSs
333  * under the super-root, so the inode number is set to 1 in this case.
334  *
335  * dip is not locked on entry.
336  */
337 int
338 hammer2_inode_create(hammer2_inode_t *dip,
339 		     struct vattr *vap, struct ucred *cred,
340 		     const uint8_t *name, size_t name_len,
341 		     hammer2_inode_t **nipp, hammer2_chain_t **nchainp)
342 {
343 	hammer2_inode_data_t *nipdata;
344 	hammer2_mount_t *hmp;
345 	hammer2_chain_t *chain;
346 	hammer2_chain_t *parent;
347 	hammer2_inode_t *nip;
348 	hammer2_key_t lhc;
349 	int error;
350 	uid_t xuid;
351 	uuid_t dip_uid;
352 	uuid_t dip_gid;
353 	uint32_t dip_mode;
354 
355 	hmp = dip->hmp;
356 	lhc = hammer2_dirhash(name, name_len);
357 
358 	/*
359 	 * Locate the inode or indirect block to create the new
360 	 * entry in.  At the same time check for key collisions
361 	 * and iterate until we don't get one.
362 	 */
363 retry:
364 	parent = hammer2_inode_lock_ex(dip);
365 
366 	dip_uid = parent->data->ipdata.uid;
367 	dip_gid = parent->data->ipdata.gid;
368 	dip_mode = parent->data->ipdata.mode;
369 
370 	error = 0;
371 	while (error == 0) {
372 		chain = hammer2_chain_lookup(hmp, &parent, lhc, lhc, 0);
373 		if (chain == NULL)
374 			break;
375 		if ((lhc & HAMMER2_DIRHASH_VISIBLE) == 0)
376 			error = ENOSPC;
377 		if ((lhc & HAMMER2_DIRHASH_LOMASK) == HAMMER2_DIRHASH_LOMASK)
378 			error = ENOSPC;
379 		hammer2_chain_unlock(hmp, chain);
380 		chain = NULL;
381 		++lhc;
382 	}
383 	if (error == 0) {
384 		chain = hammer2_chain_create(hmp, parent, NULL, lhc, 0,
385 					     HAMMER2_BREF_TYPE_INODE,
386 					     HAMMER2_INODE_BYTES,
387 					     &error);
388 	}
389 
390 	hammer2_inode_unlock_ex(dip, parent);
391 
392 	/*
393 	 * Handle the error case
394 	 */
395 	if (error) {
396 		KKASSERT(chain == NULL);
397 		if (error == EAGAIN) {
398 			hammer2_chain_wait(hmp, parent);
399 			goto retry;
400 		}
401 		*nipp = NULL;
402 		*nchainp = NULL;
403 		return (error);
404 	}
405 
406 	/*
407 	 * Set up the new inode.
408 	 *
409 	 * NOTE: *_get() integrates chain's lock into the inode lock.
410 	 */
411 	nip = hammer2_inode_get(dip->hmp, dip->pmp, dip, chain);
412 	*nipp = nip;
413 	*nchainp = chain;
414 	nipdata = &chain->data->ipdata;
415 
416 	hammer2_voldata_lock(hmp);
417 	if (vap) {
418 		nipdata->type = hammer2_get_obj_type(vap->va_type);
419 		nipdata->inum = hmp->voldata.alloc_tid++;
420 		/* XXX modify/lock */
421 	} else {
422 		nipdata->type = HAMMER2_OBJTYPE_DIRECTORY;
423 		nipdata->inum = 1;
424 	}
425 	hammer2_voldata_unlock(hmp);
426 	nipdata->version = HAMMER2_INODE_VERSION_ONE;
427 	hammer2_update_time(&nipdata->ctime);
428 	nipdata->mtime = nipdata->ctime;
429 	if (vap)
430 		nipdata->mode = vap->va_mode;
431 	nipdata->nlinks = 1;
432 	if (vap) {
433 		if (dip) {
434 			xuid = hammer2_to_unix_xid(&dip_uid);
435 			xuid = vop_helper_create_uid(dip->pmp->mp,
436 						     dip_mode,
437 						     xuid,
438 						     cred,
439 						     &vap->va_mode);
440 		} else {
441 			xuid = 0;
442 		}
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);
447 		else
448 			hammer2_guid_to_uuid(&nipdata->uid, xuid);
449 
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);
454 		else if (dip)
455 			nipdata->gid = dip_gid;
456 	}
457 
458 	/*
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.
462 	 */
463 	if (nipdata->type == HAMMER2_OBJTYPE_REGFILE ||
464 	    nipdata->type == HAMMER2_OBJTYPE_SOFTLINK) {
465 		nipdata->op_flags |= HAMMER2_OPFLAG_DIRECTDATA;
466 	}
467 
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;
472 
473 	return (0);
474 }
475 
476 /*
477  * Create a duplicate of the inode (chain) in the specified target directory
478  * (dip), return the duplicated chain in *nchainp (locked).  chain is locked
479  * on call and remains locked on return.
480  *
481  * If name is NULL the inode is duplicated as a hidden directory entry.
482  *
483  * XXX name needs to be NULL for now.
484  */
485 int
486 hammer2_inode_duplicate(hammer2_inode_t *dip,
487 			hammer2_chain_t *ochain, hammer2_chain_t **nchainp)
488 {
489 	hammer2_inode_data_t *nipdata;
490 	hammer2_mount_t *hmp;
491 	hammer2_chain_t *parent;
492 	hammer2_chain_t *chain;
493 	hammer2_key_t lhc;
494 	int error = 0;
495 
496 	hmp = dip->hmp;
497 	lhc = ochain->data->ipdata.inum;
498 	*nchainp = NULL;
499 	KKASSERT((lhc & HAMMER2_DIRHASH_VISIBLE) == 0);
500 
501 	/*
502 	 * Locate the inode or indirect block to create the new
503 	 * entry in.
504 	 *
505 	 * There should be no key collisions with invisible inode keys.
506 	 */
507 retry:
508 	parent = dip->chain;
509 	hammer2_chain_lock(hmp, parent, HAMMER2_RESOLVE_ALWAYS);
510 	chain = hammer2_chain_lookup(hmp, &parent, lhc, lhc, 0);
511 	if (chain) {
512 		hammer2_chain_unlock(hmp, chain);
513 		chain = NULL;
514 		error = ENOSPC;
515 	}
516 
517 	/*
518 	 * Create entry in common parent directory.
519 	 */
520 	if (error == 0) {
521 		chain = hammer2_chain_create(hmp, parent, NULL, lhc, 0,
522 					     HAMMER2_BREF_TYPE_INODE, /* n/a */
523 					     HAMMER2_INODE_BYTES,     /* n/a */
524 					     &error);
525 	}
526 
527 	/*
528 	 * Clean up, but we need to retain a ref on parent so we can wait
529 	 * on it for certain errors.
530 	 */
531 	if (error == EAGAIN)
532 		hammer2_chain_ref(hmp, parent);
533 	hammer2_chain_unlock(hmp, parent);
534 
535 	/*
536 	 * Handle the error case
537 	 */
538 	if (error) {
539 		KKASSERT(chain == NULL);
540 		if (error == EAGAIN) {
541 			hammer2_chain_wait(hmp, parent);
542 			hammer2_chain_drop(hmp, parent);
543 			goto retry;
544 		}
545 		return (error);
546 	}
547 
548 	/*
549 	 * XXX This is currently a horrible hack.  Well, if we wanted to
550 	 *     duplicate a file, i.e. as in a snapshot, we definitely
551 	 *     would have to flush it first.
552 	 *
553 	 *     For hardlink target generation we can theoretically move any
554 	 *     active chain structures without flushing, but that gets really
555 	 *     iffy for code which follows chain->parent and ip->pip links.
556 	 *
557 	 * XXX only works with files.  Duplicating a directory hierarchy
558 	 *     requires a flush but doesn't deal with races post-flush.
559 	 *     Well, it would work I guess, but you might catch some files
560 	 *     mid-operation.
561 	 *
562 	 * We cannot leave ochain with any in-memory chains because (for a
563 	 * hardlink), ochain will become a OBJTYPE_HARDLINK which is just a
564 	 * pointer to the real hardlink's inum and can't have any sub-chains.
565 	 * XXX might be 0-ref chains left.
566 	 */
567 	hammer2_chain_flush(hmp, ochain, 0);
568 	/*KKASSERT(RB_EMPTY(&ochain.rbhead));*/
569 
570 	hammer2_chain_modify(hmp, chain, 0);
571 	nipdata = &chain->data->ipdata;
572 	*nipdata = ochain->data->ipdata;
573 
574 	/*
575 	 * Directory entries are inodes but this is a hidden hardlink
576 	 * target.  The name isn't used but to ease debugging give it
577 	 * a name after its inode number.
578 	 */
579 	ksnprintf(nipdata->filename, sizeof(nipdata->filename),
580 		  "0x%016jx", (intmax_t)nipdata->inum);
581 	nipdata->name_len = strlen(nipdata->filename);
582 	nipdata->name_key = lhc;
583 
584 	*nchainp = chain;
585 
586 	return (0);
587 }
588 
589 /*
590  * Connect *chainp to the media topology represented by (dip, name, len).
591  * A directory entry is created which points to *chainp.  *chainp is then
592  * unlocked and set to NULL.
593  *
594  * If *chainp is not currently connected we simply connect it up.
595  *
596  * If *chainp is already connected we create a OBJTYPE_HARDLINK entry which
597  * points to chain's inode number.  *chainp is expected to be the terminus of
598  * the hardlink sitting as a hidden file in a common parent directory
599  * in this situation.
600  *
601  * The caller always wants to reference the hardlink terminus, not the
602  * hardlink pointer that we might be creating, so we do NOT replace
603  * *chainp here, we simply unlock and NULL it out.
604  */
605 int
606 hammer2_inode_connect(hammer2_inode_t *dip, hammer2_chain_t **chainp,
607 		      const uint8_t *name, size_t name_len)
608 {
609 	hammer2_inode_data_t *ipdata;
610 	hammer2_mount_t *hmp;
611 	hammer2_chain_t *nchain;
612 	hammer2_chain_t *parent;
613 	hammer2_chain_t *ochain;
614 	hammer2_key_t lhc;
615 	int error;
616 	int hlink;
617 
618 	hmp = dip->hmp;
619 
620 	ochain = *chainp;
621 	*chainp = NULL;
622 
623 	/*
624 	 * Since ochain is either disconnected from the topology or represents
625 	 * a hardlink terminus which is always a parent of or equal to dip,
626 	 * we should be able to safely lock dip->chain for our setup.
627 	 */
628 retry:
629 	parent = dip->chain;
630 	hammer2_chain_lock(hmp, parent, HAMMER2_RESOLVE_ALWAYS);
631 
632 	lhc = hammer2_dirhash(name, name_len);
633 	hlink = (ochain->parent != NULL);
634 
635 	/*
636 	 * In fake mode flush oip so we can just snapshot it downbelow.
637 	 */
638 	if (hlink && hammer2_hardlink_enable < 0)
639 		hammer2_chain_flush(hmp, ochain, 0);
640 
641 	/*
642 	 * Locate the inode or indirect block to create the new
643 	 * entry in.  At the same time check for key collisions
644 	 * and iterate until we don't get one.
645 	 */
646 	error = 0;
647 	while (error == 0) {
648 		nchain = hammer2_chain_lookup(hmp, &parent, lhc, lhc, 0);
649 		if (nchain == NULL)
650 			break;
651 		if ((lhc & HAMMER2_DIRHASH_LOMASK) == HAMMER2_DIRHASH_LOMASK)
652 			error = ENOSPC;
653 		hammer2_chain_unlock(hmp, nchain);
654 		nchain = NULL;
655 		++lhc;
656 	}
657 
658 	/*
659 	 * Passing a non-NULL chain to hammer2_chain_create() reconnects the
660 	 * existing chain instead of creating a new one.  The chain's bref
661 	 * will be properly updated.
662 	 */
663 	if (error == 0) {
664 		if (hlink) {
665 			nchain = hammer2_chain_create(hmp, parent,
666 						     NULL, lhc, 0,
667 						     HAMMER2_BREF_TYPE_INODE,
668 						     HAMMER2_INODE_BYTES,
669 						     &error);
670 		} else {
671 			/*
672 			 * NOTE: reconnects oip->chain to the media
673 			 *	 topology and returns its argument
674 			 *	 (oip->chain).
675 			 *
676 			 * No additional locks or refs are obtained on
677 			 * the returned chain so don't double-unlock!
678 			 */
679 			nchain = hammer2_chain_create(hmp, parent,
680 						     ochain, lhc, 0,
681 						     HAMMER2_BREF_TYPE_INODE,
682 						     HAMMER2_INODE_BYTES,
683 						     &error);
684 		}
685 	}
686 
687 	/*
688 	 * Unlock stuff.  This is a bit messy, if we have an EAGAIN error
689 	 * we need to wait for operations on parent to finish.
690 	 */
691 	if (error == EAGAIN)
692 		hammer2_chain_ref(hmp, parent);
693 	hammer2_chain_unlock(hmp, parent);
694 
695 	/*
696 	 * ochain still active.
697 	 *
698 	 * Handle the error case
699 	 */
700 	if (error) {
701 		KKASSERT(nchain == NULL);
702 		if (error == EAGAIN) {
703 			hammer2_chain_wait(hmp, parent);
704 			hammer2_chain_drop(hmp, parent);
705 			goto retry;
706 		}
707 		hammer2_chain_unlock(hmp, ochain);
708 		return (error);
709 	}
710 
711 	/*
712 	 * Directory entries are inodes so if the name has changed we have
713 	 * to update the inode.
714 	 *
715 	 * When creating an OBJTYPE_HARDLINK entry remember to unlock the
716 	 * chain, the caller will access the hardlink via the actual hardlink
717 	 * target file and not the hardlink pointer entry.
718 	 */
719 	if (hlink && hammer2_hardlink_enable >= 0) {
720 		/*
721 		 * Create the HARDLINK pointer.  oip represents the hardlink
722 		 * target in this situation.
723 		 *
724 		 * NOTE: *_get() integrates chain's lock into the inode lock.
725 		 */
726 		hammer2_chain_modify(hmp, nchain, 0);
727 		KKASSERT(name_len < HAMMER2_INODE_MAXNAME);
728 		ipdata = &nchain->data->ipdata;
729 		bcopy(name, ipdata->filename, name_len);
730 		ipdata->name_key = lhc;
731 		ipdata->name_len = name_len;
732 		ipdata->target_type = ochain->data->ipdata.type;
733 		ipdata->type = HAMMER2_OBJTYPE_HARDLINK;
734 		ipdata->inum = ochain->data->ipdata.inum;
735 		ipdata->nlinks = 1;
736 		kprintf("created hardlink %*.*s\n",
737 			(int)name_len, (int)name_len, name);
738 		hammer2_chain_unlock(hmp, nchain);
739 	} else if (hlink && hammer2_hardlink_enable < 0) {
740 		/*
741 		 * Create a snapshot (hardlink fake mode for debugging).
742 		 *
743 		 * NOTE: *_get() integrates nchain's lock into the inode lock.
744 		 */
745 		hammer2_chain_modify(hmp, nchain, 0);
746 		KKASSERT(name_len < HAMMER2_INODE_MAXNAME);
747 		ipdata = &nchain->data->ipdata;
748 		*ipdata = ochain->data->ipdata;
749 		bcopy(name, ipdata->filename, name_len);
750 		ipdata->name_key = lhc;
751 		ipdata->name_len = name_len;
752 		kprintf("created fake hardlink %*.*s\n",
753 			(int)name_len, (int)name_len, name);
754 		hammer2_chain_unlock(hmp, nchain);
755 	} else {
756 		/*
757 		 * Normally disconnected inode (e.g. during a rename) that
758 		 * was reconnected.  We must fixup the name stored in
759 		 * oip.
760 		 *
761 		 * We are using oip as chain, already locked by caller,
762 		 * do not unlock it.
763 		 */
764 		hammer2_chain_modify(hmp, ochain, 0);
765 		ipdata = &ochain->data->ipdata;
766 
767 		if (ipdata->name_len != name_len ||
768 		    bcmp(ipdata->filename, name, name_len) != 0) {
769 			KKASSERT(name_len < HAMMER2_INODE_MAXNAME);
770 			bcopy(name, ipdata->filename, name_len);
771 			ipdata->name_key = lhc;
772 			ipdata->name_len = name_len;
773 		}
774 		ipdata->nlinks = 1;
775 	}
776 	hammer2_chain_unlock(hmp, ochain);
777 	return (0);
778 }
779 
780 /*
781  * Unlink the file from the specified directory inode.  The directory inode
782  * does not need to be locked.  The caller should pass a non-NULL (ip)
783  * representing the object being removed only if the related vnode is
784  * potentially inactive (not referenced in the caller's active path),
785  * so we can vref/vrele it to trigger the VOP_INACTIVE path and properly
786  * recycle it.
787  *
788  * isdir determines whether a directory/non-directory check should be made.
789  * No check is made if isdir is set to -1.
790  *
791  * If retain_chain is non-NULL this function can fail with an EAGAIN if it
792  * catches the object in the middle of a flush.
793  */
794 int
795 hammer2_unlink_file(hammer2_inode_t *dip,
796 		    const uint8_t *name, size_t name_len,
797 		    int isdir, hammer2_chain_t *retain_chain)
798 {
799 	hammer2_inode_data_t *ipdata;
800 	hammer2_mount_t *hmp;
801 	hammer2_chain_t *parent;
802 	hammer2_chain_t *ochain;
803 	hammer2_chain_t *chain;
804 	hammer2_chain_t *dparent;
805 	hammer2_chain_t *dchain;
806 	hammer2_key_t lhc;
807 	int error;
808 	int parent_ref;
809 	uint8_t type;
810 
811 	parent_ref = 0;
812 	error = 0;
813 	ochain = NULL;
814 	hmp = dip->hmp;
815 	lhc = hammer2_dirhash(name, name_len);
816 
817 	/*
818 	 * Search for the filename in the directory
819 	 */
820 	parent = hammer2_inode_lock_ex(dip);
821 	chain = hammer2_chain_lookup(hmp, &parent,
822 				     lhc, lhc + HAMMER2_DIRHASH_LOMASK,
823 				     0);
824 	while (chain) {
825 		if (chain->bref.type == HAMMER2_BREF_TYPE_INODE &&
826 		    name_len == chain->data->ipdata.name_len &&
827 		    bcmp(name, chain->data->ipdata.filename, name_len) == 0) {
828 			break;
829 		}
830 		chain = hammer2_chain_next(hmp, &parent, chain,
831 					   lhc, lhc + HAMMER2_DIRHASH_LOMASK,
832 					   0);
833 	}
834 	hammer2_inode_unlock_ex(dip, NULL);	/* retain parent */
835 
836 	/*
837 	 * Not found or wrong type (isdir < 0 disables the type check).
838 	 * If a hardlink pointer, type checks use the hardlink target.
839 	 */
840 	if (chain == NULL) {
841 		error = ENOENT;
842 		goto done;
843 	}
844 	if ((type = chain->data->ipdata.type) == HAMMER2_OBJTYPE_HARDLINK)
845 		type = chain->data->ipdata.target_type;
846 
847 	if (type == HAMMER2_OBJTYPE_DIRECTORY && isdir == 0) {
848 		error = ENOTDIR;
849 		goto done;
850 	}
851 	if (type != HAMMER2_OBJTYPE_DIRECTORY && isdir == 1) {
852 		error = EISDIR;
853 		goto done;
854 	}
855 
856 	/*
857 	 * Hardlink must be resolved.  We can't hold parent locked while we
858 	 * do this or we could deadlock.
859 	 *
860 	 * On success chain will be adjusted to point at the hardlink target
861 	 * and ochain will point to the hardlink pointer in the original
862 	 * directory.  Otherwise chain remains pointing to the original.
863 	 */
864 	if (chain->data->ipdata.type == HAMMER2_OBJTYPE_HARDLINK) {
865 		KKASSERT(parent_ref == 0);
866 		hammer2_chain_unlock(hmp, parent);
867 		parent = NULL;
868 		error = hammer2_hardlink_find(dip, &chain, &ochain);
869 	}
870 
871 	/*
872 	 * If this is a directory the directory must be empty.  However, if
873 	 * isdir < 0 we are doing a rename and the directory does not have
874 	 * to be empty.
875 	 *
876 	 * NOTE: We check the full key range here which covers both visible
877 	 *	 and invisible entries.  Theoretically there should be no
878 	 *	 invisible (hardlink target) entries if there are no visible
879 	 *	 entries.
880 	 */
881 	if (type == HAMMER2_OBJTYPE_DIRECTORY && isdir >= 0) {
882 		dparent = chain;
883 		hammer2_chain_lock(hmp, dparent, HAMMER2_RESOLVE_ALWAYS);
884 		dchain = hammer2_chain_lookup(hmp, &dparent,
885 					      0, (hammer2_key_t)-1,
886 					      HAMMER2_LOOKUP_NODATA);
887 		if (dchain) {
888 			hammer2_chain_unlock(hmp, dchain);
889 			hammer2_chain_unlock(hmp, dparent);
890 			error = ENOTEMPTY;
891 			goto done;
892 		}
893 		hammer2_chain_unlock(hmp, dparent);
894 		dparent = NULL;
895 		/* dchain NULL */
896 	}
897 
898 	/*
899 	 * Ok, we can now unlink the chain.  We always decrement nlinks even
900 	 * if the entry can be deleted in case someone has the file open and
901 	 * does an fstat().
902 	 *
903 	 * The chain itself will no longer be in the on-media topology but
904 	 * can still be flushed to the media (e.g. if an open descriptor
905 	 * remains).  When the last vnode/ip ref goes away the chain will
906 	 * be marked unmodified, avoiding any further (now unnecesary) I/O.
907 	 *
908 	 * A non-NULL ochain indicates a hardlink.
909 	 */
910 	if (ochain) {
911 		/*
912 		 * Delete the original hardlink pointer.
913 		 *
914 		 * NOTE: parent from above is NULL when ochain != NULL
915 		 *	 so we can reuse it.
916 		 */
917 		hammer2_chain_lock(hmp, ochain, HAMMER2_RESOLVE_ALWAYS);
918 		parent_ref = 1;
919 		for (;;) {
920 			parent = ochain->parent;
921 			hammer2_chain_ref(hmp, parent);
922 			hammer2_chain_unlock(hmp, ochain);
923 			hammer2_chain_lock(hmp, parent, HAMMER2_RESOLVE_ALWAYS);
924 			hammer2_chain_lock(hmp, ochain, HAMMER2_RESOLVE_ALWAYS);
925 			if (ochain->parent == parent)
926 				break;
927 			hammer2_chain_unlock(hmp, parent);
928 			hammer2_chain_drop(hmp, parent);
929 		}
930 
931 		if (ochain == retain_chain && ochain->flushing) {
932 			hammer2_chain_unlock(hmp, ochain);
933 			error = EAGAIN;
934 			goto done;
935 		}
936 		hammer2_chain_delete(hmp, parent, ochain,
937 				     (ochain == retain_chain));
938 		hammer2_chain_unlock(hmp, ochain);
939 		hammer2_chain_unlock(hmp, parent);
940 		hammer2_chain_drop(hmp, parent);
941 		parent = NULL;
942 
943 		/*
944 		 * Then decrement nlinks on hardlink target, deleting
945 		 * the target when nlinks drops to 0.
946 		 */
947 		if (chain->data->ipdata.nlinks == 1) {
948 			dparent = chain->parent;
949 			hammer2_chain_ref(hmp, chain);
950 			hammer2_chain_unlock(hmp, chain);
951 			hammer2_chain_lock(hmp, dparent,
952 					   HAMMER2_RESOLVE_ALWAYS);
953 			hammer2_chain_lock(hmp, chain,
954 					   HAMMER2_RESOLVE_ALWAYS);
955 			hammer2_chain_drop(hmp, chain);
956 			hammer2_chain_modify(hmp, chain, 0);
957 			--chain->data->ipdata.nlinks;
958 			hammer2_chain_delete(hmp, dparent, chain, 0);
959 			hammer2_chain_unlock(hmp, dparent);
960 		} else {
961 			hammer2_chain_modify(hmp, chain, 0);
962 			--chain->data->ipdata.nlinks;
963 		}
964 	} else {
965 		/*
966 		 * Otherwise this was not a hardlink and we can just
967 		 * remove the entry and decrement nlinks.
968 		 *
969 		 * NOTE: *_get() integrates chain's lock into the inode lock.
970 		 */
971 		ipdata = &chain->data->ipdata;
972 		if (chain == retain_chain && chain->flushing) {
973 			error = EAGAIN;
974 			goto done;
975 		}
976 		hammer2_chain_modify(hmp, chain, 0);
977 		--ipdata->nlinks;
978 		hammer2_chain_delete(hmp, parent, chain,
979 				     (retain_chain == chain));
980 	}
981 
982 	error = 0;
983 done:
984 	if (chain)
985 		hammer2_chain_unlock(hmp, chain);
986 	if (parent) {
987 		hammer2_chain_unlock(hmp, parent);
988 		if (parent_ref)
989 			hammer2_chain_drop(hmp, parent);
990 	}
991 	if (ochain)
992 		hammer2_chain_drop(hmp, ochain);
993 
994 	return error;
995 }
996 
997 /*
998  * Calculate the allocation size for the file fragment straddling EOF
999  */
1000 int
1001 hammer2_inode_calc_alloc(hammer2_key_t filesize)
1002 {
1003 	int frag = (int)filesize & HAMMER2_PBUFMASK;
1004 	int radix;
1005 
1006 	if (frag == 0)
1007 		return(0);
1008 	for (radix = HAMMER2_MINALLOCRADIX; frag > (1 << radix); ++radix)
1009 		;
1010 	return (radix);
1011 }
1012 
1013 /*
1014  * Given an unlocked ip consolidate for hardlink creation, adding (nlinks)
1015  * to the file's link count and potentially relocating the file to a
1016  * directory common to ip->pip and tdip.
1017  *
1018  * If the file has to be relocated ip->chain will also be adjusted.
1019  */
1020 int
1021 hammer2_hardlink_consolidate(hammer2_inode_t *ip, hammer2_chain_t **chainp,
1022 			     hammer2_inode_t *tdip, int nlinks)
1023 {
1024 	hammer2_inode_data_t *ipdata;
1025 	hammer2_mount_t *hmp;
1026 	hammer2_inode_t *fdip;
1027 	hammer2_inode_t *cdip;
1028 	hammer2_chain_t *chain;
1029 	hammer2_chain_t *nchain;
1030 	hammer2_chain_t *parent;
1031 	int error;
1032 
1033 	hmp = tdip->hmp;
1034 	*chainp = NULL;
1035 	chain = hammer2_inode_lock_ex(ip);
1036 
1037 	if (nlinks == 0 &&			/* no hardlink needed */
1038 	    (chain->data->ipdata.name_key & HAMMER2_DIRHASH_VISIBLE)) {
1039 		hammer2_inode_unlock_ex(ip, NULL);
1040 		*chainp = chain;
1041 		return (0);
1042 	}
1043 	if (hammer2_hardlink_enable < 0) {	/* fake hardlinks */
1044 		hammer2_inode_unlock_ex(ip, NULL);
1045 		*chainp = chain;
1046 		return (0);
1047 	}
1048 	if (hammer2_hardlink_enable == 0) {	/* disallow hardlinks */
1049 		hammer2_inode_unlock_ex(ip, chain);
1050 		return (ENOTSUP);
1051 	}
1052 
1053 	/*
1054 	 * cdip will be returned with a ref, but not locked.
1055 	 */
1056 	fdip = ip->pip;
1057 	cdip = hammer2_inode_common_parent(hmp, fdip, tdip);
1058 
1059 	/*
1060 	 * If no change in the hardlink's target directory is required and
1061 	 * this is already a hardlink target, all we need to do is adjust
1062 	 * the link count.
1063 	 */
1064 	if (cdip == fdip &&
1065 	    (chain->data->ipdata.name_key & HAMMER2_DIRHASH_VISIBLE) == 0) {
1066 		if (nlinks) {
1067 			hammer2_chain_modify(hmp, chain, 0);
1068 			chain->data->ipdata.nlinks += nlinks;
1069 		}
1070 		*chainp = chain;
1071 		error = 0;
1072 		goto done;
1073 	}
1074 
1075 	/*
1076 	 * We either have to move an existing hardlink target or we have
1077 	 * to create a fresh hardlink target.
1078 	 *
1079 	 * Hardlink targets are hidden inodes in a parent directory common
1080 	 * to all directory entries referencing the hardlink.
1081 	 */
1082 	error = hammer2_inode_duplicate(cdip, chain, &nchain);
1083 	if (error == 0) {
1084 		/*
1085 		 * Bump nlinks on duplicated hidden inode.
1086 		 */
1087 		hammer2_chain_modify(hmp, nchain, 0);
1088 		nchain->data->ipdata.nlinks += nlinks;
1089 
1090 		/*
1091 		 * If the old chain is not a hardlink target then replace
1092 		 * it with a OBJTYPE_HARDLINK pointer.
1093 		 *
1094 		 * If the old chain IS a hardlink target then delete it.
1095 		 */
1096 		if (chain->data->ipdata.name_key & HAMMER2_DIRHASH_VISIBLE) {
1097 			hammer2_chain_modify(hmp, chain, 0);
1098 			ipdata = &chain->data->ipdata;
1099 			ipdata->target_type = ipdata->type;
1100 			ipdata->type = HAMMER2_OBJTYPE_HARDLINK;
1101 			ipdata->uflags = 0;
1102 			ipdata->rmajor = 0;
1103 			ipdata->rminor = 0;
1104 			ipdata->ctime = 0;
1105 			ipdata->mtime = 0;
1106 			ipdata->atime = 0;
1107 			ipdata->btime = 0;
1108 			bzero(&ipdata->uid, sizeof(ipdata->uid));
1109 			bzero(&ipdata->gid, sizeof(ipdata->gid));
1110 			ipdata->op_flags = HAMMER2_OPFLAG_DIRECTDATA;
1111 			ipdata->cap_flags = 0;
1112 			ipdata->mode = 0;
1113 			ipdata->size = 0;
1114 			ipdata->nlinks = 1;
1115 			ipdata->iparent = 0;	/* XXX */
1116 			ipdata->pfs_type = 0;
1117 			ipdata->pfs_inum = 0;
1118 			bzero(&ipdata->pfs_clid, sizeof(ipdata->pfs_clid));
1119 			bzero(&ipdata->pfs_fsid, sizeof(ipdata->pfs_fsid));
1120 			ipdata->data_quota = 0;
1121 			ipdata->data_count = 0;
1122 			ipdata->inode_quota = 0;
1123 			ipdata->inode_count = 0;
1124 			ipdata->attr_tid = 0;
1125 			ipdata->dirent_tid = 0;
1126 			bzero(&ipdata->u, sizeof(ipdata->u));
1127 			/* XXX transaction ids */
1128 		} else {
1129 			kprintf("DELETE INVISIBLE\n");
1130 			for (;;) {
1131 				parent = chain->parent;
1132 				hammer2_chain_ref(hmp, parent);
1133 				hammer2_chain_ref(hmp, chain);
1134 				hammer2_chain_unlock(hmp, chain);
1135 				hammer2_chain_lock(hmp, parent,
1136 						   HAMMER2_RESOLVE_ALWAYS);
1137 				hammer2_chain_lock(hmp, chain,
1138 						   HAMMER2_RESOLVE_ALWAYS);
1139 				hammer2_chain_drop(hmp, chain);
1140 				if (chain->parent == parent)
1141 					break;
1142 				hammer2_chain_unlock(hmp, parent);
1143 				hammer2_chain_drop(hmp, parent);
1144 			}
1145 			hammer2_chain_delete(hmp, parent, chain, 0);
1146 			hammer2_chain_unlock(hmp, parent);
1147 			hammer2_chain_drop(hmp, parent);
1148 		}
1149 
1150 		/*
1151 		 * Replace ip->chain with nchain (ip is still locked).
1152 		 */
1153 		hammer2_chain_ref(hmp, nchain);			/* ip->chain */
1154 		if (ip->chain)
1155 			hammer2_chain_drop(hmp, ip->chain);	/* ip->chain */
1156 		ip->chain = nchain;
1157 
1158 		hammer2_chain_unlock(hmp, chain);
1159 		*chainp = nchain;
1160 	} else {
1161 		hammer2_chain_unlock(hmp, chain);
1162 	}
1163 
1164 	/*
1165 	 * Cleanup, chain/nchain already dealt with.
1166 	 */
1167 done:
1168 	hammer2_inode_unlock_ex(ip, NULL);
1169 	hammer2_inode_drop(cdip);
1170 
1171 	return (error);
1172 }
1173 
1174 /*
1175  * If (*ochainp) is non-NULL it points to the forward OBJTYPE_HARDLINK
1176  * inode while (*chainp) points to the resolved (hidden hardlink
1177  * target) inode.  In this situation when nlinks is 1 we wish to
1178  * deconsolidate the hardlink, moving it back to the directory that now
1179  * represents the only remaining link.
1180  */
1181 int
1182 hammer2_hardlink_deconsolidate(hammer2_inode_t *dip,
1183 			       hammer2_chain_t **chainp,
1184 			       hammer2_chain_t **ochainp)
1185 {
1186 	if (*ochainp == NULL)
1187 		return (0);
1188 	/* XXX */
1189 	return (0);
1190 }
1191 
1192 /*
1193  * The caller presents a locked *chainp pointing to a HAMMER2_BREF_TYPE_INODE
1194  * with an obj_type of HAMMER2_OBJTYPE_HARDLINK.  This routine will gobble
1195  * the *chainp and return a new locked *chainp representing the file target
1196  * (the original *chainp will be unlocked).
1197  *
1198  * When a match is found the chain representing the original HARDLINK
1199  * will be returned in *ochainp with a ref, but not locked.
1200  *
1201  * When no match is found *chainp is set to NULL and EIO is returned.
1202  * (*ochainp) will still be set to the original chain with a ref but not
1203  * locked.
1204  */
1205 int
1206 hammer2_hardlink_find(hammer2_inode_t *dip, hammer2_chain_t **chainp,
1207 		      hammer2_chain_t **ochainp)
1208 {
1209 	hammer2_mount_t *hmp = dip->hmp;
1210 	hammer2_chain_t *chain = *chainp;
1211 	hammer2_chain_t *parent;
1212 	hammer2_inode_t *ip;
1213 	hammer2_inode_t *pip;
1214 	hammer2_key_t lhc;
1215 
1216 	pip = dip;
1217 	hammer2_inode_ref(pip);		/* for loop */
1218 	hammer2_chain_ref(hmp, chain);	/* for (*ochainp) */
1219 
1220 	*ochainp = chain;
1221 
1222 	/*
1223 	 * Locate the hardlink.  pip is referenced and not locked,
1224 	 * ipp.
1225 	 *
1226 	 * chain is reused.
1227 	 */
1228 	lhc = chain->data->ipdata.inum;
1229 	hammer2_chain_unlock(hmp, chain);
1230 	chain = NULL;
1231 
1232 	while ((ip = pip) != NULL) {
1233 		parent = hammer2_inode_lock_ex(ip);
1234 		hammer2_inode_drop(ip);			/* loop */
1235 		KKASSERT(parent->bref.type == HAMMER2_BREF_TYPE_INODE);
1236 		chain = hammer2_chain_lookup(hmp, &parent, lhc, lhc, 0);
1237 		hammer2_chain_unlock(hmp, parent);
1238 		if (chain)
1239 			break;
1240 		pip = ip->pip;		/* safe, ip held locked */
1241 		if (pip)
1242 			hammer2_inode_ref(pip);		/* loop */
1243 		hammer2_inode_unlock_ex(ip, NULL);
1244 	}
1245 
1246 	/*
1247 	 * chain is locked, ip is locked.  Unlock ip, return the locked
1248 	 * chain.  *ipp is already set w/a ref count and not locked.
1249 	 *
1250 	 * (parent is already unlocked).
1251 	 */
1252 	hammer2_inode_unlock_ex(ip, NULL);
1253 	*chainp = chain;
1254 	if (chain) {
1255 		KKASSERT(chain->bref.type == HAMMER2_BREF_TYPE_INODE);
1256 		/* already locked */
1257 		return (0);
1258 	} else {
1259 		return (EIO);
1260 	}
1261 }
1262 
1263 /*
1264  * Find the directory common to both fdip and tdip, hold and return
1265  * its inode.
1266  */
1267 hammer2_inode_t *
1268 hammer2_inode_common_parent(hammer2_mount_t *hmp,
1269 			    hammer2_inode_t *fdip, hammer2_inode_t *tdip)
1270 {
1271 	hammer2_inode_t *scan1;
1272 	hammer2_inode_t *scan2;
1273 
1274 	/*
1275 	 * We used to have a depth field but it complicated matters too
1276 	 * much for directory renames.  So now its ugly.  Check for
1277 	 * simple cases before giving up and doing it the expensive way.
1278 	 *
1279 	 * XXX need a bottom-up topology stability lock
1280 	 */
1281 	if (fdip == tdip || fdip == tdip->pip) {
1282 		hammer2_inode_ref(fdip);
1283 		return(fdip);
1284 	}
1285 	if (fdip->pip == tdip) {
1286 		hammer2_inode_ref(tdip);
1287 		return(tdip);
1288 	}
1289 
1290 	/*
1291 	 * XXX not MPSAFE
1292 	 */
1293 	for (scan1 = fdip; scan1->pmp == fdip->pmp; scan1 = scan1->pip) {
1294 		scan2 = tdip;
1295 		while (scan2->pmp == tdip->pmp) {
1296 			if (scan1 == scan2) {
1297 				hammer2_inode_ref(scan1);
1298 				return(scan1);
1299 			}
1300 			scan2 = scan2->pip;
1301 		}
1302 	}
1303 	panic("hammer2_inode_common_parent: no common parent %p %p\n",
1304 	      fdip, tdip);
1305 	/* NOT REACHED */
1306 	return(NULL);
1307 }
1308