xfs: invalidate dentries for a file before moving it to the orphanage
Invalidate the cached dentries that point to the file that we're moving to lost+found before we actually move it. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
6d335233fe
commit
5e1c7d0b29
@ -434,16 +434,17 @@ xrep_adoption_check_dcache(
|
|||||||
{
|
{
|
||||||
struct qstr qname = QSTR_INIT(adopt->xname->name,
|
struct qstr qname = QSTR_INIT(adopt->xname->name,
|
||||||
adopt->xname->len);
|
adopt->xname->len);
|
||||||
|
struct xfs_scrub *sc = adopt->sc;
|
||||||
struct dentry *d_orphanage, *d_child;
|
struct dentry *d_orphanage, *d_child;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
d_orphanage = d_find_alias(VFS_I(adopt->sc->orphanage));
|
d_orphanage = d_find_alias(VFS_I(sc->orphanage));
|
||||||
if (!d_orphanage)
|
if (!d_orphanage)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
d_child = d_hash_and_lookup(d_orphanage, &qname);
|
d_child = d_hash_and_lookup(d_orphanage, &qname);
|
||||||
if (d_child) {
|
if (d_child) {
|
||||||
trace_xrep_adoption_check_child(adopt->sc->mp, d_child);
|
trace_xrep_adoption_check_child(sc->mp, d_child);
|
||||||
|
|
||||||
if (d_is_positive(d_child)) {
|
if (d_is_positive(d_child)) {
|
||||||
ASSERT(d_is_negative(d_child));
|
ASSERT(d_is_negative(d_child));
|
||||||
@ -454,33 +455,15 @@ xrep_adoption_check_dcache(
|
|||||||
}
|
}
|
||||||
|
|
||||||
dput(d_orphanage);
|
dput(d_orphanage);
|
||||||
if (error)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Do we need to update d_parent of the dentry for the file being
|
|
||||||
* repaired? There shouldn't be a hashed dentry with a parent since
|
|
||||||
* the file had nonzero nlink but wasn't connected to any parent dir.
|
|
||||||
*/
|
|
||||||
d_child = d_find_alias(VFS_I(adopt->sc->ip));
|
|
||||||
if (!d_child)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
trace_xrep_adoption_check_alias(adopt->sc->mp, d_child);
|
|
||||||
|
|
||||||
if (d_child->d_parent && !d_unhashed(d_child)) {
|
|
||||||
ASSERT(d_child->d_parent == NULL || d_unhashed(d_child));
|
|
||||||
error = -EFSCORRUPTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
dput(d_child);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove all negative dentries from the dcache. There should not be any
|
* Invalidate all dentries for the name that was added to the orphanage
|
||||||
* positive entries, since we've maintained our lock on the orphanage
|
* directory, and all dentries pointing to the child inode that was moved.
|
||||||
* directory.
|
*
|
||||||
|
* There should not be any positive entries for the name, since we've
|
||||||
|
* maintained our lock on the orphanage directory.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
xrep_adoption_zap_dcache(
|
xrep_adoption_zap_dcache(
|
||||||
@ -488,15 +471,17 @@ xrep_adoption_zap_dcache(
|
|||||||
{
|
{
|
||||||
struct qstr qname = QSTR_INIT(adopt->xname->name,
|
struct qstr qname = QSTR_INIT(adopt->xname->name,
|
||||||
adopt->xname->len);
|
adopt->xname->len);
|
||||||
|
struct xfs_scrub *sc = adopt->sc;
|
||||||
struct dentry *d_orphanage, *d_child;
|
struct dentry *d_orphanage, *d_child;
|
||||||
|
|
||||||
d_orphanage = d_find_alias(VFS_I(adopt->sc->orphanage));
|
/* Invalidate all dentries for the adoption name */
|
||||||
|
d_orphanage = d_find_alias(VFS_I(sc->orphanage));
|
||||||
if (!d_orphanage)
|
if (!d_orphanage)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
d_child = d_hash_and_lookup(d_orphanage, &qname);
|
d_child = d_hash_and_lookup(d_orphanage, &qname);
|
||||||
while (d_child != NULL) {
|
while (d_child != NULL) {
|
||||||
trace_xrep_adoption_invalidate_child(adopt->sc->mp, d_child);
|
trace_xrep_adoption_invalidate_child(sc->mp, d_child);
|
||||||
|
|
||||||
ASSERT(d_is_negative(d_child));
|
ASSERT(d_is_negative(d_child));
|
||||||
d_invalidate(d_child);
|
d_invalidate(d_child);
|
||||||
@ -505,6 +490,14 @@ xrep_adoption_zap_dcache(
|
|||||||
}
|
}
|
||||||
|
|
||||||
dput(d_orphanage);
|
dput(d_orphanage);
|
||||||
|
|
||||||
|
/* Invalidate all the dentries pointing down to this file. */
|
||||||
|
while ((d_child = d_find_alias(VFS_I(sc->ip))) != NULL) {
|
||||||
|
trace_xrep_adoption_invalidate_child(sc->mp, d_child);
|
||||||
|
|
||||||
|
d_invalidate(d_child);
|
||||||
|
dput(d_child);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3265,8 +3265,6 @@ DEFINE_EVENT(xrep_dentry_class, name, \
|
|||||||
TP_PROTO(struct xfs_mount *mp, const struct dentry *dentry), \
|
TP_PROTO(struct xfs_mount *mp, const struct dentry *dentry), \
|
||||||
TP_ARGS(mp, dentry))
|
TP_ARGS(mp, dentry))
|
||||||
DEFINE_REPAIR_DENTRY_EVENT(xrep_adoption_check_child);
|
DEFINE_REPAIR_DENTRY_EVENT(xrep_adoption_check_child);
|
||||||
DEFINE_REPAIR_DENTRY_EVENT(xrep_adoption_check_alias);
|
|
||||||
DEFINE_REPAIR_DENTRY_EVENT(xrep_adoption_check_dentry);
|
|
||||||
DEFINE_REPAIR_DENTRY_EVENT(xrep_adoption_invalidate_child);
|
DEFINE_REPAIR_DENTRY_EVENT(xrep_adoption_invalidate_child);
|
||||||
DEFINE_REPAIR_DENTRY_EVENT(xrep_dirtree_delete_child);
|
DEFINE_REPAIR_DENTRY_EVENT(xrep_dirtree_delete_child);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user