Skip to content

Commit

Permalink
zuf: Filesystem operations
Browse files Browse the repository at this point in the history
The principle for all operations is the same.

* The few parameters are given on the despatch IOCTL
  buffer (up to 4k of parameters)

* Any application buffers or other big buffers
  like readdir are mapped via zuf-core to the the Server VM

* The operation is despatched. Return code and few out
  parameter are returned in the despatch-return buffer.
  Any data stored/read at mapped application buffers.

* zus objects like zus_inode symlinks and so on are returned
  through a dpp_t (Dual port pointer) - a special kind of zuf
  construct that enables to have a Kernel pointer and a server
  pointer to the same memory. If pmem is used this is usually
  a pointer to pmem.

  The Kernel's zuf part may even write to this returned pointer
  but it will then send a despatch, for the FS to persist the
  change.

TODO:
	This patch is probably too big. how best to split it?

Signed-off-by: Boaz Harrosh <boazh@netapp.com>
  • Loading branch information
Boaz17 committed Mar 13, 2018
1 parent b8041d6 commit 70650fc
Show file tree
Hide file tree
Showing 8 changed files with 1,953 additions and 4 deletions.
2 changes: 1 addition & 1 deletion fs/zuf/Makefile
Expand Up @@ -17,5 +17,5 @@ zuf-y += md.o t2.o t1.o
zuf-y += zuf-core.o zuf-root.o

# Main FS
zuf-y += super.o inode.o
zuf-y += super.o inode.o directory.o file.o namei.o symlink.o
zuf-y += module.o
48 changes: 48 additions & 0 deletions fs/zuf/_extern.h
Expand Up @@ -19,16 +19,43 @@
* extern functions declarations
*/

/* directory.c */
int zuf_add_dentry(struct inode *dir, struct qstr *str,
struct inode *inode, bool rename);
int zuf_remove_dentry(struct inode *dir, struct qstr *str);

/* inode.c */
int zuf_evict_dispatch(struct super_block *sb, struct zus_inode_info *zus_ii,
int operation);
struct inode *zuf_iget(struct super_block *sb, struct zus_inode_info *zus_ii,
zu_dpp_t _zi, bool *exist);
void zuf_evict_inode(struct inode *inode);
struct inode *zuf_new_inode(struct inode *dir, umode_t mode,
const struct qstr *qstr, const char *symname,
ulong rdev_or_isize, bool tmpfile);
int zuf_write_inode(struct inode *inode, struct writeback_control *wbc);
int zuf_update_time(struct inode *inode, struct timespec *time, int flags);
int zuf_setattr(struct dentry *dentry, struct iattr *attr);
int zuf_getattr(const struct path *path, struct kstat *stat,
u32 request_mask, unsigned int flags);
void zuf_set_inode_flags(struct inode *inode, struct zus_inode *zi);
bool zuf_dir_emit(struct super_block *sb, struct dir_context *ctx,
ulong ino, const char *name, int length);

/* symlink.c */
uint zuf_prepare_symname(struct zufs_ioc_new_inode *ioc_new_inode,
const char *symname, ulong len, struct page *pages[2]);

/* file.c */
int zuf_isync(struct inode *inode, loff_t start, loff_t end, int datasync);

/* super.c */
int zuf_init_inodecache(void);
void zuf_destroy_inodecache(void);

void zuf_sync_inc(struct inode *inode);
void zuf_sync_dec(struct inode *inode, ulong write_unmapped);

struct dentry *zuf_mount(struct file_system_type *fs_type, int flags,
const char *dev_name, void *data);

Expand Down Expand Up @@ -56,4 +83,25 @@ int zuf_register_fs(struct super_block *sb, struct zufs_ioc_register_fs *rfs);
/* t1.c */
int zuf_pmem_mmap(struct file *file, struct vm_area_struct *vma);

/*
* Inodes and files operations
*/

/* dir.c */
extern const struct file_operations zuf_dir_operations;

/* file.c */
extern const struct inode_operations zuf_file_inode_operations;
extern const struct file_operations zuf_file_operations;

/* inode.c */
extern const struct address_space_operations zuf_aops;

/* namei.c */
extern const struct inode_operations zuf_dir_inode_operations;
extern const struct inode_operations zuf_special_inode_operations;

/* symlink.c */
extern const struct inode_operations zuf_symlink_inode_operations;

#endif /*ndef __ZUF_EXTERN_H__*/
156 changes: 156 additions & 0 deletions fs/zuf/directory.c
@@ -0,0 +1,156 @@
/*
* BRIEF DESCRIPTION
*
* File operations for directories.
*
* Copyright (c) 2018 NetApp Inc. All rights reserved.
*
* ZUFS-License: GPL-2.0 OR BSD-3-Clause. See module.c for LICENSE details.
*
* Authors:
* Boaz Harrosh <boazh@netapp.com>
* Sagi Manole <sagim@netapp.com>"
*/

