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

📄 inode.c

📁 Solaris操作系统下的过滤驱动程序, C源码程序.
💻 C
📖 第 1 页 / 共 2 页
字号:
    if (!check_parent(hidden_dir_dentry, hidden_dentry))	goto out;    err = vfs_mknod(hidden_dir_dentry->d_inode,		    hidden_dentry,		    mode,		    dev);    if (err)	goto out;    err = wrapfs_interpose(hidden_dentry, dentry, dir->i_sb, 0);    if (err)	goto out;    fist_copy_attr_timesizes(dir, hidden_dir_dentry->d_inode); out:    unlock_dir(hidden_dir_dentry);    fist_checkinode(dir, "post wrapfs_mknod-dir");    print_exit_status(err);    return err;}STATIC intwrapfs_rename(inode_t *old_dir, dentry_t *old_dentry,	      inode_t *new_dir, dentry_t *new_dentry){    int err;    dentry_t *hidden_old_dentry = wrapfs_hidden_dentry(old_dentry);    dentry_t *hidden_new_dentry = wrapfs_hidden_dentry(new_dentry);    dentry_t *hidden_old_dir_dentry;    dentry_t *hidden_new_dir_dentry;    print_entry_location();    fist_checkinode(old_dir, "wrapfs_rename-old_dir");    fist_checkinode(new_dir, "wrapfs_rename-new_dir");    dget(hidden_old_dentry);    dget(hidden_new_dentry);    hidden_old_dir_dentry = get_parent(hidden_old_dentry);    hidden_new_dir_dentry = get_parent(hidden_new_dentry);    double_lock(hidden_old_dir_dentry, hidden_new_dir_dentry);    err = -ENOENT;#ifdef FIST_FILTER_SCA    /* Also rename the index file */    if (old_dentry->d_inode && S_ISREG(old_dentry->d_inode->i_mode)) {	/* These must be in the same directory as the main file */	dentry_t *idx_old_dentry = dtopd(old_dentry)->idx_dentry;	dentry_t *idx_new_dentry = dtopd(new_dentry)->idx_dentry;	if (check_parent(hidden_old_dir_dentry, idx_old_dentry) &&	    check_parent(hidden_new_dir_dentry, idx_new_dentry))	    err = vfs_rename(hidden_old_dir_dentry->d_inode, idx_old_dentry,			     hidden_new_dir_dentry->d_inode, idx_new_dentry);	if (err)	    goto out_lock;    }#endif    if (check_parent(hidden_old_dir_dentry, hidden_old_dentry) &&	check_parent(hidden_new_dir_dentry, hidden_new_dentry))	err = vfs_rename(hidden_old_dir_dentry->d_inode, hidden_old_dentry,			 hidden_new_dir_dentry->d_inode, hidden_new_dentry);    if (err)	goto out_lock;    fist_copy_attr_all(new_dir, hidden_new_dir_dentry->d_inode);    if (new_dir != old_dir)	fist_copy_attr_all(old_dir, hidden_old_dir_dentry->d_inode); out_lock:    // double_unlock will dput the new/old parent dentries whose refcnts    // were incremented via get_parent above.    double_unlock(hidden_old_dir_dentry, hidden_new_dir_dentry);    dput(hidden_new_dentry);    dput(hidden_old_dentry);    fist_checkinode(new_dir, "post wrapfs_rename-new_dir");    print_exit_status(err);    return err;}STATIC intwrapfs_readlink(dentry_t *dentry, char *buf, int bufsiz){    int err;    dentry_t *hidden_dentry = wrapfs_hidden_dentry(dentry);#ifdef FIST_FILTER_NAME    char *decoded_name, *hidden_buf;    mm_segment_t old_fs;#endif /* FIST_FILTER_NAME */    print_entry_location();    fist_print_dentry("wrapfs_readlink IN", dentry);    if (!hidden_dentry->d_inode->i_op ||	!hidden_dentry->d_inode->i_op->readlink) {	err = -EINVAL;	goto out;    }#ifndef FIST_FILTER_NAME    err = hidden_dentry->d_inode->i_op->readlink(hidden_dentry,						 buf,						 bufsiz);    if (err > 0)	fist_copy_attr_atime(dentry->d_inode, hidden_dentry->d_inode);#else /* FIST_FILTER_NAME */    hidden_buf = kmalloc(bufsiz, GFP_KERNEL);    if (hidden_buf == NULL) {	printk("Out of memory.\n");	err = -ENOMEM;	goto out;    }    old_fs = get_fs();    set_fs(KERNEL_DS);    err = hidden_dentry->d_inode->i_op->readlink(hidden_dentry,						 hidden_buf,						 bufsiz);    set_fs(old_fs);    if (err >= 0) {	// don't do this, it's not zero-terminated!!!	//	fist_dprint(7, "READLINK: link \"%s\", length %d\n", hidden_buf, err);	err = wrapfs_decode_filename(hidden_buf, err,				     &decoded_name, DO_DOTS, dentry->d_inode, dentry->d_sb);	if (err > 0) {	    if (copy_to_user(buf, decoded_name, err))		err = -EFAULT;	    kfree_s(decoded_name, err);	}	fist_copy_attr_atime(dentry->d_inode, hidden_dentry->d_inode);    }    kfree_s(hidden_buf, bufsiz);#endif /* FIST_FILTER_NAME */ out:    print_exit_status(err);    return err;}STATIC intwrapfs_follow_link(dentry_t *dentry, struct nameidata *nd){    char *buf;    int len = PAGE_SIZE, err;    mm_segment_t old_fs;    print_entry_location();    //    fist_print_dentry("wrapfs_follow_link dentry IN", dentry);    buf = kmalloc(len, GFP_KERNEL);    if (!buf) {	err = -ENOMEM;	goto out;    }    /* read the symlink, and then we will follow it */    old_fs = get_fs();    set_fs(KERNEL_DS);    err = dentry->d_inode->i_op->readlink(dentry, buf, len);    set_fs(old_fs);    if (err < 0)	goto out_free;    buf[err] = 0;	// terminate the buffer -- XXX still needed?    // XXX: FIXME w/ wrapfs_encode_filename()    /*     * vfs_follow_link will increase the nd's mnt refcnt     * we assume that some other VFS code decrements it.     */    err = vfs_follow_link(nd, buf); out_free:    kfree_s(buf, len); out:#if 0    if (err < 0) {	dput(nd->dentry);	printk("EZK follow_link() mnt_cnt %d\n", atomic_read(&nd->mnt->mnt_count));	mntput(nd->mnt);    }#endif    print_exit_status(err);    return err;}#ifdef FIST_FILTER_SCASTATIC intwrapfs_truncate_and_enlarge(dentry_t *dentry){    dentry_t *hidden_dentry = dtohd(dentry);    inode_t *hidden_inode = hidden_dentry->d_inode;    inode_t *inode = dentry->d_inode;    int err = 0;    page_t *page = NULL;    int index, new_index;    unsigned offset, new_offset, real_size;    struct encoded_page *ep = NULL, *next_ep, **cur_ep;    struct scafs_header *hdr = &itopd(inode)->hdr;    void *opaque;    file_t *hidden_file;    struct iattr attr;    off_t abs_offset;    int need_to_call = 1;    file_t fake_file; /* needed b/c notify change doesn't get a struct file */    print_entry_location();    if (dentry->d_inode->i_size == hdr->real_size)	goto out;    down(&hidden_inode->i_sem);    // calculate page index and page offset (offset)    new_index = inode->i_size >> PAGE_CACHE_SHIFT;    new_offset = inode->i_size & ~PAGE_CACHE_MASK;    if (inode->i_size > hdr->real_size) {	/* enlarge */	index = hdr->real_size >> PAGE_CACHE_SHIFT;	offset = hdr->real_size & ~PAGE_CACHE_MASK;	/* abs_offset is the absolute offset within the hidden_file	 * where the encoded representation of the current page begins.	 * Whee... */	abs_offset = HIDDEN_PAGE_STARTING_OFFSET(index, inode);    } else {	/* shrink */	index = new_index;	offset = new_offset;	abs_offset = HIDDEN_PAGE_STARTING_OFFSET(new_index, inode);    }    real_size = 0;    if (offset == 0 || IS_HOLE(index, inode))	goto page_boundary;    if (index == new_index)	offset = new_offset;    else	offset = PAGE_CACHE_SIZE;    /*     * get our page at offset inode->i_size     * this is either the page within which we're truncating,     *		if we are shrinking,     * or the former last page, if we are enlarging     */    /*     * XXX: set up fake file.  A hack b/c address_ops need a struct file     * but notify_change only gets a dentry.     */    memset(&fake_file, 0, sizeof(file_t));    // XXX: may need to initialize other fields!    fake_file.f_dentry = dentry;    page = wrapfs_get1page(&fake_file, index);    if (IS_ERR(page)) {	err = PTR_ERR(page);	goto out_unlock;    }    /* re-encode our page from 0 to "offset" within page */    kmap(page);    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(offset, inode)) {	    memcpy((*cur_ep)->data, (char *) page_address(page), offset);	    need_to_call = 0;	    err = offset;	    hdr->flags |= SCA_FLAG_FASTTAIL;	} else#endif /* FIST_FAST_TAILS */	{	    err = wrapfs_encode_buffers((*cur_ep)->data,					(char *) page_address(page),					&need_to_call,					offset,					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;	real_size += err;    }    wrapfs_idx_set_entry(hdr, index, abs_offset + real_size);    // write new bytes    dget(hidden_dentry);    /*     * dentry_open will decrement mnt refcnt if err.     * otherwise fput() will do an mntput() for us upon file close.     */    mntget(stopd(inode->i_sb)->hidden_mnt);    hidden_file = dentry_open(hidden_dentry, stopd(inode->i_sb)->hidden_mnt, FMODE_WRITE, O_WRONLY);    if (IS_ERR(hidden_file)) {	err = PTR_ERR(hidden_file);	goto out_free;    }    err = wrapfs_copy_encoded_data(hidden_file,				   abs_offset,				   ep,				   real_size);    fput(hidden_file);    if (err < 0)	goto out_free; page_boundary:    index = new_index;    offset = new_offset;    abs_offset = HIDDEN_PAGE_STARTING_OFFSET(new_index, inode);    if (index >= hdr->num_chunks)	real_size = 0;		/* hole, even though imcomplete */    // call notify change on lower data file w/ new size    attr.ia_size = abs_offset + real_size;    attr.ia_valid = ATTR_SIZE;    err = notify_change(hidden_dentry, &attr);    if (err < 0)	goto out_free;    // update IT for the new encoded bytes    hdr->real_size = inode->i_size;    if (offset == 0) {	if (index > 0)	    err = wrapfs_idx_set_entry(hdr, index - 1, attr.ia_size);	hdr->num_chunks = index;    } else {	err = wrapfs_idx_set_entry(hdr, index, attr.ia_size);	hdr->num_chunks = index + 1;    }    if (err < 0)	goto out_free;    mark_inode_dirty(inode);	/* so it'll write the index table */    /* all is ok */ 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;    }    kunmap(page);    if (page)	page_cache_release(page); out_unlock:    up(&hidden_inode->i_sem); out:    print_exit_location();    return err;}#endif /* not FIST_FILTER_SCA */STATIC intwrapfs_permission(inode_t *inode, int mask){    inode_t *hidden_inode = itohi(inode);    int mode = inode->i_mode;    int err;    print_entry_location();    if ((mask & S_IWOTH) && IS_RDONLY(inode) &&	(S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) {	err = -EROFS; /* Nobody gets write access to a read-only fs */	goto out;    }    err = permission(hidden_inode, mask); out:    print_exit_status(err);    return err;}STATIC intwrapfs_inode_revalidate(dentry_t *dentry){    int err = 0;    dentry_t *hidden_dentry = wrapfs_hidden_dentry(dentry);    inode_t *hidden_inode = hidden_dentry->d_inode;    print_entry_location();    //    fist_print_dentry("inode_revalidate IN", dentry);    if (hidden_inode->i_op && hidden_inode->i_op->revalidate) {	err = hidden_inode->i_op->revalidate(hidden_dentry);	if (!err)	    fist_copy_attr_all(dentry->d_inode, hidden_inode);    }    //    fist_print_dentry("inode_revalidate OUT", dentry);    print_exit_status(err);    return err;}STATIC intwrapfs_setattr(dentry_t *dentry, struct iattr *ia){    int err = 0;    dentry_t *hidden_dentry = wrapfs_hidden_dentry(dentry);    inode_t *inode = dentry->d_inode;    inode_t *hidden_inode = itohi(inode);    print_entry_location();    fist_checkinode(inode, "wrapfs_setattr");#ifdef FIST_FILTER_SCA    if (ia->ia_valid & ATTR_SIZE) {	dentry->d_inode->i_size = ia->ia_size;	err = wrapfs_truncate_and_enlarge(dentry);	if (err < 0)	    goto out;	ia->ia_valid &= ~ATTR_SIZE; /* b/c we handled it */    }#endif /* FIST_FILTER_SCA */    err = notify_change(hidden_dentry, ia);#ifdef FIST_FILTER_SCA out:#endif /* FIST_FILTER_SCA */    /*     * The lower file system might has changed the attributes, even if     * notify_change above resulted in an error(!)  so we copy the     * hidden_inode's attributes (and a few more) to our inode.     */    fist_copy_attr_all(inode, hidden_inode);    fist_checkinode(inode, "post wrapfs_setattr");    print_exit_status(err);    return err;}#if NOT_USED_YETSTATIC intwrapfs_getattr(dentry_t *dentry, struct iattr *ia){    return -ENOSYS;}#endif /* NOT_USED_YET */struct inode_operations wrapfs_iops_symlink ={    create:	wrapfs_create,    lookup:	wrapfs_lookup,    link:	wrapfs_link,    unlink:	wrapfs_unlink,    symlink:	wrapfs_symlink,    mkdir:	wrapfs_mkdir,    rmdir:	wrapfs_rmdir,    mknod:	wrapfs_mknod,    rename:	wrapfs_rename,    readlink:	wrapfs_readlink,    follow_link: wrapfs_follow_link,    // off because we have setattr    //    truncate:	wrapfs_truncate,    permission:	wrapfs_permission,    revalidate:	wrapfs_inode_revalidate,    setattr:	wrapfs_setattr,#if 0    // XXX: off, b/c the VFS doesn't call getattr yet    getattr:	wrapfs_getattr,#endif};struct inode_operations wrapfs_iops ={    create:	wrapfs_create,    lookup:	wrapfs_lookup,    link:	wrapfs_link,    unlink:	wrapfs_unlink,    symlink:	wrapfs_symlink,    mkdir:	wrapfs_mkdir,    rmdir:	wrapfs_rmdir,    mknod:	wrapfs_mknod,    rename:	wrapfs_rename,    //readlink:	wrapfs_readlink,    //follow_link: wrapfs_follow_link,    // off because we have setattr    //    truncate:	wrapfs_truncate,    permission:	wrapfs_permission,    revalidate:	wrapfs_inode_revalidate,    setattr:	wrapfs_setattr,#if 0    // XXX: off, b/c the VFS doesn't call getattr yet    getattr:	wrapfs_getattr,#endif};/* * Local variables: * c-basic-offset: 4 * End: */

⌨️ 快捷键说明

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