LCOV - code coverage report
Current view: top level - fsck - afterpass1_common.c (source / functions) Coverage Total Hit
Test: gfs2-utils.info Lines: 0.0 % 138 0
Test Date: 2024-03-07 16:24:06 Functions: 0.0 % 12 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 2.0-1