1/*	$NetBSD: lfs_rename.c,v 1.25 2021/10/20 03:08:19 thorpej Exp $	*/
2/*  from NetBSD: ufs_rename.c,v 1.12 2015/03/27 17:27:56 riastradh Exp  */
3
4/*-
5 * Copyright (c) 2012 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Taylor R Campbell.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32/*-
33 * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
34 * All rights reserved.
35 *
36 * This code is derived from software contributed to The NetBSD Foundation
37 * by Konrad E. Schroder <perseant@hhhh.org>.
38 *
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
41 * are met:
42 * 1. Redistributions of source code must retain the above copyright
43 *    notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 *    notice, this list of conditions and the following disclaimer in the
46 *    documentation and/or other materials provided with the distribution.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
49 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
50 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
51 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
52 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
53 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
54 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
55 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
56 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
57 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
58 * POSSIBILITY OF SUCH DAMAGE.
59 */
60/*
61 * Copyright (c) 1986, 1989, 1991, 1993, 1995
62 *	The Regents of the University of California.  All rights reserved.
63 *
64 * Redistribution and use in source and binary forms, with or without
65 * modification, are permitted provided that the following conditions
66 * are met:
67 * 1. Redistributions of source code must retain the above copyright
68 *    notice, this list of conditions and the following disclaimer.
69 * 2. Redistributions in binary form must reproduce the above copyright
70 *    notice, this list of conditions and the following disclaimer in the
71 *    documentation and/or other materials provided with the distribution.
72 * 3. Neither the name of the University nor the names of its contributors
73 *    may be used to endorse or promote products derived from this software
74 *    without specific prior written permission.
75 *
76 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
77 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
78 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
79 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
80 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
81 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
82 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
83 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
84 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
85 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
86 * SUCH DAMAGE.
87 *
88 *	@(#)lfs_vnops.c	8.13 (Berkeley) 6/10/95
89 */
90
91#include <sys/cdefs.h>
92__KERNEL_RCSID(0, "$NetBSD: lfs_rename.c,v 1.25 2021/10/20 03:08:19 thorpej Exp $");
93
94#include <sys/param.h>
95#include <sys/systm.h>
96#include <sys/errno.h>
97#include <sys/namei.h>
98#include <sys/resourcevar.h>
99#include <sys/kernel.h>
100#include <sys/file.h>
101#include <sys/stat.h>
102#include <sys/buf.h>
103#include <sys/proc.h>
104#include <sys/mount.h>
105#include <sys/vnode.h>
106#include <sys/vnode_if.h>
107#include <sys/pool.h>
108#include <sys/signalvar.h>
109#include <sys/kauth.h>
110#include <sys/syslog.h>
111
112#include <miscfs/fifofs/fifo.h>
113#include <miscfs/genfs/genfs.h>
114#include <miscfs/specfs/specdev.h>
115
116#include <ufs/lfs/ulfs_inode.h>
117#include <ufs/lfs/ulfsmount.h>
118#include <ufs/lfs/ulfs_bswap.h>
119#include <ufs/lfs/ulfs_extern.h>
120
121#include <ufs/lfs/lfs.h>
122#include <ufs/lfs/lfs_accessors.h>
123#include <ufs/lfs/lfs_extern.h>
124
125/*
126 * ulfs_gro_directory_empty_p: Return true if the directory vp is
127 * empty.  dvp is its parent.
128 *
129 * vp and dvp must be locked and referenced.
130 */
131static bool
132ulfs_gro_directory_empty_p(struct mount *mp, kauth_cred_t cred,
133    struct vnode *vp, struct vnode *dvp)
134{
135
136	(void)mp;
137	KASSERT(mp != NULL);
138	KASSERT(vp != NULL);
139	KASSERT(dvp != NULL);
140	KASSERT(vp != dvp);
141	KASSERT(vp->v_mount == mp);
142	KASSERT(dvp->v_mount == mp);
143	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
144	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
145
146	return ulfs_dirempty(VTOI(vp), VTOI(dvp)->i_number, cred);
147}
148
149/*
150 * ulfs_gro_rename_check_possible: Check whether a rename is possible
151 * independent of credentials.
152 */
153static int
154ulfs_gro_rename_check_possible(struct mount *mp,
155    struct vnode *fdvp, struct vnode *fvp,
156    struct vnode *tdvp, struct vnode *tvp)
157{
158
159	(void)mp;
160	KASSERT(mp != NULL);
161	KASSERT(fdvp != NULL);
162	KASSERT(fvp != NULL);
163	KASSERT(tdvp != NULL);
164	KASSERT(fdvp != fvp);
165	KASSERT(fdvp != tvp);
166	KASSERT(tdvp != fvp);
167	KASSERT(tdvp != tvp);
168	KASSERT(fvp != tvp);
169	KASSERT(fdvp->v_type == VDIR);
170	KASSERT(tdvp->v_type == VDIR);
171	KASSERT(fdvp->v_mount == mp);
172	KASSERT(fvp->v_mount == mp);
173	KASSERT(tdvp->v_mount == mp);
174	KASSERT((tvp == NULL) || (tvp->v_mount == mp));
175	KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
176	KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
177	KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
178	KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
179
180	return genfs_ufslike_rename_check_possible(
181	    VTOI(fdvp)->i_flags, VTOI(fvp)->i_flags,
182	    VTOI(tdvp)->i_flags, (tvp? VTOI(tvp)->i_flags : 0),
183	    (tvp != NULL),
184	    IMMUTABLE, APPEND);
185}
186
187/*
188 * ulfs_gro_rename_check_permitted: Check whether a rename is permitted
189 * given our credentials.
190 */
191static int
192ulfs_gro_rename_check_permitted(struct mount *mp, kauth_cred_t cred,
193    struct vnode *fdvp, struct vnode *fvp,
194    struct vnode *tdvp, struct vnode *tvp)
195{
196
197	(void)mp;
198	KASSERT(mp != NULL);
199	KASSERT(fdvp != NULL);
200	KASSERT(fvp != NULL);
201	KASSERT(tdvp != NULL);
202	KASSERT(fdvp != fvp);
203	KASSERT(fdvp != tvp);
204	KASSERT(tdvp != fvp);
205	KASSERT(tdvp != tvp);
206	KASSERT(fvp != tvp);
207	KASSERT(fdvp->v_type == VDIR);
208	KASSERT(tdvp->v_type == VDIR);
209	KASSERT(fdvp->v_mount == mp);
210	KASSERT(fvp->v_mount == mp);
211	KASSERT(tdvp->v_mount == mp);
212	KASSERT((tvp == NULL) || (tvp->v_mount == mp));
213	KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
214	KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
215	KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
216	KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
217
218	return genfs_ufslike_rename_check_permitted(cred,
219	    fdvp, VTOI(fdvp)->i_mode, VTOI(fdvp)->i_uid,
220	    fvp, VTOI(fvp)->i_uid,
221	    tdvp, VTOI(tdvp)->i_mode, VTOI(tdvp)->i_uid,
222	    tvp, (tvp? VTOI(tvp)->i_uid : 0));
223}
224
225/*
226 * ulfs_gro_remove_check_possible: Check whether a remove is possible
227 * independent of credentials.
228 */
229static int
230ulfs_gro_remove_check_possible(struct mount *mp,
231    struct vnode *dvp, struct vnode *vp)
232{
233
234	(void)mp;
235	KASSERT(mp != NULL);
236	KASSERT(dvp != NULL);
237	KASSERT(vp != NULL);
238	KASSERT(dvp != vp);
239	KASSERT(dvp->v_type == VDIR);
240	KASSERT(vp->v_type != VDIR);
241	KASSERT(dvp->v_mount == mp);
242	KASSERT(vp->v_mount == mp);
243	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
244	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
245
246	return genfs_ufslike_remove_check_possible(
247	    VTOI(dvp)->i_flags, VTOI(vp)->i_flags,
248	    IMMUTABLE, APPEND);
249}
250
251/*
252 * ulfs_gro_remove_check_permitted: Check whether a remove is permitted
253 * given our credentials.
254 */
255static int
256ulfs_gro_remove_check_permitted(struct mount *mp, kauth_cred_t cred,
257    struct vnode *dvp, struct vnode *vp)
258{
259
260	(void)mp;
261	KASSERT(mp != NULL);
262	KASSERT(dvp != NULL);
263	KASSERT(vp != NULL);
264	KASSERT(dvp != vp);
265	KASSERT(dvp->v_type == VDIR);
266	KASSERT(vp->v_type != VDIR);
267	KASSERT(dvp->v_mount == mp);
268	KASSERT(vp->v_mount == mp);
269	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
270	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
271
272	return genfs_ufslike_remove_check_permitted(cred,
273	    dvp, VTOI(dvp)->i_mode, VTOI(dvp)->i_uid, vp, VTOI(vp)->i_uid);
274}
275
276/*
277 * ulfs_rename_ulr_overlap_p: True iff tulr overlaps with fulr so that
278 * entering a directory entry at tulr may move fulr.
279 */
280static bool
281ulfs_rename_ulr_overlap_p(const struct ulfs_lookup_results *fulr,
282    const struct ulfs_lookup_results *tulr)
283{
284	doff_t from_prev_start, from_prev_end, to_start, to_end;
285
286	KASSERT(fulr != NULL);
287	KASSERT(tulr != NULL);
288	KASSERT(fulr != tulr);
289
290	/*
291	 * fulr is from a DELETE lookup, so fulr->ulr_count is the size
292	 * of the preceding entry (d_reclen).
293	 */
294	from_prev_end = fulr->ulr_offset;
295	KASSERT(fulr->ulr_count <= from_prev_end);
296	from_prev_start = (from_prev_end - fulr->ulr_count);
297
298	/*
299	 * tulr is from a RENAME lookup, so tulr->ulr_count is the size
300	 * of the free space for an entry that we are about to fill.
301	 */
302	to_start = tulr->ulr_offset;
303	KASSERT(tulr->ulr_count < (LFS_MAXDIRSIZE - to_start));
304	to_end = (to_start + tulr->ulr_count);
305
306	return
307	    (((to_start <= from_prev_start) && (from_prev_start < to_end)) ||
308		((to_start <= from_prev_end) && (from_prev_end < to_end)));
309}
310
311/*
312 * ulfs_direct_namlen: Return the namlen of the directory entry ep from
313 * the directory vp.
314 */
315static int			/* XXX int?  uint8_t?  */
316ulfs_direct_namlen(const LFS_DIRHEADER *ep, const struct vnode *vp)
317{
318	struct lfs *fs;
319
320	KASSERT(ep != NULL);
321	KASSERT(vp != NULL);
322	KASSERT(VTOI(vp) != NULL);
323	KASSERT(VTOI(vp)->i_ump != NULL);
324	KASSERT(VTOI(vp)->i_lfs != NULL);
325	fs = VTOI(vp)->i_lfs;
326
327	return lfs_dir_getnamlen(fs, ep);
328}
329
330/*
331 * ulfs_rename_recalculate_fulr: If we have just entered a directory into
332 * dvp at tulr, and we were about to remove one at fulr for an entry
333 * named fcnp, fulr may be invalid.  So, if necessary, recalculate it.
334 */
335static int
336ulfs_rename_recalculate_fulr(struct vnode *dvp,
337    struct ulfs_lookup_results *fulr, const struct ulfs_lookup_results *tulr,
338    const struct componentname *fcnp)
339{
340	struct mount *mp;
341	struct lfs *fs;
342	struct ulfsmount *ump;
343	/* XXX int is a silly type for this; blame ulfsmount::um_dirblksiz.  */
344	int dirblksiz;
345	doff_t search_start, search_end;
346	doff_t offset;		/* Offset of entry we're examining.  */
347	struct buf *bp;		/* I/O block we're examining.  */
348	char *dirbuf;		/* Pointer into directory at search_start.  */
349	LFS_DIRHEADER *ep;	/* Pointer to the entry we're examining.  */
350	/* XXX direct::d_reclen is 16-bit;
351	 * ulfs_lookup_results::ulr_reclen is 32-bit.  Blah.  */
352	uint32_t reclen;	/* Length of the entry we're examining.  */
353	uint32_t prev_reclen;	/* Length of the preceding entry.  */
354	int error;
355
356	KASSERT(dvp != NULL);
357	KASSERT(dvp->v_mount != NULL);
358	KASSERT(VTOI(dvp) != NULL);
359	KASSERT(fulr != NULL);
360	KASSERT(tulr != NULL);
361	KASSERT(fulr != tulr);
362	KASSERT(ulfs_rename_ulr_overlap_p(fulr, tulr));
363
364	mp = dvp->v_mount;
365	ump = VFSTOULFS(mp);
366	fs = ump->um_lfs;
367	KASSERT(ump != NULL);
368	KASSERT(ump == VTOI(dvp)->i_ump);
369	KASSERT(fs == VTOI(dvp)->i_lfs);
370
371	dirblksiz = fs->um_dirblksiz;
372	KASSERT(0 < dirblksiz);
373	KASSERT((dirblksiz & (dirblksiz - 1)) == 0);
374
375	/* A directory block may not span across multiple I/O blocks.  */
376	KASSERT(dirblksiz <= mp->mnt_stat.f_iosize);
377
378	/* Find the bounds of the search.  */
379	search_start = tulr->ulr_offset;
380	KASSERT(fulr->ulr_reclen < (LFS_MAXDIRSIZE - fulr->ulr_offset));
381	search_end = (fulr->ulr_offset + fulr->ulr_reclen);
382
383	/* Compaction must happen only within a directory block. (*)  */
384	KASSERT(search_start <= search_end);
385	KASSERT((search_end - (search_start &~ (dirblksiz - 1))) <= dirblksiz);
386
387	dirbuf = NULL;
388	bp = NULL;
389	error = ulfs_blkatoff(dvp, (off_t)search_start, &dirbuf, &bp, false);
390	if (error)
391		return error;
392	KASSERT(dirbuf != NULL);
393	KASSERT(bp != NULL);
394
395	/*
396	 * Guarantee we sha'n't go past the end of the buffer we got.
397	 * dirbuf is bp->b_data + (search_start & (iosize - 1)), and
398	 * the valid range is [bp->b_data, bp->b_data + bp->b_bcount).
399	 */
400	KASSERT((search_end - search_start) <=
401	    (bp->b_bcount - (search_start & (mp->mnt_stat.f_iosize - 1))));
402
403	prev_reclen = fulr->ulr_count;
404	offset = search_start;
405
406	/*
407	 * Search from search_start to search_end for the entry matching
408	 * fcnp, which must be there because we found it before and it
409	 * should only at most have moved earlier.
410	 */
411	for (;;) {
412		KASSERT(search_start <= offset);
413		KASSERT(offset < search_end);
414
415		/*
416		 * Examine the directory entry at offset.
417		 */
418		ep = (LFS_DIRHEADER *)(dirbuf + (offset - search_start));
419		reclen = lfs_dir_getreclen(fs, ep);
420
421		if (lfs_dir_getino(fs, ep) == 0)
422			goto next;	/* Entry is unused.  */
423
424		if (lfs_dir_getino(fs, ep) == ULFS_WINO)
425			goto next;	/* Entry is whiteout.  */
426
427		if (fcnp->cn_namelen != ulfs_direct_namlen(ep, dvp))
428			goto next;	/* Wrong name length.  */
429
430		if (memcmp(lfs_dir_nameptr(fs, ep), fcnp->cn_nameptr, fcnp->cn_namelen))
431			goto next;	/* Wrong name.  */
432
433		/* Got it!  */
434		break;
435
436next:
437		if (! ((reclen < search_end) &&
438			(offset < (search_end - reclen)))) {
439			brelse(bp, 0);
440			return EIO;	/* XXX Panic?  What?  */
441		}
442
443		/* We may not move past the search end.  */
444		KASSERT(reclen < search_end);
445		KASSERT(offset < (search_end - reclen));
446
447		/*
448		 * We may not move across a directory block boundary;
449		 * see (*) above.
450		 */
451		KASSERT((offset &~ (dirblksiz - 1)) ==
452		    ((offset + reclen) &~ (dirblksiz - 1)));
453
454		prev_reclen = reclen;
455		offset += reclen;
456	}
457
458	/*
459	 * Found the entry.  Record where.
460	 */
461	fulr->ulr_offset = offset;
462	fulr->ulr_reclen = reclen;
463
464	/*
465	 * Record the preceding record length, but not if we're at the
466	 * start of a directory block.
467	 */
468	fulr->ulr_count = ((offset & (dirblksiz - 1))? prev_reclen : 0);
469
470	brelse(bp, 0);
471	return 0;
472}
473
474/*
475 * ulfs_gro_remove: Rename an object over another link to itself,
476 * effectively removing just the original link.
477 */
478static int
479ulfs_gro_remove(struct mount *mp, kauth_cred_t cred,
480    struct vnode *dvp, struct componentname *cnp, void *de, struct vnode *vp,
481    nlink_t *tvp_nlinkp)
482{
483	struct ulfs_lookup_results *ulr = de;
484	int error;
485
486	KASSERT(mp != NULL);
487	KASSERT(dvp != NULL);
488	KASSERT(cnp != NULL);
489	KASSERT(ulr != NULL);
490	KASSERT(vp != NULL);
491	KASSERT(dvp != vp);
492	KASSERT(dvp->v_mount == mp);
493	KASSERT(vp->v_mount == mp);
494	KASSERT(dvp->v_type == VDIR);
495	KASSERT(vp->v_type != VDIR);
496	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
497	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
498	KASSERT(cnp->cn_nameiop == DELETE);
499
500	/* XXX ulfs_dirremove decrements vp's link count for us.  */
501	error = ulfs_dirremove(dvp, ulr, VTOI(vp), cnp->cn_flags, 0);
502
503	*tvp_nlinkp = VTOI(vp)->i_nlink;
504
505	return error;
506}
507
508/*
509 * ulfs_gro_lookup: Look up and save the lookup results.
510 */
511static int
512ulfs_gro_lookup(struct mount *mp, struct vnode *dvp,
513    struct componentname *cnp, void *de_ret, struct vnode **vp_ret)
514{
515	struct ulfs_lookup_results *ulr_ret = de_ret;
516	struct vnode *vp = NULL;
517	int error;
518
519	(void)mp;
520	KASSERT(mp != NULL);
521	KASSERT(dvp != NULL);
522	KASSERT(cnp != NULL);
523	KASSERT(ulr_ret != NULL);
524	KASSERT(vp_ret != NULL);
525	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
526
527	/* Kludge cargo-culted from dholland's ulfs_rename.  */
528	cnp->cn_flags &=~ MODMASK;
529	cnp->cn_flags |= (LOCKPARENT | LOCKLEAF);
530
531	error = relookup(dvp, &vp, cnp, 0 /* dummy */);
532	if ((error == 0) && (vp == NULL)) {
533		error = ENOENT;
534		goto out;
535	} else if (error) {
536		return error;
537	}
538
539	/*
540	 * Thanks to VFS insanity, relookup locks vp, which screws us
541	 * in various ways.
542	 */
543	KASSERT(vp != NULL);
544	VOP_UNLOCK(vp);
545
546out:	*ulr_ret = VTOI(dvp)->i_crap;
547	*vp_ret = vp;
548	return error;
549}
550
551/*
552 * ulfs_rmdired_p: Check whether the directory vp has been rmdired.
553 *
554 * vp must be locked and referenced.
555 */
556static bool
557ulfs_rmdired_p(struct vnode *vp)
558{
559
560	KASSERT(vp != NULL);
561	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
562	KASSERT(vp->v_type == VDIR);
563
564	/* XXX Is this correct?  */
565	return (VTOI(vp)->i_size == 0);
566}
567
568/*
569 * ulfs_read_dotdot: Store in *ino_ret the inode number of the parent
570 * of the directory vp.
571 */
572static int
573ulfs_read_dotdot(struct vnode *vp, kauth_cred_t cred, ino_t *ino_ret)
574{
575	struct lfs *fs;
576	union lfs_dirtemplate dirbuf;
577	LFS_DIRHEADER *dotdot;
578	const char *name;
579	int error;
580
581	KASSERT(vp != NULL);
582	KASSERT(ino_ret != NULL);
583	KASSERT(vp->v_type == VDIR);
584
585	KASSERT(VTOI(vp) != NULL);
586	KASSERT(VTOI(vp)->i_lfs != NULL);
587	fs = VTOI(vp)->i_lfs;
588
589	error = ulfs_bufio(UIO_READ, vp, &dirbuf, sizeof dirbuf, (off_t)0,
590	    IO_NODELOCKED, cred, NULL, NULL);
591	if (error)
592		return error;
593
594	dotdot = lfs_dirtemplate_dotdot(fs, &dirbuf);
595	name = lfs_dirtemplate_dotdotname(fs, &dirbuf);
596	if (lfs_dir_getnamlen(fs, dotdot) != 2 ||
597	    name[0] != '.' ||
598	    name[1] != '.')
599		/* XXX Panic?  Print warning?  */
600		return ENOTDIR;
601
602	*ino_ret = lfs_dir_getino(fs, dotdot);
603	return 0;
604}
605
606/*
607 * ulfs_gro_lock_directory: Lock the directory vp, but fail if it has
608 * been rmdir'd.
609 */
610static int
611ulfs_gro_lock_directory(struct mount *mp, struct vnode *vp)
612{
613
614	(void)mp;
615	KASSERT(mp != NULL);
616	KASSERT(vp != NULL);
617	KASSERT(vp->v_mount == mp);
618
619	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
620
621	if (ulfs_rmdired_p(vp)) {
622		VOP_UNLOCK(vp);
623		return ENOENT;
624	}
625
626	return 0;
627}
628
629/*
630 * ulfs_gro_genealogy: Analyze the genealogy of the source and target
631 * directories.
632 */
633static int
634ulfs_gro_genealogy(struct mount *mp, kauth_cred_t cred,
635    struct vnode *fdvp, struct vnode *tdvp,
636    struct vnode **intermediate_node_ret)
637{
638	struct vnode *vp, *dvp;
639	ino_t dotdot_ino = -1;	/* XXX  gcc 4.8: maybe-uninitialized */
640	int error;
641
642	KASSERT(mp != NULL);
643	KASSERT(fdvp != NULL);
644	KASSERT(tdvp != NULL);
645	KASSERT(fdvp != tdvp);
646	KASSERT(intermediate_node_ret != NULL);
647	KASSERT(fdvp->v_mount == mp);
648	KASSERT(tdvp->v_mount == mp);
649	KASSERT(fdvp->v_type == VDIR);
650	KASSERT(tdvp->v_type == VDIR);
651
652	/*
653	 * We need to provisionally lock tdvp to keep rmdir from
654	 * deleting it -- or any ancestor -- at an inopportune moment.
655	 */
656	error = ulfs_gro_lock_directory(mp, tdvp);
657	if (error)
658		return error;
659
660	vp = tdvp;
661	vref(vp);
662
663	for (;;) {
664		KASSERT(vp != NULL);
665		KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
666		KASSERT(vp->v_mount == mp);
667		KASSERT(vp->v_type == VDIR);
668		KASSERT(!ulfs_rmdired_p(vp));
669
670		/* Did we hit the root without finding fdvp?  */
671		if (VTOI(vp)->i_number == ULFS_ROOTINO) {
672			vput(vp);
673			*intermediate_node_ret = NULL;
674			return 0;
675		}
676
677		error = ulfs_read_dotdot(vp, cred, &dotdot_ino);
678		if (error) {
679			vput(vp);
680			return error;
681		}
682
683		/* Did we find that fdvp is an ancestor of tdvp?  */
684		if (VTOI(fdvp)->i_number == dotdot_ino) {
685			/* Unlock vp, but keep it referenced.  */
686			VOP_UNLOCK(vp);
687			*intermediate_node_ret = vp;
688			return 0;
689		}
690
691		/* Neither -- keep ascending the family tree.  */
692		error = vcache_get(mp, &dotdot_ino, sizeof(dotdot_ino), &dvp);
693		vput(vp);
694		if (error)
695			return error;
696		error = vn_lock(dvp, LK_EXCLUSIVE);
697		if (error) {
698			vrele(dvp);
699			return error;
700		}
701
702		KASSERT(dvp != NULL);
703		KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
704		vp = dvp;
705
706		if (vp->v_type != VDIR) {
707			/*
708			 * XXX Panic?  Print a warning?  Can this
709			 * happen if we lose the race I suspect to
710			 * exist above, and the `..' inode number has
711			 * been recycled?
712			 */
713			vput(vp);
714			return ENOTDIR;
715		}
716
717		if (ulfs_rmdired_p(vp)) {
718			vput(vp);
719			return ENOENT;
720		}
721	}
722}
723
724/*
725 * ulfs_gro_rename: Actually perform the rename operation.
726 */
727static int
728ulfs_gro_rename(struct mount *mp, kauth_cred_t cred,
729    struct vnode *fdvp, struct componentname *fcnp,
730    void *fde, struct vnode *fvp,
731    struct vnode *tdvp, struct componentname *tcnp,
732    void *tde, struct vnode *tvp, nlink_t *tvp_nlinkp)
733{
734	struct lfs *fs;
735	struct ulfs_lookup_results *fulr = fde;
736	struct ulfs_lookup_results *tulr = tde;
737	bool directory_p, reparent_p;
738	int error;
739
740	KASSERT(mp != NULL);
741	KASSERT(fdvp != NULL);
742	KASSERT(fcnp != NULL);
743	KASSERT(fulr != NULL);
744	KASSERT(fvp != NULL);
745	KASSERT(tdvp != NULL);
746	KASSERT(tcnp != NULL);
747	KASSERT(tulr != NULL);
748	KASSERT(fulr != tulr);
749	KASSERT(fdvp != fvp);
750	KASSERT(fdvp != tvp);
751	KASSERT(tdvp != fvp);
752	KASSERT(tdvp != tvp);
753	KASSERT(fvp != tvp);
754	KASSERT(fdvp->v_mount == mp);
755	KASSERT(fvp->v_mount == mp);
756	KASSERT(tdvp->v_mount == mp);
757	KASSERT((tvp == NULL) || (tvp->v_mount == mp));
758	KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
759	KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
760	KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
761	KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
762
763	fs = VTOI(fdvp)->i_lfs;
764	KASSERT(fs == VTOI(tdvp)->i_lfs);
765
766	/*
767	 * We shall need to temporarily bump the link count, so make
768	 * sure there is room to do so.
769	 */
770	if ((nlink_t)VTOI(fvp)->i_nlink >= LINK_MAX)
771		return EMLINK;
772
773	directory_p = (fvp->v_type == VDIR);
774	KASSERT(directory_p == ((VTOI(fvp)->i_mode & LFS_IFMT) == LFS_IFDIR));
775	KASSERT((tvp == NULL) || (directory_p == (tvp->v_type == VDIR)));
776	KASSERT((tvp == NULL) || (directory_p ==
777		((VTOI(tvp)->i_mode & LFS_IFMT) == LFS_IFDIR)));
778
779	reparent_p = (fdvp != tdvp);
780	KASSERT(reparent_p == (VTOI(fdvp)->i_number != VTOI(tdvp)->i_number));
781
782	/*
783	 * Commence hacking of the data on disk.
784	 */
785
786	error = 0;
787
788	/*
789	 * 1) Bump link count while we're moving stuff
790	 *    around.  If we crash somewhere before
791	 *    completing our work, the link count
792	 *    may be wrong, but correctable.
793	 */
794
795	KASSERT((nlink_t)VTOI(fvp)->i_nlink < LINK_MAX);
796	VTOI(fvp)->i_nlink++;
797	DIP_ASSIGN(VTOI(fvp), nlink, VTOI(fvp)->i_nlink);
798	VTOI(fvp)->i_state |= IN_CHANGE;
799	error = lfs_update(fvp, NULL, NULL, UPDATE_DIROP);
800	if (error)
801		goto whymustithurtsomuch;
802
803	/*
804	 * 2) If target doesn't exist, link the target
805	 *    to the source and unlink the source.
806	 *    Otherwise, rewrite the target directory
807	 *    entry to reference the source inode and
808	 *    expunge the original entry's existence.
809	 */
810
811	if (tvp == NULL) {
812		/*
813		 * Account for ".." in new directory.
814		 * When source and destination have the same
815		 * parent we don't fool with the link count.
816		 */
817		if (directory_p && reparent_p) {
818			if ((nlink_t)VTOI(tdvp)->i_nlink >= LINK_MAX) {
819				error = EMLINK;
820				goto whymustithurtsomuch;
821			}
822			KASSERT((nlink_t)VTOI(tdvp)->i_nlink < LINK_MAX);
823			VTOI(tdvp)->i_nlink++;
824			DIP_ASSIGN(VTOI(tdvp), nlink, VTOI(tdvp)->i_nlink);
825			VTOI(tdvp)->i_state |= IN_CHANGE;
826			error = lfs_update(tdvp, NULL, NULL, UPDATE_DIROP);
827			if (error) {
828				/*
829				 * Link count update didn't take --
830				 * back out the in-memory link count.
831				 */
832				KASSERT(0 < VTOI(tdvp)->i_nlink);
833				VTOI(tdvp)->i_nlink--;
834				DIP_ASSIGN(VTOI(tdvp), nlink,
835				    VTOI(tdvp)->i_nlink);
836				VTOI(tdvp)->i_state |= IN_CHANGE;
837				goto whymustithurtsomuch;
838			}
839		}
840
841		error = ulfs_direnter(tdvp, tulr,
842		    NULL, tcnp, VTOI(fvp)->i_number, LFS_IFTODT(VTOI(fvp)->i_mode),
843		    NULL);
844		if (error) {
845			if (directory_p && reparent_p) {
846				/*
847				 * Directory update didn't take, but
848				 * the link count update did -- back
849				 * out the in-memory link count and the
850				 * on-disk link count.
851				 */
852				KASSERT(0 < VTOI(tdvp)->i_nlink);
853				VTOI(tdvp)->i_nlink--;
854				DIP_ASSIGN(VTOI(tdvp), nlink,
855				    VTOI(tdvp)->i_nlink);
856				VTOI(tdvp)->i_state |= IN_CHANGE;
857				(void)lfs_update(tdvp, NULL, NULL,
858				    UPDATE_WAIT | UPDATE_DIROP);
859			}
860			goto whymustithurtsomuch;
861		}
862	} else {
863		if (directory_p)
864			/* XXX WTF?  Why purge here?  Why not purge others?  */
865			cache_purge(tdvp);
866
867		/*
868		 * Make the target directory's entry for tcnp point at
869		 * the source node.
870		 *
871		 * XXX ulfs_dirrewrite decrements tvp's link count, but
872		 * doesn't touch the link count of the new inode.  Go
873		 * figure.
874		 */
875		error = ulfs_dirrewrite(VTOI(tdvp), tulr->ulr_offset,
876		    VTOI(tvp), VTOI(fvp)->i_number, LFS_IFTODT(VTOI(fvp)->i_mode),
877		    ((directory_p && reparent_p) ? reparent_p : directory_p),
878		    IN_CHANGE | IN_UPDATE);
879		if (error)
880			goto whymustithurtsomuch;
881
882		/*
883		 * If the source and target are directories, and the
884		 * target is in the same directory as the source,
885		 * decrement the link count of the common parent
886		 * directory, since we are removing the target from
887		 * that directory.
888		 */
889		if (directory_p && !reparent_p) {
890			KASSERT(fdvp == tdvp);
891			/* XXX check, don't kassert */
892			KASSERT(0 < VTOI(tdvp)->i_nlink);
893			VTOI(tdvp)->i_nlink--;
894			DIP_ASSIGN(VTOI(tdvp), nlink, VTOI(tdvp)->i_nlink);
895			VTOI(tdvp)->i_state |= IN_CHANGE;
896		}
897
898		if (directory_p) {
899			/*
900			 * XXX I don't understand the following comment
901			 * from ulfs_rename -- in particular, the part
902			 * about `there may be other hard links'.
903			 *
904			 * Truncate inode. The only stuff left in the directory
905			 * is "." and "..". The "." reference is inconsequential
906			 * since we are quashing it. We have removed the "."
907			 * reference and the reference in the parent directory,
908			 * but there may be other hard links.
909			 *
910			 * XXX The ulfs_dirempty call earlier does
911			 * not guarantee anything about nlink.
912			 */
913			if (VTOI(tvp)->i_nlink != 1)
914				ulfs_dirbad(VTOI(tvp), (doff_t)0,
915				    "hard-linked directory");
916			VTOI(tvp)->i_nlink = 0;
917			DIP_ASSIGN(VTOI(tvp), nlink, 0);
918			error = lfs_truncate(tvp, (off_t)0, IO_SYNC, cred);
919			if (error)
920				goto whymustithurtsomuch;
921		}
922	}
923
924	/*
925	 * If the source is a directory with a new parent, the link
926	 * count of the old parent directory must be decremented and
927	 * ".." set to point to the new parent.
928	 *
929	 * XXX ulfs_dirrewrite updates the link count of fdvp, but not
930	 * the link count of fvp or the link count of tdvp.  Go figure.
931	 */
932	if (directory_p && reparent_p) {
933		off_t position;
934
935		/*
936		 * The .. entry goes immediately after the . entry, so
937		 * the position is the record length of the . entry,
938		 * namely LFS_DIRECTSIZ(1).
939		 */
940		position = LFS_DIRECTSIZ(fs, 1);
941		error = ulfs_dirrewrite(VTOI(fvp), position,
942		    VTOI(fdvp), VTOI(tdvp)->i_number, LFS_DT_DIR, 0, IN_CHANGE);
943#if 0		/* XXX This branch was not in ulfs_rename! */
944		if (error)
945			goto whymustithurtsomuch;
946#endif
947
948		/* XXX WTF?  Why purge here?  Why not purge others?  */
949		cache_purge(fdvp);
950	}
951
952	/*
953	 * 3) Unlink the source.
954	 */
955
956	/*
957	 * ulfs_direnter may compact the directory in the process of
958	 * inserting a new entry.  That may invalidate fulr, which we
959	 * need in order to remove the old entry.  In that case, we
960	 * need to recalculate what fulr should be.
961	 */
962	if (!reparent_p && (tvp == NULL) &&
963	    ulfs_rename_ulr_overlap_p(fulr, tulr)) {
964		error = ulfs_rename_recalculate_fulr(fdvp, fulr, tulr, fcnp);
965#if 0				/* XXX */
966		if (error)	/* XXX Try to back out changes?  */
967			goto whymustithurtsomuch;
968#endif
969	}
970
971	/*
972	 * XXX 0 means !isrmdir.  But can't this be an rmdir?
973	 * XXX Well, turns out that argument to ulfs_dirremove is ignored...
974	 * XXX And it turns out ulfs_dirremove updates the link count of fvp.
975	 * XXX But it doesn't update the link count of fdvp.  Go figure.
976	 * XXX fdvp's link count is updated in ulfs_dirrewrite instead.
977	 * XXX Actually, sometimes it doesn't update fvp's link count.
978	 * XXX I hate the world.
979	 */
980	error = ulfs_dirremove(fdvp, fulr, VTOI(fvp), fcnp->cn_flags, 0);
981	if (error)
982#if 0				/* XXX */
983		goto whymustithurtsomuch;
984#endif
985		goto arghmybrainhurts;
986
987	if (tvp != NULL) {
988		*tvp_nlinkp = VTOI(tvp)->i_nlink;
989	}
990#if 0				/* XXX */
991	genfs_rename_cache_purge(fdvp, fvp, tdvp, tvp);
992#endif
993	goto arghmybrainhurts;
994
995whymustithurtsomuch:
996	KASSERT(0 < VTOI(fvp)->i_nlink);
997	VTOI(fvp)->i_nlink--;
998	DIP_ASSIGN(VTOI(fvp), nlink, VTOI(fvp)->i_nlink);
999	VTOI(fvp)->i_state |= IN_CHANGE;
1000
1001arghmybrainhurts:
1002/*ihateyou:*/
1003	return error;
1004}
1005
1006/*
1007 * lfs_gro_rename: Actually perform the rename operation.  Do a little
1008 * LFS bookkeeping and then defer to ulfs_gro_rename.
1009 */
1010static int
1011lfs_gro_rename(struct mount *mp, kauth_cred_t cred,
1012    struct vnode *fdvp, struct componentname *fcnp,
1013    void *fde, struct vnode *fvp,
1014    struct vnode *tdvp, struct componentname *tcnp,
1015    void *tde, struct vnode *tvp, nlink_t *tvp_nlinkp)
1016{
1017	int error;
1018
1019	KASSERT(mp != NULL);
1020	KASSERT(fdvp != NULL);
1021	KASSERT(fcnp != NULL);
1022	KASSERT(fde != NULL);
1023	KASSERT(fvp != NULL);
1024	KASSERT(tdvp != NULL);
1025	KASSERT(tcnp != NULL);
1026	KASSERT(tde != NULL);
1027	KASSERT(fdvp != fvp);
1028	KASSERT(fdvp != tvp);
1029	KASSERT(tdvp != fvp);
1030	KASSERT(tdvp != tvp);
1031	KASSERT(fvp != tvp);
1032	KASSERT(fdvp->v_mount == mp);
1033	KASSERT(fvp->v_mount == mp);
1034	KASSERT(tdvp->v_mount == mp);
1035	KASSERT((tvp == NULL) || (tvp->v_mount == mp));
1036	KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
1037	KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
1038	KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
1039	KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
1040
1041	error = lfs_set_dirop(tdvp, tvp);
1042	if (error != 0)
1043		return error;
1044
1045	MARK_VNODE(fdvp);
1046	MARK_VNODE(fvp);
1047
1048	error = ulfs_gro_rename(mp, cred,
1049	    fdvp, fcnp, fde, fvp,
1050	    tdvp, tcnp, tde, tvp,
1051	    tvp_nlinkp);
1052
1053	if (tvp && VTOI(tvp)->i_nlink == 0)
1054		lfs_orphan(VTOI(tvp)->i_lfs, VTOI(tvp)->i_number);
1055
1056	UNMARK_VNODE(fdvp);
1057	UNMARK_VNODE(fvp);
1058	UNMARK_VNODE(tdvp);
1059	if (tvp) {
1060		UNMARK_VNODE(tvp);
1061	}
1062	lfs_unset_dirop(VFSTOULFS(mp)->um_lfs, tdvp, "rename");
1063	vrele(tdvp);
1064	if (tvp) {
1065		vrele(tvp);
1066	}
1067
1068	return error;
1069}
1070
1071static const struct genfs_rename_ops lfs_genfs_rename_ops = {
1072	.gro_directory_empty_p		= ulfs_gro_directory_empty_p,
1073	.gro_rename_check_possible	= ulfs_gro_rename_check_possible,
1074	.gro_rename_check_permitted	= ulfs_gro_rename_check_permitted,
1075	.gro_remove_check_possible	= ulfs_gro_remove_check_possible,
1076	.gro_remove_check_permitted	= ulfs_gro_remove_check_permitted,
1077	.gro_rename			= lfs_gro_rename,
1078	.gro_remove			= ulfs_gro_remove,
1079	.gro_lookup			= ulfs_gro_lookup,
1080	.gro_genealogy			= ulfs_gro_genealogy,
1081	.gro_lock_directory		= ulfs_gro_lock_directory,
1082};
1083
1084/*
1085 * lfs_sane_rename: The hairiest vop, with the saner API.
1086 *
1087 * Arguments:
1088 *
1089 * . fdvp (from directory vnode),
1090 * . fcnp (from component name),
1091 * . tdvp (to directory vnode),
1092 * . tcnp (to component name),
1093 * . cred (credentials structure), and
1094 * . posixly_correct (flag for behaviour if target & source link same file).
1095 *
1096 * fdvp and tdvp may be the same, and must be referenced and unlocked.
1097 */
1098static int
1099lfs_sane_rename(
1100    struct vnode *fdvp, struct componentname *fcnp,
1101    struct vnode *tdvp, struct componentname *tcnp,
1102    kauth_cred_t cred, bool posixly_correct)
1103{
1104	struct ulfs_lookup_results fulr, tulr;
1105
1106	/*
1107	 * XXX Provisional kludge -- ulfs_lookup does not reject rename
1108	 * of . or .. (from or to), so we hack it here.  This is not
1109	 * the right place: it should be caller's responsibility to
1110	 * reject this case.
1111	 */
1112	KASSERT(fcnp != NULL);
1113	KASSERT(tcnp != NULL);
1114	KASSERT(fcnp != tcnp);
1115	KASSERT(fcnp->cn_nameptr != NULL);
1116	KASSERT(tcnp->cn_nameptr != NULL);
1117
1118	if ((fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT)
1119		return EINVAL;	/* XXX EISDIR?  */
1120	if ((fcnp->cn_namelen == 1) && (fcnp->cn_nameptr[0] == '.'))
1121		return EINVAL;
1122	if ((tcnp->cn_namelen == 1) && (tcnp->cn_nameptr[0] == '.'))
1123		return EINVAL;
1124
1125	return genfs_sane_rename(&lfs_genfs_rename_ops,
1126	    fdvp, fcnp, &fulr, tdvp, tcnp, &tulr,
1127	    cred, posixly_correct);
1128}
1129
1130/*
1131 * lfs_rename: The hairiest vop, with the insanest API.  Defer to
1132 * genfs_insane_rename immediately.
1133 */
1134int
1135lfs_rename(void *v)
1136{
1137
1138	return genfs_insane_rename(v, &lfs_sane_rename);
1139}
1140