1 ext4: add shutdown bit and check for it
3 Add a shutdown bit that will cause ext4 processing to fail immediately
6 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
8 fs/ext4/ext4.h | 6 ++++++
9 fs/ext4/ext4_jbd2.c | 11 +++++++++++
10 fs/ext4/file.c | 12 ++++++++++++
11 fs/ext4/fsync.c | 3 +++
12 fs/ext4/ialloc.c | 3 +++
13 fs/ext4/inline.c | 3 +++
14 fs/ext4/inode.c | 30 ++++++++++++++++++++++++++++--
15 fs/ext4/namei.c | 12 ++++++++++++
16 fs/ext4/page-io.c | 2 +-
17 fs/ext4/super.c | 21 +++++++++++++++++++++
18 fs/ext4/xattr.c | 3 +++
19 11 files changed, 103 insertions(+), 3 deletions(-)
21 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
22 index 2e7e02f2f771..35d93ab7f3fb 100644
25 @@ -1836,6 +1836,12 @@ static inline bool ext4_has_incompat_features(struct super_block *sb)
28 #define EXT4_FLAGS_RESIZING 0
29 +#define EXT4_FLAGS_SHUTDOWN 1
31 +static inline int ext4_forced_shutdown(struct ext4_sb_info *sbi)
33 + return test_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags);
38 diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
39 index e770c1ee4613..dd106b1d5d89 100644
40 --- a/fs/ext4/ext4_jbd2.c
41 +++ b/fs/ext4/ext4_jbd2.c
42 @@ -43,6 +43,10 @@ static int ext4_journal_check_start(struct super_block *sb)
47 + if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
50 if (sb->s_flags & MS_RDONLY)
52 WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE);
53 @@ -161,6 +165,13 @@ int __ext4_journal_get_write_access(const char *where, unsigned int line,
56 if (ext4_handle_valid(handle)) {
57 + struct super_block *sb;
59 + sb = handle->h_transaction->t_journal->j_private;
60 + if (unlikely(ext4_forced_shutdown(EXT4_SB(sb)))) {
61 + jbd2_journal_abort_handle(handle);
64 err = jbd2_journal_get_write_access(handle, bh);
66 ext4_journal_abort_handle(where, line, __func__, bh,
67 diff --git a/fs/ext4/file.c b/fs/ext4/file.c
68 index d663d3d7c81c..ff3f6107b0ba 100644
71 @@ -57,6 +57,9 @@ static ssize_t ext4_dax_read_iter(struct kiocb *iocb, struct iov_iter *to)
73 static ssize_t ext4_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
75 + if (unlikely(ext4_forced_shutdown(EXT4_SB(file_inode(iocb->ki_filp)->i_sb))))
78 if (!iov_iter_count(to))
79 return 0; /* skip atime */
81 @@ -213,6 +216,9 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
85 + if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
90 return ext4_dax_write_iter(iocb, from);
91 @@ -348,6 +354,9 @@ static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma)
93 struct inode *inode = file->f_mapping->host;
95 + if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
98 if (ext4_encrypted_inode(inode)) {
99 int err = fscrypt_get_encryption_info(inode);
101 @@ -375,6 +384,9 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
105 + if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
108 if (unlikely(!(sbi->s_mount_flags & EXT4_MF_MNTDIR_SAMPLED) &&
109 !(sb->s_flags & MS_RDONLY))) {
110 sbi->s_mount_flags |= EXT4_MF_MNTDIR_SAMPLED;
111 diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
112 index 88effb1053c7..9d549608fd30 100644
113 --- a/fs/ext4/fsync.c
114 +++ b/fs/ext4/fsync.c
115 @@ -100,6 +100,9 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
117 bool needs_barrier = false;
119 + if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
122 J_ASSERT(ext4_journal_current_handle() == NULL);
124 trace_ext4_sync_file_enter(file, datasync);
125 diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
126 index f372fc431b8e..b14bae2598bc 100644
127 --- a/fs/ext4/ialloc.c
128 +++ b/fs/ext4/ialloc.c
129 @@ -764,6 +764,9 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
130 if (!dir || !dir->i_nlink)
131 return ERR_PTR(-EPERM);
133 + if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb))))
134 + return ERR_PTR(-EIO);
136 if ((ext4_encrypted_inode(dir) ||
137 DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb))) &&
138 (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) {
139 diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
140 index b777b8aa14ae..30a9f210d1e3 100644
141 --- a/fs/ext4/inline.c
142 +++ b/fs/ext4/inline.c
143 @@ -215,6 +215,9 @@ static void ext4_write_inline_data(struct inode *inode, struct ext4_iloc *iloc,
144 struct ext4_inode *raw_inode;
147 + if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
150 BUG_ON(!EXT4_I(inode)->i_inline_off);
151 BUG_ON(pos + len > EXT4_I(inode)->i_inline_size);
153 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
154 index af97b9170358..bc282f9d0969 100644
155 --- a/fs/ext4/inode.c
156 +++ b/fs/ext4/inode.c
157 @@ -1189,6 +1189,9 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
161 + if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
164 trace_ext4_write_begin(inode, pos, len, flags);
166 * Reserve one block more for addition to orphan list in case
167 @@ -2047,6 +2050,12 @@ static int ext4_writepage(struct page *page,
168 struct ext4_io_submit io_submit;
169 bool keep_towrite = false;
171 + if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) {
172 + ext4_invalidatepage(page, 0, PAGE_SIZE);
177 trace_ext4_writepage(page);
178 size = i_size_read(inode);
179 if (page->index == size >> PAGE_SHIFT)
180 @@ -2422,7 +2431,8 @@ static int mpage_map_and_submit_extent(handle_t *handle,
182 struct super_block *sb = inode->i_sb;
184 - if (EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED)
185 + if (ext4_forced_shutdown(EXT4_SB(sb)) ||
186 + EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED)
187 goto invalidate_dirty_pages;
189 * Let the uper layers retry transient errors.
190 @@ -2644,6 +2654,9 @@ static int ext4_writepages(struct address_space *mapping,
191 struct blk_plug plug;
192 bool give_up_on_write = false;
194 + if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
197 percpu_down_read(&sbi->s_journal_flag_rwsem);
198 trace_ext4_writepages(inode, wbc);
200 @@ -2680,7 +2693,8 @@ static int ext4_writepages(struct address_space *mapping,
201 * *never* be called, so if that ever happens, we would want
204 - if (unlikely(sbi->s_mount_flags & EXT4_MF_FS_ABORTED)) {
205 + if (unlikely(ext4_forced_shutdown(EXT4_SB(mapping->host->i_sb)) ||
206 + sbi->s_mount_flags & EXT4_MF_FS_ABORTED)) {
210 @@ -2905,6 +2919,9 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
211 struct inode *inode = mapping->host;
214 + if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
217 index = pos >> PAGE_SHIFT;
219 if (ext4_nonda_switch(inode->i_sb) ||
220 @@ -5212,6 +5229,9 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
222 const unsigned int ia_valid = attr->ia_valid;
224 + if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
227 error = setattr_prepare(dentry, attr);
230 @@ -5498,6 +5518,9 @@ int ext4_mark_iloc_dirty(handle_t *handle,
234 + if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
237 if (IS_I_VERSION(inode))
238 inode_inc_iversion(inode);
240 @@ -5521,6 +5544,9 @@ ext4_reserve_inode_write(handle_t *handle, struct inode *inode,
244 + if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
247 err = ext4_get_inode_loc(inode, iloc);
249 BUFFER_TRACE(iloc->bh, "get_write_access");
250 diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
251 index 931da9d5d915..6ad612c576fc 100644
252 --- a/fs/ext4/namei.c
253 +++ b/fs/ext4/namei.c
254 @@ -2939,6 +2939,9 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
255 struct ext4_dir_entry_2 *de;
256 handle_t *handle = NULL;
258 + if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb))))
261 /* Initialize quotas before so that eventual writes go in
262 * separate transaction */
263 retval = dquot_initialize(dir);
264 @@ -3012,6 +3015,9 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
265 struct ext4_dir_entry_2 *de;
266 handle_t *handle = NULL;
268 + if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb))))
271 trace_ext4_unlink_enter(dir, dentry);
272 /* Initialize quotas before so that eventual writes go
273 * in separate transaction */
274 @@ -3082,6 +3088,9 @@ static int ext4_symlink(struct inode *dir,
275 struct fscrypt_str disk_link;
276 struct fscrypt_symlink_data *sd = NULL;
278 + if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb))))
281 disk_link.len = len + 1;
282 disk_link.name = (char *) symname;
284 @@ -3874,6 +3883,9 @@ static int ext4_rename2(struct inode *old_dir, struct dentry *old_dentry,
285 struct inode *new_dir, struct dentry *new_dentry,
288 + if (unlikely(ext4_forced_shutdown(EXT4_SB(old_dir->i_sb))))
291 if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
294 diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
295 index d83b0f3c5fe9..f8808835a28b 100644
296 --- a/fs/ext4/page-io.c
297 +++ b/fs/ext4/page-io.c
298 @@ -158,7 +158,7 @@ static int ext4_end_io(ext4_io_end_t *io)
300 io->handle = NULL; /* Following call will use up the handle */
301 ret = ext4_convert_unwritten_extents(handle, inode, offset, size);
303 + if (ret < 0 && !ext4_forced_shutdown(EXT4_SB(inode->i_sb))) {
304 ext4_msg(inode->i_sb, KERN_EMERG,
305 "failed to convert unwritten extents to written "
306 "extents -- potential data loss! "
307 diff --git a/fs/ext4/super.c b/fs/ext4/super.c
308 index 514e5fc59893..cfa4ce5a1f80 100644
309 --- a/fs/ext4/super.c
310 +++ b/fs/ext4/super.c
311 @@ -438,6 +438,9 @@ void __ext4_error(struct super_block *sb, const char *function,
312 struct va_format vaf;
315 + if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
318 if (ext4_error_ratelimit(sb)) {
321 @@ -459,6 +462,9 @@ void __ext4_error_inode(struct inode *inode, const char *function,
322 struct va_format vaf;
323 struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
325 + if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
328 es->s_last_error_ino = cpu_to_le32(inode->i_ino);
329 es->s_last_error_block = cpu_to_le64(block);
330 if (ext4_error_ratelimit(inode->i_sb)) {
331 @@ -491,6 +497,9 @@ void __ext4_error_file(struct file *file, const char *function,
332 struct inode *inode = file_inode(file);
333 char pathname[80], *path;
335 + if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
338 es = EXT4_SB(inode->i_sb)->s_es;
339 es->s_last_error_ino = cpu_to_le32(inode->i_ino);
340 if (ext4_error_ratelimit(inode->i_sb)) {
341 @@ -567,6 +576,9 @@ void __ext4_std_error(struct super_block *sb, const char *function,
345 + if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
348 /* Special case: if the error is EROFS, and we're not already
349 * inside a transaction, then there's really no point in logging
351 @@ -600,6 +612,9 @@ void __ext4_abort(struct super_block *sb, const char *function,
352 struct va_format vaf;
355 + if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
358 save_error_info(sb, function, line);
361 @@ -695,6 +710,9 @@ __acquires(bitlock)
363 struct ext4_super_block *es = EXT4_SB(sb)->s_es;
365 + if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
368 es->s_last_error_ino = cpu_to_le32(ino);
369 es->s_last_error_block = cpu_to_le64(block);
370 __save_error_info(sb, function, line);
371 @@ -4717,6 +4735,9 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
372 bool needs_barrier = false;
373 struct ext4_sb_info *sbi = EXT4_SB(sb);
375 + if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
378 trace_ext4_sync_fs(sb, wait);
379 flush_workqueue(sbi->rsv_conversion_wq);
381 diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
382 index c40bd55b6400..67636acf7624 100644
383 --- a/fs/ext4/xattr.c
384 +++ b/fs/ext4/xattr.c
385 @@ -411,6 +411,9 @@ ext4_xattr_get(struct inode *inode, int name_index, const char *name,
389 + if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
392 if (strlen(name) > 255)