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

📄 mmap.c

📁 Solaris操作系统下的过滤驱动程序, C源码程序.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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.64 2002/12/27 20:19:02 ezk 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 */STATIC intwrapfs_writepage(file_t *file, page_t *page){    int err = -EIO;    dentry_t *dentry = file->f_dentry;    dentry_t *hidden_dentry = dtohd(dentry);    inode_t *inode = dentry->d_inode;    inode_t *hidden_inode = itohi(inode);    file_t *hidden_file = ftohf(file);    page_t *hidden_page;    char *kaddr, *hidden_kaddr;    print_entry_location();    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);#ifdef FIST_FILTER_SCA    /* XXX Do we need to do anything here? XXX This is never called...*/#else  /* not FIST_FILTER_SCA */    wrapfs_encode_block(kaddr, hidden_kaddr, PAGE_SIZE, inode, inode->i_sb);#endif /* not FIST_FILTER_SCA */    /* 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_file,						    hidden_page);    UnlockPage(hidden_page);	/* b/c grab_cache_page locked it */    page_cache_release(hidden_page); /* b/c grab_cache_page increased refcnt */    if (err)	ClearPageUptodate(page);    else	SetPageUptodate(page);out:    print_exit_status(err);    return err;}/* * 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->f_dentry;    file_t *hidden_file = ftohf(file);    dentry_t *hidden_dentry = dtohd(dentry);    inode_t *inode = dentry->d_inode;    inode_t *hidden_inode = itohi(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;#endif /* not FIST_FILTER_SCA */    print_entry_location();    fist_dprint(7, "requesting page %d from file %s\n", 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, "Current page index = %d\n", 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;    wrapfs_decode_block(hidden_page_data, page_data, PAGE_SIZE, inode, inode->i_sb);#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 "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 */intwrapfs_shift_inward(file_t *file,	/* hidden file we're shifting */		    off_t dst_offset,	/* where to shift to (abs offset) */		    off_t src_offset,	/* where to shift from (abs offset) */		    off_t total_bytes_to_shift){    int dst_page_index, src_page_index;    unsigned int dst_page_offset, src_page_offset;    page_t *dst_page, *src_page;    off_t bytes_to_copy;    int dst_page_bytes_left, src_page_bytes_left;    char *dst_kaddr, *src_kaddr;    int err = 0;    struct address_space_operations *a_ops;    print_entry_location();    if (total_bytes_to_shift <= 0) {	printk("wrapfs_shift_inward asked to shift %ld bytes\n", total_bytes_to_shift);	goto out;    }    /* compute page indices */    dst_page_index = dst_offset >> PAGE_CACHE_SHIFT;    src_page_index = src_offset >> PAGE_CACHE_SHIFT;    /* compute offsets within pages */    dst_page_offset = dst_offset & ~PAGE_CACHE_MASK;    src_page_offset = src_offset & ~PAGE_CACHE_MASK;    /* compute number of bytes left in pages */    dst_page_bytes_left = PAGE_CACHE_SIZE - dst_page_offset;    src_page_bytes_left = PAGE_CACHE_SIZE - src_page_offset;    /* get pages */    dst_page = wrapfs_get1page(file, dst_page_index);    if (IS_ERR(dst_page)) {	err = PTR_ERR(dst_page);	goto out;    }    src_page = wrapfs_get1page(file, src_page_index);    if (IS_ERR(src_page)) {	page_cache_release(dst_page);	err = PTR_ERR(src_page);	goto out;    }    src_kaddr = (char *) kmap(src_page);    a_ops = file->f_dentry->d_inode->i_mapping->a_ops;    while (1) {	src_page_bytes_left = MIN(src_page_bytes_left, total_bytes_to_shift);	bytes_to_copy = MIN(src_page_bytes_left, dst_page_bytes_left);	/* lock destination page */	lock_page(dst_page);	err = a_ops->prepare_write(file,				   dst_page,				   dst_page_offset,				   dst_page_offset+bytes_to_copy);	if (err < 0) {		/* XXX: what about partial writes */	    UnlockPage(dst_page);	    goto out_release;	}	dst_kaddr = (char *) page_address(dst_page);	/* actually copy some bytes */	memmove(dst_kaddr + dst_page_offset,		src_kaddr + src_page_offset,		bytes_to_copy);	err = a_ops->commit_write(file,				  dst_page,				  dst_page_offset,				  dst_page_offset+bytes_to_copy);	UnlockPage(dst_page);	if (err) {	    goto out_release;	}	total_bytes_to_shift -= bytes_to_copy;	if (total_bytes_to_shift == 0)	    break;	/* adjust destinations as needed */	dst_page_bytes_left -= bytes_to_copy;	if (dst_page_bytes_left == 0) { /* get new page */	    page_cache_release(dst_page);	    dst_page_index++;	    dst_page_offset = 0;	    dst_page_bytes_left = PAGE_CACHE_SIZE;	    dst_page = wrapfs_get1page(file, dst_page_index);	    if (IS_ERR(dst_page)) {		page_cache_release(src_page);		err = PTR_ERR(dst_page);		goto out;	    }	} else {	    dst_page_offset += bytes_to_copy;	}	/* adjust sources as needed */	src_page_bytes_left -= bytes_to_copy;	if (src_page_bytes_left == 0) { /* get new page */	    kunmap(src_page);	    page_cache_release(src_page);	    src_page_index++;	    src_page_offset = 0;	    src_page_bytes_left = PAGE_CACHE_SIZE;	    src_page = wrapfs_get1page(file, src_page_index);	    if (IS_ERR(src_page)) {		page_cache_release(dst_page);		err = PTR_ERR(src_page);		goto out;	    }	    src_kaddr = (char *) kmap(src_page);	} else {	    src_page_offset += bytes_to_copy;	}    } /* end of "while (1)" */ out_release:    page_cache_release(dst_page);    page_cache_release(src_page); out:    print_exit_status(err);    return err;}/* * shift data inwards; return 0 if ok or -errno */intwrapfs_shift_outward(file_t *file,	/* hidden file we're shifting */		     off_t dst_offset,	/* where to shift to (abs offset) */		     off_t src_offset,	/* where to shift from (abs offset) */		     off_t total_bytes_to_shift){    int dst_page_index, src_page_index;    unsigned int dst_page_offset, src_page_offset;    page_t *dst_page, *src_page;    off_t bytes_to_copy;    int dst_page_bytes_left, src_page_bytes_left;    char *dst_kaddr, *src_kaddr;    int err = 0;    struct address_space_operations *a_ops;    print_entry_location();    fist_dprint(8, __FUNCTION__ " args: dst_off=%d, src_off=%d, bytes=%d\n",		dst_offset, src_offset, total_bytes_to_shift);    if (total_bytes_to_shift <= 0) {	printk("wrapfs_shift_outward asked to shift %ld bytes\n", total_bytes_to_shift);	goto out;    }    /* compute page indices */    dst_page_index = (dst_offset + total_bytes_to_shift) >> PAGE_CACHE_SHIFT;    src_page_index = (src_offset + total_bytes_to_shift) >> PAGE_CACHE_SHIFT;    /* compute offsets within pages */    dst_page_offset = (dst_offset + total_bytes_to_shift) & ~PAGE_CACHE_MASK;    src_page_offset = (src_offset + total_bytes_to_shift) & ~PAGE_CACHE_MASK;    /* compute number of bytes left in pages */    dst_page_bytes_left = dst_page_offset;    src_page_bytes_left = src_page_offset;    fist_dprint(8, __FUNCTION__ " dst: index=%d, offset=%d, bytesleft=%d\n",		dst_page_index, dst_page_offset, dst_page_bytes_left);    fist_dprint(8, __FUNCTION__ " src: index=%d, offset=%d, bytesleft=%d\n",		src_page_index, src_page_offset, src_page_bytes_left);    /* get pages */    dst_page = wrapfs_get1page(file, dst_page_index);    if (IS_ERR(dst_page)) {	err = PTR_ERR(dst_page);	goto out;    }    src_page = wrapfs_get1page(file, src_page_index);    if (IS_ERR(src_page)) {	page_cache_release(dst_page);	err = PTR_ERR(src_page);	goto out;    }    src_kaddr = (char *) kmap(src_page);    a_ops = file->f_dentry->d_inode->i_mapping->a_ops;    while (1) {	src_page_bytes_left = MIN(src_page_bytes_left, total_bytes_to_shift);	bytes_to_copy = MIN(src_page_bytes_left, dst_page_bytes_left);	dst_page_offset -= bytes_to_copy;	src_page_offset -= bytes_to_copy;	/* lock destination page */	lock_page(dst_page);	err = a_ops->prepare_write(file,				   dst_page,				   dst_page_offset,				   dst_page_offset+bytes_to_copy);	if (err < 0) {		/* XXX: what about partial writes */	    UnlockPage(dst_page);	    goto out_release;	}	dst_kaddr = (char *) page_address(dst_page);	/* actually copy some bytes */	memmove(dst_kaddr + dst_page_offset,		src_kaddr + src_page_offset,		bytes_to_copy);	err = a_ops->commit_write(file,				  dst_page,				  dst_page_offset,				  dst_page_offset+bytes_to_copy);	UnlockPage(dst_page);	if (err) {	    goto out_release;	}	total_bytes_to_shift -= bytes_to_copy;	if (total_bytes_to_shift == 0)	    break;	/* adjust destinations as needed */	dst_page_bytes_left -= bytes_to_copy;	if (dst_page_bytes_left == 0) { /* get new page */	    page_cache_release(dst_page);	    dst_page_index--;	    dst_page_offset = PAGE_CACHE_SIZE;	    dst_page_bytes_left = PAGE_CACHE_SIZE;	    fist_dprint(8, __FUNCTION__ " dst: index=%d, offset=%d, bytesleft=%d\n",			dst_page_index, dst_page_offset, dst_page_bytes_left);	    dst_page = wrapfs_get1page(file, dst_page_index);	    if (IS_ERR(dst_page)) {		page_cache_release(src_page);		err = PTR_ERR(dst_page);		goto out;	    }	}	/* adjust sources as needed */	src_page_bytes_left -= bytes_to_copy;	if (src_page_bytes_left == 0) { /* get new page */	    page_cache_release(src_page);

⌨️ 快捷键说明

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