예제 #1
0
void unionfs_reinterpose(struct dentry *dentry)
{
	struct dentry *hidden_dentry;
	struct inode *inode;
	int bindex, bstart, bend;

	print_entry_location();
	verify_locked(dentry);
	fist_print_dentry("IN: unionfs_reinterpose: ", dentry);

	/* This is pre-allocated inode */
	inode = dentry->d_inode;

	bstart = dbstart(dentry);
	bend = dbend(dentry);
	for (bindex = bstart; bindex <= bend; bindex++) {
		hidden_dentry = dtohd_index(dentry, bindex);
		if (!hidden_dentry)
			continue;

		if (!hidden_dentry->d_inode)
			continue;
		if (itohi_index(inode, bindex))
			continue;
		set_itohi_index(inode, bindex, IGRAB(hidden_dentry->d_inode));
	}
	ibstart(inode) = dbstart(dentry);
	ibend(inode) = dbend(dentry);

	fist_print_dentry("OUT: unionfs_reinterpose: ", dentry);
	fist_print_inode("OUT: unionfs_reinterpose: ", inode);

	print_exit_location();
}
예제 #2
0
파일: dentry.c 프로젝트: dmeister/kbdb
/*
 * we don't really need kdb3fs_d_iput, because dentry_iput will call iput() if
 * kdb3fs_d_iput is not defined. We left this implemented for ease of
 * tracing/debugging.
 */
void
kdb3fs_d_iput(dentry_t *dentry, inode_t *inode)
{
	print_entry_location();
	iput(inode);
	print_exit_location();
}
예제 #3
0
STATIC void
base0fs_vm_shared_unmap(vm_area_t *vma, unsigned long start, size_t len)
{
        vm_area_t *lower_vma;
        file_t *file;
        file_t *lower_file = NULL;

        print_entry_location();
        lower_vma = VMA_TO_LOWER(vma);
        file = vma->vm_file;
        if (FILE_TO_PRIVATE(file) != NULL)
                lower_file = FILE_TO_LOWER(file);
        BUG_ON(!lower_file);

        fist_dprint(6, "VM_S_UNMAP1: file 0x%x, lower_file 0x%x, file->f_count %d, lower_file->f_count %d\n",
                    (int) file, (int) lower_file,
                    (int) atomic_read(&file->f_count),
                    (int) atomic_read(&lower_file->f_count));

        /*
         * call sync (filemap_sync) because the default filemap_unmap
         * calls it too.
         */
        filemap_sync(vma, start, len, MS_ASYNC);

        if (lower_vma->vm_ops->unmap)
                lower_vma->vm_ops->unmap(lower_vma, start, len);

        fist_dprint(6, "VM_S_UNMAP2: file 0x%x, lower_file 0x%x, file->f_count %d, lower_file->f_count %d\n",
                    (int) file, (int) lower_file,
                    (int) atomic_read(&file->f_count),
                    (int) atomic_read(&lower_file->f_count));
        print_exit_location();
}
예제 #4
0
/* final actions when unmounting a file system */
static void unionfs_put_super(struct super_block *sb)
{
	int bindex, bstart, bend;
	struct unionfs_sb_info *spd;

	print_entry_location();

	if ((spd = stopd(sb))) {
		/* XXX: Free persistent inode stuff. */

		bstart = sbstart(sb);
		bend = sbend(sb);
		for (bindex = bstart; bindex <= bend; bindex++)
			mntput(stohiddenmnt_index(sb, bindex));

		/* Make sure we have no leaks of branchget/branchput. */
		for (bindex = bstart; bindex <= bend; bindex++)
			ASSERT(branch_count(sb, bindex) == 0);

		KFREE(stohs_ptr(sb));
		KFREE(stohiddenmnt_ptr(sb));
		KFREE(spd->usi_sbcount_p);
		KFREE(spd->usi_branchperms_p);
		KFREE(spd->usi_putmaps);
		KFREE(spd);
		stopd_lhs(sb) = NULL;
	}
	fist_dprint(6, "unionfs: released super\n");

	print_exit_location();
}
예제 #5
0
파일: dentry.c 프로젝트: dmeister/kbdb
void
kdb3fs_d_release(dentry_t *dentry)
{
	dentry_t *hidden_dentry;

	print_entry_location();
#if 0	
	fist_print_dentry("kdb3fs_d_release IN dentry", dentry);

	/* this could be a negative dentry, so check first */
	if (!dtopd(dentry)) {
		fist_dprint(6, "dentry without private data: %*s", dentry->d_name.len, dentry->d_name.name);
		goto out;
	}
	hidden_dentry = dtohd(dentry);
	fist_print_dentry("kdb3fs_d_release IN hidden_dentry", hidden_dentry);
	if (hidden_dentry->d_inode)
		fist_dprint(6, "kdb3fs_d_release: hidden_inode->i_count %d, i_num %lu.\n",
			    atomic_read(&hidden_dentry->d_inode->i_count),
			    hidden_dentry->d_inode->i_ino);

	/* free private data (kdb3fs_dentry_info) here */
	KFREE(dtopd(dentry));
	dtopd(dentry) = NULL;	/* just to be safe */
	/* decrement hidden dentry's counter and free its inode */
	dput(hidden_dentry);
#endif
out:
	print_exit_location();
}
예제 #6
0
STATIC void
base0fs_vm_close(vm_area_t *vma)
{
        vm_area_t *lower_vma;
        file_t *file;
        file_t *lower_file = NULL;

        print_entry_location();

        lower_vma = VMA_TO_LOWER(vma);
        file = vma->vm_file;
        if (FILE_TO_PRIVATE(file) != NULL)
                lower_file = FILE_TO_LOWER(file);
        BUG_ON(!lower_file);

        fist_dprint(6, "VM_CLOSE1: file 0x%x, lower_file 0x%x, file->f_count %d, lower_file->f_count %d\n",
                    (int) file, (int) lower_file,
                    (int) atomic_read(&file->f_count),
                    (int) atomic_read(&lower_file->f_count));

        BUG_ON(!lower_vma);

        if (lower_vma->vm_ops->close)
                lower_vma->vm_ops->close(lower_vma);
        fput(lower_file);
        KFREE(lower_vma);
        VMA_TO_LOWER(vma) = NULL;

        fist_dprint(6, "VM_CLOSE2: file 0x%x, lower_file 0x%x, file->f_count %d, lower_file->f_count %d\n",
                    (int) file, (int) lower_file,
                    (int) atomic_read(&file->f_count),
                    (int) atomic_read(&lower_file->f_count));
        print_exit_location();
}
예제 #7
0
void unionfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
#endif
{
	char *link;
	print_entry_location();
	link = nd_get_link(nd);
	KFREE(link);
	print_exit_location();
}
예제 #8
0
/*
 * we now define delete_inode, because there are two VFS paths that may
 * destroy an inode: one of them calls clear inode before doing everything
 * else that's needed, and the other is fine.  This way we truncate the inode
 * size (and its pages) and then clear our own inode, which will do an iput
 * on our and the lower inode.
 */
