162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * (C) 2001 Clemson University and The University of Chicago 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * See COPYING in top-level directory. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "protocol.h" 962306a36Sopenharmony_ci#include "orangefs-kernel.h" 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci/* tags assigned to kernel upcall operations */ 1262306a36Sopenharmony_cistatic __u64 next_tag_value; 1362306a36Sopenharmony_cistatic DEFINE_SPINLOCK(next_tag_value_lock); 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci/* the orangefs memory caches */ 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/* a cache for orangefs upcall/downcall operations */ 1862306a36Sopenharmony_cistatic struct kmem_cache *op_cache; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ciint op_cache_initialize(void) 2162306a36Sopenharmony_ci{ 2262306a36Sopenharmony_ci op_cache = kmem_cache_create("orangefs_op_cache", 2362306a36Sopenharmony_ci sizeof(struct orangefs_kernel_op_s), 2462306a36Sopenharmony_ci 0, 2562306a36Sopenharmony_ci ORANGEFS_CACHE_CREATE_FLAGS, 2662306a36Sopenharmony_ci NULL); 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci if (!op_cache) { 2962306a36Sopenharmony_ci gossip_err("Cannot create orangefs_op_cache\n"); 3062306a36Sopenharmony_ci return -ENOMEM; 3162306a36Sopenharmony_ci } 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci /* initialize our atomic tag counter */ 3462306a36Sopenharmony_ci spin_lock(&next_tag_value_lock); 3562306a36Sopenharmony_ci next_tag_value = 100; 3662306a36Sopenharmony_ci spin_unlock(&next_tag_value_lock); 3762306a36Sopenharmony_ci return 0; 3862306a36Sopenharmony_ci} 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ciint op_cache_finalize(void) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci kmem_cache_destroy(op_cache); 4362306a36Sopenharmony_ci return 0; 4462306a36Sopenharmony_ci} 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cichar *get_opname_string(struct orangefs_kernel_op_s *new_op) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci if (new_op) { 4962306a36Sopenharmony_ci __s32 type = new_op->upcall.type; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci if (type == ORANGEFS_VFS_OP_FILE_IO) 5262306a36Sopenharmony_ci return "OP_FILE_IO"; 5362306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_LOOKUP) 5462306a36Sopenharmony_ci return "OP_LOOKUP"; 5562306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_CREATE) 5662306a36Sopenharmony_ci return "OP_CREATE"; 5762306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_GETATTR) 5862306a36Sopenharmony_ci return "OP_GETATTR"; 5962306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_REMOVE) 6062306a36Sopenharmony_ci return "OP_REMOVE"; 6162306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_MKDIR) 6262306a36Sopenharmony_ci return "OP_MKDIR"; 6362306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_READDIR) 6462306a36Sopenharmony_ci return "OP_READDIR"; 6562306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_READDIRPLUS) 6662306a36Sopenharmony_ci return "OP_READDIRPLUS"; 6762306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_SETATTR) 6862306a36Sopenharmony_ci return "OP_SETATTR"; 6962306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_SYMLINK) 7062306a36Sopenharmony_ci return "OP_SYMLINK"; 7162306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_RENAME) 7262306a36Sopenharmony_ci return "OP_RENAME"; 7362306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_STATFS) 7462306a36Sopenharmony_ci return "OP_STATFS"; 7562306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_TRUNCATE) 7662306a36Sopenharmony_ci return "OP_TRUNCATE"; 7762306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_RA_FLUSH) 7862306a36Sopenharmony_ci return "OP_RA_FLUSH"; 7962306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_FS_MOUNT) 8062306a36Sopenharmony_ci return "OP_FS_MOUNT"; 8162306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_FS_UMOUNT) 8262306a36Sopenharmony_ci return "OP_FS_UMOUNT"; 8362306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_GETXATTR) 8462306a36Sopenharmony_ci return "OP_GETXATTR"; 8562306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_SETXATTR) 8662306a36Sopenharmony_ci return "OP_SETXATTR"; 8762306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_LISTXATTR) 8862306a36Sopenharmony_ci return "OP_LISTXATTR"; 8962306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_REMOVEXATTR) 9062306a36Sopenharmony_ci return "OP_REMOVEXATTR"; 9162306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_PARAM) 9262306a36Sopenharmony_ci return "OP_PARAM"; 9362306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_PERF_COUNT) 9462306a36Sopenharmony_ci return "OP_PERF_COUNT"; 9562306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_CANCEL) 9662306a36Sopenharmony_ci return "OP_CANCEL"; 9762306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_FSYNC) 9862306a36Sopenharmony_ci return "OP_FSYNC"; 9962306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_FSKEY) 10062306a36Sopenharmony_ci return "OP_FSKEY"; 10162306a36Sopenharmony_ci else if (type == ORANGEFS_VFS_OP_FEATURES) 10262306a36Sopenharmony_ci return "OP_FEATURES"; 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci return "OP_UNKNOWN?"; 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_civoid orangefs_new_tag(struct orangefs_kernel_op_s *op) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci spin_lock(&next_tag_value_lock); 11062306a36Sopenharmony_ci op->tag = next_tag_value++; 11162306a36Sopenharmony_ci if (next_tag_value == 0) 11262306a36Sopenharmony_ci next_tag_value = 100; 11362306a36Sopenharmony_ci spin_unlock(&next_tag_value_lock); 11462306a36Sopenharmony_ci} 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_cistruct orangefs_kernel_op_s *op_alloc(__s32 type) 11762306a36Sopenharmony_ci{ 11862306a36Sopenharmony_ci struct orangefs_kernel_op_s *new_op = NULL; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci new_op = kmem_cache_zalloc(op_cache, GFP_KERNEL); 12162306a36Sopenharmony_ci if (new_op) { 12262306a36Sopenharmony_ci INIT_LIST_HEAD(&new_op->list); 12362306a36Sopenharmony_ci spin_lock_init(&new_op->lock); 12462306a36Sopenharmony_ci init_completion(&new_op->waitq); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci new_op->upcall.type = ORANGEFS_VFS_OP_INVALID; 12762306a36Sopenharmony_ci new_op->downcall.type = ORANGEFS_VFS_OP_INVALID; 12862306a36Sopenharmony_ci new_op->downcall.status = -1; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci new_op->op_state = OP_VFS_STATE_UNKNOWN; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci /* initialize the op specific tag and upcall credentials */ 13362306a36Sopenharmony_ci orangefs_new_tag(new_op); 13462306a36Sopenharmony_ci new_op->upcall.type = type; 13562306a36Sopenharmony_ci new_op->attempts = 0; 13662306a36Sopenharmony_ci gossip_debug(GOSSIP_CACHE_DEBUG, 13762306a36Sopenharmony_ci "Alloced OP (%p: %llu %s)\n", 13862306a36Sopenharmony_ci new_op, 13962306a36Sopenharmony_ci llu(new_op->tag), 14062306a36Sopenharmony_ci get_opname_string(new_op)); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci new_op->upcall.uid = from_kuid(&init_user_ns, 14362306a36Sopenharmony_ci current_fsuid()); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci new_op->upcall.gid = from_kgid(&init_user_ns, 14662306a36Sopenharmony_ci current_fsgid()); 14762306a36Sopenharmony_ci } else { 14862306a36Sopenharmony_ci gossip_err("op_alloc: kmem_cache_zalloc failed!\n"); 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci return new_op; 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_civoid op_release(struct orangefs_kernel_op_s *orangefs_op) 15462306a36Sopenharmony_ci{ 15562306a36Sopenharmony_ci if (orangefs_op) { 15662306a36Sopenharmony_ci gossip_debug(GOSSIP_CACHE_DEBUG, 15762306a36Sopenharmony_ci "Releasing OP (%p: %llu)\n", 15862306a36Sopenharmony_ci orangefs_op, 15962306a36Sopenharmony_ci llu(orangefs_op->tag)); 16062306a36Sopenharmony_ci kmem_cache_free(op_cache, orangefs_op); 16162306a36Sopenharmony_ci } else { 16262306a36Sopenharmony_ci gossip_err("NULL pointer in op_release\n"); 16362306a36Sopenharmony_ci } 16462306a36Sopenharmony_ci} 165