Skip to content

Commit 08e9cbe

Browse files
johnhubbardmartinkpetersen
authored andcommitted
scsi: st: Convert convert get_user_pages() --> pin_user_pages()
This code was using get_user_pages*(), in a "Case 1" scenario (Direct IO), using the categorization from [1]. That means that it's time to convert the get_user_pages*() + put_page() calls to pin_user_pages*() + unpin_user_pages() calls. There is some helpful background in [2]: basically, this is a small part of fixing a long-standing disconnect between pinning pages, and file systems' use of those pages. Note that this effectively changes the code's behavior as well: it now ultimately calls set_page_dirty_lock(), instead of SetPageDirty().This is probably more accurate. As Christoph Hellwig put it, "set_page_dirty() is only safe if we are dealing with a file backed page where we have reference on the inode it hangs off." [3] Also, this deletes one of the two FIXME comments (about refcounting), because there is nothing wrong with the refcounting at this point. [1] Documentation/core-api/pin_user_pages.rst [2] "Explicit pinning of user-space pages": https://lwn.net/Articles/807108/ [3] https://lore.kernel.org/r/[email protected] Link: https://lore.kernel.org/r/[email protected] Cc: "Kai Mäkisara (Kolumbus)" <[email protected]> Cc: Bart Van Assche <[email protected]> Cc: James E.J. Bottomley <[email protected]> Cc: Martin K. Petersen <[email protected]> Cc: [email protected] Acked-by: Kai Mäkisara <[email protected]> Signed-off-by: John Hubbard <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 987db58 commit 08e9cbe

File tree

1 file changed

+5
-15
lines changed

1 file changed

+5
-15
lines changed

drivers/scsi/st.c

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4921,7 +4921,7 @@ static int sgl_map_user_pages(struct st_buffer *STbp,
49214921
unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT;
49224922
unsigned long start = uaddr >> PAGE_SHIFT;
49234923
const int nr_pages = end - start;
4924-
int res, i, j;
4924+
int res, i;
49254925
struct page **pages;
49264926
struct rq_map_data *mdata = &STbp->map_data;
49274927

@@ -4943,7 +4943,7 @@ static int sgl_map_user_pages(struct st_buffer *STbp,
49434943

49444944
/* Try to fault in all of the necessary pages */
49454945
/* rw==READ means read from drive, write into memory area */
4946-
res = get_user_pages_fast(uaddr, nr_pages, rw == READ ? FOLL_WRITE : 0,
4946+
res = pin_user_pages_fast(uaddr, nr_pages, rw == READ ? FOLL_WRITE : 0,
49474947
pages);
49484948

49494949
/* Errors and no page mapped should return here */
@@ -4963,8 +4963,7 @@ static int sgl_map_user_pages(struct st_buffer *STbp,
49634963
return nr_pages;
49644964
out_unmap:
49654965
if (res > 0) {
4966-
for (j=0; j < res; j++)
4967-
put_page(pages[j]);
4966+
unpin_user_pages(pages, res);
49684967
res = 0;
49694968
}
49704969
kfree(pages);
@@ -4976,18 +4975,9 @@ static int sgl_map_user_pages(struct st_buffer *STbp,
49764975
static int sgl_unmap_user_pages(struct st_buffer *STbp,
49774976
const unsigned int nr_pages, int dirtied)
49784977
{
4979-
int i;
4980-
4981-
for (i=0; i < nr_pages; i++) {
4982-
struct page *page = STbp->mapped_pages[i];
4978+
/* FIXME: cache flush missing for rw==READ */
4979+
unpin_user_pages_dirty_lock(STbp->mapped_pages, nr_pages, dirtied);
49834980

4984-
if (dirtied)
4985-
SetPageDirty(page);
4986-
/* FIXME: cache flush missing for rw==READ
4987-
* FIXME: call the correct reference counting function
4988-
*/
4989-
put_page(page);
4990-
}
49914981
kfree(STbp->mapped_pages);
49924982
STbp->mapped_pages = NULL;
49934983

0 commit comments

Comments
 (0)