diff options
Diffstat (limited to 'fs')
| -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 | ||||
| -rw-r--r-- | fs/xfs/xfs_da_btree.c | 5 | ||||
| -rw-r--r-- | fs/xfs/xfs_dir2.c | 6 | ||||
| -rw-r--r-- | fs/xfs/xfs_inode.c | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_log.c | 39 | ||||
| -rw-r--r-- | fs/xfs/xfs_log_recover.c | 8 | ||||
| -rw-r--r-- | fs/xfs/xfs_mount.c | 5 |
15 files changed, 314 insertions, 229 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 */ |
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 9e561a9cefca..a11a8390bf6c 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c | |||
| @@ -1566,11 +1566,14 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno) | |||
| 1566 | int nmap, error, w, count, c, got, i, mapi; | 1566 | int nmap, error, w, count, c, got, i, mapi; |
| 1567 | xfs_trans_t *tp; | 1567 | xfs_trans_t *tp; |
| 1568 | xfs_mount_t *mp; | 1568 | xfs_mount_t *mp; |
| 1569 | xfs_drfsbno_t nblks; | ||
| 1569 | 1570 | ||
| 1570 | dp = args->dp; | 1571 | dp = args->dp; |
| 1571 | mp = dp->i_mount; | 1572 | mp = dp->i_mount; |
| 1572 | w = args->whichfork; | 1573 | w = args->whichfork; |
| 1573 | tp = args->trans; | 1574 | tp = args->trans; |
| 1575 | nblks = dp->i_d.di_nblocks; | ||
| 1576 | |||
| 1574 | /* | 1577 | /* |
| 1575 | * For new directories adjust the file offset and block count. | 1578 | * For new directories adjust the file offset and block count. |
| 1576 | */ | 1579 | */ |
| @@ -1647,6 +1650,8 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno) | |||
| 1647 | } | 1650 | } |
| 1648 | if (mapp != &map) | 1651 | if (mapp != &map) |
| 1649 | kmem_free(mapp); | 1652 | kmem_free(mapp); |
| 1653 | /* account for newly allocated blocks in reserved blocks total */ | ||
| 1654 | args->total -= dp->i_d.di_nblocks - nblks; | ||
| 1650 | *new_blkno = (xfs_dablk_t)bno; | 1655 | *new_blkno = (xfs_dablk_t)bno; |
| 1651 | return 0; | 1656 | return 0; |
| 1652 | } | 1657 | } |
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index 80e0dc51361c..1afb12278b8d 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c | |||
| @@ -525,11 +525,13 @@ xfs_dir2_grow_inode( | |||
| 525 | xfs_mount_t *mp; | 525 | xfs_mount_t *mp; |
| 526 | int nmap; /* number of bmap entries */ | 526 | int nmap; /* number of bmap entries */ |
| 527 | xfs_trans_t *tp; | 527 | xfs_trans_t *tp; |
| 528 | xfs_drfsbno_t nblks; | ||
| 528 | 529 | ||
| 529 | xfs_dir2_trace_args_s("grow_inode", args, space); | 530 | xfs_dir2_trace_args_s("grow_inode", args, space); |
| 530 | dp = args->dp; | 531 | dp = args->dp; |
| 531 | tp = args->trans; | 532 | tp = args->trans; |
| 532 | mp = dp->i_mount; | 533 | mp = dp->i_mount; |
| 534 | nblks = dp->i_d.di_nblocks; | ||
| 533 | /* | 535 | /* |
| 534 | * Set lowest possible block in the space requested. | 536 | * Set lowest possible block in the space requested. |
| 535 | */ | 537 | */ |
| @@ -622,7 +624,11 @@ xfs_dir2_grow_inode( | |||
| 622 | */ | 624 | */ |
| 623 | if (mapp != &map) | 625 | if (mapp != &map) |
| 624 | kmem_free(mapp); | 626 | kmem_free(mapp); |
| 627 | |||
| 628 | /* account for newly allocated blocks in reserved blocks total */ | ||
| 629 | args->total -= dp->i_d.di_nblocks - nblks; | ||
| 625 | *dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno); | 630 | *dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno); |
| 631 | |||
| 626 | /* | 632 | /* |
| 627 | * Update file's size if this is the data space and it grew. | 633 | * Update file's size if this is the data space and it grew. |
| 628 | */ | 634 | */ |
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index dbd9cef852ec..a391b955df01 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
| @@ -1414,7 +1414,7 @@ xfs_itruncate_start( | |||
| 1414 | mp = ip->i_mount; | 1414 | mp = ip->i_mount; |
| 1415 | 1415 | ||
| 1416 | /* wait for the completion of any pending DIOs */ | 1416 | /* wait for the completion of any pending DIOs */ |
| 1417 | if (new_size < ip->i_size) | 1417 | if (new_size == 0 || new_size < ip->i_size) |
| 1418 | vn_iowait(ip); | 1418 | vn_iowait(ip); |
| 1419 | 1419 | ||
| 1420 | /* | 1420 | /* |
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 0b02c6443551..3608a0f0a5f6 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
| @@ -563,6 +563,11 @@ xfs_log_mount( | |||
| 563 | } | 563 | } |
| 564 | 564 | ||
| 565 | mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks); | 565 | mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks); |
| 566 | if (!mp->m_log) { | ||
| 567 | cmn_err(CE_WARN, "XFS: Log allocation failed: No memory!"); | ||
| 568 | error = ENOMEM; | ||
| 569 | goto out; | ||
| 570 | } | ||
| 566 | 571 | ||
| 567 | /* | 572 | /* |
| 568 | * Initialize the AIL now we have a log. | 573 | * Initialize the AIL now we have a log. |
| @@ -601,6 +606,7 @@ xfs_log_mount( | |||
| 601 | return 0; | 606 | return 0; |
| 602 | error: | 607 | error: |
| 603 | xfs_log_unmount_dealloc(mp); | 608 | xfs_log_unmount_dealloc(mp); |
| 609 | out: | ||
| 604 | return error; | 610 | return error; |
| 605 | } /* xfs_log_mount */ | 611 | } /* xfs_log_mount */ |
| 606 | 612 | ||
| @@ -1217,7 +1223,9 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
| 1217 | int i; | 1223 | int i; |
| 1218 | int iclogsize; | 1224 | int iclogsize; |
| 1219 | 1225 | ||
| 1220 | log = (xlog_t *)kmem_zalloc(sizeof(xlog_t), KM_SLEEP); | 1226 | log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL); |
| 1227 | if (!log) | ||
| 1228 | return NULL; | ||
| 1221 | 1229 | ||
| 1222 | log->l_mp = mp; | 1230 | log->l_mp = mp; |
| 1223 | log->l_targ = log_target; | 1231 | log->l_targ = log_target; |
| @@ -1249,6 +1257,8 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
| 1249 | xlog_get_iclog_buffer_size(mp, log); | 1257 | xlog_get_iclog_buffer_size(mp, log); |
| 1250 | 1258 | ||
| 1251 | bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp); | 1259 | bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp); |
| 1260 | if (!bp) | ||
| 1261 | goto out_free_log; | ||
| 1252 | XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone); | 1262 | XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone); |
| 1253 | XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb); | 1263 | XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb); |
| 1254 | XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1); | 1264 | XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1); |
| @@ -1275,13 +1285,17 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
| 1275 | iclogsize = log->l_iclog_size; | 1285 | iclogsize = log->l_iclog_size; |
| 1276 | ASSERT(log->l_iclog_size >= 4096); | 1286 | ASSERT(log->l_iclog_size >= 4096); |
| 1277 | for (i=0; i < log->l_iclog_bufs; i++) { | 1287 | for (i=0; i < log->l_iclog_bufs; i++) { |
| 1278 | *iclogp = (xlog_in_core_t *) | 1288 | *iclogp = kmem_zalloc(sizeof(xlog_in_core_t), KM_MAYFAIL); |
| 1279 | kmem_zalloc(sizeof(xlog_in_core_t), KM_SLEEP); | 1289 | if (!*iclogp) |
| 1290 | goto out_free_iclog; | ||
| 1291 | |||
| 1280 | iclog = *iclogp; | 1292 | iclog = *iclogp; |
| 1281 | iclog->ic_prev = prev_iclog; | 1293 | iclog->ic_prev = prev_iclog; |
| 1282 | prev_iclog = iclog; | 1294 | prev_iclog = iclog; |
| 1283 | 1295 | ||
| 1284 | bp = xfs_buf_get_noaddr(log->l_iclog_size, mp->m_logdev_targp); | 1296 | bp = xfs_buf_get_noaddr(log->l_iclog_size, mp->m_logdev_targp); |
| 1297 | if (!bp) | ||
| 1298 | goto out_free_iclog; | ||
| 1285 | if (!XFS_BUF_CPSEMA(bp)) | 1299 | if (!XFS_BUF_CPSEMA(bp)) |
| 1286 | ASSERT(0); | 1300 | ASSERT(0); |
| 1287 | XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone); | 1301 | XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone); |
| @@ -1323,6 +1337,25 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
| 1323 | log->l_iclog->ic_prev = prev_iclog; /* re-write 1st prev ptr */ | 1337 | log->l_iclog->ic_prev = prev_iclog; /* re-write 1st prev ptr */ |
| 1324 | 1338 | ||
| 1325 | return log; | 1339 | return log; |
| 1340 | |||
| 1341 | out_free_iclog: | ||
| 1342 | for (iclog = log->l_iclog; iclog; iclog = prev_iclog) { | ||
| 1343 | prev_iclog = iclog->ic_next; | ||
| 1344 | if (iclog->ic_bp) { | ||
| 1345 | sv_destroy(&iclog->ic_force_wait); | ||
| 1346 | sv_destroy(&iclog->ic_write_wait); | ||
| 1347 | xfs_buf_free(iclog->ic_bp); | ||
| 1348 | xlog_trace_iclog_dealloc(iclog); | ||
| 1349 | } | ||
| 1350 | kmem_free(iclog); | ||
| 1351 | } | ||
| 1352 | spinlock_destroy(&log->l_icloglock); | ||
| 1353 | spinlock_destroy(&log->l_grant_lock); | ||
| 1354 | xlog_trace_loggrant_dealloc(log); | ||
| 1355 | xfs_buf_free(log->l_xbuf); | ||
| 1356 | out_free_log: | ||
| 1357 | kmem_free(log); | ||
| 1358 | return NULL; | ||
| 1326 | } /* xlog_alloc_log */ | 1359 | } /* xlog_alloc_log */ |
| 1327 | 1360 | ||
| 1328 | 1361 | ||
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 82d46ce69d5f..70e3ba32e6be 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
| @@ -1419,7 +1419,13 @@ xlog_recover_add_to_trans( | |||
| 1419 | return 0; | 1419 | return 0; |
| 1420 | item = trans->r_itemq; | 1420 | item = trans->r_itemq; |
| 1421 | if (item == NULL) { | 1421 | if (item == NULL) { |
| 1422 | ASSERT(*(uint *)dp == XFS_TRANS_HEADER_MAGIC); | 1422 | /* we need to catch log corruptions here */ |
| 1423 | if (*(uint *)dp != XFS_TRANS_HEADER_MAGIC) { | ||
| 1424 | xlog_warn("XFS: xlog_recover_add_to_trans: " | ||
| 1425 | "bad header magic number"); | ||
| 1426 | ASSERT(0); | ||
| 1427 | return XFS_ERROR(EIO); | ||
| 1428 | } | ||
| 1423 | if (len == sizeof(xfs_trans_header_t)) | 1429 | if (len == sizeof(xfs_trans_header_t)) |
| 1424 | xlog_recover_add_item(&trans->r_itemq); | 1430 | xlog_recover_add_item(&trans->r_itemq); |
| 1425 | memcpy(&trans->r_theader, dp, len); /* d, s, l */ | 1431 | memcpy(&trans->r_theader, dp, len); /* d, s, l */ |
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index a4503f5e9497..15f5dd22fbb2 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
| @@ -1245,6 +1245,9 @@ xfs_unmountfs( | |||
| 1245 | 1245 | ||
| 1246 | XFS_QM_DQPURGEALL(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_UMOUNTING); | 1246 | XFS_QM_DQPURGEALL(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_UMOUNTING); |
| 1247 | 1247 | ||
| 1248 | if (mp->m_quotainfo) | ||
| 1249 | XFS_QM_DONE(mp); | ||
| 1250 | |||
| 1248 | /* | 1251 | /* |
| 1249 | * Flush out the log synchronously so that we know for sure | 1252 | * Flush out the log synchronously so that we know for sure |
| 1250 | * that nothing is pinned. This is important because bflush() | 1253 | * that nothing is pinned. This is important because bflush() |
| @@ -1297,8 +1300,6 @@ xfs_unmountfs( | |||
| 1297 | xfs_errortag_clearall(mp, 0); | 1300 | xfs_errortag_clearall(mp, 0); |
| 1298 | #endif | 1301 | #endif |
| 1299 | xfs_free_perag(mp); | 1302 | xfs_free_perag(mp); |
| 1300 | if (mp->m_quotainfo) | ||
| 1301 | XFS_QM_DONE(mp); | ||
| 1302 | } | 1303 | } |
| 1303 | 1304 | ||
| 1304 | STATIC void | 1305 | STATIC void |
