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(name: "orangefs_op_cache" , |
23 | size: sizeof(struct orangefs_kernel_op_s), |
24 | align: 0, |
25 | ORANGEFS_CACHE_CREATE_FLAGS, |
26 | NULL); |
27 | |
28 | if (!op_cache) { |
29 | gossip_err("Cannot create orangefs_op_cache\n" ); |
30 | return -ENOMEM; |
31 | } |
32 | |
33 | /* initialize our atomic tag counter */ |
34 | spin_lock(lock: &next_tag_value_lock); |
35 | next_tag_value = 100; |
36 | spin_unlock(lock: &next_tag_value_lock); |
37 | return 0; |
38 | } |
39 | |
40 | int op_cache_finalize(void) |
41 | { |
42 | kmem_cache_destroy(s: op_cache); |
43 | return 0; |
44 | } |
45 | |
46 | char *get_opname_string(struct orangefs_kernel_op_s *new_op) |
47 | { |
48 | if (new_op) { |
49 | __s32 type = new_op->upcall.type; |
50 | |
51 | if (type == ORANGEFS_VFS_OP_FILE_IO) |
52 | return "OP_FILE_IO" ; |
53 | else if (type == ORANGEFS_VFS_OP_LOOKUP) |
54 | return "OP_LOOKUP" ; |
55 | else if (type == ORANGEFS_VFS_OP_CREATE) |
56 | return "OP_CREATE" ; |
57 | else if (type == ORANGEFS_VFS_OP_GETATTR) |
58 | return "OP_GETATTR" ; |
59 | else if (type == ORANGEFS_VFS_OP_REMOVE) |
60 | return "OP_REMOVE" ; |
61 | else if (type == ORANGEFS_VFS_OP_MKDIR) |
62 | return "OP_MKDIR" ; |
63 | else if (type == ORANGEFS_VFS_OP_READDIR) |
64 | return "OP_READDIR" ; |
65 | else if (type == ORANGEFS_VFS_OP_READDIRPLUS) |
66 | return "OP_READDIRPLUS" ; |
67 | else if (type == ORANGEFS_VFS_OP_SETATTR) |
68 | return "OP_SETATTR" ; |
69 | else if (type == ORANGEFS_VFS_OP_SYMLINK) |
70 | return "OP_SYMLINK" ; |
71 | else if (type == ORANGEFS_VFS_OP_RENAME) |
72 | return "OP_RENAME" ; |
73 | else if (type == ORANGEFS_VFS_OP_STATFS) |
74 | return "OP_STATFS" ; |
75 | else if (type == ORANGEFS_VFS_OP_TRUNCATE) |
76 | return "OP_TRUNCATE" ; |
77 | else if (type == ORANGEFS_VFS_OP_RA_FLUSH) |
78 | return "OP_RA_FLUSH" ; |
79 | else if (type == ORANGEFS_VFS_OP_FS_MOUNT) |
80 | return "OP_FS_MOUNT" ; |
81 | else if (type == ORANGEFS_VFS_OP_FS_UMOUNT) |
82 | return "OP_FS_UMOUNT" ; |
83 | else if (type == ORANGEFS_VFS_OP_GETXATTR) |
84 | return "OP_GETXATTR" ; |
85 | else if (type == ORANGEFS_VFS_OP_SETXATTR) |
86 | return "OP_SETXATTR" ; |
87 | else if (type == ORANGEFS_VFS_OP_LISTXATTR) |
88 | return "OP_LISTXATTR" ; |
89 | else if (type == ORANGEFS_VFS_OP_REMOVEXATTR) |
90 | return "OP_REMOVEXATTR" ; |
91 | else if (type == ORANGEFS_VFS_OP_PARAM) |
92 | return "OP_PARAM" ; |
93 | else if (type == ORANGEFS_VFS_OP_PERF_COUNT) |
94 | return "OP_PERF_COUNT" ; |
95 | else if (type == ORANGEFS_VFS_OP_CANCEL) |
96 | return "OP_CANCEL" ; |
97 | else if (type == ORANGEFS_VFS_OP_FSYNC) |
98 | return "OP_FSYNC" ; |
99 | else if (type == ORANGEFS_VFS_OP_FSKEY) |
100 | return "OP_FSKEY" ; |
101 | else if (type == ORANGEFS_VFS_OP_FEATURES) |
102 | return "OP_FEATURES" ; |
103 | } |
104 | return "OP_UNKNOWN?" ; |
105 | } |
106 | |
107 | void orangefs_new_tag(struct orangefs_kernel_op_s *op) |
108 | { |
109 | spin_lock(lock: &next_tag_value_lock); |
110 | op->tag = next_tag_value++; |
111 | if (next_tag_value == 0) |
112 | next_tag_value = 100; |
113 | spin_unlock(lock: &next_tag_value_lock); |
114 | } |
115 | |
116 | struct orangefs_kernel_op_s *op_alloc(__s32 type) |
117 | { |
118 | struct orangefs_kernel_op_s *new_op = NULL; |
119 | |
120 | new_op = kmem_cache_zalloc(k: op_cache, GFP_KERNEL); |
121 | if (new_op) { |
122 | INIT_LIST_HEAD(list: &new_op->list); |
123 | spin_lock_init(&new_op->lock); |
124 | init_completion(x: &new_op->waitq); |
125 | |
126 | new_op->upcall.type = ORANGEFS_VFS_OP_INVALID; |
127 | new_op->downcall.type = ORANGEFS_VFS_OP_INVALID; |
128 | new_op->downcall.status = -1; |
129 | |
130 | new_op->op_state = OP_VFS_STATE_UNKNOWN; |
131 | |
132 | /* initialize the op specific tag and upcall credentials */ |
133 | orangefs_new_tag(op: new_op); |
134 | new_op->upcall.type = type; |
135 | new_op->attempts = 0; |
136 | gossip_debug(GOSSIP_CACHE_DEBUG, |
137 | "Alloced OP (%p: %llu %s)\n" , |
138 | new_op, |
139 | llu(new_op->tag), |
140 | get_opname_string(new_op)); |
141 | |
142 | new_op->upcall.uid = from_kuid(to: &init_user_ns, |
143 | current_fsuid()); |
144 | |
145 | new_op->upcall.gid = from_kgid(to: &init_user_ns, |
146 | current_fsgid()); |
147 | } else { |
148 | gossip_err("op_alloc: kmem_cache_zalloc failed!\n" ); |
149 | } |
150 | return new_op; |
151 | } |
152 | |
153 | void op_release(struct orangefs_kernel_op_s *orangefs_op) |
154 | { |
155 | if (orangefs_op) { |
156 | gossip_debug(GOSSIP_CACHE_DEBUG, |
157 | "Releasing OP (%p: %llu)\n" , |
158 | orangefs_op, |
159 | llu(orangefs_op->tag)); |
160 | kmem_cache_free(s: op_cache, objp: orangefs_op); |
161 | } else { |
162 | gossip_err("NULL pointer in op_release\n" ); |
163 | } |
164 | } |
165 | |