hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/fs/ceph/xattr.c
....@@ -8,6 +8,7 @@
88 #include <linux/ceph/decode.h>
99
1010 #include <linux/xattr.h>
11
+#include <linux/security.h>
1112 #include <linux/posix_acl_xattr.h>
1213 #include <linux/slab.h>
1314
....@@ -17,26 +18,10 @@
1718 static int __remove_xattr(struct ceph_inode_info *ci,
1819 struct ceph_inode_xattr *xattr);
1920
20
-static const struct xattr_handler ceph_other_xattr_handler;
21
-
22
-/*
23
- * List of handlers for synthetic system.* attributes. Other
24
- * attributes are handled directly.
25
- */
26
-const struct xattr_handler *ceph_xattr_handlers[] = {
27
-#ifdef CONFIG_CEPH_FS_POSIX_ACL
28
- &posix_acl_access_xattr_handler,
29
- &posix_acl_default_xattr_handler,
30
-#endif
31
- &ceph_other_xattr_handler,
32
- NULL,
33
-};
34
-
3521 static bool ceph_is_valid_xattr(const char *name)
3622 {
37
- return !strncmp(name, XATTR_CEPH_PREFIX, XATTR_CEPH_PREFIX_LEN) ||
38
- !strncmp(name, XATTR_SECURITY_PREFIX,
39
- XATTR_SECURITY_PREFIX_LEN) ||
23
+ return !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) ||
24
+ !strncmp(name, XATTR_CEPH_PREFIX, XATTR_CEPH_PREFIX_LEN) ||
4025 !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) ||
4126 !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
4227 }
....@@ -48,8 +33,8 @@
4833 struct ceph_vxattr {
4934 char *name;
5035 size_t name_size; /* strlen(name) + 1 (for '\0') */
51
- size_t (*getxattr_cb)(struct ceph_inode_info *ci, char *val,
52
- size_t size);
36
+ ssize_t (*getxattr_cb)(struct ceph_inode_info *ci, char *val,
37
+ size_t size);
5338 bool (*exists_cb)(struct ceph_inode_info *ci);
5439 unsigned int flags;
5540 };
....@@ -68,8 +53,8 @@
6853 rcu_dereference_raw(fl->pool_ns) != NULL);
6954 }
7055
71
-static size_t ceph_vxattrcb_layout(struct ceph_inode_info *ci, char *val,
72
- size_t size)
56
+static ssize_t ceph_vxattrcb_layout(struct ceph_inode_info *ci, char *val,
57
+ size_t size)
7358 {
7459 struct ceph_fs_client *fsc = ceph_sb_to_client(ci->vfs_inode.i_sb);
7560 struct ceph_osd_client *osdc = &fsc->client->osdc;
....@@ -96,7 +81,7 @@
9681 len = snprintf(buf, sizeof(buf),
9782 "stripe_unit=%u stripe_count=%u object_size=%u pool=%lld",
9883 ci->i_layout.stripe_unit, ci->i_layout.stripe_count,
99
- ci->i_layout.object_size, (unsigned long long)pool);
84
+ ci->i_layout.object_size, pool);
10085 total_len = len;
10186 }
10287
....@@ -125,28 +110,56 @@
125110 return ret;
126111 }
127112
128
-static size_t ceph_vxattrcb_layout_stripe_unit(struct ceph_inode_info *ci,
129
- char *val, size_t size)
130
-{
131
- return snprintf(val, size, "%u", ci->i_layout.stripe_unit);
132
-}
133
-
134
-static size_t ceph_vxattrcb_layout_stripe_count(struct ceph_inode_info *ci,
135
- char *val, size_t size)
136
-{
137
- return snprintf(val, size, "%u", ci->i_layout.stripe_count);
138
-}
139
-
140
-static size_t ceph_vxattrcb_layout_object_size(struct ceph_inode_info *ci,
141
- char *val, size_t size)
142
-{
143
- return snprintf(val, size, "%u", ci->i_layout.object_size);
144
-}
145
-
146
-static size_t ceph_vxattrcb_layout_pool(struct ceph_inode_info *ci,
147
- char *val, size_t size)
113
+/*
114
+ * The convention with strings in xattrs is that they should not be NULL
115
+ * terminated, since we're returning the length with them. snprintf always
116
+ * NULL terminates however, so call it on a temporary buffer and then memcpy
117
+ * the result into place.
118
+ */
119
+static __printf(3, 4)
120
+int ceph_fmt_xattr(char *val, size_t size, const char *fmt, ...)
148121 {
149122 int ret;
123
+ va_list args;
124
+ char buf[96]; /* NB: reevaluate size if new vxattrs are added */
125
+
126
+ va_start(args, fmt);
127
+ ret = vsnprintf(buf, size ? sizeof(buf) : 0, fmt, args);
128
+ va_end(args);
129
+
130
+ /* Sanity check */
131
+ if (size && ret + 1 > sizeof(buf)) {
132
+ WARN_ONCE(true, "Returned length too big (%d)", ret);
133
+ return -E2BIG;
134
+ }
135
+
136
+ if (ret <= size)
137
+ memcpy(val, buf, ret);
138
+ return ret;
139
+}
140
+
141
+static ssize_t ceph_vxattrcb_layout_stripe_unit(struct ceph_inode_info *ci,
142
+ char *val, size_t size)
143
+{
144
+ return ceph_fmt_xattr(val, size, "%u", ci->i_layout.stripe_unit);
145
+}
146
+
147
+static ssize_t ceph_vxattrcb_layout_stripe_count(struct ceph_inode_info *ci,
148
+ char *val, size_t size)
149
+{
150
+ return ceph_fmt_xattr(val, size, "%u", ci->i_layout.stripe_count);
151
+}
152
+
153
+static ssize_t ceph_vxattrcb_layout_object_size(struct ceph_inode_info *ci,
154
+ char *val, size_t size)
155
+{
156
+ return ceph_fmt_xattr(val, size, "%u", ci->i_layout.object_size);
157
+}
158
+
159
+static ssize_t ceph_vxattrcb_layout_pool(struct ceph_inode_info *ci,
160
+ char *val, size_t size)
161
+{
162
+ ssize_t ret;
150163 struct ceph_fs_client *fsc = ceph_sb_to_client(ci->vfs_inode.i_sb);
151164 struct ceph_osd_client *osdc = &fsc->client->osdc;
152165 s64 pool = ci->i_layout.pool_id;
....@@ -154,21 +167,27 @@
154167
155168 down_read(&osdc->lock);
156169 pool_name = ceph_pg_pool_name_by_id(osdc->osdmap, pool);
157
- if (pool_name)
158
- ret = snprintf(val, size, "%s", pool_name);
159
- else
160
- ret = snprintf(val, size, "%lld", (unsigned long long)pool);
170
+ if (pool_name) {
171
+ ret = strlen(pool_name);
172
+ if (ret <= size)
173
+ memcpy(val, pool_name, ret);
174
+ } else {
175
+ ret = ceph_fmt_xattr(val, size, "%lld", pool);
176
+ }
161177 up_read(&osdc->lock);
162178 return ret;
163179 }
164180
165
-static size_t ceph_vxattrcb_layout_pool_namespace(struct ceph_inode_info *ci,
166
- char *val, size_t size)
181
+static ssize_t ceph_vxattrcb_layout_pool_namespace(struct ceph_inode_info *ci,
182
+ char *val, size_t size)
167183 {
168
- int ret = 0;
184
+ ssize_t ret = 0;
169185 struct ceph_string *ns = ceph_try_get_string(ci->i_layout.pool_ns);
186
+
170187 if (ns) {
171
- ret = snprintf(val, size, "%.*s", (int)ns->len, ns->str);
188
+ ret = ns->len;
189
+ if (ret <= size)
190
+ memcpy(val, ns->str, ret);
172191 ceph_put_string(ns);
173192 }
174193 return ret;
....@@ -176,57 +195,69 @@
176195
177196 /* directories */
178197
179
-static size_t ceph_vxattrcb_dir_entries(struct ceph_inode_info *ci, char *val,
180
- size_t size)
181
-{
182
- return snprintf(val, size, "%lld", ci->i_files + ci->i_subdirs);
183
-}
184
-
185
-static size_t ceph_vxattrcb_dir_files(struct ceph_inode_info *ci, char *val,
186
- size_t size)
187
-{
188
- return snprintf(val, size, "%lld", ci->i_files);
189
-}
190
-
191
-static size_t ceph_vxattrcb_dir_subdirs(struct ceph_inode_info *ci, char *val,
192
- size_t size)
193
-{
194
- return snprintf(val, size, "%lld", ci->i_subdirs);
195
-}
196
-
197
-static size_t ceph_vxattrcb_dir_rentries(struct ceph_inode_info *ci, char *val,
198
+static ssize_t ceph_vxattrcb_dir_entries(struct ceph_inode_info *ci, char *val,
198199 size_t size)
199200 {
200
- return snprintf(val, size, "%lld", ci->i_rfiles + ci->i_rsubdirs);
201
+ return ceph_fmt_xattr(val, size, "%lld", ci->i_files + ci->i_subdirs);
201202 }
202203
203
-static size_t ceph_vxattrcb_dir_rfiles(struct ceph_inode_info *ci, char *val,
204
+static ssize_t ceph_vxattrcb_dir_files(struct ceph_inode_info *ci, char *val,
204205 size_t size)
205206 {
206
- return snprintf(val, size, "%lld", ci->i_rfiles);
207
+ return ceph_fmt_xattr(val, size, "%lld", ci->i_files);
207208 }
208209
209
-static size_t ceph_vxattrcb_dir_rsubdirs(struct ceph_inode_info *ci, char *val,
210
+static ssize_t ceph_vxattrcb_dir_subdirs(struct ceph_inode_info *ci, char *val,
210211 size_t size)
211212 {
212
- return snprintf(val, size, "%lld", ci->i_rsubdirs);
213
+ return ceph_fmt_xattr(val, size, "%lld", ci->i_subdirs);
213214 }
214215
215
-static size_t ceph_vxattrcb_dir_rbytes(struct ceph_inode_info *ci, char *val,
216
- size_t size)
216
+static ssize_t ceph_vxattrcb_dir_rentries(struct ceph_inode_info *ci, char *val,
217
+ size_t size)
217218 {
218
- return snprintf(val, size, "%lld", ci->i_rbytes);
219
+ return ceph_fmt_xattr(val, size, "%lld",
220
+ ci->i_rfiles + ci->i_rsubdirs);
219221 }
220222
221
-static size_t ceph_vxattrcb_dir_rctime(struct ceph_inode_info *ci, char *val,
222
- size_t size)
223
+static ssize_t ceph_vxattrcb_dir_rfiles(struct ceph_inode_info *ci, char *val,
224
+ size_t size)
223225 {
224
- return snprintf(val, size, "%lld.%09ld", ci->i_rctime.tv_sec,
225
- ci->i_rctime.tv_nsec);
226
+ return ceph_fmt_xattr(val, size, "%lld", ci->i_rfiles);
227
+}
228
+
229
+static ssize_t ceph_vxattrcb_dir_rsubdirs(struct ceph_inode_info *ci, char *val,
230
+ size_t size)
231
+{
232
+ return ceph_fmt_xattr(val, size, "%lld", ci->i_rsubdirs);
233
+}
234
+
235
+static ssize_t ceph_vxattrcb_dir_rbytes(struct ceph_inode_info *ci, char *val,
236
+ size_t size)
237
+{
238
+ return ceph_fmt_xattr(val, size, "%lld", ci->i_rbytes);
239
+}
240
+
241
+static ssize_t ceph_vxattrcb_dir_rctime(struct ceph_inode_info *ci, char *val,
242
+ size_t size)
243
+{
244
+ return ceph_fmt_xattr(val, size, "%lld.%09ld", ci->i_rctime.tv_sec,
245
+ ci->i_rctime.tv_nsec);
246
+}
247
+
248
+/* dir pin */
249
+static bool ceph_vxattrcb_dir_pin_exists(struct ceph_inode_info *ci)
250
+{
251
+ return ci->i_dir_pin != -ENODATA;
252
+}
253
+
254
+static ssize_t ceph_vxattrcb_dir_pin(struct ceph_inode_info *ci, char *val,
255
+ size_t size)
256
+{
257
+ return ceph_fmt_xattr(val, size, "%d", (int)ci->i_dir_pin);
226258 }
227259
228260 /* quotas */
229
-
230261 static bool ceph_vxattrcb_quota_exists(struct ceph_inode_info *ci)
231262 {
232263 bool ret = false;
....@@ -240,23 +271,36 @@
240271 return ret;
241272 }
242273
243
-static size_t ceph_vxattrcb_quota(struct ceph_inode_info *ci, char *val,
244
- size_t size)
274
+static ssize_t ceph_vxattrcb_quota(struct ceph_inode_info *ci, char *val,
275
+ size_t size)
245276 {
246
- return snprintf(val, size, "max_bytes=%llu max_files=%llu",
247
- ci->i_max_bytes, ci->i_max_files);
277
+ return ceph_fmt_xattr(val, size, "max_bytes=%llu max_files=%llu",
278
+ ci->i_max_bytes, ci->i_max_files);
248279 }
249280
250
-static size_t ceph_vxattrcb_quota_max_bytes(struct ceph_inode_info *ci,
251
- char *val, size_t size)
281
+static ssize_t ceph_vxattrcb_quota_max_bytes(struct ceph_inode_info *ci,
282
+ char *val, size_t size)
252283 {
253
- return snprintf(val, size, "%llu", ci->i_max_bytes);
284
+ return ceph_fmt_xattr(val, size, "%llu", ci->i_max_bytes);
254285 }
255286
256
-static size_t ceph_vxattrcb_quota_max_files(struct ceph_inode_info *ci,
257
- char *val, size_t size)
287
+static ssize_t ceph_vxattrcb_quota_max_files(struct ceph_inode_info *ci,
288
+ char *val, size_t size)
258289 {
259
- return snprintf(val, size, "%llu", ci->i_max_files);
290
+ return ceph_fmt_xattr(val, size, "%llu", ci->i_max_files);
291
+}
292
+
293
+/* snapshots */
294
+static bool ceph_vxattrcb_snap_btime_exists(struct ceph_inode_info *ci)
295
+{
296
+ return (ci->i_snap_btime.tv_sec != 0 || ci->i_snap_btime.tv_nsec != 0);
297
+}
298
+
299
+static ssize_t ceph_vxattrcb_snap_btime(struct ceph_inode_info *ci, char *val,
300
+ size_t size)
301
+{
302
+ return ceph_fmt_xattr(val, size, "%lld.%09ld", ci->i_snap_btime.tv_sec,
303
+ ci->i_snap_btime.tv_nsec);
260304 }
261305
262306 #define CEPH_XATTR_NAME(_type, _name) XATTR_CEPH_PREFIX #_type "." #_name
....@@ -273,6 +317,14 @@
273317 }
274318 #define XATTR_RSTAT_FIELD(_type, _name) \
275319 XATTR_NAME_CEPH(_type, _name, VXATTR_FLAG_RSTAT)
320
+#define XATTR_RSTAT_FIELD_UPDATABLE(_type, _name) \
321
+ { \
322
+ .name = CEPH_XATTR_NAME(_type, _name), \
323
+ .name_size = sizeof (CEPH_XATTR_NAME(_type, _name)), \
324
+ .getxattr_cb = ceph_vxattrcb_ ## _type ## _ ## _name, \
325
+ .exists_cb = NULL, \
326
+ .flags = VXATTR_FLAG_RSTAT, \
327
+ }
276328 #define XATTR_LAYOUT_FIELD(_type, _name, _field) \
277329 { \
278330 .name = CEPH_XATTR_NAME2(_type, _name, _field), \
....@@ -310,7 +362,14 @@
310362 XATTR_RSTAT_FIELD(dir, rfiles),
311363 XATTR_RSTAT_FIELD(dir, rsubdirs),
312364 XATTR_RSTAT_FIELD(dir, rbytes),
313
- XATTR_RSTAT_FIELD(dir, rctime),
365
+ XATTR_RSTAT_FIELD_UPDATABLE(dir, rctime),
366
+ {
367
+ .name = "ceph.dir.pin",
368
+ .name_size = sizeof("ceph.dir.pin"),
369
+ .getxattr_cb = ceph_vxattrcb_dir_pin,
370
+ .exists_cb = ceph_vxattrcb_dir_pin_exists,
371
+ .flags = VXATTR_FLAG_HIDDEN,
372
+ },
314373 {
315374 .name = "ceph.quota",
316375 .name_size = sizeof("ceph.quota"),
....@@ -320,9 +379,15 @@
320379 },
321380 XATTR_QUOTA_FIELD(quota, max_bytes),
322381 XATTR_QUOTA_FIELD(quota, max_files),
382
+ {
383
+ .name = "ceph.snap.btime",
384
+ .name_size = sizeof("ceph.snap.btime"),
385
+ .getxattr_cb = ceph_vxattrcb_snap_btime,
386
+ .exists_cb = ceph_vxattrcb_snap_btime_exists,
387
+ .flags = VXATTR_FLAG_READONLY,
388
+ },
323389 { .name = NULL, 0 } /* Required table terminator */
324390 };
325
-static size_t ceph_dir_vxattrs_name_size; /* total size of all names */
326391
327392 /* files */
328393
....@@ -339,9 +404,15 @@
339404 XATTR_LAYOUT_FIELD(file, layout, object_size),
340405 XATTR_LAYOUT_FIELD(file, layout, pool),
341406 XATTR_LAYOUT_FIELD(file, layout, pool_namespace),
407
+ {
408
+ .name = "ceph.snap.btime",
409
+ .name_size = sizeof("ceph.snap.btime"),
410
+ .getxattr_cb = ceph_vxattrcb_snap_btime,
411
+ .exists_cb = ceph_vxattrcb_snap_btime_exists,
412
+ .flags = VXATTR_FLAG_READONLY,
413
+ },
342414 { .name = NULL, 0 } /* Required table terminator */
343415 };
344
-static size_t ceph_file_vxattrs_name_size; /* total size of all names */
345416
346417 static struct ceph_vxattr *ceph_inode_vxattrs(struct inode *inode)
347418 {
....@@ -350,47 +421,6 @@
350421 else if (S_ISREG(inode->i_mode))
351422 return ceph_file_vxattrs;
352423 return NULL;
353
-}
354
-
355
-static size_t ceph_vxattrs_name_size(struct ceph_vxattr *vxattrs)
356
-{
357
- if (vxattrs == ceph_dir_vxattrs)
358
- return ceph_dir_vxattrs_name_size;
359
- if (vxattrs == ceph_file_vxattrs)
360
- return ceph_file_vxattrs_name_size;
361
- BUG_ON(vxattrs);
362
- return 0;
363
-}
364
-
365
-/*
366
- * Compute the aggregate size (including terminating '\0') of all
367
- * virtual extended attribute names in the given vxattr table.
368
- */
369
-static size_t __init vxattrs_name_size(struct ceph_vxattr *vxattrs)
370
-{
371
- struct ceph_vxattr *vxattr;
372
- size_t size = 0;
373
-
374
- for (vxattr = vxattrs; vxattr->name; vxattr++) {
375
- if (!(vxattr->flags & VXATTR_FLAG_HIDDEN))
376
- size += vxattr->name_size;
377
- }
378
-
379
- return size;
380
-}
381
-
382
-/* Routines called at initialization and exit time */
383
-
384
-void __init ceph_xattr_init(void)
385
-{
386
- ceph_dir_vxattrs_name_size = vxattrs_name_size(ceph_dir_vxattrs);
387
- ceph_file_vxattrs_name_size = vxattrs_name_size(ceph_file_vxattrs);
388
-}
389
-
390
-void ceph_xattr_exit(void)
391
-{
392
- ceph_dir_vxattrs_name_size = 0;
393
- ceph_file_vxattrs_name_size = 0;
394424 }
395425
396426 static struct ceph_vxattr *ceph_match_vxattr(struct inode *inode,
....@@ -476,10 +506,10 @@
476506 kfree(*newxattr);
477507 *newxattr = NULL;
478508 if (xattr->should_free_val)
479
- kfree((void *)xattr->val);
509
+ kfree(xattr->val);
480510
481511 if (update_xattr) {
482
- kfree((void *)name);
512
+ kfree(name);
483513 name = xattr->name;
484514 }
485515 ci->i_xattrs.names_size -= xattr->name_len;
....@@ -502,8 +532,8 @@
502532 dout("__set_xattr_val p=%p\n", p);
503533 }
504534
505
- dout("__set_xattr_val added %llx.%llx xattr %p %s=%.*s\n",
506
- ceph_vinop(&ci->vfs_inode), xattr, name, val_len, val);
535
+ dout("__set_xattr_val added %llx.%llx xattr %p %.*s=%.*s\n",
536
+ ceph_vinop(&ci->vfs_inode), xattr, name_len, name, val_len, val);
507537
508538 return 0;
509539 }
....@@ -545,9 +575,9 @@
545575 BUG_ON(!xattr);
546576
547577 if (xattr->should_free_name)
548
- kfree((void *)xattr->name);
578
+ kfree(xattr->name);
549579 if (xattr->should_free_val)
550
- kfree((void *)xattr->val);
580
+ kfree(xattr->val);
551581
552582 kfree(xattr);
553583 }
....@@ -561,9 +591,9 @@
561591 rb_erase(&xattr->node, &ci->i_xattrs.index);
562592
563593 if (xattr->should_free_name)
564
- kfree((void *)xattr->name);
594
+ kfree(xattr->name);
565595 if (xattr->should_free_val)
566
- kfree((void *)xattr->val);
596
+ kfree(xattr->val);
567597
568598 ci->i_xattrs.names_size -= xattr->name_len;
569599 ci->i_xattrs.vals_size -= xattr->val_len;
....@@ -634,7 +664,7 @@
634664 u32 len;
635665 const char *name, *val;
636666 struct ceph_inode_info *ci = ceph_inode(inode);
637
- int xattr_version;
667
+ u64 xattr_version;
638668 struct ceph_inode_xattr **xattrs = NULL;
639669 int err = 0;
640670 int i;
....@@ -807,7 +837,7 @@
807837 struct ceph_inode_xattr *xattr;
808838 struct ceph_vxattr *vxattr = NULL;
809839 int req_mask;
810
- int err;
840
+ ssize_t err;
811841
812842 /* let's see if a virtual xattr was requested */
813843 vxattr = ceph_match_vxattr(inode, name);
....@@ -830,12 +860,12 @@
830860 req_mask = __get_request_mask(inode);
831861
832862 spin_lock(&ci->i_ceph_lock);
833
- dout("getxattr %p ver=%lld index_ver=%lld\n", inode,
863
+ dout("getxattr %p name '%s' ver=%lld index_ver=%lld\n", inode, name,
834864 ci->i_xattrs.version, ci->i_xattrs.index_version);
835865
836866 if (ci->i_xattrs.version == 0 ||
837867 !((req_mask & CEPH_CAP_XATTR_SHARED) ||
838
- __ceph_caps_issued_mask(ci, CEPH_CAP_XATTR_SHARED, 1))) {
868
+ __ceph_caps_issued_mask_metric(ci, CEPH_CAP_XATTR_SHARED, 1))) {
839869 spin_unlock(&ci->i_ceph_lock);
840870
841871 /* security module gets xattr while filling trace */
....@@ -872,7 +902,8 @@
872902 memcpy(value, xattr->val, xattr->val_len);
873903
874904 if (current->journal_info &&
875
- !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN))
905
+ !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) &&
906
+ security_ismaclabel(name + XATTR_SECURITY_PREFIX_LEN))
876907 ci->i_ceph_flags |= CEPH_I_SEC_INITED;
877908 out:
878909 spin_unlock(&ci->i_ceph_lock);
....@@ -883,19 +914,16 @@
883914 {
884915 struct inode *inode = d_inode(dentry);
885916 struct ceph_inode_info *ci = ceph_inode(inode);
886
- struct ceph_vxattr *vxattrs = ceph_inode_vxattrs(inode);
887
- u32 vir_namelen = 0;
917
+ bool len_only = (size == 0);
888918 u32 namelen;
889919 int err;
890
- u32 len;
891
- int i;
892920
893921 spin_lock(&ci->i_ceph_lock);
894922 dout("listxattr %p ver=%lld index_ver=%lld\n", inode,
895923 ci->i_xattrs.version, ci->i_xattrs.index_version);
896924
897925 if (ci->i_xattrs.version == 0 ||
898
- !__ceph_caps_issued_mask(ci, CEPH_CAP_XATTR_SHARED, 1)) {
926
+ !__ceph_caps_issued_mask_metric(ci, CEPH_CAP_XATTR_SHARED, 1)) {
899927 spin_unlock(&ci->i_ceph_lock);
900928 err = ceph_do_getattr(inode, CEPH_STAT_CAP_XATTR, true);
901929 if (err)
....@@ -906,38 +934,18 @@
906934 err = __build_xattrs(inode);
907935 if (err < 0)
908936 goto out;
909
- /*
910
- * Start with virtual dir xattr names (if any) (including
911
- * terminating '\0' characters for each).
912
- */
913
- vir_namelen = ceph_vxattrs_name_size(vxattrs);
914937
915
- /* adding 1 byte per each variable due to the null termination */
938
+ /* add 1 byte for each xattr due to the null termination */
916939 namelen = ci->i_xattrs.names_size + ci->i_xattrs.count;
917
- err = -ERANGE;
918
- if (size && vir_namelen + namelen > size)
919
- goto out;
920
-
921
- err = namelen + vir_namelen;
922
- if (size == 0)
923
- goto out;
924
-
925
- names = __copy_xattr_names(ci, names);
926
-
927
- /* virtual xattr names, too */
928
- err = namelen;
929
- if (vxattrs) {
930
- for (i = 0; vxattrs[i].name; i++) {
931
- if (!(vxattrs[i].flags & VXATTR_FLAG_HIDDEN) &&
932
- !(vxattrs[i].exists_cb &&
933
- !vxattrs[i].exists_cb(ci))) {
934
- len = sprintf(names, "%s", vxattrs[i].name);
935
- names += len + 1;
936
- err += len + 1;
937
- }
940
+ if (!len_only) {
941
+ if (namelen > size) {
942
+ err = -ERANGE;
943
+ goto out;
938944 }
945
+ names = __copy_xattr_names(ci, names);
946
+ size -= namelen;
939947 }
940
-
948
+ err = namelen;
941949 out:
942950 spin_unlock(&ci->i_ceph_lock);
943951 return err;
....@@ -956,11 +964,10 @@
956964
957965 if (size > 0) {
958966 /* copy value into pagelist */
959
- pagelist = kmalloc(sizeof(*pagelist), GFP_NOFS);
967
+ pagelist = ceph_pagelist_alloc(GFP_NOFS);
960968 if (!pagelist)
961969 return -ENOMEM;
962970
963
- ceph_pagelist_init(pagelist);
964971 err = ceph_pagelist_append(pagelist, value, size);
965972 if (err)
966973 goto out;
....@@ -1080,7 +1087,8 @@
10801087 }
10811088 }
10821089
1083
- dout("setxattr %p issued %s\n", inode, ceph_cap_string(issued));
1090
+ dout("setxattr %p name '%s' issued %s\n", inode, name,
1091
+ ceph_cap_string(issued));
10841092 __build_xattrs(inode);
10851093
10861094 required_blob_size = __get_required_blob_size(ci, name_len, val_len);
....@@ -1155,7 +1163,8 @@
11551163
11561164 static int ceph_get_xattr_handler(const struct xattr_handler *handler,
11571165 struct dentry *dentry, struct inode *inode,
1158
- const char *name, void *value, size_t size)
1166
+ const char *name, void *value, size_t size,
1167
+ int flags)
11591168 {
11601169 if (!ceph_is_valid_xattr(name))
11611170 return -EOPNOTSUPP;
....@@ -1198,4 +1207,101 @@
11981207 spin_unlock(&ci->i_ceph_lock);
11991208 return ret;
12001209 }
1210
+
1211
+#ifdef CONFIG_CEPH_FS_SECURITY_LABEL
1212
+int ceph_security_init_secctx(struct dentry *dentry, umode_t mode,
1213
+ struct ceph_acl_sec_ctx *as_ctx)
1214
+{
1215
+ struct ceph_pagelist *pagelist = as_ctx->pagelist;
1216
+ const char *name;
1217
+ size_t name_len;
1218
+ int err;
1219
+
1220
+ err = security_dentry_init_security(dentry, mode, &dentry->d_name,
1221
+ &as_ctx->sec_ctx,
1222
+ &as_ctx->sec_ctxlen);
1223
+ if (err < 0) {
1224
+ WARN_ON_ONCE(err != -EOPNOTSUPP);
1225
+ err = 0; /* do nothing */
1226
+ goto out;
1227
+ }
1228
+
1229
+ err = -ENOMEM;
1230
+ if (!pagelist) {
1231
+ pagelist = ceph_pagelist_alloc(GFP_KERNEL);
1232
+ if (!pagelist)
1233
+ goto out;
1234
+ err = ceph_pagelist_reserve(pagelist, PAGE_SIZE);
1235
+ if (err)
1236
+ goto out;
1237
+ ceph_pagelist_encode_32(pagelist, 1);
1238
+ }
1239
+
1240
+ /*
1241
+ * FIXME: Make security_dentry_init_security() generic. Currently
1242
+ * It only supports single security module and only selinux has
1243
+ * dentry_init_security hook.
1244
+ */
1245
+ name = XATTR_NAME_SELINUX;
1246
+ name_len = strlen(name);
1247
+ err = ceph_pagelist_reserve(pagelist,
1248
+ 4 * 2 + name_len + as_ctx->sec_ctxlen);
1249
+ if (err)
1250
+ goto out;
1251
+
1252
+ if (as_ctx->pagelist) {
1253
+ /* update count of KV pairs */
1254
+ BUG_ON(pagelist->length <= sizeof(__le32));
1255
+ if (list_is_singular(&pagelist->head)) {
1256
+ le32_add_cpu((__le32*)pagelist->mapped_tail, 1);
1257
+ } else {
1258
+ struct page *page = list_first_entry(&pagelist->head,
1259
+ struct page, lru);
1260
+ void *addr = kmap_atomic(page);
1261
+ le32_add_cpu((__le32*)addr, 1);
1262
+ kunmap_atomic(addr);
1263
+ }
1264
+ } else {
1265
+ as_ctx->pagelist = pagelist;
1266
+ }
1267
+
1268
+ ceph_pagelist_encode_32(pagelist, name_len);
1269
+ ceph_pagelist_append(pagelist, name, name_len);
1270
+
1271
+ ceph_pagelist_encode_32(pagelist, as_ctx->sec_ctxlen);
1272
+ ceph_pagelist_append(pagelist, as_ctx->sec_ctx, as_ctx->sec_ctxlen);
1273
+
1274
+ err = 0;
1275
+out:
1276
+ if (pagelist && !as_ctx->pagelist)
1277
+ ceph_pagelist_release(pagelist);
1278
+ return err;
1279
+}
1280
+#endif /* CONFIG_CEPH_FS_SECURITY_LABEL */
1281
+#endif /* CONFIG_SECURITY */
1282
+
1283
+void ceph_release_acl_sec_ctx(struct ceph_acl_sec_ctx *as_ctx)
1284
+{
1285
+#ifdef CONFIG_CEPH_FS_POSIX_ACL
1286
+ posix_acl_release(as_ctx->acl);
1287
+ posix_acl_release(as_ctx->default_acl);
12011288 #endif
1289
+#ifdef CONFIG_CEPH_FS_SECURITY_LABEL
1290
+ security_release_secctx(as_ctx->sec_ctx, as_ctx->sec_ctxlen);
1291
+#endif
1292
+ if (as_ctx->pagelist)
1293
+ ceph_pagelist_release(as_ctx->pagelist);
1294
+}
1295
+
1296
+/*
1297
+ * List of handlers for synthetic system.* attributes. Other
1298
+ * attributes are handled directly.
1299
+ */
1300
+const struct xattr_handler *ceph_xattr_handlers[] = {
1301
+#ifdef CONFIG_CEPH_FS_POSIX_ACL
1302
+ &posix_acl_access_xattr_handler,
1303
+ &posix_acl_default_xattr_handler,
1304
+#endif
1305
+ &ceph_other_xattr_handler,
1306
+ NULL,
1307
+};