#include <linux/fs.h>
#include <linux/vmalloc.h>
#include "zuf.h"

static int zuf_readdir(struct file *file, struct dir_context *ctx)
{
struct inode *inode = file_inode(file);
struct super_block *sb = inode->i_sb;
loff_t i_size = i_size_read(inode);
struct zufs_ioc_readdir ioc_readdir = {
.hdr.in_len = sizeof(ioc_readdir),
.hdr.out_len = sizeof(ioc_readdir),
.hdr.operation = ZUS_OP_READDIR,
.dir_ii = ZUII(inode)->zus_ii,
};
struct zufs_readdir_iter rdi;
struct page *pages[ZUS_API_MAP_MAX_PAGES];
struct zufs_dir_entry *zde;
void *addr, *__a;
uint nump, i;
int err;

if (ctx->pos && i_size <= ctx->pos)
return 0;
if (!i_size)
i_size = PAGE_SIZE; /* Just for the . && .. */

ioc_readdir.hdr.len = min_t(loff_t, i_size - ctx->pos,
ZUS_API_MAP_MAX_SIZE);
nump = md_o2p_up(ioc_readdir.hdr.len);
addr = vzalloc(md_p2o(nump));
if (unlikely(!addr))
return -ENOMEM;

WARN_ON((ulong)addr & (PAGE_SIZE - 1));

__a = addr;
for (i = 0; i < nump; ++i) {
pages[i] = vmalloc_to_page(__a);
__a += PAGE_SIZE;
}

more:
ioc_readdir.pos = ctx->pos;

err = zufs_dispatch(ZUF_ROOT(SBI(sb)), &ioc_readdir.hdr, pages, nump);
if (unlikely(err)) {
zuf_err("zufs_dispatch failed => %d\n", err);
goto out;
}

zufs_readdir_iter_init(&rdi, &ioc_readdir, addr);
while ((zde = zufs_next_zde(&rdi)) != NULL) {
zuf_dbg_verbose("%s pos=0x%lx\n",
zde->zstr.name, (ulong)zde->pos);
ctx->pos = zde->pos;
if (!dir_emit(ctx, zde->zstr.name, zde->zstr.len, zde->ino,
zde->type))
goto out;
}
ctx->pos = ioc_readdir.pos;
if (ioc_readdir.more) {
zuf_dbg_err("more\n");
goto more;
}
out:
vfree(addr);
return err;
}

/*
*FIXME comment to full git diff
*/

static int _dentry_dispatch(struct inode *dir, struct inode *inode,
struct qstr *str, int operation)
{
struct zufs_ioc_dentry ioc_dentry = {
.hdr.operation = operation,
.hdr.in_len = sizeof(ioc_dentry),
.hdr.out_len = sizeof(ioc_dentry),
.zus_ii = inode ? ZUII(inode)->zus_ii : NULL,
.zus_dir_ii = ZUII(dir)->zus_ii,
.str.len = str->len,
};
int err;

memcpy(&ioc_dentry.str.name, str->name, str->len);

err = zufs_dispatch(ZUF_ROOT(SBI(dir->i_sb)), &ioc_dentry.hdr, NULL, 0);
if (unlikely(err)) {
zuf_err("op=%d zufs_dispatch failed => %d\n", operation, err);
return err;
}

return 0;
}

/* return pointer to added de on success, err-code on failure */
int zuf_add_dentry(struct inode *dir, struct qstr *str, struct inode *inode,
bool rename)
{
struct zuf_inode_info *zii = ZUII(dir);
int err;

if (!str->len || !zii->zi)
return -EINVAL;

zus_inode_cmtime_now(dir, zii->zi);
err = _dentry_dispatch(dir, inode, str, ZUS_OP_ADD_DENTRY);
if (unlikely(err)) {
zuf_err("_dentry_dispatch failed => %d\n", err);
return err;
}
i_size_write(dir, le64_to_cpu(zii->zi->i_size));

return 0;
}

int zuf_remove_dentry(struct inode *dir, struct qstr *str)
{
struct zuf_inode_info *zii = ZUII(dir);
int err;

if (!str->len)
return -EINVAL;

zus_inode_cmtime_now(dir, zii->zi);
err = _dentry_dispatch(dir, NULL, str, ZUS_OP_REMOVE_DENTRY);
if (unlikely(err))
return err;

i_size_write(dir, le64_to_cpu(zii->zi->i_size));
return 0;
}

const struct file_operations zuf_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.iterate_shared = zuf_readdir,
.fsync = noop_fsync,
};

0 comments on commit 70650fc

Please sign in to comment.