Module Name: src Committed By: hannken Date: Sun May 28 16:38:55 UTC 2017
Modified Files: src/sys/ufs/ext2fs: ext2fs_alloc.c ext2fs_extern.h ext2fs_vfsops.c ext2fs_vnops.c Log Message: Change ext2fs to use vcache_new like we did for ffs: - Change ext2fs_valloc to return an inode number. - Make ext2fs_makeinode private to ext2fs_vnops.c and pass vattr instead of mode. To generate a diff of this commit: cvs rdiff -u -r1.51 -r1.52 src/sys/ufs/ext2fs/ext2fs_alloc.c cvs rdiff -u -r1.55 -r1.56 src/sys/ufs/ext2fs/ext2fs_extern.h cvs rdiff -u -r1.208 -r1.209 src/sys/ufs/ext2fs/ext2fs_vfsops.c cvs rdiff -u -r1.127 -r1.128 src/sys/ufs/ext2fs/ext2fs_vnops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/ufs/ext2fs/ext2fs_alloc.c diff -u src/sys/ufs/ext2fs/ext2fs_alloc.c:1.51 src/sys/ufs/ext2fs/ext2fs_alloc.c:1.52 --- src/sys/ufs/ext2fs/ext2fs_alloc.c:1.51 Sat Aug 20 19:53:43 2016 +++ src/sys/ufs/ext2fs/ext2fs_alloc.c Sun May 28 16:38:55 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ext2fs_alloc.c,v 1.51 2016/08/20 19:53:43 jdolecek Exp $ */ +/* $NetBSD: ext2fs_alloc.c,v 1.52 2017/05/28 16:38:55 hannken Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 @@ -60,7 +60,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ext2fs_alloc.c,v 1.51 2016/08/20 19:53:43 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ext2fs_alloc.c,v 1.52 2017/05/28 16:38:55 hannken Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -167,16 +167,13 @@ nospace: * available inode is located. */ int -ext2fs_valloc(struct vnode *pvp, int mode, kauth_cred_t cred, - struct vnode **vpp) +ext2fs_valloc(struct vnode *pvp, int mode, kauth_cred_t cred, ino_t *inop) { struct inode *pip; struct m_ext2fs *fs; - struct inode *ip; ino_t ino, ipref; - int cg, error; + int cg; - *vpp = NULL; pip = VTOI(pvp); fs = pip->i_e2fs; if (fs->e2fs.e2fs_ficount == 0) @@ -190,32 +187,10 @@ ext2fs_valloc(struct vnode *pvp, int mod ino = (ino_t)ext2fs_hashalloc(pip, cg, (long)ipref, mode, ext2fs_nodealloccg); if (ino == 0) goto noinodes; - error = VFS_VGET(pvp->v_mount, ino, vpp); - if (error) { - ext2fs_vfree(pvp, ino, mode); - return error; - } - ip = VTOI(*vpp); - - KASSERT(!E2FS_HAS_GD_CSUM(fs) || (fs->e2fs_gd[ino_to_cg(fs, ino)].ext2bgd_flags & h2fs16(E2FS_BG_INODE_ZEROED)) != 0); - - /* check for already used inode; makes sense only for ZEROED itable */ - if (__predict_false(ip->i_e2fs_mode && ip->i_e2fs_nlink != 0)) { - printf("mode = 0%o, nlinks %d, inum = %llu, fs = %s\n", - ip->i_e2fs_mode, ip->i_e2fs_nlink, - (unsigned long long)ip->i_number, fs->e2fs_fsmnt); - panic("ext2fs_valloc: dup alloc"); - } - - memset(ip->i_din.e2fs_din, 0, EXT2_DINODE_SIZE(fs)); - /* - * Set up a new generation number for this inode. - */ - if (++ext2gennumber < time_second) - ext2gennumber = time_second; - ip->i_e2fs_gen = ext2gennumber; + *inop = ino; return 0; + noinodes: ext2fs_fserr(fs, kauth_cred_geteuid(cred), "out of inodes"); uprintf("\n%s: create/symlink failed, no inodes free\n", fs->e2fs_fsmnt); Index: src/sys/ufs/ext2fs/ext2fs_extern.h diff -u src/sys/ufs/ext2fs/ext2fs_extern.h:1.55 src/sys/ufs/ext2fs/ext2fs_extern.h:1.56 --- src/sys/ufs/ext2fs/ext2fs_extern.h:1.55 Sat Aug 20 19:47:44 2016 +++ src/sys/ufs/ext2fs/ext2fs_extern.h Sun May 28 16:38:55 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ext2fs_extern.h,v 1.55 2016/08/20 19:47:44 jdolecek Exp $ */ +/* $NetBSD: ext2fs_extern.h,v 1.56 2017/05/28 16:38:55 hannken Exp $ */ /*- * Copyright (c) 1991, 1993, 1994 @@ -95,7 +95,7 @@ int ext2fs_alloc(struct inode *, daddr_t daddr_t *); int ext2fs_realloccg(struct inode *, daddr_t, daddr_t, int, int , kauth_cred_t, struct buf **); -int ext2fs_valloc(struct vnode *, int, kauth_cred_t, struct vnode **); +int ext2fs_valloc(struct vnode *, int, kauth_cred_t, ino_t *); /* XXX ondisk32 */ daddr_t ext2fs_blkpref(struct inode *, daddr_t, int, int32_t *); void ext2fs_blkfree(struct inode *, daddr_t); @@ -176,8 +176,6 @@ int ext2fs_advlock(void *); int ext2fs_fsync(void *); int ext2fs_vinit(struct mount *, int (**specops)(void *), int (**fifoops)(void *), struct vnode **); -int ext2fs_makeinode(int, struct vnode *, struct vnode **, - struct componentname *cnp, int); int ext2fs_reclaim(void *); /* ext2fs_hash.c */ Index: src/sys/ufs/ext2fs/ext2fs_vfsops.c diff -u src/sys/ufs/ext2fs/ext2fs_vfsops.c:1.208 src/sys/ufs/ext2fs/ext2fs_vfsops.c:1.209 --- src/sys/ufs/ext2fs/ext2fs_vfsops.c:1.208 Mon Apr 17 08:32:01 2017 +++ src/sys/ufs/ext2fs/ext2fs_vfsops.c Sun May 28 16:38:55 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ext2fs_vfsops.c,v 1.208 2017/04/17 08:32:01 hannken Exp $ */ +/* $NetBSD: ext2fs_vfsops.c,v 1.209 2017/05/28 16:38:55 hannken Exp $ */ /* * Copyright (c) 1989, 1991, 1993, 1994 @@ -60,7 +60,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.208 2017/04/17 08:32:01 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.209 2017/05/28 16:38:55 hannken Exp $"); #if defined(_KERNEL_OPT) #include "opt_compat_netbsd.h" @@ -131,6 +131,7 @@ struct vfsops ext2fs_vfsops = { .vfs_sync = ext2fs_sync, .vfs_vget = ufs_vget, .vfs_loadvnode = ext2fs_loadvnode, + .vfs_newvnode = ext2fs_newvnode, .vfs_fhtovp = ext2fs_fhtovp, .vfs_vptofh = ext2fs_vptofh, .vfs_init = ext2fs_init, @@ -966,25 +967,16 @@ ext2fs_sync(struct mount *mp, int waitfo } /* - * Read an inode from disk and initialize this vnode / inode pair. - * Caller assures no other thread will try to load this inode. + * Load inode from disk and initialize vnode. */ -int -ext2fs_loadvnode(struct mount *mp, struct vnode *vp, - const void *key, size_t key_len, const void **new_key) +static int +ext2fs_init_vnode(struct ufsmount *ump, struct vnode *vp, ino_t ino) { - ino_t ino; struct m_ext2fs *fs; struct inode *ip; - struct ufsmount *ump; struct buf *bp; - dev_t dev; int error; - KASSERT(key_len == sizeof(ino)); - memcpy(&ino, key, key_len); - ump = VFSTOUFS(mp); - dev = ump->um_dev; fs = ump->um_e2fs; /* Read in the disk contents for the inode, copy into the inode. */ @@ -996,25 +988,20 @@ ext2fs_loadvnode(struct mount *mp, struc /* Allocate and initialize inode. */ ip = pool_get(&ext2fs_inode_pool, PR_WAITOK); memset(ip, 0, sizeof(struct inode)); - vp->v_tag = VT_EXT2FS; - vp->v_op = ext2fs_vnodeop_p; - vp->v_vflag |= VV_LOCKSWORK; - vp->v_data = ip; ip->i_vnode = vp; ip->i_ump = ump; ip->i_e2fs = fs; - ip->i_dev = dev; + ip->i_dev = ump->um_dev; ip->i_number = ino; ip->i_e2fs_last_lblk = 0; ip->i_e2fs_last_blk = 0; - /* Initialize genfs node. */ - genfs_node_init(vp, &ext2fs_genfsops); - error = ext2fs_loadvnode_content(fs, ino, bp, ip); brelse(bp, 0); - if (error) + if (error) { + pool_put(&ext2fs_inode_pool, ip); return error; + } /* If the inode was deleted, reset all fields */ if (ip->i_e2fs_dtime != 0) { @@ -1024,6 +1011,41 @@ ext2fs_loadvnode(struct mount *mp, struc memset(ip->i_e2fs_blocks, 0, sizeof(ip->i_e2fs_blocks)); } + /* Initialise vnode with this inode. */ + vp->v_tag = VT_EXT2FS; + vp->v_op = ext2fs_vnodeop_p; + vp->v_vflag |= VV_LOCKSWORK; + vp->v_data = ip; + + /* Initialize genfs node. */ + genfs_node_init(vp, &ext2fs_genfsops); + + return 0; +} + +/* + * Read an inode from disk and initialize this vnode / inode pair. + * Caller assures no other thread will try to load this inode. + */ +int +ext2fs_loadvnode(struct mount *mp, struct vnode *vp, + const void *key, size_t key_len, const void **new_key) +{ + ino_t ino; + struct inode *ip; + struct ufsmount *ump; + int error; + + KASSERT(key_len == sizeof(ino)); + memcpy(&ino, key, key_len); + ump = VFSTOUFS(mp); + + error = ext2fs_init_vnode(ump, vp, ino); + if (error) + return error; + + ip = VTOI(vp); + /* Initialize the vnode from the inode. */ ext2fs_vinit(mp, ext2fs_specop_p, ext2fs_fifoop_p, &vp); @@ -1049,6 +1071,113 @@ ext2fs_loadvnode(struct mount *mp, struc } /* + * Create a new inode on disk and initialize this vnode / inode pair. + */ +int +ext2fs_newvnode(struct mount *mp, struct vnode *dvp, struct vnode *vp, + struct vattr *vap, kauth_cred_t cred, + size_t *key_len, const void **new_key) +{ + ino_t ino; + struct inode *ip, *pdir; + struct m_ext2fs *fs; + struct ufsmount *ump; + int error, mode; + + KASSERT(dvp->v_mount == mp); + KASSERT(vap->va_type != VNON); + + *key_len = sizeof(ino); + + pdir = VTOI(dvp); + fs = pdir->i_e2fs; + ump = VFSTOUFS(mp); + mode = MAKEIMODE(vap->va_type, vap->va_mode); + + /* Allocate fresh inode. */ + error = ext2fs_valloc(dvp, mode, cred, &ino); + if (error) + return error; + + /* Attach inode to vnode. */ + error = ext2fs_init_vnode(ump, vp, ino); + if (error) { + ext2fs_vfree(dvp, ino, mode); + return error; + } + + ip = VTOI(vp); + + KASSERT(!E2FS_HAS_GD_CSUM(fs) || (fs->e2fs_gd[ino_to_cg(fs, ino)].ext2bgd_flags & h2fs16(E2FS_BG_INODE_ZEROED)) != 0); + + /* check for already used inode; makes sense only for ZEROED itable */ + if (__predict_false(ip->i_e2fs_mode && ip->i_e2fs_nlink != 0)) { + printf("mode = 0%o, nlinks %d, inum = %llu, fs = %s\n", + ip->i_e2fs_mode, ip->i_e2fs_nlink, + (unsigned long long)ip->i_number, fs->e2fs_fsmnt); + panic("ext2fs_valloc: dup alloc"); + } + + memset(ip->i_din.e2fs_din, 0, EXT2_DINODE_SIZE(fs)); + + /* + * Set up a new generation number for this inode. + */ + if (++ext2gennumber < time_second) + ext2gennumber = time_second; + ip->i_e2fs_gen = ext2gennumber; + + ip->i_uid = kauth_cred_geteuid(cred); + ip->i_e2fs_uid = ip->i_uid & 0xffff; + ip->i_e2fs_gid = pdir->i_e2fs_gid; + if (ip->i_e2fs->e2fs.e2fs_rev > E2FS_REV0) { + ip->i_e2fs_uid_high = (ip->i_uid >> 16) & 0xffff; + ip->i_e2fs_gid_high = pdir->i_e2fs_gid_high; + } else { + ip->i_e2fs_uid_high = 0; + ip->i_e2fs_gid_high = 0; + } + ip->i_gid = ip->i_e2fs_gid | (ip->i_e2fs_gid_high << 16); + ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; + ip->i_e2fs_mode = mode; + vp->v_type = IFTOVT(mode); + ip->i_e2fs_nlink = 1; + + /* Authorize setting SGID if needed. */ + if (ip->i_e2fs_mode & ISGID) { + error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, + vp, NULL, genfs_can_chmod(vp->v_type, cred, ip->i_uid, + ip->i_gid, mode)); + if (error) + ip->i_e2fs_mode &= ~ISGID; + } + + /* Initialize extra_isize according to what is set in superblock */ + if (EXT2F_HAS_ROCOMPAT_FEATURE(ip->i_e2fs, EXT2F_ROCOMPAT_EXTRA_ISIZE) + && EXT2_DINODE_SIZE(ip->i_e2fs) > EXT2_REV0_DINODE_SIZE) { + ip->i_din.e2fs_din->e2di_extra_isize = ip->i_e2fs->e2fs.e4fs_want_extra_isize; + } + + /* Set create time if possible */ + if (EXT2_DINODE_FITS(ip->i_din.e2fs_din, e2di_crtime, EXT2_DINODE_SIZE(ip->i_e2fs))) { + struct timespec now; + vfs_timestamp(&now); + EXT2_DINODE_TIME_SET(&now, ip->i_din.e2fs_din, e2di_crtime, EXT2_DINODE_SIZE(ip->i_e2fs)); + } + + /* Initialize the vnode from the inode. */ + ext2fs_vinit(mp, ext2fs_specop_p, ext2fs_fifoop_p, &vp); + + /* Finish inode initialization. */ + ip->i_devvp = ump->um_devvp; + vref(ip->i_devvp); + + uvm_vnp_setsize(vp, ext2fs_size(ip)); + *new_key = &ip->i_number; + return 0; +} + +/* * File handle to vnode * * Have to be really careful about stale file handles: Index: src/sys/ufs/ext2fs/ext2fs_vnops.c diff -u src/sys/ufs/ext2fs/ext2fs_vnops.c:1.127 src/sys/ufs/ext2fs/ext2fs_vnops.c:1.128 --- src/sys/ufs/ext2fs/ext2fs_vnops.c:1.127 Fri May 26 14:21:02 2017 +++ src/sys/ufs/ext2fs/ext2fs_vnops.c Sun May 28 16:38:55 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ext2fs_vnops.c,v 1.127 2017/05/26 14:21:02 riastradh Exp $ */ +/* $NetBSD: ext2fs_vnops.c,v 1.128 2017/05/28 16:38:55 hannken Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 @@ -65,7 +65,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.127 2017/05/26 14:21:02 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.128 2017/05/28 16:38:55 hannken Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -101,6 +101,8 @@ extern int prtactive; static int ext2fs_chmod(struct vnode *, int, kauth_cred_t, struct lwp *); static int ext2fs_chown(struct vnode *, uid_t, gid_t, kauth_cred_t, struct lwp *); +static int ext2fs_makeinode(struct vattr *, struct vnode *, struct vnode **, + struct componentname *, int); union _qcvt { int64_t qcvt; @@ -134,9 +136,7 @@ ext2fs_create(void *v) } */ *ap = v; int error; - error = - ext2fs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode), - ap->a_dvp, ap->a_vpp, ap->a_cnp, 1); + error = ext2fs_makeinode(ap->a_vap, ap->a_dvp, ap->a_vpp, ap->a_cnp, 1); if (error) return error; @@ -162,37 +162,13 @@ ext2fs_mknod(void *v) struct vnode **vpp = ap->a_vpp; struct inode *ip; int error; - struct mount *mp; - ino_t ino; - if ((error = ext2fs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode), - ap->a_dvp, vpp, ap->a_cnp, 1)) != 0) + if ((error = ext2fs_makeinode(vap, ap->a_dvp, vpp, ap->a_cnp, 1)) != 0) return error; VN_KNOTE(ap->a_dvp, NOTE_WRITE); ip = VTOI(*vpp); - mp = (*vpp)->v_mount; - ino = ip->i_number; ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; - if (vap->va_rdev != VNOVAL) { - /* - * Want to be able to use this to make badblock - * inodes, so don't truncate the dev number. - */ - ip->i_din.e2fs_din->e2di_rdev = h2fs32(vap->va_rdev); - } - /* - * Remove inode so that it will be reloaded by vcache_get and - * checked to see if it is an alias of an existing entry in - * the inode cache. - */ - (*vpp)->v_type = VNON; VOP_UNLOCK(*vpp); - vgone(*vpp); - error = vcache_get(mp, &ino, sizeof(ino), vpp); - if (error != 0) { - *vpp = NULL; - return error; - } return 0; } @@ -676,11 +652,12 @@ ext2fs_mkdir(void *v) ulr = &VTOI(dvp)->i_crap; UFS_CHECK_CRAPCOUNTER(VTOI(dvp)); + KASSERT(ap->a_vap->va_type == VDIR); + /* * Acquire the inode, but don't sync/direnter it just yet */ - error = ext2fs_makeinode(IFDIR | ap->a_vap->va_mode, ap->a_dvp, - &tvp, ap->a_cnp, 0); + error = ext2fs_makeinode(ap->a_vap, ap->a_dvp, &tvp, ap->a_cnp, 0); if (error) goto out; @@ -881,8 +858,8 @@ ext2fs_symlink(void *v) int len, error; vpp = ap->a_vpp; - error = ext2fs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp, - vpp, ap->a_cnp, 1); + KASSERT(ap->a_vap->va_type == VLNK); + error = ext2fs_makeinode(ap->a_vap, ap->a_dvp, vpp, ap->a_cnp, 1); if (error) return error; VN_KNOTE(ap->a_dvp, NOTE_WRITE); @@ -1030,8 +1007,8 @@ ext2fs_vinit(struct mount *mntp, int (** /* * Allocate a new inode. */ -int -ext2fs_makeinode(int mode, struct vnode *dvp, struct vnode **vpp, +static int +ext2fs_makeinode(struct vattr *vap, struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, int do_direnter) { struct inode *ip, *pdir; @@ -1046,51 +1023,16 @@ ext2fs_makeinode(int mode, struct vnode UFS_CHECK_CRAPCOUNTER(pdir); *vpp = NULL; - if ((mode & IFMT) == 0) - mode |= IFREG; - if ((error = ext2fs_valloc(dvp, mode, cnp->cn_cred, &tvp)) != 0) { + error = vcache_new(dvp->v_mount, dvp, vap, cnp->cn_cred, &tvp); + if (error) + return error; + error = vn_lock(tvp, LK_EXCLUSIVE); + if (error) { + vrele(tvp); return error; } ip = VTOI(tvp); - ip->i_uid = kauth_cred_geteuid(cnp->cn_cred); - ip->i_e2fs_uid = ip->i_uid & 0xffff; - ip->i_e2fs_gid = pdir->i_e2fs_gid; - if (ip->i_e2fs->e2fs.e2fs_rev > E2FS_REV0) { - ip->i_e2fs_uid_high = (ip->i_uid >> 16) & 0xffff; - ip->i_e2fs_gid_high = pdir->i_e2fs_gid_high; - } else { - ip->i_e2fs_uid_high = 0; - ip->i_e2fs_gid_high = 0; - } - ip->i_gid = ip->i_e2fs_gid | (ip->i_e2fs_gid_high << 16); - ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; - ip->i_e2fs_mode = mode; - tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */ - ip->i_e2fs_nlink = 1; - - /* Authorize setting SGID if needed. */ - if (ip->i_e2fs_mode & ISGID) { - error = kauth_authorize_vnode(cnp->cn_cred, KAUTH_VNODE_WRITE_SECURITY, - tvp, NULL, genfs_can_chmod(tvp->v_type, cnp->cn_cred, ip->i_uid, - ip->i_gid, mode)); - if (error) - ip->i_e2fs_mode &= ~ISGID; - } - - /* Initialize extra_isize according to what is set in superblock */ - if (EXT2F_HAS_ROCOMPAT_FEATURE(ip->i_e2fs, EXT2F_ROCOMPAT_EXTRA_ISIZE) - && EXT2_DINODE_SIZE(ip->i_e2fs) > EXT2_REV0_DINODE_SIZE) { - ip->i_din.e2fs_din->e2di_extra_isize = ip->i_e2fs->e2fs.e4fs_want_extra_isize; - } - - /* Set create time if possible */ - if (EXT2_DINODE_FITS(ip->i_din.e2fs_din, e2di_crtime, EXT2_DINODE_SIZE(ip->i_e2fs))) { - struct timespec now; - vfs_timestamp(&now); - EXT2_DINODE_TIME_SET(&now, ip->i_din.e2fs_din, e2di_crtime, EXT2_DINODE_SIZE(ip->i_e2fs)); - } - if (do_direnter) { /* * Make sure inode goes to disk before directory entry. @@ -1110,7 +1052,6 @@ bad: * Write error occurred trying to update the inode * or the directory so must deallocate the inode. */ - tvp->v_type = VNON; /* Stop explosion if VBLK */ ip->i_e2fs_nlink = 0; ip->i_flag |= IN_CHANGE; vput(tvp);