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

📄 inode.c

📁 Solaris操作系统下的过滤驱动程序, C源码程序.
💻 C
📖 第 1 页 / 共 3 页
字号:
    /*     * The dentry->d_count stuff confuses d_delete() enough to     * not kill the inode from under us while it is locked. This     * wouldn't be needed, except the dentry semaphore is really     * in the inode, not in the dentry..     */    fist_print_dentry("wrapfs_rmdir-hidden_dentry1", hidden_dentry);    hidden_dentry->d_count++;    double_lock(hidden_dir_dentry, hidden_dentry);    if (!check_parent(hidden_dir_dentry, hidden_dentry))	goto out_lock;    /* avoid destroying the hidden inode if the file is in use */    dget(hidden_dentry);    err = vfs_rmdir(hidden_dir_dentry->d_inode, hidden_dentry);    dput(hidden_dentry);    if (!err)	d_delete(hidden_dentry); out_lock:    fist_copy_attr_times(dir, hidden_dir_dentry->d_inode);    /* copy the nlink count for our dentry and our parent's dentry */    dir->i_nlink =  hidden_dir_dentry->d_inode->i_nlink;    double_unlock(hidden_dentry, hidden_dir_dentry);    fist_print_dentry("wrapfs_rmdir-dentry", dentry);    fist_print_inode("wrapfs_rmdir-inode", dentry->d_inode);    /*     * call d_drop so the system "forgets" about us     */    if (!err)	d_drop(dentry);    dput(dentry);    print_exit_status(err);    return err;}STATIC intwrapfs_mknod(inode_t *dir, dentry_t *dentry, int mode, int dev){    int err;    dentry_t *hidden_dentry = wrapfs_hidden_dentry(dentry);    dentry_t *hidden_dir_dentry;    print_entry_location();    fist_checkinode(dir, "wrapfs_mknod-dir");    hidden_dir_dentry = lock_parent(hidden_dentry);    err = -ENOENT;    if (!check_parent(hidden_dir_dentry, hidden_dentry))	goto out_lock;    if (!hidden_dir_dentry->d_inode->i_op || !hidden_dir_dentry->d_inode->i_op->mknod) {	err = -EPERM;	goto out_lock;    }    DQUOT_INIT(hidden_dir_dentry->d_inode);    err = hidden_dir_dentry->d_inode->i_op->mknod(hidden_dir_dentry->d_inode,						  hidden_dentry,						  mode,						  dev);    if (err || !hidden_dentry->d_inode)	goto out_lock;    err = wrapfs_interpose(hidden_dentry, dentry, dir->i_sb, 0);    if (err)	goto out_lock;    fist_copy_attr_timesizes(dir, hidden_dir_dentry->d_inode); out_lock:    unlock_dir(hidden_dir_dentry);    if (!dentry->d_inode)	d_drop(dentry); out:    fist_checkinode(dir, "post wrapfs_mknod-dir");    print_exit_status(err);    return err;}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6)/* this is for kernels before 2.2.6 */STATIC intwrapfs_rename(inode_t *old_dir, dentry_t *old_dentry,	      inode_t *new_dir, dentry_t *new_dentry){    int err = -EPERM;    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;    int (*rename_fxn) (inode_t *, dentry_t *, inode_t *, dentry_t *);    print_entry_location();    hidden_old_dir_dentry = get_parent(hidden_old_dentry);    hidden_new_dir_dentry = get_parent(hidden_new_dentry);    dget(hidden_old_dentry);    dget(hidden_new_dentry);    double_lock(hidden_old_dir_dentry, hidden_new_dir_dentry);    fist_checkinode(old_dir, "wrapfs_rename-old_dir");    fist_checkinode(new_dir, "wrapfs_rename-new_dir");    if (!hidden_old_dir_dentry->d_inode->i_op ||	!(rename_fxn = hidden_old_dir_dentry->d_inode->i_op->rename)) {	err = -EPERM;	goto out_lock;    }    err = rename_fxn(hidden_old_dir_dentry->d_inode, hidden_old_dentry,		     hidden_new_dir_dentry->d_inode, hidden_new_dentry);    if (err)	goto out_lock;    //    ASSERT(new_dentry->d_inode == NULL);    //    new_dentry->d_inode = old_dentry->d_inode;    //    err = wrapfs_interpose(hidden_new_dentry, new_dentry, new_dir->i_sb, 0);    d_move(old_dentry, new_dentry);    fist_copy_attr_all(new_dir, hidden_new_dir_dentry->d_inode);    if (new_dir != old_dir)	fist_copy_attr_times(old_dir, hidden_old_dir_dentry->d_inode); out_lock:    double_unlock(hidden_old_dir_dentry, hidden_new_dir_dentry); out:    dput(hidden_new_dentry);    dput(hidden_old_dentry);    fist_checkinode(new_dir, "post wrapfs_mknod-new_dir");    print_exit_status(err);    return err;}#else /* not LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6) *//* this is for 2.2.6 kernels and later (big rename changes) */STATIC intwrapfs_rename(inode_t *old_dir, dentry_t *old_dentry,	      inode_t *new_dir, dentry_t *new_dentry){    int err = -EPERM;    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;    int (*rename_fxn) (inode_t *, dentry_t *, inode_t *, dentry_t *);    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;    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(hidden_old_dir_dentry, hidden_new_dir_dentry);    dput(hidden_new_dentry);    dput(hidden_old_dentry);    fist_checkinode(new_dir, "post wrapfs_mknod-new_dir");    print_exit_status(err);    return err;}#endif /* not LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6) */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) {	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;}/* inode is from wrapfs, dir could be anything */STATIC dentry_t *wrapfs_follow_link(dentry_t *dentry, dentry_t *base, unsigned int follow){    char *buf;    int len = PAGE_SIZE, err;    dentry_t *ret_dentry = dentry;    dentry_t *hidden_dentry = wrapfs_hidden_dentry(dentry);    mm_segment_t old_fs;    print_entry_location();    //    fist_print_dentry("wrapfs_follow_link dentry IN", dentry);    //    fist_print_dentry("wrapfs_follow_link base IN", base);    if (!hidden_dentry->d_inode->i_op ||	!hidden_dentry->d_inode->i_op->readlink ||	!hidden_dentry->d_inode->i_op->follow_link) {	/*	 * do_follow_link will do a dput() on the dentry passed to us	 * and if that is the same as ret_dentry, and we want it kept,	 * then we must increment the dentry's refcount to avoid having	 * it deallocate/destroyed.	 */	dget(ret_dentry);	/*	 * Looking at do_follow_link, if we implement follow_link, then	 * we have to dput(base).  Normally that's done by lookup_dentry	 * but here we don't run that code.	 */	dput(base);	goto out;    }    buf = kmalloc(len, GFP_KERNEL);    if (!buf) {	ret_dentry = ERR_PTR(-ENOMEM);	dput(base); // for the same reason as above	goto out;    }    /* read the hidden 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) {	ret_dentry = ERR_PTR(err);	dput(base); // for the same reason as above	goto out_free;    }    fist_copy_attr_atime(dentry->d_inode, hidden_dentry->d_inode);    buf[err] = 0;	// terminate the buffer for lookup_dentry's sake    /*     * We do not dget(base) b/c the way we were called here,     * the base (passed to us) was already dget'ed.     */    ret_dentry = lookup_dentry(buf, base, follow);    //    fist_print_dentry("wrapfs_follow_link base OUT", base); out_free:    kfree_s(buf, len); out:    print_exit_location();    return ret_dentry;}#if 0STATIC voidfist_page_mkclean(page_t *page){    unsigned long address;    pmd_t *pmd;    pgd_t *pgd;    pte_t *ppte;    ASSERT(page != NULL);    ASSERT(page->inode != NULL);    ASSERT(page->inode->i_mmap != NULL);    ASSERT(page->inode->i_mmap->vm_mm != NULL);    ASSERT(page->inode->i_mmap->vm_mm->pgd != NULL);    address = page->offset;    pgd = page->inode->i_mmap->vm_mm->pgd;    pmd = pmd_offset(pgd, address);    ppte = pte_offset(pmd, address);    set_pte(ppte, pte_mkclean(*ppte));    ASSERT(!pte_dirty(*ppte));}STATIC voidfist_page_assertclean(page_t *page){    unsigned long address;    pmd_t *pmd;    pgd_t *pgd;    pte_t *ppte;    ASSERT(page != NULL);    ASSERT(page->inode != NULL);    ASSERT(page->inode->i_mmap != NULL);    ASSERT(page->inode->i_mmap->vm_mm != NULL);    ASSERT(page->inode->i_mmap->vm_mm->pgd != NULL);    address = page->offset;    pgd = page->inode->i_mmap->vm_mm->pgd;    pmd = pmd_offset(pgd, address);    ppte = pte_offset(pmd, address);    //    set_pte(ppte, pte_mkclean(*ppte));    ASSERT(!pte_dirty(*ppte));}#endif#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)static inlinestruct page *__read_cache_page(struct inode *inode,			       unsigned long offset,			       int (*filler)(void *,struct page*),			       void *data){	struct page **hash = page_hash(inode, offset);	struct page *page;	unsigned long cached_page = 0;	int err;	offset &= PAGE_CACHE_MASK;repeat:	page = __find_page(inode, offset, *hash);	if (!page) {		if (!cached_page) {			cached_page = page_cache_alloc();			if (!cached_page)				return ERR_PTR(-ENOMEM);			goto repeat;		}		page = page_cache_entry(cached_page);		cached_page = 0;		add_to_page_cache(page, inode, offset, hash);		set_bit(PG_locked, &page->flags);		err = filler(data, page);		if (err < 0) {			page_cache_release(page);			page = ERR_PTR(err);		}	}	if (cached_page)		page_cache_free(cached_page);	return page;}/* * Read into the page cache. If a page already exists, * and Page_Uptodate() is not set, try to fill the page. */struct page *read_cache_page(struct inode *inode,				unsigned long offset,				int (*filler)(void *,struct page*),

⌨️ 快捷键说明

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