LCOV - code coverage report
Current view: top level - fsck - lost_n_found.c (source / functions) Hit Total Coverage
Test: gfs2-utils.info Lines: 0 119 0.0 %
Date: 2023-10-25 12:04:14 Functions: 0 3 0.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 1.14