Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/fs/ceph/xattr.c
26282 views
1
// SPDX-License-Identifier: GPL-2.0
2
#include <linux/ceph/ceph_debug.h>
3
#include <linux/ceph/pagelist.h>
4
5
#include "super.h"
6
#include "mds_client.h"
7
8
#include <linux/ceph/decode.h>
9
10
#include <linux/xattr.h>
11
#include <linux/security.h>
12
#include <linux/posix_acl_xattr.h>
13
#include <linux/slab.h>
14
15
#define XATTR_CEPH_PREFIX "ceph."
16
#define XATTR_CEPH_PREFIX_LEN (sizeof (XATTR_CEPH_PREFIX) - 1)
17
18
static int __remove_xattr(struct ceph_inode_info *ci,
19
struct ceph_inode_xattr *xattr);
20
21
static bool ceph_is_valid_xattr(const char *name)
22
{
23
return !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) ||
24
!strncmp(name, XATTR_CEPH_PREFIX, XATTR_CEPH_PREFIX_LEN) ||
25
!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) ||
26
!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
27
}
28
29
/*
30
* These define virtual xattrs exposing the recursive directory
31
* statistics and layout metadata.
32
*/
33
struct ceph_vxattr {
34
char *name;
35
size_t name_size; /* strlen(name) + 1 (for '\0') */
36
ssize_t (*getxattr_cb)(struct ceph_inode_info *ci, char *val,
37
size_t size);
38
bool (*exists_cb)(struct ceph_inode_info *ci);
39
unsigned int flags;
40
};
41
42
#define VXATTR_FLAG_READONLY (1<<0)
43
#define VXATTR_FLAG_HIDDEN (1<<1)
44
#define VXATTR_FLAG_RSTAT (1<<2)
45
#define VXATTR_FLAG_DIRSTAT (1<<3)
46
47
/* layouts */
48
49
static bool ceph_vxattrcb_layout_exists(struct ceph_inode_info *ci)
50
{
51
struct ceph_file_layout *fl = &ci->i_layout;
52
return (fl->stripe_unit > 0 || fl->stripe_count > 0 ||
53
fl->object_size > 0 || fl->pool_id >= 0 ||
54
rcu_dereference_raw(fl->pool_ns) != NULL);
55
}
56
57
static ssize_t ceph_vxattrcb_layout(struct ceph_inode_info *ci, char *val,
58
size_t size)
59
{
60
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(ci->netfs.inode.i_sb);
61
struct ceph_client *cl = fsc->client;
62
struct ceph_osd_client *osdc = &fsc->client->osdc;
63
struct ceph_string *pool_ns;
64
s64 pool = ci->i_layout.pool_id;
65
const char *pool_name;
66
const char *ns_field = " pool_namespace=";
67
char buf[128];
68
size_t len, total_len = 0;
69
ssize_t ret;
70
71
pool_ns = ceph_try_get_string(ci->i_layout.pool_ns);
72
73
doutc(cl, "%p\n", &ci->netfs.inode);
74
down_read(&osdc->lock);
75
pool_name = ceph_pg_pool_name_by_id(osdc->osdmap, pool);
76
if (pool_name) {
77
len = snprintf(buf, sizeof(buf),
78
"stripe_unit=%u stripe_count=%u object_size=%u pool=",
79
ci->i_layout.stripe_unit, ci->i_layout.stripe_count,
80
ci->i_layout.object_size);
81
total_len = len + strlen(pool_name);
82
} else {
83
len = snprintf(buf, sizeof(buf),
84
"stripe_unit=%u stripe_count=%u object_size=%u pool=%lld",
85
ci->i_layout.stripe_unit, ci->i_layout.stripe_count,
86
ci->i_layout.object_size, pool);
87
total_len = len;
88
}
89
90
if (pool_ns)
91
total_len += strlen(ns_field) + pool_ns->len;
92
93
ret = total_len;
94
if (size >= total_len) {
95
memcpy(val, buf, len);
96
ret = len;
97
if (pool_name) {
98
len = strlen(pool_name);
99
memcpy(val + ret, pool_name, len);
100
ret += len;
101
}
102
if (pool_ns) {
103
len = strlen(ns_field);
104
memcpy(val + ret, ns_field, len);
105
ret += len;
106
memcpy(val + ret, pool_ns->str, pool_ns->len);
107
ret += pool_ns->len;
108
}
109
}
110
up_read(&osdc->lock);
111
ceph_put_string(pool_ns);
112
return ret;
113
}
114
115
/*
116
* The convention with strings in xattrs is that they should not be NULL
117
* terminated, since we're returning the length with them. snprintf always
118
* NULL terminates however, so call it on a temporary buffer and then memcpy
119
* the result into place.
120
*/
121
static __printf(3, 4)
122
int ceph_fmt_xattr(char *val, size_t size, const char *fmt, ...)
123
{
124
int ret;
125
va_list args;
126
char buf[96]; /* NB: reevaluate size if new vxattrs are added */
127
128
va_start(args, fmt);
129
ret = vsnprintf(buf, size ? sizeof(buf) : 0, fmt, args);
130
va_end(args);
131
132
/* Sanity check */
133
if (size && ret + 1 > sizeof(buf)) {
134
WARN_ONCE(true, "Returned length too big (%d)", ret);
135
return -E2BIG;
136
}
137
138
if (ret <= size)
139
memcpy(val, buf, ret);
140
return ret;
141
}
142
143
static ssize_t ceph_vxattrcb_layout_stripe_unit(struct ceph_inode_info *ci,
144
char *val, size_t size)
145
{
146
return ceph_fmt_xattr(val, size, "%u", ci->i_layout.stripe_unit);
147
}
148
149
static ssize_t ceph_vxattrcb_layout_stripe_count(struct ceph_inode_info *ci,
150
char *val, size_t size)
151
{
152
return ceph_fmt_xattr(val, size, "%u", ci->i_layout.stripe_count);
153
}
154
155
static ssize_t ceph_vxattrcb_layout_object_size(struct ceph_inode_info *ci,
156
char *val, size_t size)
157
{
158
return ceph_fmt_xattr(val, size, "%u", ci->i_layout.object_size);
159
}
160
161
static ssize_t ceph_vxattrcb_layout_pool(struct ceph_inode_info *ci,
162
char *val, size_t size)
163
{
164
ssize_t ret;
165
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(ci->netfs.inode.i_sb);
166
struct ceph_osd_client *osdc = &fsc->client->osdc;
167
s64 pool = ci->i_layout.pool_id;
168
const char *pool_name;
169
170
down_read(&osdc->lock);
171
pool_name = ceph_pg_pool_name_by_id(osdc->osdmap, pool);
172
if (pool_name) {
173
ret = strlen(pool_name);
174
if (ret <= size)
175
memcpy(val, pool_name, ret);
176
} else {
177
ret = ceph_fmt_xattr(val, size, "%lld", pool);
178
}
179
up_read(&osdc->lock);
180
return ret;
181
}
182
183
static ssize_t ceph_vxattrcb_layout_pool_namespace(struct ceph_inode_info *ci,
184
char *val, size_t size)
185
{
186
ssize_t ret = 0;
187
struct ceph_string *ns = ceph_try_get_string(ci->i_layout.pool_ns);
188
189
if (ns) {
190
ret = ns->len;
191
if (ret <= size)
192
memcpy(val, ns->str, ret);
193
ceph_put_string(ns);
194
}
195
return ret;
196
}
197
198
/* directories */
199
200
static ssize_t ceph_vxattrcb_dir_entries(struct ceph_inode_info *ci, char *val,
201
size_t size)
202
{
203
return ceph_fmt_xattr(val, size, "%lld", ci->i_files + ci->i_subdirs);
204
}
205
206
static ssize_t ceph_vxattrcb_dir_files(struct ceph_inode_info *ci, char *val,
207
size_t size)
208
{
209
return ceph_fmt_xattr(val, size, "%lld", ci->i_files);
210
}
211
212
static ssize_t ceph_vxattrcb_dir_subdirs(struct ceph_inode_info *ci, char *val,
213
size_t size)
214
{
215
return ceph_fmt_xattr(val, size, "%lld", ci->i_subdirs);
216
}
217
218
static ssize_t ceph_vxattrcb_dir_rentries(struct ceph_inode_info *ci, char *val,
219
size_t size)
220
{
221
return ceph_fmt_xattr(val, size, "%lld",
222
ci->i_rfiles + ci->i_rsubdirs);
223
}
224
225
static ssize_t ceph_vxattrcb_dir_rfiles(struct ceph_inode_info *ci, char *val,
226
size_t size)
227
{
228
return ceph_fmt_xattr(val, size, "%lld", ci->i_rfiles);
229
}
230
231
static ssize_t ceph_vxattrcb_dir_rsubdirs(struct ceph_inode_info *ci, char *val,
232
size_t size)
233
{
234
return ceph_fmt_xattr(val, size, "%lld", ci->i_rsubdirs);
235
}
236
237
static ssize_t ceph_vxattrcb_dir_rsnaps(struct ceph_inode_info *ci, char *val,
238
size_t size)
239
{
240
return ceph_fmt_xattr(val, size, "%lld", ci->i_rsnaps);
241
}
242
243
static ssize_t ceph_vxattrcb_dir_rbytes(struct ceph_inode_info *ci, char *val,
244
size_t size)
245
{
246
return ceph_fmt_xattr(val, size, "%lld", ci->i_rbytes);
247
}
248
249
static ssize_t ceph_vxattrcb_dir_rctime(struct ceph_inode_info *ci, char *val,
250
size_t size)
251
{
252
return ceph_fmt_xattr(val, size, "%lld.%09ld", ci->i_rctime.tv_sec,
253
ci->i_rctime.tv_nsec);
254
}
255
256
/* dir pin */
257
static bool ceph_vxattrcb_dir_pin_exists(struct ceph_inode_info *ci)
258
{
259
return ci->i_dir_pin != -ENODATA;
260
}
261
262
static ssize_t ceph_vxattrcb_dir_pin(struct ceph_inode_info *ci, char *val,
263
size_t size)
264
{
265
return ceph_fmt_xattr(val, size, "%d", (int)ci->i_dir_pin);
266
}
267
268
/* quotas */
269
static bool ceph_vxattrcb_quota_exists(struct ceph_inode_info *ci)
270
{
271
bool ret = false;
272
spin_lock(&ci->i_ceph_lock);
273
if ((ci->i_max_files || ci->i_max_bytes) &&
274
ci->i_vino.snap == CEPH_NOSNAP &&
275
ci->i_snap_realm &&
276
ci->i_snap_realm->ino == ci->i_vino.ino)
277
ret = true;
278
spin_unlock(&ci->i_ceph_lock);
279
return ret;
280
}
281
282
static ssize_t ceph_vxattrcb_quota(struct ceph_inode_info *ci, char *val,
283
size_t size)
284
{
285
return ceph_fmt_xattr(val, size, "max_bytes=%llu max_files=%llu",
286
ci->i_max_bytes, ci->i_max_files);
287
}
288
289
static ssize_t ceph_vxattrcb_quota_max_bytes(struct ceph_inode_info *ci,
290
char *val, size_t size)
291
{
292
return ceph_fmt_xattr(val, size, "%llu", ci->i_max_bytes);
293
}
294
295
static ssize_t ceph_vxattrcb_quota_max_files(struct ceph_inode_info *ci,
296
char *val, size_t size)
297
{
298
return ceph_fmt_xattr(val, size, "%llu", ci->i_max_files);
299
}
300
301
/* snapshots */
302
static bool ceph_vxattrcb_snap_btime_exists(struct ceph_inode_info *ci)
303
{
304
return (ci->i_snap_btime.tv_sec != 0 || ci->i_snap_btime.tv_nsec != 0);
305
}
306
307
static ssize_t ceph_vxattrcb_snap_btime(struct ceph_inode_info *ci, char *val,
308
size_t size)
309
{
310
return ceph_fmt_xattr(val, size, "%lld.%09ld", ci->i_snap_btime.tv_sec,
311
ci->i_snap_btime.tv_nsec);
312
}
313
314
static ssize_t ceph_vxattrcb_cluster_fsid(struct ceph_inode_info *ci,
315
char *val, size_t size)
316
{
317
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(ci->netfs.inode.i_sb);
318
319
return ceph_fmt_xattr(val, size, "%pU", &fsc->client->fsid);
320
}
321
322
static ssize_t ceph_vxattrcb_client_id(struct ceph_inode_info *ci,
323
char *val, size_t size)
324
{
325
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(ci->netfs.inode.i_sb);
326
327
return ceph_fmt_xattr(val, size, "client%lld",
328
ceph_client_gid(fsc->client));
329
}
330
331
static ssize_t ceph_vxattrcb_caps(struct ceph_inode_info *ci, char *val,
332
size_t size)
333
{
334
int issued;
335
336
spin_lock(&ci->i_ceph_lock);
337
issued = __ceph_caps_issued(ci, NULL);
338
spin_unlock(&ci->i_ceph_lock);
339
340
return ceph_fmt_xattr(val, size, "%s/0x%x",
341
ceph_cap_string(issued), issued);
342
}
343
344
static ssize_t ceph_vxattrcb_auth_mds(struct ceph_inode_info *ci,
345
char *val, size_t size)
346
{
347
int ret;
348
349
spin_lock(&ci->i_ceph_lock);
350
ret = ceph_fmt_xattr(val, size, "%d",
351
ci->i_auth_cap ? ci->i_auth_cap->session->s_mds : -1);
352
spin_unlock(&ci->i_ceph_lock);
353
return ret;
354
}
355
356
#if IS_ENABLED(CONFIG_FS_ENCRYPTION)
357
static bool ceph_vxattrcb_fscrypt_auth_exists(struct ceph_inode_info *ci)
358
{
359
return ci->fscrypt_auth_len;
360
}
361
362
static ssize_t ceph_vxattrcb_fscrypt_auth(struct ceph_inode_info *ci,
363
char *val, size_t size)
364
{
365
if (size) {
366
if (size < ci->fscrypt_auth_len)
367
return -ERANGE;
368
memcpy(val, ci->fscrypt_auth, ci->fscrypt_auth_len);
369
}
370
return ci->fscrypt_auth_len;
371
}
372
#endif /* CONFIG_FS_ENCRYPTION */
373
374
#define CEPH_XATTR_NAME(_type, _name) XATTR_CEPH_PREFIX #_type "." #_name
375
#define CEPH_XATTR_NAME2(_type, _name, _name2) \
376
XATTR_CEPH_PREFIX #_type "." #_name "." #_name2
377
378
#define XATTR_NAME_CEPH(_type, _name, _flags) \
379
{ \
380
.name = CEPH_XATTR_NAME(_type, _name), \
381
.name_size = sizeof (CEPH_XATTR_NAME(_type, _name)), \
382
.getxattr_cb = ceph_vxattrcb_ ## _type ## _ ## _name, \
383
.exists_cb = NULL, \
384
.flags = (VXATTR_FLAG_READONLY | _flags), \
385
}
386
#define XATTR_RSTAT_FIELD(_type, _name) \
387
XATTR_NAME_CEPH(_type, _name, VXATTR_FLAG_RSTAT)
388
#define XATTR_RSTAT_FIELD_UPDATABLE(_type, _name) \
389
{ \
390
.name = CEPH_XATTR_NAME(_type, _name), \
391
.name_size = sizeof (CEPH_XATTR_NAME(_type, _name)), \
392
.getxattr_cb = ceph_vxattrcb_ ## _type ## _ ## _name, \
393
.exists_cb = NULL, \
394
.flags = VXATTR_FLAG_RSTAT, \
395
}
396
#define XATTR_LAYOUT_FIELD(_type, _name, _field) \
397
{ \
398
.name = CEPH_XATTR_NAME2(_type, _name, _field), \
399
.name_size = sizeof (CEPH_XATTR_NAME2(_type, _name, _field)), \
400
.getxattr_cb = ceph_vxattrcb_ ## _name ## _ ## _field, \
401
.exists_cb = ceph_vxattrcb_layout_exists, \
402
.flags = VXATTR_FLAG_HIDDEN, \
403
}
404
#define XATTR_QUOTA_FIELD(_type, _name) \
405
{ \
406
.name = CEPH_XATTR_NAME(_type, _name), \
407
.name_size = sizeof(CEPH_XATTR_NAME(_type, _name)), \
408
.getxattr_cb = ceph_vxattrcb_ ## _type ## _ ## _name, \
409
.exists_cb = ceph_vxattrcb_quota_exists, \
410
.flags = VXATTR_FLAG_HIDDEN, \
411
}
412
413
static struct ceph_vxattr ceph_dir_vxattrs[] = {
414
{
415
.name = "ceph.dir.layout",
416
.name_size = sizeof("ceph.dir.layout"),
417
.getxattr_cb = ceph_vxattrcb_layout,
418
.exists_cb = ceph_vxattrcb_layout_exists,
419
.flags = VXATTR_FLAG_HIDDEN,
420
},
421
XATTR_LAYOUT_FIELD(dir, layout, stripe_unit),
422
XATTR_LAYOUT_FIELD(dir, layout, stripe_count),
423
XATTR_LAYOUT_FIELD(dir, layout, object_size),
424
XATTR_LAYOUT_FIELD(dir, layout, pool),
425
XATTR_LAYOUT_FIELD(dir, layout, pool_namespace),
426
XATTR_NAME_CEPH(dir, entries, VXATTR_FLAG_DIRSTAT),
427
XATTR_NAME_CEPH(dir, files, VXATTR_FLAG_DIRSTAT),
428
XATTR_NAME_CEPH(dir, subdirs, VXATTR_FLAG_DIRSTAT),
429
XATTR_RSTAT_FIELD(dir, rentries),
430
XATTR_RSTAT_FIELD(dir, rfiles),
431
XATTR_RSTAT_FIELD(dir, rsubdirs),
432
XATTR_RSTAT_FIELD(dir, rsnaps),
433
XATTR_RSTAT_FIELD(dir, rbytes),
434
XATTR_RSTAT_FIELD_UPDATABLE(dir, rctime),
435
{
436
.name = "ceph.dir.pin",
437
.name_size = sizeof("ceph.dir.pin"),
438
.getxattr_cb = ceph_vxattrcb_dir_pin,
439
.exists_cb = ceph_vxattrcb_dir_pin_exists,
440
.flags = VXATTR_FLAG_HIDDEN,
441
},
442
{
443
.name = "ceph.quota",
444
.name_size = sizeof("ceph.quota"),
445
.getxattr_cb = ceph_vxattrcb_quota,
446
.exists_cb = ceph_vxattrcb_quota_exists,
447
.flags = VXATTR_FLAG_HIDDEN,
448
},
449
XATTR_QUOTA_FIELD(quota, max_bytes),
450
XATTR_QUOTA_FIELD(quota, max_files),
451
{
452
.name = "ceph.snap.btime",
453
.name_size = sizeof("ceph.snap.btime"),
454
.getxattr_cb = ceph_vxattrcb_snap_btime,
455
.exists_cb = ceph_vxattrcb_snap_btime_exists,
456
.flags = VXATTR_FLAG_READONLY,
457
},
458
{
459
.name = "ceph.caps",
460
.name_size = sizeof("ceph.caps"),
461
.getxattr_cb = ceph_vxattrcb_caps,
462
.exists_cb = NULL,
463
.flags = VXATTR_FLAG_HIDDEN,
464
},
465
{ .name = NULL, 0 } /* Required table terminator */
466
};
467
468
/* files */
469
470
static struct ceph_vxattr ceph_file_vxattrs[] = {
471
{
472
.name = "ceph.file.layout",
473
.name_size = sizeof("ceph.file.layout"),
474
.getxattr_cb = ceph_vxattrcb_layout,
475
.exists_cb = ceph_vxattrcb_layout_exists,
476
.flags = VXATTR_FLAG_HIDDEN,
477
},
478
XATTR_LAYOUT_FIELD(file, layout, stripe_unit),
479
XATTR_LAYOUT_FIELD(file, layout, stripe_count),
480
XATTR_LAYOUT_FIELD(file, layout, object_size),
481
XATTR_LAYOUT_FIELD(file, layout, pool),
482
XATTR_LAYOUT_FIELD(file, layout, pool_namespace),
483
{
484
.name = "ceph.snap.btime",
485
.name_size = sizeof("ceph.snap.btime"),
486
.getxattr_cb = ceph_vxattrcb_snap_btime,
487
.exists_cb = ceph_vxattrcb_snap_btime_exists,
488
.flags = VXATTR_FLAG_READONLY,
489
},
490
{
491
.name = "ceph.caps",
492
.name_size = sizeof("ceph.caps"),
493
.getxattr_cb = ceph_vxattrcb_caps,
494
.exists_cb = NULL,
495
.flags = VXATTR_FLAG_HIDDEN,
496
},
497
{ .name = NULL, 0 } /* Required table terminator */
498
};
499
500
static struct ceph_vxattr ceph_common_vxattrs[] = {
501
{
502
.name = "ceph.cluster_fsid",
503
.name_size = sizeof("ceph.cluster_fsid"),
504
.getxattr_cb = ceph_vxattrcb_cluster_fsid,
505
.exists_cb = NULL,
506
.flags = VXATTR_FLAG_READONLY,
507
},
508
{
509
.name = "ceph.client_id",
510
.name_size = sizeof("ceph.client_id"),
511
.getxattr_cb = ceph_vxattrcb_client_id,
512
.exists_cb = NULL,
513
.flags = VXATTR_FLAG_READONLY,
514
},
515
{
516
.name = "ceph.auth_mds",
517
.name_size = sizeof("ceph.auth_mds"),
518
.getxattr_cb = ceph_vxattrcb_auth_mds,
519
.exists_cb = NULL,
520
.flags = VXATTR_FLAG_READONLY,
521
},
522
#if IS_ENABLED(CONFIG_FS_ENCRYPTION)
523
{
524
.name = "ceph.fscrypt.auth",
525
.name_size = sizeof("ceph.fscrypt.auth"),
526
.getxattr_cb = ceph_vxattrcb_fscrypt_auth,
527
.exists_cb = ceph_vxattrcb_fscrypt_auth_exists,
528
.flags = VXATTR_FLAG_READONLY,
529
},
530
#endif /* CONFIG_FS_ENCRYPTION */
531
{ .name = NULL, 0 } /* Required table terminator */
532
};
533
534
static struct ceph_vxattr *ceph_inode_vxattrs(struct inode *inode)
535
{
536
if (S_ISDIR(inode->i_mode))
537
return ceph_dir_vxattrs;
538
else if (S_ISREG(inode->i_mode))
539
return ceph_file_vxattrs;
540
return NULL;
541
}
542
543
static struct ceph_vxattr *ceph_match_vxattr(struct inode *inode,
544
const char *name)
545
{
546
struct ceph_vxattr *vxattr = ceph_inode_vxattrs(inode);
547
548
if (vxattr) {
549
while (vxattr->name) {
550
if (!strcmp(vxattr->name, name))
551
return vxattr;
552
vxattr++;
553
}
554
}
555
556
vxattr = ceph_common_vxattrs;
557
while (vxattr->name) {
558
if (!strcmp(vxattr->name, name))
559
return vxattr;
560
vxattr++;
561
}
562
563
return NULL;
564
}
565
566
#define MAX_XATTR_VAL_PRINT_LEN 256
567
568
static int __set_xattr(struct ceph_inode_info *ci,
569
const char *name, int name_len,
570
const char *val, int val_len,
571
int flags, int update_xattr,
572
struct ceph_inode_xattr **newxattr)
573
{
574
struct inode *inode = &ci->netfs.inode;
575
struct ceph_client *cl = ceph_inode_to_client(inode);
576
struct rb_node **p;
577
struct rb_node *parent = NULL;
578
struct ceph_inode_xattr *xattr = NULL;
579
int c;
580
int new = 0;
581
582
p = &ci->i_xattrs.index.rb_node;
583
while (*p) {
584
parent = *p;
585
xattr = rb_entry(parent, struct ceph_inode_xattr, node);
586
c = strncmp(name, xattr->name, min(name_len, xattr->name_len));
587
if (c < 0)
588
p = &(*p)->rb_left;
589
else if (c > 0)
590
p = &(*p)->rb_right;
591
else {
592
if (name_len == xattr->name_len)
593
break;
594
else if (name_len < xattr->name_len)
595
p = &(*p)->rb_left;
596
else
597
p = &(*p)->rb_right;
598
}
599
xattr = NULL;
600
}
601
602
if (update_xattr) {
603
int err = 0;
604
605
if (xattr && (flags & XATTR_CREATE))
606
err = -EEXIST;
607
else if (!xattr && (flags & XATTR_REPLACE))
608
err = -ENODATA;
609
if (err) {
610
kfree(name);
611
kfree(val);
612
kfree(*newxattr);
613
return err;
614
}
615
if (update_xattr < 0) {
616
if (xattr)
617
__remove_xattr(ci, xattr);
618
kfree(name);
619
kfree(*newxattr);
620
return 0;
621
}
622
}
623
624
if (!xattr) {
625
new = 1;
626
xattr = *newxattr;
627
xattr->name = name;
628
xattr->name_len = name_len;
629
xattr->should_free_name = update_xattr;
630
631
ci->i_xattrs.count++;
632
doutc(cl, "count=%d\n", ci->i_xattrs.count);
633
} else {
634
kfree(*newxattr);
635
*newxattr = NULL;
636
if (xattr->should_free_val)
637
kfree(xattr->val);
638
639
if (update_xattr) {
640
kfree(name);
641
name = xattr->name;
642
}
643
ci->i_xattrs.names_size -= xattr->name_len;
644
ci->i_xattrs.vals_size -= xattr->val_len;
645
}
646
ci->i_xattrs.names_size += name_len;
647
ci->i_xattrs.vals_size += val_len;
648
if (val)
649
xattr->val = val;
650
else
651
xattr->val = "";
652
653
xattr->val_len = val_len;
654
xattr->dirty = update_xattr;
655
xattr->should_free_val = (val && update_xattr);
656
657
if (new) {
658
rb_link_node(&xattr->node, parent, p);
659
rb_insert_color(&xattr->node, &ci->i_xattrs.index);
660
doutc(cl, "p=%p\n", p);
661
}
662
663
doutc(cl, "added %p %llx.%llx xattr %p %.*s=%.*s%s\n", inode,
664
ceph_vinop(inode), xattr, name_len, name, min(val_len,
665
MAX_XATTR_VAL_PRINT_LEN), val,
666
val_len > MAX_XATTR_VAL_PRINT_LEN ? "..." : "");
667
668
return 0;
669
}
670
671
static struct ceph_inode_xattr *__get_xattr(struct ceph_inode_info *ci,
672
const char *name)
673
{
674
struct ceph_client *cl = ceph_inode_to_client(&ci->netfs.inode);
675
struct rb_node **p;
676
struct rb_node *parent = NULL;
677
struct ceph_inode_xattr *xattr = NULL;
678
int name_len = strlen(name);
679
int c;
680
681
p = &ci->i_xattrs.index.rb_node;
682
while (*p) {
683
parent = *p;
684
xattr = rb_entry(parent, struct ceph_inode_xattr, node);
685
c = strncmp(name, xattr->name, xattr->name_len);
686
if (c == 0 && name_len > xattr->name_len)
687
c = 1;
688
if (c < 0)
689
p = &(*p)->rb_left;
690
else if (c > 0)
691
p = &(*p)->rb_right;
692
else {
693
int len = min(xattr->val_len, MAX_XATTR_VAL_PRINT_LEN);
694
695
doutc(cl, "%s found %.*s%s\n", name, len, xattr->val,
696
xattr->val_len > len ? "..." : "");
697
return xattr;
698
}
699
}
700
701
doutc(cl, "%s not found\n", name);
702
703
return NULL;
704
}
705
706
static void __free_xattr(struct ceph_inode_xattr *xattr)
707
{
708
BUG_ON(!xattr);
709
710
if (xattr->should_free_name)
711
kfree(xattr->name);
712
if (xattr->should_free_val)
713
kfree(xattr->val);
714
715
kfree(xattr);
716
}
717
718
static int __remove_xattr(struct ceph_inode_info *ci,
719
struct ceph_inode_xattr *xattr)
720
{
721
if (!xattr)
722
return -ENODATA;
723
724
rb_erase(&xattr->node, &ci->i_xattrs.index);
725
726
if (xattr->should_free_name)
727
kfree(xattr->name);
728
if (xattr->should_free_val)
729
kfree(xattr->val);
730
731
ci->i_xattrs.names_size -= xattr->name_len;
732
ci->i_xattrs.vals_size -= xattr->val_len;
733
ci->i_xattrs.count--;
734
kfree(xattr);
735
736
return 0;
737
}
738
739
static char *__copy_xattr_names(struct ceph_inode_info *ci,
740
char *dest)
741
{
742
struct ceph_client *cl = ceph_inode_to_client(&ci->netfs.inode);
743
struct rb_node *p;
744
struct ceph_inode_xattr *xattr = NULL;
745
746
p = rb_first(&ci->i_xattrs.index);
747
doutc(cl, "count=%d\n", ci->i_xattrs.count);
748
749
while (p) {
750
xattr = rb_entry(p, struct ceph_inode_xattr, node);
751
memcpy(dest, xattr->name, xattr->name_len);
752
dest[xattr->name_len] = '\0';
753
754
doutc(cl, "dest=%s %p (%s) (%d/%d)\n", dest, xattr, xattr->name,
755
xattr->name_len, ci->i_xattrs.names_size);
756
757
dest += xattr->name_len + 1;
758
p = rb_next(p);
759
}
760
761
return dest;
762
}
763
764
void __ceph_destroy_xattrs(struct ceph_inode_info *ci)
765
{
766
struct ceph_client *cl = ceph_inode_to_client(&ci->netfs.inode);
767
struct rb_node *p, *tmp;
768
struct ceph_inode_xattr *xattr = NULL;
769
770
p = rb_first(&ci->i_xattrs.index);
771
772
doutc(cl, "p=%p\n", p);
773
774
while (p) {
775
xattr = rb_entry(p, struct ceph_inode_xattr, node);
776
tmp = p;
777
p = rb_next(tmp);
778
doutc(cl, "next p=%p (%.*s)\n", p, xattr->name_len, xattr->name);
779
rb_erase(tmp, &ci->i_xattrs.index);
780
781
__free_xattr(xattr);
782
}
783
784
ci->i_xattrs.names_size = 0;
785
ci->i_xattrs.vals_size = 0;
786
ci->i_xattrs.index_version = 0;
787
ci->i_xattrs.count = 0;
788
ci->i_xattrs.index = RB_ROOT;
789
}
790
791
static int __build_xattrs(struct inode *inode)
792
__releases(ci->i_ceph_lock)
793
__acquires(ci->i_ceph_lock)
794
{
795
struct ceph_client *cl = ceph_inode_to_client(inode);
796
u32 namelen;
797
u32 numattr = 0;
798
void *p, *end;
799
u32 len;
800
const char *name, *val;
801
struct ceph_inode_info *ci = ceph_inode(inode);
802
u64 xattr_version;
803
struct ceph_inode_xattr **xattrs = NULL;
804
int err = 0;
805
int i;
806
807
doutc(cl, "len=%d\n",
808
ci->i_xattrs.blob ? (int)ci->i_xattrs.blob->vec.iov_len : 0);
809
810
if (ci->i_xattrs.index_version >= ci->i_xattrs.version)
811
return 0; /* already built */
812
813
__ceph_destroy_xattrs(ci);
814
815
start:
816
/* updated internal xattr rb tree */
817
if (ci->i_xattrs.blob && ci->i_xattrs.blob->vec.iov_len > 4) {
818
p = ci->i_xattrs.blob->vec.iov_base;
819
end = p + ci->i_xattrs.blob->vec.iov_len;
820
ceph_decode_32_safe(&p, end, numattr, bad);
821
xattr_version = ci->i_xattrs.version;
822
spin_unlock(&ci->i_ceph_lock);
823
824
xattrs = kcalloc(numattr, sizeof(struct ceph_inode_xattr *),
825
GFP_NOFS);
826
err = -ENOMEM;
827
if (!xattrs)
828
goto bad_lock;
829
830
for (i = 0; i < numattr; i++) {
831
xattrs[i] = kmalloc(sizeof(struct ceph_inode_xattr),
832
GFP_NOFS);
833
if (!xattrs[i])
834
goto bad_lock;
835
}
836
837
spin_lock(&ci->i_ceph_lock);
838
if (ci->i_xattrs.version != xattr_version) {
839
/* lost a race, retry */
840
for (i = 0; i < numattr; i++)
841
kfree(xattrs[i]);
842
kfree(xattrs);
843
xattrs = NULL;
844
goto start;
845
}
846
err = -EIO;
847
while (numattr--) {
848
ceph_decode_32_safe(&p, end, len, bad);
849
namelen = len;
850
name = p;
851
p += len;
852
ceph_decode_32_safe(&p, end, len, bad);
853
val = p;
854
p += len;
855
856
err = __set_xattr(ci, name, namelen, val, len,
857
0, 0, &xattrs[numattr]);
858
859
if (err < 0)
860
goto bad;
861
}
862
kfree(xattrs);
863
}
864
ci->i_xattrs.index_version = ci->i_xattrs.version;
865
ci->i_xattrs.dirty = false;
866
867
return err;
868
bad_lock:
869
spin_lock(&ci->i_ceph_lock);
870
bad:
871
if (xattrs) {
872
for (i = 0; i < numattr; i++)
873
kfree(xattrs[i]);
874
kfree(xattrs);
875
}
876
ci->i_xattrs.names_size = 0;
877
return err;
878
}
879
880
static int __get_required_blob_size(struct ceph_inode_info *ci, int name_size,
881
int val_size)
882
{
883
struct ceph_client *cl = ceph_inode_to_client(&ci->netfs.inode);
884
885
/*
886
* 4 bytes for the length, and additional 4 bytes per each xattr name,
887
* 4 bytes per each value
888
*/
889
int size = 4 + ci->i_xattrs.count*(4 + 4) +
890
ci->i_xattrs.names_size +
891
ci->i_xattrs.vals_size;
892
doutc(cl, "c=%d names.size=%d vals.size=%d\n", ci->i_xattrs.count,
893
ci->i_xattrs.names_size, ci->i_xattrs.vals_size);
894
895
if (name_size)
896
size += 4 + 4 + name_size + val_size;
897
898
return size;
899
}
900
901
/*
902
* If there are dirty xattrs, re-encode xattrs into the prealloc_blob
903
* and swap into place. It returns the old i_xattrs.blob (or NULL) so
904
* that it can be freed by the caller as the i_ceph_lock is likely to be
905
* held.
906
*/
907
struct ceph_buffer *__ceph_build_xattrs_blob(struct ceph_inode_info *ci)
908
{
909
struct inode *inode = &ci->netfs.inode;
910
struct ceph_client *cl = ceph_inode_to_client(inode);
911
struct rb_node *p;
912
struct ceph_inode_xattr *xattr = NULL;
913
struct ceph_buffer *old_blob = NULL;
914
void *dest;
915
916
doutc(cl, "%p %llx.%llx\n", inode, ceph_vinop(inode));
917
if (ci->i_xattrs.dirty) {
918
int need = __get_required_blob_size(ci, 0, 0);
919
920
BUG_ON(need > ci->i_xattrs.prealloc_blob->alloc_len);
921
922
p = rb_first(&ci->i_xattrs.index);
923
dest = ci->i_xattrs.prealloc_blob->vec.iov_base;
924
925
ceph_encode_32(&dest, ci->i_xattrs.count);
926
while (p) {
927
xattr = rb_entry(p, struct ceph_inode_xattr, node);
928
929
ceph_encode_32(&dest, xattr->name_len);
930
memcpy(dest, xattr->name, xattr->name_len);
931
dest += xattr->name_len;
932
ceph_encode_32(&dest, xattr->val_len);
933
memcpy(dest, xattr->val, xattr->val_len);
934
dest += xattr->val_len;
935
936
p = rb_next(p);
937
}
938
939
/* adjust buffer len; it may be larger than we need */
940
ci->i_xattrs.prealloc_blob->vec.iov_len =
941
dest - ci->i_xattrs.prealloc_blob->vec.iov_base;
942
943
if (ci->i_xattrs.blob)
944
old_blob = ci->i_xattrs.blob;
945
ci->i_xattrs.blob = ci->i_xattrs.prealloc_blob;
946
ci->i_xattrs.prealloc_blob = NULL;
947
ci->i_xattrs.dirty = false;
948
ci->i_xattrs.version++;
949
}
950
951
return old_blob;
952
}
953
954
static inline int __get_request_mask(struct inode *in) {
955
struct ceph_mds_request *req = current->journal_info;
956
int mask = 0;
957
if (req && req->r_target_inode == in) {
958
if (req->r_op == CEPH_MDS_OP_LOOKUP ||
959
req->r_op == CEPH_MDS_OP_LOOKUPINO ||
960
req->r_op == CEPH_MDS_OP_LOOKUPPARENT ||
961
req->r_op == CEPH_MDS_OP_GETATTR) {
962
mask = le32_to_cpu(req->r_args.getattr.mask);
963
} else if (req->r_op == CEPH_MDS_OP_OPEN ||
964
req->r_op == CEPH_MDS_OP_CREATE) {
965
mask = le32_to_cpu(req->r_args.open.mask);
966
}
967
}
968
return mask;
969
}
970
971
ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value,
972
size_t size)
973
{
974
struct ceph_client *cl = ceph_inode_to_client(inode);
975
struct ceph_inode_info *ci = ceph_inode(inode);
976
struct ceph_inode_xattr *xattr;
977
struct ceph_vxattr *vxattr;
978
int req_mask;
979
ssize_t err;
980
981
if (strncmp(name, XATTR_CEPH_PREFIX, XATTR_CEPH_PREFIX_LEN))
982
goto handle_non_vxattrs;
983
984
/* let's see if a virtual xattr was requested */
985
vxattr = ceph_match_vxattr(inode, name);
986
if (vxattr) {
987
int mask = 0;
988
if (vxattr->flags & VXATTR_FLAG_RSTAT)
989
mask |= CEPH_STAT_RSTAT;
990
if (vxattr->flags & VXATTR_FLAG_DIRSTAT)
991
mask |= CEPH_CAP_FILE_SHARED;
992
err = ceph_do_getattr(inode, mask, true);
993
if (err)
994
return err;
995
err = -ENODATA;
996
if (!(vxattr->exists_cb && !vxattr->exists_cb(ci))) {
997
err = vxattr->getxattr_cb(ci, value, size);
998
if (size && size < err)
999
err = -ERANGE;
1000
}
1001
return err;
1002
} else {
1003
err = ceph_do_getvxattr(inode, name, value, size);
1004
/* this would happen with a new client and old server combo */
1005
if (err == -EOPNOTSUPP)
1006
err = -ENODATA;
1007
return err;
1008
}
1009
handle_non_vxattrs:
1010
req_mask = __get_request_mask(inode);
1011
1012
spin_lock(&ci->i_ceph_lock);
1013
doutc(cl, "%p %llx.%llx name '%s' ver=%lld index_ver=%lld\n", inode,
1014
ceph_vinop(inode), name, ci->i_xattrs.version,
1015
ci->i_xattrs.index_version);
1016
1017
if (ci->i_xattrs.version == 0 ||
1018
!((req_mask & CEPH_CAP_XATTR_SHARED) ||
1019
__ceph_caps_issued_mask_metric(ci, CEPH_CAP_XATTR_SHARED, 1))) {
1020
spin_unlock(&ci->i_ceph_lock);
1021
1022
/* security module gets xattr while filling trace */
1023
if (current->journal_info) {
1024
pr_warn_ratelimited_client(cl,
1025
"sync %p %llx.%llx during filling trace\n",
1026
inode, ceph_vinop(inode));
1027
return -EBUSY;
1028
}
1029
1030
/* get xattrs from mds (if we don't already have them) */
1031
err = ceph_do_getattr(inode, CEPH_STAT_CAP_XATTR, true);
1032
if (err)
1033
return err;
1034
spin_lock(&ci->i_ceph_lock);
1035
}
1036
1037
err = __build_xattrs(inode);
1038
if (err < 0)
1039
goto out;
1040
1041
err = -ENODATA; /* == ENOATTR */
1042
xattr = __get_xattr(ci, name);
1043
if (!xattr)
1044
goto out;
1045
1046
err = -ERANGE;
1047
if (size && size < xattr->val_len)
1048
goto out;
1049
1050
err = xattr->val_len;
1051
if (size == 0)
1052
goto out;
1053
1054
memcpy(value, xattr->val, xattr->val_len);
1055
1056
if (current->journal_info &&
1057
!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) &&
1058
security_ismaclabel(name + XATTR_SECURITY_PREFIX_LEN))
1059
ci->i_ceph_flags |= CEPH_I_SEC_INITED;
1060
out:
1061
spin_unlock(&ci->i_ceph_lock);
1062
return err;
1063
}
1064
1065
ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size)
1066
{
1067
struct inode *inode = d_inode(dentry);
1068
struct ceph_client *cl = ceph_inode_to_client(inode);
1069
struct ceph_inode_info *ci = ceph_inode(inode);
1070
bool len_only = (size == 0);
1071
u32 namelen;
1072
int err;
1073
1074
spin_lock(&ci->i_ceph_lock);
1075
doutc(cl, "%p %llx.%llx ver=%lld index_ver=%lld\n", inode,
1076
ceph_vinop(inode), ci->i_xattrs.version,
1077
ci->i_xattrs.index_version);
1078
1079
if (ci->i_xattrs.version == 0 ||
1080
!__ceph_caps_issued_mask_metric(ci, CEPH_CAP_XATTR_SHARED, 1)) {
1081
spin_unlock(&ci->i_ceph_lock);
1082
err = ceph_do_getattr(inode, CEPH_STAT_CAP_XATTR, true);
1083
if (err)
1084
return err;
1085
spin_lock(&ci->i_ceph_lock);
1086
}
1087
1088
err = __build_xattrs(inode);
1089
if (err < 0)
1090
goto out;
1091
1092
/* add 1 byte for each xattr due to the null termination */
1093
namelen = ci->i_xattrs.names_size + ci->i_xattrs.count;
1094
if (!len_only) {
1095
if (namelen > size) {
1096
err = -ERANGE;
1097
goto out;
1098
}
1099
names = __copy_xattr_names(ci, names);
1100
size -= namelen;
1101
}
1102
err = namelen;
1103
out:
1104
spin_unlock(&ci->i_ceph_lock);
1105
return err;
1106
}
1107
1108
static int ceph_sync_setxattr(struct inode *inode, const char *name,
1109
const char *value, size_t size, int flags)
1110
{
1111
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(inode->i_sb);
1112
struct ceph_client *cl = ceph_inode_to_client(inode);
1113
struct ceph_inode_info *ci = ceph_inode(inode);
1114
struct ceph_mds_request *req;
1115
struct ceph_mds_client *mdsc = fsc->mdsc;
1116
struct ceph_osd_client *osdc = &fsc->client->osdc;
1117
struct ceph_pagelist *pagelist = NULL;
1118
int op = CEPH_MDS_OP_SETXATTR;
1119
int err;
1120
1121
if (size > 0) {
1122
/* copy value into pagelist */
1123
pagelist = ceph_pagelist_alloc(GFP_NOFS);
1124
if (!pagelist)
1125
return -ENOMEM;
1126
1127
err = ceph_pagelist_append(pagelist, value, size);
1128
if (err)
1129
goto out;
1130
} else if (!value) {
1131
if (flags & CEPH_XATTR_REPLACE)
1132
op = CEPH_MDS_OP_RMXATTR;
1133
else
1134
flags |= CEPH_XATTR_REMOVE;
1135
}
1136
1137
doutc(cl, "name %s value size %zu\n", name, size);
1138
1139
/* do request */
1140
req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS);
1141
if (IS_ERR(req)) {
1142
err = PTR_ERR(req);
1143
goto out;
1144
}
1145
1146
req->r_path2 = kstrdup(name, GFP_NOFS);
1147
if (!req->r_path2) {
1148
ceph_mdsc_put_request(req);
1149
err = -ENOMEM;
1150
goto out;
1151
}
1152
1153
if (op == CEPH_MDS_OP_SETXATTR) {
1154
req->r_args.setxattr.flags = cpu_to_le32(flags);
1155
req->r_args.setxattr.osdmap_epoch =
1156
cpu_to_le32(osdc->osdmap->epoch);
1157
req->r_pagelist = pagelist;
1158
pagelist = NULL;
1159
}
1160
1161
req->r_inode = inode;
1162
ihold(inode);
1163
req->r_num_caps = 1;
1164
req->r_inode_drop = CEPH_CAP_XATTR_SHARED;
1165
1166
doutc(cl, "xattr.ver (before): %lld\n", ci->i_xattrs.version);
1167
err = ceph_mdsc_do_request(mdsc, NULL, req);
1168
ceph_mdsc_put_request(req);
1169
doutc(cl, "xattr.ver (after): %lld\n", ci->i_xattrs.version);
1170
1171
out:
1172
if (pagelist)
1173
ceph_pagelist_release(pagelist);
1174
return err;
1175
}
1176
1177
int __ceph_setxattr(struct inode *inode, const char *name,
1178
const void *value, size_t size, int flags)
1179
{
1180
struct ceph_client *cl = ceph_inode_to_client(inode);
1181
struct ceph_vxattr *vxattr;
1182
struct ceph_inode_info *ci = ceph_inode(inode);
1183
struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
1184
struct ceph_cap_flush *prealloc_cf = NULL;
1185
struct ceph_buffer *old_blob = NULL;
1186
int issued;
1187
int err;
1188
int dirty = 0;
1189
int name_len = strlen(name);
1190
int val_len = size;
1191
char *newname = NULL;
1192
char *newval = NULL;
1193
struct ceph_inode_xattr *xattr = NULL;
1194
int required_blob_size;
1195
bool check_realm = false;
1196
bool lock_snap_rwsem = false;
1197
1198
if (ceph_snap(inode) != CEPH_NOSNAP)
1199
return -EROFS;
1200
1201
vxattr = ceph_match_vxattr(inode, name);
1202
if (vxattr) {
1203
if (vxattr->flags & VXATTR_FLAG_READONLY)
1204
return -EOPNOTSUPP;
1205
if (value && !strncmp(vxattr->name, "ceph.quota", 10))
1206
check_realm = true;
1207
}
1208
1209
/* pass any unhandled ceph.* xattrs through to the MDS */
1210
if (!strncmp(name, XATTR_CEPH_PREFIX, XATTR_CEPH_PREFIX_LEN))
1211
goto do_sync_unlocked;
1212
1213
/* preallocate memory for xattr name, value, index node */
1214
err = -ENOMEM;
1215
newname = kmemdup(name, name_len + 1, GFP_NOFS);
1216
if (!newname)
1217
goto out;
1218
1219
if (val_len) {
1220
newval = kmemdup(value, val_len, GFP_NOFS);
1221
if (!newval)
1222
goto out;
1223
}
1224
1225
xattr = kmalloc(sizeof(struct ceph_inode_xattr), GFP_NOFS);
1226
if (!xattr)
1227
goto out;
1228
1229
prealloc_cf = ceph_alloc_cap_flush();
1230
if (!prealloc_cf)
1231
goto out;
1232
1233
spin_lock(&ci->i_ceph_lock);
1234
retry:
1235
issued = __ceph_caps_issued(ci, NULL);
1236
required_blob_size = __get_required_blob_size(ci, name_len, val_len);
1237
if ((ci->i_xattrs.version == 0) || !(issued & CEPH_CAP_XATTR_EXCL) ||
1238
(required_blob_size > mdsc->mdsmap->m_max_xattr_size)) {
1239
doutc(cl, "sync version: %llu size: %d max: %llu\n",
1240
ci->i_xattrs.version, required_blob_size,
1241
mdsc->mdsmap->m_max_xattr_size);
1242
goto do_sync;
1243
}
1244
1245
if (!lock_snap_rwsem && !ci->i_head_snapc) {
1246
lock_snap_rwsem = true;
1247
if (!down_read_trylock(&mdsc->snap_rwsem)) {
1248
spin_unlock(&ci->i_ceph_lock);
1249
down_read(&mdsc->snap_rwsem);
1250
spin_lock(&ci->i_ceph_lock);
1251
goto retry;
1252
}
1253
}
1254
1255
doutc(cl, "%p %llx.%llx name '%s' issued %s\n", inode,
1256
ceph_vinop(inode), name, ceph_cap_string(issued));
1257
__build_xattrs(inode);
1258
1259
if (!ci->i_xattrs.prealloc_blob ||
1260
required_blob_size > ci->i_xattrs.prealloc_blob->alloc_len) {
1261
struct ceph_buffer *blob;
1262
1263
spin_unlock(&ci->i_ceph_lock);
1264
ceph_buffer_put(old_blob); /* Shouldn't be required */
1265
doutc(cl, " pre-allocating new blob size=%d\n",
1266
required_blob_size);
1267
blob = ceph_buffer_new(required_blob_size, GFP_NOFS);
1268
if (!blob)
1269
goto do_sync_unlocked;
1270
spin_lock(&ci->i_ceph_lock);
1271
/* prealloc_blob can't be released while holding i_ceph_lock */
1272
if (ci->i_xattrs.prealloc_blob)
1273
old_blob = ci->i_xattrs.prealloc_blob;
1274
ci->i_xattrs.prealloc_blob = blob;
1275
goto retry;
1276
}
1277
1278
err = __set_xattr(ci, newname, name_len, newval, val_len,
1279
flags, value ? 1 : -1, &xattr);
1280
1281
if (!err) {
1282
dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL,
1283
&prealloc_cf);
1284
ci->i_xattrs.dirty = true;
1285
inode_set_ctime_current(inode);
1286
}
1287
1288
spin_unlock(&ci->i_ceph_lock);
1289
ceph_buffer_put(old_blob);
1290
if (lock_snap_rwsem)
1291
up_read(&mdsc->snap_rwsem);
1292
if (dirty)
1293
__mark_inode_dirty(inode, dirty);
1294
ceph_free_cap_flush(prealloc_cf);
1295
return err;
1296
1297
do_sync:
1298
spin_unlock(&ci->i_ceph_lock);
1299
do_sync_unlocked:
1300
if (lock_snap_rwsem)
1301
up_read(&mdsc->snap_rwsem);
1302
1303
/* security module set xattr while filling trace */
1304
if (current->journal_info) {
1305
pr_warn_ratelimited_client(cl,
1306
"sync %p %llx.%llx during filling trace\n",
1307
inode, ceph_vinop(inode));
1308
err = -EBUSY;
1309
} else {
1310
err = ceph_sync_setxattr(inode, name, value, size, flags);
1311
if (err >= 0 && check_realm) {
1312
/* check if snaprealm was created for quota inode */
1313
spin_lock(&ci->i_ceph_lock);
1314
if ((ci->i_max_files || ci->i_max_bytes) &&
1315
!(ci->i_snap_realm &&
1316
ci->i_snap_realm->ino == ci->i_vino.ino))
1317
err = -EOPNOTSUPP;
1318
spin_unlock(&ci->i_ceph_lock);
1319
}
1320
}
1321
out:
1322
ceph_free_cap_flush(prealloc_cf);
1323
kfree(newname);
1324
kfree(newval);
1325
kfree(xattr);
1326
return err;
1327
}
1328
1329
static int ceph_get_xattr_handler(const struct xattr_handler *handler,
1330
struct dentry *dentry, struct inode *inode,
1331
const char *name, void *value, size_t size)
1332
{
1333
if (!ceph_is_valid_xattr(name))
1334
return -EOPNOTSUPP;
1335
return __ceph_getxattr(inode, name, value, size);
1336
}
1337
1338
static int ceph_set_xattr_handler(const struct xattr_handler *handler,
1339
struct mnt_idmap *idmap,
1340
struct dentry *unused, struct inode *inode,
1341
const char *name, const void *value,
1342
size_t size, int flags)
1343
{
1344
if (!ceph_is_valid_xattr(name))
1345
return -EOPNOTSUPP;
1346
return __ceph_setxattr(inode, name, value, size, flags);
1347
}
1348
1349
static const struct xattr_handler ceph_other_xattr_handler = {
1350
.prefix = "", /* match any name => handlers called with full name */
1351
.get = ceph_get_xattr_handler,
1352
.set = ceph_set_xattr_handler,
1353
};
1354
1355
#ifdef CONFIG_SECURITY
1356
bool ceph_security_xattr_wanted(struct inode *in)
1357
{
1358
return in->i_security != NULL;
1359
}
1360
1361
bool ceph_security_xattr_deadlock(struct inode *in)
1362
{
1363
struct ceph_inode_info *ci;
1364
bool ret;
1365
if (!in->i_security)
1366
return false;
1367
ci = ceph_inode(in);
1368
spin_lock(&ci->i_ceph_lock);
1369
ret = !(ci->i_ceph_flags & CEPH_I_SEC_INITED) &&
1370
!(ci->i_xattrs.version > 0 &&
1371
__ceph_caps_issued_mask(ci, CEPH_CAP_XATTR_SHARED, 0));
1372
spin_unlock(&ci->i_ceph_lock);
1373
return ret;
1374
}
1375
1376
#ifdef CONFIG_CEPH_FS_SECURITY_LABEL
1377
int ceph_security_init_secctx(struct dentry *dentry, umode_t mode,
1378
struct ceph_acl_sec_ctx *as_ctx)
1379
{
1380
struct ceph_pagelist *pagelist = as_ctx->pagelist;
1381
const char *name;
1382
size_t name_len;
1383
int err;
1384
1385
err = security_dentry_init_security(dentry, mode, &dentry->d_name,
1386
&name, &as_ctx->lsmctx);
1387
if (err < 0) {
1388
WARN_ON_ONCE(err != -EOPNOTSUPP);
1389
err = 0; /* do nothing */
1390
goto out;
1391
}
1392
1393
err = -ENOMEM;
1394
if (!pagelist) {
1395
pagelist = ceph_pagelist_alloc(GFP_KERNEL);
1396
if (!pagelist)
1397
goto out;
1398
err = ceph_pagelist_reserve(pagelist, PAGE_SIZE);
1399
if (err)
1400
goto out;
1401
ceph_pagelist_encode_32(pagelist, 1);
1402
}
1403
1404
/*
1405
* FIXME: Make security_dentry_init_security() generic. Currently
1406
* It only supports single security module and only selinux has
1407
* dentry_init_security hook.
1408
*/
1409
name_len = strlen(name);
1410
err = ceph_pagelist_reserve(pagelist,
1411
4 * 2 + name_len + as_ctx->lsmctx.len);
1412
if (err)
1413
goto out;
1414
1415
if (as_ctx->pagelist) {
1416
/* update count of KV pairs */
1417
BUG_ON(pagelist->length <= sizeof(__le32));
1418
if (list_is_singular(&pagelist->head)) {
1419
le32_add_cpu((__le32*)pagelist->mapped_tail, 1);
1420
} else {
1421
struct page *page = list_first_entry(&pagelist->head,
1422
struct page, lru);
1423
void *addr = kmap_atomic(page);
1424
le32_add_cpu((__le32*)addr, 1);
1425
kunmap_atomic(addr);
1426
}
1427
} else {
1428
as_ctx->pagelist = pagelist;
1429
}
1430
1431
ceph_pagelist_encode_32(pagelist, name_len);
1432
ceph_pagelist_append(pagelist, name, name_len);
1433
1434
ceph_pagelist_encode_32(pagelist, as_ctx->lsmctx.len);
1435
ceph_pagelist_append(pagelist, as_ctx->lsmctx.context,
1436
as_ctx->lsmctx.len);
1437
1438
err = 0;
1439
out:
1440
if (pagelist && !as_ctx->pagelist)
1441
ceph_pagelist_release(pagelist);
1442
return err;
1443
}
1444
#endif /* CONFIG_CEPH_FS_SECURITY_LABEL */
1445
#endif /* CONFIG_SECURITY */
1446
1447
void ceph_release_acl_sec_ctx(struct ceph_acl_sec_ctx *as_ctx)
1448
{
1449
#ifdef CONFIG_CEPH_FS_POSIX_ACL
1450
posix_acl_release(as_ctx->acl);
1451
posix_acl_release(as_ctx->default_acl);
1452
#endif
1453
#ifdef CONFIG_CEPH_FS_SECURITY_LABEL
1454
security_release_secctx(&as_ctx->lsmctx);
1455
#endif
1456
#ifdef CONFIG_FS_ENCRYPTION
1457
kfree(as_ctx->fscrypt_auth);
1458
#endif
1459
if (as_ctx->pagelist)
1460
ceph_pagelist_release(as_ctx->pagelist);
1461
}
1462
1463
/*
1464
* List of handlers for synthetic system.* attributes. Other
1465
* attributes are handled directly.
1466
*/
1467
const struct xattr_handler * const ceph_xattr_handlers[] = {
1468
&ceph_other_xattr_handler,
1469
NULL,
1470
};
1471
1472