Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 181815
b: refs/heads/master
c: 777df5a
h: refs/heads/master
i:
  181813: eed9daf
  181811: e1b3aba
  181807: c98637f
v: v3
  • Loading branch information
Dave Chinner committed Feb 6, 2010
1 parent 88bcffd commit b936d3f
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 30 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d5db0f97fbbeff11c88dec1aaf1536a975afbaeb
refs/heads/master: 777df5afdb26c71634edd60582be620ff94e87a0
81 changes: 62 additions & 19 deletions trunk/fs/xfs/linux-2.6/xfs_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -706,12 +706,43 @@ __xfs_inode_clear_reclaim_tag(
XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG);
}

/*
* Inodes in different states need to be treated differently, and the return
* value of xfs_iflush is not sufficient to get this right. The following table
* lists the inode states and the reclaim actions necessary for non-blocking
* reclaim:
*
*
* inode state iflush ret required action
* --------------- ---------- ---------------
* bad - reclaim
* shutdown EIO unpin and reclaim
* clean, unpinned 0 reclaim
* stale, unpinned 0 reclaim
* clean, pinned(*) 0 unpin and reclaim
* stale, pinned 0 unpin and reclaim
* dirty, async 0 block on flush lock, reclaim
* dirty, sync flush 0 block on flush lock, reclaim
*
* (*) dgc: I don't think the clean, pinned state is possible but it gets
* handled anyway given the order of checks implemented.
*
* Hence the order of actions after gaining the locks should be:
* bad => reclaim
* shutdown => unpin and reclaim
* pinned => unpin
* stale => reclaim
* clean => reclaim
* dirty => flush, wait and reclaim
*/
STATIC int
xfs_reclaim_inode(
struct xfs_inode *ip,
struct xfs_perag *pag,
int sync_mode)
{
int error;

/*
* The radix tree lock here protects a thread in xfs_iget from racing
* with us starting reclaim on the inode. Once we have the
Expand All @@ -729,30 +760,42 @@ xfs_reclaim_inode(
spin_unlock(&ip->i_flags_lock);
write_unlock(&pag->pag_ici_lock);

/*
* If the inode is still dirty, then flush it out. If the inode
* is not in the AIL, then it will be OK to flush it delwri as
* long as xfs_iflush() does not keep any references to the inode.
* We leave that decision up to xfs_iflush() since it has the
* knowledge of whether it's OK to simply do a delwri flush of
* the inode or whether we need to wait until the inode is
* pulled from the AIL.
* We get the flush lock regardless, though, just to make sure
* we don't free it while it is being flushed.
*/
xfs_ilock(ip, XFS_ILOCK_EXCL);
xfs_iflock(ip);

/*
* In the case of a forced shutdown we rely on xfs_iflush() to
* wait for the inode to be unpinned before returning an error.
*/
if (!is_bad_inode(VFS_I(ip)) && xfs_iflush(ip, sync_mode) == 0) {
/* synchronize with xfs_iflush_done */
xfs_iflock(ip);
xfs_ifunlock(ip);
if (is_bad_inode(VFS_I(ip)))
goto reclaim;
if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
xfs_iunpin_wait(ip);
goto reclaim;
}
if (xfs_ipincount(ip))
xfs_iunpin_wait(ip);
if (xfs_iflags_test(ip, XFS_ISTALE))
goto reclaim;
if (xfs_inode_clean(ip))
goto reclaim;

/* Now we have an inode that needs flushing */
error = xfs_iflush(ip, sync_mode);
if (!error) {
switch(sync_mode) {
case XFS_IFLUSH_DELWRI_ELSE_ASYNC:
case XFS_IFLUSH_DELWRI:
case XFS_IFLUSH_ASYNC:
case XFS_IFLUSH_DELWRI_ELSE_SYNC:
case XFS_IFLUSH_SYNC:
/* IO issued, synchronise with IO completion */
xfs_iflock(ip);
break;
default:
ASSERT(0);
break;
}
}

reclaim:
xfs_ifunlock(ip);
xfs_iunlock(ip, XFS_ILOCK_EXCL);
xfs_ireclaim(ip);
return 0;
Expand Down
11 changes: 1 addition & 10 deletions trunk/fs/xfs/xfs_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -2493,7 +2493,7 @@ __xfs_iunpin_wait(
wait_event(ip->i_ipin_wait, (atomic_read(&ip->i_pincount) == 0));
}

static inline void
void
xfs_iunpin_wait(
xfs_inode_t *ip)
{
Expand Down Expand Up @@ -2848,15 +2848,6 @@ xfs_iflush(
iip = ip->i_itemp;
mp = ip->i_mount;

/*
* If the inode isn't dirty, then just release the inode flush lock and
* do nothing.
*/
if (xfs_inode_clean(ip)) {
xfs_ifunlock(ip);
return 0;
}

/*
* We can't flush the inode until it is unpinned, so wait for it if we
* are allowed to block. We know noone new can pin it, because we are
Expand Down
1 change: 1 addition & 0 deletions trunk/fs/xfs/xfs_inode.h
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,7 @@ int xfs_iunlink(struct xfs_trans *, xfs_inode_t *);
void xfs_iext_realloc(xfs_inode_t *, int, int);
void xfs_ipin(xfs_inode_t *);
void xfs_iunpin(xfs_inode_t *);
void xfs_iunpin_wait(xfs_inode_t *);
int xfs_iflush(xfs_inode_t *, uint);
void xfs_ichgtime(xfs_inode_t *, int);
void xfs_lock_inodes(xfs_inode_t **, int, uint);
Expand Down

0 comments on commit b936d3f

Please sign in to comment.