Ejemplo n.º 1
0
long do_fsync(struct file *file, int datasync)
{
	int ret;
	int err;
	struct address_space *mapping = file->f_mapping;
	
	if (live_transaction()){
		/* DEP 5/27/10 - Defer fsync until commit. */
		struct deferred_object_operation *def_op;
		txobj_thread_list_node_t *list_node = workset_has_object(&file->f_mapping->host->xobj);

		if (!list_node) {
			tx_cache_get_file_ro(file);
			tx_cache_get_inode_ro(file->f_mapping->host);
			list_node = workset_has_object(&file->f_mapping->host->xobj); 
		}

		def_op = alloc_deferred_object_operation();
		INIT_LIST_HEAD(&def_op->list);
		def_op->type = DEFERRED_TYPE_FSYNC;
		def_op->u.fsync.datasync = datasync;
		def_op->u.fsync.file = file;

		/* DEP: Pin the file until the sync is executed */
		tx_atomic_inc_not_zero(&file->f_count);

		// XXX: Could probably use something finer grained here.  
		WORKSET_LOCK(current->transaction);
		list_add(&def_op->list, &list_node->deferred_operations);
		WORKSET_UNLOCK(current->transaction);
		return 0;
	}

	if (!file->f_op || !file->f_op->fsync) {
		/* Why?  We can still call filemap_fdatawrite */
		ret = -EINVAL;
		goto out;
	}

	ret = filemap_fdatawrite(mapping);

	/*
	 * We need to protect against concurrent writers, which could cause
	 * livelocks in fsync_buffers_list().
	 */
	if (!committing_transaction())
		mutex_lock(&mapping->host->i_mutex);
	err = file->f_op->fsync(file, file_get_dentry(file), datasync);
	if (!ret)
		ret = err;
	if (!committing_transaction())
		mutex_unlock(&mapping->host->i_mutex);
	err = filemap_fdatawait(mapping);
	if (!ret)
		ret = err;
out:
	return ret;
}
Ejemplo n.º 2
0
static long do_ioctl(struct file *filp, unsigned int cmd,
		unsigned long arg)
{
	int error = -ENOTTY;
	void *f;

	/* Whitelist check */
	if(live_transaction()){
		switch(cmd){
		case FIOCLEX:
		case FIONCLEX:
		case FIONBIO:
		case FIOASYNC:
		case FIOQSIZE:
		case TCGETS:
			break;
		default:
			if(current->transaction->unsupported_operation_action == UNSUPPORTED_ABORT){
				// Don't leap out of the stack
				printk(KERN_ERR "Aborting on unsupported ioctl in tx: %u\n", cmd);
				abort_self(NULL, 0);
			} else if(current->transaction->unsupported_operation_action == UNSUPPORTED_ERROR_CODE){
				printk(KERN_ERR "Warning: Stopped execution of unsupported ioctl in tx: %u\n", cmd);
				return -ENOTXSUPPORT;
			} else {
#ifdef CONFIG_TX_KSTM_WARNINGS
				printk(KERN_ERR "Warning: Executing unsupported ioctl in tx: %u\n", cmd);
#endif
			}
		}
	}

	if (!filp->f_op)
		goto out;

	if (filp->f_op->unlocked_ioctl) {
		error = filp->f_op->unlocked_ioctl(filp, cmd, arg);
		if (error == -ENOIOCTLCMD)
			error = -EINVAL;
		goto out;
	} else if ((f = filp->f_op->ioctl)) {
		lock_kernel();
		if (!filp->f_op->ioctl) {
			printk("%s: ioctl %p disappeared\n", __FUNCTION__, f);
			print_symbol("symbol: %s\n", (unsigned long)f);
			dump_stack();
		} else {
			error = filp->f_op->ioctl((file_get_dentry(filp)->d_inode),
						  filp, cmd, arg);
		}
		unlock_kernel();
	}

 out:
	return error;
}
Ejemplo n.º 3
0
static struct file *__dentry_open(struct _dentry *dentry, struct vfsmount *mnt,
					int flags, struct file *f,
					int (*open)(struct _inode *, struct file *))
{
	struct _inode *inode;
	int error;
	struct super_block *sb;
	struct _file *_f = tx_cache_get_file(f);

	_f->f_flags = flags;
	_f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK |
		 		FMODE_PREAD | FMODE_PWRITE;
	inode = d_get_inode(dentry);
	sb = inode->i_sb;

	if (_f->f_mode & FMODE_WRITE) {
		error = get_write_access(parent(inode));
		if (error)
			goto cleanup_file;
	}

	f->f_mapping = inode->i_mapping;
	_f->f_path.dentry = parent(dentry);
	_f->f_path.mnt = mnt;
	_f->f_pos = 0;
	f->f_op = fops_get(inode->i_fop);
	file_move(f, &sb->s_files);

	if (!open && f->f_op)
		open = f->f_op->open;
	if (open) {
		error = open(inode, f);
		if (error)
			goto cleanup_all;
	}

	_f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

	file_ra_state_init(&f->f_ra, 
			   tx_cache_get_inode(f->f_mapping->host)->i_mapping);

	/* NB: we're sure to have correct a_ops only after f_op->open */
	if (_f->f_flags & O_DIRECT) {
		if (!f->f_mapping->a_ops ||
		    ((!f->f_mapping->a_ops->direct_IO) &&
		    (!f->f_mapping->a_ops->get_xip_page))) {
			fput(f);
			f = ERR_PTR(-EINVAL);
		}
	}

	return f;

cleanup_all:
	fops_put(f->f_op);
	if (_f->f_mode & FMODE_WRITE)
		put_write_access(parent(inode));
	file_kill(f);
	_f->f_path.dentry = NULL;
	_f->f_path.mnt = NULL;
cleanup_file:
	/* Avoid issues if we recycle this object */
	if(live_transaction())
		early_release(&f->xobj, 1);
	put_filp(f);
	dput(parent(dentry));
	mntput(mnt);
	return ERR_PTR(error);
}
Ejemplo n.º 4
0
/*
 * When you add any new common ioctls to the switches above and below
 * please update compat_sys_ioctl() too.
 *
 * vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
 * It's just a simple helper for sys_ioctl and compat_sys_ioctl.
 */
int vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned long arg)
{
	unsigned int flag;
	int on, error = 0;
	umode_t mode;
	
	struct _file *_filp = tx_cache_get_file(filp);
	/* Patch up ioctl for bad tx cases*/
	if((!_filp) || !_filp->f_dentry ){
#ifdef CONFIG_TX_KSTM_WARNINGS
		printk(KERN_ERR "Fixing up ioctl\n");
#endif
		return 0;
	}
	mode = d_get_inode_ro(f_get_dentry(_filp))->i_mode;

	switch (cmd) {
		case FIOCLEX:
			set_close_on_exec(fd, 1);
			break;

		case FIONCLEX:
			set_close_on_exec(fd, 0);
			break;

		case FIONBIO:
			if ((error = get_user(on, (int __user *)arg)) != 0)
				break;
			flag = O_NONBLOCK;
#ifdef __sparc__
			/* SunOS compatibility item. */
			if(O_NONBLOCK != O_NDELAY)
				flag |= O_NDELAY;
#endif
			if (on)
				_filp->f_flags |= flag;
			else
				_filp->f_flags &= ~flag;
			break;

		case FIOASYNC:
			if ((error = get_user(on, (int __user *)arg)) != 0)
				break;
			flag = on ? FASYNC : 0;

			/* Did FASYNC state change ? */
			if ((flag ^ _filp->f_flags) & FASYNC) {
				if (filp->f_op && filp->f_op->fasync) {
					lock_kernel();
					error = filp->f_op->fasync(fd, filp, on);
					unlock_kernel();
				}
				else error = -ENOTTY;
			}
			if (error != 0)
				break;

			if (on)
				_filp->f_flags |= FASYNC;
			else
				_filp->f_flags &= ~FASYNC;
			break;

		case FIOQSIZE:
			if (S_ISDIR(mode) ||
			    S_ISREG(mode) ||
			    S_ISLNK(mode)) {
				loff_t res = inode_get_bytes(f_get_dentry(_filp)->d_inode);
				error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0;
			}
			else
				error = -ENOTTY;
			break;
		default:
			if(live_transaction()){
				/* Short circuit this stupid ioctl */
				if(cmd == TIOCGWINSZ){
#ifdef CONFIG_TX_KSTM_WARNINGS
					printk(KERN_ERR "Warning: some bozo wants to know the terminal width in a transaction.\n");
#endif
					error = -EINVAL;
					break;
				} else if(cmd != TCGETS)
					BUG();
			}

			if (S_ISREG(mode))
				error = file_ioctl(filp, cmd, arg);
			else
				error = do_ioctl(filp, cmd, arg);
			break;
	}
	return error;
}