diff options
author | Mike Marshall <hubcap@omnibond.com> | 2015-07-17 10:38:13 -0400 |
---|---|---|
committer | Mike Marshall <hubcap@omnibond.com> | 2015-10-03 11:39:55 -0400 |
commit | 274dcf55bd4ab12af1cc1d3b77416285bef8ebf4 (patch) | |
tree | 0b4bba244b5deccb8c853a2578e0e4c6b92d0bac /fs/orangefs/pvfs2-cache.c | |
parent | 5db11c21a929cd9d8c0484006efb1014fc723c93 (diff) | |
download | lwn-274dcf55bd4ab12af1cc1d3b77416285bef8ebf4.tar.gz lwn-274dcf55bd4ab12af1cc1d3b77416285bef8ebf4.zip |
Orangefs: kernel client part 3
Signed-off-by: Mike Marshall <hubcap@omnibond.com>
Diffstat (limited to 'fs/orangefs/pvfs2-cache.c')
-rw-r--r-- | fs/orangefs/pvfs2-cache.c | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/fs/orangefs/pvfs2-cache.c b/fs/orangefs/pvfs2-cache.c new file mode 100644 index 000000000000..15251884ba4a --- /dev/null +++ b/fs/orangefs/pvfs2-cache.c @@ -0,0 +1,260 @@ +/* + * (C) 2001 Clemson University and The University of Chicago + * + * See COPYING in top-level directory. + */ + +#include "protocol.h" +#include "pvfs2-kernel.h" + +/* tags assigned to kernel upcall operations */ +static __u64 next_tag_value; +static DEFINE_SPINLOCK(next_tag_value_lock); + +/* the pvfs2 memory caches */ + +/* a cache for pvfs2 upcall/downcall operations */ +static struct kmem_cache *op_cache; + +/* a cache for device (/dev/pvfs2-req) communication */ +static struct kmem_cache *dev_req_cache; + +/* a cache for pvfs2_kiocb objects (i.e pvfs2 iocb structures ) */ +static struct kmem_cache *pvfs2_kiocb_cache; + +int op_cache_initialize(void) +{ + op_cache = kmem_cache_create("pvfs2_op_cache", + sizeof(struct pvfs2_kernel_op_s), + 0, + PVFS2_CACHE_CREATE_FLAGS, + NULL); + + if (!op_cache) { + gossip_err("Cannot create pvfs2_op_cache\n"); + return -ENOMEM; + } + + /* initialize our atomic tag counter */ + spin_lock(&next_tag_value_lock); + next_tag_value = 100; + spin_unlock(&next_tag_value_lock); + return 0; +} + +int op_cache_finalize(void) +{ + kmem_cache_destroy(op_cache); + return 0; +} + +char *get_opname_string(struct pvfs2_kernel_op_s *new_op) +{ + if (new_op) { + __s32 type = new_op->upcall.type; + + if (type == PVFS2_VFS_OP_FILE_IO) + return "OP_FILE_IO"; + else if (type == PVFS2_VFS_OP_LOOKUP) + return "OP_LOOKUP"; + else if (type == PVFS2_VFS_OP_CREATE) + return "OP_CREATE"; + else if (type == PVFS2_VFS_OP_GETATTR) + return "OP_GETATTR"; + else if (type == PVFS2_VFS_OP_REMOVE) + return "OP_REMOVE"; + else if (type == PVFS2_VFS_OP_MKDIR) + return "OP_MKDIR"; + else if (type == PVFS2_VFS_OP_READDIR) + return "OP_READDIR"; + else if (type == PVFS2_VFS_OP_READDIRPLUS) + return "OP_READDIRPLUS"; + else if (type == PVFS2_VFS_OP_SETATTR) + return "OP_SETATTR"; + else if (type == PVFS2_VFS_OP_SYMLINK) + return "OP_SYMLINK"; + else if (type == PVFS2_VFS_OP_RENAME) + return "OP_RENAME"; + else if (type == PVFS2_VFS_OP_STATFS) + return "OP_STATFS"; + else if (type == PVFS2_VFS_OP_TRUNCATE) + return "OP_TRUNCATE"; + else if (type == PVFS2_VFS_OP_MMAP_RA_FLUSH) + return "OP_MMAP_RA_FLUSH"; + else if (type == PVFS2_VFS_OP_FS_MOUNT) + return "OP_FS_MOUNT"; + else if (type == PVFS2_VFS_OP_FS_UMOUNT) + return "OP_FS_UMOUNT"; + else if (type == PVFS2_VFS_OP_GETXATTR) + return "OP_GETXATTR"; + else if (type == PVFS2_VFS_OP_SETXATTR) + return "OP_SETXATTR"; + else if (type == PVFS2_VFS_OP_LISTXATTR) + return "OP_LISTXATTR"; + else if (type == PVFS2_VFS_OP_REMOVEXATTR) + return "OP_REMOVEXATTR"; + else if (type == PVFS2_VFS_OP_PARAM) + return "OP_PARAM"; + else if (type == PVFS2_VFS_OP_PERF_COUNT) + return "OP_PERF_COUNT"; + else if (type == PVFS2_VFS_OP_CANCEL) + return "OP_CANCEL"; + else if (type == PVFS2_VFS_OP_FSYNC) + return "OP_FSYNC"; + else if (type == PVFS2_VFS_OP_FSKEY) + return "OP_FSKEY"; + else if (type == PVFS2_VFS_OP_FILE_IOX) + return "OP_FILE_IOX"; + } + return "OP_UNKNOWN?"; +} + +static struct pvfs2_kernel_op_s *op_alloc_common(__s32 op_linger, __s32 type) +{ + struct pvfs2_kernel_op_s *new_op = NULL; + + new_op = kmem_cache_alloc(op_cache, PVFS2_CACHE_ALLOC_FLAGS); + if (new_op) { + memset(new_op, 0, sizeof(struct pvfs2_kernel_op_s)); + + INIT_LIST_HEAD(&new_op->list); + spin_lock_init(&new_op->lock); + init_waitqueue_head(&new_op->waitq); + + init_waitqueue_head(&new_op->io_completion_waitq); + atomic_set(&new_op->aio_ref_count, 0); + + pvfs2_op_initialize(new_op); + + /* initialize the op specific tag and upcall credentials */ + spin_lock(&next_tag_value_lock); + new_op->tag = next_tag_value++; + if (next_tag_value == 0) + next_tag_value = 100; + spin_unlock(&next_tag_value_lock); + new_op->upcall.type = type; + new_op->attempts = 0; + gossip_debug(GOSSIP_CACHE_DEBUG, + "Alloced OP (%p: %llu %s)\n", + new_op, + llu(new_op->tag), + get_opname_string(new_op)); + + new_op->upcall.uid = from_kuid(current_user_ns(), + current_fsuid()); + + new_op->upcall.gid = from_kgid(current_user_ns(), + current_fsgid()); + + new_op->op_linger = new_op->op_linger_tmp = op_linger; + } else { + gossip_err("op_alloc: kmem_cache_alloc failed!\n"); + } + return new_op; +} + +struct pvfs2_kernel_op_s *op_alloc(__s32 type) +{ + return op_alloc_common(1, type); +} + +struct pvfs2_kernel_op_s *op_alloc_trailer(__s32 type) +{ + return op_alloc_common(2, type); +} + +void op_release(struct pvfs2_kernel_op_s *pvfs2_op) +{ + if (pvfs2_op) { + gossip_debug(GOSSIP_CACHE_DEBUG, + "Releasing OP (%p: %llu)\n", + pvfs2_op, + llu(pvfs2_op->tag)); + pvfs2_op_initialize(pvfs2_op); + kmem_cache_free(op_cache, pvfs2_op); + } else { + gossip_err("NULL pointer in op_release\n"); + } +} + +int dev_req_cache_initialize(void) +{ + dev_req_cache = kmem_cache_create("pvfs2_devreqcache", + MAX_ALIGNED_DEV_REQ_DOWNSIZE, + 0, + PVFS2_CACHE_CREATE_FLAGS, + NULL); + + if (!dev_req_cache) { + gossip_err("Cannot create pvfs2_dev_req_cache\n"); + return -ENOMEM; + } + return 0; +} + +int dev_req_cache_finalize(void) +{ + kmem_cache_destroy(dev_req_cache); + return 0; +} + +void *dev_req_alloc(void) +{ + void *buffer; + + buffer = kmem_cache_alloc(dev_req_cache, PVFS2_CACHE_ALLOC_FLAGS); + if (buffer == NULL) + gossip_err("Failed to allocate from dev_req_cache\n"); + else + memset(buffer, 0, sizeof(MAX_ALIGNED_DEV_REQ_DOWNSIZE)); + return buffer; +} + +void dev_req_release(void *buffer) +{ + if (buffer) + kmem_cache_free(dev_req_cache, buffer); + else + gossip_err("NULL pointer passed to dev_req_release\n"); +} + +int kiocb_cache_initialize(void) +{ + pvfs2_kiocb_cache = kmem_cache_create("pvfs2_kiocbcache", + sizeof(struct pvfs2_kiocb_s), + 0, + PVFS2_CACHE_CREATE_FLAGS, + NULL); + + if (!pvfs2_kiocb_cache) { + gossip_err("Cannot create pvfs2_kiocb_cache!\n"); + return -ENOMEM; + } + return 0; +} + +int kiocb_cache_finalize(void) +{ + kmem_cache_destroy(pvfs2_kiocb_cache); + return 0; +} + +struct pvfs2_kiocb_s *kiocb_alloc(void) +{ + struct pvfs2_kiocb_s *x = NULL; + + x = kmem_cache_alloc(pvfs2_kiocb_cache, PVFS2_CACHE_ALLOC_FLAGS); + if (x == NULL) + gossip_err("kiocb_alloc: kmem_cache_alloc failed!\n"); + else + memset(x, 0, sizeof(struct pvfs2_kiocb_s)); + return x; +} + +void kiocb_release(struct pvfs2_kiocb_s *x) +{ + if (x) + kmem_cache_free(pvfs2_kiocb_cache, x); + else + gossip_err("kiocb_release: kmem_cache_free NULL pointer!\n"); +} |