Ejemplo n.º 1
0
/*
 * 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) quadratically 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) quadratically rehash into other cylinder groups, until an
 *	  available inode is located.
 */
int
ext2fs_inode_alloc(struct inode *pip, mode_t mode, struct ucred *cred,
    struct vnode **vpp)
{
	struct vnode *pvp;
	struct m_ext2fs *fs;
	struct inode *ip;
	ufsino_t ino, ipref;
	int cg, error;

	*vpp = NULL;
	pvp = ITOV(pip);
	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 = (ufsino_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_inode_free(pip, ino, mode);
		return (error);
	}
	ip = VTOI(*vpp);
	if (ip->i_e2fs_mode && ip->i_e2fs_nlink != 0) {
		printf("mode = 0%o, nlinks %u, inum = %u, fs = %s\n",
			ip->i_e2fs_mode, ip->i_e2fs_nlink, ip->i_number, fs->e2fs_fsmnt);
		panic("ext2fs_valloc: dup alloc");
	}

	memset(ip->i_e2din, 0, sizeof(struct ext2fs_dinode));

	/*
	 * Set up a new generation number for this inode.
	 */
	if (++ext2gennumber < (u_long)time_second)
		ext2gennumber = time_second;
	ip->i_e2fs_gen = ext2gennumber;
	return (0);
noinodes:
	ext2fs_fserr(fs, cred->cr_uid, "out of inodes");
	uprintf("\n%s: create/symlink failed, no inodes free\n", fs->e2fs_fsmnt);
	return (ENOSPC);
}
Ejemplo n.º 2
0
/*
 * Last reference to an inode.  If necessary, write or delete it.
 */
int
ext2fs_inactive(void *v)
{
	struct vop_inactive_args *ap = v;
	struct vnode *vp = ap->a_vp;
	struct inode *ip = VTOI(vp);
	struct proc *p = ap->a_p;
	struct timespec ts;
	int error = 0;
#ifdef DIAGNOSTIC
	extern int prtactive;

	if (prtactive && vp->v_usecount != 0)
		vprint("ext2fs_inactive: pushing active", vp);
#endif

	/* Get rid of inodes related to stale file handles. */
	if (ip->i_e2din == NULL || ip->i_e2fs_mode == 0 || ip->i_e2fs_dtime)
		goto out;

	error = 0;
	if (ip->i_e2fs_nlink == 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
		if (ext2fs_size(ip) != 0) {
			error = ext2fs_truncate(ip, (off_t)0, 0, NOCRED);
		}
		getnanotime(&ts);
		ip->i_e2fs_dtime = ts.tv_sec;
		ip->i_flag |= IN_CHANGE | IN_UPDATE;
		ext2fs_inode_free(ip, ip->i_number, ip->i_e2fs_mode);
	}
	if (ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) {
		ext2fs_update(ip, 0);
	}
out:
	VOP_UNLOCK(vp, p);
	/*
	 * If we are done with the inode, reclaim it
	 * so that it can be reused immediately.
	 */
	if (ip->i_e2din == NULL || ip->i_e2fs_dtime != 0)
		vrecycle(vp, p);
	return (error);
}