1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * (C) 2001 Clemson University and The University of Chicago 4 * 5 * See COPYING in top-level directory. 6 */ 7 8 #include "protocol.h" 9 #include "orangefs-kernel.h" 10 11 /* tags assigned to kernel upcall operations */ 12 static __u64 next_tag_value; 13 static DEFINE_SPINLOCK(next_tag_value_lock); 14 15 /* the orangefs memory caches */ 16 17 /* a cache for orangefs upcall/downcall operations */ 18 static struct kmem_cache *op_cache; 19 20 int op_cache_initialize(void) 21 { 22 op_cache = kmem_cache_create_usercopy("orangefs_op_cache", 23 sizeof(struct orangefs_kernel_op_s), 24 0, 25 0, 26 offsetof(struct orangefs_kernel_op_s, tag), 27 offsetof(struct orangefs_kernel_op_s, upcall) + 28 sizeof(struct orangefs_upcall_s) - 29 offsetof(struct orangefs_kernel_op_s, tag), 30 NULL); 31 32 if (!op_cache) { 33 gossip_err("Cannot create orangefs_op_cache\n"); 34 return -ENOMEM; 35 } 36 37 /* initialize our atomic tag counter */ 38 spin_lock(&next_tag_value_lock); 39 next_tag_value = 100; 40 spin_unlock(&next_tag_value_lock); 41 return 0; 42 } 43 44 int op_cache_finalize(void) 45 { 46 kmem_cache_destroy(op_cache); 47 return 0; 48 } 49 50 char *get_opname_string(struct orangefs_kernel_op_s *new_op) 51 { 52 if (new_op) { 53 __s32 type = new_op->upcall.type; 54 55 if (type == ORANGEFS_VFS_OP_FILE_IO) 56 return "OP_FILE_IO"; 57 else if (type == ORANGEFS_VFS_OP_LOOKUP) 58 return "OP_LOOKUP"; 59 else if (type == ORANGEFS_VFS_OP_CREATE) 60 return "OP_CREATE"; 61 else if (type == ORANGEFS_VFS_OP_GETATTR) 62 return "OP_GETATTR"; 63 else if (type == ORANGEFS_VFS_OP_REMOVE) 64 return "OP_REMOVE"; 65 else if (type == ORANGEFS_VFS_OP_MKDIR) 66 return "OP_MKDIR"; 67 else if (type == ORANGEFS_VFS_OP_READDIR) 68 return "OP_READDIR"; 69 else if (type == ORANGEFS_VFS_OP_READDIRPLUS) 70 return "OP_READDIRPLUS"; 71 else if (type == ORANGEFS_VFS_OP_SETATTR) 72 return "OP_SETATTR"; 73 else if (type == ORANGEFS_VFS_OP_SYMLINK) 74 return "OP_SYMLINK"; 75 else if (type == ORANGEFS_VFS_OP_RENAME) 76 return "OP_RENAME"; 77 else if (type == ORANGEFS_VFS_OP_STATFS) 78 return "OP_STATFS"; 79 else if (type == ORANGEFS_VFS_OP_TRUNCATE) 80 return "OP_TRUNCATE"; 81 else if (type == ORANGEFS_VFS_OP_RA_FLUSH) 82 return "OP_RA_FLUSH"; 83 else if (type == ORANGEFS_VFS_OP_FS_MOUNT) 84 return "OP_FS_MOUNT"; 85 else if (type == ORANGEFS_VFS_OP_FS_UMOUNT) 86 return "OP_FS_UMOUNT"; 87 else if (type == ORANGEFS_VFS_OP_GETXATTR) 88 return "OP_GETXATTR"; 89 else if (type == ORANGEFS_VFS_OP_SETXATTR) 90 return "OP_SETXATTR"; 91 else if (type == ORANGEFS_VFS_OP_LISTXATTR) 92 return "OP_LISTXATTR"; 93 else if (type == ORANGEFS_VFS_OP_REMOVEXATTR) 94 return "OP_REMOVEXATTR"; 95 else if (type == ORANGEFS_VFS_OP_PARAM) 96 return "OP_PARAM"; 97 else if (type == ORANGEFS_VFS_OP_PERF_COUNT) 98 return "OP_PERF_COUNT"; 99 else if (type == ORANGEFS_VFS_OP_CANCEL) 100 return "OP_CANCEL"; 101 else if (type == ORANGEFS_VFS_OP_FSYNC) 102 return "OP_FSYNC"; 103 else if (type == ORANGEFS_VFS_OP_FSKEY) 104 return "OP_FSKEY"; 105 else if (type == ORANGEFS_VFS_OP_FEATURES) 106 return "OP_FEATURES"; 107 } 108 return "OP_UNKNOWN?"; 109 } 110 111 void orangefs_new_tag(struct orangefs_kernel_op_s *op) 112 { 113 spin_lock(&next_tag_value_lock); 114 op->tag = next_tag_value++; 115 if (next_tag_value == 0) 116 next_tag_value = 100; 117 spin_unlock(&next_tag_value_lock); 118 } 119 120 struct orangefs_kernel_op_s *op_alloc(__s32 type) 121 { 122 struct orangefs_kernel_op_s *new_op = NULL; 123 124 new_op = kmem_cache_zalloc(op_cache, GFP_KERNEL); 125 if (new_op) { 126 INIT_LIST_HEAD(&new_op->list); 127 spin_lock_init(&new_op->lock); 128 init_completion(&new_op->waitq); 129 130 new_op->upcall.type = ORANGEFS_VFS_OP_INVALID; 131 new_op->downcall.type = ORANGEFS_VFS_OP_INVALID; 132 new_op->downcall.status = -1; 133 134 new_op->op_state = OP_VFS_STATE_UNKNOWN; 135 136 /* initialize the op specific tag and upcall credentials */ 137 orangefs_new_tag(new_op); 138 new_op->upcall.type = type; 139 new_op->attempts = 0; 140 gossip_debug(GOSSIP_CACHE_DEBUG, 141 "Alloced OP (%p: %llu %s)\n", 142 new_op, 143 llu(new_op->tag), 144 get_opname_string(new_op)); 145 146 new_op->upcall.uid = from_kuid(&init_user_ns, 147 current_fsuid()); 148 149 new_op->upcall.gid = from_kgid(&init_user_ns, 150 current_fsgid()); 151 } else { 152 gossip_err("op_alloc: kmem_cache_zalloc failed!\n"); 153 } 154 return new_op; 155 } 156 157 void op_release(struct orangefs_kernel_op_s *orangefs_op) 158 { 159 if (orangefs_op) { 160 gossip_debug(GOSSIP_CACHE_DEBUG, 161 "Releasing OP (%p: %llu)\n", 162 orangefs_op, 163 llu(orangefs_op->tag)); 164 kmem_cache_free(op_cache, orangefs_op); 165 } else { 166 gossip_err("NULL pointer in op_release\n"); 167 } 168 } 169