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

📄 mmap.c

📁 Solaris操作系统下的过滤驱动程序, C源码程序.
💻 C
📖 第 1 页 / 共 2 页
字号:
	    src_page_index--;	    src_page_offset = PAGE_CACHE_SIZE;	    src_page_bytes_left = PAGE_CACHE_SIZE;	    fist_dprint(8, __FUNCTION__ " src: index=%d, offset=%d, bytesleft=%d\n",			src_page_index, src_page_offset, src_page_bytes_left);	    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);	}    } /* end of "while (1)" */ out_release:    page_cache_release(dst_page);    page_cache_release(src_page); out:    print_exit_status(err);    return err;}/* * copy data bytes; return 0 if ok or -errno */intwrapfs_copy_encoded_data(file_t *file,	/* hidden file */			 off_t dst_offset, /* where to copy to (abs offset) */			 encoded_pages_t *encoded_pages,			 off_t total_bytes_to_copy){    int dst_page_index;    unsigned int dst_page_offset, src_page_offset;    page_t *dst_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();    // XXX: check errors    //    printk("EZK0: total_bytes_to_copy 0x%x\n", (int) total_bytes_to_copy);    /* compute page indices */    dst_page_index = dst_offset >> PAGE_CACHE_SHIFT;    /* compute offsets within pages */    dst_page_offset = dst_offset & ~PAGE_CACHE_MASK;    src_page_offset = 0;    /* compute number of bytes left in pages */    dst_page_bytes_left = PAGE_CACHE_SIZE - dst_page_offset;    src_page_bytes_left = PAGE_CACHE_SIZE; /* adjusted below */    /* get pages */    dst_page = wrapfs_get1page(file, dst_page_index);    if (IS_ERR(dst_page)) {	err = PTR_ERR(dst_page);	goto out;    }    /* map pages into kernel addresses */    src_kaddr = encoded_pages->data;    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_copy);	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_copy -= bytes_to_copy;	//	printk("EZK1: total_bytes_to_copy 0x%x\n", (int) total_bytes_to_copy);	if (total_bytes_to_copy == 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)) {		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 */	    src_page_offset = 0;	    src_page_bytes_left = PAGE_CACHE_SIZE;	    encoded_pages = encoded_pages->next;	    src_kaddr = encoded_pages->data;	} else {	    src_page_offset += bytes_to_copy;	}    } /* end of "while (1)" */ out_release:    page_cache_release(dst_page); out:    print_exit_status(err);    return err;}STATIC intwrapfs_commit_write(file_t *file, page_t *page, unsigned from, unsigned to){    int err;    inode_t *inode = (inode_t *) page->mapping->host;    inode_t *hidden_inode = itohi(inode);    file_t *hidden_file = NULL;    loff_t pos = 0;    struct encoded_page *ep = NULL, *next_ep, **cur_ep;    unsigned real_to, hidden_size, page_offset;    struct iattr attr;    void *opaque = NULL;    off_t old_hidden_size, hidden_offset, old_hidden_offset, delta;    dentry_t *hidden_dentry;    struct scafs_header *hdr;    int need_to_call = 1;    print_entry_location();    ASSERT(file != NULL);    hidden_file = ftohf(file);    hidden_dentry = hidden_file->f_dentry;    down(&hidden_inode->i_sem);    /*     * 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 */    hdr = &itopd(inode)->hdr;    page_offset = page->index << PAGE_CACHE_SHIFT;    if (inode->i_size > page_offset + to)	if (inode->i_size > page_offset + PAGE_CACHE_SIZE)	    real_to = PAGE_CACHE_SIZE;	else	    real_to = inode->i_size - page_offset;    else	real_to = to;    hidden_size = 0;    cur_ep = &ep;    while (need_to_call) {	*cur_ep = kmalloc(sizeof(struct encoded_page), GFP_KERNEL);	(*cur_ep)->data = (char *) __get_free_page(GFP_KERNEL);#ifdef FIST_FAST_TAILS	if (CAN_BE_FASTTAIL_PAGE(real_to, inode) &&	    page->index + 1 >= hdr->num_chunks) {	    memcpy((*cur_ep)->data, (char *) page_address(page), real_to);	    need_to_call = 0;	    err = real_to;	    hdr->flags |= SCA_FLAG_FASTTAIL;	} else#endif /* FIST_FAST_TAILS */	{	    err = wrapfs_encode_buffers((*cur_ep)->data,					(char *) page_address(page),					&need_to_call,					real_to,					inode,					inode->i_sb,					&opaque);	    if (page->index + 1 >= hdr->num_chunks)		hdr->flags &= ~SCA_FLAG_FASTTAIL;	}	cur_ep = &(*cur_ep)->next;	*cur_ep = NULL;	if (err < 0)	    goto out_free;	hidden_size += err;    }    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);		    (*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;		}		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_s(temp_ep, sizeof(encoded_pages_t));		    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);out_free:    /* free encoded_pages */    while (ep) {	next_ep = ep->next;	free_page((unsigned long) ep->data);	kfree_s(ep, sizeof(encoded_pages_t));	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 *) page->mapping->host;    inode_t *hidden_inode = itohi(inode);    page_t *hidden_page;    file_t *hidden_file = NULL;    char *hidden_kaddr;    loff_t pos = 0;    unsigned bytes = to - from;    print_entry_location();    down(&hidden_inode->i_sem);    /*     * 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 */    /* find lower page (returns a locked page) */    hidden_page = grab_cache_page(hidden_inode->i_mapping, page->index);    if (!hidden_page)	goto out;    ASSERT(file != NULL);    hidden_file = ftohf(file);    /* 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,							    from,							    to);    if (err) {	/* don't leave locked pages behind, esp. on an ENOSPC */	goto out_unlock;    }    /* get page address, and encode it */    hidden_kaddr = (char*) page_address(hidden_page);    wrapfs_encode_block((char *) page_address(page), hidden_kaddr, PAGE_SIZE, inode, inode->i_sb);    /* 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,						       from,						       to);    ASSERT(err == 0 || err == bytes);	/* disallow partial writes */    if (err == 0)	err = bytes;	/* convert error to no. of bytes */    /* we may have to update hidden_inode->i_size */    if (err >= 0) {	pos = (page->index << PAGE_CACHE_SHIFT) + to;	if (pos > hidden_inode->i_size) {	    hidden_inode->i_size = pos;	}    }    if (hidden_inode->i_size > inode->i_size) {	inode->i_size = hidden_inode->i_size;	inode->i_blocks = hidden_inode->i_blocks;    }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 *) mapping->host;    inode_t *hidden_inode = itohi(inode);    print_entry_location();    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;}/* * XXX: we may not need this function if not FIST_FILTER_DATA. * XXX: 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 *) page->mapping->host;    inode_t *hidden_inode = itohi(inode);    page_t *hidden_page;    print_entry_location();    /* 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;}struct address_space_operations wrapfs_aops ={    writepage:		wrapfs_writepage,    readpage:		wrapfs_readpage,    prepare_write:	wrapfs_prepare_write,    commit_write:	wrapfs_commit_write,    bmap:		wrapfs_bmap,    sync_page:		wrapfs_sync_page,};/* * Local variables: * c-basic-offset: 4 * End: */

⌨️ 快捷键说明

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