Beispiel #1
0
static int __logfs_readdir(struct file *file, void *buf, filldir_t filldir)
{
	struct inode *dir = file->f_dentry->d_inode;
	loff_t pos = file->f_pos - IMPLICIT_NODES;
	struct page *page;
	struct logfs_disk_dentry *dd;
	int full;

	BUG_ON(pos < 0);
	for (;; pos++) {
		if (beyond_eof(dir, pos))
			break;
		if (!logfs_exist_block(dir, pos)) {
			/* deleted dentry */
			pos = dir_seek_data(dir, pos);
			continue;
		}
		page = read_cache_page(dir->i_mapping, pos,
				(filler_t *)logfs_readpage, NULL);
		if (IS_ERR(page))
			return PTR_ERR(page);
		dd = kmap(page);
		BUG_ON(dd->namelen == 0);

		full = filldir(buf, (char *)dd->name, be16_to_cpu(dd->namelen),
				pos, be64_to_cpu(dd->ino), dd->type);
		kunmap(page);
		page_cache_release(page);
		if (full)
			break;
	}

	file->f_pos = pos + IMPLICIT_NODES;
	return 0;
}
Beispiel #2
0
static int logfs_delete_dd(struct inode *dir, loff_t pos)
{
	/*
	 * Getting called with pos somewhere beyond eof is either a goofup
	 * within this file or means someone maliciously edited the
	 * (crc-protected) journal.
	 */
	BUG_ON(beyond_eof(dir, pos));
	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
	log_dir(" Delete dentry (%lx, %llx)\n", dir->i_ino, pos);
	return logfs_delete(dir, pos, NULL);
}
Beispiel #3
0
/* FIXME: readdir currently has it's own dir_walk code.  I don't see a good
 * way to combine the two copies */
static int logfs_readdir(struct file *file, struct dir_context *ctx)
{
	struct inode *dir = file_inode(file);
	loff_t pos;
	struct page *page;
	struct logfs_disk_dentry *dd;

	if (ctx->pos < 0)
		return -EINVAL;

	if (!dir_emit_dots(file, ctx))
		return 0;

	pos = ctx->pos - 2;
	BUG_ON(pos < 0);
	for (;; pos++, ctx->pos++) {
		bool full;
		if (beyond_eof(dir, pos))
			break;
		if (!logfs_exist_block(dir, pos)) {
			/* deleted dentry */
			pos = dir_seek_data(dir, pos);
			continue;
		}
		page = read_cache_page(dir->i_mapping, pos,
				(filler_t *)logfs_readpage, NULL);
		if (IS_ERR(page))
			return PTR_ERR(page);
		dd = kmap(page);
		BUG_ON(dd->namelen == 0);

		full = !dir_emit(ctx, (char *)dd->name,
				be16_to_cpu(dd->namelen),
				be64_to_cpu(dd->ino), dd->type);
		kunmap(page);
		page_cache_release(page);
		if (full)
			break;
	}
	return 0;
}
Beispiel #4
0
static struct page *logfs_get_dd_page(struct inode *dir, struct dentry *dentry)
{
	struct qstr *name = &dentry->d_name;
	struct page *page;
	struct logfs_disk_dentry *dd;
	u32 hash = hash_32(name->name, name->len, 0);
	pgoff_t index;
	int round;

	if (name->len > LOGFS_MAX_NAMELEN)
		return ERR_PTR(-ENAMETOOLONG);

	for (round = 0; round < 20; round++) {
		index = hash_index(hash, round);

		if (beyond_eof(dir, index))
			return NULL;
		if (!logfs_exist_block(dir, index))
			continue;
		page = read_cache_page(dir->i_mapping, index,
				(filler_t *)logfs_readpage, NULL);
		if (IS_ERR(page))
			return page;
		dd = kmap_atomic(page, KM_USER0);
		BUG_ON(dd->namelen == 0);

		if (name->len != be16_to_cpu(dd->namelen) ||
				memcmp(name->name, dd->name, name->len)) {
			kunmap_atomic(dd, KM_USER0);
			page_cache_release(page);
			continue;
		}

		kunmap_atomic(dd, KM_USER0);
		return page;
	}
	return NULL;
}