1
/* -*- mode: c; c-basic-offset: 8; -*-
2
* vim: noexpandtab sw=8 ts=8 sts=0:
6
* Copyright (C) 2004, 2008 Oracle. All rights reserved.
8
* This program is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU General Public
10
* License version 2 as published by the Free Software Foundation.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* General Public License for more details.
20
#include "ocfs2/byteorder.h"
21
#include "ocfs2/ocfs2.h"
23
struct ocfs2_xattr_def_value_root {
24
struct ocfs2_xattr_value_root xv;
25
struct ocfs2_extent_rec er;
28
#define OCFS2_XATTR_ROOT_SIZE (sizeof(struct ocfs2_xattr_def_value_root))
30
uint32_t ocfs2_xattr_uuid_hash(unsigned char *uuid)
34
for (i = 0; i < OCFS2_VOL_UUID_LEN; i++) {
35
hash = (hash << OCFS2_HASH_SHIFT) ^
36
(hash >> (8*sizeof(hash) - OCFS2_HASH_SHIFT)) ^
42
uint32_t ocfs2_xattr_name_hash(uint32_t uuid_hash,
46
/* Get hash value of uuid from super block */
47
uint32_t hash = uuid_hash;
50
/* hash extended attribute name */
51
for (i = 0; i < name_len; i++) {
52
hash = (hash << OCFS2_HASH_SHIFT) ^
53
(hash >> (8*sizeof(hash) - OCFS2_HASH_SHIFT)) ^
60
uint16_t ocfs2_xattr_buckets_per_cluster(ocfs2_filesys *fs)
62
return fs->fs_clustersize / OCFS2_XATTR_BUCKET_SIZE;
65
uint16_t ocfs2_blocks_per_xattr_bucket(ocfs2_filesys *fs)
67
return OCFS2_XATTR_BUCKET_SIZE / fs->fs_blocksize;
70
static void ocfs2_swap_xattr_entry(struct ocfs2_xattr_entry *xe)
72
xe->xe_name_hash = bswap_32(xe->xe_name_hash);
73
xe->xe_name_offset = bswap_16(xe->xe_name_offset);
74
xe->xe_value_size = bswap_64(xe->xe_value_size);
77
static void ocfs2_swap_xattr_tree_root(struct ocfs2_xattr_tree_root *xt)
79
xt->xt_clusters = bswap_32(xt->xt_clusters);
80
xt->xt_last_eb_blk = bswap_64(xt->xt_last_eb_blk);
83
static void ocfs2_swap_xattr_value_root(struct ocfs2_xattr_value_root *xr)
85
xr->xr_clusters = bswap_32(xr->xr_clusters);
86
xr->xr_last_eb_blk = bswap_64(xr->xr_last_eb_blk);
89
static void ocfs2_swap_xattr_block_header(struct ocfs2_xattr_block *xb)
91
xb->xb_suballoc_slot = bswap_16(xb->xb_suballoc_slot);
92
xb->xb_suballoc_bit = bswap_16(xb->xb_suballoc_bit);
93
xb->xb_fs_generation = bswap_32(xb->xb_fs_generation);
94
xb->xb_blkno = bswap_64(xb->xb_blkno);
95
xb->xb_flags = bswap_16(xb->xb_flags);
98
static void ocfs2_swap_xattr_header(struct ocfs2_xattr_header *xh)
100
if (cpu_is_little_endian)
103
xh->xh_count = bswap_16(xh->xh_count);
104
xh->xh_free_start = bswap_16(xh->xh_free_start);
105
xh->xh_name_value_len = bswap_16(xh->xh_name_value_len);
106
xh->xh_num_buckets = bswap_16(xh->xh_num_buckets);
109
static void ocfs2_swap_xattr_entries_to_cpu(struct ocfs2_xattr_header *xh)
113
if (cpu_is_little_endian)
116
for (i = 0; i < xh->xh_count; i++) {
117
struct ocfs2_xattr_entry *xe = &xh->xh_entries[i];
119
ocfs2_swap_xattr_entry(xe);
121
if (!ocfs2_xattr_is_local(xe)) {
122
struct ocfs2_xattr_value_root *xr =
123
(struct ocfs2_xattr_value_root *)
124
((char *)xh + xe->xe_name_offset +
125
OCFS2_XATTR_SIZE(xe->xe_name_len));
127
ocfs2_swap_xattr_value_root(xr);
128
ocfs2_swap_extent_list_to_cpu(&xr->xr_list);
133
static void ocfs2_swap_xattr_entries_from_cpu(struct ocfs2_xattr_header *xh)
137
if (cpu_is_little_endian)
140
for (i = 0; i < xh->xh_count; i++) {
141
struct ocfs2_xattr_entry *xe = &xh->xh_entries[i];
143
if (!ocfs2_xattr_is_local(xe)) {
144
struct ocfs2_xattr_value_root *xr =
145
(struct ocfs2_xattr_value_root *)
146
((char *)xh + xe->xe_name_offset +
147
OCFS2_XATTR_SIZE(xe->xe_name_len));
149
ocfs2_swap_extent_list_from_cpu(&xr->xr_list);
150
ocfs2_swap_xattr_value_root(xr);
152
ocfs2_swap_xattr_entry(xe);
156
void ocfs2_swap_xattrs_to_cpu(struct ocfs2_xattr_header *xh)
158
ocfs2_swap_xattr_header(xh);
159
ocfs2_swap_xattr_entries_to_cpu(xh);
162
void ocfs2_swap_xattrs_from_cpu(struct ocfs2_xattr_header *xh)
164
ocfs2_swap_xattr_entries_from_cpu(xh);
165
ocfs2_swap_xattr_header(xh);
168
void ocfs2_swap_xattr_block_to_cpu(struct ocfs2_xattr_block *xb)
170
if (cpu_is_little_endian)
173
ocfs2_swap_xattr_block_header(xb);
174
if (!(xb->xb_flags & OCFS2_XATTR_INDEXED)) {
175
ocfs2_swap_xattr_header(&xb->xb_attrs.xb_header);
176
ocfs2_swap_xattr_entries_to_cpu(&xb->xb_attrs.xb_header);
178
ocfs2_swap_xattr_tree_root(&xb->xb_attrs.xb_root);
179
ocfs2_swap_extent_list_to_cpu(&xb->xb_attrs.xb_root.xt_list);
183
void ocfs2_swap_xattr_block_from_cpu(struct ocfs2_xattr_block *xb)
185
if (cpu_is_little_endian)
188
if (!(xb->xb_flags & OCFS2_XATTR_INDEXED)) {
189
ocfs2_swap_xattr_entries_from_cpu(&xb->xb_attrs.xb_header);
190
ocfs2_swap_xattr_header(&xb->xb_attrs.xb_header);
192
ocfs2_swap_extent_list_from_cpu(&xb->xb_attrs.xb_root.xt_list);
193
ocfs2_swap_xattr_tree_root(&xb->xb_attrs.xb_root);
196
ocfs2_swap_xattr_block_header(xb);
199
errcode_t ocfs2_read_xattr_block(ocfs2_filesys *fs,
205
struct ocfs2_xattr_block *xb;
207
if ((blkno < OCFS2_SUPER_BLOCK_BLKNO) ||
208
(blkno > fs->fs_blocks))
209
return OCFS2_ET_BAD_BLKNO;
211
ret = ocfs2_malloc_block(fs->fs_io, &blk);
215
ret = io_read_block(fs->fs_io, blkno, 1, blk);
219
xb = (struct ocfs2_xattr_block *)blk;
221
ret = ocfs2_validate_meta_ecc(fs, blk, &xb->xb_check);
225
if (memcmp(xb->xb_signature, OCFS2_XATTR_BLOCK_SIGNATURE,
226
strlen(OCFS2_XATTR_BLOCK_SIGNATURE))) {
227
ret = OCFS2_ET_BAD_XATTR_BLOCK_MAGIC;
231
memcpy(xb_buf, blk, fs->fs_blocksize);
232
xb = (struct ocfs2_xattr_block *)xb_buf;
233
ocfs2_swap_xattr_block_to_cpu(xb);
239
errcode_t ocfs2_write_xattr_block(ocfs2_filesys *fs,
245
struct ocfs2_xattr_block *xb;
247
if (!(fs->fs_flags & OCFS2_FLAG_RW))
248
return OCFS2_ET_RO_FILESYS;
250
if ((blkno < OCFS2_SUPER_BLOCK_BLKNO) ||
251
(blkno > fs->fs_blocks))
252
return OCFS2_ET_BAD_BLKNO;
254
ret = ocfs2_malloc_block(fs->fs_io, &blk);
258
memcpy(blk, xb_buf, fs->fs_blocksize);
260
xb = (struct ocfs2_xattr_block *)blk;
261
ocfs2_swap_xattr_block_from_cpu(xb);
263
ocfs2_compute_meta_ecc(fs, blk, &xb->xb_check);
264
ret = io_write_block(fs->fs_io, blkno, 1, blk);
266
fs->fs_flags |= OCFS2_FLAG_CHANGED;
272
errcode_t ocfs2_xattr_get_rec(ocfs2_filesys *fs,
273
struct ocfs2_xattr_block *xb,
277
uint32_t *num_clusters)
282
struct ocfs2_extent_block *eb;
283
struct ocfs2_extent_rec *rec = NULL;
284
struct ocfs2_extent_list *el = &xb->xb_attrs.xb_root.xt_list;
285
uint64_t e_blkno = 0;
287
if (!(xb->xb_flags & OCFS2_XATTR_INDEXED))
288
return OCFS2_ET_INVALID_ARGUMENT;
290
if (el->l_tree_depth) {
291
ret = ocfs2_xattr_find_leaf(fs, xb, name_hash, &eb_buf);
295
eb = (struct ocfs2_extent_block *) eb_buf;
298
if (el->l_tree_depth) {
299
ret = OCFS2_ET_INVALID_ARGUMENT;
304
for (i = el->l_next_free_rec - 1; i >= 0; i--) {
305
rec = &el->l_recs[i];
307
if (rec->e_cpos <= name_hash) {
308
e_blkno = rec->e_blkno;
314
ret = OCFS2_ET_INVALID_ARGUMENT;
318
*p_blkno = rec->e_blkno;
319
*num_clusters = rec->e_leaf_clusters;
321
*e_cpos = rec->e_cpos;
328
uint16_t ocfs2_xattr_value_real_size(uint16_t name_len,
333
if (value_len <= OCFS2_XATTR_INLINE_SIZE)
334
size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_SIZE(value_len);
336
size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_ROOT_SIZE;
341
uint16_t ocfs2_xattr_min_offset(struct ocfs2_xattr_header *xh, uint16_t size)
344
uint16_t min_offs = size;
346
for (i = 0 ; i < xh->xh_count; i++) {
347
struct ocfs2_xattr_entry *xe = &xh->xh_entries[i];
348
size_t offs = xe->xe_name_offset;
356
uint16_t ocfs2_xattr_name_value_len(struct ocfs2_xattr_header *xh)
359
uint16_t total_len = 0;
361
for (i = 0 ; i < xh->xh_count; i++) {
362
struct ocfs2_xattr_entry *xe = &xh->xh_entries[i];
364
total_len += ocfs2_xattr_value_real_size(xe->xe_name_len,
370
errcode_t ocfs2_read_xattr_bucket(ocfs2_filesys *fs,
376
struct ocfs2_xattr_header *xh;
377
int blk_per_bucket = ocfs2_blocks_per_xattr_bucket(fs);
379
ret = ocfs2_malloc_blocks(fs->fs_io, blk_per_bucket, &bucket);
383
ret = io_read_block(fs->fs_io, blkno, blk_per_bucket, bucket);
387
xh = (struct ocfs2_xattr_header *)bucket;
388
if (ocfs2_meta_ecc(OCFS2_RAW_SB(fs->fs_super))) {
389
ret = ocfs2_block_check_validate(bucket,
390
OCFS2_XATTR_BUCKET_SIZE,
396
memcpy(bucket_buf, bucket, OCFS2_XATTR_BUCKET_SIZE);
397
xh = (struct ocfs2_xattr_header *)bucket_buf;
398
ocfs2_swap_xattrs_to_cpu(xh);
404
errcode_t ocfs2_write_xattr_bucket(ocfs2_filesys *fs,
411
struct ocfs2_xattr_header *xh;
412
int blk_per_bucket = ocfs2_blocks_per_xattr_bucket(fs);
414
if (!(fs->fs_flags & OCFS2_FLAG_RW))
415
return OCFS2_ET_RO_FILESYS;
417
if ((blkno < OCFS2_SUPER_BLOCK_BLKNO) ||
418
(blkno > fs->fs_blocks))
419
return OCFS2_ET_BAD_BLKNO;
421
ret = ocfs2_malloc_blocks(fs->fs_io, blk_per_bucket, &bucket);
425
memcpy(bucket, bucket_buf, OCFS2_XATTR_BUCKET_SIZE);
427
xh = (struct ocfs2_xattr_header *)bucket;
428
ocfs2_swap_xattrs_from_cpu(xh);
430
if (ocfs2_meta_ecc(OCFS2_RAW_SB(fs->fs_super)))
431
ocfs2_block_check_compute(bucket, OCFS2_XATTR_BUCKET_SIZE,
434
ret = io_write_block(fs->fs_io, blkno, blk_per_bucket, bucket);
436
fs->fs_flags |= OCFS2_FLAG_CHANGED;