blob: fb17f7fe4c66b458b11440e61121b112ec45ae80 [file] [log] [blame]
Tao Maf56654c2008-08-18 17:38:48 +08001/* -*- mode: c; c-basic-offset: 8; -*-
2 * vim: noexpandtab sw=8 ts=8 sts=0:
3 *
4 * xattr.c
5 *
6 * Copyright (C) 2008 Oracle. All rights reserved.
7 *
Tiger Yangcf1d6c72008-08-18 17:11:00 +08008 * CREDITS:
9 * Lots of code in this file is taken from ext3.
10 *
Tao Maf56654c2008-08-18 17:38:48 +080011 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public
22 * License along with this program; if not, write to the
23 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 * Boston, MA 021110-1307, USA.
25 */
26
Tiger Yangcf1d6c72008-08-18 17:11:00 +080027#include <linux/capability.h>
28#include <linux/fs.h>
29#include <linux/types.h>
30#include <linux/slab.h>
31#include <linux/highmem.h>
32#include <linux/pagemap.h>
33#include <linux/uio.h>
34#include <linux/sched.h>
35#include <linux/splice.h>
36#include <linux/mount.h>
37#include <linux/writeback.h>
38#include <linux/falloc.h>
39
Tao Maf56654c2008-08-18 17:38:48 +080040#define MLOG_MASK_PREFIX ML_XATTR
41#include <cluster/masklog.h>
42
43#include "ocfs2.h"
44#include "alloc.h"
45#include "dlmglue.h"
46#include "file.h"
Tiger Yangcf1d6c72008-08-18 17:11:00 +080047#include "symlink.h"
48#include "sysfile.h"
Tao Maf56654c2008-08-18 17:38:48 +080049#include "inode.h"
50#include "journal.h"
51#include "ocfs2_fs.h"
52#include "suballoc.h"
53#include "uptodate.h"
54#include "buffer_head_io.h"
Tao Ma0c044f02008-08-18 17:38:50 +080055#include "super.h"
Tiger Yangcf1d6c72008-08-18 17:11:00 +080056#include "xattr.h"
57
58
59struct ocfs2_xattr_def_value_root {
60 struct ocfs2_xattr_value_root xv;
61 struct ocfs2_extent_rec er;
62};
63
Tao Ma0c044f02008-08-18 17:38:50 +080064struct ocfs2_xattr_bucket {
65 struct buffer_head *bhs[OCFS2_XATTR_MAX_BLOCKS_PER_BUCKET];
66 struct ocfs2_xattr_header *xh;
67};
68
Tiger Yangcf1d6c72008-08-18 17:11:00 +080069#define OCFS2_XATTR_ROOT_SIZE (sizeof(struct ocfs2_xattr_def_value_root))
70#define OCFS2_XATTR_INLINE_SIZE 80
71
72static struct ocfs2_xattr_def_value_root def_xv = {
73 .xv.xr_list.l_count = cpu_to_le16(1),
74};
75
76struct xattr_handler *ocfs2_xattr_handlers[] = {
77 &ocfs2_xattr_user_handler,
78 &ocfs2_xattr_trusted_handler,
79 NULL
80};
81
82static struct xattr_handler *ocfs2_xattr_handler_map[] = {
83 [OCFS2_XATTR_INDEX_USER] = &ocfs2_xattr_user_handler,
84 [OCFS2_XATTR_INDEX_TRUSTED] = &ocfs2_xattr_trusted_handler,
85};
86
87struct ocfs2_xattr_info {
88 int name_index;
89 const char *name;
90 const void *value;
91 size_t value_len;
92};
93
94struct ocfs2_xattr_search {
95 struct buffer_head *inode_bh;
96 /*
97 * xattr_bh point to the block buffer head which has extended attribute
98 * when extended attribute in inode, xattr_bh is equal to inode_bh.
99 */
100 struct buffer_head *xattr_bh;
101 struct ocfs2_xattr_header *header;
102 void *base;
103 void *end;
104 struct ocfs2_xattr_entry *here;
105 int not_found;
106};
107
Tao Ma0c044f02008-08-18 17:38:50 +0800108static int ocfs2_xattr_tree_list_index_block(struct inode *inode,
109 struct ocfs2_xattr_tree_root *xt,
110 char *buffer,
111 size_t buffer_size);
112
Tiger Yangcf1d6c72008-08-18 17:11:00 +0800113static inline struct xattr_handler *ocfs2_xattr_handler(int name_index)
114{
115 struct xattr_handler *handler = NULL;
116
117 if (name_index > 0 && name_index < OCFS2_XATTR_MAX)
118 handler = ocfs2_xattr_handler_map[name_index];
119
120 return handler;
121}
122
123static inline u32 ocfs2_xattr_name_hash(struct inode *inode,
124 char *prefix,
125 int prefix_len,
126 char *name,
127 int name_len)
128{
129 /* Get hash value of uuid from super block */
130 u32 hash = OCFS2_SB(inode->i_sb)->uuid_hash;
131 int i;
132
133 /* hash extended attribute prefix */
134 for (i = 0; i < prefix_len; i++) {
135 hash = (hash << OCFS2_HASH_SHIFT) ^
136 (hash >> (8*sizeof(hash) - OCFS2_HASH_SHIFT)) ^
137 *prefix++;
138 }
139 /* hash extended attribute name */
140 for (i = 0; i < name_len; i++) {
141 hash = (hash << OCFS2_HASH_SHIFT) ^
142 (hash >> (8*sizeof(hash) - OCFS2_HASH_SHIFT)) ^
143 *name++;
144 }
145
146 return hash;
147}
148
149/*
150 * ocfs2_xattr_hash_entry()
151 *
152 * Compute the hash of an extended attribute.
153 */
154static void ocfs2_xattr_hash_entry(struct inode *inode,
155 struct ocfs2_xattr_header *header,
156 struct ocfs2_xattr_entry *entry)
157{
158 u32 hash = 0;
159 struct xattr_handler *handler =
160 ocfs2_xattr_handler(ocfs2_xattr_get_type(entry));
161 char *prefix = handler->prefix;
162 char *name = (char *)header + le16_to_cpu(entry->xe_name_offset);
163 int prefix_len = strlen(handler->prefix);
164
165 hash = ocfs2_xattr_name_hash(inode, prefix, prefix_len, name,
166 entry->xe_name_len);
167 entry->xe_name_hash = cpu_to_le32(hash);
168
169 return;
170}
Tao Maf56654c2008-08-18 17:38:48 +0800171
172static int ocfs2_xattr_extend_allocation(struct inode *inode,
173 u32 clusters_to_add,
174 struct buffer_head *xattr_bh,
175 struct ocfs2_xattr_value_root *xv)
176{
177 int status = 0;
178 int restart_func = 0;
179 int credits = 0;
180 handle_t *handle = NULL;
181 struct ocfs2_alloc_context *data_ac = NULL;
182 struct ocfs2_alloc_context *meta_ac = NULL;
183 enum ocfs2_alloc_restarted why;
184 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
185 struct ocfs2_extent_list *root_el = &xv->xr_list;
186 u32 prev_clusters, logical_start = le32_to_cpu(xv->xr_clusters);
187
188 mlog(0, "(clusters_to_add for xattr= %u)\n", clusters_to_add);
189
190restart_all:
191
192 status = ocfs2_lock_allocators(inode, xattr_bh, root_el,
193 clusters_to_add, 0, &data_ac,
194 &meta_ac, OCFS2_XATTR_VALUE_EXTENT, xv);
195 if (status) {
196 mlog_errno(status);
197 goto leave;
198 }
199
200 credits = ocfs2_calc_extend_credits(osb->sb, root_el, clusters_to_add);
201 handle = ocfs2_start_trans(osb, credits);
202 if (IS_ERR(handle)) {
203 status = PTR_ERR(handle);
204 handle = NULL;
205 mlog_errno(status);
206 goto leave;
207 }
208
209restarted_transaction:
210 status = ocfs2_journal_access(handle, inode, xattr_bh,
211 OCFS2_JOURNAL_ACCESS_WRITE);
212 if (status < 0) {
213 mlog_errno(status);
214 goto leave;
215 }
216
217 prev_clusters = le32_to_cpu(xv->xr_clusters);
218 status = ocfs2_add_clusters_in_btree(osb,
219 inode,
220 &logical_start,
221 clusters_to_add,
222 0,
223 xattr_bh,
224 root_el,
225 handle,
226 data_ac,
227 meta_ac,
228 &why,
229 OCFS2_XATTR_VALUE_EXTENT,
230 xv);
231 if ((status < 0) && (status != -EAGAIN)) {
232 if (status != -ENOSPC)
233 mlog_errno(status);
234 goto leave;
235 }
236
237 status = ocfs2_journal_dirty(handle, xattr_bh);
238 if (status < 0) {
239 mlog_errno(status);
240 goto leave;
241 }
242
243 clusters_to_add -= le32_to_cpu(xv->xr_clusters) - prev_clusters;
244
245 if (why != RESTART_NONE && clusters_to_add) {
246 if (why == RESTART_META) {
247 mlog(0, "restarting function.\n");
248 restart_func = 1;
249 } else {
250 BUG_ON(why != RESTART_TRANS);
251
252 mlog(0, "restarting transaction.\n");
253 /* TODO: This can be more intelligent. */
254 credits = ocfs2_calc_extend_credits(osb->sb,
255 root_el,
256 clusters_to_add);
257 status = ocfs2_extend_trans(handle, credits);
258 if (status < 0) {
259 /* handle still has to be committed at
260 * this point. */
261 status = -ENOMEM;
262 mlog_errno(status);
263 goto leave;
264 }
265 goto restarted_transaction;
266 }
267 }
268
269leave:
270 if (handle) {
271 ocfs2_commit_trans(osb, handle);
272 handle = NULL;
273 }
274 if (data_ac) {
275 ocfs2_free_alloc_context(data_ac);
276 data_ac = NULL;
277 }
278 if (meta_ac) {
279 ocfs2_free_alloc_context(meta_ac);
280 meta_ac = NULL;
281 }
282 if ((!status) && restart_func) {
283 restart_func = 0;
284 goto restart_all;
285 }
286
287 return status;
288}
289
290static int __ocfs2_remove_xattr_range(struct inode *inode,
291 struct buffer_head *root_bh,
292 struct ocfs2_xattr_value_root *xv,
293 u32 cpos, u32 phys_cpos, u32 len,
294 struct ocfs2_cached_dealloc_ctxt *dealloc)
295{
296 int ret;
297 u64 phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos);
298 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
299 struct inode *tl_inode = osb->osb_tl_inode;
300 handle_t *handle;
301 struct ocfs2_alloc_context *meta_ac = NULL;
302
303 ret = ocfs2_lock_allocators(inode, root_bh, &xv->xr_list,
304 0, 1, NULL, &meta_ac,
305 OCFS2_XATTR_VALUE_EXTENT, xv);
306 if (ret) {
307 mlog_errno(ret);
308 return ret;
309 }
310
311 mutex_lock(&tl_inode->i_mutex);
312
313 if (ocfs2_truncate_log_needs_flush(osb)) {
314 ret = __ocfs2_flush_truncate_log(osb);
315 if (ret < 0) {
316 mlog_errno(ret);
317 goto out;
318 }
319 }
320
321 handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS);
322 if (IS_ERR(handle)) {
323 ret = PTR_ERR(handle);
324 mlog_errno(ret);
325 goto out;
326 }
327
328 ret = ocfs2_journal_access(handle, inode, root_bh,
329 OCFS2_JOURNAL_ACCESS_WRITE);
330 if (ret) {
331 mlog_errno(ret);
332 goto out_commit;
333 }
334
335 ret = ocfs2_remove_extent(inode, root_bh, cpos, len, handle, meta_ac,
336 dealloc, OCFS2_XATTR_VALUE_EXTENT, xv);
337 if (ret) {
338 mlog_errno(ret);
339 goto out_commit;
340 }
341
342 le32_add_cpu(&xv->xr_clusters, -len);
343
344 ret = ocfs2_journal_dirty(handle, root_bh);
345 if (ret) {
346 mlog_errno(ret);
347 goto out_commit;
348 }
349
350 ret = ocfs2_truncate_log_append(osb, handle, phys_blkno, len);
351 if (ret)
352 mlog_errno(ret);
353
354out_commit:
355 ocfs2_commit_trans(osb, handle);
356out:
357 mutex_unlock(&tl_inode->i_mutex);
358
359 if (meta_ac)
360 ocfs2_free_alloc_context(meta_ac);
361
362 return ret;
363}
364
365static int ocfs2_xattr_shrink_size(struct inode *inode,
366 u32 old_clusters,
367 u32 new_clusters,
368 struct buffer_head *root_bh,
369 struct ocfs2_xattr_value_root *xv)
370{
371 int ret = 0;
372 u32 trunc_len, cpos, phys_cpos, alloc_size;
373 u64 block;
374 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
375 struct ocfs2_cached_dealloc_ctxt dealloc;
376
377 ocfs2_init_dealloc_ctxt(&dealloc);
378
379 if (old_clusters <= new_clusters)
380 return 0;
381
382 cpos = new_clusters;
383 trunc_len = old_clusters - new_clusters;
384 while (trunc_len) {
385 ret = ocfs2_xattr_get_clusters(inode, cpos, &phys_cpos,
386 &alloc_size, &xv->xr_list);
387 if (ret) {
388 mlog_errno(ret);
389 goto out;
390 }
391
392 if (alloc_size > trunc_len)
393 alloc_size = trunc_len;
394
395 ret = __ocfs2_remove_xattr_range(inode, root_bh, xv, cpos,
396 phys_cpos, alloc_size,
397 &dealloc);
398 if (ret) {
399 mlog_errno(ret);
400 goto out;
401 }
402
403 block = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos);
404 ocfs2_remove_xattr_clusters_from_cache(inode, block,
405 alloc_size);
406 cpos += alloc_size;
407 trunc_len -= alloc_size;
408 }
409
410out:
411 ocfs2_schedule_truncate_log_flush(osb, 1);
412 ocfs2_run_deallocs(osb, &dealloc);
413
414 return ret;
415}
416
417static int ocfs2_xattr_value_truncate(struct inode *inode,
418 struct buffer_head *root_bh,
419 struct ocfs2_xattr_value_root *xv,
420 int len)
421{
422 int ret;
423 u32 new_clusters = ocfs2_clusters_for_bytes(inode->i_sb, len);
424 u32 old_clusters = le32_to_cpu(xv->xr_clusters);
425
426 if (new_clusters == old_clusters)
427 return 0;
428
429 if (new_clusters > old_clusters)
430 ret = ocfs2_xattr_extend_allocation(inode,
431 new_clusters - old_clusters,
432 root_bh, xv);
433 else
434 ret = ocfs2_xattr_shrink_size(inode,
435 old_clusters, new_clusters,
436 root_bh, xv);
437
438 return ret;
439}
Tiger Yangcf1d6c72008-08-18 17:11:00 +0800440
441static int ocfs2_xattr_list_entries(struct inode *inode,
442 struct ocfs2_xattr_header *header,
443 char *buffer, size_t buffer_size)
444{
445 size_t rest = buffer_size;
446 int i;
447
448 for (i = 0 ; i < le16_to_cpu(header->xh_count); i++) {
449 struct ocfs2_xattr_entry *entry = &header->xh_entries[i];
450 struct xattr_handler *handler =
451 ocfs2_xattr_handler(ocfs2_xattr_get_type(entry));
452
453 if (handler) {
454 size_t size = handler->list(inode, buffer, rest,
455 ((char *)header +
456 le16_to_cpu(entry->xe_name_offset)),
457 entry->xe_name_len);
458 if (buffer) {
459 if (size > rest)
460 return -ERANGE;
461 buffer += size;
462 }
463 rest -= size;
464 }
465 }
466
467 return buffer_size - rest;
468}
469
470static int ocfs2_xattr_ibody_list(struct inode *inode,
471 struct ocfs2_dinode *di,
472 char *buffer,
473 size_t buffer_size)
474{
475 struct ocfs2_xattr_header *header = NULL;
476 struct ocfs2_inode_info *oi = OCFS2_I(inode);
477 int ret = 0;
478
479 if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL))
480 return ret;
481
482 header = (struct ocfs2_xattr_header *)
483 ((void *)di + inode->i_sb->s_blocksize -
484 le16_to_cpu(di->i_xattr_inline_size));
485
486 ret = ocfs2_xattr_list_entries(inode, header, buffer, buffer_size);
487
488 return ret;
489}
490
491static int ocfs2_xattr_block_list(struct inode *inode,
492 struct ocfs2_dinode *di,
493 char *buffer,
494 size_t buffer_size)
495{
496 struct buffer_head *blk_bh = NULL;
Tao Ma0c044f02008-08-18 17:38:50 +0800497 struct ocfs2_xattr_block *xb;
Tiger Yangcf1d6c72008-08-18 17:11:00 +0800498 int ret = 0;
499
500 if (!di->i_xattr_loc)
501 return ret;
502
503 ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
504 le64_to_cpu(di->i_xattr_loc),
505 &blk_bh, OCFS2_BH_CACHED, inode);
506 if (ret < 0) {
507 mlog_errno(ret);
508 return ret;
509 }
510 /*Verify the signature of xattr block*/
511 if (memcmp((void *)blk_bh->b_data, OCFS2_XATTR_BLOCK_SIGNATURE,
512 strlen(OCFS2_XATTR_BLOCK_SIGNATURE))) {
513 ret = -EFAULT;
514 goto cleanup;
515 }
516
Tao Ma0c044f02008-08-18 17:38:50 +0800517 xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
Tiger Yangcf1d6c72008-08-18 17:11:00 +0800518
Tao Ma0c044f02008-08-18 17:38:50 +0800519 if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) {
520 struct ocfs2_xattr_header *header = &xb->xb_attrs.xb_header;
521 ret = ocfs2_xattr_list_entries(inode, header,
522 buffer, buffer_size);
523 } else {
524 struct ocfs2_xattr_tree_root *xt = &xb->xb_attrs.xb_root;
525 ret = ocfs2_xattr_tree_list_index_block(inode, xt,
526 buffer, buffer_size);
527 }
Tiger Yangcf1d6c72008-08-18 17:11:00 +0800528cleanup:
529 brelse(blk_bh);
530
531 return ret;
532}
533
534ssize_t ocfs2_listxattr(struct dentry *dentry,
535 char *buffer,
536 size_t size)
537{
538 int ret = 0, i_ret = 0, b_ret = 0;
539 struct buffer_head *di_bh = NULL;
540 struct ocfs2_dinode *di = NULL;
541 struct ocfs2_inode_info *oi = OCFS2_I(dentry->d_inode);
542
543 if (!(oi->ip_dyn_features & OCFS2_HAS_XATTR_FL))
544 return ret;
545
546 ret = ocfs2_inode_lock(dentry->d_inode, &di_bh, 0);
547 if (ret < 0) {
548 mlog_errno(ret);
549 return ret;
550 }
551
552 di = (struct ocfs2_dinode *)di_bh->b_data;
553
554 down_read(&oi->ip_xattr_sem);
555 i_ret = ocfs2_xattr_ibody_list(dentry->d_inode, di, buffer, size);
556 if (i_ret < 0)
557 b_ret = 0;
558 else {
559 if (buffer) {
560 buffer += i_ret;
561 size -= i_ret;
562 }
563 b_ret = ocfs2_xattr_block_list(dentry->d_inode, di,
564 buffer, size);
565 if (b_ret < 0)
566 i_ret = 0;
567 }
568 up_read(&oi->ip_xattr_sem);
569 ocfs2_inode_unlock(dentry->d_inode, 0);
570
571 brelse(di_bh);
572
573 return i_ret + b_ret;
574}
575
576static int ocfs2_xattr_find_entry(int name_index,
577 const char *name,
578 struct ocfs2_xattr_search *xs)
579{
580 struct ocfs2_xattr_entry *entry;
581 size_t name_len;
582 int i, cmp = 1;
583
584 if (name == NULL)
585 return -EINVAL;
586
587 name_len = strlen(name);
588 entry = xs->here;
589 for (i = 0; i < le16_to_cpu(xs->header->xh_count); i++) {
590 cmp = name_index - ocfs2_xattr_get_type(entry);
591 if (!cmp)
592 cmp = name_len - entry->xe_name_len;
593 if (!cmp)
594 cmp = memcmp(name, (xs->base +
595 le16_to_cpu(entry->xe_name_offset)),
596 name_len);
597 if (cmp == 0)
598 break;
599 entry += 1;
600 }
601 xs->here = entry;
602
603 return cmp ? -ENODATA : 0;
604}
605
606static int ocfs2_xattr_get_value_outside(struct inode *inode,
607 struct ocfs2_xattr_search *xs,
608 void *buffer,
609 size_t len)
610{
611 u32 cpos, p_cluster, num_clusters, bpc, clusters;
612 u64 blkno;
613 int i, ret = 0;
614 size_t cplen, blocksize;
615 struct buffer_head *bh = NULL;
616 struct ocfs2_xattr_value_root *xv;
617 struct ocfs2_extent_list *el;
618
619 xv = (struct ocfs2_xattr_value_root *)
620 (xs->base + le16_to_cpu(xs->here->xe_name_offset) +
621 OCFS2_XATTR_SIZE(xs->here->xe_name_len));
622 el = &xv->xr_list;
623 clusters = le32_to_cpu(xv->xr_clusters);
624 bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
625 blocksize = inode->i_sb->s_blocksize;
626
627 cpos = 0;
628 while (cpos < clusters) {
629 ret = ocfs2_xattr_get_clusters(inode, cpos, &p_cluster,
630 &num_clusters, el);
631 if (ret) {
632 mlog_errno(ret);
633 goto out;
634 }
635
636 blkno = ocfs2_clusters_to_blocks(inode->i_sb, p_cluster);
637 /* Copy ocfs2_xattr_value */
638 for (i = 0; i < num_clusters * bpc; i++, blkno++) {
639 ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), blkno,
640 &bh, OCFS2_BH_CACHED, inode);
641 if (ret) {
642 mlog_errno(ret);
643 goto out;
644 }
645
646 cplen = len >= blocksize ? blocksize : len;
647 memcpy(buffer, bh->b_data, cplen);
648 len -= cplen;
649 buffer += cplen;
650
651 brelse(bh);
652 bh = NULL;
653 if (len == 0)
654 break;
655 }
656 cpos += num_clusters;
657 }
658out:
659 return ret;
660}
661
662static int ocfs2_xattr_ibody_get(struct inode *inode,
663 int name_index,
664 const char *name,
665 void *buffer,
666 size_t buffer_size,
667 struct ocfs2_xattr_search *xs)
668{
669 struct ocfs2_inode_info *oi = OCFS2_I(inode);
670 struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data;
671 size_t size;
672 int ret = 0;
673
674 if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL))
675 return -ENODATA;
676
677 xs->end = (void *)di + inode->i_sb->s_blocksize;
678 xs->header = (struct ocfs2_xattr_header *)
679 (xs->end - le16_to_cpu(di->i_xattr_inline_size));
680 xs->base = (void *)xs->header;
681 xs->here = xs->header->xh_entries;
682
683 ret = ocfs2_xattr_find_entry(name_index, name, xs);
684 if (ret)
685 return ret;
686 size = le64_to_cpu(xs->here->xe_value_size);
687 if (buffer) {
688 if (size > buffer_size)
689 return -ERANGE;
690 if (ocfs2_xattr_is_local(xs->here)) {
691 memcpy(buffer, (void *)xs->base +
692 le16_to_cpu(xs->here->xe_name_offset) +
693 OCFS2_XATTR_SIZE(xs->here->xe_name_len), size);
694 } else {
695 ret = ocfs2_xattr_get_value_outside(inode, xs,
696 buffer, size);
697 if (ret < 0) {
698 mlog_errno(ret);
699 return ret;
700 }
701 }
702 }
703
704 return size;
705}
706
707static int ocfs2_xattr_block_get(struct inode *inode,
708 int name_index,
709 const char *name,
710 void *buffer,
711 size_t buffer_size,
712 struct ocfs2_xattr_search *xs)
713{
714 struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data;
715 struct buffer_head *blk_bh = NULL;
716 struct ocfs2_xattr_block *xb;
717 size_t size;
718 int ret = -ENODATA;
719
720 if (!di->i_xattr_loc)
721 return ret;
722
723 ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
724 le64_to_cpu(di->i_xattr_loc),
725 &blk_bh, OCFS2_BH_CACHED, inode);
726 if (ret < 0) {
727 mlog_errno(ret);
728 return ret;
729 }
730 /*Verify the signature of xattr block*/
731 if (memcmp((void *)blk_bh->b_data, OCFS2_XATTR_BLOCK_SIGNATURE,
732 strlen(OCFS2_XATTR_BLOCK_SIGNATURE))) {
733 ret = -EFAULT;
734 goto cleanup;
735 }
736
737 xs->xattr_bh = blk_bh;
738 xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
739 xs->header = &xb->xb_attrs.xb_header;
740 xs->base = (void *)xs->header;
741 xs->end = (void *)(blk_bh->b_data) + blk_bh->b_size;
742 xs->here = xs->header->xh_entries;
743
744 ret = ocfs2_xattr_find_entry(name_index, name, xs);
745 if (ret)
746 goto cleanup;
747 size = le64_to_cpu(xs->here->xe_value_size);
748 if (buffer) {
749 ret = -ERANGE;
750 if (size > buffer_size)
751 goto cleanup;
752 if (ocfs2_xattr_is_local(xs->here)) {
753 memcpy(buffer, (void *)xs->base +
754 le16_to_cpu(xs->here->xe_name_offset) +
755 OCFS2_XATTR_SIZE(xs->here->xe_name_len), size);
756 } else {
757 ret = ocfs2_xattr_get_value_outside(inode, xs,
758 buffer, size);
759 if (ret < 0) {
760 mlog_errno(ret);
761 goto cleanup;
762 }
763 }
764 }
765 ret = size;
766cleanup:
767 brelse(blk_bh);
768
769 return ret;
770}
771
772/* ocfs2_xattr_get()
773 *
774 * Copy an extended attribute into the buffer provided.
775 * Buffer is NULL to compute the size of buffer required.
776 */
777int ocfs2_xattr_get(struct inode *inode,
778 int name_index,
779 const char *name,
780 void *buffer,
781 size_t buffer_size)
782{
783 int ret;
784 struct ocfs2_dinode *di = NULL;
785 struct buffer_head *di_bh = NULL;
786 struct ocfs2_inode_info *oi = OCFS2_I(inode);
787 struct ocfs2_xattr_search xis = {
788 .not_found = -ENODATA,
789 };
790 struct ocfs2_xattr_search xbs = {
791 .not_found = -ENODATA,
792 };
793
794 if (!(oi->ip_dyn_features & OCFS2_HAS_XATTR_FL))
795 ret = -ENODATA;
796
797 ret = ocfs2_inode_lock(inode, &di_bh, 0);
798 if (ret < 0) {
799 mlog_errno(ret);
800 return ret;
801 }
802 xis.inode_bh = xbs.inode_bh = di_bh;
803 di = (struct ocfs2_dinode *)di_bh->b_data;
804
805 down_read(&oi->ip_xattr_sem);
806 ret = ocfs2_xattr_ibody_get(inode, name_index, name, buffer,
807 buffer_size, &xis);
808 if (ret == -ENODATA)
809 ret = ocfs2_xattr_block_get(inode, name_index, name, buffer,
810 buffer_size, &xbs);
811 up_read(&oi->ip_xattr_sem);
812 ocfs2_inode_unlock(inode, 0);
813
814 brelse(di_bh);
815
816 return ret;
817}
818
819static int __ocfs2_xattr_set_value_outside(struct inode *inode,
820 struct ocfs2_xattr_value_root *xv,
821 const void *value,
822 int value_len)
823{
824 int ret = 0, i, cp_len, credits;
825 u16 blocksize = inode->i_sb->s_blocksize;
826 u32 p_cluster, num_clusters;
827 u32 cpos = 0, bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
828 u32 clusters = ocfs2_clusters_for_bytes(inode->i_sb, value_len);
829 u64 blkno;
830 struct buffer_head *bh = NULL;
831 handle_t *handle;
832
833 BUG_ON(clusters > le32_to_cpu(xv->xr_clusters));
834
835 credits = clusters * bpc;
836 handle = ocfs2_start_trans(OCFS2_SB(inode->i_sb), credits);
837 if (IS_ERR(handle)) {
838 ret = PTR_ERR(handle);
839 mlog_errno(ret);
840 goto out;
841 }
842
843 while (cpos < clusters) {
844 ret = ocfs2_xattr_get_clusters(inode, cpos, &p_cluster,
845 &num_clusters, &xv->xr_list);
846 if (ret) {
847 mlog_errno(ret);
848 goto out_commit;
849 }
850
851 blkno = ocfs2_clusters_to_blocks(inode->i_sb, p_cluster);
852
853 for (i = 0; i < num_clusters * bpc; i++, blkno++) {
854 ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), blkno,
855 &bh, OCFS2_BH_CACHED, inode);
856 if (ret) {
857 mlog_errno(ret);
858 goto out_commit;
859 }
860
861 ret = ocfs2_journal_access(handle,
862 inode,
863 bh,
864 OCFS2_JOURNAL_ACCESS_WRITE);
865 if (ret < 0) {
866 mlog_errno(ret);
867 goto out_commit;
868 }
869
870 cp_len = value_len > blocksize ? blocksize : value_len;
871 memcpy(bh->b_data, value, cp_len);
872 value_len -= cp_len;
873 value += cp_len;
874 if (cp_len < blocksize)
875 memset(bh->b_data + cp_len, 0,
876 blocksize - cp_len);
877
878 ret = ocfs2_journal_dirty(handle, bh);
879 if (ret < 0) {
880 mlog_errno(ret);
881 goto out_commit;
882 }
883 brelse(bh);
884 bh = NULL;
885
886 /*
887 * XXX: do we need to empty all the following
888 * blocks in this cluster?
889 */
890 if (!value_len)
891 break;
892 }
893 cpos += num_clusters;
894 }
895out_commit:
896 ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
897out:
898 brelse(bh);
899
900 return ret;
901}
902
903static int ocfs2_xattr_cleanup(struct inode *inode,
904 struct ocfs2_xattr_info *xi,
905 struct ocfs2_xattr_search *xs,
906 size_t offs)
907{
908 handle_t *handle = NULL;
909 int ret = 0;
910 size_t name_len = strlen(xi->name);
911 void *val = xs->base + offs;
912 size_t size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_ROOT_SIZE;
913
914 handle = ocfs2_start_trans((OCFS2_SB(inode->i_sb)),
915 OCFS2_XATTR_BLOCK_UPDATE_CREDITS);
916 if (IS_ERR(handle)) {
917 ret = PTR_ERR(handle);
918 mlog_errno(ret);
919 goto out;
920 }
921 ret = ocfs2_journal_access(handle, inode, xs->xattr_bh,
922 OCFS2_JOURNAL_ACCESS_WRITE);
923 if (ret) {
924 mlog_errno(ret);
925 goto out_commit;
926 }
927 /* Decrease xattr count */
928 le16_add_cpu(&xs->header->xh_count, -1);
929 /* Remove the xattr entry and tree root which has already be set*/
930 memset((void *)xs->here, 0, sizeof(struct ocfs2_xattr_entry));
931 memset(val, 0, size);
932
933 ret = ocfs2_journal_dirty(handle, xs->xattr_bh);
934 if (ret < 0)
935 mlog_errno(ret);
936out_commit:
937 ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
938out:
939 return ret;
940}
941
942static int ocfs2_xattr_update_entry(struct inode *inode,
943 struct ocfs2_xattr_info *xi,
944 struct ocfs2_xattr_search *xs,
945 size_t offs)
946{
947 handle_t *handle = NULL;
948 int ret = 0;
949
950 handle = ocfs2_start_trans((OCFS2_SB(inode->i_sb)),
951 OCFS2_XATTR_BLOCK_UPDATE_CREDITS);
952 if (IS_ERR(handle)) {
953 ret = PTR_ERR(handle);
954 mlog_errno(ret);
955 goto out;
956 }
957 ret = ocfs2_journal_access(handle, inode, xs->xattr_bh,
958 OCFS2_JOURNAL_ACCESS_WRITE);
959 if (ret) {
960 mlog_errno(ret);
961 goto out_commit;
962 }
963
964 xs->here->xe_name_offset = cpu_to_le16(offs);
965 xs->here->xe_value_size = cpu_to_le64(xi->value_len);
966 if (xi->value_len <= OCFS2_XATTR_INLINE_SIZE)
967 ocfs2_xattr_set_local(xs->here, 1);
968 else
969 ocfs2_xattr_set_local(xs->here, 0);
970 ocfs2_xattr_hash_entry(inode, xs->header, xs->here);
971
972 ret = ocfs2_journal_dirty(handle, xs->xattr_bh);
973 if (ret < 0)
974 mlog_errno(ret);
975out_commit:
976 ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
977out:
978 return ret;
979}
980
981/*
982 * ocfs2_xattr_set_value_outside()
983 *
984 * Set large size value in B tree.
985 */
986static int ocfs2_xattr_set_value_outside(struct inode *inode,
987 struct ocfs2_xattr_info *xi,
988 struct ocfs2_xattr_search *xs,
989 size_t offs)
990{
991 size_t name_len = strlen(xi->name);
992 void *val = xs->base + offs;
993 struct ocfs2_xattr_value_root *xv = NULL;
994 size_t size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_ROOT_SIZE;
995 int ret = 0;
996
997 memset(val, 0, size);
998 memcpy(val, xi->name, name_len);
999 xv = (struct ocfs2_xattr_value_root *)
1000 (val + OCFS2_XATTR_SIZE(name_len));
1001 xv->xr_clusters = 0;
1002 xv->xr_last_eb_blk = 0;
1003 xv->xr_list.l_tree_depth = 0;
1004 xv->xr_list.l_count = cpu_to_le16(1);
1005 xv->xr_list.l_next_free_rec = 0;
1006
1007 ret = ocfs2_xattr_value_truncate(inode, xs->xattr_bh, xv,
1008 xi->value_len);
1009 if (ret < 0) {
1010 mlog_errno(ret);
1011 return ret;
1012 }
1013 ret = __ocfs2_xattr_set_value_outside(inode, xv, xi->value,
1014 xi->value_len);
1015 if (ret < 0) {
1016 mlog_errno(ret);
1017 return ret;
1018 }
1019 ret = ocfs2_xattr_update_entry(inode, xi, xs, offs);
1020 if (ret < 0)
1021 mlog_errno(ret);
1022
1023 return ret;
1024}
1025
1026/*
1027 * ocfs2_xattr_set_entry_local()
1028 *
1029 * Set, replace or remove extended attribute in local.
1030 */
1031static void ocfs2_xattr_set_entry_local(struct inode *inode,
1032 struct ocfs2_xattr_info *xi,
1033 struct ocfs2_xattr_search *xs,
1034 struct ocfs2_xattr_entry *last,
1035 size_t min_offs)
1036{
1037 size_t name_len = strlen(xi->name);
1038 int i;
1039
1040 if (xi->value && xs->not_found) {
1041 /* Insert the new xattr entry. */
1042 le16_add_cpu(&xs->header->xh_count, 1);
1043 ocfs2_xattr_set_type(last, xi->name_index);
1044 ocfs2_xattr_set_local(last, 1);
1045 last->xe_name_len = name_len;
1046 } else {
1047 void *first_val;
1048 void *val;
1049 size_t offs, size;
1050
1051 first_val = xs->base + min_offs;
1052 offs = le16_to_cpu(xs->here->xe_name_offset);
1053 val = xs->base + offs;
1054
1055 if (le64_to_cpu(xs->here->xe_value_size) >
1056 OCFS2_XATTR_INLINE_SIZE)
1057 size = OCFS2_XATTR_SIZE(name_len) +
1058 OCFS2_XATTR_ROOT_SIZE;
1059 else
1060 size = OCFS2_XATTR_SIZE(name_len) +
1061 OCFS2_XATTR_SIZE(le64_to_cpu(xs->here->xe_value_size));
1062
1063 if (xi->value && size == OCFS2_XATTR_SIZE(name_len) +
1064 OCFS2_XATTR_SIZE(xi->value_len)) {
1065 /* The old and the new value have the
1066 same size. Just replace the value. */
1067 ocfs2_xattr_set_local(xs->here, 1);
1068 xs->here->xe_value_size = cpu_to_le64(xi->value_len);
1069 /* Clear value bytes. */
1070 memset(val + OCFS2_XATTR_SIZE(name_len),
1071 0,
1072 OCFS2_XATTR_SIZE(xi->value_len));
1073 memcpy(val + OCFS2_XATTR_SIZE(name_len),
1074 xi->value,
1075 xi->value_len);
1076 return;
1077 }
1078 /* Remove the old name+value. */
1079 memmove(first_val + size, first_val, val - first_val);
1080 memset(first_val, 0, size);
1081 xs->here->xe_name_hash = 0;
1082 xs->here->xe_name_offset = 0;
1083 ocfs2_xattr_set_local(xs->here, 1);
1084 xs->here->xe_value_size = 0;
1085
1086 min_offs += size;
1087
1088 /* Adjust all value offsets. */
1089 last = xs->header->xh_entries;
1090 for (i = 0 ; i < le16_to_cpu(xs->header->xh_count); i++) {
1091 size_t o = le16_to_cpu(last->xe_name_offset);
1092
1093 if (o < offs)
1094 last->xe_name_offset = cpu_to_le16(o + size);
1095 last += 1;
1096 }
1097
1098 if (!xi->value) {
1099 /* Remove the old entry. */
1100 last -= 1;
1101 memmove(xs->here, xs->here + 1,
1102 (void *)last - (void *)xs->here);
1103 memset(last, 0, sizeof(struct ocfs2_xattr_entry));
1104 le16_add_cpu(&xs->header->xh_count, -1);
1105 }
1106 }
1107 if (xi->value) {
1108 /* Insert the new name+value. */
1109 size_t size = OCFS2_XATTR_SIZE(name_len) +
1110 OCFS2_XATTR_SIZE(xi->value_len);
1111 void *val = xs->base + min_offs - size;
1112
1113 xs->here->xe_name_offset = cpu_to_le16(min_offs - size);
1114 memset(val, 0, size);
1115 memcpy(val, xi->name, name_len);
1116 memcpy(val + OCFS2_XATTR_SIZE(name_len),
1117 xi->value,
1118 xi->value_len);
1119 xs->here->xe_value_size = cpu_to_le64(xi->value_len);
1120 ocfs2_xattr_set_local(xs->here, 1);
1121 ocfs2_xattr_hash_entry(inode, xs->header, xs->here);
1122 }
1123
1124 return;
1125}
1126
1127/*
1128 * ocfs2_xattr_set_entry()
1129 *
1130 * Set extended attribute entry into inode or block.
1131 *
1132 * If extended attribute value size > OCFS2_XATTR_INLINE_SIZE,
1133 * We first insert tree root(ocfs2_xattr_value_root) with set_entry_local(),
1134 * then set value in B tree with set_value_outside().
1135 */
1136static int ocfs2_xattr_set_entry(struct inode *inode,
1137 struct ocfs2_xattr_info *xi,
1138 struct ocfs2_xattr_search *xs,
1139 int flag)
1140{
1141 struct ocfs2_xattr_entry *last;
1142 struct ocfs2_inode_info *oi = OCFS2_I(inode);
1143 struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data;
1144 size_t min_offs = xs->end - xs->base, name_len = strlen(xi->name);
1145 size_t size_l = 0;
1146 handle_t *handle = NULL;
1147 int free, i, ret;
1148 struct ocfs2_xattr_info xi_l = {
1149 .name_index = xi->name_index,
1150 .name = xi->name,
1151 .value = xi->value,
1152 .value_len = xi->value_len,
1153 };
1154
1155 /* Compute min_offs, last and free space. */
1156 last = xs->header->xh_entries;
1157
1158 for (i = 0 ; i < le16_to_cpu(xs->header->xh_count); i++) {
1159 size_t offs = le16_to_cpu(last->xe_name_offset);
1160 if (offs < min_offs)
1161 min_offs = offs;
1162 last += 1;
1163 }
1164
1165 free = min_offs - ((void *)last - xs->base) - sizeof(__u32);
1166 if (free < 0)
1167 return -EFAULT;
1168
1169 if (!xs->not_found) {
1170 size_t size = 0;
1171 if (ocfs2_xattr_is_local(xs->here))
1172 size = OCFS2_XATTR_SIZE(name_len) +
1173 OCFS2_XATTR_SIZE(le64_to_cpu(xs->here->xe_value_size));
1174 else
1175 size = OCFS2_XATTR_SIZE(name_len) +
1176 OCFS2_XATTR_ROOT_SIZE;
1177 free += (size + sizeof(struct ocfs2_xattr_entry));
1178 }
1179 /* Check free space in inode or block */
1180 if (xi->value && xi->value_len > OCFS2_XATTR_INLINE_SIZE) {
1181 if (free < sizeof(struct ocfs2_xattr_entry) +
1182 OCFS2_XATTR_SIZE(name_len) +
1183 OCFS2_XATTR_ROOT_SIZE) {
1184 ret = -ENOSPC;
1185 goto out;
1186 }
1187 size_l = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_ROOT_SIZE;
1188 xi_l.value = (void *)&def_xv;
1189 xi_l.value_len = OCFS2_XATTR_ROOT_SIZE;
1190 } else if (xi->value) {
1191 if (free < sizeof(struct ocfs2_xattr_entry) +
1192 OCFS2_XATTR_SIZE(name_len) +
1193 OCFS2_XATTR_SIZE(xi->value_len)) {
1194 ret = -ENOSPC;
1195 goto out;
1196 }
1197 }
1198
1199 if (!xs->not_found) {
1200 /* For existing extended attribute */
1201 size_t size = OCFS2_XATTR_SIZE(name_len) +
1202 OCFS2_XATTR_SIZE(le64_to_cpu(xs->here->xe_value_size));
1203 size_t offs = le16_to_cpu(xs->here->xe_name_offset);
1204 void *val = xs->base + offs;
1205
1206 if (ocfs2_xattr_is_local(xs->here) && size == size_l) {
1207 /* Replace existing local xattr with tree root */
1208 ret = ocfs2_xattr_set_value_outside(inode, xi, xs,
1209 offs);
1210 if (ret < 0)
1211 mlog_errno(ret);
1212 goto out;
1213 } else if (!ocfs2_xattr_is_local(xs->here)) {
1214 /* For existing xattr which has value outside */
1215 struct ocfs2_xattr_value_root *xv = NULL;
1216 xv = (struct ocfs2_xattr_value_root *)(val +
1217 OCFS2_XATTR_SIZE(name_len));
1218
1219 if (xi->value_len > OCFS2_XATTR_INLINE_SIZE) {
1220 /*
1221 * If new value need set outside also,
1222 * first truncate old value to new value,
1223 * then set new value with set_value_outside().
1224 */
1225 ret = ocfs2_xattr_value_truncate(inode,
1226 xs->xattr_bh,
1227 xv,
1228 xi->value_len);
1229 if (ret < 0) {
1230 mlog_errno(ret);
1231 goto out;
1232 }
1233
1234 ret = __ocfs2_xattr_set_value_outside(inode,
1235 xv,
1236 xi->value,
1237 xi->value_len);
1238 if (ret < 0) {
1239 mlog_errno(ret);
1240 goto out;
1241 }
1242
1243 ret = ocfs2_xattr_update_entry(inode,
1244 xi,
1245 xs,
1246 offs);
1247 if (ret < 0)
1248 mlog_errno(ret);
1249 goto out;
1250 } else {
1251 /*
1252 * If new value need set in local,
1253 * just trucate old value to zero.
1254 */
1255 ret = ocfs2_xattr_value_truncate(inode,
1256 xs->xattr_bh,
1257 xv,
1258 0);
1259 if (ret < 0)
1260 mlog_errno(ret);
1261 }
1262 }
1263 }
1264
1265 handle = ocfs2_start_trans((OCFS2_SB(inode->i_sb)),
1266 OCFS2_INODE_UPDATE_CREDITS);
1267 if (IS_ERR(handle)) {
1268 ret = PTR_ERR(handle);
1269 mlog_errno(ret);
1270 goto out;
1271 }
1272
1273 ret = ocfs2_journal_access(handle, inode, xs->inode_bh,
1274 OCFS2_JOURNAL_ACCESS_WRITE);
1275 if (ret) {
1276 mlog_errno(ret);
1277 goto out_commit;
1278 }
1279
1280 if (!(flag & OCFS2_INLINE_XATTR_FL)) {
1281 /*set extended attribue in external blcok*/
1282 ret = ocfs2_extend_trans(handle,
1283 OCFS2_XATTR_BLOCK_UPDATE_CREDITS);
1284 if (ret) {
1285 mlog_errno(ret);
1286 goto out_commit;
1287 }
1288 ret = ocfs2_journal_access(handle, inode, xs->xattr_bh,
1289 OCFS2_JOURNAL_ACCESS_WRITE);
1290 if (ret) {
1291 mlog_errno(ret);
1292 goto out_commit;
1293 }
1294 }
1295
1296 /*
1297 * Set value in local, include set tree root in local.
1298 * This is the first step for value size >INLINE_SIZE.
1299 */
1300 ocfs2_xattr_set_entry_local(inode, &xi_l, xs, last, min_offs);
1301
1302 if (!(flag & OCFS2_INLINE_XATTR_FL)) {
1303 ret = ocfs2_journal_dirty(handle, xs->xattr_bh);
1304 if (ret < 0) {
1305 mlog_errno(ret);
1306 goto out_commit;
1307 }
1308 }
1309
1310 if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL) &&
1311 (flag & OCFS2_INLINE_XATTR_FL)) {
1312 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
1313 unsigned int xattrsize = osb->s_xattr_inline_size;
1314
1315 /*
1316 * Adjust extent record count or inline data size
1317 * to reserve space for extended attribute.
1318 */
1319 if (oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
1320 struct ocfs2_inline_data *idata = &di->id2.i_data;
1321 le16_add_cpu(&idata->id_count, -xattrsize);
1322 } else if (!(ocfs2_inode_is_fast_symlink(inode))) {
1323 struct ocfs2_extent_list *el = &di->id2.i_list;
1324 le16_add_cpu(&el->l_count, -(xattrsize /
1325 sizeof(struct ocfs2_extent_rec)));
1326 }
1327 di->i_xattr_inline_size = cpu_to_le16(xattrsize);
1328 }
1329 /* Update xattr flag */
1330 spin_lock(&oi->ip_lock);
1331 oi->ip_dyn_features |= flag;
1332 di->i_dyn_features = cpu_to_le16(oi->ip_dyn_features);
1333 spin_unlock(&oi->ip_lock);
1334 /* Update inode ctime */
1335 inode->i_ctime = CURRENT_TIME;
1336 di->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
1337 di->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
1338
1339 ret = ocfs2_journal_dirty(handle, xs->inode_bh);
1340 if (ret < 0)
1341 mlog_errno(ret);
1342
1343out_commit:
1344 ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
1345
1346 if (!ret && xi->value_len > OCFS2_XATTR_INLINE_SIZE) {
1347 /*
1348 * Set value outside in B tree.
1349 * This is the second step for value size > INLINE_SIZE.
1350 */
1351 size_t offs = le16_to_cpu(xs->here->xe_name_offset);
1352 ret = ocfs2_xattr_set_value_outside(inode, xi, xs, offs);
1353 if (ret < 0) {
1354 int ret2;
1355
1356 mlog_errno(ret);
1357 /*
1358 * If set value outside failed, we have to clean
1359 * the junk tree root we have already set in local.
1360 */
1361 ret2 = ocfs2_xattr_cleanup(inode, xi, xs, offs);
1362 if (ret2 < 0)
1363 mlog_errno(ret2);
1364 }
1365 }
1366out:
1367 return ret;
1368
1369}
1370
1371static int ocfs2_xattr_free_block(handle_t *handle,
1372 struct ocfs2_super *osb,
1373 struct ocfs2_xattr_block *xb)
1374{
1375 struct inode *xb_alloc_inode;
1376 struct buffer_head *xb_alloc_bh = NULL;
1377 u64 blk = le64_to_cpu(xb->xb_blkno);
1378 u16 bit = le16_to_cpu(xb->xb_suballoc_bit);
1379 u64 bg_blkno = ocfs2_which_suballoc_group(blk, bit);
1380 int ret = 0;
1381
1382 xb_alloc_inode = ocfs2_get_system_file_inode(osb,
1383 EXTENT_ALLOC_SYSTEM_INODE,
1384 le16_to_cpu(xb->xb_suballoc_slot));
1385 if (!xb_alloc_inode) {
1386 ret = -ENOMEM;
1387 mlog_errno(ret);
1388 goto out;
1389 }
1390 mutex_lock(&xb_alloc_inode->i_mutex);
1391
1392 ret = ocfs2_inode_lock(xb_alloc_inode, &xb_alloc_bh, 1);
1393 if (ret < 0) {
1394 mlog_errno(ret);
1395 goto out_mutex;
1396 }
1397 ret = ocfs2_extend_trans(handle, OCFS2_SUBALLOC_FREE);
1398 if (ret < 0) {
1399 mlog_errno(ret);
1400 goto out_unlock;
1401 }
1402 ret = ocfs2_free_suballoc_bits(handle, xb_alloc_inode, xb_alloc_bh,
1403 bit, bg_blkno, 1);
1404 if (ret < 0)
1405 mlog_errno(ret);
1406out_unlock:
1407 ocfs2_inode_unlock(xb_alloc_inode, 1);
1408 brelse(xb_alloc_bh);
1409out_mutex:
1410 mutex_unlock(&xb_alloc_inode->i_mutex);
1411 iput(xb_alloc_inode);
1412out:
1413 return ret;
1414}
1415
1416static int ocfs2_remove_value_outside(struct inode*inode,
1417 struct buffer_head *bh,
1418 struct ocfs2_xattr_header *header)
1419{
1420 int ret = 0, i;
1421
1422 for (i = 0; i < le16_to_cpu(header->xh_count); i++) {
1423 struct ocfs2_xattr_entry *entry = &header->xh_entries[i];
1424
1425 if (!ocfs2_xattr_is_local(entry)) {
1426 struct ocfs2_xattr_value_root *xv;
1427 void *val;
1428
1429 val = (void *)header +
1430 le16_to_cpu(entry->xe_name_offset);
1431 xv = (struct ocfs2_xattr_value_root *)
1432 (val + OCFS2_XATTR_SIZE(entry->xe_name_len));
1433 ret = ocfs2_xattr_value_truncate(inode, bh, xv, 0);
1434 if (ret < 0) {
1435 mlog_errno(ret);
1436 return ret;
1437 }
1438 }
1439 }
1440
1441 return ret;
1442}
1443
1444static int ocfs2_xattr_ibody_remove(struct inode *inode,
1445 struct buffer_head *di_bh)
1446{
1447
1448 struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
1449 struct ocfs2_xattr_header *header;
1450 int ret;
1451
1452 header = (struct ocfs2_xattr_header *)
1453 ((void *)di + inode->i_sb->s_blocksize -
1454 le16_to_cpu(di->i_xattr_inline_size));
1455
1456 ret = ocfs2_remove_value_outside(inode, di_bh, header);
1457
1458 return ret;
1459}
1460
1461static int ocfs2_xattr_block_remove(struct inode *inode,
1462 struct buffer_head *blk_bh)
1463{
1464 struct ocfs2_xattr_block *xb;
1465 struct ocfs2_xattr_header *header;
1466 int ret = 0;
1467
1468 xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
1469 header = &(xb->xb_attrs.xb_header);
1470
1471 ret = ocfs2_remove_value_outside(inode, blk_bh, header);
1472
1473 return ret;
1474}
1475
1476/*
1477 * ocfs2_xattr_remove()
1478 *
1479 * Free extended attribute resources associated with this inode.
1480 */
1481int ocfs2_xattr_remove(struct inode *inode, struct buffer_head *di_bh)
1482{
1483 struct ocfs2_xattr_block *xb;
1484 struct buffer_head *blk_bh = NULL;
1485 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
1486 struct ocfs2_inode_info *oi = OCFS2_I(inode);
1487 struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
1488 handle_t *handle;
1489 int ret;
1490
1491 if (!(oi->ip_dyn_features & OCFS2_HAS_XATTR_FL))
1492 return 0;
1493
1494 if (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL) {
1495 ret = ocfs2_xattr_ibody_remove(inode, di_bh);
1496 if (ret < 0) {
1497 mlog_errno(ret);
1498 goto out;
1499 }
1500 }
1501 if (di->i_xattr_loc) {
1502 ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
1503 le64_to_cpu(di->i_xattr_loc),
1504 &blk_bh, OCFS2_BH_CACHED, inode);
1505 if (ret < 0) {
1506 mlog_errno(ret);
1507 return ret;
1508 }
1509 /*Verify the signature of xattr block*/
1510 if (memcmp((void *)blk_bh->b_data, OCFS2_XATTR_BLOCK_SIGNATURE,
1511 strlen(OCFS2_XATTR_BLOCK_SIGNATURE))) {
1512 ret = -EFAULT;
1513 goto out;
1514 }
1515
1516 ret = ocfs2_xattr_block_remove(inode, blk_bh);
1517 if (ret < 0) {
1518 mlog_errno(ret);
1519 goto out;
1520 }
1521 }
1522
1523 handle = ocfs2_start_trans((OCFS2_SB(inode->i_sb)),
1524 OCFS2_INODE_UPDATE_CREDITS);
1525 if (IS_ERR(handle)) {
1526 ret = PTR_ERR(handle);
1527 mlog_errno(ret);
1528 goto out;
1529 }
1530 ret = ocfs2_journal_access(handle, inode, di_bh,
1531 OCFS2_JOURNAL_ACCESS_WRITE);
1532 if (ret) {
1533 mlog_errno(ret);
1534 goto out_commit;
1535 }
1536
1537 if (di->i_xattr_loc) {
1538 xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
1539 ocfs2_xattr_free_block(handle, osb, xb);
1540 di->i_xattr_loc = cpu_to_le64(0);
1541 }
1542
1543 spin_lock(&oi->ip_lock);
1544 oi->ip_dyn_features &= ~(OCFS2_INLINE_XATTR_FL | OCFS2_HAS_XATTR_FL);
1545 di->i_dyn_features = cpu_to_le16(oi->ip_dyn_features);
1546 spin_unlock(&oi->ip_lock);
1547
1548 ret = ocfs2_journal_dirty(handle, di_bh);
1549 if (ret < 0)
1550 mlog_errno(ret);
1551out_commit:
1552 ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
1553out:
1554 brelse(blk_bh);
1555
1556 return ret;
1557}
1558
1559static int ocfs2_xattr_has_space_inline(struct inode *inode,
1560 struct ocfs2_dinode *di)
1561{
1562 struct ocfs2_inode_info *oi = OCFS2_I(inode);
1563 unsigned int xattrsize = OCFS2_SB(inode->i_sb)->s_xattr_inline_size;
1564 int free;
1565
1566 if (xattrsize < OCFS2_MIN_XATTR_INLINE_SIZE)
1567 return 0;
1568
1569 if (oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
1570 struct ocfs2_inline_data *idata = &di->id2.i_data;
1571 free = le16_to_cpu(idata->id_count) - le64_to_cpu(di->i_size);
1572 } else if (ocfs2_inode_is_fast_symlink(inode)) {
1573 free = ocfs2_fast_symlink_chars(inode->i_sb) -
1574 le64_to_cpu(di->i_size);
1575 } else {
1576 struct ocfs2_extent_list *el = &di->id2.i_list;
1577 free = (le16_to_cpu(el->l_count) -
1578 le16_to_cpu(el->l_next_free_rec)) *
1579 sizeof(struct ocfs2_extent_rec);
1580 }
1581 if (free >= xattrsize)
1582 return 1;
1583
1584 return 0;
1585}
1586
1587/*
1588 * ocfs2_xattr_ibody_find()
1589 *
1590 * Find extended attribute in inode block and
1591 * fill search info into struct ocfs2_xattr_search.
1592 */
1593static int ocfs2_xattr_ibody_find(struct inode *inode,
1594 int name_index,
1595 const char *name,
1596 struct ocfs2_xattr_search *xs)
1597{
1598 struct ocfs2_inode_info *oi = OCFS2_I(inode);
1599 struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data;
1600 int ret;
1601 int has_space = 0;
1602
1603 if (inode->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE)
1604 return 0;
1605
1606 if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL)) {
1607 down_read(&oi->ip_alloc_sem);
1608 has_space = ocfs2_xattr_has_space_inline(inode, di);
1609 up_read(&oi->ip_alloc_sem);
1610 if (!has_space)
1611 return 0;
1612 }
1613
1614 xs->xattr_bh = xs->inode_bh;
1615 xs->end = (void *)di + inode->i_sb->s_blocksize;
1616 if (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL)
1617 xs->header = (struct ocfs2_xattr_header *)
1618 (xs->end - le16_to_cpu(di->i_xattr_inline_size));
1619 else
1620 xs->header = (struct ocfs2_xattr_header *)
1621 (xs->end - OCFS2_SB(inode->i_sb)->s_xattr_inline_size);
1622 xs->base = (void *)xs->header;
1623 xs->here = xs->header->xh_entries;
1624
1625 /* Find the named attribute. */
1626 if (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL) {
1627 ret = ocfs2_xattr_find_entry(name_index, name, xs);
1628 if (ret && ret != -ENODATA)
1629 return ret;
1630 xs->not_found = ret;
1631 }
1632
1633 return 0;
1634}
1635
1636/*
1637 * ocfs2_xattr_ibody_set()
1638 *
1639 * Set, replace or remove an extended attribute into inode block.
1640 *
1641 */
1642static int ocfs2_xattr_ibody_set(struct inode *inode,
1643 struct ocfs2_xattr_info *xi,
1644 struct ocfs2_xattr_search *xs)
1645{
1646 struct ocfs2_inode_info *oi = OCFS2_I(inode);
1647 struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data;
1648 int ret;
1649
1650 if (inode->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE)
1651 return -ENOSPC;
1652
1653 down_write(&oi->ip_alloc_sem);
1654 if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL)) {
1655 if (!ocfs2_xattr_has_space_inline(inode, di)) {
1656 ret = -ENOSPC;
1657 goto out;
1658 }
1659 }
1660
1661 ret = ocfs2_xattr_set_entry(inode, xi, xs,
1662 (OCFS2_INLINE_XATTR_FL | OCFS2_HAS_XATTR_FL));
1663out:
1664 up_write(&oi->ip_alloc_sem);
1665
1666 return ret;
1667}
1668
1669/*
1670 * ocfs2_xattr_block_find()
1671 *
1672 * Find extended attribute in external block and
1673 * fill search info into struct ocfs2_xattr_search.
1674 */
1675static int ocfs2_xattr_block_find(struct inode *inode,
1676 int name_index,
1677 const char *name,
1678 struct ocfs2_xattr_search *xs)
1679{
1680 struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data;
1681 struct buffer_head *blk_bh = NULL;
1682 int ret = 0;
1683
1684 if (!di->i_xattr_loc)
1685 return ret;
1686
1687 ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
1688 le64_to_cpu(di->i_xattr_loc),
1689 &blk_bh, OCFS2_BH_CACHED, inode);
1690 if (ret < 0) {
1691 mlog_errno(ret);
1692 return ret;
1693 }
1694 /*Verify the signature of xattr block*/
1695 if (memcmp((void *)blk_bh->b_data, OCFS2_XATTR_BLOCK_SIGNATURE,
1696 strlen(OCFS2_XATTR_BLOCK_SIGNATURE))) {
1697 ret = -EFAULT;
1698 goto cleanup;
1699 }
1700
1701 xs->xattr_bh = blk_bh;
1702 xs->header = &((struct ocfs2_xattr_block *)blk_bh->b_data)->
1703 xb_attrs.xb_header;
1704 xs->base = (void *)xs->header;
1705 xs->end = (void *)(blk_bh->b_data) + blk_bh->b_size;
1706 xs->here = xs->header->xh_entries;
1707
1708 ret = ocfs2_xattr_find_entry(name_index, name, xs);
1709 if (ret && ret != -ENODATA) {
1710 xs->xattr_bh = NULL;
1711 goto cleanup;
1712 }
1713 xs->not_found = ret;
1714 return 0;
1715
1716cleanup:
1717 brelse(blk_bh);
1718
1719 return ret;
1720}
1721
1722/*
1723 * ocfs2_xattr_block_set()
1724 *
1725 * Set, replace or remove an extended attribute into external block.
1726 *
1727 */
1728static int ocfs2_xattr_block_set(struct inode *inode,
1729 struct ocfs2_xattr_info *xi,
1730 struct ocfs2_xattr_search *xs)
1731{
1732 struct buffer_head *new_bh = NULL;
1733 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
1734 struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data;
1735 struct ocfs2_alloc_context *meta_ac = NULL;
1736 handle_t *handle = NULL;
1737 struct ocfs2_xattr_block *xblk = NULL;
1738 u16 suballoc_bit_start;
1739 u32 num_got;
1740 u64 first_blkno;
1741 int ret;
1742
1743 if (!xs->xattr_bh) {
1744 /*
1745 * Alloc one external block for extended attribute
1746 * outside of inode.
1747 */
1748 ret = ocfs2_reserve_new_metadata_blocks(osb, 1, &meta_ac);
1749 if (ret < 0) {
1750 mlog_errno(ret);
1751 goto out;
1752 }
1753 handle = ocfs2_start_trans(osb,
1754 OCFS2_XATTR_BLOCK_CREATE_CREDITS);
1755 if (IS_ERR(handle)) {
1756 ret = PTR_ERR(handle);
1757 mlog_errno(ret);
1758 goto out;
1759 }
1760 ret = ocfs2_journal_access(handle, inode, xs->inode_bh,
1761 OCFS2_JOURNAL_ACCESS_CREATE);
1762 if (ret < 0) {
1763 mlog_errno(ret);
1764 goto out_commit;
1765 }
1766
1767 ret = ocfs2_claim_metadata(osb, handle, meta_ac, 1,
1768 &suballoc_bit_start, &num_got,
1769 &first_blkno);
1770 if (ret < 0) {
1771 mlog_errno(ret);
1772 goto out_commit;
1773 }
1774
1775 new_bh = sb_getblk(inode->i_sb, first_blkno);
1776 ocfs2_set_new_buffer_uptodate(inode, new_bh);
1777
1778 ret = ocfs2_journal_access(handle, inode, new_bh,
1779 OCFS2_JOURNAL_ACCESS_CREATE);
1780 if (ret < 0) {
1781 mlog_errno(ret);
1782 goto out_commit;
1783 }
1784
1785 /* Initialize ocfs2_xattr_block */
1786 xs->xattr_bh = new_bh;
1787 xblk = (struct ocfs2_xattr_block *)new_bh->b_data;
1788 memset(xblk, 0, inode->i_sb->s_blocksize);
1789 strcpy((void *)xblk, OCFS2_XATTR_BLOCK_SIGNATURE);
1790 xblk->xb_suballoc_slot = cpu_to_le16(osb->slot_num);
1791 xblk->xb_suballoc_bit = cpu_to_le16(suballoc_bit_start);
1792 xblk->xb_fs_generation = cpu_to_le32(osb->fs_generation);
1793 xblk->xb_blkno = cpu_to_le64(first_blkno);
1794
1795 xs->header = &xblk->xb_attrs.xb_header;
1796 xs->base = (void *)xs->header;
1797 xs->end = (void *)xblk + inode->i_sb->s_blocksize;
1798 xs->here = xs->header->xh_entries;
1799
1800
1801 ret = ocfs2_journal_dirty(handle, new_bh);
1802 if (ret < 0) {
1803 mlog_errno(ret);
1804 goto out_commit;
1805 }
1806 di->i_xattr_loc = cpu_to_le64(first_blkno);
1807 ret = ocfs2_journal_dirty(handle, xs->inode_bh);
1808 if (ret < 0)
1809 mlog_errno(ret);
1810out_commit:
1811 ocfs2_commit_trans(osb, handle);
1812out:
1813 if (meta_ac)
1814 ocfs2_free_alloc_context(meta_ac);
1815 if (ret < 0)
1816 return ret;
1817 }
1818
1819 /* Set extended attribute into external block */
1820 ret = ocfs2_xattr_set_entry(inode, xi, xs, OCFS2_HAS_XATTR_FL);
1821
1822 return ret;
1823}
1824
1825/*
1826 * ocfs2_xattr_set()
1827 *
1828 * Set, replace or remove an extended attribute for this inode.
1829 * value is NULL to remove an existing extended attribute, else either
1830 * create or replace an extended attribute.
1831 */
1832int ocfs2_xattr_set(struct inode *inode,
1833 int name_index,
1834 const char *name,
1835 const void *value,
1836 size_t value_len,
1837 int flags)
1838{
1839 struct buffer_head *di_bh = NULL;
1840 struct ocfs2_dinode *di;
1841 int ret;
1842
1843 struct ocfs2_xattr_info xi = {
1844 .name_index = name_index,
1845 .name = name,
1846 .value = value,
1847 .value_len = value_len,
1848 };
1849
1850 struct ocfs2_xattr_search xis = {
1851 .not_found = -ENODATA,
1852 };
1853
1854 struct ocfs2_xattr_search xbs = {
1855 .not_found = -ENODATA,
1856 };
1857
1858 ret = ocfs2_inode_lock(inode, &di_bh, 1);
1859 if (ret < 0) {
1860 mlog_errno(ret);
1861 return ret;
1862 }
1863 xis.inode_bh = xbs.inode_bh = di_bh;
1864 di = (struct ocfs2_dinode *)di_bh->b_data;
1865
1866 down_write(&OCFS2_I(inode)->ip_xattr_sem);
1867 /*
1868 * Scan inode and external block to find the same name
1869 * extended attribute and collect search infomation.
1870 */
1871 ret = ocfs2_xattr_ibody_find(inode, name_index, name, &xis);
1872 if (ret)
1873 goto cleanup;
1874 if (xis.not_found) {
1875 ret = ocfs2_xattr_block_find(inode, name_index, name, &xbs);
1876 if (ret)
1877 goto cleanup;
1878 }
1879
1880 if (xis.not_found && xbs.not_found) {
1881 ret = -ENODATA;
1882 if (flags & XATTR_REPLACE)
1883 goto cleanup;
1884 ret = 0;
1885 if (!value)
1886 goto cleanup;
1887 } else {
1888 ret = -EEXIST;
1889 if (flags & XATTR_CREATE)
1890 goto cleanup;
1891 }
1892
1893 if (!value) {
1894 /* Remove existing extended attribute */
1895 if (!xis.not_found)
1896 ret = ocfs2_xattr_ibody_set(inode, &xi, &xis);
1897 else if (!xbs.not_found)
1898 ret = ocfs2_xattr_block_set(inode, &xi, &xbs);
1899 } else {
1900 /* We always try to set extended attribute into inode first*/
1901 ret = ocfs2_xattr_ibody_set(inode, &xi, &xis);
1902 if (!ret && !xbs.not_found) {
1903 /*
1904 * If succeed and that extended attribute existing in
1905 * external block, then we will remove it.
1906 */
1907 xi.value = NULL;
1908 xi.value_len = 0;
1909 ret = ocfs2_xattr_block_set(inode, &xi, &xbs);
1910 } else if (ret == -ENOSPC) {
1911 if (di->i_xattr_loc && !xbs.xattr_bh) {
1912 ret = ocfs2_xattr_block_find(inode, name_index,
1913 name, &xbs);
1914 if (ret)
1915 goto cleanup;
1916 }
1917 /*
1918 * If no space in inode, we will set extended attribute
1919 * into external block.
1920 */
1921 ret = ocfs2_xattr_block_set(inode, &xi, &xbs);
1922 if (ret)
1923 goto cleanup;
1924 if (!xis.not_found) {
1925 /*
1926 * If succeed and that extended attribute
1927 * existing in inode, we will remove it.
1928 */
1929 xi.value = NULL;
1930 xi.value_len = 0;
1931 ret = ocfs2_xattr_ibody_set(inode, &xi, &xis);
1932 }
1933 }
1934 }
1935cleanup:
1936 up_write(&OCFS2_I(inode)->ip_xattr_sem);
1937 ocfs2_inode_unlock(inode, 1);
1938 brelse(di_bh);
1939 brelse(xbs.xattr_bh);
1940
1941 return ret;
1942}
1943
Tao Ma0c044f02008-08-18 17:38:50 +08001944/*
1945 * Find the xattr extent rec which may contains name_hash.
1946 * e_cpos will be the first name hash of the xattr rec.
1947 * el must be the ocfs2_xattr_header.xb_attrs.xb_root.xt_list.
1948 */
1949static int ocfs2_xattr_get_rec(struct inode *inode,
1950 u32 name_hash,
1951 u64 *p_blkno,
1952 u32 *e_cpos,
1953 u32 *num_clusters,
1954 struct ocfs2_extent_list *el)
1955{
1956 int ret = 0, i;
1957 struct buffer_head *eb_bh = NULL;
1958 struct ocfs2_extent_block *eb;
1959 struct ocfs2_extent_rec *rec = NULL;
1960 u64 e_blkno = 0;
1961
1962 if (el->l_tree_depth) {
1963 ret = ocfs2_find_leaf(inode, el, name_hash, &eb_bh);
1964 if (ret) {
1965 mlog_errno(ret);
1966 goto out;
1967 }
1968
1969 eb = (struct ocfs2_extent_block *) eb_bh->b_data;
1970 el = &eb->h_list;
1971
1972 if (el->l_tree_depth) {
1973 ocfs2_error(inode->i_sb,
1974 "Inode %lu has non zero tree depth in "
1975 "xattr tree block %llu\n", inode->i_ino,
1976 (unsigned long long)eb_bh->b_blocknr);
1977 ret = -EROFS;
1978 goto out;
1979 }
1980 }
1981
1982 for (i = le16_to_cpu(el->l_next_free_rec) - 1; i >= 0; i--) {
1983 rec = &el->l_recs[i];
1984
1985 if (le32_to_cpu(rec->e_cpos) <= name_hash) {
1986 e_blkno = le64_to_cpu(rec->e_blkno);
1987 break;
1988 }
1989 }
1990
1991 if (!e_blkno) {
1992 ocfs2_error(inode->i_sb, "Inode %lu has bad extent "
1993 "record (%u, %u, 0) in xattr", inode->i_ino,
1994 le32_to_cpu(rec->e_cpos),
1995 ocfs2_rec_clusters(el, rec));
1996 ret = -EROFS;
1997 goto out;
1998 }
1999
2000 *p_blkno = le64_to_cpu(rec->e_blkno);
2001 *num_clusters = le16_to_cpu(rec->e_leaf_clusters);
2002 if (e_cpos)
2003 *e_cpos = le32_to_cpu(rec->e_cpos);
2004out:
2005 brelse(eb_bh);
2006 return ret;
2007}
2008
2009typedef int (xattr_bucket_func)(struct inode *inode,
2010 struct ocfs2_xattr_bucket *bucket,
2011 void *para);
2012
2013static int ocfs2_iterate_xattr_buckets(struct inode *inode,
2014 u64 blkno,
2015 u32 clusters,
2016 xattr_bucket_func *func,
2017 void *para)
2018{
2019 int i, j, ret = 0;
2020 int blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
2021 u32 bpc = ocfs2_xattr_buckets_per_cluster(OCFS2_SB(inode->i_sb));
2022 u32 num_buckets = clusters * bpc;
2023 struct ocfs2_xattr_bucket bucket;
2024
2025 memset(&bucket, 0, sizeof(bucket));
2026
2027 mlog(0, "iterating xattr buckets in %u clusters starting from %llu\n",
2028 clusters, blkno);
2029
2030 for (i = 0; i < num_buckets; i++, blkno += blk_per_bucket) {
2031 ret = ocfs2_read_blocks(OCFS2_SB(inode->i_sb),
2032 blkno, blk_per_bucket,
2033 bucket.bhs, OCFS2_BH_CACHED, inode);
2034 if (ret) {
2035 mlog_errno(ret);
2036 goto out;
2037 }
2038
2039 bucket.xh = (struct ocfs2_xattr_header *)bucket.bhs[0]->b_data;
2040 /*
2041 * The real bucket num in this series of blocks is stored
2042 * in the 1st bucket.
2043 */
2044 if (i == 0)
2045 num_buckets = le16_to_cpu(bucket.xh->xh_num_buckets);
2046
2047 mlog(0, "iterating xattr bucket %llu\n", blkno);
2048 if (func) {
2049 ret = func(inode, &bucket, para);
2050 if (ret) {
2051 mlog_errno(ret);
2052 break;
2053 }
2054 }
2055
2056 for (j = 0; j < blk_per_bucket; j++)
2057 brelse(bucket.bhs[j]);
2058 memset(&bucket, 0, sizeof(bucket));
2059 }
2060
2061out:
2062 for (j = 0; j < blk_per_bucket; j++)
2063 brelse(bucket.bhs[j]);
2064
2065 return ret;
2066}
2067
2068struct ocfs2_xattr_tree_list {
2069 char *buffer;
2070 size_t buffer_size;
2071};
2072
2073static int ocfs2_xattr_bucket_get_name_value(struct inode *inode,
2074 struct ocfs2_xattr_header *xh,
2075 int index,
2076 int *block_off,
2077 int *new_offset)
2078{
2079 u16 name_offset;
2080
2081 if (index < 0 || index >= le16_to_cpu(xh->xh_count))
2082 return -EINVAL;
2083
2084 name_offset = le16_to_cpu(xh->xh_entries[index].xe_name_offset);
2085
2086 *block_off = name_offset >> inode->i_sb->s_blocksize_bits;
2087 *new_offset = name_offset % inode->i_sb->s_blocksize;
2088
2089 return 0;
2090}
2091
2092static int ocfs2_list_xattr_bucket(struct inode *inode,
2093 struct ocfs2_xattr_bucket *bucket,
2094 void *para)
2095{
2096 int ret = 0;
2097 struct ocfs2_xattr_tree_list *xl = (struct ocfs2_xattr_tree_list *)para;
2098 size_t size;
2099 int i, block_off, new_offset;
2100
2101 for (i = 0 ; i < le16_to_cpu(bucket->xh->xh_count); i++) {
2102 struct ocfs2_xattr_entry *entry = &bucket->xh->xh_entries[i];
2103 struct xattr_handler *handler =
2104 ocfs2_xattr_handler(ocfs2_xattr_get_type(entry));
2105
2106 if (handler) {
2107 ret = ocfs2_xattr_bucket_get_name_value(inode,
2108 bucket->xh,
2109 i,
2110 &block_off,
2111 &new_offset);
2112 if (ret)
2113 break;
2114 size = handler->list(inode, xl->buffer, xl->buffer_size,
2115 bucket->bhs[block_off]->b_data +
2116 new_offset,
2117 entry->xe_name_len);
2118 if (xl->buffer) {
2119 if (size > xl->buffer_size)
2120 return -ERANGE;
2121 xl->buffer += size;
2122 }
2123 xl->buffer_size -= size;
2124 }
2125 }
2126
2127 return ret;
2128}
2129
2130static int ocfs2_xattr_tree_list_index_block(struct inode *inode,
2131 struct ocfs2_xattr_tree_root *xt,
2132 char *buffer,
2133 size_t buffer_size)
2134{
2135 struct ocfs2_extent_list *el = &xt->xt_list;
2136 int ret = 0;
2137 u32 name_hash = UINT_MAX, e_cpos = 0, num_clusters = 0;
2138 u64 p_blkno = 0;
2139 struct ocfs2_xattr_tree_list xl = {
2140 .buffer = buffer,
2141 .buffer_size = buffer_size,
2142 };
2143
2144 if (le16_to_cpu(el->l_next_free_rec) == 0)
2145 return 0;
2146
2147 while (name_hash > 0) {
2148 ret = ocfs2_xattr_get_rec(inode, name_hash, &p_blkno,
2149 &e_cpos, &num_clusters, el);
2150 if (ret) {
2151 mlog_errno(ret);
2152 goto out;
2153 }
2154
2155 ret = ocfs2_iterate_xattr_buckets(inode, p_blkno, num_clusters,
2156 ocfs2_list_xattr_bucket,
2157 &xl);
2158 if (ret) {
2159 mlog_errno(ret);
2160 goto out;
2161 }
2162
2163 if (e_cpos == 0)
2164 break;
2165
2166 name_hash = e_cpos - 1;
2167 }
2168
2169 ret = buffer_size - xl.buffer_size;
2170out:
2171 return ret;
2172}