LCOV - code coverage report
Current view: top level - fs/ext4 - ext4_jbd2.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 41 117 35.0 %
Date: 2014-02-18 Functions: 8 12 66.7 %
Branches: 24 78 30.8 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Interface between ext4 and JBD
       3                 :            :  */
       4                 :            : 
       5                 :            : #include "ext4_jbd2.h"
       6                 :            : 
       7                 :            : #include <trace/events/ext4.h>
       8                 :            : 
       9                 :            : /* Just increment the non-pointer handle value */
      10                 :          0 : static handle_t *ext4_get_nojournal(void)
      11                 :            : {
      12                 :          0 :         handle_t *handle = current->journal_info;
      13                 :          0 :         unsigned long ref_cnt = (unsigned long)handle;
      14                 :            : 
      15         [ #  # ]:          0 :         BUG_ON(ref_cnt >= EXT4_NOJOURNAL_MAX_REF_COUNT);
      16                 :            : 
      17                 :          0 :         ref_cnt++;
      18                 :          0 :         handle = (handle_t *)ref_cnt;
      19                 :            : 
      20                 :          0 :         current->journal_info = handle;
      21                 :          0 :         return handle;
      22                 :            : }
      23                 :            : 
      24                 :            : 
      25                 :            : /* Decrement the non-pointer handle value */
      26                 :          0 : static void ext4_put_nojournal(handle_t *handle)
      27                 :            : {
      28                 :          0 :         unsigned long ref_cnt = (unsigned long)handle;
      29                 :            : 
      30         [ #  # ]:          0 :         BUG_ON(ref_cnt == 0);
      31                 :            : 
      32                 :          0 :         ref_cnt--;
      33                 :          0 :         handle = (handle_t *)ref_cnt;
      34                 :            : 
      35                 :          0 :         current->journal_info = handle;
      36                 :          0 : }
      37                 :            : 
      38                 :            : /*
      39                 :            :  * Wrappers for jbd2_journal_start/end.
      40                 :            :  */
      41                 :          0 : static int ext4_journal_check_start(struct super_block *sb)
      42                 :            : {
      43                 :   13946279 :         journal_t *journal;
      44                 :            : 
      45                 :            :         might_sleep();
      46         [ +  + ]:   13947214 :         if (sb->s_flags & MS_RDONLY)
      47                 :            :                 return -EROFS;
      48         [ -  + ]:   13946935 :         WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE);
      49                 :   13946279 :         journal = EXT4_SB(sb)->s_journal;
      50                 :            :         /*
      51                 :            :          * Special case here: if the journal has aborted behind our
      52                 :            :          * backs (eg. EIO in the commit thread), then we still need to
      53                 :            :          * take the FS itself readonly cleanly.
      54                 :            :          */
      55 [ +  - ][ -  + ]:   13946279 :         if (journal && is_journal_aborted(journal)) {
      56                 :          0 :                 ext4_abort(sb, "Detected aborted journal");
      57                 :          0 :                 return -EROFS;
      58                 :            :         }
      59                 :            :         return 0;
      60                 :            : }
      61                 :            : 
      62                 :          0 : handle_t *__ext4_journal_start_sb(struct super_block *sb, unsigned int line,
      63                 :            :                                   int type, int blocks, int rsv_blocks)
      64                 :            : {
      65                 :            :         journal_t *journal;
      66                 :            :         int err;
      67                 :            : 
      68                 :   13945794 :         trace_ext4_journal_start(sb, blocks, rsv_blocks, _RET_IP_);
      69                 :   13945764 :         err = ext4_journal_check_start(sb);
      70         [ -  + ]:   13946775 :         if (err < 0)
      71                 :          0 :                 return ERR_PTR(err);
      72                 :            : 
      73                 :   13946775 :         journal = EXT4_SB(sb)->s_journal;
      74         [ -  + ]:   13946775 :         if (!journal)
      75                 :          0 :                 return ext4_get_nojournal();
      76                 :   13946775 :         return jbd2__journal_start(journal, blocks, rsv_blocks, GFP_NOFS,
      77                 :            :                                    type, line);
      78                 :            : }
      79                 :            : 
      80                 :          0 : int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle)
      81                 :            : {
      82                 :            :         struct super_block *sb;
      83                 :            :         int err;
      84                 :            :         int rc;
      85                 :            : 
      86         [ -  + ]:   13947312 :         if (!ext4_handle_valid(handle)) {
      87                 :          0 :                 ext4_put_nojournal(handle);
      88                 :          0 :                 return 0;
      89                 :            :         }
      90                 :   13947312 :         sb = handle->h_transaction->t_journal->j_private;
      91                 :   13947312 :         err = handle->h_err;
      92                 :   13947312 :         rc = jbd2_journal_stop(handle);
      93                 :            : 
      94            [ + ]:   13947557 :         if (!err)
      95                 :            :                 err = rc;
      96         [ -  + ]:   13947557 :         if (err)
      97                 :          0 :                 __ext4_std_error(sb, where, line, err);
      98                 :   13947578 :         return err;
      99                 :            : }
     100                 :            : 
     101                 :          0 : handle_t *__ext4_journal_start_reserved(handle_t *handle, unsigned int line,
     102                 :            :                                         int type)
     103                 :            : {
     104                 :            :         struct super_block *sb;
     105                 :            :         int err;
     106                 :            : 
     107         [ #  # ]:          0 :         if (!ext4_handle_valid(handle))
     108                 :          0 :                 return ext4_get_nojournal();
     109                 :            : 
     110                 :          0 :         sb = handle->h_journal->j_private;
     111                 :          0 :         trace_ext4_journal_start_reserved(sb, handle->h_buffer_credits,
     112                 :          0 :                                           _RET_IP_);
     113                 :          0 :         err = ext4_journal_check_start(sb);
     114         [ #  # ]:          0 :         if (err < 0) {
     115                 :          0 :                 jbd2_journal_free_reserved(handle);
     116                 :          0 :                 return ERR_PTR(err);
     117                 :            :         }
     118                 :            : 
     119                 :          0 :         err = jbd2_journal_start_reserved(handle, type, line);
     120         [ #  # ]:          0 :         if (err < 0)
     121                 :          0 :                 return ERR_PTR(err);
     122                 :            :         return handle;
     123                 :            : }
     124                 :            : 
     125                 :          0 : void ext4_journal_abort_handle(const char *caller, unsigned int line,
     126                 :            :                                const char *err_fn, struct buffer_head *bh,
     127                 :            :                                handle_t *handle, int err)
     128                 :            : {
     129                 :            :         char nbuf[16];
     130                 :          0 :         const char *errstr = ext4_decode_error(NULL, err, nbuf);
     131                 :            : 
     132         [ #  # ]:          0 :         BUG_ON(!ext4_handle_valid(handle));
     133                 :            : 
     134                 :            :         if (bh)
     135                 :            :                 BUFFER_TRACE(bh, "abort");
     136                 :            : 
     137         [ #  # ]:          0 :         if (!handle->h_err)
     138                 :          0 :                 handle->h_err = err;
     139                 :            : 
     140         [ #  # ]:          0 :         if (is_handle_aborted(handle))
     141                 :          0 :                 return;
     142                 :            : 
     143                 :          0 :         printk(KERN_ERR "EXT4-fs: %s:%d: aborting transaction: %s in %s\n",
     144                 :            :                caller, line, errstr, err_fn);
     145                 :            : 
     146                 :            :         jbd2_journal_abort_handle(handle);
     147                 :            : }
     148                 :            : 
     149                 :          0 : int __ext4_journal_get_write_access(const char *where, unsigned int line,
     150                 :            :                                     handle_t *handle, struct buffer_head *bh)
     151                 :            : {
     152                 :            :         int err = 0;
     153                 :            : 
     154                 :            :         might_sleep();
     155                 :            : 
     156         [ +  + ]:   16021492 :         if (ext4_handle_valid(handle)) {
     157                 :   16020819 :                 err = jbd2_journal_get_write_access(handle, bh);
     158         [ -  + ]:   16023572 :                 if (err)
     159                 :          0 :                         ext4_journal_abort_handle(where, line, __func__, bh,
     160                 :            :                                                   handle, err);
     161                 :            :         }
     162                 :       2753 :         return err;
     163                 :            : }
     164                 :            : 
     165                 :            : /*
     166                 :            :  * The ext4 forget function must perform a revoke if we are freeing data
     167                 :            :  * which has been journaled.  Metadata (eg. indirect blocks) must be
     168                 :            :  * revoked in all cases.
     169                 :            :  *
     170                 :            :  * "bh" may be NULL: a metadata block may have been freed from memory
     171                 :            :  * but there may still be a record of it in the journal, and that record
     172                 :            :  * still needs to be revoked.
     173                 :            :  *
     174                 :            :  * If the handle isn't valid we're not journaling, but we still need to
     175                 :            :  * call into ext4_journal_revoke() to put the buffer head.
     176                 :            :  */
     177                 :          0 : int __ext4_forget(const char *where, unsigned int line, handle_t *handle,
     178                 :            :                   int is_metadata, struct inode *inode,
     179                 :            :                   struct buffer_head *bh, ext4_fsblk_t blocknr)
     180                 :            : {
     181                 :            :         int err;
     182                 :            : 
     183                 :            :         might_sleep();
     184                 :            : 
     185                 :            :         trace_ext4_forget(inode, is_metadata, blocknr);
     186                 :            :         BUFFER_TRACE(bh, "enter");
     187                 :            : 
     188                 :            :         jbd_debug(4, "forgetting bh %p: is_metadata = %d, mode %o, "
     189                 :            :                   "data mode %x\n",
     190                 :            :                   bh, is_metadata, inode->i_mode,
     191                 :            :                   test_opt(inode->i_sb, DATA_FLAGS));
     192                 :            : 
     193                 :            :         /* In the no journal case, we can just do a bforget and return */
     194         [ -  + ]:      42770 :         if (!ext4_handle_valid(handle)) {
     195                 :            :                 bforget(bh);
     196                 :            :                 return 0;
     197                 :            :         }
     198                 :            : 
     199                 :            :         /* Never use the revoke function if we are doing full data
     200                 :            :          * journaling: there is no need to, and a V1 superblock won't
     201                 :            :          * support it.  Otherwise, only skip the revoke on un-journaled
     202                 :            :          * data blocks. */
     203                 :            : 
     204 [ +  - ][ -  + ]:      42770 :         if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
     205         [ #  # ]:          0 :             (!is_metadata && !ext4_should_journal_data(inode))) {
     206         [ #  # ]:          0 :                 if (bh) {
     207                 :            :                         BUFFER_TRACE(bh, "call jbd2_journal_forget");
     208                 :          0 :                         err = jbd2_journal_forget(handle, bh);
     209         [ #  # ]:          0 :                         if (err)
     210                 :          0 :                                 ext4_journal_abort_handle(where, line, __func__,
     211                 :            :                                                           bh, handle, err);
     212                 :          0 :                         return err;
     213                 :            :                 }
     214                 :            :                 return 0;
     215                 :            :         }
     216                 :            : 
     217                 :            :         /*
     218                 :            :          * data!=journal && (is_metadata || should_journal_data(inode))
     219                 :            :          */
     220                 :            :         BUFFER_TRACE(bh, "call jbd2_journal_revoke");
     221                 :      42770 :         err = jbd2_journal_revoke(handle, blocknr, bh);
     222         [ -  + ]:      42770 :         if (err) {
     223                 :          0 :                 ext4_journal_abort_handle(where, line, __func__,
     224                 :            :                                           bh, handle, err);
     225                 :          0 :                 __ext4_abort(inode->i_sb, where, line,
     226                 :            :                            "error %d when attempting revoke", err);
     227                 :            :         }
     228                 :            :         BUFFER_TRACE(bh, "exit");
     229                 :      42770 :         return err;
     230                 :            : }
     231                 :            : 
     232                 :          0 : int __ext4_journal_get_create_access(const char *where, unsigned int line,
     233                 :            :                                 handle_t *handle, struct buffer_head *bh)
     234                 :            : {
     235                 :            :         int err = 0;
     236                 :            : 
     237         [ +  - ]:      42385 :         if (ext4_handle_valid(handle)) {
     238                 :      42385 :                 err = jbd2_journal_get_create_access(handle, bh);
     239         [ -  + ]:      42385 :                 if (err)
     240                 :          0 :                         ext4_journal_abort_handle(where, line, __func__,
     241                 :            :                                                   bh, handle, err);
     242                 :            :         }
     243                 :          0 :         return err;
     244                 :            : }
     245                 :            : 
     246                 :          0 : int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
     247                 :            :                                  handle_t *handle, struct inode *inode,
     248                 :            :                                  struct buffer_head *bh)
     249                 :            : {
     250                 :            :         int err = 0;
     251                 :            : 
     252                 :            :         might_sleep();
     253                 :            : 
     254                 :            :         set_buffer_meta(bh);
     255                 :            :         set_buffer_prio(bh);
     256         [ +  - ]:   14868300 :         if (ext4_handle_valid(handle)) {
     257                 :   14868300 :                 err = jbd2_journal_dirty_metadata(handle, bh);
     258                 :            :                 /* Errors can only happen if there is a bug */
     259 [ -  + ][ #  # ]:   14869925 :                 if (WARN_ON_ONCE(err)) {
            [ - ][ -  + ]
     260                 :          0 :                         ext4_journal_abort_handle(where, line, __func__, bh,
     261                 :            :                                                   handle, err);
     262                 :          0 :                         ext4_error_inode(inode, where, line,
     263                 :            :                                          bh->b_blocknr,
     264                 :            :                                          "journal_dirty_metadata failed: "
     265                 :            :                                          "handle type %u started at line %u, "
     266                 :            :                                          "credits %u/%u, errcode %d",
     267                 :            :                                          handle->h_type,
     268                 :            :                                          handle->h_line_no,
     269                 :            :                                          handle->h_requested_credits,
     270                 :            :                                          handle->h_buffer_credits, err);
     271                 :            :                 }
     272                 :            :         } else {
     273         [ #  # ]:          0 :                 if (inode)
     274                 :          0 :                         mark_buffer_dirty_inode(bh, inode);
     275                 :            :                 else
     276                 :          0 :                         mark_buffer_dirty(bh);
     277 [ #  # ][ #  # ]:          0 :                 if (inode && inode_needs_sync(inode)) {
     278                 :          0 :                         sync_dirty_buffer(bh);
     279 [ #  # ][ #  # ]:          0 :                         if (buffer_req(bh) && !buffer_uptodate(bh)) {
     280                 :            :                                 struct ext4_super_block *es;
     281                 :            : 
     282                 :          0 :                                 es = EXT4_SB(inode->i_sb)->s_es;
     283                 :          0 :                                 es->s_last_error_block =
     284                 :          0 :                                         cpu_to_le64(bh->b_blocknr);
     285                 :          0 :                                 ext4_error_inode(inode, where, line,
     286                 :            :                                                  bh->b_blocknr,
     287                 :            :                                         "IO error syncing itable block");
     288                 :            :                                 err = -EIO;
     289                 :            :                         }
     290                 :            :                 }
     291                 :            :         }
     292                 :   14869921 :         return err;
     293                 :            : }
     294                 :            : 
     295                 :          0 : int __ext4_handle_dirty_super(const char *where, unsigned int line,
     296                 :    1145822 :                               handle_t *handle, struct super_block *sb)
     297                 :            : {
     298                 :    1145822 :         struct buffer_head *bh = EXT4_SB(sb)->s_sbh;
     299                 :            :         int err = 0;
     300                 :            : 
     301                 :    1145822 :         ext4_superblock_csum_set(sb);
     302         [ +  - ]:    1145822 :         if (ext4_handle_valid(handle)) {
     303                 :    1145822 :                 err = jbd2_journal_dirty_metadata(handle, bh);
     304         [ -  + ]:    1145822 :                 if (err)
     305                 :          0 :                         ext4_journal_abort_handle(where, line, __func__,
     306                 :            :                                                   bh, handle, err);
     307                 :            :         } else
     308                 :          0 :                 mark_buffer_dirty(bh);
     309                 :    1145822 :         return err;
     310                 :            : }

Generated by: LCOV version 1.9