LCOV - code coverage report
Current view: top level - fsck - lost_n_found.c (source / functions) Coverage Total Hit
Test: gfs2-utils.info Lines: 0.0 % 119 0
Test Date: 2024-03-07 16:24:06 Functions: 0.0 % 3 0

            Line data    Source code
       1              : #include "clusterautoconfig.h"
       2              : 
       3              : #include <inttypes.h>
       4              : #include <stdio.h>
       5              : #include <stdlib.h>
       6              : #include <string.h>
       7              : #include <sys/stat.h>
       8              : #include <unistd.h>
       9              : #include <dirent.h>
      10              : #include <libintl.h>
      11              : #define _(String) gettext(String)
      12              : 
      13              : #include <logging.h>
      14              : #include "fsck.h"
      15              : #include "libgfs2.h"
      16              : #include "lost_n_found.h"
      17              : #include "link.h"
      18              : #include "metawalk.h"
      19              : #include "util.h"
      20              : 
      21            0 : static void add_dotdot(struct fsck_cx *cx, struct lgfs2_inode *ip)
      22              : {
      23            0 :         struct lgfs2_sbd *sdp = ip->i_sbd;
      24              :         struct dir_info *di;
      25              :         struct lgfs2_inum no;
      26              :         int err;
      27              : 
      28            0 :         log_info(_("Adding .. entry to directory %"PRIu64" (0x%"PRIx64") pointing back to lost+found\n"),
      29              :                 ip->i_num.in_addr, ip->i_num.in_addr);
      30              : 
      31              :         /* If there's a pre-existing .. directory entry, we have to
      32              :            back out the links. */
      33            0 :         di = dirtree_find(cx, ip->i_num.in_addr);
      34            0 :         if (di && valid_block(sdp, di->dotdot_parent.in_addr)) {
      35              :                 struct lgfs2_inode *dip;
      36              : 
      37            0 :                 log_debug(_("Directory (0x%"PRIx64") already had a '..' link to (0x%"PRIx64").\n"),
      38              :                           ip->i_num.in_addr, di->dotdot_parent.in_addr);
      39            0 :                 dip = fsck_load_inode(sdp, di->dotdot_parent.in_addr);
      40            0 :                 if (dip->i_num.in_formal_ino == di->dotdot_parent.in_formal_ino) {
      41            0 :                         decr_link_count(cx, di->dotdot_parent.in_addr, ip->i_num.in_addr,
      42            0 :                                         _(".. unlinked, moving to lost+found"));
      43            0 :                         if (dip->i_nlink > 0) {
      44            0 :                           dip->i_nlink--;
      45            0 :                           set_di_nlink(cx, dip); /* keep inode tree in sync */
      46            0 :                           log_debug(_("Decrementing its links to %d\n"),
      47              :                                     dip->i_nlink);
      48            0 :                           lgfs2_bmodified(dip->i_bh);
      49            0 :                         } else if (!dip->i_nlink) {
      50            0 :                           log_debug(_("Its link count is zero.\n"));
      51              :                         } else {
      52            0 :                           log_debug(_("Its link count is %d!  Changing it to 0.\n"),
      53              :                                     dip->i_nlink);
      54            0 :                           dip->i_nlink = 0;
      55            0 :                           set_di_nlink(cx, dip); /* keep inode tree in sync */
      56            0 :                           lgfs2_bmodified(dip->i_bh);
      57              :                         }
      58              :                 } else {
      59            0 :                         log_debug(_("Directory (0x%"PRIx64")'s link to parent "
      60              :                                     "(0x%"PRIx64") had a formal inode discrepancy: "
      61              :                                     "was 0x%"PRIx64", expected 0x%"PRIx64"\n"),
      62              :                                   ip->i_num.in_addr, di->dotdot_parent.in_addr,
      63              :                                   di->dotdot_parent.in_formal_ino,
      64              :                                   dip->i_num.in_formal_ino);
      65            0 :                         log_debug(_("The parent directory was not changed.\n"));
      66              :                 }
      67            0 :                 fsck_inode_put(&dip);
      68            0 :                 di = NULL;
      69              :         } else {
      70            0 :                 if (di)
      71            0 :                         log_debug(_("Couldn't find a valid '..' entry "
      72              :                                     "for orphan directory (0x%"PRIx64"): "
      73              :                                     "'..' = 0x%"PRIx64"\n"),
      74              :                                   ip->i_num.in_addr, di->dotdot_parent.in_addr);
      75              :                 else
      76            0 :                         log_debug(_("Couldn't find directory (0x%"PRIx64") "
      77              :                                     "in directory tree.\n"),
      78              :                                   ip->i_num.in_addr);
      79              :         }
      80            0 :         if (lgfs2_dirent_del(ip, "..", 2))
      81            0 :                 log_warn( _("add_inode_to_lf:  Unable to remove "
      82              :                             "\"..\" directory entry.\n"));
      83              : 
      84            0 :         no = lf_dip->i_num;
      85            0 :         err = lgfs2_dir_add(ip, "..", 2, &no, DT_DIR);
      86            0 :         if (err) {
      87            0 :                 log_crit(_("Error adding .. directory: %s\n"),
      88              :                          strerror(errno));
      89            0 :                 exit(FSCK_ERROR);
      90              :         }
      91            0 : }
      92              : 
      93            0 : void make_sure_lf_exists(struct fsck_cx *cx, struct lgfs2_inode *ip)
      94              : {
      95              :         struct dir_info *di;
      96            0 :         struct lgfs2_sbd *sdp = ip->i_sbd;
      97              :         int root_entries;
      98              : 
      99            0 :         if (lf_dip)
     100            0 :                 return;
     101              : 
     102            0 :         root_entries = sdp->md.rooti->i_entries;
     103            0 :         log_info( _("Locating/Creating lost+found directory\n"));
     104            0 :         lf_dip = lgfs2_createi(sdp->md.rooti, "lost+found", S_IFDIR|0700, 0);
     105            0 :         if (lf_dip == NULL) {
     106            0 :                 log_crit(_("Error creating lost+found: %s\n"),
     107              :                          strerror(errno));
     108            0 :                 exit(FSCK_ERROR);
     109              :         }
     110              : 
     111              :         /* lgfs2_createi will have incremented the di_nlink link count for the root
     112              :            directory.  We must set the nlink value in the hash table to keep
     113              :            them in sync so that pass4 can detect and fix any descrepancies. */
     114            0 :         set_di_nlink(cx, sdp->md.rooti);
     115              : 
     116            0 :         if (sdp->md.rooti->i_entries > root_entries) {
     117            0 :                 struct lgfs2_inum no = lf_dip->i_num;
     118            0 :                 lf_was_created = 1;
     119              :                 /* This is a new lost+found directory, so set its block type
     120              :                    and increment link counts for the directories */
     121              :                 /* FIXME: i'd feel better about this if fs_mkdir returned
     122              :                    whether it created a new directory or just found an old one,
     123              :                    and we used that instead of the bitmap_type to run this */
     124            0 :                 dirtree_insert(cx, no);
     125              :                 /* Set the bitmap AFTER the dirtree insert so that function
     126              :                    check_n_fix_bitmap will realize it's a dinode and adjust
     127              :                    the rgrp counts properly. */
     128            0 :                 fsck_bitmap_set(cx, ip, lf_dip->i_num.in_addr, _("lost+found dinode"), GFS2_BLKST_DINODE);
     129              :                 /* root inode links to lost+found */
     130            0 :                 no.in_addr = sdp->md.rooti->i_num.in_addr;
     131            0 :                 no.in_formal_ino = sdp->md.rooti->i_num.in_formal_ino;
     132            0 :                 incr_link_count(cx, no, lf_dip, _("root"));
     133              :                 /* lost+found link for '.' from itself */
     134            0 :                 no.in_addr = lf_dip->i_num.in_addr;
     135            0 :                 no.in_formal_ino = lf_dip->i_num.in_formal_ino;
     136            0 :                 incr_link_count(cx, no, lf_dip, "\".\"");
     137              :                 /* lost+found link for '..' back to root */
     138            0 :                 incr_link_count(cx, no, sdp->md.rooti, "\"..\"");
     139              :         }
     140            0 :         log_info(_("lost+found directory is dinode %"PRIu64" (0x%"PRIx64")\n"),
     141              :                  lf_dip->i_num.in_addr, lf_dip->i_num.in_addr);
     142            0 :         di = dirtree_find(cx, lf_dip->i_num.in_addr);
     143            0 :         if (di) {
     144            0 :                 log_info( _("Marking lost+found inode connected\n"));
     145            0 :                 di->checked = 1;
     146            0 :                 di = NULL;
     147              :         }
     148              : }
     149              : 
     150              : /* add_inode_to_lf - Add dir entry to lost+found for the inode
     151              :  * @ip: inode to add to lost + found
     152              :  *
     153              :  * This function adds an entry into the lost and found dir
     154              :  * for the given inode.  The name of the entry will be
     155              :  * "lost_<ip->i_num.no_addr>".
     156              :  *
     157              :  * Returns: 0 on success, -1 on failure.
     158              :  */
     159            0 : int add_inode_to_lf(struct fsck_cx *cx, struct lgfs2_inode *ip)
     160              : {
     161              :         char tmp_name[256];
     162              :         unsigned inode_type;
     163              :         struct lgfs2_inum no;
     164            0 :         int err = 0;
     165              :         uint32_t mode;
     166              : 
     167            0 :         make_sure_lf_exists(cx, ip);
     168            0 :         if (ip->i_num.in_addr == lf_dip->i_num.in_addr) {
     169            0 :                 log_err( _("Trying to add lost+found to itself...skipping"));
     170            0 :                 return 0;
     171              :         }
     172              : 
     173            0 :         mode = ip->i_mode & S_IFMT;
     174              : 
     175            0 :         switch (mode) {
     176            0 :         case S_IFDIR:
     177            0 :                 add_dotdot(cx, ip);
     178            0 :                 sprintf(tmp_name, "lost_dir_%"PRIu64, ip->i_num.in_addr);
     179            0 :                 inode_type = DT_DIR;
     180            0 :                 break;
     181            0 :         case S_IFREG:
     182            0 :                 sprintf(tmp_name, "lost_file_%"PRIu64, ip->i_num.in_addr);
     183            0 :                 inode_type = DT_REG;
     184            0 :                 break;
     185            0 :         case S_IFLNK:
     186            0 :                 sprintf(tmp_name, "lost_link_%"PRIu64, ip->i_num.in_addr);
     187            0 :                 inode_type = DT_LNK;
     188            0 :                 break;
     189            0 :         case S_IFBLK:
     190            0 :                 sprintf(tmp_name, "lost_blkdev_%"PRIu64, ip->i_num.in_addr);
     191            0 :                 inode_type = DT_BLK;
     192            0 :                 break;
     193            0 :         case S_IFCHR:
     194            0 :                 sprintf(tmp_name, "lost_chrdev_%"PRIu64, ip->i_num.in_addr);
     195            0 :                 inode_type = DT_CHR;
     196            0 :                 break;
     197            0 :         case S_IFIFO:
     198            0 :                 sprintf(tmp_name, "lost_fifo_%"PRIu64, ip->i_num.in_addr);
     199            0 :                 inode_type = DT_FIFO;
     200            0 :                 break;
     201            0 :         case S_IFSOCK:
     202            0 :                 sprintf(tmp_name, "lost_socket_%"PRIu64, ip->i_num.in_addr);
     203            0 :                 inode_type = DT_SOCK;
     204            0 :                 break;
     205            0 :         default:
     206            0 :                 sprintf(tmp_name, "lost_%"PRIu64, ip->i_num.in_addr);
     207            0 :                 inode_type = DT_REG;
     208            0 :                 break;
     209              :         }
     210              : 
     211            0 :         no = ip->i_num;
     212            0 :         err = lgfs2_dir_add(lf_dip, tmp_name, strlen(tmp_name), &no, inode_type);
     213            0 :         if (err) {
     214            0 :                 log_crit(_("Error adding directory %s: %s\n"),
     215              :                          tmp_name, strerror(errno));
     216            0 :                 exit(FSCK_ERROR);
     217              :         }
     218              : 
     219              :         /* This inode is linked from lost+found */
     220            0 :         incr_link_count(cx, no, lf_dip, _("from lost+found"));
     221              :         /* If it's a directory, lost+found is back-linked to it via .. */
     222            0 :         if (mode == S_IFDIR) {
     223            0 :                 no = lf_dip->i_num;
     224            0 :                 incr_link_count(cx, no, ip, _("to lost+found"));
     225              :         }
     226            0 :         log_notice(_("Added inode #%"PRIu64" (0x%"PRIx64") to lost+found\n"),
     227              :                    ip->i_num.in_addr, ip->i_num.in_addr);
     228            0 :         lgfs2_dinode_out(lf_dip, lf_dip->i_bh->b_data);
     229            0 :         lgfs2_bwrite(lf_dip->i_bh);
     230            0 :         return 0;
     231              : }
        

Generated by: LCOV version 2.0-1