diff options
author | Jeff Layton <jlayton@redhat.com> | 2012-09-19 09:22:30 -0400 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2012-09-24 22:46:32 -0400 |
commit | c5fab6f4f081afcfcd7c1d444d9b900d6ef3e50b (patch) | |
tree | bfec76b22571f283e85491ad6a20f1aaba757122 /fs/cifs | |
parent | f4e49cd2dce2ccac6feae64fbb4e90f7d8baf370 (diff) |
cifs: turn the pages list in cifs_readdata into an array
We'll need an array to put into a smb_rqst, so convert this into an array
instead of (ab)using the lru list_head.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/cifsglob.h | 3 | ||||
-rw-r--r-- | fs/cifs/file.c | 87 |
2 files changed, 52 insertions, 38 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 737289b50ca5..b70863ebedf2 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -977,12 +977,13 @@ struct cifs_readdata { | |||
977 | unsigned int bytes; | 977 | unsigned int bytes; |
978 | pid_t pid; | 978 | pid_t pid; |
979 | int result; | 979 | int result; |
980 | struct list_head pages; | ||
981 | struct work_struct work; | 980 | struct work_struct work; |
982 | int (*marshal_iov) (struct cifs_readdata *rdata, | 981 | int (*marshal_iov) (struct cifs_readdata *rdata, |
983 | unsigned int remaining); | 982 | unsigned int remaining); |
984 | unsigned int nr_iov; | 983 | unsigned int nr_iov; |
985 | struct kvec *iov; | 984 | struct kvec *iov; |
985 | unsigned int nr_pages; | ||
986 | struct page *pages[]; | ||
986 | }; | 987 | }; |
987 | 988 | ||
988 | struct cifs_writedata; | 989 | struct cifs_writedata; |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 61b7c834069f..6eaf48270c97 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -2419,13 +2419,13 @@ cifs_readdata_alloc(unsigned int nr_pages, work_func_t complete) | |||
2419 | if (!iov) | 2419 | if (!iov) |
2420 | return (struct cifs_readdata *)iov; | 2420 | return (struct cifs_readdata *)iov; |
2421 | 2421 | ||
2422 | rdata = kzalloc(sizeof(*rdata), GFP_KERNEL); | 2422 | rdata = kzalloc(sizeof(*rdata) + (sizeof(struct page *) * nr_pages), |
2423 | GFP_KERNEL); | ||
2423 | if (rdata != NULL) { | 2424 | if (rdata != NULL) { |
2424 | kref_init(&rdata->refcount); | 2425 | kref_init(&rdata->refcount); |
2425 | INIT_LIST_HEAD(&rdata->list); | 2426 | INIT_LIST_HEAD(&rdata->list); |
2426 | init_completion(&rdata->done); | 2427 | init_completion(&rdata->done); |
2427 | INIT_WORK(&rdata->work, complete); | 2428 | INIT_WORK(&rdata->work, complete); |
2428 | INIT_LIST_HEAD(&rdata->pages); | ||
2429 | rdata->iov = iov; | 2429 | rdata->iov = iov; |
2430 | } else { | 2430 | } else { |
2431 | kfree(iov); | 2431 | kfree(iov); |
@@ -2448,25 +2448,25 @@ cifs_readdata_release(struct kref *refcount) | |||
2448 | } | 2448 | } |
2449 | 2449 | ||
2450 | static int | 2450 | static int |
2451 | cifs_read_allocate_pages(struct list_head *list, unsigned int npages) | 2451 | cifs_read_allocate_pages(struct cifs_readdata *rdata, unsigned int nr_pages) |
2452 | { | 2452 | { |
2453 | int rc = 0; | 2453 | int rc = 0; |
2454 | struct page *page, *tpage; | 2454 | struct page *page; |
2455 | unsigned int i; | 2455 | unsigned int i; |
2456 | 2456 | ||
2457 | for (i = 0; i < npages; i++) { | 2457 | for (i = 0; i < nr_pages; i++) { |
2458 | page = alloc_page(GFP_KERNEL|__GFP_HIGHMEM); | 2458 | page = alloc_page(GFP_KERNEL|__GFP_HIGHMEM); |
2459 | if (!page) { | 2459 | if (!page) { |
2460 | rc = -ENOMEM; | 2460 | rc = -ENOMEM; |
2461 | break; | 2461 | break; |
2462 | } | 2462 | } |
2463 | list_add(&page->lru, list); | 2463 | rdata->pages[i] = page; |
2464 | } | 2464 | } |
2465 | 2465 | ||
2466 | if (rc) { | 2466 | if (rc) { |
2467 | list_for_each_entry_safe(page, tpage, list, lru) { | 2467 | for (i = 0; i < nr_pages; i++) { |
2468 | list_del(&page->lru); | 2468 | put_page(rdata->pages[i]); |
2469 | put_page(page); | 2469 | rdata->pages[i] = NULL; |
2470 | } | 2470 | } |
2471 | } | 2471 | } |
2472 | return rc; | 2472 | return rc; |
@@ -2475,13 +2475,13 @@ cifs_read_allocate_pages(struct list_head *list, unsigned int npages) | |||
2475 | static void | 2475 | static void |
2476 | cifs_uncached_readdata_release(struct kref *refcount) | 2476 | cifs_uncached_readdata_release(struct kref *refcount) |
2477 | { | 2477 | { |
2478 | struct page *page, *tpage; | ||
2479 | struct cifs_readdata *rdata = container_of(refcount, | 2478 | struct cifs_readdata *rdata = container_of(refcount, |
2480 | struct cifs_readdata, refcount); | 2479 | struct cifs_readdata, refcount); |
2480 | unsigned int i; | ||
2481 | 2481 | ||
2482 | list_for_each_entry_safe(page, tpage, &rdata->pages, lru) { | 2482 | for (i = 0; i < rdata->nr_pages; i++) { |
2483 | list_del(&page->lru); | 2483 | put_page(rdata->pages[i]); |
2484 | put_page(page); | 2484 | rdata->pages[i] = NULL; |
2485 | } | 2485 | } |
2486 | cifs_readdata_release(refcount); | 2486 | cifs_readdata_release(refcount); |
2487 | } | 2487 | } |
@@ -2525,17 +2525,18 @@ cifs_readdata_to_iov(struct cifs_readdata *rdata, const struct iovec *iov, | |||
2525 | int rc = 0; | 2525 | int rc = 0; |
2526 | struct iov_iter ii; | 2526 | struct iov_iter ii; |
2527 | size_t pos = rdata->offset - offset; | 2527 | size_t pos = rdata->offset - offset; |
2528 | struct page *page, *tpage; | ||
2529 | ssize_t remaining = rdata->bytes; | 2528 | ssize_t remaining = rdata->bytes; |
2530 | unsigned char *pdata; | 2529 | unsigned char *pdata; |
2530 | unsigned int i; | ||
2531 | 2531 | ||
2532 | /* set up iov_iter and advance to the correct offset */ | 2532 | /* set up iov_iter and advance to the correct offset */ |
2533 | iov_iter_init(&ii, iov, nr_segs, iov_length(iov, nr_segs), 0); | 2533 | iov_iter_init(&ii, iov, nr_segs, iov_length(iov, nr_segs), 0); |
2534 | iov_iter_advance(&ii, pos); | 2534 | iov_iter_advance(&ii, pos); |
2535 | 2535 | ||
2536 | *copied = 0; | 2536 | *copied = 0; |
2537 | list_for_each_entry_safe(page, tpage, &rdata->pages, lru) { | 2537 | for (i = 0; i < rdata->nr_pages; i++) { |
2538 | ssize_t copy; | 2538 | ssize_t copy; |
2539 | struct page *page = rdata->pages[i]; | ||
2539 | 2540 | ||
2540 | /* copy a whole page or whatever's left */ | 2541 | /* copy a whole page or whatever's left */ |
2541 | copy = min_t(ssize_t, remaining, PAGE_SIZE); | 2542 | copy = min_t(ssize_t, remaining, PAGE_SIZE); |
@@ -2555,9 +2556,6 @@ cifs_readdata_to_iov(struct cifs_readdata *rdata, const struct iovec *iov, | |||
2555 | iov_iter_advance(&ii, copy); | 2556 | iov_iter_advance(&ii, copy); |
2556 | } | 2557 | } |
2557 | } | 2558 | } |
2558 | |||
2559 | list_del(&page->lru); | ||
2560 | put_page(page); | ||
2561 | } | 2559 | } |
2562 | 2560 | ||
2563 | return rc; | 2561 | return rc; |
@@ -2568,13 +2566,12 @@ cifs_uncached_readv_complete(struct work_struct *work) | |||
2568 | { | 2566 | { |
2569 | struct cifs_readdata *rdata = container_of(work, | 2567 | struct cifs_readdata *rdata = container_of(work, |
2570 | struct cifs_readdata, work); | 2568 | struct cifs_readdata, work); |
2569 | unsigned int i; | ||
2571 | 2570 | ||
2572 | /* if the result is non-zero then the pages weren't kmapped */ | 2571 | /* if the result is non-zero then the pages weren't kmapped */ |
2573 | if (rdata->result == 0) { | 2572 | if (rdata->result == 0) { |
2574 | struct page *page; | 2573 | for (i = 0; i < rdata->nr_pages; i++) |
2575 | 2574 | kunmap(rdata->pages[i]); | |
2576 | list_for_each_entry(page, &rdata->pages, lru) | ||
2577 | kunmap(page); | ||
2578 | } | 2575 | } |
2579 | 2576 | ||
2580 | complete(&rdata->done); | 2577 | complete(&rdata->done); |
@@ -2586,10 +2583,13 @@ cifs_uncached_read_marshal_iov(struct cifs_readdata *rdata, | |||
2586 | unsigned int remaining) | 2583 | unsigned int remaining) |
2587 | { | 2584 | { |
2588 | int len = 0; | 2585 | int len = 0; |
2589 | struct page *page, *tpage; | 2586 | unsigned int i; |
2587 | unsigned int nr_pages = rdata->nr_pages; | ||
2590 | 2588 | ||
2591 | rdata->nr_iov = 1; | 2589 | rdata->nr_iov = 1; |
2592 | list_for_each_entry_safe(page, tpage, &rdata->pages, lru) { | 2590 | for (i = 0; i < nr_pages; i++) { |
2591 | struct page *page = rdata->pages[i]; | ||
2592 | |||
2593 | if (remaining >= PAGE_SIZE) { | 2593 | if (remaining >= PAGE_SIZE) { |
2594 | /* enough data to fill the page */ | 2594 | /* enough data to fill the page */ |
2595 | rdata->iov[rdata->nr_iov].iov_base = kmap(page); | 2595 | rdata->iov[rdata->nr_iov].iov_base = kmap(page); |
@@ -2616,7 +2616,8 @@ cifs_uncached_read_marshal_iov(struct cifs_readdata *rdata, | |||
2616 | remaining = 0; | 2616 | remaining = 0; |
2617 | } else { | 2617 | } else { |
2618 | /* no need to hold page hostage */ | 2618 | /* no need to hold page hostage */ |
2619 | list_del(&page->lru); | 2619 | rdata->pages[i] = NULL; |
2620 | rdata->nr_pages--; | ||
2620 | put_page(page); | 2621 | put_page(page); |
2621 | } | 2622 | } |
2622 | } | 2623 | } |
@@ -2675,11 +2676,12 @@ cifs_iovec_read(struct file *file, const struct iovec *iov, | |||
2675 | goto error; | 2676 | goto error; |
2676 | } | 2677 | } |
2677 | 2678 | ||
2678 | rc = cifs_read_allocate_pages(&rdata->pages, npages); | 2679 | rc = cifs_read_allocate_pages(rdata, npages); |
2679 | if (rc) | 2680 | if (rc) |
2680 | goto error; | 2681 | goto error; |
2681 | 2682 | ||
2682 | rdata->cfile = cifsFileInfo_get(open_file); | 2683 | rdata->cfile = cifsFileInfo_get(open_file); |
2684 | rdata->nr_pages = npages; | ||
2683 | rdata->offset = offset; | 2685 | rdata->offset = offset; |
2684 | rdata->bytes = cur_len; | 2686 | rdata->bytes = cur_len; |
2685 | rdata->pid = pid; | 2687 | rdata->pid = pid; |
@@ -2923,12 +2925,13 @@ int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) | |||
2923 | static void | 2925 | static void |
2924 | cifs_readv_complete(struct work_struct *work) | 2926 | cifs_readv_complete(struct work_struct *work) |
2925 | { | 2927 | { |
2928 | unsigned int i; | ||
2926 | struct cifs_readdata *rdata = container_of(work, | 2929 | struct cifs_readdata *rdata = container_of(work, |
2927 | struct cifs_readdata, work); | 2930 | struct cifs_readdata, work); |
2928 | struct page *page, *tpage; | ||
2929 | 2931 | ||
2930 | list_for_each_entry_safe(page, tpage, &rdata->pages, lru) { | 2932 | for (i = 0; i < rdata->nr_pages; i++) { |
2931 | list_del(&page->lru); | 2933 | struct page *page = rdata->pages[i]; |
2934 | |||
2932 | lru_cache_add_file(page); | 2935 | lru_cache_add_file(page); |
2933 | 2936 | ||
2934 | if (rdata->result == 0) { | 2937 | if (rdata->result == 0) { |
@@ -2943,6 +2946,7 @@ cifs_readv_complete(struct work_struct *work) | |||
2943 | cifs_readpage_to_fscache(rdata->mapping->host, page); | 2946 | cifs_readpage_to_fscache(rdata->mapping->host, page); |
2944 | 2947 | ||
2945 | page_cache_release(page); | 2948 | page_cache_release(page); |
2949 | rdata->pages[i] = NULL; | ||
2946 | } | 2950 | } |
2947 | kref_put(&rdata->refcount, cifs_readdata_release); | 2951 | kref_put(&rdata->refcount, cifs_readdata_release); |
2948 | } | 2952 | } |
@@ -2951,9 +2955,10 @@ static int | |||
2951 | cifs_readpages_marshal_iov(struct cifs_readdata *rdata, unsigned int remaining) | 2955 | cifs_readpages_marshal_iov(struct cifs_readdata *rdata, unsigned int remaining) |
2952 | { | 2956 | { |
2953 | int len = 0; | 2957 | int len = 0; |
2954 | struct page *page, *tpage; | 2958 | unsigned int i; |
2955 | u64 eof; | 2959 | u64 eof; |
2956 | pgoff_t eof_index; | 2960 | pgoff_t eof_index; |
2961 | unsigned int nr_pages = rdata->nr_pages; | ||
2957 | 2962 | ||
2958 | /* determine the eof that the server (probably) has */ | 2963 | /* determine the eof that the server (probably) has */ |
2959 | eof = CIFS_I(rdata->mapping->host)->server_eof; | 2964 | eof = CIFS_I(rdata->mapping->host)->server_eof; |
@@ -2961,7 +2966,9 @@ cifs_readpages_marshal_iov(struct cifs_readdata *rdata, unsigned int remaining) | |||
2961 | cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index); | 2966 | cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index); |
2962 | 2967 | ||
2963 | rdata->nr_iov = 1; | 2968 | rdata->nr_iov = 1; |
2964 | list_for_each_entry_safe(page, tpage, &rdata->pages, lru) { | 2969 | for (i = 0; i < nr_pages; i++) { |
2970 | struct page *page = rdata->pages[i]; | ||
2971 | |||
2965 | if (remaining >= PAGE_CACHE_SIZE) { | 2972 | if (remaining >= PAGE_CACHE_SIZE) { |
2966 | /* enough data to fill the page */ | 2973 | /* enough data to fill the page */ |
2967 | rdata->iov[rdata->nr_iov].iov_base = kmap(page); | 2974 | rdata->iov[rdata->nr_iov].iov_base = kmap(page); |
@@ -2996,18 +3003,20 @@ cifs_readpages_marshal_iov(struct cifs_readdata *rdata, unsigned int remaining) | |||
2996 | * fill them until the writes are flushed. | 3003 | * fill them until the writes are flushed. |
2997 | */ | 3004 | */ |
2998 | zero_user(page, 0, PAGE_CACHE_SIZE); | 3005 | zero_user(page, 0, PAGE_CACHE_SIZE); |
2999 | list_del(&page->lru); | ||
3000 | lru_cache_add_file(page); | 3006 | lru_cache_add_file(page); |
3001 | flush_dcache_page(page); | 3007 | flush_dcache_page(page); |
3002 | SetPageUptodate(page); | 3008 | SetPageUptodate(page); |
3003 | unlock_page(page); | 3009 | unlock_page(page); |
3004 | page_cache_release(page); | 3010 | page_cache_release(page); |
3011 | rdata->pages[i] = NULL; | ||
3012 | rdata->nr_pages--; | ||
3005 | } else { | 3013 | } else { |
3006 | /* no need to hold page hostage */ | 3014 | /* no need to hold page hostage */ |
3007 | list_del(&page->lru); | ||
3008 | lru_cache_add_file(page); | 3015 | lru_cache_add_file(page); |
3009 | unlock_page(page); | 3016 | unlock_page(page); |
3010 | page_cache_release(page); | 3017 | page_cache_release(page); |
3018 | rdata->pages[i] = NULL; | ||
3019 | rdata->nr_pages--; | ||
3011 | } | 3020 | } |
3012 | } | 3021 | } |
3013 | 3022 | ||
@@ -3065,6 +3074,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
3065 | * the rdata->pages, then we want them in increasing order. | 3074 | * the rdata->pages, then we want them in increasing order. |
3066 | */ | 3075 | */ |
3067 | while (!list_empty(page_list)) { | 3076 | while (!list_empty(page_list)) { |
3077 | unsigned int i; | ||
3068 | unsigned int bytes = PAGE_CACHE_SIZE; | 3078 | unsigned int bytes = PAGE_CACHE_SIZE; |
3069 | unsigned int expected_index; | 3079 | unsigned int expected_index; |
3070 | unsigned int nr_pages = 1; | 3080 | unsigned int nr_pages = 1; |
@@ -3135,13 +3145,16 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
3135 | rdata->bytes = bytes; | 3145 | rdata->bytes = bytes; |
3136 | rdata->pid = pid; | 3146 | rdata->pid = pid; |
3137 | rdata->marshal_iov = cifs_readpages_marshal_iov; | 3147 | rdata->marshal_iov = cifs_readpages_marshal_iov; |
3138 | list_splice_init(&tmplist, &rdata->pages); | 3148 | |
3149 | list_for_each_entry_safe(page, tpage, &tmplist, lru) { | ||
3150 | list_del(&page->lru); | ||
3151 | rdata->pages[rdata->nr_pages++] = page; | ||
3152 | } | ||
3139 | 3153 | ||
3140 | rc = cifs_retry_async_readv(rdata); | 3154 | rc = cifs_retry_async_readv(rdata); |
3141 | if (rc != 0) { | 3155 | if (rc != 0) { |
3142 | list_for_each_entry_safe(page, tpage, &rdata->pages, | 3156 | for (i = 0; i < rdata->nr_pages; i++) { |
3143 | lru) { | 3157 | page = rdata->pages[i]; |
3144 | list_del(&page->lru); | ||
3145 | lru_cache_add_file(page); | 3158 | lru_cache_add_file(page); |
3146 | unlock_page(page); | 3159 | unlock_page(page); |
3147 | page_cache_release(page); | 3160 | page_cache_release(page); |