Commit 5ecad6fd authored by Sage Weil's avatar Sage Weil

ceph: fix check for invalidate_mapping_pages success

We need to know whether there was any page left behind, and not the
return value (the total number of pages invalidated).  Look at the mapping
to see if we were successful or not.

Move it all into a helper to simplify the two callers.
Signed-off-by: default avatarYehuda Sadeh <yehuda@hq.newdream.net>
Signed-off-by: default avatarSage Weil <sage@newdream.net>
parent 2c27c9a5
...@@ -1361,6 +1361,41 @@ static int __mark_caps_flushing(struct inode *inode, ...@@ -1361,6 +1361,41 @@ static int __mark_caps_flushing(struct inode *inode,
return flushing; return flushing;
} }
/*
* try to invalidate mapping pages without blocking.
*/
static int mapping_is_empty(struct address_space *mapping)
{
struct page *page = find_get_page(mapping, 0);
if (!page)
return 1;
put_page(page);
return 0;
}
static int try_nonblocking_invalidate(struct inode *inode)
{
struct ceph_inode_info *ci = ceph_inode(inode);
u32 invalidating_gen = ci->i_rdcache_gen;
spin_unlock(&inode->i_lock);
invalidate_mapping_pages(&inode->i_data, 0, -1);
spin_lock(&inode->i_lock);
if (mapping_is_empty(&inode->i_data) &&
invalidating_gen == ci->i_rdcache_gen) {
/* success. */
dout("try_nonblocking_invalidate %p success\n", inode);
ci->i_rdcache_gen = 0;
ci->i_rdcache_revoking = 0;
return 0;
}
dout("try_nonblocking_invalidate %p failed\n", inode);
return -1;
}
/* /*
* Swiss army knife function to examine currently used and wanted * Swiss army knife function to examine currently used and wanted
* versus held caps. Release, flush, ack revoked caps to mds as * versus held caps. Release, flush, ack revoked caps to mds as
...@@ -1451,27 +1486,19 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags, ...@@ -1451,27 +1486,19 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags,
(file_wanted == 0 || /* no open files */ (file_wanted == 0 || /* no open files */
(revoking & CEPH_CAP_FILE_CACHE)) && /* or revoking cache */ (revoking & CEPH_CAP_FILE_CACHE)) && /* or revoking cache */
!tried_invalidate) { !tried_invalidate) {
u32 invalidating_gen = ci->i_rdcache_gen;
int ret;
dout("check_caps trying to invalidate on %p\n", inode); dout("check_caps trying to invalidate on %p\n", inode);
spin_unlock(&inode->i_lock); if (try_nonblocking_invalidate(inode) < 0) {
ret = invalidate_mapping_pages(&inode->i_data, 0, -1); if (revoking & CEPH_CAP_FILE_CACHE) {
spin_lock(&inode->i_lock); dout("check_caps queuing invalidate\n");
if (ret == 0 && invalidating_gen == ci->i_rdcache_gen) { queue_invalidate = 1;
/* success. */ ci->i_rdcache_revoking = ci->i_rdcache_gen;
ci->i_rdcache_gen = 0; } else {
ci->i_rdcache_revoking = 0; dout("check_caps failed to invalidate pages\n");
} else if (revoking & CEPH_CAP_FILE_CACHE) { /* we failed to invalidate pages. check these
dout("check_caps queuing invalidate\n"); caps again later. */
queue_invalidate = 1; force_requeue = 1;
ci->i_rdcache_revoking = ci->i_rdcache_gen; __cap_set_timeouts(mdsc, ci);
} else { }
dout("check_caps failed to invalidate pages\n");
/* we failed to invalidate pages. check these
caps again later. */
force_requeue = 1;
__cap_set_timeouts(mdsc, ci);
} }
tried_invalidate = 1; tried_invalidate = 1;
goto retry_locked; goto retry_locked;
...@@ -2184,7 +2211,6 @@ static int handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, ...@@ -2184,7 +2211,6 @@ static int handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
int revoked_rdcache = 0; int revoked_rdcache = 0;
int queue_invalidate = 0; int queue_invalidate = 0;
int tried_invalidate = 0; int tried_invalidate = 0;
int ret;
dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n", dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n",
inode, cap, mds, seq, ceph_cap_string(newcaps)); inode, cap, mds, seq, ceph_cap_string(newcaps));
...@@ -2199,24 +2225,16 @@ static int handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, ...@@ -2199,24 +2225,16 @@ static int handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
restart: restart:
if (((cap->issued & ~newcaps) & CEPH_CAP_FILE_CACHE) && if (((cap->issued & ~newcaps) & CEPH_CAP_FILE_CACHE) &&
!ci->i_wrbuffer_ref && !tried_invalidate) { !ci->i_wrbuffer_ref && !tried_invalidate) {
dout("CACHE invalidation\n");
spin_unlock(&inode->i_lock);
tried_invalidate = 1; tried_invalidate = 1;
if (try_nonblocking_invalidate(inode) == 0) {
ret = invalidate_mapping_pages(&inode->i_data, 0, -1); revoked_rdcache = 1;
spin_lock(&inode->i_lock); } else {
if (ret < 0) {
/* there were locked pages.. invalidate later /* there were locked pages.. invalidate later
in a separate thread. */ in a separate thread. */
if (ci->i_rdcache_revoking != ci->i_rdcache_gen) { if (ci->i_rdcache_revoking != ci->i_rdcache_gen) {
queue_invalidate = 1; queue_invalidate = 1;
ci->i_rdcache_revoking = ci->i_rdcache_gen; ci->i_rdcache_revoking = ci->i_rdcache_gen;
} }
} else {
/* we successfully invalidated those pages */
revoked_rdcache = 1;
ci->i_rdcache_gen = 0;
ci->i_rdcache_revoking = 0;
} }
goto restart; goto restart;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment