Beispiel #1
0
static int autofs4_getpath(struct autofs_sb_info *sbi,
			   struct dentry *dentry, char **name)
{
	struct dentry *root = sbi->sb->s_root;
	struct _dentry *tmp;
	char *buf = *name;
	char *p;
	int len = 0;
	struct _dentry *_dentry = tx_cache_get_dentry(dentry);

	spin_lock(&dcache_lock);
	for (tmp = tx_cache_get_dentry(dentry) ; parent(tmp) != root ; 
	     tmp = tx_cache_get_dentry(tmp->d_parent))
		len += tmp->d_name.len + 1;

	if (--len > NAME_MAX) {
		spin_unlock(&dcache_lock);
		return 0;
	}

	*(buf + len) = '\0';
	p = buf + len - _dentry->d_name.len;
	strncpy(p, _dentry->d_name.name, _dentry->d_name.len);

	for (tmp = tx_cache_get_dentry(_dentry->d_parent); 
	     parent(tmp) != root ; tmp = tx_cache_get_dentry(tmp->d_parent)) {
		*(--p) = '/';
		p -= tmp->d_name.len;
		strncpy(p, tmp->d_name.name, tmp->d_name.len);
	}
	spin_unlock(&dcache_lock);

	return len;
}
Beispiel #2
0
static int oprofilefs_fill_super(struct super_block * sb, void * data, int silent)
{
	struct inode * root_inode;
	struct _inode * _root_inode;
	struct dentry * root_dentry;

	sb->s_blocksize = PAGE_CACHE_SIZE;
	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
	sb->s_magic = OPROFILEFS_MAGIC;
	sb->s_op = &s_ops;
	sb->s_time_gran = 1;

	root_inode = oprofilefs_get_inode(sb, S_IFDIR | 0755);
	if (!root_inode)
		return -ENOMEM;
	_root_inode = tx_cache_get_inode(root_inode);
	_root_inode->i_op = &simple_dir_inode_operations;
	_root_inode->i_fop = &simple_dir_operations;
	root_dentry = d_alloc_root(_root_inode);
	if (!root_dentry) {
		iput(root_inode);
		return -ENOMEM;
	}

	sb->s_root = root_dentry;

	oprofile_create_files(sb, tx_cache_get_dentry(root_dentry));

	// FIXME: verify kill_litter_super removes our dentries
	return 0;
}
Beispiel #3
0
static int
flush_write_buffer(struct dentry * dentry, struct configfs_buffer * buffer, size_t count)
{
	struct configfs_attribute * attr = to_attr(dentry);
	struct config_item * item = to_item(tx_cache_get_dentry(dentry)->d_parent);
	struct configfs_item_operations * ops = buffer->ops;

	return ops->store_attribute(item,attr,buffer->page,count);
}
Beispiel #4
0
int configfs_add_file(struct dentry * dir, const struct configfs_attribute * attr, int type)
{
	struct configfs_dirent * parent_sd = dir->d_fsdata;
	umode_t mode = (attr->ca_mode & S_IALLUGO) | S_IFREG;
	int error = 0;
	struct inode *inode = tx_cache_get_dentry(dir)->d_inode;

	mutex_lock(&inode->i_mutex);
	error = configfs_make_dirent(parent_sd, NULL, (void *) attr, mode, type);
	mutex_unlock(&inode->i_mutex);

	return error;
}
Beispiel #5
0
/*
 * dentry_open() will have done dput(dentry) and mntput(mnt) if it returns an
 * error.
 */
struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
{
	int error;
	struct file *f;

	error = -ENFILE;
	f = get_empty_filp();
	if (f == NULL) {
		dput(dentry);
		mntput(mnt);
		return ERR_PTR(error);
	}

	return __dentry_open(tx_cache_get_dentry(dentry), mnt, flags, f, NULL);
}
Beispiel #6
0
/**
 * lookup_instantiate_filp - instantiates the open intent filp
 * @nd: pointer to nameidata
 * @dentry: pointer to dentry
 * @open: open callback
 *
 * Helper for filesystems that want to use lookup open intents and pass back
 * a fully instantiated struct file to the caller.
 * This function is meant to be called from within a filesystem's
 * lookup method.
 * Beware of calling it for non-regular files! Those ->open methods might block
 * (e.g. in fifo_open), leaving you with parent locked (and in case of fifo,
 * leading to a deadlock, as nobody can open that fifo anymore, because
 * another process to open fifo will block on locked parent when doing lookup).
 * Note that in case of error, nd->intent.open.file is destroyed, but the
 * path information remains valid.
 * If the open callback is set to NULL, then the standard f_op->open()
 * filesystem callback is substituted.
 */
struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
		int (*open)(struct _inode *, struct file *))
{
	if (IS_ERR(nd->intent.open.file))
		goto out;
	if (IS_ERR(dentry))
		goto out_err;
	nd->intent.open.file = __dentry_open(tx_cache_get_dentry(dget(dentry)), 
					     mntget(nd->mnt),
					     nd->intent.open.flags - 1,
					     nd->intent.open.file,
					     open);
out:
	return nd->intent.open.file;
out_err:
	release_open_intent(nd);
	nd->intent.open.file = (struct file *)dentry;
	goto out;
}
Beispiel #7
0
/**
 *	fill_read_buffer - allocate and fill buffer from item.
 *	@dentry:	dentry pointer.
 *	@buffer:	data buffer for file.
 *
 *	Allocate @buffer->page, if it hasn't been already, then call the
 *	config_item's show() method to fill the buffer with this attribute's
 *	data.
 *	This is called only once, on the file's first read.
 */
static int fill_read_buffer(struct dentry * dentry, struct configfs_buffer * buffer)
{
	struct configfs_attribute * attr = to_attr(dentry);
	struct config_item * item = to_item(tx_cache_get_dentry(dentry)->d_parent);
	struct configfs_item_operations * ops = buffer->ops;
	int ret = 0;
	ssize_t count;

	if (!buffer->page)
		buffer->page = (char *) get_zeroed_page(GFP_KERNEL);
	if (!buffer->page)
		return -ENOMEM;

	count = ops->show_attribute(item,attr,buffer->page);
	buffer->needs_read_fill = 0;
	BUG_ON(count > (ssize_t)PAGE_SIZE);
	if (count >= 0)
		buffer->count = count;
	else
		ret = count;
	return ret;
}
Beispiel #8
0
/*
 * Generic function to fsync a file.
 *
 * filp may be NULL if called via the msync of a vma.
 */
int file_fsync(struct file *filp, struct dentry *dentry, int datasync)
{
	struct inode * inode = tx_cache_get_dentry(dentry)->d_inode;
	struct super_block * sb;
	int ret, err;

	/* sync the inode to buffers */
	ret = write_inode_now(inode, 0);

	/* sync the superblock to buffers */
	sb = tx_cache_get_inode_ro(inode)->i_sb;
	lock_super(sb);
	if (sb->s_op->write_super)
		sb->s_op->write_super(sb);
	unlock_super(sb);

	/* .. finally sync the buffers to disk */
	err = sync_blockdev(sb->s_bdev);
	if (!ret)
		ret = err;
	return ret;
}
Beispiel #9
0
static struct _dentry * __oprofilefs_create_file(struct super_block * sb,
	struct _dentry * root, char const * name, const struct file_operations * fops,
	int perm)
{
	struct dentry * dentry;
	struct _dentry * _dentry;
	struct inode * inode;
	struct _inode * _inode;

	dentry = d_alloc_name(root, name);
	if (!dentry)
		return NULL;
	inode = oprofilefs_get_inode(sb, S_IFREG | perm);
	if (!inode) {
		dput(dentry);
		return NULL;
	}
	_inode = tx_cache_get_inode(inode);
	_inode->i_fop = fops;
	_dentry = tx_cache_get_dentry(dentry);
	d_add(_dentry, _inode);
	return _dentry;
}
Beispiel #10
0
struct _dentry * oprofilefs_mkdir(struct super_block * sb,
	struct _dentry * root, char const * name)
{
	struct dentry * dentry;
	struct _dentry * _dentry;
	struct inode * inode;
	struct _inode * _inode;

	dentry = d_alloc_name(root, name);
	if (!dentry)
		return NULL;
	inode = oprofilefs_get_inode(sb, S_IFDIR | 0755);
	if (!inode) {
		dput(dentry);
		return NULL;
	}

	_inode = tx_cache_get_inode(inode);
	_inode->i_op = &simple_dir_inode_operations;
	_inode->i_fop = &simple_dir_operations;
	_dentry = tx_cache_get_dentry(dentry);
	d_add(_dentry, _inode);
	return _dentry;
}
Beispiel #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;
}
Beispiel #12
0
int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
		enum autofs_notify notify)
{
	struct autofs_info *ino;
	struct autofs_wait_queue *wq;
	char *name;
	unsigned int len = 0;
	unsigned int hash = 0;
	int status, type;

	/* In catatonic mode, we don't wait for nobody */
	if (sbi->catatonic)
		return -ENOENT;
	
	name = kmalloc(NAME_MAX + 1, GFP_KERNEL);
	if (!name)
		return -ENOMEM;

