Exemple #1
0
static int autofs4_write(struct file *file, const void *addr, int bytes)
{
	unsigned long sigpipe, flags;
	mm_segment_t fs;
	const char *data = (const char *)addr;
	ssize_t wr = 0;

	/** WARNING: this is not safe for writing more than PIPE_BUF bytes! **/

	sigpipe = sigismember(&current->pending.signal, SIGPIPE);

	/* Save pointer to user space and point back to kernel space */
	fs = get_fs();
	set_fs(KERNEL_DS);

	while (bytes &&
	       (wr = file->f_op->write(file,data,bytes,&tx_cache_get_file(file)->f_pos)) > 0) {
		data += wr;
		bytes -= wr;
	}

	set_fs(fs);

	/* Keep the currently executing process from receiving a
	   SIGPIPE unless it was already supposed to get one */
	if (wr == -EPIPE && !sigpipe) {
		spin_lock_irqsave(&current->sighand->siglock, flags);
		sigdelset(&current->pending.signal, SIGPIPE);
		recalc_sigpending();
		spin_unlock_irqrestore(&current->sighand->siglock, flags);
	}

	return (bytes > 0);
}
Exemple #2
0
/**
 *	seq_open -	initialize sequential file
 *	@file: file we initialize
 *	@op: method table describing the sequence
 *
 *	seq_open() sets @file, associating it with a sequence described
 *	by @op.  @op->start() sets the iterator up and returns the first
 *	element of sequence. @op->stop() shuts it down.  @op->next()
 *	returns the next element of sequence.  @op->show() prints element
 *	into the buffer.  In case of error ->start() and ->next() return
 *	ERR_PTR(error).  In the end of sequence they return %NULL. ->show()
 *	returns 0 in case of success and negative number in case of error.
 */
int seq_open(struct file *file, const struct seq_operations *op)
{
	struct seq_file *p = file->private_data;
	struct _file *_file;

	if (!p) {
		p = kmalloc(sizeof(*p), GFP_KERNEL);
		if (!p)
			return -ENOMEM;
		file->private_data = p;
		record_tx_alloc(p, NULL);
	}
	memset(p, 0, sizeof(*p));
	mutex_init(&p->lock);
	p->op = op;

	/*
	 * Wrappers around seq_open(e.g. swaps_open) need to be
	 * aware of this. If they set f_version themselves, they
	 * should call seq_open first and then set f_version.
	 */
	_file = tx_cache_get_file(file);
	_file->f_version = 0;

	/* SEQ files support lseek, but not pread/pwrite */
	_file->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
	return 0;
}
Exemple #3
0
static ssize_t
configfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
	struct configfs_buffer * buffer = file->private_data;
	ssize_t len;

	down(&buffer->sem);
	len = fill_write_buffer(buffer, buf, count);
	if (len > 0)
		len = flush_write_buffer(tx_cache_get_file(file)->f_path.dentry, buffer, count);
	if (len > 0)
		*ppos += len;
	up(&buffer->sem);
	return len;
}
Exemple #4
0
static ssize_t
configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
	struct configfs_buffer * buffer = file->private_data;
	ssize_t retval = 0;

	down(&buffer->sem);
	if (buffer->needs_read_fill) {
		if ((retval = fill_read_buffer(tx_cache_get_file(file)->f_path.dentry,buffer)))
			goto out;
	}
	pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",
		 __FUNCTION__, count, *ppos, buffer->page);
	retval = simple_read_from_buffer(buf, count, ppos, buffer->page,
					 buffer->count);
out:
	up(&buffer->sem);
	return retval;
}
Exemple #5
0
static int configfs_release(struct _inode * inode, struct file * filp)
{
	struct config_item * item = to_item(file_get_dentry(filp)->d_parent);
	struct configfs_attribute * attr = to_attr(tx_cache_get_file(filp)->f_path.dentry);
	struct module * owner = attr->ca_owner;
	struct configfs_buffer * buffer = filp->private_data;

	if (item)
		config_item_put(item);
	/* After this point, attr should not be accessed. */
	module_put(owner);

	if (buffer) {
		if (buffer->page)
			free_page((unsigned long)buffer->page);
		kfree(buffer);
	}
	return 0;
}
Exemple #6
0
static int acct_on(char *name)
{
	struct file *file;
	struct _file *_file;
	int error;

	/* Difference from BSD - they don't do O_APPEND */
	file = filp_open(name, O_WRONLY|O_APPEND|O_LARGEFILE, 0);
	if (IS_ERR(file))
		return PTR_ERR(file);


	_file = tx_cache_get_file(file);
	if (!S_ISREG(d_get_inode(f_get_dentry_ro(_file))->i_mode)) {
		filp_close(file, NULL);
		return -EACCES;
	}

	if (!file->f_op->write) {
		filp_close(file, NULL);
		return -EIO;
	}

	error = security_acct(file);
	if (error) {
		filp_close(file, NULL);
		return error;
	}

	spin_lock(&acct_globals.lock);
	mnt_pin(_file->f_path.mnt);
	acct_file_reopen(file);
	spin_unlock(&acct_globals.lock);

	mntput(_file->f_path.mnt); /* it's pinned, now give up active reference */

	return 0;
}
Exemple #7
0
/*
 * Careful here! We test whether the file pointer is NULL before
 * releasing the fd. This ensures that one clone task can't release
 * an fd while another clone is opening it.
 */
