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

📄 mmap.c

📁 Solaris操作系统下的过滤驱动程序, C源码程序.
💻 C
📖 第 1 页 / 共 3 页
字号:
	cur_ep = &(*cur_ep)->next;	*cur_ep = NULL;	if (err < 0)	    goto out_free;	hidden_size += err;	if (current->need_resched)	    schedule();    }    old_hidden_size = HIDDEN_PAGE_LENGTH(page->index, inode);    hidden_offset = HIDDEN_PAGE_STARTING_OFFSET(page->index, inode);    delta = old_hidden_size - hidden_size;    if (delta != 0) {	/*	 * update hidden size by delta	 *	 * Note! we take a snapshot of the i_size *before* we go	 * into shift_* as those functions can change it; however,	 * we only actually *write* it to disk after all is done	 */	attr.ia_size = hidden_inode->i_size - delta;	if (inode->i_size > page_offset + PAGE_CACHE_SIZE) {	    /* this is write-in-the-middle */	    if (delta > 0) {# ifdef FIST_COUNT_WRITES		count_writes_middle++;		printk("WITM:%lu:%lu:%lu:%lu:\n",		       (unsigned long) page_offset,		       (unsigned long) inode->i_size, count_writes, count_writes_middle);# endif /* FIST_COUNT_WRITES */		/* shift inwards */		err = wrapfs_shift_inward(hidden_file,					  hidden_offset + hidden_size,					  hidden_offset + old_hidden_size,					  hidden_inode->i_size - (hidden_offset + old_hidden_size));		if (err < 0)		    goto out_free;	    } else {		/* shift outwards from the end */		err = wrapfs_shift_outward(hidden_file,					   hidden_offset + hidden_size,					   hidden_offset + old_hidden_size,					   hidden_inode->i_size - (hidden_offset + old_hidden_size));		if (err < 0)		    goto out_free;	    }	} else {	    /* this is append and/or extend */	    if (page->index >= hdr->num_chunks &&		hdr->num_chunks > 0 &&		(hdr->real_size & ~PAGE_CACHE_MASK) != 0) {		/* we need to encode the former incomplete tail */		page_t *old_last_page;		char *old_last_page_data;		int temp_size;		struct encoded_page *temp_ep = NULL;		old_last_page = wrapfs_get1page(file, hdr->num_chunks - 1);		if (IS_ERR(old_last_page)) {		    err = PTR_ERR(old_last_page);		    goto out_free;		}		old_last_page_data = (char *) kmap(old_last_page);		temp_size = 0;		need_to_call = 1;		cur_ep = &temp_ep;		opaque = NULL;		while (need_to_call) {		    *cur_ep = kmalloc(sizeof(struct encoded_page), GFP_KERNEL);		    if (!*cur_ep) {			err = -ENOMEM;			goto out_free;		    }		    (*cur_ep)->data = (char *) __get_free_page(GFP_KERNEL);		    err = wrapfs_encode_buffers((*cur_ep)->data,						old_last_page_data,						&need_to_call,						PAGE_CACHE_SIZE,						inode,						inode->i_sb,						&opaque);		    cur_ep = &(*cur_ep)->next;		    *cur_ep = NULL;		    if (err < 0)			goto encode_error;		    temp_size += err;		    if (current->need_resched)			schedule();		}		old_hidden_offset = HIDDEN_PAGE_STARTING_OFFSET(old_last_page->index, inode);		err = wrapfs_copy_encoded_data(hidden_file,					       old_hidden_offset,					       temp_ep,					       temp_size);		if (err < 0)		    goto encode_error;		/* adjust hidden_offset */		hidden_offset = old_hidden_offset + temp_size;		wrapfs_idx_set_entry(hdr, hdr->num_chunks - 1, hidden_offset);		/* Calculate new hidden file size */		attr.ia_size = hidden_offset + hidden_size;	    encode_error:		/* free encoded_pages */		while (temp_ep) {		    next_ep = temp_ep->next;		    free_page((unsigned long) temp_ep->data);		    kfree(temp_ep);		    temp_ep = next_ep;		}		kunmap(old_last_page);		page_cache_release(old_last_page);		if (err < 0)		    goto out_free;	    }	}	/* update index table structure */	err = wrapfs_idx_set_entry(hdr,				   page->index,				   hidden_offset + hidden_size);	if (err < 0)	    goto out_free;	attr.ia_valid = ATTR_SIZE;	err = notify_change(hidden_dentry, &attr);	if (err < 0)	    goto out_free;	/* update header information by delta */	wrapfs_idx_update(hdr, page->index + 1, -delta);    }    /*     * copy chunk of modified bytes, now that we've     * potentially shifted and made space     */    err = wrapfs_copy_encoded_data(hidden_file,				   hidden_offset,				   ep,				   hidden_size);    if (err < 0)	goto out;    /* we return number of bytes written */    err = to - from;    /* we may have to update the header size */    pos = (page->index << PAGE_CACHE_SHIFT) + to;    if (pos > hdr->real_size)	hdr->real_size = pos;    /* update our file size */    copy_inode_size(inode, hidden_inode);    /*     * 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;out_free:    /* free encoded_pages */    while (ep) {	next_ep = ep->next;	free_page((unsigned long) ep->data);	kfree(ep);	ep = next_ep;    }out:    /* final cleanups */    kunmap(page);		/* kmap was done in prepare_write */    if (err < 0)	ClearPageUptodate(page);    else	SetPageUptodate(page);    up(&hidden_inode->i_sem);    print_exit_status(err);    return err;			/* assume all is ok */}#else /* not FIST_FILTER_SCA */STATIC intwrapfs_commit_write(file_t *file, page_t *page, unsigned from, unsigned to){    int err = -ENOMEM;    inode_t *inode;    inode_t *hidden_inode;    page_t *hidden_page;    file_t *hidden_file = NULL;    loff_t pos;    unsigned bytes = to - from;    unsigned hidden_from, hidden_to, hidden_bytes;    print_entry_location();    inode = page->mapping->host; /* CPW: Moved below print_entry_location */    hidden_inode = itohi(inode);    ASSERT(file != NULL);    /*     * here we have a kmapped page, with data from the user copied     * into it.  we need to encode_block it, and then call the lower     * commit_write.  We also need to simulate same behavior of     * generic_file_write, and call prepare_write on the lower f/s first.     */# ifdef FIST_COUNT_WRITES    count_writes++;# endif /* FIST_COUNT_WRITES */    /* this is append and/or extend -- we can't have holes so fill them in */    if (page->index > (hidden_inode->i_size >> PAGE_CACHE_SHIFT)) {	page_t *tmp_page;	int index;	for (index = hidden_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 the contents of the page at 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();	}    }    hidden_file = ftohf(file);    down(&hidden_inode->i_sem);    /* find lower page (returns a locked page) */    hidden_page = grab_cache_page(hidden_inode->i_mapping, page->index);    if (!hidden_page)	goto out;#if FIST_ENCODING_BLOCKSIZE > 1#error encoding_blocksize greater than 1 is not yet supported#endif /* FIST_ENCODING_BLOCKSIZE > 1 */#ifdef FIST_ENCODING_TYPE_NONE    hidden_from = from;    hidden_to = to;     if ((page->index << PAGE_CACHE_SHIFT) + to > hidden_inode->i_size) {	/*	 * If this call to commit_write had introduced holes and the code	 * for handling holes was invoked, then the beginning of this page	 * must be zeroed out as well:	 *	zero out bytes from 'size_of_file%pagesize' to 'from'.	 */	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));    }#endif  /* FIST_ENCODING_TYPE_NONE */#ifdef FIST_ENCODING_TYPE_STREAM    hidden_from = 0;    if ((page->index << PAGE_CACHE_SHIFT) + to > hidden_inode->i_size) {	/*	 * If this call to commit_write had introduced holes and the code	 * for handling holes was invoked, then the beginning of this page	 * must be zeroed out as well:	 *	zero out bytes from 'size_of_file%pagesize' to 'from'.	 */	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));	hidden_to = to;    }    else if (((page->index + 1) << PAGE_CACHE_SHIFT) <= hidden_inode->i_size)	hidden_to = PAGE_CACHE_SIZE;    else	hidden_to = hidden_inode->i_size & ~PAGE_CACHE_MASK;#endif /* FIST_ENCODING_TYPE_STREAM */#ifdef FIST_ENCODING_TYPE_BLOCK    hidden_from = from & (~(FIST_ENCODING_BLOCKSIZE - 1));    hidden_to = ((to + FIST_ENCODING_BLOCKSIZE - 1) & (~(FIST_ENCODING_BLOCKSIZE - 1)));    if ((page->index << PAGE_CACHE_SHIFT) + to > hidden_inode->i_size) {	/*	 * if this call to commit_write had introduced holes and the code	 * for handling holes was invoked, then the beginning of this page	 * must be zeroed out	 * zero out bytes from 'size_of_file%pagesize' to 'from'.	 */	if ((hidden_from - (inode->i_size & ~PAGE_CACHE_MASK)) > 0)                 memset((char*)page_address(page) + (inode->i_size & ~PAGE_CACHE_MASK), 0, hidden_from - (inode->i_size & ~PAGE_CACHE_MASK));    }#endif /* FIST_ENCODING_TYPE_NONE */    hidden_bytes = hidden_to - hidden_from;    /* call lower prepare_write */    err = -EINVAL;    if (hidden_inode->i_mapping &&	hidden_inode->i_mapping->a_ops &&	hidden_inode->i_mapping->a_ops->prepare_write)	err = hidden_inode->i_mapping->a_ops->prepare_write(hidden_file,							    hidden_page,							    hidden_from,							    hidden_to);    if (err)	/* don't leave locked pages behind, esp. on an ENOSPC */	goto out_unlock;    fist_dprint(8, "%s: encoding %d bytes\n", __FUNCTION__, hidden_bytes);    wrapfs_encode_block((char *) page_address(page) + hidden_from, (char*) page_address(hidden_page) + hidden_from, hidden_bytes, inode, inode->i_sb, page->index);    /* if encode_block could fail, then goto unlock and return error */    /* call lower commit_write */    err = hidden_inode->i_mapping->a_ops->commit_write(hidden_file,						       hidden_page,						       hidden_from,						       hidden_to);    if (err < 0)	goto out_unlock;    err = bytes;	/* convert error to no. of bytes */    inode->i_blocks = hidden_inode->i_blocks;    /* we may have to update i_size */    pos = (page->index << PAGE_CACHE_SHIFT) + to;    if (pos > inode->i_size)	inode->i_size = pos;    /*     * 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;    mark_inode_dirty_sync(inode);out_unlock:    UnlockPage(hidden_page);    page_cache_release(hidden_page);    kunmap(page);		/* kmap was done in prepare_write */out:    /* we must set our page as up-to-date */    if (err < 0)	ClearPageUptodate(page);    else	SetPageUptodate(page);    up(&hidden_inode->i_sem);    print_exit_status(err);    return err;			/* assume all is ok */}#endif /* not FIST_FILTER_SCA */STATIC intwrapfs_bmap(struct address_space *mapping, long block){    int err = 0;    inode_t *inode;    inode_t *hidden_inode;    print_entry_location();    inode = (inode_t *) mapping->host;    hidden_inode = itohi(inode);    if (hidden_inode->i_mapping->a_ops->bmap)	err = hidden_inode->i_mapping->a_ops->bmap(hidden_inode->i_mapping, block);    print_exit_location();    return err;}/* * This function is copied verbatim from mm/filemap.c. * XXX: It should be simply moved to some header file instead -- bug Al about it! */static inline int sync_page(struct page *page){	struct address_space *mapping = page->mapping;	if (mapping && mapping->a_ops && mapping->a_ops->sync_page)		return mapping->a_ops->sync_page(page);	return 0;}/* * XXX: we may not need this function if not FIST_FILTER_DATA. * FIXME: for FIST_FILTER_SCA, get all lower pages and sync them each. */STATIC intwrapfs_sync_page(page_t *page){    int err = 0;    inode_t *inode;    inode_t *hidden_inode;    page_t *hidden_page;    print_entry_location();    inode = page->mapping->host; /* CPW: Moved below print_entry_location */    hidden_inode = itohi(inode);    /* find lower page (returns a locked page) */    hidden_page = grab_cache_page(hidden_inode->i_mapping, page->index);    if (!hidden_page)	goto out;    err = sync_page(hidden_page);    UnlockPage(hidden_page);	/* b/c grab_cache_page locked it */    page_cache_release(hidden_page); /* b/c grab_cache_page increased refcnt */out:    print_exit_location();    return err;}#ifdef FIST_FILTER_DATAstruct address_space_operations wrapfs_aops ={#ifndef FIST_FILTER_SCA    writepage:		wrapfs_writepage,#endif /* not FIST_FILTER_SCA */    readpage:		wrapfs_readpage,    prepare_write:	wrapfs_prepare_write,    commit_write:	wrapfs_commit_write,    bmap:		wrapfs_bmap,    sync_page:		wrapfs_sync_page,};#endif /* FIST_FILTER_DATA *//* * Local variables: * c-basic-offset: 4 * End: */

⌨️ 快捷键说明

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