static void unionfs_delete_inode(struct inode *inode)
{
	print_entry_location();

	fist_checkinode(inode, "unionfs_delete_inode IN");
	inode->i_size = 0;	/* every f/s seems to do that */
	clear_inode(inode);

	print_exit_location();
}
예제 #9
0
	/* buf is allocated here, and freed when VFS calls our put_link method */
	err = -ENOMEM;
        buf = KMALLOC(len, GFP_KERNEL);
        if (!buf)
                goto out;

        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?
	err = 0;
	nd_set_link(nd,buf);
	goto out;

out_free:
	KFREE(buf);
out:
#if 0
        if (err < 0) {
                dput(nd->dentry);
                printk("EZK follow_link() mnt_cnt %d\n", 
                        (int) atomic_read(&nd->mnt->mnt_count));
                mntput(nd->mnt);
        }
#endif

        print_exit_status(err);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)
        return err;
#else /* 2.6.13 or newer */
        return ERR_PTR(err);
#endif /* 2.6.13 or newer */
}

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)
void
base0fs_put_link(struct dentry *dentry, struct nameidata *nd)
#else /* 2.6.13 or newer */
void
base0fs_put_link(struct dentry *dentry, struct nameidata *nd, void* unused)
#endif /* 2.6.13 or newer */
{
        print_entry_location();

        KFREE(nd_get_link(nd));

        print_exit_location();
}
예제 #10
0
/*
 * we now define delete_inode, because there are two VFS paths that may
 * destroy an inode: one of them calls clear inode before doing everything
 * else that's needed, and the other is fine.  This way we truncate the inode
 * size (and its pages) and then clear our own inode, which will do an iput
 * on our and the lower inode.
 */