asmlinkage long sys_close(unsigned int fd)
{
	struct file * filp;
	struct files_struct *files = current->files;
	struct fdtable *fdt;
	int retval;
	if(need_files_checkpoint())
		checkpoint_files();

	spin_lock(&files->file_lock);
	fdt = files_fdtable(files);
	if (fd >= fdt->max_fds)
		goto out_unlock;

	filp = fdt->fd[fd];
	if (!filp)
		goto out_unlock;
	tx_cache_get_file(filp); //get tx refcount on file

	rcu_assign_pointer(fdt->fd[fd], NULL);
	FD_CLR(fd, fdt->close_on_exec); //??check later
	__put_unused_fd(files, fd);
	spin_unlock(&files->file_lock);
	retval = filp_close(filp, files);
	/* can't restart close syscall because file table entry was cleared */
	if (unlikely(retval == -ERESTARTSYS ||
		     retval == -ERESTARTNOINTR ||
		     retval == -ERESTARTNOHAND ||
		     retval == -ERESTART_RESTARTBLOCK))
		retval = -EINTR;

	return retval;

out_unlock:
	spin_unlock(&files->file_lock);
	return -EBADF;
}
Exemple #8
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);
}
Exemple #9
0
/*
 * This is used by subsystems that don't want seekable
 * file descriptors
 */
int nonseekable_open(struct _inode *inode, struct file *filp)
{
	tx_cache_get_file(filp)->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
	return 0;
}
Exemple #10
0
/**
 *	seq_read -	->read() method for sequential files.
 *	@file: the file to read from
 *	@buf: the buffer to read to
 *	@size: the maximum number of bytes to read
 *	@ppos: the current position in the file
 *
 *	Ready-made ->f_op->read()
 */
ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
	struct seq_file *m = (struct seq_file *)file->private_data;
	size_t copied = 0;
	loff_t pos;
	size_t n;
	void *p;
	int err = 0;
	struct _file *_file;

	mutex_lock(&m->lock);
	/*
	 * seq_file->op->..m_start/m_stop/m_next may do special actions
	 * or optimisations based on the file->f_version, so we want to
	 * pass the file->f_version to those methods.
	 *
	 * seq_file->version is just copy of f_version, and seq_file
	 * methods can treat it simply as file version.
	 * It is copied in first and copied out after all operations.
	 * It is convenient to have it as  part of structure to avoid the
	 * need of passing another argument to all the seq_file methods.
	 */
	_file = tx_cache_get_file(file);
	m->version = _file->f_version;
	/* grab buffer if we didn't have one */
	if (!m->buf) {
		m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
		if (!m->buf)
			goto Enomem;
	}
	/* if not empty - flush it first */
	if (m->count) {
		n = min(m->count, size);
		err = copy_to_user(buf, m->buf + m->from, n);
		if (err)
			goto Efault;
		m->count -= n;
		m->from += n;
		size -= n;
		buf += n;
		copied += n;
		if (!m->count)
			m->index++;
		if (!size)
			goto Done;
	}
	/* we need at least one record in buffer */
	while (1) {
		pos = m->index;
		p = m->op->start(m, &pos);
		err = PTR_ERR(p);
		if (!p || IS_ERR(p))
			break;
		err = m->op->show(m, p);
		if (err)
			break;
		if (m->count < m->size)
			goto Fill;
		m->op->stop(m, p);
		kfree(m->buf);
		m->buf = kmalloc(m->size <<= 1, GFP_KERNEL);
		if (!m->buf)
			goto Enomem;
		m->count = 0;
		m->version = 0;
	}
	m->op->stop(m, p);
	m->count = 0;
	goto Done;
Fill:
	/* they want more? let's try to get some more */
	while (m->count < size) {
		size_t offs = m->count;
		loff_t next = pos;
		p = m->op->next(m, p, &next);
		if (!p || IS_ERR(p)) {
			err = PTR_ERR(p);
			break;
		}
		err = m->op->show(m, p);
		if (err || m->count == m->size) {
			m->count = offs;
			break;
		}
		pos = next;
	}
	m->op->stop(m, p);
	n = min(m->count, size);
	err = copy_to_user(buf, m->buf, n);
	if (err)
		goto Efault;
	copied += n;
	m->count -= n;
	if (m->count)
		m->from = n;
	else
		pos++;
	m->index = pos;
Done:
	if (!copied)
		copied = err;
	else
		*ppos += copied;
	_file->f_version = m->version;
	mutex_unlock(&m->lock);
	return copied;
Enomem:
	err = -ENOMEM;
	goto Done;
