Commit c319b58b13bb22f9a2478825b06c641c825f51ec
Committed by
Lachlan McIlroy
1 parent
98ce2b5b1b
Exists in
master
and in
39 other branches
[XFS] Make xfs_bulkstat() to report unlinked but referenced inodes
We need xfs_bulkstat() to report inode stat for inodes with link count zero but reference count non zero. The fix here: http://oss.sgi.com/archives/xfs/2007-09/msg00266.html changed this behavior and made xfs_bulkstat() to filter all unlinked inodes including those that are not destroyed yet but held by reference. The attached patch returns back to the original behavior by marking the on-disk inode buffer "dirty" when di_mode is cleared (at that time both inode link and reference counter are zero). SGI-PV: 972004 SGI-Modid: xfs-linux-melb:xfs-kern:29914a Signed-off-by: Vlad Apostolov <vapo@sgi.com> Signed-off-by: David Chinner <dgc@sgi.com> Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
Showing 2 changed files with 27 additions and 20 deletions Side-by-side Diff
fs/xfs/xfs_inode.c
... | ... | @@ -1953,24 +1953,6 @@ |
1953 | 1953 | ASSERT(agi->agi_unlinked[bucket_index]); |
1954 | 1954 | ASSERT(be32_to_cpu(agi->agi_unlinked[bucket_index]) != agino); |
1955 | 1955 | |
1956 | - error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0); | |
1957 | - if (error) | |
1958 | - return error; | |
1959 | - | |
1960 | - /* | |
1961 | - * Clear the on-disk di_nlink. This is to prevent xfs_bulkstat | |
1962 | - * from picking up this inode when it is reclaimed (its incore state | |
1963 | - * initialzed but not flushed to disk yet). The in-core di_nlink is | |
1964 | - * already cleared in xfs_droplink() and a corresponding transaction | |
1965 | - * logged. The hack here just synchronizes the in-core to on-disk | |
1966 | - * di_nlink value in advance before the actual inode sync to disk. | |
1967 | - * This is OK because the inode is already unlinked and would never | |
1968 | - * change its di_nlink again for this inode generation. | |
1969 | - * This is a temporary hack that would require a proper fix | |
1970 | - * in the future. | |
1971 | - */ | |
1972 | - dip->di_core.di_nlink = 0; | |
1973 | - | |
1974 | 1956 | if (be32_to_cpu(agi->agi_unlinked[bucket_index]) != NULLAGINO) { |
1975 | 1957 | /* |
1976 | 1958 | * There is already another inode in the bucket we need |
... | ... | @@ -1978,6 +1960,10 @@ |
1978 | 1960 | * Here we put the head pointer into our next pointer, |
1979 | 1961 | * and then we fall through to point the head at us. |
1980 | 1962 | */ |
1963 | + error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0); | |
1964 | + if (error) | |
1965 | + return error; | |
1966 | + | |
1981 | 1967 | ASSERT(be32_to_cpu(dip->di_next_unlinked) == NULLAGINO); |
1982 | 1968 | /* both on-disk, don't endian flip twice */ |
1983 | 1969 | dip->di_next_unlinked = agi->agi_unlinked[bucket_index]; |
... | ... | @@ -2367,6 +2353,8 @@ |
2367 | 2353 | int error; |
2368 | 2354 | int delete; |
2369 | 2355 | xfs_ino_t first_ino; |
2356 | + xfs_dinode_t *dip; | |
2357 | + xfs_buf_t *ibp; | |
2370 | 2358 | |
2371 | 2359 | ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE)); |
2372 | 2360 | ASSERT(ip->i_transp == tp); |
2373 | 2361 | |
... | ... | @@ -2402,7 +2390,26 @@ |
2402 | 2390 | * by reincarnations of this inode. |
2403 | 2391 | */ |
2404 | 2392 | ip->i_d.di_gen++; |
2393 | + | |
2405 | 2394 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
2395 | + | |
2396 | + error = xfs_itobp(ip->i_mount, tp, ip, &dip, &ibp, 0, 0); | |
2397 | + if (error) | |
2398 | + return error; | |
2399 | + | |
2400 | + /* | |
2401 | + * Clear the on-disk di_mode. This is to prevent xfs_bulkstat | |
2402 | + * from picking up this inode when it is reclaimed (its incore state | |
2403 | + * initialzed but not flushed to disk yet). The in-core di_mode is | |
2404 | + * already cleared and a corresponding transaction logged. | |
2405 | + * The hack here just synchronizes the in-core to on-disk | |
2406 | + * di_mode value in advance before the actual inode sync to disk. | |
2407 | + * This is OK because the inode is already unlinked and would never | |
2408 | + * change its di_mode again for this inode generation. | |
2409 | + * This is a temporary hack that would require a proper fix | |
2410 | + * in the future. | |
2411 | + */ | |
2412 | + dip->di_core.di_mode = 0; | |
2406 | 2413 | |
2407 | 2414 | if (delete) { |
2408 | 2415 | xfs_ifree_cluster(ip, tp, first_ino); |
fs/xfs/xfs_itable.c
... | ... | @@ -291,7 +291,7 @@ |
291 | 291 | dip = (xfs_dinode_t *) |
292 | 292 | xfs_buf_offset(bp, clustidx << mp->m_sb.sb_inodelog); |
293 | 293 | /* |
294 | - * Check the buffer containing the on-disk inode for di_nlink == 0. | |
294 | + * Check the buffer containing the on-disk inode for di_mode == 0. | |
295 | 295 | * This is to prevent xfs_bulkstat from picking up just reclaimed |
296 | 296 | * inodes that have their in-core state initialized but not flushed |
297 | 297 | * to disk yet. This is a temporary hack that would require a proper |
... | ... | @@ -299,7 +299,7 @@ |
299 | 299 | */ |
300 | 300 | if (be16_to_cpu(dip->di_core.di_magic) != XFS_DINODE_MAGIC || |
301 | 301 | !XFS_DINODE_GOOD_VERSION(dip->di_core.di_version) || |
302 | - !dip->di_core.di_nlink) | |
302 | + !dip->di_core.di_mode) | |
303 | 303 | return 0; |
304 | 304 | if (flags & BULKSTAT_FG_QUICK) { |
305 | 305 | *dipp = dip; |