aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2013-02-09 15:23:03 -0500
committerTheodore Ts'o <tytso@mit.edu>2013-02-09 15:23:03 -0500
commit95eaefbdececae5e781d76d03fe7472a857c8c7a (patch)
treeabe337e1490ded4166cf4d26f97cd1fe856a84ab /fs/ext4
parent64044abf05d0842a7fed30e102fa411a744c7d9f (diff)
ext4: fix the number of credits needed for acl ops with inline data
Operations which modify extended attributes may need extra journal credits if inline data is used, since there is a chance that some extended attributes may need to get pushed to an external attribute block. Changes to reflect this was made in xattr.c, but they were missed in fs/ext4/acl.c. To fix this, abstract the calculation of the number of credits needed for xattr operations to an inline function defined in ext4_jbd2.h, and use it in acl.c and xattr.c. Also move the function declarations used in inline.c from xattr.h (where they are non-obviously hidden, and caused problems since ext4_jbd2.h needs to use the function ext4_has_inline_data), and move them to ext4.h. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> Reviewed-by: Tao Ma <boyu.mt@taobao.com> Reviewed-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/acl.c4
-rw-r--r--fs/ext4/ext4.h69
-rw-r--r--fs/ext4/ext4_jbd2.h14
-rw-r--r--fs/ext4/xattr.c9
-rw-r--r--fs/ext4/xattr.h68
5 files changed, 86 insertions, 78 deletions
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
index 406cf8bb12d5..39a54a0e9fe4 100644
--- a/fs/ext4/acl.c
+++ b/fs/ext4/acl.c
@@ -325,7 +325,7 @@ ext4_acl_chmod(struct inode *inode)
325 return error; 325 return error;
326retry: 326retry:
327 handle = ext4_journal_start(inode, EXT4_HT_XATTR, 327 handle = ext4_journal_start(inode, EXT4_HT_XATTR,
328 EXT4_DATA_TRANS_BLOCKS(inode->i_sb)); 328 ext4_jbd2_credits_xattr(inode));
329 if (IS_ERR(handle)) { 329 if (IS_ERR(handle)) {
330 error = PTR_ERR(handle); 330 error = PTR_ERR(handle);
331 ext4_std_error(inode->i_sb, error); 331 ext4_std_error(inode->i_sb, error);
@@ -423,7 +423,7 @@ ext4_xattr_set_acl(struct dentry *dentry, const char *name, const void *value,
423 423
424retry: 424retry:
425 handle = ext4_journal_start(inode, EXT4_HT_XATTR, 425 handle = ext4_journal_start(inode, EXT4_HT_XATTR,
426 EXT4_DATA_TRANS_BLOCKS(inode->i_sb)); 426 ext4_jbd2_credits_xattr(inode));
427 if (IS_ERR(handle)) { 427 if (IS_ERR(handle)) {
428 error = PTR_ERR(handle); 428 error = PTR_ERR(handle);
429 goto release_and_out; 429 goto release_and_out;
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index a5ae87c51401..61ecf059f70c 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2456,6 +2456,75 @@ extern const struct file_operations ext4_file_operations;
2456extern loff_t ext4_llseek(struct file *file, loff_t offset, int origin); 2456extern loff_t ext4_llseek(struct file *file, loff_t offset, int origin);
2457extern void ext4_unwritten_wait(struct inode *inode); 2457extern void ext4_unwritten_wait(struct inode *inode);
2458 2458
2459/* inline.c */
2460extern int ext4_has_inline_data(struct inode *inode);
2461extern int ext4_get_inline_size(struct inode *inode);
2462extern int ext4_get_max_inline_size(struct inode *inode);
2463extern int ext4_find_inline_data_nolock(struct inode *inode);
2464extern void ext4_write_inline_data(struct inode *inode,
2465 struct ext4_iloc *iloc,
2466 void *buffer, loff_t pos,
2467 unsigned int len);
2468extern int ext4_prepare_inline_data(handle_t *handle, struct inode *inode,
2469 unsigned int len);
2470extern int ext4_init_inline_data(handle_t *handle, struct inode *inode,
2471 unsigned int len);
2472extern int ext4_destroy_inline_data(handle_t *handle, struct inode *inode);
2473
2474extern int ext4_readpage_inline(struct inode *inode, struct page *page);
2475extern int ext4_try_to_write_inline_data(struct address_space *mapping,
2476 struct inode *inode,
2477 loff_t pos, unsigned len,
2478 unsigned flags,
2479 struct page **pagep);
2480extern int ext4_write_inline_data_end(struct inode *inode,
2481 loff_t pos, unsigned len,
2482 unsigned copied,
2483 struct page *page);
2484extern struct buffer_head *
2485ext4_journalled_write_inline_data(struct inode *inode,
2486 unsigned len,
2487 struct page *page);
2488extern int ext4_da_write_inline_data_begin(struct address_space *mapping,
2489 struct inode *inode,
2490 loff_t pos, unsigned len,
2491 unsigned flags,
2492 struct page **pagep,
2493 void **fsdata);
2494extern int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos,
2495 unsigned len, unsigned copied,
2496 struct page *page);
2497extern int ext4_try_add_inline_entry(handle_t *handle, struct dentry *dentry,
2498 struct inode *inode);
2499extern int ext4_try_create_inline_dir(handle_t *handle,
2500 struct inode *parent,
2501 struct inode *inode);
2502extern int ext4_read_inline_dir(struct file *filp,
2503 void *dirent, filldir_t filldir,
2504 int *has_inline_data);
2505extern struct buffer_head *ext4_find_inline_entry(struct inode *dir,
2506 const struct qstr *d_name,
2507 struct ext4_dir_entry_2 **res_dir,
2508 int *has_inline_data);
2509extern int ext4_delete_inline_entry(handle_t *handle,
2510 struct inode *dir,
2511 struct ext4_dir_entry_2 *de_del,
2512 struct buffer_head *bh,
2513 int *has_inline_data);
2514extern int empty_inline_dir(struct inode *dir, int *has_inline_data);
2515extern struct buffer_head *ext4_get_first_inline_block(struct inode *inode,
2516 struct ext4_dir_entry_2 **parent_de,
2517 int *retval);
2518extern int ext4_inline_data_fiemap(struct inode *inode,
2519 struct fiemap_extent_info *fieinfo,
2520 int *has_inline);
2521extern int ext4_try_to_evict_inline_data(handle_t *handle,
2522 struct inode *inode,
2523 int needed);
2524extern void ext4_inline_data_truncate(struct inode *inode, int *has_inline);
2525
2526extern int ext4_convert_inline_data(struct inode *inode);
2527
2459/* namei.c */ 2528/* namei.c */
2460extern const struct inode_operations ext4_dir_inode_operations; 2529extern const struct inode_operations ext4_dir_inode_operations;
2461extern const struct inode_operations ext4_special_inode_operations; 2530extern const struct inode_operations ext4_special_inode_operations;
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
index c1fc2dca14ae..4c216b1bf20c 100644
--- a/fs/ext4/ext4_jbd2.h
+++ b/fs/ext4/ext4_jbd2.h
@@ -104,6 +104,20 @@
104#define EXT4_MAXQUOTAS_INIT_BLOCKS(sb) (MAXQUOTAS*EXT4_QUOTA_INIT_BLOCKS(sb)) 104#define EXT4_MAXQUOTAS_INIT_BLOCKS(sb) (MAXQUOTAS*EXT4_QUOTA_INIT_BLOCKS(sb))
105#define EXT4_MAXQUOTAS_DEL_BLOCKS(sb) (MAXQUOTAS*EXT4_QUOTA_DEL_BLOCKS(sb)) 105#define EXT4_MAXQUOTAS_DEL_BLOCKS(sb) (MAXQUOTAS*EXT4_QUOTA_DEL_BLOCKS(sb))
106 106
107static inline int ext4_jbd2_credits_xattr(struct inode *inode)
108{
109 int credits = EXT4_DATA_TRANS_BLOCKS(inode->i_sb);
110
111 /*
112 * In case of inline data, we may push out the data to a block,
113 * so we need to reserve credits for this eventuality
114 */
115 if (ext4_has_inline_data(inode))
116 credits += ext4_writepage_trans_blocks(inode) + 1;
117 return credits;
118}
119
120
107/* 121/*
108 * Ext4 handle operation types -- for logging purposes 122 * Ext4 handle operation types -- for logging purposes
109 */ 123 */
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 2efc5600b03b..cc31da027596 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -1165,16 +1165,9 @@ ext4_xattr_set(struct inode *inode, int name_index, const char *name,
1165{ 1165{
1166 handle_t *handle; 1166 handle_t *handle;
1167 int error, retries = 0; 1167 int error, retries = 0;
1168 int credits = EXT4_DATA_TRANS_BLOCKS(inode->i_sb); 1168 int credits = ext4_jbd2_credits_xattr(inode);
1169 1169
1170retry: 1170retry:
1171 /*
1172 * In case of inline data, we may push out the data to a block,
1173 * So reserve the journal space first.
1174 */
1175 if (ext4_has_inline_data(inode))
1176 credits += ext4_writepage_trans_blocks(inode) + 1;
1177
1178 handle = ext4_journal_start(inode, EXT4_HT_XATTR, credits); 1171 handle = ext4_journal_start(inode, EXT4_HT_XATTR, credits);
1179 if (IS_ERR(handle)) { 1172 if (IS_ERR(handle)) {
1180 error = PTR_ERR(handle); 1173 error = PTR_ERR(handle);
diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
index 69eda787a96a..aa25deb5c6cd 100644
--- a/fs/ext4/xattr.h
+++ b/fs/ext4/xattr.h
@@ -125,74 +125,6 @@ extern int ext4_xattr_ibody_inline_set(handle_t *handle, struct inode *inode,
125 struct ext4_xattr_info *i, 125 struct ext4_xattr_info *i,
126 struct ext4_xattr_ibody_find *is); 126 struct ext4_xattr_ibody_find *is);
127 127
128extern int ext4_has_inline_data(struct inode *inode);
129extern int ext4_get_inline_size(struct inode *inode);
130extern int ext4_get_max_inline_size(struct inode *inode);
131extern int ext4_find_inline_data_nolock(struct inode *inode);
132extern void ext4_write_inline_data(struct inode *inode,
133 struct ext4_iloc *iloc,
134 void *buffer, loff_t pos,
135 unsigned int len);
136extern int ext4_prepare_inline_data(handle_t *handle, struct inode *inode,
137 unsigned int len);
138extern int ext4_init_inline_data(handle_t *handle, struct inode *inode,
139 unsigned int len);
140extern int ext4_destroy_inline_data(handle_t *handle, struct inode *inode);
141
142extern int ext4_readpage_inline(struct inode *inode, struct page *page);
143extern int ext4_try_to_write_inline_data(struct address_space *mapping,
144 struct inode *inode,
145 loff_t pos, unsigned len,
146 unsigned flags,
147 struct page **pagep);
148extern int ext4_write_inline_data_end(struct inode *inode,
149 loff_t pos, unsigned len,
150 unsigned copied,
151 struct page *page);
152extern struct buffer_head *
153ext4_journalled_write_inline_data(struct inode *inode,
154 unsigned len,
155 struct page *page);
156extern int ext4_da_write_inline_data_begin(struct address_space *mapping,
157 struct inode *inode,
158 loff_t pos, unsigned len,
159 unsigned flags,
160 struct page **pagep,
161 void **fsdata);
162extern int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos,
163 unsigned len, unsigned copied,
164 struct page *page);
165extern int ext4_try_add_inline_entry(handle_t *handle, struct dentry *dentry,
166 struct inode *inode);
167extern int ext4_try_create_inline_dir(handle_t *handle,
168 struct inode *parent,
169 struct inode *inode);
170extern int ext4_read_inline_dir(struct file *filp,
171 void *dirent, filldir_t filldir,
172 int *has_inline_data);
173extern struct buffer_head *ext4_find_inline_entry(struct inode *dir,
174 const struct qstr *d_name,
175 struct ext4_dir_entry_2 **res_dir,
176 int *has_inline_data);
177extern int ext4_delete_inline_entry(handle_t *handle,
178 struct inode *dir,
179 struct ext4_dir_entry_2 *de_del,
180 struct buffer_head *bh,
181 int *has_inline_data);
182extern int empty_inline_dir(struct inode *dir, int *has_inline_data);
183extern struct buffer_head *ext4_get_first_inline_block(struct inode *inode,
184 struct ext4_dir_entry_2 **parent_de,
185 int *retval);
186extern int ext4_inline_data_fiemap(struct inode *inode,
187 struct fiemap_extent_info *fieinfo,
188 int *has_inline);
189extern int ext4_try_to_evict_inline_data(handle_t *handle,
190 struct inode *inode,
191 int needed);
192extern void ext4_inline_data_truncate(struct inode *inode, int *has_inline);
193
194extern int ext4_convert_inline_data(struct inode *inode);
195
196#ifdef CONFIG_EXT4_FS_SECURITY 128#ifdef CONFIG_EXT4_FS_SECURITY
197extern int ext4_init_security(handle_t *handle, struct inode *inode, 129extern int ext4_init_security(handle_t *handle, struct inode *inode,
198 struct inode *dir, const struct qstr *qstr); 130 struct inode *dir, const struct qstr *qstr);