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

📄 file.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: file.c,v 1.16 2002/12/27 20:18:59 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"/******************* * File Operations * *******************/STATIC loff_twrapfs_llseek(file_t *file, loff_t offset, int origin){    loff_t err;    file_t *hidden_file = ftohf(file);    print_entry_location();    fist_dprint(6, "wrapfs_llseek: file=%x, offset=0x%x, origin=%d\n",		(int) file, (int) offset, origin);    //    fist_print_file("LLSEEK Before file", file);    //    fist_print_file("LLSEEK Before hidden_file", hidden_file);    /* always set hidden position to this one */    hidden_file->f_pos = file->f_pos;    if (file->f_reada) { /* update readahead information if needed */	hidden_file->f_reada = file->f_reada;	hidden_file->f_ramax = file->f_ramax;	hidden_file->f_raend = file->f_raend;	hidden_file->f_ralen = file->f_ralen;	hidden_file->f_rawin = file->f_rawin;    }    ASSERT(hidden_file->f_reada == file->f_reada);    ASSERT(hidden_file->f_ramax == file->f_ramax);    ASSERT(hidden_file->f_raend == file->f_raend);    ASSERT(hidden_file->f_ralen == file->f_ralen);    ASSERT(hidden_file->f_rawin == file->f_rawin);    if (hidden_file->f_op && hidden_file->f_op->llseek) {	err = hidden_file->f_op->llseek(hidden_file, offset, origin);    } else {	err = default_llseek(hidden_file, offset, origin);    }    if (err < 0) {	goto out;    }    if (err != file->f_pos) {	file->f_pos = err;	// ION maybe this?	// 	file->f_pos = hidden_file->f_pos;	file->f_reada = 0;	file->f_version = ++global_event;    }out:    //    fist_print_file("LLSEEK After file", file);    //    fist_print_file("LLSEEK After hidden_file", hidden_file);    print_exit_status(err);    return err;}STATIC ssize_twrapfs_dir_read(file_t *file, char *buf, size_t count, loff_t *ppos){    return -EISDIR;}/* * generic_file_read updates the atime of upper layer inode. * But, it doesn't give us a chance to update the atime of * the lower layer inode. This function is a wrapper to * generic_file_read. it Updates the atime of the lower level * inode if generic_file_read returns without any errors * this function should be used only for file reads and not * for directory reads. */STATIC ssize_twrapfs_read(file_t *file, char* buf, size_t count, loff_t *ppos){    int err = 0;    print_entry_location();    err = generic_file_read(file, buf, count, ppos);    if (err >= 0)	UPDATE_ATIME(itohi(file->f_dentry->d_inode));    print_exit_status(err);    return err;}/* * Adapted from 2.1 generic_file_write */STATIC ssize_twrapfs_write(file_t *file, const char *buf, size_t count, loff_t *ppos){    file_t *hidden_file;    page_t *page, **hash;    unsigned long page_cache = 0;    unsigned long pgpos, orig_pgpos, offset;    unsigned long bytes, written;    size_t bytes_to_write;    loff_t pos, orig_pos, tmp_pos;    ssize_t status;    long didread;    mm_segment_t old_fs;    char *hidden_buffer;    inode_t *inode = file->f_dentry->d_inode;    inode_t *hidden_inode = itohi(inode);    print_entry_location();    /* check that offsets are correct */    ASSERT(file != NULL);    ASSERT(ppos != NULL);    pos = *ppos;    written = 0;    status = 0;    old_fs = get_fs();    hidden_file = ftohf(file);    ASSERT(hidden_file != NULL);    hidden_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);    if (!hidden_buffer) {	printk("Out of memory.\n");	status = -ENOMEM;	goto out;    }    /* we don't want anybody to do updates while we write, so lock the inode */    down(&hidden_inode->i_sem);    if (file->f_flags & O_APPEND)	pos = inode->i_size;    fist_dprint(6, "EZK: WRITE: initial values: pos %ld, count %d\n", (long) pos, count);    fist_print_file("EZK: WRITE file IN", file);    /* we need to handle sparse files differently */    orig_pos = pos;    orig_pgpos = orig_pos & PAGE_MASK;    if (pos > inode->i_size)	pos = inode->i_size;    while (count) {	fist_dprint(7, "WRITE: pos %ld, written %ld, count %d, buf 0x%lx\n",		    (long) pos, written, count, (long) buf);	/*	 * Try to find the page in the cache. If it isn't there,	 * allocate a free page.	 */	offset = (pos & ~PAGE_MASK);	pgpos = pos & PAGE_MASK;	if ((bytes = PAGE_SIZE - offset) > count && pgpos >= orig_pgpos)	    bytes = count;	hash = page_hash(inode, pgpos);	if (!(page = __find_page(inode, pgpos, *hash))) {	    if (!page_cache) {		page_cache = __get_free_page(GFP_KERNEL);		if (page_cache)		    continue;		status = -ENOMEM;		break;	    }	    page = mem_map + MAP_NR(page_cache);	    add_to_page_cache(page, inode, pgpos, hash);	    page_cache = 0;	}	/*	 * Note: setting of the PG_locked bit is handled	 * below the i_op->xxx interface.	 */	didread = 0;    page_wait:	wait_on_page(page);	if (PageUptodate(page))	    goto do_update_page;	/*	 * The page is not up-to-date ... if we're writing less	 * than a full page of data, we may have to read it first.	 * But if the page is past the current end of file, we must	 * clear it before updating.	 */	if (bytes < PAGE_SIZE) {	    if (pgpos < inode->i_size) {		status = -EIO;		if (didread >= 2)		    goto done_with_page;		/* call our own readpage function */		status = inode->i_op->readpage(file, page);		if (status < 0)		    goto done_with_page;		didread++;		goto page_wait;	    } else {		/* Must clear for partial writes */		fist_dprint(7, "WRITE1: clearing page at offset 0x%x\n", (int) pgpos);		memset((void *) page_address(page), 0, PAGE_SIZE);	    }	} else if (pos < orig_pos) {	    /* Must clear for sparse files */	    fist_dprint(7, "WRITE2: clearing page at offset 0x%x\n", (int) pgpos);	    memset((void *) page_address(page), 0, PAGE_SIZE);	}	/*	 * N.B. We should defer setting PG_uptodate at least until	 * the data is copied. A failure in i_op->updatepage() could	 * leave the page with garbage data.	 */	set_bit(PG_uptodate, &page->flags);    do_update_page:	/* Alright, the page is there.  Now update it. */	fist_dprint(7, "WRITE: count %d, pos %ld, offset %ld, pgpos 0x%x, bytes %d\n",		    count, (int) pos, (int) offset, (int) pgpos, (int) bytes);	if (pgpos < orig_pgpos)	    /* nothing to do, not even copy_from_user */	    goto encode_page;	if (pgpos == orig_pgpos) {	    /*	     * this is the only interesting case,	     * we have to shift from orig_pos to pos somehow	     */	    pos = orig_pos;	    offset = pos & ~PAGE_MASK;	    if ((bytes = PAGE_SIZE - offset) > count)		bytes = count;	}#if 0	status = inode->i_op->updatepage(file, page, buf,					 offset, bytes, sync);#else	fist_dprint(7, "WRITE: copying %ld bytes at offset %ld\n", bytes, offset);	copy_from_user((char *) (page_address(page) + offset), buf, bytes);    encode_page:	wrapfs_encode_block((char *) page_address(page), hidden_buffer, PAGE_SIZE, inode, inode->i_sb);	hidden_file->f_pos = pgpos; /* is this needed? */	if (inode->i_size < pgpos + PAGE_SIZE)	    if (inode->i_size > pos + bytes)		bytes_to_write = inode->i_size - pgpos;	    else		bytes_to_write = offset + bytes;	else	    bytes_to_write = PAGE_SIZE;	fist_dprint(7, "WRITE: writing at pgpos %ld, size %ld\n", pgpos, bytes_to_write);	/* switch to kernel space */	set_fs(KERNEL_DS);	tmp_pos = pgpos;	status = hidden_file->f_op->write(hidden_file,					  hidden_buffer,					  bytes_to_write,					  &tmp_pos);	fist_dprint(7, "WROTE: tmp_pos %ld, status %d\n", (int) tmp_pos, (int) status);	/* switch back to user space */	set_fs(old_fs);#endif	/* the rest of the code must not see that we are writing extra bytes */	/* do not adjust status if only filling up holes */	if (status > 0 && pgpos >= orig_pgpos) {	    if (status < offset) {		status = 0;	    } else {		status -= offset;		if (status > bytes)		    status = bytes;	    }	}    done_with_page:	__free_page(page);	if (status < 0)	    break;	/* do not adjust these variables if only filling up holes */	if (pgpos >= orig_pgpos) {	    written += status;	    count -= status;	    buf += status;	}	pos += status;    }    // MAJOR HACK    /*     * because pread() does not have any way to tell us that it is     * our caller, then we don't know for sure if we have to update     * the file positions.  This hack relies on read() having passed us     * the "real" pointer of its struct file's f_pos field.     */    if (ppos == &file->f_pos)	hidden_file->f_pos = *ppos = pos;    //    file->f_pos = pos;    if (pos > inode->i_size) {	inode->i_size = pos;	/* update the number of disk blocks allocated */	inode->i_blocks = hidden_inode->i_blocks;    }    /* for write operations, mtime and ctime must be updated */    fist_copy_attr_times(inode, hidden_inode);    up(&hidden_inode->i_sem);    kfree_s(hidden_buffer, PAGE_SIZE);    if (page_cache)	free_page(page_cache);    status = written ? written : status;out:    print_exit_status(status);    //    fist_print_file("WRITE file", file);    //    fist_print_file("WRITE hidden_file", hidden_file);    //    fist_set_debug_value(0);    return status;}#ifdef FIST_FILTER_NAMEstruct wrapfs_getdents_callback {    void *dirent;    dentry_t *dentry;    filldir_t filldir;};/* copied from generic filldir in fs/readir.c */STATIC intwrapfs_filldir(void *dirent, const char *name, int namlen, off_t offset, ino_t ino){    struct wrapfs_getdents_callback *buf = (struct wrapfs_getdents_callback *) dirent;    int err;    char *decoded_name;    int decoded_length;    decoded_length = wrapfs_decode_filename(name, namlen, &decoded_name, SKIP_DOTS,					    buf->dentry->d_inode, buf->dentry->d_sb);    if (decoded_length < 0)	return 0;			/* no error, just skip the entry */    FIST_OP_READDIR_CALL;    err = buf->filldir(buf->dirent, decoded_name, decoded_length, offset, ino);    kfree_s(decoded_name, decoded_length);    return err;}#endif /* FIST_FILTER_NAME */STATIC intwrapfs_readdir(file_t *file, void *dirent, filldir_t filldir){    int err = -ENOTDIR;    file_t *hidden_file = ftohf(file);    inode_t *inode = file->f_dentry->d_inode;    inode_t *hidden_inode = itohi(inode);#ifdef FIST_FILTER_NAME    struct wrapfs_getdents_callback buf;#endif /* FIST_FILTER_NAME */    print_entry_location();    fist_checkinode(inode, "wrapfs_readdir");    if (!hidden_file || !hidden_file->f_op || !hidden_file->f_op->readdir)	goto out;    down(&hidden_inode->i_sem);#ifdef FIST_FILTER_NAME    /* prepare for callback */    buf.dirent = dirent;    buf.dentry = file->f_dentry;    buf.filldir = filldir;    err = hidden_file->f_op->readdir(hidden_file, (void *) &buf, wrapfs_filldir);#else /* not FIST_FILTER_NAME */    err = hidden_file->f_op->readdir(hidden_file, dirent, filldir);#endif /* not FIST_FILTER_NAME */    up(&hidden_inode->i_sem);    file->f_pos = hidden_file->f_pos;    if (err > 0)	fist_copy_attr_atime(inode, hidden_inode);out:    fist_checkinode(inode, "post wrapfs_readdir");    print_exit_status(err);    return err;}

⌨️ 快捷键说明

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