/* * Allocate an inode in the file system. * * If allocating a directory, use ext2fs_dirpref to select the inode. * If allocating in a directory, the following hierarchy is followed: * 1) allocate the preferred inode. * 2) allocate an inode in the same cylinder group. * 3) quadradically rehash into other cylinder groups, until an * available inode is located. * If no inode preference is given the following hierarchy is used * to allocate an inode: * 1) allocate an inode in cylinder group 0. * 2) quadradically rehash into other cylinder groups, until an * available inode is located. */ int ext2fs_valloc(struct vnode *pvp, int mode, kauth_cred_t cred, struct vnode **vpp) { struct inode *pip; struct m_ext2fs *fs; struct inode *ip; ino_t ino, ipref; int cg, error; *vpp = NULL; pip = VTOI(pvp); fs = pip->i_e2fs; if (fs->e2fs.e2fs_ficount == 0) goto noinodes; if ((mode & IFMT) == IFDIR) cg = ext2fs_dirpref(fs); else cg = ino_to_cg(fs, pip->i_number); ipref = cg * fs->e2fs.e2fs_ipg + 1; 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); if (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, sizeof(struct ext2fs_dinode)); /* * Set up a new generation number for this inode. */ if (++ext2gennumber < time_second) ext2gennumber = time_second; ip->i_e2fs_gen = ext2gennumber; 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); return (ENOSPC); }
/* * Allocate a block in the file system. * * A preference may be optionally specified. If a preference is given * the following hierarchy is used to allocate a block: * 1) allocate the requested block. * 2) allocate a rotationally optimal block in the same cylinder. * 3) allocate a block in the same cylinder group. * 4) quadradically rehash into other cylinder groups, until an * available block is located. * If no block preference is given the following hierarchy is used * to allocate a block: * 1) allocate a block in the cylinder group that contains the * inode for the file. * 2) quadradically rehash into other cylinder groups, until an * available block is located. */ int ext2fs_alloc(struct inode *ip, daddr_t lbn, daddr_t bpref, kauth_cred_t cred, daddr_t *bnp) { struct m_ext2fs *fs; daddr_t bno; int cg; *bnp = 0; fs = ip->i_e2fs; #ifdef DIAGNOSTIC if (cred == NOCRED) panic("ext2fs_alloc: missing credential"); #endif /* DIAGNOSTIC */ if (fs->e2fs.e2fs_fbcount == 0) goto nospace; if (kauth_authorize_system(cred, KAUTH_SYSTEM_FS_RESERVEDSPACE, 0, NULL, NULL, NULL) != 0 && freespace(fs) <= 0) goto nospace; if (bpref >= fs->e2fs.e2fs_bcount) bpref = 0; if (bpref == 0) cg = ino_to_cg(fs, ip->i_number); else cg = dtog(fs, bpref); bno = (daddr_t)ext2fs_hashalloc(ip, cg, bpref, fs->e2fs_bsize, ext2fs_alloccg); if (bno > 0) { ip->i_e2fs_nblock += btodb(fs->e2fs_bsize); ip->i_flag |= IN_CHANGE | IN_UPDATE; *bnp = bno; return (0); } nospace: ext2fs_fserr(fs, kauth_cred_geteuid(cred), "file system full"); uprintf("\n%s: write failed, file system is full\n", fs->e2fs_fsmnt); return (ENOSPC); }
/* * Allocate a block in the file system. * * A preference may be optionally specified. If a preference is given * the following hierarchy is used to allocate a block: * 1) allocate the requested block. * 2) allocate a rotationally optimal block in the same cylinder. * 3) allocate a block in the same cylinder group. * 4) quadratically rehash into other cylinder groups, until an * available block is located. * If no block preference is given the following hierarchy is used * to allocate a block: * 1) allocate a block in the cylinder group that contains the * inode for the file. * 2) quadratically rehash into other cylinder groups, until an * available block is located. */ int ext2fs_alloc(struct inode *ip, int32_t lbn, int32_t bpref, struct ucred *cred, int32_t *bnp) { struct m_ext2fs *fs; int32_t bno; int cg; *bnp = 0; fs = ip->i_e2fs; #ifdef DIAGNOSTIC if (cred == NOCRED) panic("ext2fs_alloc: missing credential"); #endif /* DIAGNOSTIC */ if (fs->e2fs.e2fs_fbcount == 0) goto nospace; if (cred->cr_uid != 0 && freespace(fs) <= 0) goto nospace; if (bpref >= fs->e2fs.e2fs_bcount) bpref = 0; if (bpref == 0) cg = ino_to_cg(fs, ip->i_number); else cg = dtog(fs, bpref); bno = (int32_t)ext2fs_hashalloc(ip, cg, bpref, fs->e2fs_bsize, ext2fs_alloccg); if (bno > 0) { ip->i_e2fs_nblock += btodb(fs->e2fs_bsize); ip->i_flag |= IN_CHANGE | IN_UPDATE; *bnp = bno; return (0); } nospace: ext2fs_fserr(fs, cred->cr_uid, "file system full"); uprintf("\n%s: write failed, file system is full\n", fs->e2fs_fsmnt); return (ENOSPC); }