root/fs/nfs/bio.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. do_read_nfs_sync
  2. nfs_read_cb
  3. do_read_nfs_async
  4. nfs_readpage

   1 /*
   2  * linux/fs/nfs/bio.c
   3  *
   4  * Block I/O for NFS
   5  *
   6  * Partial copy of Linus' read cache modifications to fs/nfs/file.c
   7  * modified for async RPC by okir@monad.swb.de
   8  *
   9  * We do an ugly hack here in order to return proper error codes to the
  10  * user program when a read request failed. This is a huge problem because
  11  * generic_file_read only checks the return value of inode->i_op->readpage()
  12  * which is usually 0 for async RPC. To overcome this obstacle, we set
  13  * the error bit of the page to 1 when an error occurs, and make nfs_readpage
  14  * transmit requests synchronously when encountering this.
  15  *
  16  * Another possible solution to this problem may be to have a cache of recent
  17  * RPC call results indexed by page pointer, or even a result code field
  18  * in struct page.
  19  */
  20 
  21 #include <linux/sched.h>
  22 #include <linux/kernel.h>
  23 #include <linux/errno.h>
  24 #include <linux/fcntl.h>
  25 #include <linux/stat.h>
  26 #include <linux/mm.h>
  27 #include <linux/nfs_fs.h>
  28 #include <linux/nfsiod.h>
  29 #include <linux/malloc.h>
  30 #include <linux/pagemap.h>
  31 
  32 #include <asm/segment.h>
  33 #include <asm/system.h>
  34 
  35 #undef DEBUG_BIO
  36 #ifdef DEBUG_BIO
  37 #define dprintk(args...)        printk(## args)
  38 #else
  39 #define dprintk(args...)        /* nothing */
  40 #endif
  41 
  42 static inline int
  43 do_read_nfs_sync(struct inode * inode, struct page * page)
     /* [previous][next][first][last][top][bottom][index][help] */
  44 {
  45         struct nfs_fattr fattr;
  46         int             result, refresh = 0;
  47         int             count = PAGE_SIZE;
  48         int             rsize = NFS_SERVER(inode)->rsize;
  49         char            *buf = (char *) page_address(page);
  50         unsigned long   pos = page->offset;
  51 
  52         dprintk("NFS: do_read_nfs_sync(%p)\n", page);
  53 
  54         set_bit(PG_locked, &page->flags);
  55         clear_bit(PG_error, &page->flags);
  56 
  57         do {
  58                 if (count < rsize)
  59                         rsize = count;
  60                 result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode), 
  61                         pos, rsize, buf, &fattr);
  62                 dprintk("nfs_proc_read(%s, (%x,%lx), %ld, %d, %p) = %d\n",
  63                                 NFS_SERVER(inode)->hostname,
  64                                 inode->i_dev, inode->i_ino,
  65                                 pos, rsize, buf, result);
  66                 if (result < 0)
  67                         break;
  68                 refresh = 1;
  69                 count -= result;
  70                 pos += result;
  71                 buf += result;
  72                 if (result < rsize)
  73                         break;
  74         } while (count);
  75 
  76         memset(buf, 0, count);
  77         if (refresh) {
  78                 nfs_refresh_inode(inode, &fattr);
  79                 result = 0;
  80                 set_bit(PG_uptodate, &page->flags);
  81         }
  82         clear_bit(PG_locked, &page->flags);
  83         wake_up(&page->wait);
  84         return result;
  85 }
  86 
  87 /*
  88  * This is the callback from nfsiod telling us whether a reply was
  89  * received or some error occurred (timeout or socket shutdown).
  90  */
  91 static void
  92 nfs_read_cb(int result, struct nfsiod_req *req)
     /* [previous][next][first][last][top][bottom][index][help] */
  93 {
  94         struct page     *page = (struct page *) req->rq_cdata;
  95         static int      succ = 0, fail = 0;
  96 
  97         dprintk("BIO: received callback for page %p, result %d\n",
  98                         page, result);
  99 
 100         if (result >= 0
 101          && (result = nfs_proc_read_reply(&req->rq_rpcreq)) >= 0) {
 102                 succ++;
 103                 set_bit(PG_uptodate, &page->flags);
 104         } else {
 105                 fail++;
 106                 printk("BIO: %d successful reads, %d failures\n", succ, fail);
 107                 set_bit(PG_error, &page->flags);
 108         }
 109         clear_bit(PG_locked, &page->flags);
 110         wake_up(&page->wait);
 111         free_page(page_address(page));
 112 }
 113 
 114 static inline int
 115 do_read_nfs_async(struct inode *inode, struct page *page)
     /* [previous][next][first][last][top][bottom][index][help] */
 116 {
 117         struct nfsiod_req *req;
 118         int             result = -1;    /* totally arbitrary */
 119 
 120         dprintk("NFS: do_read_nfs_async(%p)\n", page);
 121 
 122         set_bit(PG_locked, &page->flags);
 123         clear_bit(PG_error, &page->flags);
 124 
 125         if (!(req = nfsiod_reserve(NFS_SERVER(inode), nfs_read_cb)))
 126                 goto done;
 127         result = nfs_proc_read_request(&req->rq_rpcreq,
 128                         NFS_SERVER(inode), NFS_FH(inode),
 129                         page->offset, PAGE_SIZE, 
 130                         (__u32 *) page_address(page));
 131         if (result >= 0) {
 132                 req->rq_cdata = page;
 133                 page->count++;
 134                 result = nfsiod_enqueue(req);
 135                 if (result >= 0)
 136                         dprintk("NFS: enqueued async READ request.\n");
 137         }
 138         if (result < 0) {
 139                 dprintk("NFS: deferring async READ request.\n");
 140                 nfsiod_release(req);
 141                 clear_bit(PG_locked, &page->flags);
 142                 wake_up(&page->wait);
 143         }
 144 
 145 done:
 146         return result < 0? result : 0;
 147 }
 148 
 149 int
 150 nfs_readpage(struct inode *inode, struct page *page)
     /* [previous][next][first][last][top][bottom][index][help] */
 151 {
 152         unsigned long   address;
 153         int             error = -1;
 154 
 155         dprintk("NFS: nfs_readpage %08lx\n", page_address(page));
 156         address = page_address(page);
 157         page->count++;
 158         if (!PageError(page) && NFS_SERVER(inode)->rsize >= PAGE_SIZE)
 159                 error = do_read_nfs_async(inode, page);
 160         if (error < 0)          /* couldn't enqueue */
 161                 error = do_read_nfs_sync(inode, page);
 162         free_page(address);
 163         return error;
 164 }

/* [previous][next][first][last][top][bottom][index][help] */