xref: /openbsd-src/sys/ufs/ext2fs/ext2fs_subr.c (revision 307cfebb4763f3c4ca6ad5215fb00804000935ec)
1*307cfebbSjsg /*	$OpenBSD: ext2fs_subr.c,v 1.38 2024/10/08 02:58:26 jsg Exp $	*/
21414b0faSart /*	$NetBSD: ext2fs_subr.c,v 1.1 1997/06/11 09:34:03 bouyer Exp $	*/
35ac2d602Sdownsj 
45ac2d602Sdownsj /*
51f3ff51cSdownsj  * Copyright (c) 1997 Manuel Bouyer.
65ac2d602Sdownsj  * Copyright (c) 1982, 1986, 1989, 1993
75ac2d602Sdownsj  *	The Regents of the University of California.  All rights reserved.
85ac2d602Sdownsj  *
95ac2d602Sdownsj  * Redistribution and use in source and binary forms, with or without
105ac2d602Sdownsj  * modification, are permitted provided that the following conditions
115ac2d602Sdownsj  * are met:
125ac2d602Sdownsj  * 1. Redistributions of source code must retain the above copyright
135ac2d602Sdownsj  *    notice, this list of conditions and the following disclaimer.
145ac2d602Sdownsj  * 2. Redistributions in binary form must reproduce the above copyright
155ac2d602Sdownsj  *    notice, this list of conditions and the following disclaimer in the
165ac2d602Sdownsj  *    documentation and/or other materials provided with the distribution.
1729295d1cSmillert  * 3. Neither the name of the University nor the names of its contributors
185ac2d602Sdownsj  *    may be used to endorse or promote products derived from this software
195ac2d602Sdownsj  *    without specific prior written permission.
205ac2d602Sdownsj  *
215ac2d602Sdownsj  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
225ac2d602Sdownsj  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
235ac2d602Sdownsj  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
245ac2d602Sdownsj  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
255ac2d602Sdownsj  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
265ac2d602Sdownsj  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
275ac2d602Sdownsj  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
285ac2d602Sdownsj  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
295ac2d602Sdownsj  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
305ac2d602Sdownsj  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
315ac2d602Sdownsj  * SUCH DAMAGE.
325ac2d602Sdownsj  *
335ac2d602Sdownsj  *	@(#)ffs_subr.c	8.2 (Berkeley) 9/21/93
341f3ff51cSdownsj  * Modified for ext2fs by Manuel Bouyer.
355ac2d602Sdownsj  */
365ac2d602Sdownsj 
375ac2d602Sdownsj #include <sys/param.h>
385ac2d602Sdownsj #include <sys/systm.h>
395ac2d602Sdownsj #include <sys/vnode.h>
40895e8cacStedu #include <sys/mount.h>
415ac2d602Sdownsj #include <sys/buf.h>
42544451c3Sderaadt #include <sys/specdev.h>
43895e8cacStedu 
445ac2d602Sdownsj #include <ufs/ufs/quota.h>
455ac2d602Sdownsj #include <ufs/ufs/inode.h>
46895e8cacStedu #include <ufs/ufs/ufsmount.h>
47895e8cacStedu 
48d4c58812Sart #include <ufs/ext2fs/ext2fs.h>
49d4c58812Sart #include <ufs/ext2fs/ext2fs_extern.h>
50ea0c9824Spelikan #include <ufs/ext2fs/ext2fs_extents.h>
51d4c58812Sart 
52d4c58812Sart #ifdef _KERNEL
535ac2d602Sdownsj 
545ac2d602Sdownsj /*
555ac2d602Sdownsj  * Return buffer with the contents of block "offset" from the beginning of
565ac2d602Sdownsj  * directory "ip".  If "res" is non-zero, fill it in with a pointer to the
575ac2d602Sdownsj  * remaining space in the directory.
585ac2d602Sdownsj  */
595ac2d602Sdownsj int
60b080ad39Scsapuntz ext2fs_bufatoff(struct inode *ip, off_t offset, char **res, struct buf **bpp)
615ac2d602Sdownsj {
62b080ad39Scsapuntz 	struct vnode *vp;
63b080ad39Scsapuntz 	struct m_ext2fs *fs;
645ac2d602Sdownsj 	struct buf *bp;
65ea0c9824Spelikan 	daddr_t lbn, pos;
665ac2d602Sdownsj 	int error;
675ac2d602Sdownsj 
68b080ad39Scsapuntz 	vp = ITOV(ip);
695ac2d602Sdownsj 	fs = ip->i_e2fs;
70b080ad39Scsapuntz 	lbn = lblkno(fs, offset);
715ac2d602Sdownsj 
72ea0c9824Spelikan 	if (ip->i_e2din->e2di_flags & EXT4_EXTENTS) {
73ea0c9824Spelikan 		struct ext4_extent_path path;
74ea0c9824Spelikan 		struct ext4_extent *ep;
75ea0c9824Spelikan 
76ea0c9824Spelikan 		memset(&path, 0, sizeof path);
77ea0c9824Spelikan 		if (ext4_ext_find_extent(fs, ip, lbn, &path) == NULL ||
78ea0c9824Spelikan 		    (ep = path.ep_ext) == NULL)
79ea0c9824Spelikan 			goto normal;
80ea0c9824Spelikan 
81ea0c9824Spelikan 		if (path.ep_bp != NULL) {
82ea0c9824Spelikan 			brelse(path.ep_bp);
83ea0c9824Spelikan 			path.ep_bp = NULL;
84ea0c9824Spelikan 		}
85ea0c9824Spelikan 		pos = lbn - ep->e_blk + (((daddr_t)ep->e_start_hi << 32) | ep->e_start_lo);
86ea0c9824Spelikan 		error = bread(ip->i_devvp, fsbtodb(fs, pos), fs->e2fs_bsize, &bp);
87ea0c9824Spelikan 		if (error) {
88ea0c9824Spelikan 			brelse(bp);
89ea0c9824Spelikan 			return (error);
90ea0c9824Spelikan 		}
91ea0c9824Spelikan 
92ea0c9824Spelikan 		if (res)
93ea0c9824Spelikan 			*res = (char *)bp->b_data + blkoff(fs, offset);
94ea0c9824Spelikan 
95ea0c9824Spelikan 		*bpp = bp;
96ea0c9824Spelikan 
97ea0c9824Spelikan 		return (0);
98ea0c9824Spelikan 	}
99ea0c9824Spelikan 
100ea0c9824Spelikan  normal:
101b080ad39Scsapuntz 	*bpp = NULL;
10293f62a9eStedu 	if ((error = bread(vp, lbn, fs->e2fs_bsize, &bp)) != 0) {
1035ac2d602Sdownsj 		brelse(bp);
1045ac2d602Sdownsj 		return (error);
1055ac2d602Sdownsj 	}
106b080ad39Scsapuntz 	if (res)
107b080ad39Scsapuntz 		*res = (char *)bp->b_data + blkoff(fs, offset);
108b080ad39Scsapuntz 	*bpp = bp;
1095ac2d602Sdownsj 	return (0);
1105ac2d602Sdownsj }
1115ac2d602Sdownsj #endif
1125ac2d602Sdownsj 
1132374824dSpedro /*
1142374824dSpedro  * Initialize the vnode associated with a new inode, handle aliased vnodes.
1152374824dSpedro  */
1162374824dSpedro int
1174af3a708Snatano ext2fs_vinit(struct mount *mp, struct vnode **vpp)
1182374824dSpedro {
1192374824dSpedro 	struct inode *ip;
1202374824dSpedro 	struct vnode *vp, *nvp;
1212374824dSpedro 	struct timeval tv;
1222374824dSpedro 
1232374824dSpedro 	vp = *vpp;
1242374824dSpedro 	ip = VTOI(vp);
1252374824dSpedro 	vp->v_type = IFTOVT(ip->i_e2fs_mode);
1262374824dSpedro 
1272374824dSpedro 	switch(vp->v_type) {
1282374824dSpedro 	case VCHR:
1292374824dSpedro 	case VBLK:
1304af3a708Snatano 		vp->v_op = &ext2fs_specvops;
1312374824dSpedro 
132f7dbefaaSpelikan 		nvp = checkalias(vp, letoh32(ip->i_e2din->e2di_rdev), mp);
1332374824dSpedro 		if (nvp != NULL) {
1342374824dSpedro 			/*
1352374824dSpedro 			 * Discard unneeded vnode, but save its inode. Note
1362374824dSpedro 			 * that the lock is carried over in the inode to the
1372374824dSpedro 			 * replacement vnode.
1382374824dSpedro 			 */
1392374824dSpedro 			nvp->v_data = vp->v_data;
1402374824dSpedro 			vp->v_data = NULL;
141dc81e71aSthib 			vp->v_op = &spec_vops;
14205ee8c21Ssemarie #ifdef VFSLCKDEBUG
14305ee8c21Ssemarie 			vp->v_flag &= ~VLOCKSWORK;
14405ee8c21Ssemarie #endif
1452374824dSpedro 			vrele(vp);
1462374824dSpedro 			vgone(vp);
1472374824dSpedro 			/* Reinitialize aliased vnode. */
1482374824dSpedro 			vp = nvp;
1492374824dSpedro 			ip->i_vnode = vp;
1502374824dSpedro 		}
1512374824dSpedro 
1522374824dSpedro 		break;
1532374824dSpedro 
1542374824dSpedro 	case VFIFO:
1552374824dSpedro #ifdef FIFO
1564af3a708Snatano 		vp->v_op = &ext2fs_fifovops;
1572374824dSpedro 		break;
1582374824dSpedro #else
1592374824dSpedro 		return (EOPNOTSUPP);
1602374824dSpedro #endif /* FIFO */
1612374824dSpedro 
1622374824dSpedro 	default:
1632374824dSpedro 
1642374824dSpedro 		break;
1652374824dSpedro 	}
1662374824dSpedro 
1672374824dSpedro 	if (ip->i_number == EXT2_ROOTINO)
1682374824dSpedro 		vp->v_flag |= VROOT;
1692374824dSpedro 
1702374824dSpedro 	/* Initialize modrev times */
1712374824dSpedro 	getmicrouptime(&tv);
172484da6dcSmikeb 	ip->i_modrev = (u_quad_t)tv.tv_sec << 32;
173484da6dcSmikeb 	ip->i_modrev |= (u_quad_t)tv.tv_usec * 4294;
1742374824dSpedro 
1752374824dSpedro 	*vpp = vp;
1762374824dSpedro 
1772374824dSpedro 	return (0);
1782374824dSpedro }
179