/* * Free an inode. * * the maintenance of the actual bitmaps is again up to the linux code */ int ext2_vfree(struct vnode *pvp, ino_t ino, int mode) { struct ext2_sb_info *fs; struct inode *pip; mode_t save_i_mode; pip = VTOI(pvp); fs = pip->i_e2fs; if ((u_int)ino > fs->s_inodes_per_group * fs->s_groups_count) panic("ext2_vfree: range: dev = (%d, %d), ino = %"PRId64", fs = %s", major(pip->i_dev), minor(pip->i_dev), ino, fs->fs_fsmnt); /* ext2_debug("ext2_vfree (%d, %d) called\n", pip->i_number, mode); */ ext2_discard_prealloc(pip); /* we need to make sure that ext2_free_inode can adjust the used_dir_counts in the group summary information - I'd really like to know what the rationale behind this 'set i_mode to zero to denote an unused inode' is */ save_i_mode = pip->i_mode; pip->i_mode = mode; ext2_free_inode(pip); pip->i_mode = save_i_mode; return (0); }
/** * Remove the target file or link */ void ext2_rm(struct ext2_disk *disk, const char *target_file_name) { // Read info about the containing directory char *last_segment; uint32_t container_inode; struct ext2_inode *containing_directory = ext2_traverse_path(disk, NULL, target_file_name, &last_segment, &container_inode); struct ext2_directory_entry *entry; if ((entry = ext2_read_entry_from_directory(disk, containing_directory, last_segment)) == NULL) { // File does not exist errx(1, "File with name %s does not exist", last_segment); } else if (IS_DIRECTORY(ext2_get_inode(disk, 0, entry->inode_addr))) { // Target is a directory errx(1, "Cannot remove directory %s", last_segment); } else { // Save the inode number uint32_t inode_addr = entry->inode_addr; // Remove the directory entry by clearing its fields entry->inode_addr = 0; entry->size = 0; entry->name_length = 0; entry->type_indicator = 0; entry->name = 0; // Decrement the hard link count if (--ext2_get_inode(disk, 0, inode_addr)->num_links == 0) // No more hard links point to the inode; free the inode and data blocks ext2_free_inode(disk, inode_addr); } }
/* * Called at the last iput() if i_nlink is zero. */ void ext2_delete_inode (struct inode * inode) { if (is_bad_inode(inode)) goto no_delete; EXT2_I(inode)->i_dtime = get_seconds(); mark_inode_dirty(inode); ext2_update_inode(inode, inode_needs_sync(inode)); inode->i_size = 0; if (inode->i_blocks) ext2_truncate (inode); ext2_free_inode (inode); return; no_delete: clear_inode(inode); /* We must guarantee clearing of inode... */ }
/* * Called at the last iput() if i_nlink is zero. */ void ext2_delete_inode (struct inode * inode) { lock_kernel(); if (is_bad_inode(inode)) goto no_delete; inode->u.ext2_i.i_dtime = CURRENT_TIME; mark_inode_dirty(inode); ext2_update_inode(inode, IS_SYNC(inode)); inode->i_size = 0; if (inode->i_blocks) ext2_truncate (inode); ext2_free_inode (inode); unlock_kernel(); return; no_delete: unlock_kernel(); clear_inode(inode); /* We must guarantee clearing of inode... */ }
/* * Called at the last iput() if i_nlink is zero. */ void ext2_evict_inode(struct inode * inode) { struct ext2_block_alloc_info *rsv; int want_delete = 0; if (!inode->i_nlink && !is_bad_inode(inode)) { want_delete = 1; dquot_initialize(inode); } else { dquot_drop(inode); } truncate_inode_pages_final(&inode->i_data); if (want_delete) { sb_start_intwrite(inode->i_sb); /* set dtime */ EXT2_I(inode)->i_dtime = get_seconds(); mark_inode_dirty(inode); __ext2_write_inode(inode, inode_needs_sync(inode)); /* truncate to 0 */ inode->i_size = 0; if (inode->i_blocks) ext2_truncate_blocks(inode, 0); ext2_xattr_delete_inode(inode); } invalidate_inode_buffers(inode); clear_inode(inode); ext2_discard_reservation(inode); rsv = EXT2_I(inode)->i_block_alloc_info; EXT2_I(inode)->i_block_alloc_info = NULL; if (unlikely(rsv)) kfree(rsv); if (want_delete) { ext2_free_inode(inode); sb_end_intwrite(inode->i_sb); } }