⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmap.c

📁 Solaris操作系统下的过滤驱动程序, C源码程序.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1997-2003 Erez Zadok * Copyright (c) 2001-2003 Stony Brook University * Copyright (c) 1997-2000 Columbia University * * For specific licensing information, see the COPYING file distributed with * this package, or get one from ftp://ftp.filesystems.org/pub/fist/COPYING. * * This Copyright notice must be kept intact and distributed with all * fistgen sources INCLUDING sources generated by fistgen. *//* *  $Id: mmap.c,v 1.19 2003/02/10 04:08:02 cwright Exp $ */#ifdef HAVE_CONFIG_H# include <config.h>#endif /* HAVE_CONFIG_H */#ifdef FISTGEN# include "fist_wrapfs.h"#endif /* FISTGEN */#include "fist.h"#include "wrapfs.h"#ifdef FIST_COUNT_WRITES/* for counting writes in the middle vs. regular writes */unsigned long count_writes = 0, count_writes_middle = 0;#endif /* FIST_COUNT_WRITES *//* forward declaration of commit write and prepare write */STATIC int wrapfs_commit_write(file_t *file, page_t *page, unsigned from, unsigned to);STATIC int wrapfs_prepare_write(file_t *file, page_t *page, unsigned from, unsigned to);/* * Function for handling creation of holes when lseek-ing past the * end of the file and then writing some data. */intwrapfs_fill_zeros(file_t* file, page_t *page, unsigned from){    int err = 0;    dentry_t *dentry = file->f_dentry;    inode_t *inode = dentry->d_inode;    page_t *tmp_page;    int index;    for (index = inode->i_size >> PAGE_CACHE_SHIFT; index < page->index; index++) {	tmp_page = wrapfs_get1page(file, index);	if (IS_ERR(tmp_page)) {	    err = PTR_ERR(tmp_page);	    goto out;	}	/*	 * zero out rest of the contents of the page between the appropriate	 * offsets.	 */	memset((char*)page_address(tmp_page) + (inode->i_size & ~PAGE_CACHE_MASK), 0, PAGE_CACHE_SIZE - (inode->i_size & ~PAGE_CACHE_MASK));	if (! (err = wrapfs_prepare_write(file, tmp_page, 0, PAGE_CACHE_SIZE)))            err = wrapfs_commit_write(file, tmp_page, 0, PAGE_CACHE_SIZE);	page_cache_release(tmp_page);	if (err < 0)		goto out;        if (current->need_resched)            schedule();    }    /* zero out appropriate parts of last page */#ifdef FIST_ENCODING_TYPE_BLOCK    /*     * if the encoding type is block, then adjust the 'from' (where the     * zeroing will start) offset appropriately     */    from = from & (~(FIST_ENCODING_BLOCKSIZE - 1));#endif /* FIST_ENCODING_TYPE_BLOCK */    if ((from - (inode->i_size & ~PAGE_CACHE_MASK)) > 0) {	memset((char*)page_address(page) + (inode->i_size & ~PAGE_CACHE_MASK), 0, from - (inode->i_size & ~PAGE_CACHE_MASK));	if (! (err = wrapfs_prepare_write(file, page, 0, PAGE_CACHE_SIZE)))            err = wrapfs_commit_write(file, page, 0, PAGE_CACHE_SIZE);	if (err < 0)		goto out;        if (current->need_resched)            schedule();    }out:    return err;}/* * Currently there is no way to make writepage() work with the SCA code, * because we need access to a dentry and writepage only gives us an inode. */#ifndef FIST_FILTER_SCASTATIC intwrapfs_writepage(page_t *page){    int err = -EIO;    inode_t *inode;    inode_t *hidden_inode;    page_t *hidden_page;    char *kaddr, *hidden_kaddr;    print_entry_location();    inode = page->mapping->host;/* CPW: Moved below print_entry_location */    hidden_inode = itohi(inode);    printk("Entering writepage\n");    /*     * writepage is called when shared mmap'ed files need to write     * their pages, while prepare/commit_write are called from the     * non-paged write() interface.  (However, in 2.3 the two interfaces     * share the same cache, while in 2.2 they didn't.)     *     * So we pretty much have to duplicate much of what commit_write does.     */    /* find lower page (returns a locked page) */    hidden_page = grab_cache_page(hidden_inode->i_mapping, page->index);    if (!hidden_page)	goto out;    /* get page address, and encode it */    kaddr = (char *) kmap(page);    hidden_kaddr = (char*) kmap(hidden_page);    wrapfs_encode_block(kaddr, hidden_kaddr, PAGE_CACHE_SIZE, inode, inode->i_sb, page->index);    /* if encode_block could fail, then return error */    kunmap(page);    kunmap(hidden_page);    /* call lower writepage (expects locked page) */    err = hidden_inode->i_mapping->a_ops->writepage(hidden_page);    /*     * update mtime and ctime of lower level file system     * wrapfs' mtime and ctime are updated by generic_file_write     */    hidden_inode->i_mtime = hidden_inode->i_ctime = CURRENT_TIME;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,1)    UnlockPage(hidden_page);	/* b/c grab_cache_page locked it */#endif /* kernel older than 2.4.1 */    page_cache_release(hidden_page); /* b/c grab_cache_page increased refcnt */    if (err)	ClearPageUptodate(page);    else	SetPageUptodate(page);out:#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,1)    UnlockPage(page);#endif /* kernel 2.4.1 and newer */    print_exit_status(err);    return err;}#endif /* not FIST_FILTER_SCA *//* * get one page from cache or lower f/s, return error otherwise. * returns unlocked, up-to-date page (if ok), with increased refcnt. */page_t *wrapfs_get1page(file_t *file, int index){    page_t *page;    dentry_t *dentry;    inode_t *inode;    struct address_space *mapping;    int err;    print_entry_location();    dentry = file->f_dentry; /* CPW: Moved below print_entry_location */    inode = dentry->d_inode;    mapping = inode->i_mapping;    fist_dprint(8, "%s: read page index %d\n", __FUNCTION__, index);    if (index < 0) {	printk("%s BUG: index=%d\n", __FUNCTION__, index);	page = ERR_PTR(-EIO);	goto out;    }    page = read_cache_page(mapping,			   index,			   (filler_t *) mapping->a_ops->readpage,			   (void *) file);    if (IS_ERR(page))	goto out;    wait_on_page(page);    if (!Page_Uptodate(page)) {	lock_page(page);	err = mapping->a_ops->readpage(file, page);	if (err) {	    page = ERR_PTR(err);	    goto out;	}	wait_on_page(page);	if (!Page_Uptodate(page)) {	    page = ERR_PTR(-EIO);	    goto out;	}    } out:    print_exit_pointer(page);    return page;}/* * readpage is called from generic_page_read and the fault handler. * If your file system uses generic_page_read for the read op, it * must implement readpage. * * Readpage expects a locked page, and must unlock it. */STATIC intwrapfs_do_readpage(file_t *file, page_t *page){    int err = -EIO;    dentry_t *dentry;    file_t *hidden_file;    dentry_t *hidden_dentry;    inode_t *inode;    inode_t *hidden_inode;    char *page_data;#ifdef FIST_FILTER_SCA    int i;    int num_hidden_pages;    int hidden_page_index;    page_t **hidden_pages;    char **hidden_pages_data;    void *opaque;#else  /* not FIST_FILTER_SCA */    page_t *hidden_page;    char *hidden_page_data;    int real_size;#endif /* not FIST_FILTER_SCA */    print_entry_location();    dentry = file->f_dentry; /* CPW: Moved below print_entry_location */    hidden_file = ftohf(file);    hidden_dentry = dtohd(dentry);    inode = dentry->d_inode;    hidden_inode = itohi(inode);    fist_dprint(7, "%s: requesting page %d from file %s\n", __FUNCTION__, page->index, dentry->d_name.name);#ifdef FIST_FILTER_SCA    num_hidden_pages = wrapfs_count_hidden_pages(page->index,						 inode,						 &hidden_page_index,						 &opaque);    if (num_hidden_pages <= 0) {	err = num_hidden_pages;	if (err == 0) {	    page_data = (char *) kmap(page);	    memset(page_data, 0, PAGE_CACHE_SIZE);	    kunmap(page);	}	goto out;    }#endif /* FIST_FILTER_SCA */    MALLOC_PAGE_POINTERS(hidden_pages, num_hidden_pages);    MALLOC_PAGEDATA_POINTERS(hidden_pages_data, num_hidden_pages);    FOR_EACH_PAGE	CURRENT_HIDDEN_PAGE = NULL;    /* find lower page (returns a locked page) */    FOR_EACH_PAGE {	fist_dprint(8, "%s: Current page index = %d\n", __FUNCTION__, CURRENT_HIDDEN_PAGEINDEX);	CURRENT_HIDDEN_PAGE = read_cache_page(hidden_inode->i_mapping,					      CURRENT_HIDDEN_PAGEINDEX,					      (filler_t *) hidden_inode->i_mapping->a_ops->readpage,					      (void *) hidden_file);	if (IS_ERR(CURRENT_HIDDEN_PAGE)) {	    err = PTR_ERR(CURRENT_HIDDEN_PAGE);	    CURRENT_HIDDEN_PAGE = NULL;	    goto out_release;	}    }    /*     * wait for the page data to show up     * (signaled by readpage as unlocking the page)     */    FOR_EACH_PAGE {	wait_on_page(CURRENT_HIDDEN_PAGE);	if (!Page_Uptodate(CURRENT_HIDDEN_PAGE)) {	    /*	     * call readpage() again if we returned from wait_on_page with a	     * page that's not up-to-date; that can happen when a partial	     * page has a few buffers which are ok, but not the whole	     * page.	     */	    lock_page(CURRENT_HIDDEN_PAGE);	    err = hidden_inode->i_mapping->a_ops->readpage(hidden_file,							   CURRENT_HIDDEN_PAGE);	    if (err) {		CURRENT_HIDDEN_PAGE = NULL;		goto out_release;	    }	    wait_on_page(CURRENT_HIDDEN_PAGE);	    if (!Page_Uptodate(CURRENT_HIDDEN_PAGE)) {		err = -EIO;		goto out_release;	    }	}    }    /* map pages, get their addresses */    page_data = (char *) kmap(page);    FOR_EACH_PAGE	CURRENT_HIDDEN_PAGEDATA = (char *) kmap(CURRENT_HIDDEN_PAGE);#ifdef FIST_FILTER_SCA# ifdef FIST_FAST_TAILS    /*     * If this is a fast tail (page we were asked for is     * the last page of the file), then we don't need to     * decode this buffer, just stick it into page_data     */    if (IS_FASTTAIL_PAGE(page->index, inode)) {	int offset, len, len0;	offset = HIDDEN_PAGE_STARTING_OFFSET(page->index, inode) & ~PAGE_CACHE_MASK;	len = HIDDEN_PAGE_LENGTH(page->index, inode);	if (offset + len <= PAGE_CACHE_SIZE) {	    /* copy one page */	    ASSERT(num_hidden_pages == 1);	    memcpy(page_data, hidden_pages_data[0] + offset, len);	} else {	    /* copy two pages */	    ASSERT(num_hidden_pages == 2);	    len0 = PAGE_CACHE_SIZE - offset;	    memcpy(page_data, hidden_pages_data[0] + offset, len0);	    memcpy(page_data + len0, hidden_pages_data[1], len - len0);	}	memset(page_data + len, 0, PAGE_CACHE_SIZE - len);	err = 0;    } else# endif /* FIST_FAST_TAILS */	err = wrapfs_decode_buffers(num_hidden_pages, hidden_pages_data,				    page_data, inode, inode->i_sb, opaque);    if (err > 0)	err = 0;#else /* not FIST_FILTER_SCA */    /* if decode_block could fail, then return error */    err = 0;    real_size = hidden_inode->i_size - (page->index << PAGE_CACHE_SHIFT);    if (real_size <= 0)	memset(page_data, 0, PAGE_CACHE_SIZE);    else if (real_size < PAGE_CACHE_SIZE) {	wrapfs_decode_block(hidden_page_data, page_data, real_size, inode, inode->i_sb, page->index);	memset(page_data + real_size, 0, PAGE_CACHE_SIZE - real_size);    } else	wrapfs_decode_block(hidden_page_data, page_data, PAGE_CACHE_SIZE, inode, inode->i_sb, page->index);#endif /* not FIST_FILTER_SCA */    FOR_EACH_PAGE	kunmap(CURRENT_HIDDEN_PAGE);    kunmap(page);out_release:    FOR_EACH_PAGE	if (CURRENT_HIDDEN_PAGE)	    page_cache_release(CURRENT_HIDDEN_PAGE); /* undo read_cache_page */    FREE_PAGE_POINTERS(hidden_pages, num_hidden_pages);    FREE_PAGEDATA_POINTERS(hidden_pages_data, num_hidden_pages);out:    if (err == 0)	SetPageUptodate(page);    else	ClearPageUptodate(page);    print_exit_status(err);    return err;}STATIC intwrapfs_readpage(file_t *file, page_t *page){    int err;    print_entry_location();    err = wrapfs_do_readpage(file, page);    /*     * we have to unlock our page, b/c we _might_ have gotten a locked page.     * but we no longer have to wakeup on our page here, b/c UnlockPage does     * it     */    UnlockPage(page);    print_exit_status(err);    return err;}STATIC intwrapfs_prepare_write(file_t *file, page_t *page, unsigned from, unsigned to){    int err = 0;    print_entry_location();    /*     * we call kmap(page) only here, and do the kunmap     * and the actual downcalls, including unlockpage and uncache     * in commit_write.     */    kmap(page);    /* fast path for whole page writes */    if (from == 0 && to == PAGE_CACHE_SIZE)	goto out;    /* read the page to "revalidate" our data */    /* call the helper function which doesn't unlock the page */    if (!Page_Uptodate(page))        err = wrapfs_do_readpage(file, page); out:    print_exit_status(err);    return err;}#ifdef FIST_FILTER_SCA/* * shift data inwards; return 0 if ok or -errno */int

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -