FreeBSD/sys/fs/ext2fs/ext2_alloc.c
/*
 * Allocate an inode in the filesystem.
 * 
 */
Allocate an inode in the filesystem.
Allocate an inode in the filesystem .
int
ext2_valloc(struct vnode *pvp, int mode, struct ucred *cred, struct vnode **vpp)
{
	struct timespec ts;
	struct inode *pip;
	struct m_ext2fs *fs;
	struct inode *ip;
	struct ext2mount *ump;
	ino_t ino, ipref;
	int i, error, cg;
	*vpp = NULL;
	pip = VTOI(pvp);
	fs = pip->i_e2fs;
	ump = pip->i_ump;
	EXT2_LOCK(ump);
	if (fs->e2fs->e2fs_ficount == 0)
		goto noinodes;
	if ((mode & IFMT) == IFDIR) {
		cg = ext2_dirpref(pip);
		if (fs->e2fs_contigdirs[cg] < 255)
			fs->e2fs_contigdirs[cg]++;
	} else {
		cg = ino_to_cg(fs, pip->i_number);
		if (fs->e2fs_contigdirs[cg] > 0)
			fs->e2fs_contigdirs[cg]--;
	}
	ipref = cg * fs->e2fs->e2fs_ipg + 1;
	ino = (ino_t)ext2_hashalloc(pip, cg, (long)ipref, mode, ext2_nodealloccg);
	if (ino == 0) 
		goto noinodes;
	error = VFS_VGET(pvp->v_mount, ino, LK_EXCLUSIVE, vpp);
	if (error) {
		ext2_vfree(pvp, ino, mode);
		return (error);
	}
	ip = VTOI(*vpp);
	ip->i_flag = 0;
	ip->i_size = 0;
	ip->i_blocks = 0;
	ip->i_mode = 0;
	ip->i_flags = 0;
	for (i = 0; i < NDADDR; i++)
		ip->i_db[i] = 0;
	for (i = 0; i < NIADDR; i++)
		ip->i_ib[i] = 0;
	do {
		ip->i_gen = arc4random();
	} while ( ip->i_gen == 0);
	vfs_timestamp(&ts);
	ip->i_birthtime = ts.tv_sec;
	ip->i_birthnsec = ts.tv_nsec;
	return (0);
noinodes:
	EXT2_UNLOCK(ump);
	ext2_fserr(fs, cred->cr_uid, "out of inodes");
	uprintf("\n%s: create/symlink failed, no inodes free\n", fs->e2fs_fsmnt);
	return (ENOSPC);
}
int ext2_valloc ( struct vnode * pvp , int mode , struct ucred * cred , struct vnode * * vpp ) { struct timespec ts ; struct inode * pip ; struct m_ext2fs * fs ; struct inode * ip ; struct ext2mount * ump ; ino_t ino , ipref ; int i , error , cg ; * vpp = NULL ; pip = VTOI ( pvp ) ; fs = pip -> i_e2fs ; ump = pip -> i_ump ; EXT2_LOCK ( ump ) ; if ( fs -> e2fs -> e2fs_ficount == 0 ) goto noinodes ; if ( ( mode & IFMT ) == IFDIR ) { cg = ext2_dirpref ( pip ) ; if ( fs -> e2fs_contigdirs [ cg ] < 255 ) fs -> e2fs_contigdirs [ cg ] ++ ; } else { cg = ino_to_cg ( fs , pip -> i_number ) ; if ( fs -> e2fs_contigdirs [ cg ] > 0 ) fs -> e2fs_contigdirs [ cg ] -- ; } ipref = cg * fs -> e2fs -> e2fs_ipg + 1 ; ino = ( ino_t ) ext2_hashalloc ( pip , cg , ( long ) ipref , mode , ext2_nodealloccg ) ; if ( ino == 0 ) goto noinodes ; error = VFS_VGET ( pvp -> v_mount , ino , LK_EXCLUSIVE , vpp ) ; if ( error ) { ext2_vfree ( pvp , ino , mode ) ; return ( error ) ; } ip = VTOI ( * vpp ) ; ip -> i_flag = 0 ; ip -> i_size = 0 ; ip -> i_blocks = 0 ; ip -> i_mode = 0 ; ip -> i_flags = 0 ; for ( i = 0 ; i < NDADDR ; i ++ ) ip -> i_db [ i ] = 0 ; for ( i = 0 ; i < NIADDR ; i ++ ) ip -> i_ib [ i ] = 0 ; do { ip -> i_gen = arc4random ( ) ; } while ( ip -> i_gen == 0 ) ; vfs_timestamp ( & ts ) ; ip -> i_birthtime = ts . tv_sec ; ip -> i_birthnsec = ts . tv_nsec ; return ( 0 ) ; noinodes : EXT2_UNLOCK ( ump ) ; ext2_fserr ( fs , cred -> cr_uid , " " ) ; uprintf ( " \n \n " , fs -> e2fs_fsmnt ) ; return ( ENOSPC ) ; }
Allocate an inode in the filesystem.
Allocate an inode in the filesystem .
/*
	 * If it is a directory then obtain a cylinder group based on
	 * ext2_dirpref else obtain it using ino_to_cg. The preferred inode is
	 * always the next inode.
	 */ /*
	 * The question is whether using VGET was such good idea at all:
	 * Linux doesn't read the old inode in when it is allocating a
	 * new one. I will set at least i_size and i_blocks to zero.
	 */ /* now we want to make sure that the block pointers are zeroed out */ /*
	 * Set up a new generation number for this inode.
	 * Avoid zero values.
	 */ /*
printf("ext2_valloc: allocated inode %d\n", ino);
*/