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