void sfs_evict_inode(struct inode *inode) { truncate_inode_pages(&inode->i_data, 0); if (!inode->i_nlink) { inode->i_size = 0; sfs_truncate(inode); } invalidate_inode_buffers(inode); clear_inode(inode); if (!inode->i_nlink) sfs_free_inode(inode); }
/* * ディレクトリを削除する。 * */ W sfs_i_rmdir (struct inode *parent, char *fname, struct access_info *acc) { int nentry; int i; int inodeindex; struct inode *ip; W rsize, errno; errno = fs_lookup (parent, fname, O_RDWR, 0, acc, &ip); if (errno) { printk("[PM] sfs_i_rmdir: can't remove directory %s(%d)\n", fname, errno); return (errno); } if ((ip->i_mode & SFS_FMT_DIR) == 0) { fs_close_file(ip); return (EP_NOTDIR); } if (ip->i_refcount >= 2) { fs_close_file(ip); return (EP_BUSY); } nentry = sfs_read_dir (ip, 0, NULL); if (nentry >= 3) { fs_close_file(ip); return (EP_NOTEMPTY); } nentry = sfs_read_dir (parent, 0, NULL); if (nentry <= 0) { fs_close_file(ip); return (EP_NOENT); } { struct sfs_dir buf[nentry]; /* GCC の拡張機能を使っている */ if (sfs_read_dir (parent, nentry, buf) != 0) { fs_close_file(ip); return (EP_IO); } for (i = 0; i < nentry; i++) { /* 表示文字長を SFS_MAXNAMELEN にするため.後に pad があるので大丈夫 */ if (strncmp (fname, buf[i].sfs_d_name, SFS_MAXNAMELEN+1) == 0) { inodeindex = buf[i].sfs_d_index; break; } } if (i >= nentry) { fs_close_file(ip); return (EP_NOENT); } while (i < nentry) { buf[i].sfs_d_index = buf[i + 1].sfs_d_index; /* 表示文字長を SFS_MAXNAMELEN にするため.後に pad があるので大丈夫 */ strncpy (buf[i].sfs_d_name, buf[i + 1].sfs_d_name, SFS_MAXNAMELEN+1); i++; } i = parent->i_size - sizeof (struct sfs_dir); sfs_i_write(parent, 0, (B *)buf, i, &rsize); sfs_i_truncate (parent, i); ip->i_link--; ip->i_dirty = 1; if (ip->i_link <= 1) { sfs_i_truncate (ip, 0); sfs_free_inode(ip->i_fs, inodeindex); } parent->i_link -= 1; parent->i_dirty = 1; } fs_close_file(ip); return (EP_OK); }