aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorFelix Blyakher <felixb@sgi.com>2004-08-20 07:15:48 +1000
committerNathan Scott <nathans@lips.borg.umn.edu>2004-08-20 07:15:48 +1000
commit7b5ad0c54f3a1c4867c695e7b0828d59d5b33292 (patch)
treeee3d09c48f48d5ec5f92b46082b0bc1e19eb30f8 /fs
parent102a69292a52b846d57840c12830755e2b2460d3 (diff)
downloadhistory-7b5ad0c54f3a1c4867c695e7b0828d59d5b33292.tar.gz
[XFS] Restored xfs_iflush_all, which is still used to finish reclaims.
SGI Modid: xfs-linux:xfs-kern:174868a Signed-off-by: Nathan Scott <nathans@sgi.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/xfs_inode.c102
-rw-r--r--fs/xfs/xfs_inode.h1
-rw-r--r--fs/xfs/xfs_mount.c2
3 files changed, 105 insertions, 0 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index da75ee97371162..e0561f39cd0ca3 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -3581,6 +3581,108 @@ corrupt_out:
/*
+ * Flush all inactive inodes in mp. Return true if no user references
+ * were found, false otherwise.
+ */
+int
+xfs_iflush_all(
+ xfs_mount_t *mp,
+ int flag)
+{
+ int busy;
+ int done;
+ int purged;
+ xfs_inode_t *ip;
+ vmap_t vmap;
+ vnode_t *vp;
+
+ busy = done = 0;
+ while (!done) {
+ purged = 0;
+ XFS_MOUNT_ILOCK(mp);
+ ip = mp->m_inodes;
+ if (ip == NULL) {
+ break;
+ }
+ do {
+ /* Make sure we skip markers inserted by sync */
+ if (ip->i_mount == NULL) {
+ ip = ip->i_mnext;
+ continue;
+ }
+
+ /*
+ * It's up to our caller to purge the root
+ * and quota vnodes later.
+ */
+ vp = XFS_ITOV_NULL(ip);
+
+ if (!vp) {
+ XFS_MOUNT_IUNLOCK(mp);
+ xfs_finish_reclaim(ip, 0, XFS_IFLUSH_ASYNC);
+ purged = 1;
+ break;
+ }
+
+ if (vn_count(vp) != 0) {
+ if (vn_count(vp) == 1 &&
+ (ip == mp->m_rootip ||
+ (mp->m_quotainfo &&
+ (ip->i_ino == mp->m_sb.sb_uquotino ||
+ ip->i_ino == mp->m_sb.sb_gquotino)))) {
+
+ ip = ip->i_mnext;
+ continue;
+ }
+ if (!(flag & XFS_FLUSH_ALL)) {
+ busy = 1;
+ done = 1;
+ break;
+ }
+ /*
+ * Ignore busy inodes but continue flushing
+ * others.
+ */
+ ip = ip->i_mnext;
+ continue;
+ }
+ /*
+ * Sample vp mapping while holding mp locked on MP
+ * systems, so we don't purge a reclaimed or
+ * nonexistent vnode. We break from the loop
+ * since we know that we modify
+ * it by pulling ourselves from it in xfs_reclaim()
+ * called via vn_purge() below. Set ip to the next
+ * entry in the list anyway so we'll know below
+ * whether we reached the end or not.
+ */
+ VMAP(vp, vmap);
+ XFS_MOUNT_IUNLOCK(mp);
+
+ vn_purge(vp, &vmap);
+
+ purged = 1;
+ break;
+ } while (ip != mp->m_inodes);
+ /*
+ * We need to distinguish between when we exit the loop
+ * after a purge and when we simply hit the end of the
+ * list. We can't use the (ip == mp->m_inodes) test,
+ * because when we purge an inode at the start of the list
+ * the next inode on the list becomes mp->m_inodes. That
+ * would cause such a test to bail out early. The purged
+ * variable tells us how we got out of the loop.
+ */
+ if (!purged) {
+ done = 1;
+ }
+ }
+ XFS_MOUNT_IUNLOCK(mp);
+ return !busy;
+}
+
+
+/*
* xfs_iaccess: check accessibility of inode for mode.
*/
int
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 0f262d71573c0c..f606073adf6bf5 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -527,6 +527,7 @@ void xfs_ipin(xfs_inode_t *);
void xfs_iunpin(xfs_inode_t *);
int xfs_iextents_copy(xfs_inode_t *, xfs_bmbt_rec_t *, int);
int xfs_iflush(xfs_inode_t *, uint);
+int xfs_iflush_all(struct xfs_mount *, int);
int xfs_iaccess(xfs_inode_t *, mode_t, cred_t *);
uint xfs_iroundup(uint);
void xfs_ichgtime(xfs_inode_t *, int);
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index d2a73e9b00c4dd..de1b850b154896 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -1074,6 +1074,8 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
int64_t fsid;
#endif
+ xfs_iflush_all(mp, XFS_FLUSH_ALL);
+
XFS_QM_DQPURGEALL(mp,
XFS_QMOPT_UQUOTA | XFS_QMOPT_GQUOTA | XFS_QMOPT_UMOUNTING);