~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to fs/nfs/pagelist.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
#include <linux/nfs_mount.h>
21
21
 
22
22
#include "internal.h"
 
23
#include "pnfs.h"
23
24
 
24
25
static struct kmem_cache *nfs_page_cachep;
25
26
 
134
135
                nfs_unlock_request(req);
135
136
}
136
137
 
137
 
/**
 
138
/*
138
139
 * nfs_clear_request - Free up all resources allocated to the request
139
140
 * @req:
140
141
 *
141
142
 * Release page and open context resources associated with a read/write
142
143
 * request after it has completed.
143
144
 */
144
 
void nfs_clear_request(struct nfs_page *req)
 
145
static void nfs_clear_request(struct nfs_page *req)
145
146
{
146
147
        struct page *page = req->wb_page;
147
148
        struct nfs_open_context *ctx = req->wb_context;
203
204
                        TASK_UNINTERRUPTIBLE);
204
205
}
205
206
 
 
207
bool nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, struct nfs_page *prev, struct nfs_page *req)
 
208
{
 
209
        /*
 
210
         * FIXME: ideally we should be able to coalesce all requests
 
211
         * that are not block boundary aligned, but currently this
 
212
         * is problematic for the case of bsize < PAGE_CACHE_SIZE,
 
213
         * since nfs_flush_multi and nfs_pagein_multi assume you
 
214
         * can have only one struct nfs_page.
 
215
         */
 
216
        if (desc->pg_bsize < PAGE_SIZE)
 
217
                return 0;
 
218
 
 
219
        return desc->pg_count + req->wb_bytes <= desc->pg_bsize;
 
220
}
 
221
EXPORT_SYMBOL_GPL(nfs_generic_pg_test);
 
222
 
206
223
/**
207
224
 * nfs_pageio_init - initialise a page io descriptor
208
225
 * @desc: pointer to descriptor
213
230
 */
214
231
void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
215
232
                     struct inode *inode,
216
 
                     int (*doio)(struct inode *, struct list_head *, unsigned int, size_t, int),
 
233
                     int (*doio)(struct nfs_pageio_descriptor *),
217
234
                     size_t bsize,
218
235
                     int io_flags)
219
236
{
222
239
        desc->pg_count = 0;
223
240
        desc->pg_bsize = bsize;
224
241
        desc->pg_base = 0;
 
242
        desc->pg_moreio = 0;
225
243
        desc->pg_inode = inode;
226
244
        desc->pg_doio = doio;
227
245
        desc->pg_ioflags = io_flags;
228
246
        desc->pg_error = 0;
 
247
        desc->pg_lseg = NULL;
 
248
        desc->pg_test = nfs_generic_pg_test;
 
249
        pnfs_pageio_init(desc, inode);
229
250
}
230
251
 
231
252
/**
239
260
 *
240
261
 * Return 'true' if this is the case, else return 'false'.
241
262
 */
242
 
static int nfs_can_coalesce_requests(struct nfs_page *prev,
243
 
                                     struct nfs_page *req)
 
263
static bool nfs_can_coalesce_requests(struct nfs_page *prev,
 
264
                                      struct nfs_page *req,
 
265
                                      struct nfs_pageio_descriptor *pgio)
244
266
{
245
267
        if (req->wb_context->cred != prev->wb_context->cred)
246
 
                return 0;
 
268
                return false;
247
269
        if (req->wb_lock_context->lockowner != prev->wb_lock_context->lockowner)
248
 
                return 0;
 
270
                return false;
249
271
        if (req->wb_context->state != prev->wb_context->state)
250
 
                return 0;
 
272
                return false;
251
273
        if (req->wb_index != (prev->wb_index + 1))
252
 
                return 0;
 
274
                return false;
253
275
        if (req->wb_pgbase != 0)
254
 
                return 0;
 
276
                return false;
255
277
        if (prev->wb_pgbase + prev->wb_bytes != PAGE_CACHE_SIZE)
256
 
                return 0;
257
 
        return 1;
 
278
                return false;
 
279
        return pgio->pg_test(pgio, prev, req);
258
280
}
259
281
 
260
282
/**
268
290
static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc,
269
291
                                     struct nfs_page *req)
270
292
{
271
 
        size_t newlen = req->wb_bytes;
272
 
 
273
293
        if (desc->pg_count != 0) {
274
294
                struct nfs_page *prev;
275
295
 
276
 
                /*
277
 
                 * FIXME: ideally we should be able to coalesce all requests
278
 
                 * that are not block boundary aligned, but currently this
279
 
                 * is problematic for the case of bsize < PAGE_CACHE_SIZE,
280
 
                 * since nfs_flush_multi and nfs_pagein_multi assume you
281
 
                 * can have only one struct nfs_page.
282
 
                 */
283
 
                if (desc->pg_bsize < PAGE_SIZE)
284
 
                        return 0;
285
 
                newlen += desc->pg_count;
286
 
                if (newlen > desc->pg_bsize)
287
 
                        return 0;
288
296
                prev = nfs_list_entry(desc->pg_list.prev);
289
 
                if (!nfs_can_coalesce_requests(prev, req))
 
297
                if (!nfs_can_coalesce_requests(prev, req, desc))
290
298
                        return 0;
291
 
        } else
 
299
        } else {
292
300
                desc->pg_base = req->wb_pgbase;
 
301
        }
293
302
        nfs_list_remove_request(req);
294
303
        nfs_list_add_request(req, &desc->pg_list);
295
 
        desc->pg_count = newlen;
 
304
        desc->pg_count += req->wb_bytes;
296
305
        return 1;
297
306
}
298
307
 
302
311
static void nfs_pageio_doio(struct nfs_pageio_descriptor *desc)
303
312
{
304
313
        if (!list_empty(&desc->pg_list)) {
305
 
                int error = desc->pg_doio(desc->pg_inode,
306
 
                                          &desc->pg_list,
307
 
                                          nfs_page_array_len(desc->pg_base,
308
 
                                                             desc->pg_count),
309
 
                                          desc->pg_count,
310
 
                                          desc->pg_ioflags);
 
314
                int error = desc->pg_doio(desc);
311
315
                if (error < 0)
312
316
                        desc->pg_error = error;
313
317
                else
331
335
                           struct nfs_page *req)
332
336
{
333
337
        while (!nfs_pageio_do_add_request(desc, req)) {
 
338
                desc->pg_moreio = 1;
334
339
                nfs_pageio_doio(desc);
335
340
                if (desc->pg_error < 0)
336
341
                        return 0;
 
342
                desc->pg_moreio = 0;
337
343
        }
338
344
        return 1;
339
345
}
391
397
        pgoff_t idx_end;
392
398
        int found, i;
393
399
        int res;
 
400
        struct list_head *list;
394
401
 
395
402
        res = 0;
396
403
        if (npages == 0)
411
418
                        idx_start = req->wb_index + 1;
412
419
                        if (nfs_set_page_tag_locked(req)) {
413
420
                                kref_get(&req->wb_kref);
414
 
                                nfs_list_remove_request(req);
415
421
                                radix_tree_tag_clear(&nfsi->nfs_page_tree,
416
422
                                                req->wb_index, tag);
417
 
                                nfs_list_add_request(req, dst);
 
423
                                list = pnfs_choose_commit_list(req, dst);
 
424
                                nfs_list_add_request(req, list);
418
425
                                res++;
419
426
                                if (res == INT_MAX)
420
427
                                        goto out;