STATIC void
mini_fo_delete_inode(inode_t *inode)
{
	print_entry_location();

	fist_checkinode(inode, "mini_fo_delete_inode IN");
	inode->i_size = 0;		/* every f/s seems to do that */
	clear_inode(inode);

	print_exit_location();
}
예제 #11
0
/* This function replicates the directory structure upto given dentry
 * in the bindex branch. Can create directory structure recursively to the right
 * also.
 */
struct dentry *create_parents(struct inode *dir, struct dentry *dentry,
			      int bindex)
{
	struct dentry *hidden_dentry;

	print_entry_location();
	hidden_dentry =
	    create_parents_named(dir, dentry, dentry->d_name.name, bindex);
	print_exit_location();

	return (hidden_dentry);
}
예제 #12
0
void unionfs_d_release(struct dentry *dentry)
{
	struct dentry *hidden_dentry;
	int bindex, bstart, bend;

	print_entry_location();
	/* There is no reason to lock the dentry, because we have the only
	 * reference, but the printing functions verify that we have a lock
	 * on the dentry before calling dbstart, etc. */
	lock_dentry(dentry);
	__fist_print_dentry("unionfs_d_release IN dentry", dentry, 0);

	/* this could be a negative dentry, so check first */
	if (!dtopd(dentry)) {
		fist_dprint(6, "dentry without private data: %*s",
			    dentry->d_name.len, dentry->d_name.name);
		goto out;
	} else if (dbstart(dentry) < 0) {
		/* this is due to a failed lookup */
		/* the failed lookup has a dtohd_ptr set to null,
		   but this is a better check */
		fist_dprint(6, "dentry without hidden dentries : %*s",
			    dentry->d_name.len, dentry->d_name.name);
		goto out_free;
	}

	/* Release all the hidden dentries */
	bstart = dbstart(dentry);
	bend = dbend(dentry);
	for (bindex = bstart; bindex <= bend; bindex++) {
		hidden_dentry = dtohd_index(dentry, bindex);
		DPUT(hidden_dentry);
		set_dtohd_index(dentry, bindex, NULL);
	}
	/* free private data (unionfs_dentry_info) here */
	KFREE(dtohd_ptr(dentry));
	dtohd_ptr(dentry) = NULL;
      out_free:
	/* No need to unlock it, because it is disappeared. */
#ifdef TRACKLOCK
	printk("DESTROYLOCK:%p\n", dentry);
#endif
	free_dentry_private_data(dtopd(dentry));
	dtopd_lhs(dentry) = NULL;	/* just to be safe */
      out:
	print_exit_location();
}
예제 #13
0
static void unionfs_read_inode(struct inode *inode)
{
	static struct address_space_operations unionfs_empty_aops;

	print_entry_location();

	if (!itopd(inode)) {
		FISTBUG
		    ("No kernel memory when allocating inode private data!\n");
	}

	PASSERT(inode->i_sb);
	memset(itopd(inode), 0, sizeof(struct unionfs_inode_info));
	itopd(inode)->b_start = -1;
	itopd(inode)->b_end = -1;
	atomic_set(&itopd(inode)->uii_generation,
		   atomic_read(&stopd(inode->i_sb)->usi_generation));
	itopd(inode)->uii_rdlock = SPIN_LOCK_UNLOCKED;
	itopd(inode)->uii_rdcount = 1;
	itopd(inode)->uii_hashsize = -1;
	INIT_LIST_HEAD(&itopd(inode)->uii_readdircache);

	if (sbmax(inode->i_sb) > UNIONFS_INLINE_OBJECTS) {
		int size =
		    (sbmax(inode->i_sb) -
		     UNIONFS_INLINE_OBJECTS) * sizeof(struct inode *);
		itohi_ptr(inode) = KMALLOC(size, GFP_UNIONFS);
		if (!itohi_ptr(inode)) {
			FISTBUG
			    ("No kernel memory when allocating lower-pointer array!\n");
		}
		memset(itohi_ptr(inode), 0, size);
	}
	memset(itohi_inline(inode), 0,
	       UNIONFS_INLINE_OBJECTS * sizeof(struct inode *));

	inode->i_version++;
	inode->i_op = &unionfs_main_iops;
	inode->i_fop = &unionfs_main_fops;
	/* I don't think ->a_ops is ever allowed to be NULL */
	inode->i_mapping->a_ops = &unionfs_empty_aops;
	fist_dprint(7, "setting inode 0x%p a_ops to empty (0x%p)\n",
		    inode, inode->i_mapping->a_ops);

	print_exit_location();
}
예제 #14
0
static void unionfs_put_inode(struct inode *inode)
{
	print_entry_location();
	fist_dprint(8, "%s i_count = %d, i_nlink = %d\n", __FUNCTION__,
		    atomic_read(&inode->i_count), inode->i_nlink);
	/*
	 * This is really funky stuff:
	 * Basically, if i_count == 1, iput will then decrement it and this inode will be destroyed.
	 * It is currently holding a reference to the hidden inode.
	 * Therefore, it needs to release that reference by calling iput on the hidden inode.
	 * iput() _will_ do it for us (by calling our clear_inode), but _only_ if i_nlink == 0.
	 * The problem is, NFS keeps i_nlink == 1 for silly_rename'd files.
	 * So we must for our i_nlink to 0 here to trick iput() into calling our clear_inode.
	 */
	if (atomic_read(&inode->i_count) == 1)
		inode->i_nlink = 0;
	print_exit_location();
}
예제 #15
0
STATIC void
base0fs_vm_open(vm_area_t *vma)
{
        vm_area_t *lower_vma, *lower_vma2;
        file_t *file;
        file_t *lower_file = NULL;

        print_entry_location();

        lower_vma = VMA_TO_LOWER(vma);
        file = vma->vm_file;
        if (FILE_TO_PRIVATE(file) != NULL)
                lower_file = FILE_TO_LOWER(file);
        BUG_ON(!lower_file);

        fist_dprint(6, "VM_OPEN: file 0x%x, lower_file 0x%x, file->f_count %d, lower_file->f_count %d\n",
                    (int) file, (int) lower_file,
                    (int) atomic_read(&file->f_count),
                    (int) atomic_read(&lower_file->f_count));

        if (lower_vma->vm_ops->open)
                lower_vma->vm_ops->open(lower_vma);
        atomic_inc(&lower_file->f_count);

        /* we need to duplicate the private data */
        lower_vma2 = KMALLOC(sizeof(vm_area_t), GFP_KERNEL);
        if (!lower_vma2) {
                printk("VM_OPEN: Out of memory\n");
                goto out;
        }
        memcpy(lower_vma2, lower_vma, sizeof(vm_area_t));
        VMA_TO_LOWER(vma) = lower_vma2;

out:
        fist_dprint(6, "VM_OPEN2: file 0x%x, lower_file 0x%x, file->f_count %d, lower_file->f_count %d\n",
                    (int) file, (int) lower_file,
                    (int) atomic_read(&file->f_count),
                    (int) atomic_read(&lower_file->f_count));
        print_exit_location();
}
예제 #16
0
static void fixputmaps(struct super_block *sb)
{
	struct unionfs_sb_info *spd;
	struct putmap *cur;
	int gen;
	int i;

	print_entry_location();

	spd = stopd(sb);
	cur = spd->usi_putmaps[spd->usi_lastputmap - spd->usi_firstputmap];

	for (gen = 0; gen < spd->usi_lastputmap - spd->usi_firstputmap; gen++) {
		if (!spd->usi_putmaps[gen])
			continue;
		for (i = 0; i <= spd->usi_putmaps[gen]->bend; i++)
			spd->usi_putmaps[gen]->map[i] =
			    cur->map[spd->usi_putmaps[gen]->map[i]];
	}

	print_exit_location();
}
예제 #17
0
/*
 * we don't really need unionfs_d_iput, because dentry_iput will call iput() if
 * unionfs_d_iput is not defined. We left this implemented for ease of
 * tracing/debugging.
 */
