LCOV - code coverage report
Current view: top level - fsck - afterpass1_common.c (source / functions) Hit Total Coverage
Test: gfs2-utils.info Lines: 0 138 0.0 %
Date: 2023-09-27 13:48:55 Functions: 0 12 0.0 %

          Line data    Source code
       1             : #include <inttypes.h>
       2             : #include <stdio.h>
       3             : #include <stdlib.h>
       4             : #include <string.h>
       5             : #include <sys/types.h>
       6             : #include <sys/stat.h>
       7             : #include <unistd.h>
       8             : #include <libintl.h>
       9             : #include <ctype.h>
      10             : #include <fcntl.h>
      11             : #define _(String) gettext(String)
      12             : 
      13             : #include <logging.h>
      14             : #include "libgfs2.h"
      15             : #include "fsck.h"
      16             : #include "afterpass1_common.h"
      17             : #include "metawalk.h"
      18             : #include "util.h"
      19             : 
      20             : /**
      21             :  * find_remove_dup - find out if this is a duplicate ref.  If so, remove it.
      22             :  *
      23             :  * Returns: 1 if there are any remaining references to this block, else 0.
      24             :  */
      25           0 : static int find_remove_dup(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block,
      26             :                            const char *btype, int *removed_last_meta)
      27             : {
      28             :         struct duptree *dt;
      29             :         struct inode_with_dups *id;
      30           0 :         int deleted_a_meta_ref = 0;
      31           0 :         int meta_refs_left = 0;
      32             : 
      33           0 :         dt = dupfind(cx, block);
      34           0 :         if (!dt)
      35           0 :                 return 0;
      36             : 
      37             :         /* remove the inode reference id structure for this reference. */
      38           0 :         id = find_dup_ref_inode(dt, ip);
      39           0 :         if (!id)
      40           0 :                 goto more_refs;
      41             : 
      42           0 :         if (id->reftypecount[REF_AS_META])
      43           0 :                 deleted_a_meta_ref = 1;
      44           0 :         dup_listent_delete(dt, id);
      45           0 :         if (dt->refs == 0) {
      46           0 :                 log_info( _("This was the last reference: it's no longer a "
      47             :                             "duplicate.\n"));
      48           0 :                 dup_delete(cx, dt); /* not duplicate now */
      49           0 :                 if (deleted_a_meta_ref) {
      50           0 :                         log_debug("Removed the last reference as metadata.\n");
      51           0 :                         *removed_last_meta = 1;
      52             :                 }
      53           0 :                 return 0;
      54           0 :         } else if (deleted_a_meta_ref) {
      55             :                 /* If we deleted a metadata reference, see if there are more
      56             :                    references as meta, or if it was the last one. */
      57           0 :                 meta_refs_left = count_dup_meta_refs(dt);
      58             :         }
      59           0 : more_refs:
      60           0 :         log_info(_("%d block reference(s) remain (%d as metadata).\n"),
      61             :                  dt->refs, meta_refs_left);
      62           0 :         if (deleted_a_meta_ref && meta_refs_left == 0) {
      63           0 :                 log_debug("Removed the last reference as metadata.\n");
      64           0 :                 *removed_last_meta = 1;
      65             :         }
      66           0 :         return 1; /* references still exist so do not free the block. */
      67             : }
      68             : 
      69             : /**
      70             :  * delete_block_if_notdup - delete blocks associated with an inode
      71             :  *
      72             :  * Ignore blocks that are already marked free.
      73             :  * If it has been identified as duplicate, remove the duplicate reference.
      74             :  * If all duplicate references have been removed, delete the block.
      75             :  */
      76           0 : static int delete_block_if_notdup(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block,
      77             :                                   struct lgfs2_buffer_head **bh,
      78             :                                   const char *btype, int *was_duplicate,
      79             :                                   void *private)
      80             : {
      81             :         int q;
      82           0 :         int removed_lastmeta = 0;
      83             : 
      84           0 :         if (!valid_block_ip(ip, block))
      85           0 :                 return META_ERROR;
      86             : 
      87           0 :         q = bitmap_type(ip->i_sbd, block);
      88           0 :         if (q == GFS2_BLKST_FREE) {
      89           0 :                 log_info(_("%s block %"PRIu64" (0x%"PRIx64"), part of inode "
      90             :                            "%"PRIu64" (0x%"PRIx64"), was already free.\n"),
      91             :                         btype, block, block, ip->i_num.in_addr, ip->i_num.in_addr);
      92           0 :                 return META_IS_GOOD;
      93             :         }
      94           0 :         if (find_remove_dup(cx, ip, block, btype, &removed_lastmeta)) { /* a dup */
      95           0 :                 if (was_duplicate) {
      96           0 :                         if (removed_lastmeta)
      97           0 :                                 log_debug("Removed last reference as meta.\n");
      98             :                         else
      99           0 :                                 *was_duplicate = 1;
     100             :                 }
     101           0 :                 log_err(_("Not clearing duplicate reference in inode at block #%"PRIu64
     102             :                           " (0x%"PRIx64") to block #%"PRIu64" (0x%"PRIx64") "
     103             :                           "because it's referenced by another inode.\n"),
     104             :                         ip->i_num.in_addr, ip->i_num.in_addr, block, block);
     105             :         } else {
     106           0 :                 check_n_fix_bitmap(cx, ip->i_rgd, block, 0,
     107             :                                    GFS2_BLKST_FREE);
     108             :         }
     109           0 :         return META_IS_GOOD;
     110             : }
     111             : 
     112           0 : static int remove_dentry(struct fsck_cx *cx, struct lgfs2_inode *ip, struct gfs2_dirent *dent,
     113             :                          struct gfs2_dirent *prev_de,
     114             :                          struct lgfs2_buffer_head *bh,
     115             :                          char *filename, uint32_t *count, int *lindex,
     116             :                          void *private)
     117             : {
     118             :         /* the metawalk_fxn's private field must be set to the dentry
     119             :          * block we want to clear */
     120           0 :         uint64_t *dentryblock = (uint64_t *) private;
     121             :         struct lgfs2_dirent d;
     122             : 
     123           0 :         lgfs2_dirent_in(&d, dent);
     124             : 
     125           0 :         if (d.dr_inum.in_addr == *dentryblock)
     126           0 :                 lgfs2_dirent2_del(ip, bh, prev_de, dent);
     127             :         else
     128           0 :                 (*count)++;
     129             : 
     130           0 :         return 0;
     131             : 
     132             : }
     133             : 
     134           0 : int remove_dentry_from_dir(struct fsck_cx *cx, uint64_t dir, uint64_t dentryblock)
     135             : {
     136           0 :         struct metawalk_fxns remove_dentry_fxns = {0};
     137           0 :         struct lgfs2_sbd *sdp = cx->sdp;
     138             :         struct lgfs2_inode *ip;
     139             :         int q;
     140             :         int error;
     141             : 
     142           0 :         log_debug(_("Removing dentry %"PRIu64" (0x%"PRIx64") from directory %"PRIu64" (0x%"PRIx64")\n"),
     143             :                   dentryblock, dentryblock, dir, dir);
     144           0 :         if (!valid_block(sdp, dir)) {
     145           0 :                 log_err( _("Parent directory is invalid\n"));
     146           0 :                 return 1;
     147             :         }
     148           0 :         remove_dentry_fxns.private = &dentryblock;
     149           0 :         remove_dentry_fxns.check_dentry = remove_dentry;
     150             : 
     151           0 :         q = bitmap_type(sdp, dir);
     152           0 :         if (q != GFS2_BLKST_DINODE) {
     153           0 :                 log_info( _("Parent block is not an inode...ignoring\n"));
     154           0 :                 return 1;
     155             :         }
     156             : 
     157           0 :         ip = fsck_load_inode(sdp, dir);
     158           0 :         if (ip == NULL) {
     159           0 :                 stack;
     160           0 :                 return -1;
     161             :         }
     162             :         /* Need to run check_dir with a private var of dentryblock,
     163             :          * and fxns that remove that dentry if found */
     164           0 :         error = check_dir(cx, ip, &remove_dentry_fxns);
     165           0 :         fsck_inode_put(&ip);
     166           0 :         return error;
     167             : }
     168             : 
     169           0 : int delete_metadata(struct fsck_cx *cx, struct iptr iptr, struct lgfs2_buffer_head **bh, int h, int *is_valid,
     170             :                     int *was_duplicate, void *private)
     171             : {
     172           0 :         struct lgfs2_inode *ip = iptr.ipt_ip;
     173           0 :         uint64_t block = iptr_block(iptr);
     174             : 
     175           0 :         *is_valid = 1;
     176           0 :         *was_duplicate = 0;
     177           0 :         return delete_block_if_notdup(cx, ip, block, bh, _("metadata"),
     178             :                                       was_duplicate, private);
     179             : }
     180             : 
     181           0 : int delete_leaf(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block, void *private)
     182             : {
     183           0 :         return delete_block_if_notdup(cx, ip, block, NULL, _("leaf"), NULL,
     184             :                                       private);
     185             : }
     186             : 
     187           0 : int delete_data(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t metablock,
     188             :                 uint64_t block, void *private, struct lgfs2_buffer_head *bh,
     189             :                 __be64 *ptr)
     190             : {
     191           0 :         return delete_block_if_notdup(cx, ip, block, NULL, _("data"), NULL,
     192             :                                       private);
     193             : }
     194             : 
     195           0 : static int del_eattr_generic(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block,
     196             :                              uint64_t parent, struct lgfs2_buffer_head **bh,
     197             :                              void *private, const char *eatype)
     198             : {
     199           0 :         int ret = 0;
     200           0 :         int was_free = 0;
     201             :         int q;
     202             : 
     203           0 :         if (valid_block_ip(ip, block)) {
     204           0 :                 q = bitmap_type(ip->i_sbd, block);
     205           0 :                 if (q == GFS2_BLKST_FREE)
     206           0 :                         was_free = 1;
     207           0 :                 ret = delete_block_if_notdup(cx, ip, block, NULL, eatype,
     208             :                                              NULL, private);
     209           0 :                 if (!ret) {
     210           0 :                         *bh = lgfs2_bread(ip->i_sbd, block);
     211           0 :                         if (!was_free)
     212           0 :                                 ip->i_blocks--;
     213           0 :                         lgfs2_bmodified(ip->i_bh);
     214             :                 }
     215             :         }
     216             :         /* Even if it's a duplicate reference, we want to eliminate the
     217             :            reference itself, and adjust di_blocks accordingly. */
     218           0 :         if (ip->i_eattr) {
     219           0 :                 if (block == ip->i_eattr)
     220           0 :                         ip->i_eattr = 0;
     221           0 :                 lgfs2_bmodified(ip->i_bh);
     222             :         }
     223           0 :         return ret;
     224             : }
     225             : 
     226           0 : int delete_eattr_indir(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block, uint64_t parent,
     227             :                        struct lgfs2_buffer_head **bh, void *private)
     228             : {
     229           0 :         return del_eattr_generic(cx, ip, block, parent, bh, private,
     230           0 :                                  _("extended attribute"));
     231             : }
     232             : 
     233           0 : int delete_eattr_leaf(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block, uint64_t parent,
     234             :                       struct lgfs2_buffer_head **bh, void *private)
     235             : {
     236           0 :         return del_eattr_generic(cx, ip, block, parent, bh, private,
     237           0 :                                  _("indirect extended attribute"));
     238             : }
     239             : 
     240           0 : int delete_eattr_entry(struct fsck_cx *cx, struct lgfs2_inode *ip, struct lgfs2_buffer_head *leaf_bh,
     241             :                        struct gfs2_ea_header *ea_hdr,
     242             :                        struct gfs2_ea_header *ea_hdr_prev, void *private)
     243             : {
     244           0 :         struct lgfs2_sbd *sdp = ip->i_sbd;
     245             :         char ea_name[256];
     246             :         uint32_t avail_size;
     247             :         int max_ptrs;
     248             : 
     249           0 :         if (!ea_hdr->ea_name_len){
     250             :                 /* Skip this entry for now */
     251           0 :                 return 1;
     252             :         }
     253             : 
     254           0 :         memset(ea_name, 0, sizeof(ea_name));
     255           0 :         strncpy(ea_name, (char *)ea_hdr + sizeof(struct gfs2_ea_header),
     256           0 :                 ea_hdr->ea_name_len);
     257             : 
     258           0 :         if (!GFS2_EATYPE_VALID(ea_hdr->ea_type) &&
     259           0 :            ((ea_hdr_prev) || (!ea_hdr_prev && ea_hdr->ea_type))){
     260             :                 /* Skip invalid entry */
     261           0 :                 return 1;
     262             :         }
     263             : 
     264           0 :         if (!ea_hdr->ea_num_ptrs)
     265           0 :                 return 0;
     266             : 
     267           0 :         avail_size = sdp->sd_bsize - sizeof(struct gfs2_meta_header);
     268           0 :         max_ptrs = (be32_to_cpu(ea_hdr->ea_data_len) + avail_size - 1) /
     269             :                 avail_size;
     270             : 
     271           0 :         if (max_ptrs > ea_hdr->ea_num_ptrs)
     272           0 :                 return 1;
     273             : 
     274           0 :         log_debug( _("  Pointers Required: %d\n  Pointers Reported: %d\n"),
     275             :                    max_ptrs, ea_hdr->ea_num_ptrs);
     276             : 
     277           0 :         return 0;
     278             : }
     279             : 
     280           0 : int delete_eattr_extentry(struct fsck_cx *cx, struct lgfs2_inode *ip, int i, __be64 *ea_data_ptr,
     281             :                           struct lgfs2_buffer_head *leaf_bh, uint32_t tot_ealen,
     282             :                           struct gfs2_ea_header *ea_hdr,
     283             :                           struct gfs2_ea_header *ea_hdr_prev, void *private)
     284             : {
     285           0 :         uint64_t block = be64_to_cpu(*ea_data_ptr);
     286             :         int error;
     287             : 
     288           0 :         error = delete_block_if_notdup(cx, ip, block, NULL,
     289           0 :                                        _("extended attribute"), NULL, private);
     290           0 :         if (error) {
     291           0 :                 log_err(_("Bad extended attribute found at block %"PRIu64 " (0x%"PRIx64")"),
     292             :                         be64_to_cpu(*ea_data_ptr), be64_to_cpu(*ea_data_ptr));
     293           0 :                 if (query(cx, _("Repair the bad Extended Attribute? (y/n) "))) {
     294           0 :                         ea_hdr->ea_num_ptrs = i;
     295           0 :                         ea_hdr->ea_data_len = cpu_to_be32(tot_ealen);
     296           0 :                         *ea_data_ptr = 0;
     297           0 :                         lgfs2_bmodified(leaf_bh);
     298             :                         /* Endianness doesn't matter in this case because it's
     299             :                            a single byte. */
     300           0 :                         fsck_bitmap_set(cx, ip, ip->i_eattr,
     301             :                                         _("extended attribute"),
     302             :                                         GFS2_BLKST_USED);
     303           0 :                         log_err( _("The EA was fixed.\n"));
     304             :                 } else {
     305           0 :                         error = 1;
     306           0 :                         log_err( _("The bad EA was not fixed.\n"));
     307             :                 }
     308             :         }
     309           0 :         return error;
     310             : }

Generated by: LCOV version 1.14