hc
2024-05-10 10ebd8556b7990499c896a550e3d416b444211e6
kernel/fs/orangefs/xattr.c
....@@ -1,6 +1,7 @@
11 // SPDX-License-Identifier: GPL-2.0
22 /*
33 * (C) 2001 Clemson University and The University of Chicago
4
+ * Copyright 2018 Omnibond Systems, L.L.C.
45 *
56 * See COPYING in top-level directory.
67 */
....@@ -14,7 +15,7 @@
1415 #include "orangefs-bufmap.h"
1516 #include <linux/posix_acl_xattr.h>
1617 #include <linux/xattr.h>
17
-
18
+#include <linux/hashtable.h>
1819
1920 #define SYSTEM_ORANGEFS_KEY "system.pvfs2."
2021 #define SYSTEM_ORANGEFS_KEY_LEN 13
....@@ -50,6 +51,35 @@
5051 return internal_flag;
5152 }
5253
54
+static unsigned int xattr_key(const char *key)
55
+{
56
+ unsigned int i = 0;
57
+ while (key)
58
+ i += *key++;
59
+ return i % 16;
60
+}
61
+
62
+static struct orangefs_cached_xattr *find_cached_xattr(struct inode *inode,
63
+ const char *key)
64
+{
65
+ struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
66
+ struct orangefs_cached_xattr *cx;
67
+ struct hlist_head *h;
68
+ struct hlist_node *tmp;
69
+ h = &orangefs_inode->xattr_cache[xattr_key(key)];
70
+ if (hlist_empty(h))
71
+ return NULL;
72
+ hlist_for_each_entry_safe(cx, tmp, h, node) {
73
+/* if (!time_before(jiffies, cx->timeout)) {
74
+ hlist_del(&cx->node);
75
+ kfree(cx);
76
+ continue;
77
+ }*/
78
+ if (!strcmp(cx->key, key))
79
+ return cx;
80
+ }
81
+ return NULL;
82
+}
5383
5484 /*
5585 * Tries to get a specified key's attributes of a given
....@@ -65,6 +95,7 @@
6595 {
6696 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
6797 struct orangefs_kernel_op_s *new_op = NULL;
98
+ struct orangefs_cached_xattr *cx;
6899 ssize_t ret = -ENOMEM;
69100 ssize_t length = 0;
70101 int fsuid;
....@@ -93,6 +124,27 @@
93124
94125 down_read(&orangefs_inode->xattr_sem);
95126
127
+ cx = find_cached_xattr(inode, name);
128
+ if (cx && time_before(jiffies, cx->timeout)) {
129
+ if (cx->length == -1) {
130
+ ret = -ENODATA;
131
+ goto out_unlock;
132
+ } else {
133
+ if (size == 0) {
134
+ ret = cx->length;
135
+ goto out_unlock;
136
+ }
137
+ if (cx->length > size) {
138
+ ret = -ERANGE;
139
+ goto out_unlock;
140
+ }
141
+ memcpy(buffer, cx->val, cx->length);
142
+ memset(buffer + cx->length, 0, size - cx->length);
143
+ ret = cx->length;
144
+ goto out_unlock;
145
+ }
146
+ }
147
+
96148 new_op = op_alloc(ORANGEFS_VFS_OP_GETXATTR);
97149 if (!new_op)
98150 goto out_unlock;
....@@ -117,6 +169,15 @@
117169 " does not exist!\n",
118170 get_khandle_from_ino(inode),
119171 (char *)new_op->upcall.req.getxattr.key);
172
+ cx = kmalloc(sizeof *cx, GFP_KERNEL);
173
+ if (cx) {
174
+ strcpy(cx->key, name);
175
+ cx->length = -1;
176
+ cx->timeout = jiffies +
177
+ orangefs_getattr_timeout_msecs*HZ/1000;
178
+ hash_add(orangefs_inode->xattr_cache, &cx->node,
179
+ xattr_key(cx->key));
180
+ }
120181 }
121182 goto out_release_op;
122183 }
....@@ -156,6 +217,23 @@
156217
157218 ret = length;
158219
220
+ if (cx) {
221
+ strcpy(cx->key, name);
222
+ memcpy(cx->val, buffer, length);
223
+ cx->length = length;
224
+ cx->timeout = jiffies + HZ;
225
+ } else {
226
+ cx = kmalloc(sizeof *cx, GFP_KERNEL);
227
+ if (cx) {
228
+ strcpy(cx->key, name);
229
+ memcpy(cx->val, buffer, length);
230
+ cx->length = length;
231
+ cx->timeout = jiffies + HZ;
232
+ hash_add(orangefs_inode->xattr_cache, &cx->node,
233
+ xattr_key(cx->key));
234
+ }
235
+ }
236
+
159237 out_release_op:
160238 op_release(new_op);
161239 out_unlock:
....@@ -168,6 +246,9 @@
168246 {
169247 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
170248 struct orangefs_kernel_op_s *new_op = NULL;
249
+ struct orangefs_cached_xattr *cx;
250
+ struct hlist_head *h;
251
+ struct hlist_node *tmp;
171252 int ret = -ENOMEM;
172253
173254 if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN)
....@@ -209,6 +290,16 @@
209290 "orangefs_inode_removexattr: returning %d\n", ret);
210291
211292 op_release(new_op);
293
+
294
+ h = &orangefs_inode->xattr_cache[xattr_key(name)];
295
+ hlist_for_each_entry_safe(cx, tmp, h, node) {
296
+ if (!strcmp(cx->key, name)) {
297
+ hlist_del(&cx->node);
298
+ kfree(cx);
299
+ break;
300
+ }
301
+ }
302
+
212303 out_unlock:
213304 up_write(&orangefs_inode->xattr_sem);
214305 return ret;
....@@ -226,6 +317,9 @@
226317 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
227318 struct orangefs_kernel_op_s *new_op;
228319 int internal_flag = 0;
320
+ struct orangefs_cached_xattr *cx;
321
+ struct hlist_head *h;
322
+ struct hlist_node *tmp;
229323 int ret = -ENOMEM;
230324
231325 gossip_debug(GOSSIP_XATTR_DEBUG,
....@@ -287,6 +381,16 @@
287381
288382 /* when request is serviced properly, free req op struct */
289383 op_release(new_op);
384
+
385
+ h = &orangefs_inode->xattr_cache[xattr_key(name)];
386
+ hlist_for_each_entry_safe(cx, tmp, h, node) {
387
+ if (!strcmp(cx->key, name)) {
388
+ hlist_del(&cx->node);
389
+ kfree(cx);
390
+ break;
391
+ }
392
+ }
393
+
290394 out_unlock:
291395 up_write(&orangefs_inode->xattr_sem);
292396 return ret;
....@@ -437,7 +541,8 @@
437541 struct inode *inode,
438542 const char *name,
439543 void *buffer,
440
- size_t size)
544
+ size_t size,
545
+ int flags)
441546 {
442547 return orangefs_inode_getxattr(inode, name, buffer, size);
443548