void unionfs_d_iput(struct dentry *dentry, struct inode *inode)
{
	print_entry_location();
	IPUT(inode);
	print_exit_location();
}
예제 #18
0
/*
 * Parse mount options.  See the manual page for usage instructions.
 *
 * Returns the dentry object of the lower-level (hidden) directory;
 * We want to mount our stackable file system on top of that hidden directory.
 *
 * Sets default debugging level to N, if any.
 */
static struct unionfs_dentry_info *unionfs_parse_options(struct super_block *sb,
							 char *options)
{
	struct unionfs_dentry_info *hidden_root_info;
	char *optname;
	int err = 0;
	int bindex;
	int dirsfound = 0;
#ifdef UNIONFS_IMAP
	int imapfound = 0;
#endif
	print_entry_location();

	/* allocate private data area */
	err = -ENOMEM;
	hidden_root_info =
	    KZALLOC(sizeof(struct unionfs_dentry_info), GFP_KERNEL);
	if (!hidden_root_info)
		goto out_error;
	hidden_root_info->udi_bstart = -1;
	hidden_root_info->udi_bend = -1;
	hidden_root_info->udi_bopaque = -1;

	while ((optname = strsep(&options, ",")) != NULL) {
		char *optarg;
		char *endptr;
		int intval;

		if (!*optname) {
			continue;
		}

		optarg = strchr(optname, '=');
		if (optarg) {
			*optarg++ = '\0';
		}

		/* All of our options take an argument now. Insert ones that
		 * don't, above this check.  */
		if (!optarg) {
			printk("unionfs: %s requires an argument.\n", optname);
			err = -EINVAL;
			goto out_error;
		}

		if (!strcmp("dirs", optname)) {
			if (++dirsfound > 1) {
				printk(KERN_WARNING
				       "unionfs: multiple dirs specified\n");
				err = -EINVAL;
				goto out_error;
			}
			err = parse_dirs_option(sb, hidden_root_info, optarg);
			if (err)
				goto out_error;
			continue;
		}
#ifdef UNIONFS_IMAP
		if (!strcmp("imap", optname)) {
			if (++imapfound > 1) {
				printk(KERN_WARNING
				       "unionfs: multiple imap specified\n");
				err = -EINVAL;
				goto out_error;
			}
			err = parse_imap_option(sb, hidden_root_info, optarg);
			if (err)
				goto out_error;
			continue;
		}
#endif
		if (!strcmp("delete", optname)) {
			if (!strcmp("whiteout", optarg)) {
				/* default */
#ifdef UNIONFS_DELETE_ALL
			} else if (!strcmp("all", optarg)) {
				MOUNT_FLAG(sb) |= DELETE_ALL;
#endif
			} else {
				printk(KERN_WARNING
				       "unionfs: invalid delete option '%s'\n",
				       optarg);
				err = -EINVAL;
				goto out_error;
			}
			continue;
		}
		if (!strcmp("copyup", optname)) {
			if (!strcmp("preserve", optarg)) {
				/* default */
			} else if (!strcmp("currentuser", optarg)) {
				MOUNT_FLAG(sb) |= COPYUP_CURRENT_USER;
			} else {
				printk(KERN_WARNING
				       "unionfs: could not parse copyup option value '%s'\n",
				       optarg);
				err = -EINVAL;
				goto out_error;
			}
			continue;
		}

		/* All of these options require an integer argument. */
		intval = simple_strtoul(optarg, &endptr, 0);
		if (*endptr) {
			printk(KERN_WARNING
			       "unionfs: invalid %s option '%s'\n",
			       optname, optarg);
			err = -EINVAL;
			goto out_error;
		}

		if (!strcmp("debug", optname)) {
			fist_set_debug_value(intval);
			continue;
		}

		err = -EINVAL;
		printk(KERN_WARNING
		       "unionfs: unrecognized option '%s'\n", optname);
		goto out_error;
	}
	if (dirsfound != 1) {
		printk(KERN_WARNING "unionfs: dirs option required\n");
		err = -EINVAL;
		goto out_error;
	}
	goto out;

      out_error:
	if (hidden_root_info && hidden_root_info->udi_dentry) {
		for (bindex = hidden_root_info->udi_bstart;
		     bindex >= 0 && bindex <= hidden_root_info->udi_bend;
		     bindex++) {
			struct dentry *d;
			d = hidden_root_info->udi_dentry[bindex];
			DPUT(d);
			if (stohiddenmnt_index(sb, bindex))
				mntput(stohiddenmnt_index(sb, bindex));
		}
	}

	KFREE(hidden_root_info->udi_dentry);
	KFREE(hidden_root_info);

	KFREE(stopd(sb)->usi_data);
	stopd(sb)->usi_data = NULL;

	hidden_root_info = ERR_PTR(err);
      out:
	print_exit_location();
	return hidden_root_info;
}
예제 #19
0
/*
 * No need to call write_inode() on the lower inode, as it
 * will have been marked 'dirty' anyway. But we might need
 * to write some of our own stuff to disk.
 */
STATIC void
mini_fo_write_inode(inode_t *inode, int sync)
{
	print_entry_location();
	print_exit_location();
}