1、修改部分代码:红色字体为修改部分
static void mpage_end_io(s truct bio *bio, int err)//bio->bi_io_vec数组对应各个数据段,每个数据段对应pages(非mpage机制每个数据段对应一个块),如:bio->bi_io_vec[0]对应一页。
{
const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
unsigned long buffer_flag=6;
int i,j;
int major=MAJOR(bio->bi_bdev->bd_dev);//求出主设备号
int nvec;
do {
struct page *page = bvec->bv_page;
if (--bvec >= bio->bi_io_vec)
prefetchw(&bvec->bv_page->flags);
if (bio_data_dir(bio) == READ) {
if (uptodate) {
/******************/
struct bio_vec *bvecx;
unsigned char *address_bf;//
unsigned long int tt;//
bvecx=bvec+1;
buffer_flag = bvecx->bv_page->buffer_flag;//page页的自定义的标记位buffer_flag
//printk(" 1111 ");
address_bf=page_address(bvecx->bv_page);//求出页的起始地址
address_bf=address_bf+bvecx->bv_offset;//页起始地址加上偏移值求出读地址
//printk(" 22222 ");
//struct buffer_head *bh;
//bh=bio->bi_private;
//printk(" 33333 ");
//unsigned char *tmp1;
//tmp1=(unsigned char*)bh->b_data;
tt = bio->bi_sector;///这个扇区号为绝对扇区号,generic_make_request()等函数里的bio中的扇区号为从分区表起始的相对扇区号。本特点本项目中没有用到。
printk(" mpage_end_io:tt:%ld ",tt);
if (buffer_flag == 3){ //buffer_flag是自己在page中定义的一个项,用于区分读写的是普通文件还是文件目录表,分区表之类的
if(major==179)//major是179,就是针对的是SD卡
{
for(i=0;i<bvecx->bv_len/512;i++)//bvecx->bv_len代表一个字段的长度,一个 扇区是512字节,表示有多少个扇区
{
printk("before read:%d ", address_bf[i*512]);
for(j=0;j<512;j++)
{
address_bf[j+i*512]^=0xff;//针对每个扇区的每个字节按位取反(相当于加密)
}
}
}
}
/******************/
SetPageUptodate(page);
} else {
ClearPageUptodate(page);
SetPageError(page);
}
unlock_page(page);
} else { /* bio_data_dir(bio) == WRITE */在这部分是针对写返回的操作
struct bio_vec *bvecx;
unsigned char *address_bf;
bvecx=bvec+1;
buffer_flag = bvecx->bv_page->buffer_flag;//
address_bf=page_address(bvecx->bv_page);//
address_bf=address_bf+bvecx->bv_offset;//
if(major==179)
{nvec=bio->bi_vcnt;
//printk(" major");
//printk(" generic: %s: tt:%ld nvec:%ld", (rw_flag)?"write":"read", tt, nvec);
for(i=0;i<nvec;i++)//每个bio中段个数
{
if(i>1)
{
printk("%d mpage nvec= ",i);
}
//buffer_flag=bio->bi_io_vec[i].bv_page->buffer_flag;
buffer_flag = bio->bi_io_vec[i].bv_page->buffer_flag;
//address_bf=page_address(bio->bi_io_vec[i].bv_page);
//address_bf=address_bf+bio->bi_io_vec[i].bv_offset;
if (buffer_flag == 3)//如果是写SD卡返回,在generic_make_request中,如果执行generic_make_request函数,则将此标记位置为3,此位置判断是否为3,如果是3的话,就判定他执行了generic_make_request函数
{ //bio->bi_io_vec[i].bv_page->buffer_flag = 3;
//buffer_flag = bio->bi_io_vec[i].bv_page->buffer_flag;
address_bf=page_address(bio->bi_io_vec[i].bv_page);//
address_bf=address_bf+bio->bi_io_vec[i].bv_offset;
memcpy(address_bf,bio->bi_io_vec[i].bv_data_address,bio->bi_io_vec[i].bv_len);//参照generic_make_request函数,在generic_make_request函数中,针对要操作的缓冲区,又申请了一个缓冲区,将原先的明文备份,此处是将备份的明文重新拷贝到原先的缓冲区中,使系统感觉不到加密,
kfree(bio->bi_io_vec[i].bv_data_address);//将申请的用于备份的缓冲区释放掉
printk(" nvec ");
printk("mpage success ");
}
printk(" end_ion success");
}
}
if (!uptodate) {
SetPageError(page);
if (page->mapping)
set_bit(AS_EIO, &page->mapping->flags);
}
end_page_writeback(page);
}
} while (bvec >= bio->bi_io_vec);
bio_put(bio);
}
void generic_make_request(struct bio *bio)
{
struct bio_list bio_list_on_stack;
/********************/
unsigned char *address_bf;
int major;
int i,k,j;
unsigned long rw_flag;
unsigned long int tt,nvec;
unsigned long buffer_flag=9;
//unsigned long check_flag;
//struct buffer_head *bh_fyk;
major=MAJOR(bio->bi_bdev->bd_dev);//求出设备的主设备号
tt=bio->bi_sector;
nvec=bio->bi_vcnt;
rw_flag=(bio->bi_rw)&WRITE;
if(major==179)//主设备号是179是SD卡
{
printk(" generic: %s: tt:%ld nvec:%ld", (rw_flag)?"write":"read", tt, nvec);
for(i=0;i<nvec;i++)
{
if (bio->bi_io_vec[i].bv_page->buffer_flag == 2)
{
bio->bi_io_vec[i].bv_page->buffer_flag = 3;//该标记在函数?中,赋值2,只有读文件时经过该函数,读目录(区)不经过。满足条件,说明是读文件,则将标记改为3.
}
buffer_flag = bio->bi_io_vec[i].bv_page->buffer_flag;//置新的标志位
if (rw_flag)//如果是写
{
address_bf=page_address(bio->bi_io_vec[i].bv_page);
address_bf=address_bf+bio->bi_io_vec[i].bv_offset;//求出地址
printk(" address_bf:%08x, page:%08x, bio:%08x ", (unsigned int)address_bf, (unsigned int)bio->bi_io_vec[i].bv_page, (unsigned int)bio);
if (buffer_flag==3)//注意:如果是写SD卡的话(前面已经有major和rw_flag进行判断),统一将buffer_flag置为3
{
//address_bf=page_address(bio->bi_io_vec[i].bv_page);
//address_bf=address_bf+bio->bi_io_vec[i].bv_offset;
bio->bi_io_vec[i].bv_data_address=kmalloc(bio->bi_io_vec[i].bv_len,GFP_KERNEL);//申请一块缓冲区
memcpy(bio->bi_io_vec[i].bv_data_address,address_bf,bio->bi_io_vec[i].bv_len);//将明文保存在地址为bio->bi_io_vec[i].bv_data_address的缓冲区中
for(k=0;k<bio->bi_io_vec[i].bv_len/512;k++)//具体到扇区中
{
printk("before write:%d ", address_bf[k*512]);
for(j=0;j<512;j++)
{
address_bf[j+k*512]^=0xff;//char型数据,8位。0xff
}
}
}
}
}
//printk(" %s buffer_flag:%ld", (rw_flag)?"write":"read", buffer_flag);
}
注:修改的结构体如下:
struct bio_vec {
struct page *bv_page;
unsigned int bv_len;
unsigned int bv_offset;
char *bv_data_address;//此处为新加的结构体项,用于保存新申请的缓冲区的指针
};
struct page {
unsigned long flags; /* Atomic flags, some possibly
* updated asynchronously */
atomic_t _count; /* Usage count, see below. */
union {
atomic_t _mapcount; /* Count of ptes mapped in mms,
* to show when page is mapped
* & limit reverse map searches.
*/
struct { /* SLUB */
u16 inuse;
u16 objects;
};
};
union {
struct {
unsigned long private; /* Mapping-private opaque data:
* usually used for buffer_heads
* if PagePrivate set; used for
* swp_entry_t if PageSwapCache;
* indicates order in the buddy
* system if PG_buddy is set.
*/
struct address_space *mapping; /* If low bit clear, points to
* inode address_space, or NULL.
* If page mapped as anonymous
* memory, low bit is set, and
* it points to anon_vma object:
* see PAGE_MAPPING_ANON below.
*/
};
#if USE_SPLIT_PTLOCKS
spinlock_t ptl;
#endif
struct kmem_cache *slab; /* SLUB: Pointer to slab */
struct page *first_page; /* Compound tail pages */
};
union {
pgoff_t index; /* Our offset within mapping. */
void *freelist; /* SLUB: freelist req. slab lock */
};
struct list_head lru; /* Pageout list, eg. active_list
* protected by zone->lru_lock !
*/
/*
* On machines where all RAM is mapped into kernel address space,
* we can simply calculate the virtual address. On machines with
* highmem some memory is mapped into kernel virtual memory
* dynamically, so we need a place to store that address.
* Note that this field could be 16 bits on x86 ... ;)
*
* Architectures with slow multiplication can define
* WANT_PAGE_VIRTUAL in asm/page.h
*/
#if defined(WANT_PAGE_VIRTUAL)
void *virtual; /* Kernel virtual address (NULL if
not kmapped, ie. highmem) */
#endif /* WANT_PAGE_VIRTUAL */
#ifdef CONFIG_WANT_PAGE_DEBUG_FLAGS
unsigned long debug_flags; /* Use atomic bitops on this */
#endif
#ifdef CONFIG_KMEMCHECK
/*
* kmemcheck wants to track the status of each byte in a page; this
* is a pointer to such a status block. NULL if not tracked.
*/
void *shadow;
#endif
unsigned long buffer_flag;//新加一个项,用于判断读写的文件类型,以及对于后面操作的一个标记位
};
buffer_flag识别函数是否经过了mpage_readpages函数。只有读文件数据经过该函数,读取目录和挂载过程不经过该函数,这个特点可以在generic_make_request()函数和回调函数中用于分辨本次IO是读文件IO(加解密),还是读取文件夹的IO(不加密))。