add patch rename-GOINGDOWN-to-SHUTDOWN
[ext4-patch-queue.git] / add_shutdown_flag
blob4a6d01f1295dea5cc448eff8f876f0f940278ac8
1 ext4: add shutdown bit and check for it
3 Add a shutdown bit that will cause ext4 processing to fail immediately
4 with EIO.
6 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
7 ---
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
23 --- a/fs/ext4/ext4.h
24 +++ b/fs/ext4/ext4.h
25 @@ -1836,6 +1836,12 @@ static inline bool ext4_has_incompat_features(struct super_block *sb)
26   * Superblock flags
27   */
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);
37  /*
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)
43         journal_t *journal;
45         might_sleep();
47 +       if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
48 +               return -EIO;
50         if (sb->s_flags & MS_RDONLY)
51                 return -EROFS;
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,
54         might_sleep();
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);
62 +                       return -EIO;
63 +               }
64                 err = jbd2_journal_get_write_access(handle, bh);
65                 if (err)
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
69 --- a/fs/ext4/file.c
70 +++ b/fs/ext4/file.c
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)
74  {
75 +       if (unlikely(ext4_forced_shutdown(EXT4_SB(file_inode(iocb->ki_filp)->i_sb))))
76 +               return -EIO;
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)
82         int overwrite = 0;
83         ssize_t ret;
85 +       if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
86 +               return -EIO;
88  #ifdef CONFIG_FS_DAX
89         if (IS_DAX(inode))
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)
92  {
93         struct inode *inode = file->f_mapping->host;
95 +       if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
96 +               return -EIO;
98         if (ext4_encrypted_inode(inode)) {
99                 int err = fscrypt_get_encryption_info(inode);
100                 if (err)
101 @@ -375,6 +384,9 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
102         char buf[64], *cp;
103         int ret;
105 +       if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
106 +               return -EIO;
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)
116         tid_t commit_tid;
117         bool needs_barrier = false;
119 +       if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
120 +               return -EIO;
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;
145         int cp_len = 0;
147 +       if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
148 +               return;
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,
158         pgoff_t index;
159         unsigned from, to;
161 +       if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
162 +               return -EIO;
164         trace_ext4_write_begin(inode, pos, len, flags);
165         /*
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);
173 +               unlock_page(page);
174 +               return -EIO;
175 +       }
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,
181                 if (err < 0) {
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;
188                         /*
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))))
195 +               return -EIO;
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
202          * the stack trace.
203          */
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)) {
207                 ret = -EROFS;
208                 goto out_writepages;
209         }
210 @@ -2905,6 +2919,9 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
211         struct inode *inode = mapping->host;
212         handle_t *handle;
214 +       if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
215 +               return -EIO;
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)
221         int orphan = 0;
222         const unsigned int ia_valid = attr->ia_valid;
224 +       if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
225 +               return -EIO;
227         error = setattr_prepare(dentry, attr);
228         if (error)
229                 return error;
230 @@ -5498,6 +5518,9 @@ int ext4_mark_iloc_dirty(handle_t *handle,
232         int err = 0;
234 +       if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
235 +               return -EIO;
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,
242         int err;
244 +       if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
245 +               return -EIO;
247         err = ext4_get_inode_loc(inode, iloc);
248         if (!err) {
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))))
259 +               return -EIO;
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))))
269 +               return -EIO;
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))))
279 +               return -EIO;
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,
286                         unsigned int flags)
288 +       if (unlikely(ext4_forced_shutdown(EXT4_SB(old_dir->i_sb))))
289 +               return -EIO;
291         if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
292                 return -EINVAL;
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);
302 -       if (ret < 0) {
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;
313         va_list args;
315 +       if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
316 +               return;
318         if (ext4_error_ratelimit(sb)) {
319                 va_start(args, fmt);
320                 vaf.fmt = fmt;
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))))
326 +               return;
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))))
336 +               return;
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,
342         char nbuf[16];
343         const char *errstr;
345 +       if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
346 +               return;
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
350          * an error. */
351 @@ -600,6 +612,9 @@ void __ext4_abort(struct super_block *sb, const char *function,
352         struct va_format vaf;
353         va_list args;
355 +       if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
356 +               return;
358         save_error_info(sb, function, line);
359         va_start(args, fmt);
360         vaf.fmt = fmt;
361 @@ -695,6 +710,9 @@ __acquires(bitlock)
362         va_list args;
363         struct ext4_super_block *es = EXT4_SB(sb)->s_es;
365 +       if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
366 +               return;
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))))
376 +               return 0;
378         trace_ext4_sync_fs(sb, wait);
379         flush_workqueue(sbi->rsv_conversion_wq);
380         /*
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,
387         int error;
389 +       if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
390 +               return -EIO;
392         if (strlen(name) > 255)
393                 return -ERANGE;