Efault:
	err = -EFAULT;
	goto Done;
}
Exemple #11
0
/**
 * anon_inode_getfd - creates a new file instance by hooking it up to and
 *                    anonymous inode, and a dentry that describe the "class"
 *                    of the file
 *
 * @pfd:     [out]   pointer to the file descriptor
 * @dpinode: [out]   pointer to the inode
 * @pfile:   [out]   pointer to the file struct
 * @name:    [in]    name of the "class" of the new file
 * @fops     [in]    file operations for the new file
 * @priv     [in]    private data for the new file (will be file's private_data)
 *
 * Creates a new file by hooking it on a single inode. This is useful for files
 * that do not need to have a full-fledged inode in order to operate correctly.
 * All the files created with anon_inode_getfd() will share a single inode, by
 * hence saving memory and avoiding code duplication for the file/inode/dentry
 * setup.
 */
int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile,
		     const char *name, const struct file_operations *fops,
		     void *priv)
{
	struct qstr this;
	struct dentry *dentry;
	struct _dentry *_dentry;
	struct inode *inode;
	struct _inode *_inode;
	struct file *file;
	struct _file *_file;
	int error, fd;

	if (IS_ERR(anon_inode_inode))
		return -ENODEV;
	file = get_empty_filp();
	if (!file)
		return -ENFILE;

	_file = tx_cache_get_file(file);

	inode = igrab(anon_inode_inode);
	if (IS_ERR(inode)) {
		error = PTR_ERR(inode);
		goto err_put_filp;
	}

	_inode = tx_cache_get_inode(inode);

	error = get_unused_fd();
	if (error < 0)
		goto err_iput;
	fd = error;

	/*
	 * Link the inode to a directory entry by creating a unique name
	 * using the inode sequence number.
	 */
	error = -ENOMEM;
	this.name = name;
	this.len = strlen(name);
	this.hash = 0;
	dentry = d_alloc(tx_cache_get_dentry(anon_inode_mnt->mnt_sb->s_root), &this);
	if (!dentry)
		goto err_put_unused_fd;
	_dentry = tx_cache_get_dentry(dentry);
	_dentry->d_op = &anon_inodefs_dentry_operations;
	/* Do not publish this dentry inside the global dentry hash table */
	_dentry->d_flags &= ~DCACHE_UNHASHED;
	d_instantiate(_dentry, _inode);

	_file->f_path.mnt = mntget(anon_inode_mnt);
	_file->f_path.dentry = dentry;
	file->f_mapping = _inode->i_mapping;

	_file->f_pos = 0;
	_file->f_flags = O_RDWR;
	file->f_op = fops;
	_file->f_mode = FMODE_READ | FMODE_WRITE;
	_file->f_version = 0;
	file->private_data = priv;

	fd_install(fd, file);

	*pfd = fd;
	*pinode = inode;
	*pfile = file;
	return 0;

err_put_unused_fd:
	put_unused_fd(fd);
err_iput:
	iput(inode);
err_put_filp:
	put_filp(file);
	return error;
}
Exemple #12
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;
}
Exemple #13
0
static int check_perm(struct _inode * inode, struct file * file)
{
	struct config_item *item = configfs_get_config_item(file_get_dentry(file)->d_parent);
	struct configfs_attribute * attr;
	struct configfs_buffer * buffer;
	struct configfs_item_operations * ops = NULL;
	struct _file *_file = tx_cache_get_file(file);
	int error = 0;
	attr = to_attr(_file->f_path.dentry);

	if (!item || !attr)
		goto Einval;

	/* Grab the module reference for this attribute if we have one */
	if (!try_module_get(attr->ca_owner)) {
		error = -ENODEV;
		goto Done;
	}

	if (item->ci_type)
		ops = item->ci_type->ct_item_ops;
	else
		goto Eaccess;

	/* File needs write support.
	 * The inode's perms must say it's ok,
	 * and we must have a store method.
	 */
	if (_file->f_mode & FMODE_WRITE) {

		if (!(inode->i_mode & S_IWUGO) || !ops->store_attribute)
			goto Eaccess;

	}

	/* File needs read support.
	 * The inode's perms must say it's ok, and we there
	 * must be a show method for it.
	 */
	if (_file->f_mode & FMODE_READ) {
		if (!(inode->i_mode & S_IRUGO) || !ops->show_attribute)
			goto Eaccess;
	}

	/* No error? Great, allocate a buffer for the file, and store it
	 * it in file->private_data for easy access.
	 */
	buffer = kzalloc(sizeof(struct configfs_buffer),GFP_KERNEL);
	if (!buffer) {
		error = -ENOMEM;
		goto Enomem;
	}
	init_MUTEX(&buffer->sem);
	buffer->needs_read_fill = 1;
	buffer->ops = ops;
	file->private_data = buffer;
	goto Done;

 Einval:
	error = -EINVAL;
	goto Done;
 Eaccess:
	error = -EACCES;
 Enomem:
	module_put(attr->ca_owner);
 Done:
	if (error && item)
		config_item_put(item);
	return error;
}