Commit 16005147 authored by Kent Overstreet's avatar Kent Overstreet
Browse files

bcachefs: Don't delete open files in online fsck

If a file is unlinked but still open, we don't want online fsck to
delete it - or fun inconsistencies will happen.

https://github.com/koverstreet/bcachefs/issues/727



Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 2c377d8a
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -177,6 +177,14 @@ static unsigned bch2_inode_hash(subvol_inum inum)
	return jhash_3words(inum.subvol, inum.inum >> 32, inum.inum, JHASH_INITVAL);
}

struct bch_inode_info *__bch2_inode_hash_find(struct bch_fs *c, subvol_inum inum)
{
	return to_bch_ei(ilookup5_nowait(c->vfs_sb,
					 bch2_inode_hash(inum),
					 bch2_iget5_test,
					 &inum));
}

static struct bch_inode_info *bch2_inode_insert(struct bch_fs *c, struct bch_inode_info *inode)
{
	subvol_inum inum = inode_inum(inode);
+7 −0
Original line number Diff line number Diff line
@@ -56,6 +56,8 @@ static inline subvol_inum inode_inum(struct bch_inode_info *inode)
	};
}

struct bch_inode_info *__bch2_inode_hash_find(struct bch_fs *, subvol_inum);

/*
 * Set if we've gotten a btree error for this inode, and thus the vfs inode and
 * btree inode may be inconsistent:
@@ -194,6 +196,11 @@ int bch2_vfs_init(void);

#define bch2_inode_update_after_write(_trans, _inode, _inode_u, _fields)	({ do {} while (0); })

static inline struct bch_inode_info *__bch2_inode_hash_find(struct bch_fs *c, subvol_inum inum)
{
	return NULL;
}

static inline void bch2_evict_subvolume_inodes(struct bch_fs *c,
					       snapshot_id_list *s) {}
static inline void bch2_vfs_exit(void) {}
+18 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include "darray.h"
#include "dirent.h"
#include "error.h"
#include "fs.h"
#include "fs-common.h"
#include "fsck.h"
#include "inode.h"
@@ -962,6 +963,22 @@ static int check_inode_dirent_inode(struct btree_trans *trans, struct bkey_s_c i
	return ret;
}

static bool bch2_inode_open(struct bch_fs *c, struct bpos p)
{
	subvol_inum inum = {
		.subvol = snapshot_t(c, p.snapshot)->subvol,
		.inum	= p.offset,
	};

	/* snapshot tree corruption, can't safely delete */
	if (!inum.subvol) {
		bch_err_ratelimited(c, "%s(): snapshot %u has no subvol", __func__, p.snapshot);
		return true;
	}

	return __bch2_inode_hash_find(c, inum) != NULL;
}

static int check_inode(struct btree_trans *trans,
		       struct btree_iter *iter,
		       struct bkey_s_c k,
@@ -1040,6 +1057,7 @@ static int check_inode(struct btree_trans *trans,
	}

	if (u.bi_flags & BCH_INODE_unlinked &&
	    !bch2_inode_open(c, k.k->p) &&
	    (!c->sb.clean ||
	     fsck_err(trans, inode_unlinked_but_clean,
		      "filesystem marked clean, but inode %llu unlinked",