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