From: Sage Weil Date: Thu, 3 Apr 2008 16:41:42 +0000 (-0700) Subject: kclient: writepages work in progress X-Git-Tag: v0.2~215 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=bda8924c51481f705a67fc652c1ef495ab5a577e;p=ceph.git kclient: writepages work in progress --- diff --git a/src/kernel/addr.c b/src/kernel/addr.c index ef35e941d155..0702946fc807 100644 --- a/src/kernel/addr.c +++ b/src/kernel/addr.c @@ -152,16 +152,28 @@ static int ceph_writepages(struct address_space *mapping, pgoff_t index, end; int range_whole = 0; int should_loop = 1; + struct page *pages; + int nr_pages = 0, max_pages; struct pagevec pvec; int done = 0; int rc = 0; dout(10, "writepages on %p\n", inode); - /* if wsize is small, write 1 page at a time */ - if (client->mount_args.wsize && - client->mount_args.wsize < PAGE_CACHE_SIZE) - return generic_writepages(mapping, wbc); + if (client->mount_args.wsize) { + /* if wsize is small, write 1 page at a time */ + if (client->mount_args.wsize < PAGE_CACHE_SIZE) + return generic_writepages(mapping, wbc); + + /* larger page vector? */ + max_pages = (client->mount_args.wsize >> PAGE_CACHE_SHIFT); + if (pages > PAGEVEC_SIZE) { + pages = kmalloc(max_pages * sizeof(void *), GFP_KERNEL); + if (!pages) + return generic_writepages(mapping, wbc); + } + } + pagevec_init(&pvec, 0); /* ?? from cifs. */ /* @@ -172,7 +184,6 @@ static int ceph_writepages(struct address_space *mapping, */ /* where to start? */ - pagevec_init(&pvec, 0); if (wbc->range_cyclic) { index = mapping->writeback_index; /* Start from prev offset */ end = -1; @@ -193,20 +204,19 @@ retry: unsigned i; pgoff_t next; struct page *page; - int nr_pages, locked_pages; - - nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, - PAGECACHE_TAG_DIRTY, - min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1); - dout(30, "lookup_tag got %d pages\n", nr_pages); - if (!nr_pages) - break; - + int got_pages, locked_pages; + first = -1; next = 0; locked_pages = 0; - - for (i = 0; i < nr_pages; i++) { + + get_more_pages: + got_pages = pagevec_lookup_tag(&pvec, mapping, &index, + PAGECACHE_TAG_DIRTY, + min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1); + dout(30, "lookup_tag got %d pages\n", got_pages); + + for (i = 0; i < got_pages; i++) { page = pvec.pages[i]; if (first < 0) lock_page(page); @@ -253,6 +263,15 @@ retry: next = page->index + 1; } + if (pages && got_pages && locked_pages < max_pages) { + /* move pagevec into big pagevec */ + memcpy(pages + nr_pages, pvec.pages, + pvec.nr * sizeof(struct page *)); + nr_pages += pvec.nr; + pagevec_reinit(pvec); + goto get_more_pages; + } + /* did we get anything? */ if (first >= 0) { loff_t offset = pvec.pages[first]->index << @@ -302,6 +321,7 @@ retry: if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) mapping->writeback_index = index; + kfree(pvec); dout(10, "writepages done, rc = %d\n", rc); return rc; } diff --git a/src/kernel/osd_client.c b/src/kernel/osd_client.c index 46ed855ed9d9..1b5e30eae0c5 100644 --- a/src/kernel/osd_client.c +++ b/src/kernel/osd_client.c @@ -636,7 +636,7 @@ int ceph_osdc_sync_write(struct ceph_osd_client *osdc, ceph_ino_t ino, int ceph_osdc_writepages(struct ceph_osd_client *osdc, ceph_ino_t ino, struct ceph_file_layout *layout, loff_t off, loff_t len, - struct page **pagevec, int nr_pages) + struct page **pages, int nr_pages) { struct ceph_msg *reqm; struct ceph_osd_request_head *reqhead; @@ -660,8 +660,8 @@ int ceph_osdc_writepages(struct ceph_osd_client *osdc, ceph_ino_t ino, nr_pages = calc_pages_for(off, len); dout(10, "writepages %llu~%llu -> %d pages\n", off, len, nr_pages); - /* copy pagevec */ - memcpy(req->r_pages, pagevec, nr_pages * sizeof(struct page *)); + /* copy pages */ + memcpy(req->r_pages, pages, nr_pages * sizeof(struct page *)); reqm->pages = req->r_pages; reqm->nr_pages = req->r_nr_pages = nr_pages; reqm->hdr.data_len = len;