diff options
author | David S. Miller <davem@davemloft.net> | 2008-11-11 18:43:02 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-11-11 18:43:02 -0500 |
commit | 7e452baf6b96b5aeba097afd91501d33d390cc97 (patch) | |
tree | 9b0e062d3677d50d731ffd0fba47423bfdee9253 /fs | |
parent | 3ac38c3a2e7dac3f8f35a56eb85c27881a4c3833 (diff) | |
parent | f21f237cf55494c3a4209de323281a3b0528da10 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts:
drivers/message/fusion/mptlan.c
drivers/net/sfc/ethtool.c
net/mac80211/debugfs_sta.c
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/ialloc.c | 2 | ||||
-rw-r--r-- | fs/ext4/inode.c | 7 | ||||
-rw-r--r-- | fs/ext4/mballoc.c | 1 | ||||
-rw-r--r-- | fs/ext4/super.c | 24 | ||||
-rw-r--r-- | fs/jbd/checkpoint.c | 31 | ||||
-rw-r--r-- | fs/jbd2/checkpoint.c | 32 | ||||
-rw-r--r-- | fs/jbd2/journal.c | 2 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 5 | ||||
-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 |
23 files changed, 384 insertions, 263 deletions
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index fe34d74cfb19..2a117e286e54 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
@@ -718,6 +718,8 @@ got: | |||
718 | gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); | 718 | gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); |
719 | free = ext4_free_blocks_after_init(sb, group, gdp); | 719 | free = ext4_free_blocks_after_init(sb, group, gdp); |
720 | gdp->bg_free_blocks_count = cpu_to_le16(free); | 720 | gdp->bg_free_blocks_count = cpu_to_le16(free); |
721 | gdp->bg_checksum = ext4_group_desc_csum(sbi, group, | ||
722 | gdp); | ||
721 | } | 723 | } |
722 | spin_unlock(sb_bgl_lock(sbi, group)); | 724 | spin_unlock(sb_bgl_lock(sbi, group)); |
723 | 725 | ||
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 8dbf6953845b..be21a5ae33cb 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -2329,6 +2329,8 @@ static int ext4_da_writepage(struct page *page, | |||
2329 | unlock_page(page); | 2329 | unlock_page(page); |
2330 | return 0; | 2330 | return 0; |
2331 | } | 2331 | } |
2332 | /* now mark the buffer_heads as dirty and uptodate */ | ||
2333 | block_commit_write(page, 0, PAGE_CACHE_SIZE); | ||
2332 | } | 2334 | } |
2333 | 2335 | ||
2334 | if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode)) | 2336 | if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode)) |
@@ -4580,9 +4582,10 @@ static int ext4_indirect_trans_blocks(struct inode *inode, int nrblocks, | |||
4580 | static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk) | 4582 | static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk) |
4581 | { | 4583 | { |
4582 | if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) | 4584 | if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) |
4583 | return ext4_indirect_trans_blocks(inode, nrblocks, 0); | 4585 | return ext4_indirect_trans_blocks(inode, nrblocks, chunk); |
4584 | return ext4_ext_index_trans_blocks(inode, nrblocks, 0); | 4586 | return ext4_ext_index_trans_blocks(inode, nrblocks, chunk); |
4585 | } | 4587 | } |
4588 | |||
4586 | /* | 4589 | /* |
4587 | * Account for index blocks, block groups bitmaps and block group | 4590 | * Account for index blocks, block groups bitmaps and block group |
4588 | * descriptor blocks if modify datablocks and index blocks | 4591 | * descriptor blocks if modify datablocks and index blocks |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index dfe17a134052..444ad998f72e 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -4441,6 +4441,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b, | |||
4441 | else if (block >= (entry->start_blk + entry->count)) | 4441 | else if (block >= (entry->start_blk + entry->count)) |
4442 | n = &(*n)->rb_right; | 4442 | n = &(*n)->rb_right; |
4443 | else { | 4443 | else { |
4444 | ext4_unlock_group(sb, group); | ||
4444 | ext4_error(sb, __func__, | 4445 | ext4_error(sb, __func__, |
4445 | "Double free of blocks %d (%d %d)\n", | 4446 | "Double free of blocks %d (%d %d)\n", |
4446 | block, entry->start_blk, entry->count); | 4447 | block, entry->start_blk, entry->count); |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 994859df010e..e4a241c65dbe 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -1458,9 +1458,8 @@ static int ext4_fill_flex_info(struct super_block *sb) | |||
1458 | 1458 | ||
1459 | /* We allocate both existing and potentially added groups */ | 1459 | /* We allocate both existing and potentially added groups */ |
1460 | flex_group_count = ((sbi->s_groups_count + groups_per_flex - 1) + | 1460 | flex_group_count = ((sbi->s_groups_count + groups_per_flex - 1) + |
1461 | ((sbi->s_es->s_reserved_gdt_blocks +1 ) << | 1461 | ((le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) + 1) << |
1462 | EXT4_DESC_PER_BLOCK_BITS(sb))) / | 1462 | EXT4_DESC_PER_BLOCK_BITS(sb))) / groups_per_flex; |
1463 | groups_per_flex; | ||
1464 | sbi->s_flex_groups = kzalloc(flex_group_count * | 1463 | sbi->s_flex_groups = kzalloc(flex_group_count * |
1465 | sizeof(struct flex_groups), GFP_KERNEL); | 1464 | sizeof(struct flex_groups), GFP_KERNEL); |
1466 | if (sbi->s_flex_groups == NULL) { | 1465 | if (sbi->s_flex_groups == NULL) { |
@@ -2885,12 +2884,9 @@ int ext4_force_commit(struct super_block *sb) | |||
2885 | /* | 2884 | /* |
2886 | * Ext4 always journals updates to the superblock itself, so we don't | 2885 | * Ext4 always journals updates to the superblock itself, so we don't |
2887 | * have to propagate any other updates to the superblock on disk at this | 2886 | * have to propagate any other updates to the superblock on disk at this |
2888 | * point. Just start an async writeback to get the buffers on their way | 2887 | * point. (We can probably nuke this function altogether, and remove |
2889 | * to the disk. | 2888 | * any mention to sb->s_dirt in all of fs/ext4; eventual cleanup...) |
2890 | * | ||
2891 | * This implicitly triggers the writebehind on sync(). | ||
2892 | */ | 2889 | */ |
2893 | |||
2894 | static void ext4_write_super(struct super_block *sb) | 2890 | static void ext4_write_super(struct super_block *sb) |
2895 | { | 2891 | { |
2896 | if (mutex_trylock(&sb->s_lock) != 0) | 2892 | if (mutex_trylock(&sb->s_lock) != 0) |
@@ -2900,15 +2896,15 @@ static void ext4_write_super(struct super_block *sb) | |||
2900 | 2896 | ||
2901 | static int ext4_sync_fs(struct super_block *sb, int wait) | 2897 | static int ext4_sync_fs(struct super_block *sb, int wait) |
2902 | { | 2898 | { |
2903 | tid_t target; | 2899 | int ret = 0; |
2904 | 2900 | ||
2905 | trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait); | 2901 | trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait); |
2906 | sb->s_dirt = 0; | 2902 | sb->s_dirt = 0; |
2907 | if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) { | 2903 | if (wait) |
2908 | if (wait) | 2904 | ret = ext4_force_commit(sb); |
2909 | jbd2_log_wait_commit(EXT4_SB(sb)->s_journal, target); | 2905 | else |
2910 | } | 2906 | jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, NULL); |
2911 | return 0; | 2907 | return ret; |
2912 | } | 2908 | } |
2913 | 2909 | ||
2914 | /* | 2910 | /* |
diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c index 1bd8d4acc6f2..61f32f3868cd 100644 --- a/fs/jbd/checkpoint.c +++ b/fs/jbd/checkpoint.c | |||
@@ -115,7 +115,7 @@ static int __try_to_free_cp_buf(struct journal_head *jh) | |||
115 | */ | 115 | */ |
116 | void __log_wait_for_space(journal_t *journal) | 116 | void __log_wait_for_space(journal_t *journal) |
117 | { | 117 | { |
118 | int nblocks; | 118 | int nblocks, space_left; |
119 | assert_spin_locked(&journal->j_state_lock); | 119 | assert_spin_locked(&journal->j_state_lock); |
120 | 120 | ||
121 | nblocks = jbd_space_needed(journal); | 121 | nblocks = jbd_space_needed(journal); |
@@ -128,25 +128,42 @@ void __log_wait_for_space(journal_t *journal) | |||
128 | /* | 128 | /* |
129 | * Test again, another process may have checkpointed while we | 129 | * Test again, another process may have checkpointed while we |
130 | * were waiting for the checkpoint lock. If there are no | 130 | * were waiting for the checkpoint lock. If there are no |
131 | * outstanding transactions there is nothing to checkpoint and | 131 | * transactions ready to be checkpointed, try to recover |
132 | * we can't make progress. Abort the journal in this case. | 132 | * journal space by calling cleanup_journal_tail(), and if |
133 | * that doesn't work, by waiting for the currently committing | ||
134 | * transaction to complete. If there is absolutely no way | ||
135 | * to make progress, this is either a BUG or corrupted | ||
136 | * filesystem, so abort the journal and leave a stack | ||
137 | * trace for forensic evidence. | ||
133 | */ | 138 | */ |
134 | spin_lock(&journal->j_state_lock); | 139 | spin_lock(&journal->j_state_lock); |
135 | spin_lock(&journal->j_list_lock); | 140 | spin_lock(&journal->j_list_lock); |
136 | nblocks = jbd_space_needed(journal); | 141 | nblocks = jbd_space_needed(journal); |
137 | if (__log_space_left(journal) < nblocks) { | 142 | space_left = __log_space_left(journal); |
143 | if (space_left < nblocks) { | ||
138 | int chkpt = journal->j_checkpoint_transactions != NULL; | 144 | int chkpt = journal->j_checkpoint_transactions != NULL; |
145 | tid_t tid = 0; | ||
139 | 146 | ||
147 | if (journal->j_committing_transaction) | ||
148 | tid = journal->j_committing_transaction->t_tid; | ||
140 | spin_unlock(&journal->j_list_lock); | 149 | spin_unlock(&journal->j_list_lock); |
141 | spin_unlock(&journal->j_state_lock); | 150 | spin_unlock(&journal->j_state_lock); |
142 | if (chkpt) { | 151 | if (chkpt) { |
143 | log_do_checkpoint(journal); | 152 | log_do_checkpoint(journal); |
153 | } else if (cleanup_journal_tail(journal) == 0) { | ||
154 | /* We were able to recover space; yay! */ | ||
155 | ; | ||
156 | } else if (tid) { | ||
157 | log_wait_commit(journal, tid); | ||
144 | } else { | 158 | } else { |
145 | printk(KERN_ERR "%s: no transactions\n", | 159 | printk(KERN_ERR "%s: needed %d blocks and " |
146 | __func__); | 160 | "only had %d space available\n", |
161 | __func__, nblocks, space_left); | ||
162 | printk(KERN_ERR "%s: no way to get more " | ||
163 | "journal space\n", __func__); | ||
164 | WARN_ON(1); | ||
147 | journal_abort(journal, 0); | 165 | journal_abort(journal, 0); |
148 | } | 166 | } |
149 | |||
150 | spin_lock(&journal->j_state_lock); | 167 | spin_lock(&journal->j_state_lock); |
151 | } else { | 168 | } else { |
152 | spin_unlock(&journal->j_list_lock); | 169 | spin_unlock(&journal->j_list_lock); |
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 9203c3332f17..9497718fe920 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c | |||
@@ -116,7 +116,7 @@ static int __try_to_free_cp_buf(struct journal_head *jh) | |||
116 | */ | 116 | */ |
117 | void __jbd2_log_wait_for_space(journal_t *journal) | 117 | void __jbd2_log_wait_for_space(journal_t *journal) |
118 | { | 118 | { |
119 | int nblocks; | 119 | int nblocks, space_left; |
120 | assert_spin_locked(&journal->j_state_lock); | 120 | assert_spin_locked(&journal->j_state_lock); |
121 | 121 | ||
122 | nblocks = jbd_space_needed(journal); | 122 | nblocks = jbd_space_needed(journal); |
@@ -129,25 +129,43 @@ void __jbd2_log_wait_for_space(journal_t *journal) | |||
129 | /* | 129 | /* |
130 | * Test again, another process may have checkpointed while we | 130 | * Test again, another process may have checkpointed while we |
131 | * were waiting for the checkpoint lock. If there are no | 131 | * were waiting for the checkpoint lock. If there are no |
132 | * outstanding transactions there is nothing to checkpoint and | 132 | * transactions ready to be checkpointed, try to recover |
133 | * we can't make progress. Abort the journal in this case. | 133 | * journal space by calling cleanup_journal_tail(), and if |
134 | * that doesn't work, by waiting for the currently committing | ||
135 | * transaction to complete. If there is absolutely no way | ||
136 | * to make progress, this is either a BUG or corrupted | ||
137 | * filesystem, so abort the journal and leave a stack | ||
138 | * trace for forensic evidence. | ||
134 | */ | 139 | */ |
135 | spin_lock(&journal->j_state_lock); | 140 | spin_lock(&journal->j_state_lock); |
136 | spin_lock(&journal->j_list_lock); | 141 | spin_lock(&journal->j_list_lock); |
137 | nblocks = jbd_space_needed(journal); | 142 | nblocks = jbd_space_needed(journal); |
138 | if (__jbd2_log_space_left(journal) < nblocks) { | 143 | space_left = __jbd2_log_space_left(journal); |
144 | if (space_left < nblocks) { | ||
139 | int chkpt = journal->j_checkpoint_transactions != NULL; | 145 | int chkpt = journal->j_checkpoint_transactions != NULL; |
146 | tid_t tid = 0; | ||
140 | 147 | ||
148 | if (journal->j_committing_transaction) | ||
149 | tid = journal->j_committing_transaction->t_tid; | ||
141 | spin_unlock(&journal->j_list_lock); | 150 | spin_unlock(&journal->j_list_lock); |
142 | spin_unlock(&journal->j_state_lock); | 151 | spin_unlock(&journal->j_state_lock); |
143 | if (chkpt) { | 152 | if (chkpt) { |
144 | jbd2_log_do_checkpoint(journal); | 153 | jbd2_log_do_checkpoint(journal); |
154 | } else if (jbd2_cleanup_journal_tail(journal) == 0) { | ||
155 | /* We were able to recover space; yay! */ | ||
156 | ; | ||
157 | } else if (tid) { | ||
158 | jbd2_log_wait_commit(journal, tid); | ||
145 | } else { | 159 | } else { |
146 | printk(KERN_ERR "%s: no transactions\n", | 160 | printk(KERN_ERR "%s: needed %d blocks and " |
147 | __func__); | 161 | "only had %d space available\n", |
162 | __func__, nblocks, space_left); | ||
163 | printk(KERN_ERR "%s: no way to get more " | ||
164 | "journal space in %s\n", __func__, | ||
165 | journal->j_devname); | ||
166 | WARN_ON(1); | ||
148 | jbd2_journal_abort(journal, 0); | 167 | jbd2_journal_abort(journal, 0); |
149 | } | 168 | } |
150 | |||
151 | spin_lock(&journal->j_state_lock); | 169 | spin_lock(&journal->j_state_lock); |
152 | } else { | 170 | } else { |
153 | spin_unlock(&journal->j_list_lock); | 171 | spin_unlock(&journal->j_list_lock); |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 783de118de92..e70d657a19f8 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
@@ -1089,6 +1089,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode) | |||
1089 | if (!journal->j_wbuf) { | 1089 | if (!journal->j_wbuf) { |
1090 | printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", | 1090 | printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", |
1091 | __func__); | 1091 | __func__); |
1092 | jbd2_stats_proc_exit(journal); | ||
1092 | kfree(journal); | 1093 | kfree(journal); |
1093 | return NULL; | 1094 | return NULL; |
1094 | } | 1095 | } |
@@ -1098,6 +1099,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode) | |||
1098 | if (err) { | 1099 | if (err) { |
1099 | printk(KERN_ERR "%s: Cannnot locate journal superblock\n", | 1100 | printk(KERN_ERR "%s: Cannnot locate journal superblock\n", |
1100 | __func__); | 1101 | __func__); |
1102 | jbd2_stats_proc_exit(journal); | ||
1101 | kfree(journal); | 1103 | kfree(journal); |
1102 | return NULL; | 1104 | return NULL; |
1103 | } | 1105 | } |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 848a03e83a42..4433c8f00163 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -1875,11 +1875,11 @@ static int nfsd_buffered_readdir(struct file *file, filldir_t func, | |||
1875 | return -ENOMEM; | 1875 | return -ENOMEM; |
1876 | 1876 | ||
1877 | offset = *offsetp; | 1877 | offset = *offsetp; |
1878 | cdp->err = nfserr_eof; /* will be cleared on successful read */ | ||
1879 | 1878 | ||
1880 | while (1) { | 1879 | while (1) { |
1881 | unsigned int reclen; | 1880 | unsigned int reclen; |
1882 | 1881 | ||
1882 | cdp->err = nfserr_eof; /* will be cleared on successful read */ | ||
1883 | buf.used = 0; | 1883 | buf.used = 0; |
1884 | buf.full = 0; | 1884 | buf.full = 0; |
1885 | 1885 | ||
@@ -1912,9 +1912,6 @@ static int nfsd_buffered_readdir(struct file *file, filldir_t func, | |||
1912 | de = (struct buffered_dirent *)((char *)de + reclen); | 1912 | de = (struct buffered_dirent *)((char *)de + reclen); |
1913 | } | 1913 | } |
1914 | offset = vfs_llseek(file, 0, SEEK_CUR); | 1914 | offset = vfs_llseek(file, 0, SEEK_CUR); |
1915 | cdp->err = nfserr_eof; | ||
1916 | if (!buf.full) | ||
1917 | break; | ||
1918 | } | 1915 | } |
1919 | 1916 | ||
1920 | done: | 1917 | done: |
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 |