aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/inode.c66
-rw-r--r--fs/ext4/xattr.c258
-rw-r--r--fs/ext4/xattr.h3
3 files changed, 184 insertions, 143 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 3e9415e2e74d..46def73d3472 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -239,7 +239,11 @@ void ext4_evict_inode(struct inode *inode)
239 */ 239 */
240 sb_start_intwrite(inode->i_sb); 240 sb_start_intwrite(inode->i_sb);
241 241
242 handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, extra_credits); 242 if (!IS_NOQUOTA(inode))
243 extra_credits += EXT4_MAXQUOTAS_DEL_BLOCKS(inode->i_sb);
244
245 handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE,
246 ext4_blocks_for_truncate(inode)+extra_credits);
243 if (IS_ERR(handle)) { 247 if (IS_ERR(handle)) {
244 ext4_std_error(inode->i_sb, PTR_ERR(handle)); 248 ext4_std_error(inode->i_sb, PTR_ERR(handle));
245 /* 249 /*
@@ -251,36 +255,9 @@ void ext4_evict_inode(struct inode *inode)
251 sb_end_intwrite(inode->i_sb); 255 sb_end_intwrite(inode->i_sb);
252 goto no_delete; 256 goto no_delete;
253 } 257 }
258
254 if (IS_SYNC(inode)) 259 if (IS_SYNC(inode))
255 ext4_handle_sync(handle); 260 ext4_handle_sync(handle);
256
257 /*
258 * Delete xattr inode before deleting the main inode.
259 */
260 err = ext4_xattr_delete_inode(handle, inode, &ea_inode_array);
261 if (err) {
262 ext4_warning(inode->i_sb,
263 "couldn't delete inode's xattr (err %d)", err);
264 goto stop_handle;
265 }
266
267 if (!IS_NOQUOTA(inode))
268 extra_credits += 2 * EXT4_QUOTA_DEL_BLOCKS(inode->i_sb);
269
270 if (!ext4_handle_has_enough_credits(handle,
271 ext4_blocks_for_truncate(inode) + extra_credits)) {
272 err = ext4_journal_extend(handle,
273 ext4_blocks_for_truncate(inode) + extra_credits);
274 if (err > 0)
275 err = ext4_journal_restart(handle,
276 ext4_blocks_for_truncate(inode) + extra_credits);
277 if (err != 0) {
278 ext4_warning(inode->i_sb,
279 "couldn't extend journal (err %d)", err);
280 goto stop_handle;
281 }
282 }
283
284 inode->i_size = 0; 261 inode->i_size = 0;
285 err = ext4_mark_inode_dirty(handle, inode); 262 err = ext4_mark_inode_dirty(handle, inode);
286 if (err) { 263 if (err) {
@@ -298,25 +275,17 @@ void ext4_evict_inode(struct inode *inode)
298 } 275 }
299 } 276 }
300 277
301 /* 278 /* Remove xattr references. */
302 * ext4_ext_truncate() doesn't reserve any slop when it 279 err = ext4_xattr_delete_inode(handle, inode, &ea_inode_array,
303 * restarts journal transactions; therefore there may not be 280 extra_credits);
304 * enough credits left in the handle to remove the inode from 281 if (err) {
305 * the orphan list and set the dtime field. 282 ext4_warning(inode->i_sb, "xattr delete (err %d)", err);
306 */ 283stop_handle:
307 if (!ext4_handle_has_enough_credits(handle, extra_credits)) { 284 ext4_journal_stop(handle);
308 err = ext4_journal_extend(handle, extra_credits); 285 ext4_orphan_del(NULL, inode);
309 if (err > 0) 286 sb_end_intwrite(inode->i_sb);
310 err = ext4_journal_restart(handle, extra_credits); 287 ext4_xattr_inode_array_free(ea_inode_array);
311 if (err != 0) { 288 goto no_delete;
312 ext4_warning(inode->i_sb,
313 "couldn't extend journal (err %d)", err);
314 stop_handle:
315 ext4_journal_stop(handle);
316 ext4_orphan_del(NULL, inode);
317 sb_end_intwrite(inode->i_sb);
318 goto no_delete;
319 }
320 } 289 }
321 290
322 /* 291 /*
@@ -342,7 +311,6 @@ void ext4_evict_inode(struct inode *inode)
342 ext4_clear_inode(inode); 311 ext4_clear_inode(inode);
343 else 312 else
344 ext4_free_inode(handle, inode); 313 ext4_free_inode(handle, inode);
345
346 ext4_journal_stop(handle); 314 ext4_journal_stop(handle);
347 sb_end_intwrite(inode->i_sb); 315 sb_end_intwrite(inode->i_sb);
348 ext4_xattr_inode_array_free(ea_inode_array); 316 ext4_xattr_inode_array_free(ea_inode_array);
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 53980ee164ed..649dc2953901 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -108,6 +108,10 @@ const struct xattr_handler *ext4_xattr_handlers[] = {
108#define EA_BLOCK_CACHE(inode) (((struct ext4_sb_info *) \ 108#define EA_BLOCK_CACHE(inode) (((struct ext4_sb_info *) \
109 inode->i_sb->s_fs_info)->s_ea_block_cache) 109 inode->i_sb->s_fs_info)->s_ea_block_cache)
110 110
111static int
112ext4_expand_inode_array(struct ext4_xattr_inode_array **ea_inode_array,
113 struct inode *inode);
114
111#ifdef CONFIG_LOCKDEP 115#ifdef CONFIG_LOCKDEP
112void ext4_xattr_inode_set_class(struct inode *ea_inode) 116void ext4_xattr_inode_set_class(struct inode *ea_inode)
113{ 117{
@@ -652,6 +656,128 @@ static void ext4_xattr_update_super_block(handle_t *handle,
652 } 656 }
653} 657}
654 658
659static int ext4_xattr_ensure_credits(handle_t *handle, struct inode *inode,
660 int credits, struct buffer_head *bh,
661 bool dirty, bool block_csum)
662{
663 int error;
664
665 if (!ext4_handle_valid(handle))
666 return 0;
667
668 if (handle->h_buffer_credits >= credits)
669 return 0;
670
671 error = ext4_journal_extend(handle, credits - handle->h_buffer_credits);
672 if (!error)
673 return 0;
674 if (error < 0) {
675 ext4_warning(inode->i_sb, "Extend journal (error %d)", error);
676 return error;
677 }
678
679 if (bh && dirty) {
680 if (block_csum)
681 ext4_xattr_block_csum_set(inode, bh);
682 error = ext4_handle_dirty_metadata(handle, NULL, bh);
683 if (error) {
684 ext4_warning(inode->i_sb, "Handle metadata (error %d)",
685 error);
686 return error;
687 }
688 }
689
690 error = ext4_journal_restart(handle, credits);
691 if (error) {
692 ext4_warning(inode->i_sb, "Restart journal (error %d)", error);
693 return error;
694 }
695
696 if (bh) {
697 error = ext4_journal_get_write_access(handle, bh);
698 if (error) {
699 ext4_warning(inode->i_sb,
700 "Get write access failed (error %d)",
701 error);
702 return error;
703 }
704 }
705 return 0;
706}
707
708static void
709ext4_xattr_inode_remove_all(handle_t *handle, struct inode *parent,
710 struct buffer_head *bh,
711 struct ext4_xattr_entry *first, bool block_csum,
712 struct ext4_xattr_inode_array **ea_inode_array,
713 int extra_credits)
714{
715 struct inode *ea_inode;
716 struct ext4_xattr_entry *entry;
717 bool dirty = false;
718 unsigned int ea_ino;
719 int err;
720 int credits;
721
722 /* One credit for dec ref on ea_inode, one for orphan list addition, */
723 credits = 2 + extra_credits;
724
725 for (entry = first; !IS_LAST_ENTRY(entry);
726 entry = EXT4_XATTR_NEXT(entry)) {
727 if (!entry->e_value_inum)
728 continue;
729 ea_ino = le32_to_cpu(entry->e_value_inum);
730 err = ext4_xattr_inode_iget(parent, ea_ino, &ea_inode);
731 if (err)
732 continue;
733
734 err = ext4_expand_inode_array(ea_inode_array, ea_inode);
735 if (err) {
736 ext4_warning_inode(ea_inode,
737 "Expand inode array err=%d", err);
738 iput(ea_inode);
739 continue;
740 }
741
742 err = ext4_xattr_ensure_credits(handle, parent, credits, bh,
743 dirty, block_csum);
744 if (err) {
745 ext4_warning_inode(ea_inode, "Ensure credits err=%d",
746 err);
747 continue;
748 }
749
750 inode_lock(ea_inode);
751 clear_nlink(ea_inode);
752 ext4_orphan_add(handle, ea_inode);
753 inode_unlock(ea_inode);
754
755 /*
756 * Forget about ea_inode within the same transaction that
757 * decrements the ref count. This avoids duplicate decrements in
758 * case the rest of the work spills over to subsequent
759 * transactions.
760 */
761 entry->e_value_inum = 0;
762 entry->e_value_size = 0;
763
764 dirty = true;
765 }
766
767 if (dirty) {
768 /*
769 * Note that we are deliberately skipping csum calculation for
770 * the final update because we do not expect any journal
771 * restarts until xattr block is freed.
772 */
773
774 err = ext4_handle_dirty_metadata(handle, NULL, bh);
775 if (err)
776 ext4_warning_inode(parent,
777 "handle dirty metadata err=%d", err);
778 }
779}
780
655/* 781/*
656 * Release the xattr block BH: If the reference count is > 1, decrement it; 782 * Release the xattr block BH: If the reference count is > 1, decrement it;
657 * otherwise free the block. 783 * otherwise free the block.
@@ -1982,42 +2108,6 @@ ext4_expand_inode_array(struct ext4_xattr_inode_array **ea_inode_array,
1982 return 0; 2108 return 0;
1983} 2109}
1984 2110
1985/**
1986 * Add xattr inode to orphan list
1987 */
1988static int
1989ext4_xattr_inode_orphan_add(handle_t *handle, struct inode *inode, int credits,
1990 struct ext4_xattr_inode_array *ea_inode_array)
1991{
1992 int idx = 0, error = 0;
1993 struct inode *ea_inode;
1994
1995 if (ea_inode_array == NULL)
1996 return 0;
1997
1998 for (; idx < ea_inode_array->count; ++idx) {
1999 if (!ext4_handle_has_enough_credits(handle, credits)) {
2000 error = ext4_journal_extend(handle, credits);
2001 if (error > 0)
2002 error = ext4_journal_restart(handle, credits);
2003
2004 if (error != 0) {
2005 ext4_warning(inode->i_sb,
2006 "couldn't extend journal "
2007 "(err %d)", error);
2008 return error;
2009 }
2010 }
2011 ea_inode = ea_inode_array->inodes[idx];
2012 inode_lock(ea_inode);
2013 ext4_orphan_add(handle, ea_inode);
2014 inode_unlock(ea_inode);
2015 /* the inode's i_count will be released by caller */
2016 }
2017
2018 return 0;
2019}
2020
2021/* 2111/*
2022 * ext4_xattr_delete_inode() 2112 * ext4_xattr_delete_inode()
2023 * 2113 *
@@ -2030,16 +2120,23 @@ ext4_xattr_inode_orphan_add(handle_t *handle, struct inode *inode, int credits,
2030 */ 2120 */
2031int 2121int
2032ext4_xattr_delete_inode(handle_t *handle, struct inode *inode, 2122ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
2033 struct ext4_xattr_inode_array **ea_inode_array) 2123 struct ext4_xattr_inode_array **ea_inode_array,
2124 int extra_credits)
2034{ 2125{
2035 struct buffer_head *bh = NULL; 2126 struct buffer_head *bh = NULL;
2036 struct ext4_xattr_ibody_header *header; 2127 struct ext4_xattr_ibody_header *header;
2037 struct ext4_inode *raw_inode; 2128 struct ext4_inode *raw_inode;
2038 struct ext4_iloc iloc; 2129 struct ext4_iloc iloc = { .bh = NULL };
2039 struct ext4_xattr_entry *entry; 2130 int error;
2040 struct inode *ea_inode; 2131
2041 unsigned int ea_ino; 2132 error = ext4_xattr_ensure_credits(handle, inode, extra_credits,
2042 int credits = 3, error = 0; 2133 NULL /* bh */,
2134 false /* dirty */,
2135 false /* block_csum */);
2136 if (error) {
2137 EXT4_ERROR_INODE(inode, "ensure credits (error %d)", error);
2138 goto cleanup;
2139 }
2043 2140
2044 if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR)) 2141 if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR))
2045 goto delete_external_ea; 2142 goto delete_external_ea;
@@ -2047,31 +2144,20 @@ ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
2047 error = ext4_get_inode_loc(inode, &iloc); 2144 error = ext4_get_inode_loc(inode, &iloc);
2048 if (error) 2145 if (error)
2049 goto cleanup; 2146 goto cleanup;
2147
2148 error = ext4_journal_get_write_access(handle, iloc.bh);
2149 if (error)
2150 goto cleanup;
2151
2050 raw_inode = ext4_raw_inode(&iloc); 2152 raw_inode = ext4_raw_inode(&iloc);
2051 header = IHDR(inode, raw_inode); 2153 header = IHDR(inode, raw_inode);
2052 for (entry = IFIRST(header); !IS_LAST_ENTRY(entry); 2154 ext4_xattr_inode_remove_all(handle, inode, iloc.bh, IFIRST(header),
2053 entry = EXT4_XATTR_NEXT(entry)) { 2155 false /* block_csum */, ea_inode_array,
2054 if (!entry->e_value_inum) 2156 extra_credits);
2055 continue;
2056 ea_ino = le32_to_cpu(entry->e_value_inum);
2057 error = ext4_xattr_inode_iget(inode, ea_ino, &ea_inode);
2058 if (error)
2059 continue;
2060 error = ext4_expand_inode_array(ea_inode_array, ea_inode);
2061 if (error) {
2062 iput(ea_inode);
2063 brelse(iloc.bh);
2064 goto cleanup;
2065 }
2066 entry->e_value_inum = 0;
2067 }
2068 brelse(iloc.bh);
2069 2157
2070delete_external_ea: 2158delete_external_ea:
2071 if (!EXT4_I(inode)->i_file_acl) { 2159 if (!EXT4_I(inode)->i_file_acl) {
2072 /* add xattr inode to orphan list */ 2160 error = 0;
2073 error = ext4_xattr_inode_orphan_add(handle, inode, credits,
2074 *ea_inode_array);
2075 goto cleanup; 2161 goto cleanup;
2076 } 2162 }
2077 bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl); 2163 bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
@@ -2089,46 +2175,32 @@ delete_external_ea:
2089 goto cleanup; 2175 goto cleanup;
2090 } 2176 }
2091 2177
2092 for (entry = BFIRST(bh); !IS_LAST_ENTRY(entry); 2178 if (ext4_has_feature_ea_inode(inode->i_sb)) {
2093 entry = EXT4_XATTR_NEXT(entry)) { 2179 error = ext4_journal_get_write_access(handle, bh);
2094 if (!entry->e_value_inum)
2095 continue;
2096 ea_ino = le32_to_cpu(entry->e_value_inum);
2097 error = ext4_xattr_inode_iget(inode, ea_ino, &ea_inode);
2098 if (error)
2099 continue;
2100 error = ext4_expand_inode_array(ea_inode_array, ea_inode);
2101 if (error)
2102 goto cleanup;
2103 entry->e_value_inum = 0;
2104 }
2105
2106 /* add xattr inode to orphan list */
2107 error = ext4_xattr_inode_orphan_add(handle, inode, credits,
2108 *ea_inode_array);
2109 if (error)
2110 goto cleanup;
2111
2112 if (!IS_NOQUOTA(inode))
2113 credits += 2 * EXT4_QUOTA_DEL_BLOCKS(inode->i_sb);
2114
2115 if (!ext4_handle_has_enough_credits(handle, credits)) {
2116 error = ext4_journal_extend(handle, credits);
2117 if (error > 0)
2118 error = ext4_journal_restart(handle, credits);
2119 if (error) { 2180 if (error) {
2120 ext4_warning(inode->i_sb, 2181 EXT4_ERROR_INODE(inode, "write access %llu",
2121 "couldn't extend journal (err %d)", error); 2182 EXT4_I(inode)->i_file_acl);
2122 goto cleanup; 2183 goto cleanup;
2123 } 2184 }
2185 ext4_xattr_inode_remove_all(handle, inode, bh,
2186 BFIRST(bh),
2187 true /* block_csum */,
2188 ea_inode_array,
2189 extra_credits);
2124 } 2190 }
2125 2191
2126 ext4_xattr_release_block(handle, inode, bh); 2192 ext4_xattr_release_block(handle, inode, bh);
2193 /* Update i_file_acl within the same transaction that releases block. */
2127 EXT4_I(inode)->i_file_acl = 0; 2194 EXT4_I(inode)->i_file_acl = 0;
2128 2195 error = ext4_mark_inode_dirty(handle, inode);
2196 if (error) {
2197 EXT4_ERROR_INODE(inode, "mark inode dirty (error %d)",
2198 error);
2199 goto cleanup;
2200 }
2129cleanup: 2201cleanup:
2202 brelse(iloc.bh);
2130 brelse(bh); 2203 brelse(bh);
2131
2132 return error; 2204 return error;
2133} 2205}
2134 2206
diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
index adf761518a73..b2005a2716d9 100644
--- a/fs/ext4/xattr.h
+++ b/fs/ext4/xattr.h
@@ -169,7 +169,8 @@ extern int ext4_xattr_set_credits(struct inode *inode, size_t value_len);
169 169
170extern int ext4_xattr_inode_unlink(struct inode *inode, unsigned long ea_ino); 170extern int ext4_xattr_inode_unlink(struct inode *inode, unsigned long ea_ino);
171extern int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode, 171extern int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
172 struct ext4_xattr_inode_array **array); 172 struct ext4_xattr_inode_array **array,
173 int extra_credits);
173extern void ext4_xattr_inode_array_free(struct ext4_xattr_inode_array *array); 174extern void ext4_xattr_inode_array_free(struct ext4_xattr_inode_array *array);
174 175
175extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, 176extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,