From mboxrd@z Thu Jan 1 00:00:00 1970 From: Martin Jambor Subject: pagevec_lookup_tag() and pagevec_release() substitutes and an OOM Date: Wed, 8 Feb 2006 01:29:44 +0100 Message-ID: <9615ac9b0602071629y5054dc07w8d1f18e070b0b01f@mail.gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7BIT Return-path: Received: from xproxy.gmail.com ([66.249.82.207]:25308 "EHLO xproxy.gmail.com") by vger.kernel.org with ESMTP id S1030314AbWBHA3r convert rfc822-to-8bit (ORCPT ); Tue, 7 Feb 2006 19:29:47 -0500 Received: by xproxy.gmail.com with SMTP id s14so1052896wxc for ; Tue, 07 Feb 2006 16:29:44 -0800 (PST) To: Linux FS Development List Content-Disposition: inline Sender: linux-fsdevel-owner@vger.kernel.org List-Id: linux-fsdevel.vger.kernel.org Hi all, I am implementing aops->writepages of a filesystem and for various reasons I cannot use mpage_writepages. On the other hand, I would like to do be able to get a vector of pages and process it page by page (in my way) just like mpage_writepages gets pages. However, pagevec functions are not exported (I don't understand why) and so I cannot use them directly by my module but rather I had to do a bit of cutting and pasting from 2.6.14 kernel source :-( So my approach was to use a plain array of pointers to pages and instead of calling unsigned pagevec_lookup_tag(struct pagevec *pvec, struct address_space *mapping, pgoff_t *index, int tag, unsigned nr_pages) I use my own function which is basically copied find_get_pages_tag() (which also isn't exported): static unsigned my_find_get_pages_tag(struct address_space *mapping, pgoff_t *index, int tag, unsigned int nr_pages, struct page **pages) { unsigned int i; unsigned int ret; read_lock_irq(&mapping->tree_lock); ret = radix_tree_gang_lookup_tag(&mapping->page_tree, (void **)pages, *index, nr_pages, tag); for (i = 0; i < ret; i++) page_cache_get(pages[i]); if (ret) *index = pages[ret - 1]->index + 1; read_unlock_irq(&mapping->tree_lock); return ret; } instead of pagevec_release() I use a much simpler function: static void release_pagearray(struct page **pages, unsigned int nr_pages) { unsigned i; for (i = 0; i < nr_pages; i++) page_cache_release(pages[i]); } Everything seems to be working well except that I get an OOM. The free and vmstat utilities show that "cache" is the only thing that is getting unreasonably bigger. There are many reasons why I believe the page cache pages are still somehow pinned down by my code and cannot be freed when I am done with them. I must admit that I find it quite difficult to uderstand the pagevec source and if someone knew what I am doing wrong, I would be very grateful. (Yes, I have carefully checked several times very carefully that I set&clear writeback as indicated in Documentation/filesystmes/Locking and how it is done by mpage_writepages.) Thank you very much in advance for any comment. Martin