PATCH [2.4.0test10]: Kiobuf#00, moving code
Subsystems (3)
Hi,
Patch 00 for kiobufs: moves a chunk of code from mm/memory.c to fs/iobuf.c. The code concerned touches physical pages but has absolutely nothing to do with virtual memory, so doesn't deserve to be lumped with the map_user_kiobuf code.
--Stephen
fs/iobuf.c +127 -0
@@ -9,6 +9,7 @@#include <linux/iobuf.h> #include <linux/malloc.h> #include <linux/slab.h> +#include <linux/pagemap.h> static kmem_cache_t *kiobuf_cachep;
@@ -126,5 +127,131 @@remove_wait_queue (&kiobuf->wait_queue, &wait); } + +/* +* Unmap all of the pages referenced by a kiobuf. We release the pages, +* and unlock them if they were locked. +*/ + +void unmap_kiobuf (struct kiobuf *iobuf) +{ +int i; +struct page *map; + +for (i =0 ; i < iobuf->nr_pages; i++) { + map = iobuf->maplist[i]; +if (map) { +if (iobuf->locked) +UnlockPage (map); +__free_page (map); + } + } + + iobuf->nr_pages =0 ; + iobuf->locked =0 ; +} + + +/* +* Lock down all of the pages of a kiovec for IO. +* +* If any page is mapped twice in the kiovec, we return the error -EINVAL. +* +* The optional wait parameter causes the lock call to block until all +* pages can be locked if set. If wait==0, the lock operation is +* aborted if any locked pages are found and -EAGAIN is returned. +*/ + +int lock_kiovec (int nr,struct kiobuf *iovec[],int wait) +{ +struct kiobuf *iobuf; +int i, j; +struct page *page, **ppage; +int doublepage =0 ; +int repeat =0 ; + + repeat: + +for (i =0 ; i < nr; i++) { + iobuf = iovec[i]; + +if (iobuf->locked) +continue ; + iobuf->locked =1 ; + + ppage = iobuf->maplist; +for (j =0 ; j < iobuf->nr_pages; ppage++, j++) { + page = *ppage; +if (!page) +continue ; + +if (TryLockPage (page)) + goto retry; + } + } + +return 0 ; + + retry: + +/* +* We couldn't lock one of the pages. Undo the locking so far, +* wait on the page we got to, and try again. +*/ + +unlock_kiovec (nr, iovec); +if (!wait) +return -EAGAIN ; + +/* +* Did the release also unlock the page we got stuck on? +*/ +if (!PageLocked (page)) { +/* +* If so, we may well have the page mapped twice +* in the IO address range. Bad news. Of +* course, it _might_ just be a coincidence, +* but if it happens more than once, chances +* are we have a double-mapped page. +*/ +if (++doublepage >=3 ) +return -EINVAL ; + +/* Try again... */ +wait_on_page (page); + } + +if (++repeat <16 ) + goto repeat; +return -EAGAIN ; +} + +/* +* Unlock all of the pages of a kiovec after IO. +*/ + +int unlock_kiovec (int nr,struct kiobuf *iovec[]) +{ +struct kiobuf *iobuf; +int i, j; +struct page *page, **ppage; + +for (i =0 ; i < nr; i++) { + iobuf = iovec[i]; + +if (!iobuf->locked) +continue ; + iobuf->locked =0 ; + + ppage = iobuf->maplist; +for (j =0 ; j < iobuf->nr_pages; ppage++, j++) { + page = *ppage; +if (!page) +continue ; +UnlockPage (page); + } + } +return 0 ; +}
include/linux/iobuf.h +3 -3
@@ -61,9 +61,6 @@/* mm/memory.c */ int map_user_kiobuf (int rw,struct kiobuf *,unsigned long va,size_t len); -void unmap_kiobuf (struct kiobuf *iobuf); -int lock_kiovec (int nr,struct kiobuf *iovec[],int wait); -int unlock_kiovec (int nr,struct kiobuf *iovec[]);/* fs/iobuf.c */
@@ -75,6 +72,9 @@void free_kiovec (int nr,struct kiobuf **);int expand_kiobuf (struct kiobuf *,int );void kiobuf_wait_for_io (struct kiobuf *); +void unmap_kiobuf (struct kiobuf *iobuf); +int lock_kiovec (int nr,struct kiobuf *iovec[],int wait); +int unlock_kiovec (int nr,struct kiobuf *iovec[]);/* fs/buffer.c */
mm/memory.c +0 -126
132 lines not on this page · raw message