diff options
| -rw-r--r-- | fs/ceph/inode.c | 46 |
1 files changed, 45 insertions, 1 deletions
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index d7d5d4923772..7abe1aed819b 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <linux/namei.h> | 10 | #include <linux/namei.h> |
| 11 | #include <linux/writeback.h> | 11 | #include <linux/writeback.h> |
| 12 | #include <linux/vmalloc.h> | 12 | #include <linux/vmalloc.h> |
| 13 | #include <linux/pagevec.h> | ||
| 13 | 14 | ||
| 14 | #include "super.h" | 15 | #include "super.h" |
| 15 | #include "decode.h" | 16 | #include "decode.h" |
| @@ -1280,6 +1281,49 @@ void ceph_queue_invalidate(struct inode *inode) | |||
| 1280 | } | 1281 | } |
| 1281 | 1282 | ||
| 1282 | /* | 1283 | /* |
| 1284 | * invalidate any pages that are not dirty or under writeback. this | ||
| 1285 | * includes pages that are clean and mapped. | ||
| 1286 | */ | ||
| 1287 | static void ceph_invalidate_nondirty_pages(struct address_space *mapping) | ||
| 1288 | { | ||
| 1289 | struct pagevec pvec; | ||
| 1290 | pgoff_t next = 0; | ||
| 1291 | int i; | ||
| 1292 | |||
| 1293 | pagevec_init(&pvec, 0); | ||
| 1294 | while (pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) { | ||
| 1295 | for (i = 0; i < pagevec_count(&pvec); i++) { | ||
| 1296 | struct page *page = pvec.pages[i]; | ||
| 1297 | pgoff_t index; | ||
| 1298 | int skip_page = | ||
| 1299 | (PageDirty(page) || PageWriteback(page)); | ||
| 1300 | |||
| 1301 | if (!skip_page) | ||
| 1302 | skip_page = !trylock_page(page); | ||
| 1303 | |||
| 1304 | /* | ||
| 1305 | * We really shouldn't be looking at the ->index of an | ||
| 1306 | * unlocked page. But we're not allowed to lock these | ||
| 1307 | * pages. So we rely upon nobody altering the ->index | ||
| 1308 | * of this (pinned-by-us) page. | ||
| 1309 | */ | ||
| 1310 | index = page->index; | ||
| 1311 | if (index > next) | ||
| 1312 | next = index; | ||
| 1313 | next++; | ||
| 1314 | |||
| 1315 | if (skip_page) | ||
| 1316 | continue; | ||
| 1317 | |||
| 1318 | generic_error_remove_page(mapping, page); | ||
| 1319 | unlock_page(page); | ||
| 1320 | } | ||
| 1321 | pagevec_release(&pvec); | ||
| 1322 | cond_resched(); | ||
| 1323 | } | ||
| 1324 | } | ||
| 1325 | |||
| 1326 | /* | ||
| 1283 | * Invalidate inode pages in a worker thread. (This can't be done | 1327 | * Invalidate inode pages in a worker thread. (This can't be done |
| 1284 | * in the message handler context.) | 1328 | * in the message handler context.) |
| 1285 | */ | 1329 | */ |
| @@ -1305,7 +1349,7 @@ static void ceph_invalidate_work(struct work_struct *work) | |||
| 1305 | orig_gen = ci->i_rdcache_gen; | 1349 | orig_gen = ci->i_rdcache_gen; |
| 1306 | spin_unlock(&inode->i_lock); | 1350 | spin_unlock(&inode->i_lock); |
| 1307 | 1351 | ||
| 1308 | truncate_inode_pages(&inode->i_data, 0); | 1352 | ceph_invalidate_nondirty_pages(inode->i_mapping); |
| 1309 | 1353 | ||
| 1310 | spin_lock(&inode->i_lock); | 1354 | spin_lock(&inode->i_lock); |
| 1311 | if (orig_gen == ci->i_rdcache_gen) { | 1355 | if (orig_gen == ci->i_rdcache_gen) { |
