-/*
- * Allocate an inode in the file system.
- *
- * A preference may be optionally specified. If a preference is given
- * the following hierarchy is used to allocate an inode:
- * 1) allocate the requested 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 heirarchy 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.
- */
-ialloc(pip, ipref, mode, ipp)
- register struct inode *pip;
- ino_t ipref;
- int mode;
- struct inode **ipp;
-{
- ino_t ino;
- register struct fs *fs;
- register struct inode *ip;
- int cg, error;
-
- *ipp = 0;
- fs = pip->i_fs;
- if (fs->fs_cstotal.cs_nifree == 0)
- goto noinodes;
-#ifdef QUOTA
- if (error = chkiq(pip->i_dev, (struct inode *)NULL, u.u_uid, 0))
- return (error);
-#endif
- if (ipref >= fs->fs_ncg * fs->fs_ipg)
- ipref = 0;
- cg = itog(fs, ipref);
- ino = (ino_t)hashalloc(pip, cg, (long)ipref, mode, ialloccg);
- if (ino == 0)
- goto noinodes;
- error = iget(pip, ino, ipp);
- if (error) {
- ifree(pip, ino, 0);
- return (error);
- }
- ip = *ipp;
- if (ip->i_mode) {
- printf("mode = 0%o, inum = %d, fs = %s\n",
- ip->i_mode, ip->i_number, fs->fs_fsmnt);
- panic("ialloc: dup alloc");
- }
- if (ip->i_blocks) { /* XXX */
- printf("free inode %s/%d had %d blocks\n",
- fs->fs_fsmnt, ino, ip->i_blocks);
- ip->i_blocks = 0;
- }
- ip->i_flags = 0;
- /*
- * Set up a new generation number for this inode.
- */
- if (++nextgennumber < (u_long)time.tv_sec)
- nextgennumber = time.tv_sec;
- ip->i_gen = nextgennumber;
- return (0);
-noinodes:
- fserr(fs, "out of inodes");
- uprintf("\n%s: create/symlink failed, no inodes free\n", fs->fs_fsmnt);
- return (ENOSPC);
-}
-
-/*
- * Find a cylinder to place a directory.
- *
- * The policy implemented by this algorithm is to select from
- * among those cylinder groups with above the average number of
- * free inodes, the one with the smallest number of directories.
- */
-ino_t
-dirpref(fs)
- register struct fs *fs;
-{
- int cg, minndir, mincg, avgifree;
-
- avgifree = fs->fs_cstotal.cs_nifree / fs->fs_ncg;
- minndir = fs->fs_ipg;
- mincg = 0;
- for (cg = 0; cg < fs->fs_ncg; cg++)
- if (fs->fs_cs(fs, cg).cs_ndir < minndir &&
- fs->fs_cs(fs, cg).cs_nifree >= avgifree) {
- mincg = cg;
- minndir = fs->fs_cs(fs, cg).cs_ndir;
- }
- return ((ino_t)(fs->fs_ipg * mincg));
-}
-
-/*
- * Select the desired position for the next block in a file. The file is
- * logically divided into sections. The first section is composed of the
- * direct blocks. Each additional section contains fs_maxbpg blocks.
- *
- * If no blocks have been allocated in the first section, the policy is to
- * request a block in the same cylinder group as the inode that describes
- * the file. If no blocks have been allocated in any other section, the
- * policy is to place the section in a cylinder group with a greater than
- * average number of free blocks. An appropriate cylinder group is found
- * by using a rotor that sweeps the cylinder groups. When a new group of
- * blocks is needed, the sweep begins in the cylinder group following the
- * cylinder group from which the previous allocation was made. The sweep
- * continues until a cylinder group with greater than the average number
- * of free blocks is found. If the allocation is for the first block in an
- * indirect block, the information on the previous allocation is unavailable;
- * here a best guess is made based upon the logical block number being
- * allocated.
- *
- * If a section is already partially allocated, the policy is to
- * contiguously allocate fs_maxcontig blocks. The end of one of these
- * contiguous blocks and the beginning of the next is physically separated
- * so that the disk head will be in transit between them for at least
- * fs_rotdelay milliseconds. This is to allow time for the processor to
- * schedule another I/O transfer.
- */
-daddr_t
-blkpref(ip, lbn, indx, bap)
- struct inode *ip;
- daddr_t lbn;
- int indx;
- daddr_t *bap;
-{
- register struct fs *fs;
- register int cg;
- int avgbfree, startcg;
- daddr_t nextblk;
-
- fs = ip->i_fs;
- if (indx % fs->fs_maxbpg == 0 || bap[indx - 1] == 0) {
- if (lbn < NDADDR) {
- cg = itog(fs, ip->i_number);
- return (fs->fs_fpg * cg + fs->fs_frag);