diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-11-11 12:31:32 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-11-11 12:31:32 -0500 |
| commit | ad1164b79f1905ec1611cdc2a44949618bced2a6 (patch) | |
| tree | cdc4be3325d6bcd58f90d552f3760585f4e4658f | |
| parent | 0906dd9df2f79042cfa82d8388895be7cbe7a51b (diff) | |
| parent | 6c1e183e12dbd78a897a859f13220406296fee31 (diff) | |
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2: (21 commits)
ocfs2: Check search result in ocfs2_xattr_block_get()
ocfs2: fix printk related build warnings in xattr.c
ocfs2: truncate outstanding block after direct io failure
ocfs2/xattr: Proper hash collision handle in bucket division
ocfs2: return 0 in page_mkwrite to let VFS retry.
ocfs2: Set journal descriptor to NULL after journal shutdown
ocfs2: Fix check of return value of ocfs2_start_trans() in xattr.c.
ocfs2: Let inode be really deleted when ocfs2_mknod_locked() fails
ocfs2: Fix checking of return value of new_inode()
ocfs2: Fix check of return value of ocfs2_start_trans()
ocfs2: Fix some typos in xattr annotations.
ocfs2: Remove unused ocfs2_restore_xattr_block().
ocfs2: Don't repeat ocfs2_xattr_block_find()
ocfs2: Specify appropriate journal access for new xattr buckets.
ocfs2: Check errors from ocfs2_xattr_update_xattr_search()
ocfs2: Don't return -EFAULT from a corrupt xattr entry.
ocfs2: Check xattr block signatures properly.
ocfs2: add handler_map array bounds checking
ocfs2: remove duplicate definition in xattr
ocfs2: fix function declaration and definition in xattr
...
| -rw-r--r-- | fs/ocfs2/file.c | 27 | ||||
| -rw-r--r-- | fs/ocfs2/inode.c | 6 | ||||
| -rw-r--r-- | fs/ocfs2/journal.c | 1 | ||||
| -rw-r--r-- | fs/ocfs2/mmap.c | 6 | ||||
| -rw-r--r-- | fs/ocfs2/namei.c | 8 | ||||
| -rw-r--r-- | fs/ocfs2/ocfs2.h | 3 | ||||
| -rw-r--r-- | fs/ocfs2/ocfs2_fs.h | 17 | ||||
| -rw-r--r-- | fs/ocfs2/xattr.c | 372 | ||||
| -rw-r--r-- | fs/ocfs2/xattr.h | 38 |
9 files changed, 256 insertions, 222 deletions
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 7efe937a415f..e2570a3bc2b2 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
| @@ -247,8 +247,8 @@ int ocfs2_update_inode_atime(struct inode *inode, | |||
| 247 | mlog_entry_void(); | 247 | mlog_entry_void(); |
| 248 | 248 | ||
| 249 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); | 249 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); |
| 250 | if (handle == NULL) { | 250 | if (IS_ERR(handle)) { |
| 251 | ret = -ENOMEM; | 251 | ret = PTR_ERR(handle); |
| 252 | mlog_errno(ret); | 252 | mlog_errno(ret); |
| 253 | goto out; | 253 | goto out; |
| 254 | } | 254 | } |
| @@ -312,8 +312,8 @@ static int ocfs2_simple_size_update(struct inode *inode, | |||
| 312 | handle_t *handle = NULL; | 312 | handle_t *handle = NULL; |
| 313 | 313 | ||
| 314 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); | 314 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); |
| 315 | if (handle == NULL) { | 315 | if (IS_ERR(handle)) { |
| 316 | ret = -ENOMEM; | 316 | ret = PTR_ERR(handle); |
| 317 | mlog_errno(ret); | 317 | mlog_errno(ret); |
| 318 | goto out; | 318 | goto out; |
| 319 | } | 319 | } |
| @@ -1055,8 +1055,8 @@ static int __ocfs2_write_remove_suid(struct inode *inode, | |||
| 1055 | (unsigned long long)OCFS2_I(inode)->ip_blkno, inode->i_mode); | 1055 | (unsigned long long)OCFS2_I(inode)->ip_blkno, inode->i_mode); |
| 1056 | 1056 | ||
| 1057 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); | 1057 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); |
| 1058 | if (handle == NULL) { | 1058 | if (IS_ERR(handle)) { |
| 1059 | ret = -ENOMEM; | 1059 | ret = PTR_ERR(handle); |
| 1060 | mlog_errno(ret); | 1060 | mlog_errno(ret); |
| 1061 | goto out; | 1061 | goto out; |
| 1062 | } | 1062 | } |
| @@ -1259,8 +1259,8 @@ static int __ocfs2_remove_inode_range(struct inode *inode, | |||
| 1259 | } | 1259 | } |
| 1260 | 1260 | ||
| 1261 | handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS); | 1261 | handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS); |
| 1262 | if (handle == NULL) { | 1262 | if (IS_ERR(handle)) { |
| 1263 | ret = -ENOMEM; | 1263 | ret = PTR_ERR(handle); |
| 1264 | mlog_errno(ret); | 1264 | mlog_errno(ret); |
| 1265 | goto out; | 1265 | goto out; |
| 1266 | } | 1266 | } |
| @@ -1352,8 +1352,8 @@ static int ocfs2_zero_partial_clusters(struct inode *inode, | |||
| 1352 | goto out; | 1352 | goto out; |
| 1353 | 1353 | ||
| 1354 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); | 1354 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); |
| 1355 | if (handle == NULL) { | 1355 | if (IS_ERR(handle)) { |
| 1356 | ret = -ENOMEM; | 1356 | ret = PTR_ERR(handle); |
| 1357 | mlog_errno(ret); | 1357 | mlog_errno(ret); |
| 1358 | goto out; | 1358 | goto out; |
| 1359 | } | 1359 | } |
| @@ -1866,6 +1866,13 @@ relock: | |||
| 1866 | written = generic_file_direct_write(iocb, iov, &nr_segs, *ppos, | 1866 | written = generic_file_direct_write(iocb, iov, &nr_segs, *ppos, |
| 1867 | ppos, count, ocount); | 1867 | ppos, count, ocount); |
| 1868 | if (written < 0) { | 1868 | if (written < 0) { |
| 1869 | /* | ||
| 1870 | * direct write may have instantiated a few | ||
| 1871 | * blocks outside i_size. Trim these off again. | ||
| 1872 | * Don't need i_size_read because we hold i_mutex. | ||
| 1873 | */ | ||
| 1874 | if (*ppos + count > inode->i_size) | ||
| 1875 | vmtruncate(inode, inode->i_size); | ||
| 1869 | ret = written; | 1876 | ret = written; |
| 1870 | goto out_dio; | 1877 | goto out_dio; |
| 1871 | } | 1878 | } |
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 4903688f72a9..7aa00d511874 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c | |||
| @@ -1106,6 +1106,12 @@ void ocfs2_clear_inode(struct inode *inode) | |||
| 1106 | oi->ip_last_trans = 0; | 1106 | oi->ip_last_trans = 0; |
| 1107 | oi->ip_dir_start_lookup = 0; | 1107 | oi->ip_dir_start_lookup = 0; |
| 1108 | oi->ip_blkno = 0ULL; | 1108 | oi->ip_blkno = 0ULL; |
| 1109 | |||
| 1110 | /* | ||
| 1111 | * ip_jinode is used to track txns against this inode. We ensure that | ||
| 1112 | * the journal is flushed before journal shutdown. Thus it is safe to | ||
| 1113 | * have inodes get cleaned up after journal shutdown. | ||
| 1114 | */ | ||
| 1109 | jbd2_journal_release_jbd_inode(OCFS2_SB(inode->i_sb)->journal->j_journal, | 1115 | jbd2_journal_release_jbd_inode(OCFS2_SB(inode->i_sb)->journal->j_journal, |
| 1110 | &oi->ip_jinode); | 1116 | &oi->ip_jinode); |
| 1111 | 1117 | ||
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 81e40677eecb..99fe9d584f3c 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c | |||
| @@ -690,6 +690,7 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb) | |||
| 690 | 690 | ||
| 691 | /* Shutdown the kernel journal system */ | 691 | /* Shutdown the kernel journal system */ |
| 692 | jbd2_journal_destroy(journal->j_journal); | 692 | jbd2_journal_destroy(journal->j_journal); |
| 693 | journal->j_journal = NULL; | ||
| 693 | 694 | ||
| 694 | OCFS2_I(inode)->ip_open_count--; | 695 | OCFS2_I(inode)->ip_open_count--; |
| 695 | 696 | ||
diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c index 3dc18d67557c..eea1d24713ea 100644 --- a/fs/ocfs2/mmap.c +++ b/fs/ocfs2/mmap.c | |||
| @@ -113,7 +113,11 @@ static int __ocfs2_page_mkwrite(struct inode *inode, struct buffer_head *di_bh, | |||
| 113 | * ocfs2_write_begin_nolock(). | 113 | * ocfs2_write_begin_nolock(). |
| 114 | */ | 114 | */ |
| 115 | if (!PageUptodate(page) || page->mapping != inode->i_mapping) { | 115 | if (!PageUptodate(page) || page->mapping != inode->i_mapping) { |
| 116 | ret = -EINVAL; | 116 | /* |
| 117 | * the page has been umapped in ocfs2_data_downconvert_worker. | ||
| 118 | * So return 0 here and let VFS retry. | ||
| 119 | */ | ||
| 120 | ret = 0; | ||
| 117 | goto out; | 121 | goto out; |
| 118 | } | 122 | } |
| 119 | 123 | ||
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 485a6aa0ad39..f4967e634ffd 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
| @@ -378,8 +378,8 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, | |||
| 378 | } | 378 | } |
| 379 | 379 | ||
| 380 | inode = new_inode(dir->i_sb); | 380 | inode = new_inode(dir->i_sb); |
| 381 | if (IS_ERR(inode)) { | 381 | if (!inode) { |
| 382 | status = PTR_ERR(inode); | 382 | status = -ENOMEM; |
| 383 | mlog(ML_ERROR, "new_inode failed!\n"); | 383 | mlog(ML_ERROR, "new_inode failed!\n"); |
| 384 | goto leave; | 384 | goto leave; |
| 385 | } | 385 | } |
| @@ -491,8 +491,10 @@ leave: | |||
| 491 | brelse(*new_fe_bh); | 491 | brelse(*new_fe_bh); |
| 492 | *new_fe_bh = NULL; | 492 | *new_fe_bh = NULL; |
| 493 | } | 493 | } |
| 494 | if (inode) | 494 | if (inode) { |
| 495 | clear_nlink(inode); | ||
| 495 | iput(inode); | 496 | iput(inode); |
| 497 | } | ||
| 496 | } | 498 | } |
| 497 | 499 | ||
| 498 | mlog_exit(status); | 500 | mlog_exit(status); |
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index a21a465490c4..fef7ece32376 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
| @@ -473,6 +473,9 @@ static inline int ocfs2_uses_extended_slot_map(struct ocfs2_super *osb) | |||
| 473 | (____gd)->bg_signature); \ | 473 | (____gd)->bg_signature); \ |
| 474 | } while (0) | 474 | } while (0) |
| 475 | 475 | ||
| 476 | #define OCFS2_IS_VALID_XATTR_BLOCK(ptr) \ | ||
| 477 | (!strcmp((ptr)->xb_signature, OCFS2_XATTR_BLOCK_SIGNATURE)) | ||
| 478 | |||
| 476 | static inline unsigned long ino_from_blkno(struct super_block *sb, | 479 | static inline unsigned long ino_from_blkno(struct super_block *sb, |
| 477 | u64 blkno) | 480 | u64 blkno) |
| 478 | { | 481 | { |
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h index f24ce3d3f956..5f180cf7abbd 100644 --- a/fs/ocfs2/ocfs2_fs.h +++ b/fs/ocfs2/ocfs2_fs.h | |||
| @@ -742,12 +742,12 @@ struct ocfs2_group_desc | |||
| 742 | */ | 742 | */ |
| 743 | struct ocfs2_xattr_entry { | 743 | struct ocfs2_xattr_entry { |
| 744 | __le32 xe_name_hash; /* hash value of xattr prefix+suffix. */ | 744 | __le32 xe_name_hash; /* hash value of xattr prefix+suffix. */ |
| 745 | __le16 xe_name_offset; /* byte offset from the 1st etnry in the local | 745 | __le16 xe_name_offset; /* byte offset from the 1st entry in the |
| 746 | local xattr storage(inode, xattr block or | 746 | local xattr storage(inode, xattr block or |
| 747 | xattr bucket). */ | 747 | xattr bucket). */ |
| 748 | __u8 xe_name_len; /* xattr name len, does't include prefix. */ | 748 | __u8 xe_name_len; /* xattr name len, does't include prefix. */ |
| 749 | __u8 xe_type; /* the low 7 bits indicates the name prefix's | 749 | __u8 xe_type; /* the low 7 bits indicate the name prefix |
| 750 | * type and the highest 1 bits indicate whether | 750 | * type and the highest bit indicates whether |
| 751 | * the EA is stored in the local storage. */ | 751 | * the EA is stored in the local storage. */ |
| 752 | __le64 xe_value_size; /* real xattr value length. */ | 752 | __le64 xe_value_size; /* real xattr value length. */ |
| 753 | }; | 753 | }; |
| @@ -766,9 +766,10 @@ struct ocfs2_xattr_header { | |||
| 766 | xattr. */ | 766 | xattr. */ |
| 767 | __le16 xh_name_value_len; /* total length of name/value | 767 | __le16 xh_name_value_len; /* total length of name/value |
| 768 | length in this bucket. */ | 768 | length in this bucket. */ |
| 769 | __le16 xh_num_buckets; /* bucket nums in one extent | 769 | __le16 xh_num_buckets; /* Number of xattr buckets |
| 770 | record, only valid in the | 770 | in this extent record, |
| 771 | first bucket. */ | 771 | only valid in the first |
| 772 | bucket. */ | ||
| 772 | __le64 xh_csum; | 773 | __le64 xh_csum; |
| 773 | struct ocfs2_xattr_entry xh_entries[0]; /* xattr entry list. */ | 774 | struct ocfs2_xattr_entry xh_entries[0]; /* xattr entry list. */ |
| 774 | }; | 775 | }; |
| @@ -776,8 +777,8 @@ struct ocfs2_xattr_header { | |||
| 776 | /* | 777 | /* |
| 777 | * On disk structure for xattr value root. | 778 | * On disk structure for xattr value root. |
| 778 | * | 779 | * |
| 779 | * It is used when one extended attribute's size is larger, and we will save it | 780 | * When an xattr's value is large enough, it is stored in an external |
| 780 | * in an outside cluster. It will stored in a b-tree like file content. | 781 | * b-tree like file data. The xattr value root points to this structure. |
| 781 | */ | 782 | */ |
| 782 | struct ocfs2_xattr_value_root { | 783 | struct ocfs2_xattr_value_root { |
| 783 | /*00*/ __le32 xr_clusters; /* clusters covered by xattr value. */ | 784 | /*00*/ __le32 xr_clusters; /* clusters covered by xattr value. */ |
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 802c41492214..054e2efb0b7e 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
| @@ -3,25 +3,20 @@ | |||
| 3 | * | 3 | * |
| 4 | * xattr.c | 4 | * xattr.c |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 2008 Oracle. All rights reserved. | 6 | * Copyright (C) 2004, 2008 Oracle. All rights reserved. |
| 7 | * | 7 | * |
| 8 | * CREDITS: | 8 | * CREDITS: |
| 9 | * Lots of code in this file is taken from ext3. | 9 | * Lots of code in this file is copy from linux/fs/ext3/xattr.c. |
| 10 | * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de> | ||
| 10 | * | 11 | * |
| 11 | * This program is free software; you can redistribute it and/or | 12 | * This program is free software; you can redistribute it and/or |
| 12 | * modify it under the terms of the GNU General Public | 13 | * modify it under the terms of the GNU General Public |
| 13 | * License as published by the Free Software Foundation; either | 14 | * License version 2 as published by the Free Software Foundation. |
| 14 | * version 2 of the License, or (at your option) any later version. | ||
| 15 | * | 15 | * |
| 16 | * This program is distributed in the hope that it will be useful, | 16 | * This program is distributed in the hope that it will be useful, |
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 19 | * General Public License for more details. | 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 | */ | 20 | */ |
| 26 | 21 | ||
| 27 | #include <linux/capability.h> | 22 | #include <linux/capability.h> |
| @@ -83,7 +78,7 @@ struct xattr_handler *ocfs2_xattr_handlers[] = { | |||
| 83 | NULL | 78 | NULL |
| 84 | }; | 79 | }; |
| 85 | 80 | ||
| 86 | static struct xattr_handler *ocfs2_xattr_handler_map[] = { | 81 | static struct xattr_handler *ocfs2_xattr_handler_map[OCFS2_XATTR_MAX] = { |
| 87 | [OCFS2_XATTR_INDEX_USER] = &ocfs2_xattr_user_handler, | 82 | [OCFS2_XATTR_INDEX_USER] = &ocfs2_xattr_user_handler, |
| 88 | [OCFS2_XATTR_INDEX_TRUSTED] = &ocfs2_xattr_trusted_handler, | 83 | [OCFS2_XATTR_INDEX_TRUSTED] = &ocfs2_xattr_trusted_handler, |
| 89 | }; | 84 | }; |
| @@ -116,6 +111,10 @@ static int ocfs2_xattr_bucket_get_name_value(struct inode *inode, | |||
| 116 | int *block_off, | 111 | int *block_off, |
| 117 | int *new_offset); | 112 | int *new_offset); |
| 118 | 113 | ||
| 114 | static int ocfs2_xattr_block_find(struct inode *inode, | ||
| 115 | int name_index, | ||
| 116 | const char *name, | ||
| 117 | struct ocfs2_xattr_search *xs); | ||
| 119 | static int ocfs2_xattr_index_block_find(struct inode *inode, | 118 | static int ocfs2_xattr_index_block_find(struct inode *inode, |
| 120 | struct buffer_head *root_bh, | 119 | struct buffer_head *root_bh, |
| 121 | int name_index, | 120 | int name_index, |
| @@ -137,6 +136,24 @@ static int ocfs2_xattr_set_entry_index_block(struct inode *inode, | |||
| 137 | static int ocfs2_delete_xattr_index_block(struct inode *inode, | 136 | static int ocfs2_delete_xattr_index_block(struct inode *inode, |
| 138 | struct buffer_head *xb_bh); | 137 | struct buffer_head *xb_bh); |
| 139 | 138 | ||
| 139 | static inline u16 ocfs2_xattr_buckets_per_cluster(struct ocfs2_super *osb) | ||
| 140 | { | ||
| 141 | return (1 << osb->s_clustersize_bits) / OCFS2_XATTR_BUCKET_SIZE; | ||
| 142 | } | ||
| 143 | |||
| 144 | static inline u16 ocfs2_blocks_per_xattr_bucket(struct super_block *sb) | ||
| 145 | { | ||
| 146 | return OCFS2_XATTR_BUCKET_SIZE / (1 << sb->s_blocksize_bits); | ||
| 147 | } | ||
| 148 | |||
| 149 | static inline u16 ocfs2_xattr_max_xe_in_bucket(struct super_block *sb) | ||
| 150 | { | ||
| 151 | u16 len = sb->s_blocksize - | ||
| 152 | offsetof(struct ocfs2_xattr_header, xh_entries); | ||
| 153 | |||
| 154 | return len / sizeof(struct ocfs2_xattr_entry); | ||
| 155 | } | ||
| 156 | |||
| 140 | static inline const char *ocfs2_xattr_prefix(int name_index) | 157 | static inline const char *ocfs2_xattr_prefix(int name_index) |
| 141 | { | 158 | { |
| 142 | struct xattr_handler *handler = NULL; | 159 | struct xattr_handler *handler = NULL; |
| @@ -542,14 +559,12 @@ static int ocfs2_xattr_block_list(struct inode *inode, | |||
| 542 | mlog_errno(ret); | 559 | mlog_errno(ret); |
| 543 | return ret; | 560 | return ret; |
| 544 | } | 561 | } |
| 545 | /*Verify the signature of xattr block*/ | ||
| 546 | if (memcmp((void *)blk_bh->b_data, OCFS2_XATTR_BLOCK_SIGNATURE, | ||
| 547 | strlen(OCFS2_XATTR_BLOCK_SIGNATURE))) { | ||
| 548 | ret = -EFAULT; | ||
| 549 | goto cleanup; | ||
| 550 | } | ||
| 551 | 562 | ||
| 552 | xb = (struct ocfs2_xattr_block *)blk_bh->b_data; | 563 | xb = (struct ocfs2_xattr_block *)blk_bh->b_data; |
| 564 | if (!OCFS2_IS_VALID_XATTR_BLOCK(xb)) { | ||
| 565 | ret = -EIO; | ||
| 566 | goto cleanup; | ||
| 567 | } | ||
| 553 | 568 | ||
| 554 | if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) { | 569 | if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) { |
| 555 | struct ocfs2_xattr_header *header = &xb->xb_attrs.xb_header; | 570 | struct ocfs2_xattr_header *header = &xb->xb_attrs.xb_header; |
| @@ -749,47 +764,25 @@ static int ocfs2_xattr_block_get(struct inode *inode, | |||
| 749 | size_t buffer_size, | 764 | size_t buffer_size, |
| 750 | struct ocfs2_xattr_search *xs) | 765 | struct ocfs2_xattr_search *xs) |
| 751 | { | 766 | { |
| 752 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data; | ||
| 753 | struct buffer_head *blk_bh = NULL; | ||
| 754 | struct ocfs2_xattr_block *xb; | 767 | struct ocfs2_xattr_block *xb; |
| 755 | struct ocfs2_xattr_value_root *xv; | 768 | struct ocfs2_xattr_value_root *xv; |
| 756 | size_t size; | 769 | size_t size; |
| 757 | int ret = -ENODATA, name_offset, name_len, block_off, i; | 770 | int ret = -ENODATA, name_offset, name_len, block_off, i; |
| 758 | 771 | ||
| 759 | if (!di->i_xattr_loc) | ||
| 760 | return ret; | ||
| 761 | |||
| 762 | memset(&xs->bucket, 0, sizeof(xs->bucket)); | 772 | memset(&xs->bucket, 0, sizeof(xs->bucket)); |
| 763 | 773 | ||
| 764 | ret = ocfs2_read_block(inode, le64_to_cpu(di->i_xattr_loc), &blk_bh); | 774 | ret = ocfs2_xattr_block_find(inode, name_index, name, xs); |
| 765 | if (ret < 0) { | 775 | if (ret) { |
| 766 | mlog_errno(ret); | 776 | mlog_errno(ret); |
| 767 | return ret; | ||
| 768 | } | ||
| 769 | /*Verify the signature of xattr block*/ | ||
| 770 | if (memcmp((void *)blk_bh->b_data, OCFS2_XATTR_BLOCK_SIGNATURE, | ||
| 771 | strlen(OCFS2_XATTR_BLOCK_SIGNATURE))) { | ||
| 772 | ret = -EFAULT; | ||
| 773 | goto cleanup; | 777 | goto cleanup; |
| 774 | } | 778 | } |
| 775 | 779 | ||
| 776 | xs->xattr_bh = blk_bh; | 780 | if (xs->not_found) { |
| 777 | xb = (struct ocfs2_xattr_block *)blk_bh->b_data; | 781 | ret = -ENODATA; |
| 778 | |||
| 779 | if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) { | ||
| 780 | xs->header = &xb->xb_attrs.xb_header; | ||
| 781 | xs->base = (void *)xs->header; | ||
| 782 | xs->end = (void *)(blk_bh->b_data) + blk_bh->b_size; | ||
| 783 | xs->here = xs->header->xh_entries; | ||
| 784 | |||
| 785 | ret = ocfs2_xattr_find_entry(name_index, name, xs); | ||
| 786 | } else | ||
| 787 | ret = ocfs2_xattr_index_block_find(inode, blk_bh, | ||
| 788 | name_index, | ||
| 789 | name, xs); | ||
| 790 | |||
| 791 | if (ret) | ||
| 792 | goto cleanup; | 782 | goto cleanup; |
| 783 | } | ||
| 784 | |||
| 785 | xb = (struct ocfs2_xattr_block *)xs->xattr_bh->b_data; | ||
| 793 | size = le64_to_cpu(xs->here->xe_value_size); | 786 | size = le64_to_cpu(xs->here->xe_value_size); |
| 794 | if (buffer) { | 787 | if (buffer) { |
| 795 | ret = -ERANGE; | 788 | ret = -ERANGE; |
| @@ -828,7 +821,8 @@ cleanup: | |||
| 828 | brelse(xs->bucket.bhs[i]); | 821 | brelse(xs->bucket.bhs[i]); |
| 829 | memset(&xs->bucket, 0, sizeof(xs->bucket)); | 822 | memset(&xs->bucket, 0, sizeof(xs->bucket)); |
| 830 | 823 | ||
| 831 | brelse(blk_bh); | 824 | brelse(xs->xattr_bh); |
| 825 | xs->xattr_bh = NULL; | ||
| 832 | return ret; | 826 | return ret; |
| 833 | } | 827 | } |
| 834 | 828 | ||
| @@ -837,11 +831,11 @@ cleanup: | |||
| 837 | * Copy an extended attribute into the buffer provided. | 831 | * Copy an extended attribute into the buffer provided. |
| 838 | * Buffer is NULL to compute the size of buffer required. | 832 | * Buffer is NULL to compute the size of buffer required. |
| 839 | */ | 833 | */ |
| 840 | int ocfs2_xattr_get(struct inode *inode, | 834 | static int ocfs2_xattr_get(struct inode *inode, |
| 841 | int name_index, | 835 | int name_index, |
| 842 | const char *name, | 836 | const char *name, |
| 843 | void *buffer, | 837 | void *buffer, |
| 844 | size_t buffer_size) | 838 | size_t buffer_size) |
| 845 | { | 839 | { |
| 846 | int ret; | 840 | int ret; |
| 847 | struct ocfs2_dinode *di = NULL; | 841 | struct ocfs2_dinode *di = NULL; |
| @@ -871,7 +865,7 @@ int ocfs2_xattr_get(struct inode *inode, | |||
| 871 | down_read(&oi->ip_xattr_sem); | 865 | down_read(&oi->ip_xattr_sem); |
| 872 | ret = ocfs2_xattr_ibody_get(inode, name_index, name, buffer, | 866 | ret = ocfs2_xattr_ibody_get(inode, name_index, name, buffer, |
| 873 | buffer_size, &xis); | 867 | buffer_size, &xis); |
| 874 | if (ret == -ENODATA) | 868 | if (ret == -ENODATA && di->i_xattr_loc) |
| 875 | ret = ocfs2_xattr_block_get(inode, name_index, name, buffer, | 869 | ret = ocfs2_xattr_block_get(inode, name_index, name, buffer, |
| 876 | buffer_size, &xbs); | 870 | buffer_size, &xbs); |
| 877 | up_read(&oi->ip_xattr_sem); | 871 | up_read(&oi->ip_xattr_sem); |
| @@ -1229,7 +1223,7 @@ static int ocfs2_xattr_set_entry(struct inode *inode, | |||
| 1229 | 1223 | ||
| 1230 | free = min_offs - ((void *)last - xs->base) - sizeof(__u32); | 1224 | free = min_offs - ((void *)last - xs->base) - sizeof(__u32); |
| 1231 | if (free < 0) | 1225 | if (free < 0) |
| 1232 | return -EFAULT; | 1226 | return -EIO; |
| 1233 | 1227 | ||
| 1234 | if (!xs->not_found) { | 1228 | if (!xs->not_found) { |
| 1235 | size_t size = 0; | 1229 | size_t size = 0; |
| @@ -1514,10 +1508,9 @@ static int ocfs2_xattr_free_block(struct inode *inode, | |||
| 1514 | goto out; | 1508 | goto out; |
| 1515 | } | 1509 | } |
| 1516 | 1510 | ||
| 1517 | /*Verify the signature of xattr block*/ | 1511 | xb = (struct ocfs2_xattr_block *)blk_bh->b_data; |
| 1518 | if (memcmp((void *)blk_bh->b_data, OCFS2_XATTR_BLOCK_SIGNATURE, | 1512 | if (!OCFS2_IS_VALID_XATTR_BLOCK(xb)) { |
| 1519 | strlen(OCFS2_XATTR_BLOCK_SIGNATURE))) { | 1513 | ret = -EIO; |
| 1520 | ret = -EFAULT; | ||
| 1521 | goto out; | 1514 | goto out; |
| 1522 | } | 1515 | } |
| 1523 | 1516 | ||
| @@ -1527,7 +1520,6 @@ static int ocfs2_xattr_free_block(struct inode *inode, | |||
| 1527 | goto out; | 1520 | goto out; |
| 1528 | } | 1521 | } |
| 1529 | 1522 | ||
| 1530 | xb = (struct ocfs2_xattr_block *)blk_bh->b_data; | ||
| 1531 | blk = le64_to_cpu(xb->xb_blkno); | 1523 | blk = le64_to_cpu(xb->xb_blkno); |
| 1532 | bit = le16_to_cpu(xb->xb_suballoc_bit); | 1524 | bit = le16_to_cpu(xb->xb_suballoc_bit); |
| 1533 | bg_blkno = ocfs2_which_suballoc_group(blk, bit); | 1525 | bg_blkno = ocfs2_which_suballoc_group(blk, bit); |
| @@ -1771,15 +1763,14 @@ static int ocfs2_xattr_block_find(struct inode *inode, | |||
| 1771 | mlog_errno(ret); | 1763 | mlog_errno(ret); |
| 1772 | return ret; | 1764 | return ret; |
| 1773 | } | 1765 | } |
| 1774 | /*Verify the signature of xattr block*/ | 1766 | |
| 1775 | if (memcmp((void *)blk_bh->b_data, OCFS2_XATTR_BLOCK_SIGNATURE, | 1767 | xb = (struct ocfs2_xattr_block *)blk_bh->b_data; |
| 1776 | strlen(OCFS2_XATTR_BLOCK_SIGNATURE))) { | 1768 | if (!OCFS2_IS_VALID_XATTR_BLOCK(xb)) { |
| 1777 | ret = -EFAULT; | 1769 | ret = -EIO; |
| 1778 | goto cleanup; | 1770 | goto cleanup; |
| 1779 | } | 1771 | } |
| 1780 | 1772 | ||
| 1781 | xs->xattr_bh = blk_bh; | 1773 | xs->xattr_bh = blk_bh; |
| 1782 | xb = (struct ocfs2_xattr_block *)blk_bh->b_data; | ||
| 1783 | 1774 | ||
| 1784 | if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) { | 1775 | if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) { |
| 1785 | xs->header = &xb->xb_attrs.xb_header; | 1776 | xs->header = &xb->xb_attrs.xb_header; |
| @@ -1806,52 +1797,6 @@ cleanup: | |||
| 1806 | } | 1797 | } |
| 1807 | 1798 | ||
| 1808 | /* | 1799 | /* |
| 1809 | * When all the xattrs are deleted from index btree, the ocfs2_xattr_tree | ||
| 1810 | * will be erased and ocfs2_xattr_block will have its ocfs2_xattr_header | ||
| 1811 | * re-initialized. | ||
| 1812 | */ | ||
| 1813 | static int ocfs2_restore_xattr_block(struct inode *inode, | ||
| 1814 | struct ocfs2_xattr_search *xs) | ||
| 1815 | { | ||
| 1816 | int ret; | ||
| 1817 | handle_t *handle; | ||
| 1818 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
| 1819 | struct ocfs2_xattr_block *xb = | ||
| 1820 | (struct ocfs2_xattr_block *)xs->xattr_bh->b_data; | ||
| 1821 | struct ocfs2_extent_list *el = &xb->xb_attrs.xb_root.xt_list; | ||
| 1822 | u16 xb_flags = le16_to_cpu(xb->xb_flags); | ||
| 1823 | |||
| 1824 | BUG_ON(!(xb_flags & OCFS2_XATTR_INDEXED) || | ||
| 1825 | le16_to_cpu(el->l_next_free_rec) != 0); | ||
| 1826 | |||
| 1827 | handle = ocfs2_start_trans(osb, OCFS2_XATTR_BLOCK_UPDATE_CREDITS); | ||
| 1828 | if (IS_ERR(handle)) { | ||
| 1829 | ret = PTR_ERR(handle); | ||
| 1830 | handle = NULL; | ||
| 1831 | goto out; | ||
| 1832 | } | ||
| 1833 | |||
| 1834 | ret = ocfs2_journal_access(handle, inode, xs->xattr_bh, | ||
| 1835 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
| 1836 | if (ret < 0) { | ||
| 1837 | mlog_errno(ret); | ||
| 1838 | goto out_commit; | ||
| 1839 | } | ||
| 1840 | |||
| 1841 | memset(&xb->xb_attrs, 0, inode->i_sb->s_blocksize - | ||
| 1842 | offsetof(struct ocfs2_xattr_block, xb_attrs)); | ||
| 1843 | |||
| 1844 | xb->xb_flags = cpu_to_le16(xb_flags & ~OCFS2_XATTR_INDEXED); | ||
| 1845 | |||
| 1846 | ocfs2_journal_dirty(handle, xs->xattr_bh); | ||
| 1847 | |||
| 1848 | out_commit: | ||
| 1849 | ocfs2_commit_trans(osb, handle); | ||
| 1850 | out: | ||
| 1851 | return ret; | ||
| 1852 | } | ||
| 1853 | |||
| 1854 | /* | ||
| 1855 | * ocfs2_xattr_block_set() | 1800 | * ocfs2_xattr_block_set() |
| 1856 | * | 1801 | * |
| 1857 | * Set, replace or remove an extended attribute into external block. | 1802 | * Set, replace or remove an extended attribute into external block. |
| @@ -1961,8 +1906,6 @@ out: | |||
| 1961 | } | 1906 | } |
| 1962 | 1907 | ||
| 1963 | ret = ocfs2_xattr_set_entry_index_block(inode, xi, xs); | 1908 | ret = ocfs2_xattr_set_entry_index_block(inode, xi, xs); |
| 1964 | if (!ret && xblk->xb_attrs.xb_root.xt_list.l_next_free_rec == 0) | ||
| 1965 | ret = ocfs2_restore_xattr_block(inode, xs); | ||
| 1966 | 1909 | ||
| 1967 | end: | 1910 | end: |
| 1968 | 1911 | ||
| @@ -2398,7 +2341,8 @@ static int ocfs2_xattr_index_block_find(struct inode *inode, | |||
| 2398 | BUG_ON(p_blkno == 0 || num_clusters == 0 || first_hash > name_hash); | 2341 | BUG_ON(p_blkno == 0 || num_clusters == 0 || first_hash > name_hash); |
| 2399 | 2342 | ||
| 2400 | mlog(0, "find xattr extent rec %u clusters from %llu, the first hash " | 2343 | mlog(0, "find xattr extent rec %u clusters from %llu, the first hash " |
| 2401 | "in the rec is %u\n", num_clusters, p_blkno, first_hash); | 2344 | "in the rec is %u\n", num_clusters, (unsigned long long)p_blkno, |
| 2345 | first_hash); | ||
| 2402 | 2346 | ||
| 2403 | ret = ocfs2_xattr_bucket_find(inode, name_index, name, name_hash, | 2347 | ret = ocfs2_xattr_bucket_find(inode, name_index, name, name_hash, |
| 2404 | p_blkno, first_hash, num_clusters, xs); | 2348 | p_blkno, first_hash, num_clusters, xs); |
| @@ -2422,7 +2366,7 @@ static int ocfs2_iterate_xattr_buckets(struct inode *inode, | |||
| 2422 | memset(&bucket, 0, sizeof(bucket)); | 2366 | memset(&bucket, 0, sizeof(bucket)); |
| 2423 | 2367 | ||
| 2424 | mlog(0, "iterating xattr buckets in %u clusters starting from %llu\n", | 2368 | mlog(0, "iterating xattr buckets in %u clusters starting from %llu\n", |
| 2425 | clusters, blkno); | 2369 | clusters, (unsigned long long)blkno); |
| 2426 | 2370 | ||
| 2427 | for (i = 0; i < num_buckets; i++, blkno += blk_per_bucket) { | 2371 | for (i = 0; i < num_buckets; i++, blkno += blk_per_bucket) { |
| 2428 | ret = ocfs2_read_blocks(inode, blkno, blk_per_bucket, | 2372 | ret = ocfs2_read_blocks(inode, blkno, blk_per_bucket, |
| @@ -2440,7 +2384,8 @@ static int ocfs2_iterate_xattr_buckets(struct inode *inode, | |||
| 2440 | if (i == 0) | 2384 | if (i == 0) |
| 2441 | num_buckets = le16_to_cpu(bucket.xh->xh_num_buckets); | 2385 | num_buckets = le16_to_cpu(bucket.xh->xh_num_buckets); |
| 2442 | 2386 | ||
| 2443 | mlog(0, "iterating xattr bucket %llu, first hash %u\n", blkno, | 2387 | mlog(0, "iterating xattr bucket %llu, first hash %u\n", |
| 2388 | (unsigned long long)blkno, | ||
| 2444 | le32_to_cpu(bucket.xh->xh_entries[0].xe_name_hash)); | 2389 | le32_to_cpu(bucket.xh->xh_entries[0].xe_name_hash)); |
| 2445 | if (func) { | 2390 | if (func) { |
| 2446 | ret = func(inode, &bucket, para); | 2391 | ret = func(inode, &bucket, para); |
| @@ -2776,7 +2721,8 @@ static int ocfs2_xattr_create_index_block(struct inode *inode, | |||
| 2776 | */ | 2721 | */ |
| 2777 | blkno = ocfs2_clusters_to_blocks(inode->i_sb, bit_off); | 2722 | blkno = ocfs2_clusters_to_blocks(inode->i_sb, bit_off); |
| 2778 | 2723 | ||
| 2779 | mlog(0, "allocate 1 cluster from %llu to xattr block\n", blkno); | 2724 | mlog(0, "allocate 1 cluster from %llu to xattr block\n", |
| 2725 | (unsigned long long)blkno); | ||
| 2780 | 2726 | ||
| 2781 | xh_bh = sb_getblk(inode->i_sb, blkno); | 2727 | xh_bh = sb_getblk(inode->i_sb, blkno); |
| 2782 | if (!xh_bh) { | 2728 | if (!xh_bh) { |
| @@ -2818,7 +2764,11 @@ static int ocfs2_xattr_create_index_block(struct inode *inode, | |||
| 2818 | if (data_bh) | 2764 | if (data_bh) |
| 2819 | ocfs2_journal_dirty(handle, data_bh); | 2765 | ocfs2_journal_dirty(handle, data_bh); |
| 2820 | 2766 | ||
| 2821 | ocfs2_xattr_update_xattr_search(inode, xs, xb_bh, xh_bh); | 2767 | ret = ocfs2_xattr_update_xattr_search(inode, xs, xb_bh, xh_bh); |
| 2768 | if (ret) { | ||
| 2769 | mlog_errno(ret); | ||
| 2770 | goto out_commit; | ||
| 2771 | } | ||
| 2822 | 2772 | ||
| 2823 | /* Change from ocfs2_xattr_header to ocfs2_xattr_tree_root */ | 2773 | /* Change from ocfs2_xattr_header to ocfs2_xattr_tree_root */ |
| 2824 | memset(&xb->xb_attrs, 0, inode->i_sb->s_blocksize - | 2774 | memset(&xb->xb_attrs, 0, inode->i_sb->s_blocksize - |
| @@ -2941,8 +2891,8 @@ static int ocfs2_defrag_xattr_bucket(struct inode *inode, | |||
| 2941 | 2891 | ||
| 2942 | mlog(0, "adjust xattr bucket in %llu, count = %u, " | 2892 | mlog(0, "adjust xattr bucket in %llu, count = %u, " |
| 2943 | "xh_free_start = %u, xh_name_value_len = %u.\n", | 2893 | "xh_free_start = %u, xh_name_value_len = %u.\n", |
| 2944 | blkno, le16_to_cpu(xh->xh_count), xh_free_start, | 2894 | (unsigned long long)blkno, le16_to_cpu(xh->xh_count), |
| 2945 | le16_to_cpu(xh->xh_name_value_len)); | 2895 | xh_free_start, le16_to_cpu(xh->xh_name_value_len)); |
| 2946 | 2896 | ||
| 2947 | /* | 2897 | /* |
| 2948 | * sort all the entries by their offset. | 2898 | * sort all the entries by their offset. |
| @@ -3058,7 +3008,7 @@ static int ocfs2_mv_xattr_bucket_cross_cluster(struct inode *inode, | |||
| 3058 | prev_blkno += (num_clusters - 1) * bpc + bpc / 2; | 3008 | prev_blkno += (num_clusters - 1) * bpc + bpc / 2; |
| 3059 | 3009 | ||
| 3060 | mlog(0, "move half of xattrs in cluster %llu to %llu\n", | 3010 | mlog(0, "move half of xattrs in cluster %llu to %llu\n", |
| 3061 | prev_blkno, new_blkno); | 3011 | (unsigned long long)prev_blkno, (unsigned long long)new_blkno); |
| 3062 | 3012 | ||
| 3063 | /* | 3013 | /* |
| 3064 | * We need to update the 1st half of the new cluster and | 3014 | * We need to update the 1st half of the new cluster and |
| @@ -3168,26 +3118,74 @@ static int ocfs2_read_xattr_bucket(struct inode *inode, | |||
| 3168 | } | 3118 | } |
| 3169 | 3119 | ||
| 3170 | /* | 3120 | /* |
| 3171 | * Move half num of the xattrs in old bucket(blk) to new bucket(new_blk). | 3121 | * Find the suitable pos when we divide a bucket into 2. |
| 3122 | * We have to make sure the xattrs with the same hash value exist | ||
| 3123 | * in the same bucket. | ||
| 3124 | * | ||
| 3125 | * If this ocfs2_xattr_header covers more than one hash value, find a | ||
| 3126 | * place where the hash value changes. Try to find the most even split. | ||
| 3127 | * The most common case is that all entries have different hash values, | ||
| 3128 | * and the first check we make will find a place to split. | ||
| 3129 | */ | ||
| 3130 | static int ocfs2_xattr_find_divide_pos(struct ocfs2_xattr_header *xh) | ||
| 3131 | { | ||
| 3132 | struct ocfs2_xattr_entry *entries = xh->xh_entries; | ||
| 3133 | int count = le16_to_cpu(xh->xh_count); | ||
| 3134 | int delta, middle = count / 2; | ||
| 3135 | |||
| 3136 | /* | ||
| 3137 | * We start at the middle. Each step gets farther away in both | ||
| 3138 | * directions. We therefore hit the change in hash value | ||
| 3139 | * nearest to the middle. Note that this loop does not execute for | ||
| 3140 | * count < 2. | ||
| 3141 | */ | ||
| 3142 | for (delta = 0; delta < middle; delta++) { | ||
| 3143 | /* Let's check delta earlier than middle */ | ||
| 3144 | if (cmp_xe(&entries[middle - delta - 1], | ||
| 3145 | &entries[middle - delta])) | ||
| 3146 | return middle - delta; | ||
| 3147 | |||
| 3148 | /* For even counts, don't walk off the end */ | ||
| 3149 | if ((middle + delta + 1) == count) | ||
| 3150 | continue; | ||
| 3151 | |||
| 3152 | /* Now try delta past middle */ | ||
| 3153 | if (cmp_xe(&entries[middle + delta], | ||
| 3154 | &entries[middle + delta + 1])) | ||
| 3155 | return middle + delta + 1; | ||
| 3156 | } | ||
| 3157 | |||
| 3158 | /* Every entry had the same hash */ | ||
| 3159 | return count; | ||
| 3160 | } | ||
| 3161 | |||
| 3162 | /* | ||
| 3163 | * Move some xattrs in old bucket(blk) to new bucket(new_blk). | ||
| 3172 | * first_hash will record the 1st hash of the new bucket. | 3164 | * first_hash will record the 1st hash of the new bucket. |
| 3165 | * | ||
| 3166 | * Normally half of the xattrs will be moved. But we have to make | ||
| 3167 | * sure that the xattrs with the same hash value are stored in the | ||
| 3168 | * same bucket. If all the xattrs in this bucket have the same hash | ||
| 3169 | * value, the new bucket will be initialized as an empty one and the | ||
| 3170 | * first_hash will be initialized as (hash_value+1). | ||
| 3173 | */ | 3171 | */ |
| 3174 | static int ocfs2_half_xattr_bucket(struct inode *inode, | 3172 | static int ocfs2_divide_xattr_bucket(struct inode *inode, |
| 3175 | handle_t *handle, | 3173 | handle_t *handle, |
| 3176 | u64 blk, | 3174 | u64 blk, |
| 3177 | u64 new_blk, | 3175 | u64 new_blk, |
| 3178 | u32 *first_hash, | 3176 | u32 *first_hash, |
| 3179 | int new_bucket_head) | 3177 | int new_bucket_head) |
| 3180 | { | 3178 | { |
| 3181 | int ret, i; | 3179 | int ret, i; |
| 3182 | u16 count, start, len, name_value_len, xe_len, name_offset; | 3180 | int count, start, len, name_value_len = 0, xe_len, name_offset = 0; |
| 3183 | u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb); | 3181 | u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb); |
| 3184 | struct buffer_head **s_bhs, **t_bhs = NULL; | 3182 | struct buffer_head **s_bhs, **t_bhs = NULL; |
| 3185 | struct ocfs2_xattr_header *xh; | 3183 | struct ocfs2_xattr_header *xh; |
| 3186 | struct ocfs2_xattr_entry *xe; | 3184 | struct ocfs2_xattr_entry *xe; |
| 3187 | int blocksize = inode->i_sb->s_blocksize; | 3185 | int blocksize = inode->i_sb->s_blocksize; |
| 3188 | 3186 | ||
| 3189 | mlog(0, "move half of xattrs from bucket %llu to %llu\n", | 3187 | mlog(0, "move some of xattrs from bucket %llu to %llu\n", |
| 3190 | blk, new_blk); | 3188 | (unsigned long long)blk, (unsigned long long)new_blk); |
| 3191 | 3189 | ||
| 3192 | s_bhs = kcalloc(blk_per_bucket, sizeof(struct buffer_head *), GFP_NOFS); | 3190 | s_bhs = kcalloc(blk_per_bucket, sizeof(struct buffer_head *), GFP_NOFS); |
| 3193 | if (!s_bhs) | 3191 | if (!s_bhs) |
| @@ -3220,21 +3218,44 @@ static int ocfs2_half_xattr_bucket(struct inode *inode, | |||
| 3220 | 3218 | ||
| 3221 | for (i = 0; i < blk_per_bucket; i++) { | 3219 | for (i = 0; i < blk_per_bucket; i++) { |
| 3222 | ret = ocfs2_journal_access(handle, inode, t_bhs[i], | 3220 | ret = ocfs2_journal_access(handle, inode, t_bhs[i], |
| 3223 | OCFS2_JOURNAL_ACCESS_CREATE); | 3221 | new_bucket_head ? |
| 3222 | OCFS2_JOURNAL_ACCESS_CREATE : | ||
| 3223 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
| 3224 | if (ret) { | 3224 | if (ret) { |
| 3225 | mlog_errno(ret); | 3225 | mlog_errno(ret); |
| 3226 | goto out; | 3226 | goto out; |
| 3227 | } | 3227 | } |
| 3228 | } | 3228 | } |
| 3229 | 3229 | ||
| 3230 | xh = (struct ocfs2_xattr_header *)s_bhs[0]->b_data; | ||
| 3231 | count = le16_to_cpu(xh->xh_count); | ||
| 3232 | start = ocfs2_xattr_find_divide_pos(xh); | ||
| 3233 | |||
| 3234 | if (start == count) { | ||
| 3235 | xe = &xh->xh_entries[start-1]; | ||
| 3236 | |||
| 3237 | /* | ||
| 3238 | * initialized a new empty bucket here. | ||
| 3239 | * The hash value is set as one larger than | ||
| 3240 | * that of the last entry in the previous bucket. | ||
| 3241 | */ | ||
| 3242 | for (i = 0; i < blk_per_bucket; i++) | ||
| 3243 | memset(t_bhs[i]->b_data, 0, blocksize); | ||
| 3244 | |||
| 3245 | xh = (struct ocfs2_xattr_header *)t_bhs[0]->b_data; | ||
| 3246 | xh->xh_free_start = cpu_to_le16(blocksize); | ||
| 3247 | xh->xh_entries[0].xe_name_hash = xe->xe_name_hash; | ||
| 3248 | le32_add_cpu(&xh->xh_entries[0].xe_name_hash, 1); | ||
| 3249 | |||
| 3250 | goto set_num_buckets; | ||
| 3251 | } | ||
| 3252 | |||
| 3230 | /* copy the whole bucket to the new first. */ | 3253 | /* copy the whole bucket to the new first. */ |
| 3231 | for (i = 0; i < blk_per_bucket; i++) | 3254 | for (i = 0; i < blk_per_bucket; i++) |
| 3232 | memcpy(t_bhs[i]->b_data, s_bhs[i]->b_data, blocksize); | 3255 | memcpy(t_bhs[i]->b_data, s_bhs[i]->b_data, blocksize); |
| 3233 | 3256 | ||
| 3234 | /* update the new bucket. */ | 3257 | /* update the new bucket. */ |
| 3235 | xh = (struct ocfs2_xattr_header *)t_bhs[0]->b_data; | 3258 | xh = (struct ocfs2_xattr_header *)t_bhs[0]->b_data; |
| 3236 | count = le16_to_cpu(xh->xh_count); | ||
| 3237 | start = count / 2; | ||
| 3238 | 3259 | ||
| 3239 | /* | 3260 | /* |
| 3240 | * Calculate the total name/value len and xh_free_start for | 3261 | * Calculate the total name/value len and xh_free_start for |
| @@ -3291,6 +3312,7 @@ static int ocfs2_half_xattr_bucket(struct inode *inode, | |||
| 3291 | xh->xh_free_start = xe->xe_name_offset; | 3312 | xh->xh_free_start = xe->xe_name_offset; |
| 3292 | } | 3313 | } |
| 3293 | 3314 | ||
| 3315 | set_num_buckets: | ||
| 3294 | /* set xh->xh_num_buckets for the new xh. */ | 3316 | /* set xh->xh_num_buckets for the new xh. */ |
| 3295 | if (new_bucket_head) | 3317 | if (new_bucket_head) |
| 3296 | xh->xh_num_buckets = cpu_to_le16(1); | 3318 | xh->xh_num_buckets = cpu_to_le16(1); |
| @@ -3308,9 +3330,13 @@ static int ocfs2_half_xattr_bucket(struct inode *inode, | |||
| 3308 | *first_hash = le32_to_cpu(xh->xh_entries[0].xe_name_hash); | 3330 | *first_hash = le32_to_cpu(xh->xh_entries[0].xe_name_hash); |
| 3309 | 3331 | ||
| 3310 | /* | 3332 | /* |
| 3311 | * Now only update the 1st block of the old bucket. | 3333 | * Now only update the 1st block of the old bucket. If we |
| 3312 | * Please note that the entry has been sorted already above. | 3334 | * just added a new empty bucket, there is no need to modify |
| 3335 | * it. | ||
| 3313 | */ | 3336 | */ |
| 3337 | if (start == count) | ||
| 3338 | goto out; | ||
| 3339 | |||
| 3314 | xh = (struct ocfs2_xattr_header *)s_bhs[0]->b_data; | 3340 | xh = (struct ocfs2_xattr_header *)s_bhs[0]->b_data; |
| 3315 | memset(&xh->xh_entries[start], 0, | 3341 | memset(&xh->xh_entries[start], 0, |
| 3316 | sizeof(struct ocfs2_xattr_entry) * (count - start)); | 3342 | sizeof(struct ocfs2_xattr_entry) * (count - start)); |
| @@ -3358,7 +3384,8 @@ static int ocfs2_cp_xattr_bucket(struct inode *inode, | |||
| 3358 | BUG_ON(s_blkno == t_blkno); | 3384 | BUG_ON(s_blkno == t_blkno); |
| 3359 | 3385 | ||
| 3360 | mlog(0, "cp bucket %llu to %llu, target is %d\n", | 3386 | mlog(0, "cp bucket %llu to %llu, target is %d\n", |
| 3361 | s_blkno, t_blkno, t_is_new); | 3387 | (unsigned long long)s_blkno, (unsigned long long)t_blkno, |
| 3388 | t_is_new); | ||
| 3362 | 3389 | ||
| 3363 | s_bhs = kzalloc(sizeof(struct buffer_head *) * blk_per_bucket, | 3390 | s_bhs = kzalloc(sizeof(struct buffer_head *) * blk_per_bucket, |
| 3364 | GFP_NOFS); | 3391 | GFP_NOFS); |
| @@ -3382,6 +3409,8 @@ static int ocfs2_cp_xattr_bucket(struct inode *inode, | |||
| 3382 | 3409 | ||
| 3383 | for (i = 0; i < blk_per_bucket; i++) { | 3410 | for (i = 0; i < blk_per_bucket; i++) { |
| 3384 | ret = ocfs2_journal_access(handle, inode, t_bhs[i], | 3411 | ret = ocfs2_journal_access(handle, inode, t_bhs[i], |
| 3412 | t_is_new ? | ||
| 3413 | OCFS2_JOURNAL_ACCESS_CREATE : | ||
| 3385 | OCFS2_JOURNAL_ACCESS_WRITE); | 3414 | OCFS2_JOURNAL_ACCESS_WRITE); |
| 3386 | if (ret) | 3415 | if (ret) |
| 3387 | goto out; | 3416 | goto out; |
| @@ -3428,7 +3457,8 @@ static int ocfs2_cp_xattr_cluster(struct inode *inode, | |||
| 3428 | struct ocfs2_xattr_header *xh; | 3457 | struct ocfs2_xattr_header *xh; |
| 3429 | u64 to_blk_start = to_blk; | 3458 | u64 to_blk_start = to_blk; |
| 3430 | 3459 | ||
| 3431 | mlog(0, "cp xattrs from cluster %llu to %llu\n", src_blk, to_blk); | 3460 | mlog(0, "cp xattrs from cluster %llu to %llu\n", |
| 3461 | (unsigned long long)src_blk, (unsigned long long)to_blk); | ||
| 3432 | 3462 | ||
| 3433 | /* | 3463 | /* |
| 3434 | * We need to update the new cluster and 1 more for the update of | 3464 | * We need to update the new cluster and 1 more for the update of |
| @@ -3493,15 +3523,15 @@ out: | |||
| 3493 | } | 3523 | } |
| 3494 | 3524 | ||
| 3495 | /* | 3525 | /* |
| 3496 | * Move half of the xattrs in this cluster to the new cluster. | 3526 | * Move some xattrs in this cluster to the new cluster. |
| 3497 | * This function should only be called when bucket size == cluster size. | 3527 | * This function should only be called when bucket size == cluster size. |
| 3498 | * Otherwise ocfs2_mv_xattr_bucket_cross_cluster should be used instead. | 3528 | * Otherwise ocfs2_mv_xattr_bucket_cross_cluster should be used instead. |
| 3499 | */ | 3529 | */ |
| 3500 | static int ocfs2_half_xattr_cluster(struct inode *inode, | 3530 | static int ocfs2_divide_xattr_cluster(struct inode *inode, |
| 3501 | handle_t *handle, | 3531 | handle_t *handle, |
| 3502 | u64 prev_blk, | 3532 | u64 prev_blk, |
| 3503 | u64 new_blk, | 3533 | u64 new_blk, |
| 3504 | u32 *first_hash) | 3534 | u32 *first_hash) |
| 3505 | { | 3535 | { |
| 3506 | u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb); | 3536 | u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb); |
| 3507 | int ret, credits = 2 * blk_per_bucket; | 3537 | int ret, credits = 2 * blk_per_bucket; |
| @@ -3515,8 +3545,8 @@ static int ocfs2_half_xattr_cluster(struct inode *inode, | |||
| 3515 | } | 3545 | } |
| 3516 | 3546 | ||
| 3517 | /* Move half of the xattr in start_blk to the next bucket. */ | 3547 | /* Move half of the xattr in start_blk to the next bucket. */ |
| 3518 | return ocfs2_half_xattr_bucket(inode, handle, prev_blk, | 3548 | return ocfs2_divide_xattr_bucket(inode, handle, prev_blk, |
| 3519 | new_blk, first_hash, 1); | 3549 | new_blk, first_hash, 1); |
| 3520 | } | 3550 | } |
| 3521 | 3551 | ||
| 3522 | /* | 3552 | /* |
| @@ -3559,7 +3589,8 @@ static int ocfs2_adjust_xattr_cross_cluster(struct inode *inode, | |||
| 3559 | int bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1); | 3589 | int bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1); |
| 3560 | 3590 | ||
| 3561 | mlog(0, "adjust xattrs from cluster %llu len %u to %llu\n", | 3591 | mlog(0, "adjust xattrs from cluster %llu len %u to %llu\n", |
| 3562 | prev_blk, prev_clusters, new_blk); | 3592 | (unsigned long long)prev_blk, prev_clusters, |
| 3593 | (unsigned long long)new_blk); | ||
| 3563 | 3594 | ||
| 3564 | if (ocfs2_xattr_buckets_per_cluster(OCFS2_SB(inode->i_sb)) > 1) | 3595 | if (ocfs2_xattr_buckets_per_cluster(OCFS2_SB(inode->i_sb)) > 1) |
| 3565 | ret = ocfs2_mv_xattr_bucket_cross_cluster(inode, | 3596 | ret = ocfs2_mv_xattr_bucket_cross_cluster(inode, |
| @@ -3578,9 +3609,9 @@ static int ocfs2_adjust_xattr_cross_cluster(struct inode *inode, | |||
| 3578 | last_blk, new_blk, | 3609 | last_blk, new_blk, |
| 3579 | v_start); | 3610 | v_start); |
| 3580 | else { | 3611 | else { |
| 3581 | ret = ocfs2_half_xattr_cluster(inode, handle, | 3612 | ret = ocfs2_divide_xattr_cluster(inode, handle, |
| 3582 | last_blk, new_blk, | 3613 | last_blk, new_blk, |
| 3583 | v_start); | 3614 | v_start); |
| 3584 | 3615 | ||
| 3585 | if ((*header_bh)->b_blocknr == last_blk && extend) | 3616 | if ((*header_bh)->b_blocknr == last_blk && extend) |
| 3586 | *extend = 0; | 3617 | *extend = 0; |
| @@ -3629,7 +3660,7 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, | |||
| 3629 | mlog(0, "Add new xattr cluster for %llu, previous xattr hash = %u, " | 3660 | mlog(0, "Add new xattr cluster for %llu, previous xattr hash = %u, " |
| 3630 | "previous xattr blkno = %llu\n", | 3661 | "previous xattr blkno = %llu\n", |
| 3631 | (unsigned long long)OCFS2_I(inode)->ip_blkno, | 3662 | (unsigned long long)OCFS2_I(inode)->ip_blkno, |
| 3632 | prev_cpos, prev_blkno); | 3663 | prev_cpos, (unsigned long long)prev_blkno); |
| 3633 | 3664 | ||
| 3634 | ocfs2_init_xattr_tree_extent_tree(&et, inode, root_bh); | 3665 | ocfs2_init_xattr_tree_extent_tree(&et, inode, root_bh); |
| 3635 | 3666 | ||
| @@ -3716,7 +3747,7 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, | |||
| 3716 | } | 3747 | } |
| 3717 | } | 3748 | } |
| 3718 | mlog(0, "Insert %u clusters at block %llu for xattr at %u\n", | 3749 | mlog(0, "Insert %u clusters at block %llu for xattr at %u\n", |
| 3719 | num_bits, block, v_start); | 3750 | num_bits, (unsigned long long)block, v_start); |
| 3720 | ret = ocfs2_insert_extent(osb, handle, inode, &et, v_start, block, | 3751 | ret = ocfs2_insert_extent(osb, handle, inode, &et, v_start, block, |
| 3721 | num_bits, 0, meta_ac); | 3752 | num_bits, 0, meta_ac); |
| 3722 | if (ret < 0) { | 3753 | if (ret < 0) { |
| @@ -3761,7 +3792,7 @@ static int ocfs2_extend_xattr_bucket(struct inode *inode, | |||
| 3761 | u16 bucket = le16_to_cpu(first_xh->xh_num_buckets); | 3792 | u16 bucket = le16_to_cpu(first_xh->xh_num_buckets); |
| 3762 | 3793 | ||
| 3763 | mlog(0, "extend xattr bucket in %llu, xattr extend rec starting " | 3794 | mlog(0, "extend xattr bucket in %llu, xattr extend rec starting " |
| 3764 | "from %llu, len = %u\n", start_blk, | 3795 | "from %llu, len = %u\n", (unsigned long long)start_blk, |
| 3765 | (unsigned long long)first_bh->b_blocknr, num_clusters); | 3796 | (unsigned long long)first_bh->b_blocknr, num_clusters); |
| 3766 | 3797 | ||
| 3767 | BUG_ON(bucket >= num_buckets); | 3798 | BUG_ON(bucket >= num_buckets); |
| @@ -3797,8 +3828,8 @@ static int ocfs2_extend_xattr_bucket(struct inode *inode, | |||
| 3797 | } | 3828 | } |
| 3798 | 3829 | ||
| 3799 | /* Move half of the xattr in start_blk to the next bucket. */ | 3830 | /* Move half of the xattr in start_blk to the next bucket. */ |
| 3800 | ret = ocfs2_half_xattr_bucket(inode, handle, start_blk, | 3831 | ret = ocfs2_divide_xattr_bucket(inode, handle, start_blk, |
| 3801 | start_blk + blk_per_bucket, NULL, 0); | 3832 | start_blk + blk_per_bucket, NULL, 0); |
| 3802 | 3833 | ||
| 3803 | le16_add_cpu(&first_xh->xh_num_buckets, 1); | 3834 | le16_add_cpu(&first_xh->xh_num_buckets, 1); |
| 3804 | ocfs2_journal_dirty(handle, first_bh); | 3835 | ocfs2_journal_dirty(handle, first_bh); |
| @@ -4146,7 +4177,7 @@ static int ocfs2_xattr_value_update_size(struct inode *inode, | |||
| 4146 | handle_t *handle = NULL; | 4177 | handle_t *handle = NULL; |
| 4147 | 4178 | ||
| 4148 | handle = ocfs2_start_trans(osb, 1); | 4179 | handle = ocfs2_start_trans(osb, 1); |
| 4149 | if (handle == NULL) { | 4180 | if (IS_ERR(handle)) { |
| 4150 | ret = -ENOMEM; | 4181 | ret = -ENOMEM; |
| 4151 | mlog_errno(ret); | 4182 | mlog_errno(ret); |
| 4152 | goto out; | 4183 | goto out; |
| @@ -4313,7 +4344,7 @@ static int ocfs2_rm_xattr_cluster(struct inode *inode, | |||
| 4313 | } | 4344 | } |
| 4314 | 4345 | ||
| 4315 | handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS); | 4346 | handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS); |
| 4316 | if (handle == NULL) { | 4347 | if (IS_ERR(handle)) { |
| 4317 | ret = -ENOMEM; | 4348 | ret = -ENOMEM; |
| 4318 | mlog_errno(ret); | 4349 | mlog_errno(ret); |
| 4319 | goto out; | 4350 | goto out; |
| @@ -4489,11 +4520,21 @@ out: | |||
| 4489 | return ret; | 4520 | return ret; |
| 4490 | } | 4521 | } |
| 4491 | 4522 | ||
| 4492 | /* check whether the xattr bucket is filled up with the same hash value. */ | 4523 | /* |
| 4524 | * check whether the xattr bucket is filled up with the same hash value. | ||
| 4525 | * If we want to insert the xattr with the same hash, return -ENOSPC. | ||
| 4526 | * If we want to insert a xattr with different hash value, go ahead | ||
| 4527 | * and ocfs2_divide_xattr_bucket will handle this. | ||
| 4528 | */ | ||
| 4493 | static int ocfs2_check_xattr_bucket_collision(struct inode *inode, | 4529 | static int ocfs2_check_xattr_bucket_collision(struct inode *inode, |
| 4494 | struct ocfs2_xattr_bucket *bucket) | 4530 | struct ocfs2_xattr_bucket *bucket, |
| 4531 | const char *name) | ||
| 4495 | { | 4532 | { |
| 4496 | struct ocfs2_xattr_header *xh = bucket->xh; | 4533 | struct ocfs2_xattr_header *xh = bucket->xh; |
| 4534 | u32 name_hash = ocfs2_xattr_name_hash(inode, name, strlen(name)); | ||
| 4535 | |||
| 4536 | if (name_hash != le32_to_cpu(xh->xh_entries[0].xe_name_hash)) | ||
| 4537 | return 0; | ||
| 4497 | 4538 | ||
| 4498 | if (xh->xh_entries[le16_to_cpu(xh->xh_count) - 1].xe_name_hash == | 4539 | if (xh->xh_entries[le16_to_cpu(xh->xh_count) - 1].xe_name_hash == |
| 4499 | xh->xh_entries[0].xe_name_hash) { | 4540 | xh->xh_entries[0].xe_name_hash) { |
| @@ -4616,7 +4657,9 @@ try_again: | |||
| 4616 | * one bucket's worth, so check it here whether we need to | 4657 | * one bucket's worth, so check it here whether we need to |
| 4617 | * add a new bucket for the insert. | 4658 | * add a new bucket for the insert. |
| 4618 | */ | 4659 | */ |
| 4619 | ret = ocfs2_check_xattr_bucket_collision(inode, &xs->bucket); | 4660 | ret = ocfs2_check_xattr_bucket_collision(inode, |
| 4661 | &xs->bucket, | ||
| 4662 | xi->name); | ||
| 4620 | if (ret) { | 4663 | if (ret) { |
| 4621 | mlog_errno(ret); | 4664 | mlog_errno(ret); |
| 4622 | goto out; | 4665 | goto out; |
| @@ -4727,14 +4770,11 @@ out: | |||
| 4727 | /* | 4770 | /* |
| 4728 | * 'trusted' attributes support | 4771 | * 'trusted' attributes support |
| 4729 | */ | 4772 | */ |
| 4730 | |||
| 4731 | #define XATTR_TRUSTED_PREFIX "trusted." | ||
| 4732 | |||
| 4733 | static size_t ocfs2_xattr_trusted_list(struct inode *inode, char *list, | 4773 | static size_t ocfs2_xattr_trusted_list(struct inode *inode, char *list, |
| 4734 | size_t list_size, const char *name, | 4774 | size_t list_size, const char *name, |
| 4735 | size_t name_len) | 4775 | size_t name_len) |
| 4736 | { | 4776 | { |
| 4737 | const size_t prefix_len = sizeof(XATTR_TRUSTED_PREFIX) - 1; | 4777 | const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN; |
| 4738 | const size_t total_len = prefix_len + name_len + 1; | 4778 | const size_t total_len = prefix_len + name_len + 1; |
| 4739 | 4779 | ||
| 4740 | if (list && total_len <= list_size) { | 4780 | if (list && total_len <= list_size) { |
| @@ -4771,18 +4811,14 @@ struct xattr_handler ocfs2_xattr_trusted_handler = { | |||
| 4771 | .set = ocfs2_xattr_trusted_set, | 4811 | .set = ocfs2_xattr_trusted_set, |
| 4772 | }; | 4812 | }; |
| 4773 | 4813 | ||
| 4774 | |||
| 4775 | /* | 4814 | /* |
| 4776 | * 'user' attributes support | 4815 | * 'user' attributes support |
| 4777 | */ | 4816 | */ |
| 4778 | |||
| 4779 | #define XATTR_USER_PREFIX "user." | ||
| 4780 | |||
| 4781 | static size_t ocfs2_xattr_user_list(struct inode *inode, char *list, | 4817 | static size_t ocfs2_xattr_user_list(struct inode *inode, char *list, |
| 4782 | size_t list_size, const char *name, | 4818 | size_t list_size, const char *name, |
| 4783 | size_t name_len) | 4819 | size_t name_len) |
| 4784 | { | 4820 | { |
| 4785 | const size_t prefix_len = sizeof(XATTR_USER_PREFIX) - 1; | 4821 | const size_t prefix_len = XATTR_USER_PREFIX_LEN; |
| 4786 | const size_t total_len = prefix_len + name_len + 1; | 4822 | const size_t total_len = prefix_len + name_len + 1; |
| 4787 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 4823 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
| 4788 | 4824 | ||
diff --git a/fs/ocfs2/xattr.h b/fs/ocfs2/xattr.h index c25c7c62a059..1d8314c7656d 100644 --- a/fs/ocfs2/xattr.h +++ b/fs/ocfs2/xattr.h | |||
| @@ -3,24 +3,16 @@ | |||
| 3 | * | 3 | * |
| 4 | * xattr.h | 4 | * xattr.h |
| 5 | * | 5 | * |
| 6 | * Function prototypes | 6 | * Copyright (C) 2004, 2008 Oracle. All rights reserved. |
| 7 | * | ||
| 8 | * Copyright (C) 2008 Oracle. All rights reserved. | ||
| 9 | * | 7 | * |
| 10 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
| 11 | * modify it under the terms of the GNU General Public | 9 | * modify it under the terms of the GNU General Public |
| 12 | * License as published by the Free Software Foundation; either | 10 | * License version 2 as published by the Free Software Foundation. |
| 13 | * version 2 of the License, or (at your option) any later version. | ||
| 14 | * | 11 | * |
| 15 | * This program is distributed in the hope that it will be useful, | 12 | * This program is distributed in the hope that it will be useful, |
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 18 | * General Public License for more details. | 15 | * General Public License for more details. |
| 19 | * | ||
| 20 | * You should have received a copy of the GNU General Public | ||
| 21 | * License along with this program; if not, write to the | ||
| 22 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 23 | * Boston, MA 021110-1307, USA. | ||
| 24 | */ | 16 | */ |
| 25 | 17 | ||
| 26 | #ifndef OCFS2_XATTR_H | 18 | #ifndef OCFS2_XATTR_H |
| @@ -40,29 +32,11 @@ enum ocfs2_xattr_type { | |||
| 40 | 32 | ||
| 41 | extern struct xattr_handler ocfs2_xattr_user_handler; | 33 | extern struct xattr_handler ocfs2_xattr_user_handler; |
| 42 | extern struct xattr_handler ocfs2_xattr_trusted_handler; | 34 | extern struct xattr_handler ocfs2_xattr_trusted_handler; |
| 43 | |||
| 44 | extern ssize_t ocfs2_listxattr(struct dentry *, char *, size_t); | ||
| 45 | extern int ocfs2_xattr_get(struct inode *, int, const char *, void *, size_t); | ||
| 46 | extern int ocfs2_xattr_set(struct inode *, int, const char *, const void *, | ||
| 47 | size_t, int); | ||
| 48 | extern int ocfs2_xattr_remove(struct inode *inode, struct buffer_head *di_bh); | ||
| 49 | extern struct xattr_handler *ocfs2_xattr_handlers[]; | 35 | extern struct xattr_handler *ocfs2_xattr_handlers[]; |
| 50 | 36 | ||
| 51 | static inline u16 ocfs2_xattr_buckets_per_cluster(struct ocfs2_super *osb) | 37 | ssize_t ocfs2_listxattr(struct dentry *, char *, size_t); |
| 52 | { | 38 | int ocfs2_xattr_set(struct inode *, int, const char *, const void *, |
| 53 | return (1 << osb->s_clustersize_bits) / OCFS2_XATTR_BUCKET_SIZE; | 39 | size_t, int); |
| 54 | } | 40 | int ocfs2_xattr_remove(struct inode *, struct buffer_head *); |
| 55 | |||
| 56 | static inline u16 ocfs2_blocks_per_xattr_bucket(struct super_block *sb) | ||
| 57 | { | ||
| 58 | return OCFS2_XATTR_BUCKET_SIZE / (1 << sb->s_blocksize_bits); | ||
| 59 | } | ||
| 60 | |||
| 61 | static inline u16 ocfs2_xattr_max_xe_in_bucket(struct super_block *sb) | ||
| 62 | { | ||
| 63 | u16 len = sb->s_blocksize - | ||
| 64 | offsetof(struct ocfs2_xattr_header, xh_entries); | ||
| 65 | 41 | ||
| 66 | return len / sizeof(struct ocfs2_xattr_entry); | ||
| 67 | } | ||
| 68 | #endif /* OCFS2_XATTR_H */ | 42 | #endif /* OCFS2_XATTR_H */ |
