/* * NOTE! When we get the inode, we're the only people * that have access to it, and as such there are no * race conditions we have to worry about. The inode * is not on the hash-lists, and it cannot be reached * through the filesystem because the directory entry * has been deleted earlier. * * HOWEVER: we must make sure that we get no aliases, * which means that we have to call "clear_inode()" * _before_ we mark the inode not in use in the inode * bitmaps. Otherwise a newly created file might use * the same inode number (not actually the same pointer * though), and then we'd have two inodes sharing the * same inode number and space on the harddisk.
*/ void ufs_free_inode (struct inode * inode)
{ struct super_block * sb; struct ufs_sb_private_info * uspi; struct ufs_cg_private_info * ucpi; struct ufs_cylinder_group * ucg; int is_directory; unsigned ino, cg, bit;
/* * Nullify new chunk of inodes, * BSD people also set ui_gen field of inode * during nullification, but we not care about * that because of linux ufs do not support NFS
*/ staticvoid ufs2_init_inodes_chunk(struct super_block *sb, struct ufs_cg_private_info *ucpi, struct ufs_cylinder_group *ucg)
{ struct buffer_head *bh; struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
sector_t beg = uspi->s_sbbase +
ufs_inotofsba(ucpi->c_cgx * uspi->s_ipg +
fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk));
sector_t end = beg + uspi->s_fpb;
UFSD("ENTER cgno %d\n", ucpi->c_cgx);
for (; beg < end; ++beg) {
bh = sb_getblk(sb, beg);
lock_buffer(bh);
memset(bh->b_data, 0, sb->s_blocksize);
set_buffer_uptodate(bh);
mark_buffer_dirty(bh);
unlock_buffer(bh); if (sb->s_flags & SB_SYNCHRONOUS)
sync_dirty_buffer(bh);
brelse(bh);
}
fs32_add(sb, &ucg->cg_u.cg_u2.cg_initediblk, uspi->s_inopb);
ubh_mark_buffer_dirty(UCPI_UBH(ucpi)); if (sb->s_flags & SB_SYNCHRONOUS)
ubh_sync_block(UCPI_UBH(ucpi));
UFSD("EXIT\n");
}
/* * There are two policies for allocating an inode. If the new inode is * a directory, then a forward search is made for a block group with both * free space and a low directory-to-inode ratio; if that fails, then of * the groups with above-average free space, that group with the fewest * directories already is chosen. * * For other inodes, search forward from the parent directory's block * group to find a free inode.
*/ struct inode *ufs_new_inode(struct inode *dir, umode_t mode)
{ struct super_block * sb; struct ufs_sb_info * sbi; struct ufs_sb_private_info * uspi; struct ufs_cg_private_info * ucpi; struct ufs_cylinder_group * ucg; struct inode * inode; struct timespec64 ts; unsigned cg, bit, i, j, start; struct ufs_inode_info *ufsi; int err = -ENOSPC;
UFSD("ENTER\n");
/* Cannot create files in a deleted directory */ if (!dir || !dir->i_nlink) return ERR_PTR(-EPERM);
sb = dir->i_sb;
inode = new_inode(sb); if (!inode) return ERR_PTR(-ENOMEM);
ufsi = UFS_I(inode);
sbi = UFS_SB(sb);
uspi = sbi->s_uspi;
mutex_lock(&sbi->s_lock);
/* * Try to place the inode in its parent directory
*/
i = ufs_inotocg(dir->i_ino); if (sbi->fs_cs(i).cs_nifree) {
cg = i; goto cg_found;
}
/* * Use a quadratic hash to find a group with a free inode
*/ for ( j = 1; j < uspi->s_ncg; j <<= 1 ) {
i += j; if (i >= uspi->s_ncg)
i -= uspi->s_ncg; if (sbi->fs_cs(i).cs_nifree) {
cg = i; goto cg_found;
}
}
/* * That failed: try linear search for a free inode
*/
i = ufs_inotocg(dir->i_ino) + 1; for (j = 2; j < uspi->s_ncg; j++) {
i++; if (i >= uspi->s_ncg)
i = 0; if (sbi->fs_cs(i).cs_nifree) {
cg = i; goto cg_found;
}
}
goto failed;
cg_found:
ucpi = ufs_load_cylinder (sb, cg); if (!ucpi) {
err = -EIO; goto failed;
}
ucg = ubh_get_ucg(UCPI_UBH(ucpi)); if (!ufs_cg_chkmagic(sb, ucg))
ufs_panic (sb, "ufs_new_inode", "internal error, bad cg magic number");
start = ucpi->c_irotor;
bit = ubh_find_next_zero_bit (UCPI_UBH(ucpi), ucpi->c_iusedoff, uspi->s_ipg, start); if (!(bit < uspi->s_ipg)) {
bit = ubh_find_first_zero_bit (UCPI_UBH(ucpi), ucpi->c_iusedoff, start); if (!(bit < start)) {
ufs_error (sb, "ufs_new_inode", "cylinder group %u corrupted - error in inode bitmap\n", cg);
err = -EIO; goto failed;
}
}
UFSD("start = %u, bit = %u, ipg = %u\n", start, bit, uspi->s_ipg); if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit))
ubh_setbit (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit); else {
ufs_panic (sb, "ufs_new_inode", "internal error");
err = -EIO; goto failed;
}
if (uspi->fs_magic == UFS2_MAGIC) {
u32 initediblk = fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk);
/* * setup birth date, we do it here because of there is no sense * to hold it in struct ufs_inode_info, and lose 64 bit
*/
bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino)); if (!bh) {
ufs_warning(sb, "ufs_read_inode", "unable to read inode %lu\n",
inode->i_ino);
err = -EIO; goto fail_remove_inode;
}
lock_buffer(bh);
ufs2_inode = (struct ufs2_inode *)bh->b_data;
ufs2_inode += ufs_inotofsbo(inode->i_ino);
ktime_get_real_ts64(&ts);
ufs2_inode->ui_birthtime = cpu_to_fs64(sb, ts.tv_sec);
ufs2_inode->ui_birthnsec = cpu_to_fs32(sb, ts.tv_nsec);
mark_buffer_dirty(bh);
unlock_buffer(bh); if (sb->s_flags & SB_SYNCHRONOUS)
sync_dirty_buffer(bh);
brelse(bh);
}
mutex_unlock(&sbi->s_lock);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.