inode.c

来自「Solaris操作系统下的过滤驱动程序, C源码程序.」· C语言 代码 · 共 1,095 行 · 第 1/2 页

C
1,095
字号
    dentry_t *hidden_new_dir_dentry;    print_entry_location();    hidden_old_dentry = wrapfs_hidden_dentry(old_dentry);/* CPW: Moved below print_entry_location */    hidden_new_dentry = wrapfs_hidden_dentry(new_dentry);    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);#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;	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    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;#ifdef FIST_FILTER_NAME    char *decoded_name, *hidden_buf;    mm_segment_t old_fs;#endif /* FIST_FILTER_NAME */    print_entry_location();    hidden_dentry = wrapfs_hidden_dentry(dentry);/* CPW: Moved below 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(decoded_name);	}	fist_copy_attr_atime(dentry->d_inode, hidden_dentry->d_inode);    }    kfree(hidden_buf);#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(buf); 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;    inode_t *hidden_inode;    inode_t *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;    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();    hidden_dentry = dtohd(dentry);/* CPW: Moved below print_entry_location */    hidden_inode = hidden_dentry->d_inode;    inode = dentry->d_inode;    hdr = &itopd(inode)->hdr;    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, 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(ep);	ep = next_ep;    }    kunmap(page);    if (page)	page_cache_release(page); out_unlock:    up(&hidden_inode->i_sem); out:    print_exit_location();    return err;}#else /* not FIST_FILTER_SCA */# ifdef FIST_FILTER_DATA/* * Function to handle truncations extending the size of the file for non-SCA * file systems. */STATIC intwrapfs_truncate(dentry_t *dentry, loff_t new_length){    inode_t *inode = dentry->d_inode;    file_t fake_file;    page_t *tmp_page;    int index;    unsigned to;    int err = 0;    /*     * if this is a truncate past the end of the file, call wrapfs_fill_zeros     */    if (new_length > inode->i_size) {	memset(&fake_file, 0, sizeof(fake_file));	fake_file.f_dentry = dentry;	index = new_length >> PAGE_CACHE_SHIFT;	tmp_page = wrapfs_get1page(&fake_file, index);	if (IS_ERR(tmp_page)) {	    err = PTR_ERR(tmp_page);	    goto out;	}	to = new_length & ~PAGE_CACHE_MASK;	/*	 * 'to' is passed to wrapfs_fill_zeros instead of a 'from'	 *  because unlike the normal case where we fill in zeros	 *  till 'from', we need to fill it in with zeros till the	 *  end of the file	 */	err = wrapfs_fill_zeros(&fake_file, tmp_page, to);    } out:    return err;}# endif /* FIST_FILTER_DATA */#endif /* not FIST_FILTER_SCA */STATIC intwrapfs_permission(inode_t *inode, int mask){    inode_t *hidden_inode;    int mode;    int err;    print_entry_location();    hidden_inode = itohi(inode);/* CPW: Moved below print_entry_location */    mode = inode->i_mode;    err = vfs_permission(inode, mask);    if (err)	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;    inode_t *hidden_inode;    print_entry_location();    hidden_dentry = wrapfs_hidden_dentry(dentry);/* CPW: Moved below print_entry_location */    hidden_inode = hidden_dentry->d_inode;    //    fist_print_dentry("wrapfs_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("wrapfs_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;    inode_t *inode;    inode_t *hidden_inode;    print_entry_location();    hidden_dentry = wrapfs_hidden_dentry(dentry);    inode = dentry->d_inode;    hidden_inode = itohi(inode);    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 */    }#else /* not FIST_FILTER_SCA */# ifdef FIST_FILTER_DATA    if (ia->ia_valid & ATTR_SIZE) {	err = wrapfs_truncate(dentry, ia->ia_size);	if (err < 0)	    goto out;    }# endif /* FIST_FILTER_DATA */#endif /* not FIST_FILTER_SCA */    err = notify_change(hidden_dentry, ia);#if defined(FIST_FILTER_DATA) || defined(FIST_FILTER_SCA) out:#endif /* FIST_FILTER_DATA || 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_symlink_iops ={    readlink:	wrapfs_readlink,    follow_link: wrapfs_follow_link,    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_dir_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,    /* no readlink/follow_link for non-symlinks */    // 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_main_iops ={    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 + =
减小字号Ctrl + -
显示快捷键?