Exemplo n.º 1
0
int set_di_nlink(struct gfs2_inode *ip)
{
	struct inode_info *ii;
	struct dir_info *di;

	if (is_dir(&ip->i_di, ip->i_sbd->gfs1)) {
		di = dirtree_find(ip->i_di.di_num.no_addr);
		if (di == NULL) {
			log_err(_("Error: directory %lld (0x%llx) is not "
				  "in the dir_tree (set).\n"),
				(unsigned long long)ip->i_di.di_num.no_addr,
				(unsigned long long)ip->i_di.di_num.no_addr);
			return -1;
		}
		di->di_nlink = ip->i_di.di_nlink;
		return 0;
	}
	if (ip->i_di.di_nlink == 1) {
		link1_set(&nlink1map, ip->i_di.di_num.no_addr, 1);
		return 0;
	}
	/*log_debug( _("Setting link count to %u for %" PRIu64
	  " (0x%" PRIx64 ")\n"), count, inode_no, inode_no);*/
	/* If the list has entries, look for one that matches inode_no */
	ii = inodetree_find(ip->i_di.di_num.no_addr);
	if (!ii)
		ii = inodetree_insert(ip->i_di.di_num);
	if (ii)
		ii->di_nlink = ip->i_di.di_nlink;
	else
		return -1;
	return 0;
}
Exemplo n.º 2
0
int decr_link_count(uint64_t inode_no, uint64_t referenced_from, int gfs1,
		    const char *why)
{
	struct inode_info *ii = NULL;
	struct dir_info *di;

	di = dirtree_find(inode_no);
	if (di) {
		if (!di->counted_links) {
			log_debug( _("Dir (0x%llx)'s link to "
				     "(0x%llx) via %s is zero!\n"),
				   (unsigned long long)referenced_from,
				   (unsigned long long)inode_no, why);
			return 0;
		}
		di->counted_links--;
		whydecr(inode_no, why, referenced_from, di->counted_links);
		return 0;
	}

	ii = inodetree_find(inode_no);
	/* If the list has entries, look for one that matches
	 * inode_no */
	if (ii) {
		if (!ii->counted_links) {
			log_debug( _("Dir (0x%llx)'s link to "
			     "(0x%llx) via %s is zero!\n"),
			   (unsigned long long)referenced_from,
			   (unsigned long long)inode_no, why);
			return 0;
		}
		ii->counted_links--;
		whydecr(inode_no, why, referenced_from, ii->counted_links);
		return 0;
	}
	if (link1_type(&clink1map, inode_no) == 1) { /* 1 -> 0 */
		link1_set(&clink1map, inode_no, 0);
		whydecr(inode_no, why, referenced_from, 0);
		return 0;
	}

	log_debug( _("No match found when decrementing link for (0x%llx)!\n"),
		   (unsigned long long)inode_no);
	return -1;

}
Exemplo n.º 3
0
void make_sure_lf_exists(struct gfs2_inode *ip)
{
	struct dir_info *di;
	struct gfs2_sbd *sdp = ip->i_sbd;
	uint32_t mode;
	int root_entries;

	if (lf_dip)
		return;

	root_entries = sdp->md.rooti->i_di.di_entries;
	log_info( _("Locating/Creating lost+found directory\n"));

	/* if this is gfs1, we have to trick createi into using
	   no_formal_ino = no_addr, so we set next_inum to the
	   free block we're about to allocate. */
	if (sdp->gfs1)
		sdp->md.next_inum = find_free_blk(sdp);
	mode = (sdp->gfs1 ? DT2IF(GFS_FILE_DIR) : S_IFDIR) | 0700;
	if (sdp->gfs1)
		lf_dip = gfs_createi(sdp->md.rooti, "lost+found", mode, 0);
	else
		lf_dip = createi(sdp->md.rooti, "lost+found",
				 S_IFDIR | 0700, 0);
	if (lf_dip == NULL) {
		log_crit(_("Error creating lost+found: %s\n"),
			 strerror(errno));
		exit(FSCK_ERROR);
	}

	/* createi will have incremented the di_nlink link count for the root
	   directory.  We must set the nlink value in the hash table to keep
	   them in sync so that pass4 can detect and fix any descrepancies. */
	set_di_nlink(sdp->md.rooti);

	if (sdp->md.rooti->i_di.di_entries > root_entries) {
		lf_was_created = 1;
		/* This is a new lost+found directory, so set its block type
		   and increment link counts for the directories */
		/* FIXME: i'd feel better about this if fs_mkdir returned
		   whether it created a new directory or just found an old one,
		   and we used that instead of the bitmap_type to run this */
		dirtree_insert(lf_dip->i_di.di_num);
		/* Set the bitmap AFTER the dirtree insert so that function
		   check_n_fix_bitmap will realize it's a dinode and adjust
		   the rgrp counts properly. */
		fsck_bitmap_set(ip, lf_dip->i_di.di_num.no_addr,
				_("lost+found dinode"), GFS2_BLKST_DINODE);
		/* root inode links to lost+found */
		incr_link_count(sdp->md.rooti->i_di.di_num, lf_dip, _("root"));
		/* lost+found link for '.' from itself */
		incr_link_count(lf_dip->i_di.di_num, lf_dip, "\".\"");
		/* lost+found link for '..' back to root */
		incr_link_count(lf_dip->i_di.di_num, sdp->md.rooti, "\"..\"");
		if (sdp->gfs1)
			lf_dip->i_di.__pad1 = GFS_FILE_DIR;
	}
	log_info( _("lost+found directory is dinode %lld (0x%llx)\n"),
		  (unsigned long long)lf_dip->i_di.di_num.no_addr,
		  (unsigned long long)lf_dip->i_di.di_num.no_addr);
	di = dirtree_find(lf_dip->i_di.di_num.no_addr);
	if (di) {
		log_info( _("Marking lost+found inode connected\n"));
		di->checked = 1;
		di = NULL;
	}
}
Exemplo n.º 4
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);
	}
}
Exemplo n.º 5
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;
}