	/* If this is a direct mount request create a dummy name */
	if (IS_ROOT(tx_cache_get_dentry(dentry)) && (sbi->type & AUTOFS_TYPE_DIRECT))
		len = sprintf(name, "%p", dentry);
	else {
		len = autofs4_getpath(sbi, dentry, &name);
		if (!len) {
			kfree(name);
			return -ENOENT;
		}
	}
	hash = full_name_hash(name, len);

	if (mutex_lock_interruptible(&sbi->wq_mutex)) {
		kfree(name);
		return -EINTR;
	}

	wq = autofs4_find_wait(sbi, name, hash, len);
	ino = autofs4_dentry_ino(dentry);
	if (!wq && ino && notify == NFY_NONE) {
		/*
		 * Either we've betean the pending expire to post it's
		 * wait or it finished while we waited on the mutex.
		 * So we need to wait till either, the wait appears
		 * or the expire finishes.
		 */

		while (ino->flags & AUTOFS_INF_EXPIRING) {
			mutex_unlock(&sbi->wq_mutex);
			schedule_timeout_interruptible(HZ/10);
			if (mutex_lock_interruptible(&sbi->wq_mutex)) {
				kfree(name);
				return -EINTR;
			}
			wq = autofs4_find_wait(sbi, name, hash, len);
			if (wq)
				break;
		}

		/*
		 * Not ideal but the status has already gone. Of the two
		 * cases where we wait on NFY_NONE neither depend on the
		 * return status of the wait.
		 */
		if (!wq) {
			kfree(name);
			mutex_unlock(&sbi->wq_mutex);
			return 0;
		}
	}

	if (!wq) {
		/* Create a new wait queue */
		wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL);
		if (!wq) {
			kfree(name);
			mutex_unlock(&sbi->wq_mutex);
			return -ENOMEM;
		}

		wq->wait_queue_token = autofs4_next_wait_queue;
		if (++autofs4_next_wait_queue == 0)
			autofs4_next_wait_queue = 1;
		wq->next = sbi->queues;
		sbi->queues = wq;
		init_waitqueue_head(&wq->queue);
		wq->hash = hash;
		wq->name = name;
		wq->len = len;
		wq->dev = autofs4_get_dev(sbi);
		wq->ino = autofs4_get_ino(sbi);
		wq->uid = current->uid;
		wq->gid = current->gid;
		wq->pid = current->pid;
		wq->tgid = current->tgid;
		wq->status = -EINTR; /* Status return if interrupted */
		atomic_set(&wq->wait_ctr, 2);
		mutex_unlock(&sbi->wq_mutex);

		if (sbi->version < 5) {
			if (notify == NFY_MOUNT)
				type = autofs_ptype_missing;
			else
				type = autofs_ptype_expire_multi;
		} else {
			if (notify == NFY_MOUNT)
				type = (sbi->type & AUTOFS_TYPE_DIRECT) ?
					autofs_ptype_missing_direct :
					 autofs_ptype_missing_indirect;
			else
				type = (sbi->type & AUTOFS_TYPE_DIRECT) ?
					autofs_ptype_expire_direct :
					autofs_ptype_expire_indirect;
		}

		DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d\n",
			(unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);

		/* autofs4_notify_daemon() may block */
		autofs4_notify_daemon(sbi, wq, type);
	} else {
		atomic_inc(&wq->wait_ctr);
		mutex_unlock(&sbi->wq_mutex);
		kfree(name);
		DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d",
			(unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
	}

	/* wq->name is NULL if and only if the lock is already released */

	if (sbi->catatonic) {
		/* We might have slept, so check again for catatonic mode */
		wq->status = -ENOENT;
		kfree(wq->name);
		wq->name = NULL;
	}

	if (wq->name) {
		/* Block all but "shutdown" signals while waiting */
		sigset_t oldset;
		unsigned long irqflags;

		spin_lock_irqsave(&current->sighand->siglock, irqflags);
		oldset = current->blocked;
		siginitsetinv(&current->blocked, SHUTDOWN_SIGS & ~oldset.sig[0]);
		recalc_sigpending();
		spin_unlock_irqrestore(&current->sighand->siglock, irqflags);

		wait_event_interruptible(wq->queue, wq->name == NULL);

		spin_lock_irqsave(&current->sighand->siglock, irqflags);
		current->blocked = oldset;
		recalc_sigpending();
		spin_unlock_irqrestore(&current->sighand->siglock, irqflags);
	} else {
		DPRINTK("skipped sleeping");
	}

	status = wq->status;

	/* Are we the last process to need status? */
	if (atomic_dec_and_test(&wq->wait_ctr))
		kfree(wq);

	return status;
}