mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 14:12:06 +00:00
xfs: update the unlinked list when repairing link counts
When we're repairing the link counts of a file, we must ensure either that the file has zero link count and is on the unlinked list; or that it has nonzero link count and is not on the unlinked list. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
e921533ef1
commit
669dfe883c
@ -17,6 +17,7 @@
|
||||
#include "xfs_iwalk.h"
|
||||
#include "xfs_ialloc.h"
|
||||
#include "xfs_sb.h"
|
||||
#include "xfs_ag.h"
|
||||
#include "scrub/scrub.h"
|
||||
#include "scrub/common.h"
|
||||
#include "scrub/repair.h"
|
||||
@ -36,6 +37,20 @@
|
||||
* inode is locked.
|
||||
*/
|
||||
|
||||
/* Remove an inode from the unlinked list. */
|
||||
STATIC int
|
||||
xrep_nlinks_iunlink_remove(
|
||||
struct xfs_scrub *sc)
|
||||
{
|
||||
struct xfs_perag *pag;
|
||||
int error;
|
||||
|
||||
pag = xfs_perag_get(sc->mp, XFS_INO_TO_AGNO(sc->mp, sc->ip->i_ino));
|
||||
error = xfs_iunlink_remove(sc->tp, pag, sc->ip);
|
||||
xfs_perag_put(pag);
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Correct the link count of the given inode. Because we have to grab locks
|
||||
* and resources in a certain order, it's possible that this will be a no-op.
|
||||
@ -99,16 +114,25 @@ xrep_nlinks_repair_inode(
|
||||
}
|
||||
|
||||
/*
|
||||
* We did not find any links to this inode. If the inode agrees, we
|
||||
* have nothing further to do. If not, the inode has a nonzero link
|
||||
* count and we don't have anywhere to graft the child onto. Dropping
|
||||
* a live inode's link count to zero can cause unexpected shutdowns in
|
||||
* inactivation, so leave it alone.
|
||||
* If this inode is linked from the directory tree and on the unlinked
|
||||
* list, remove it from the unlinked list.
|
||||
*/
|
||||
if (total_links == 0) {
|
||||
if (actual_nlink != 0)
|
||||
trace_xrep_nlinks_unfixable_inode(mp, ip, &obs);
|
||||
goto out_trans;
|
||||
if (total_links > 0 && xfs_inode_on_unlinked_list(ip)) {
|
||||
error = xrep_nlinks_iunlink_remove(sc);
|
||||
if (error)
|
||||
goto out_trans;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this inode is not linked from the directory tree yet not on the
|
||||
* unlinked list, put it on the unlinked list.
|
||||
*/
|
||||
if (total_links == 0 && !xfs_inode_on_unlinked_list(ip)) {
|
||||
error = xfs_iunlink(sc->tp, ip);
|
||||
if (error)
|
||||
goto out_trans;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
/* Commit the new link count if it changed. */
|
||||
|
Loading…
Reference in New Issue
Block a user