Пример #1
0
static void add_dotdot(struct gfs2_inode *ip)
{
	struct dir_info *di;
	struct gfs2_sbd *sdp = ip->i_sbd;
	int err;

	log_info( _("Adding .. entry to directory %llu (0x%llx) pointing back "
		    "to lost+found\n"),
		  (unsigned long long)ip->i_di.di_num.no_addr,
		  (unsigned long long)ip->i_di.di_num.no_addr);

	/* If there's a pre-existing .. directory entry, we have to
	   back out the links. */
	di = dirtree_find(ip->i_di.di_num.no_addr);
	if (di && valid_block(sdp, di->dotdot_parent.no_addr)) {
		struct gfs2_inode *dip;

		log_debug(_("Directory (0x%llx) already had a "
			    "\"..\" link to (0x%llx).\n"),
			  (unsigned long long)ip->i_di.di_num.no_addr,
			  (unsigned long long)di->dotdot_parent.no_addr);
		dip = fsck_load_inode(sdp, di->dotdot_parent.no_addr);
		if (dip->i_di.di_num.no_formal_ino ==
		    di->dotdot_parent.no_formal_ino) {
			decr_link_count(di->dotdot_parent.no_addr,
					ip->i_di.di_num.no_addr, sdp->gfs1,
					_(".. unlinked, moving to lost+found"));
			if (dip->i_di.di_nlink > 0) {
			  dip->i_di.di_nlink--;
			  set_di_nlink(dip); /* keep inode tree in sync */
			  log_debug(_("Decrementing its links to %d\n"),
				    dip->i_di.di_nlink);
			  bmodified(dip->i_bh);
			} else if (!dip->i_di.di_nlink) {
			  log_debug(_("Its link count is zero.\n"));
			} else {
			  log_debug(_("Its link count is %d!  Changing "
				      "it to 0.\n"), dip->i_di.di_nlink);
			  dip->i_di.di_nlink = 0;
			  set_di_nlink(dip); /* keep inode tree in sync */
			  bmodified(dip->i_bh);
			}
		} else {
			log_debug(_("Directory (0x%llx)'s link to parent "
				    "(0x%llx) had a formal inode discrepancy: "
				    "was 0x%llx, expected 0x%llx\n"),
				  (unsigned long long)ip->i_di.di_num.no_addr,
				  (unsigned long long)di->dotdot_parent.no_addr,
				  di->dotdot_parent.no_formal_ino,
				  dip->i_di.di_num.no_formal_ino);
			log_debug(_("The parent directory was not changed.\n"));
		}
		fsck_inode_put(&dip);
		di = NULL;
	} else {
		if (di)
			log_debug(_("Couldn't find a valid \"..\" entry "
				    "for orphan directory (0x%llx): "
				    "'..' = 0x%llx\n"),
				  (unsigned long long)ip->i_di.di_num.no_addr,
				  (unsigned long long)di->dotdot_parent.no_addr);
		else
			log_debug(_("Couldn't find directory (0x%llx) "
				    "in directory tree.\n"),
				  (unsigned long long)ip->i_di.di_num.no_addr);
	}
	if (gfs2_dirent_del(ip, "..", 2))
		log_warn( _("add_inode_to_lf:  Unable to remove "
			    "\"..\" directory entry.\n"));

	err = dir_add(ip, "..", 2, &(lf_dip->i_di.di_num),
		      (sdp->gfs1 ? GFS_FILE_DIR : DT_DIR));
	if (err) {
		log_crit(_("Error adding .. directory: %s\n"),
			 strerror(errno));
		exit(FSCK_ERROR);
	}
}
Пример #2
0
int incr_link_count(struct gfs2_inum no, struct gfs2_inode *ip,
		    const char *why)
{
	struct inode_info *ii = NULL;
	uint64_t referenced_from = ip ? ip->i_di.di_num.no_addr : 0;
	struct dir_info *di;
	struct gfs2_inode *link_ip;

	di = dirtree_find(no.no_addr);
	if (di) {
		if (di->dinode.no_formal_ino != no.no_formal_ino)
			return 1;

		di->counted_links++;
		whyincr(no.no_addr, why, referenced_from, di->counted_links);
		return 0;
	}
	ii = inodetree_find(no.no_addr);
	/* If the list has entries, look for one that matches inode_no */
	if (ii) {
		if (ii->di_num.no_formal_ino != no.no_formal_ino)
			return 1;

		ii->counted_links++;
		whyincr(no.no_addr, why, referenced_from, ii->counted_links);
		return 0;
	}
	if (link1_type(&clink1map, no.no_addr) != 1) {
		link1_set(&clink1map, no.no_addr, 1);
		whyincr(no.no_addr, why, referenced_from, 1);
		return 0;
	}

	link_ip = fsck_load_inode(ip->i_sbd, no.no_addr);
	/* Check formal ino against dinode before adding to inode tree. */
	if (no.no_formal_ino != ip->i_di.di_num.no_formal_ino) {
		fsck_inode_put(&link_ip);
		return 1;
	}
	/* Move it from the link1 maps to a real inode tree entry */
	link1_set(&nlink1map, no.no_addr, 0);
	link1_set(&clink1map, no.no_addr, 0);

	/* If no match was found, it must be a hard link. In theory, it can't
	   be a duplicate because those were resolved in pass1b. Add a new
	   inodetree entry and set its counted links to 2 */
	ii = inodetree_insert(no);
	if (!ii) {
		log_debug( _("Ref: (0x%llx) Error incrementing link for "
			     "(0x%llx)!\n"),
			   (unsigned long long)referenced_from,
			   (unsigned long long)no.no_addr);
		fsck_inode_put(&link_ip);
		return -1;
	}
	ii->di_num = link_ip->i_di.di_num;
	fsck_inode_put(&link_ip);
	ii->di_nlink = 1; /* Must be 1 or it wouldn't have gotten into the
			     nlink1map */
	ii->counted_links = 2;
	whyincr(no.no_addr, why, referenced_from, ii->counted_links);
	return 0;
}