Commit dae6da31 authored by root's avatar root
Browse files

extract inode

parent 690ca1ec
11/15/2016 v2.0
You can now extract inode of specific file.
To extract inode, you should specify path of file(e.q., "/mnt/testF")
Look test.c
11/11/2016 v1.1
in extractmd.h
struct extractmd_meta_data contains extractmd_super_block and extractmd_group_desc.
......
No preview for this file type
......@@ -8,7 +8,6 @@
#include "extractmd.h"
#include "linux-4.0.9/fs/ext4/ext4.h"
/* Prototypes */
static int __init init_extractmd(void);
static void __exit cleanup_extractmd(void);
......@@ -17,14 +16,17 @@ static int extractmd_ioctl(struct inode *, struct file *, struct extractmd_meta_
static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static struct ext4_group_desc *get_group_desc(struct super_block *sb, ext4_group_t block_group);
static int copy_super_block(struct ext4_super_block *, struct ext4_super_block *);
static int copy_group_desc(struct ext4_group_desc *, struct ext4_group_desc *);
static struct ext4_group_desc *extractmd_get_group_desc(struct super_block *sb, ext4_group_t block_group);
static int extractmd_get_inode_loc(struct inode *, struct ext4_iloc *);
ext4_fsblk_t extractmd_inode_table(struct super_block *, struct ext4_group_desc *);
ext4_fsblk_t extractmd_inode_bitmap(struct super_block *, struct ext4_group_desc *);
__u32 extractmd_itable_unused_count(struct super_block *, struct ext4_group_desc *);
#define DEVICE_NAME "extractmd" /* Dev name as it appears in /proc/devices */
#define MAJOR_NUM 199 /* Device MAJOR number */
/* Global variables are declared as static, so are global within the file.*/
static struct class *my_class;
static dev_t devt;
......@@ -59,62 +61,36 @@ static void __exit cleanup_extractmd(void)
static int extractmd_ioctl(struct inode *inode, struct file *f, struct extractmd_meta_data *md_user)
{
struct file *fp = filp_open("/mnt", O_RDONLY, 0);
struct file *fp = filp_open(md_user->md_path, O_RDONLY, 0);
struct super_block *sb = fp->f_inode->i_sb; // get super_block of vfs
//struct super_block *sb = fp->f_path.mnt->mnt_sb;
struct ext4_sb_info *sbi = EXT4_SB(sb); // get ext4_sb_info
struct ext4_super_block *sbt = sbi->s_es; // get ext4_super_block
struct ext4_group_desc *gdp = get_group_desc(sb,0);
//ext4_group_t ngroup = sbi->s_groups_count;
//unsigned long i = 0;
int ret = 0;
struct ext4_group_desc *gdp = extractmd_get_group_desc(sb,0);
struct ext4_iloc iloc;
extractmd_get_inode_loc(fp->f_inode, &iloc);
struct ext4_inode *raw_inode = ext4_raw_inode(&iloc);
//ext4_group_t ngroup = sbi->s_groups_count;
int ret = 0; // Result for extracing. If ret != 0, some data is not extract.
struct extractmd_meta_data md;
md.md_super_block = *(struct extractmd_super_block *)sbt;
md.md_group_desc = *(struct extractmd_group_desc *)gdp;
// unsigned long tmp = 99;
// int ret = copy_to_user(addr, &tmp, sizeof(unsigned long));
// if( addr == NULL)
// {
// printk(KERN_INFO "NULL POINTER\n");
// return 0;
// }
md.md_inode = *(struct extractmd_inode *)raw_inode;
printk(KERN_INFO "Extractmd start!\n");
freeze_super(sb);
// printk(KERN_INFO "Free inode counts : %lu\n", (unsigned long)sbi->s_es->s_free_inodes_count);
// printk(KERN_INFO "Groups with sparse_super2 SBs : %lu,%lu\n", (unsigned long)sbt->s_backup_bgs[0], (unsigned long)sbt->s_backup_bgs[1]);
// printk(KERN_INFO "Number of groups in fs : %lu\n", (unsigned long)ngroup);
// printk(KERN_INFO "=========================================================\n");
/* for (i = 0; i < ngroup; i++) {
gdp = get_group_desc(sb, i);
printk(KERN_INFO "Group %lu\n", i);
printk(KERN_INFO "Block bitmap at %lu\n", (unsigned long)gdp->bg_block_bitmap_lo);
printk(KERN_INFO "Inode bitmap at %lu\n", (unsigned long)gdp->bg_inode_bitmap_lo);
printk(KERN_INFO "Inode table location : %lu\n", (unsigned long)gdp->bg_inode_table_lo);
printk(KERN_INFO "Free inode counts : %lu\n", (unsigned long)gdp->bg_free_inodes_count_lo);
}*/
freeze_super(sb);
ret = copy_to_user(md_user, &md, sizeof(struct extractmd_meta_data));
thaw_super(sb);
printk(KERN_INFO "%d left\n", ret);
return 0;
}
static struct ext4_group_desc *get_group_desc(struct super_block *sb, ext4_group_t block_group)
static struct ext4_group_desc *extractmd_get_group_desc(struct super_block *sb, ext4_group_t block_group)
{
unsigned int group_desc = block_group >> EXT4_DESC_PER_BLOCK_BITS(sb);
unsigned int offset = block_group &(EXT4_DESC_PER_BLOCK(sb) - 1);
......@@ -122,31 +98,169 @@ static struct ext4_group_desc *get_group_desc(struct super_block *sb, ext4_group
return (struct ext4_group_desc *)((__u8 *)sbi->s_group_desc[group_desc]->b_data + offset * EXT4_DESC_SIZE(sb));
}
/* Called when a process tries to open the device file */
static int device_open(struct inode *inode, struct file *file)
static int extractmd_get_inode_loc(struct inode *inode, struct ext4_iloc *iloc)
{
int in_mem = !ext4_test_inode_state(inode, EXT4_STATE_XATTR);
struct ext4_group_desc *gdp;
struct buffer_head *bh;
struct super_block *sb = inode->i_sb;
ext4_fsblk_t block;
int inodes_per_block, inode_offset;
iloc->bh = NULL;
if (!ext4_valid_inum(sb, inode->i_ino))
return -EIO;
iloc->block_group = (inode->i_ino - 1) / EXT4_INODES_PER_GROUP(sb);
gdp = extractmd_get_group_desc(sb, iloc->block_group);
if (!gdp)
return -EIO;
/*
* Figure out the offset within the block group inode table
*/
inodes_per_block = EXT4_SB(sb)->s_inodes_per_block;
inode_offset = ((inode->i_ino - 1) %
EXT4_INODES_PER_GROUP(sb));
block = extractmd_inode_table(sb, gdp) + (inode_offset / inodes_per_block);
iloc->offset = (inode_offset % inodes_per_block) * EXT4_INODE_SIZE(sb);
bh = sb_getblk(sb, block);
if (unlikely(!bh))
return -ENOMEM;
if (!buffer_uptodate(bh)) {
lock_buffer(bh);
/*
* If the buffer has the write error flag, we have failed
* to write out another inode in the same block. In this
* case, we don't have to read the block because we may
* read the old inode data successfully.
*/
if (buffer_write_io_error(bh) && !buffer_uptodate(bh))
set_buffer_uptodate(bh);
if (buffer_uptodate(bh)) {
/* someone brought it uptodate while we waited */
unlock_buffer(bh);
goto has_buffer;
}
/*
* If we have all information of the inode in memory and this
* is the only valid inode in the block, we need not read the
* block.
*/
if (in_mem) {
struct buffer_head *bitmap_bh;
int i, start;
start = inode_offset & ~(inodes_per_block - 1);
/* Is the inode bitmap in cache? */
bitmap_bh = sb_getblk(sb, extractmd_inode_bitmap(sb, gdp));
if (unlikely(!bitmap_bh))
goto make_io;
/*
* If the inode bitmap isn't in cache then the
* optimisation may end up performing two reads instead
* of one, so skip it.
*/
if (!buffer_uptodate(bitmap_bh)) {
brelse(bitmap_bh);
goto make_io;
}
for (i = start; i < start + inodes_per_block; i++) {
if (i == inode_offset)
continue;
if (ext4_test_bit(i, bitmap_bh->b_data))
break;
}
brelse(bitmap_bh);
if (i == start + inodes_per_block) {
/* all other inodes are free, so skip I/O */
memset(bh->b_data, 0, bh->b_size);
set_buffer_uptodate(bh);
unlock_buffer(bh);
goto has_buffer;
}
}
make_io:
/*
* If we need to do any I/O, try to pre-readahead extra
* blocks from the inode table.
*/
if (EXT4_SB(sb)->s_inode_readahead_blks) {
ext4_fsblk_t b, end, table;
unsigned num;
__u32 ra_blks = EXT4_SB(sb)->s_inode_readahead_blks;
table = extractmd_inode_table(sb, gdp);
/* s_inode_readahead_blks is always a power of 2 */
b = block & ~((ext4_fsblk_t) ra_blks - 1);
if (table > b)
b = table;
end = b + ra_blks;
num = EXT4_INODES_PER_GROUP(sb);
if (ext4_has_group_desc_csum(sb))
num -= extractmd_itable_unused_count(sb, gdp);
table += num / inodes_per_block;
if (end > table)
end = table;
while (b <= end)
sb_breadahead(sb, b++);
}
/*
* There are other valid inodes in the buffer, this inode
* has in-inode xattrs, or we don't have this inode in memory.
* Read the block from disk.
*/
//trace_ext4_load_inode(inode);
get_bh(bh);
bh->b_end_io = end_buffer_read_sync;
submit_bh(READ | REQ_META | REQ_PRIO, bh);
wait_on_buffer(bh);
if (!buffer_uptodate(bh)) {
brelse(bh);
return -EIO;
}
}
has_buffer:
iloc->bh = bh;
return 0;
}
/* Called when a process closes the device file */
static int device_release(struct inode *inode, struct file *file)
ext4_fsblk_t extractmd_inode_table(struct super_block *sb, struct ext4_group_desc *bg)
{
return 0;
return le32_to_cpu(bg->bg_inode_table_lo) | (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ? (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_table_hi) << 32 : 0);
}
ext4_fsblk_t extractmd_inode_bitmap(struct super_block *sb, struct ext4_group_desc *bg)
{
return le32_to_cpu(bg->bg_inode_bitmap_lo) | (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ? (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_bitmap_hi) << 32 : 0);
}
static int copy_super_block(struct ext4_super_block *dst, struct ext4_super_block *src)
__u32 extractmd_itable_unused_count(struct super_block *sb, struct ext4_group_desc *bg)
{
int ret = copy_to_user(dst, src, sizeof(struct ext4_super_block));
return ret;
return le16_to_cpu(bg->bg_itable_unused_lo) | (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ? (__u32)le16_to_cpu(bg->bg_itable_unused_hi) << 16 : 0);
}
static int copy_group_desc(struct ext4_group_desc *dst, struct ext4_group_desc *src)
/* Called when a process tries to open the device file */
static int device_open(struct inode *inode, struct file *file)
{
int ret = copy_to_user(dst, src, sizeof(struct ext4_group_desc));
return ret;
return 0;
}
/* Called when a process closes the device file */
static int device_release(struct inode *inode, struct file *file)
{
return 0;
}
module_init(init_extractmd);
module_exit(cleanup_extractmd);
......
......@@ -148,7 +148,71 @@ struct extractmd_group_desc
__u32 bg_reserved;
};
struct extractmd_inode {
__le16 i_mode; /* File mode */
__le16 i_uid; /* Low 16 bits of Owner Uid */
__le32 i_size_lo; /* Size in bytes */
__le32 i_atime; /* Access time */
__le32 i_ctime; /* Inode Change time */
__le32 i_mtime; /* Modification time */
__le32 i_dtime; /* Deletion Time */
__le16 i_gid; /* Low 16 bits of Group Id */
__le16 i_links_count; /* Links count */
__le32 i_blocks_lo; /* Blocks count */
__le32 i_flags; /* File flags */
union {
struct {
__le32 l_i_version;
} linux1;
struct {
__u32 h_i_translator;
} hurd1;
struct {
__u32 m_i_reserved1;
} masix1;
} osd1; /* OS dependent 1 */
__le32 i_block[15];/* Pointers to blocks */
__le32 i_generation; /* File version (for NFS) */
__le32 i_file_acl_lo; /* File ACL */
__le32 i_size_high;
__le32 i_obso_faddr; /* Obsoleted fragment address */
union {
struct {
__le16 l_i_blocks_high; /* were l_i_reserved1 */
__le16 l_i_file_acl_high;
__le16 l_i_uid_high; /* these 2 fields */
__le16 l_i_gid_high; /* were reserved2[0] */
__le16 l_i_checksum_lo;/* crc32c(uuid+inum+inode) LE */
__le16 l_i_reserved;
} linux2;
struct {
__le16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
__u16 h_i_mode_high;
__u16 h_i_uid_high;
__u16 h_i_gid_high;
__u32 h_i_author;
} hurd2;
struct {
__le16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
__le16 m_i_file_acl_high;
__u32 m_i_reserved2[2];
} masix2;
} osd2; /* OS dependent 2 */
__le16 i_extra_isize;
__le16 i_checksum_hi; /* crc32c(uuid+inum+inode) BE */
__le32 i_ctime_extra; /* extra Change time (nsec << 2 | epoch) */
__le32 i_mtime_extra; /* extra Modification time(nsec << 2 | epoch) */
__le32 i_atime_extra; /* extra Access time (nsec << 2 | epoch) */
__le32 i_crtime; /* File Creation time */
__le32 i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */
__le32 i_version_hi; /* high 32 bits for 64-bit version */
};
struct extractmd_meta_data {
char *md_path;
struct extractmd_super_block md_super_block;
struct extractmd_group_desc md_group_desc;
};
struct extractmd_inode md_inode;
};
\ No newline at end of file
No preview for this file type
No preview for this file type
......@@ -9,13 +9,25 @@ int main()
{
int fd = open("/dev/extractmd", O_RDWR);
struct extractmd_meta_data md;
md.md_path = "/mnt/testE";
ioctl(fd,&md);
printf("%lu\n", (unsigned long)md.md_super_block.s_free_inodes_count);
printf("%lu\n", (unsigned long)md.md_group_desc.bg_inode_table_lo);
printf("%lu\n", (unsigned long)md.md_inode.i_size_lo);
md.md_path = "/mnt/testF";
ioctl(fd,&md);
struct extractmd_super_block a = md.md_super_block;
struct extractmd_group_desc b = md.md_group_desc;
printf("%lu\n", (unsigned long)a.s_free_inodes_count);
printf("%lu\n", (unsigned long)b.bg_inode_table_lo);
printf("%lu\n", (unsigned long)md.md_super_block.s_free_inodes_count);
printf("%lu\n", (unsigned long)md.md_group_desc.bg_inode_table_lo);
printf("%lu\n", (unsigned long)md.md_inode.i_size_lo);
close(fd);
return 0;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment