afs: Use cell for md5 inode numbers
[openafs.git] / src / afs / LINUX24 / osi_vnodeops.c
index 625db17..8744691 100644 (file)
 #if defined(AFS_LINUX24_ENV)
 #include "h/smp_lock.h"
 #endif
-#if defined(AFS_CACHE_BYPASS)
 #include "afs/lock.h"
 #include "afs/afs_bypasscache.h"
-#endif
-
-#include "osi_pagecopy.h"
 
 #ifdef pgoff2loff
 #define pageoff(pp) pgoff2loff((pp)->index)
 #define pageoff(pp) pp->offset
 #endif
 
-#ifndef HAVE_PAGEVEC_LRU_ADD_FILE
-#define __pagevec_lru_add_file __pagevec_lru_add
-#endif
-
 #ifndef MAX_ERRNO
 #define MAX_ERRNO 1000L
 #endif
@@ -124,7 +116,7 @@ afs_linux_read(struct file *fp, char *buf, size_t count, loff_t * offp)
 {
     ssize_t code = 0;
     struct vcache *vcp = VTOAFS(fp->f_dentry->d_inode);
-#if defined(AFS_CACHE_BYPASS) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
     afs_size_t isize, offindex;
 #endif
 
@@ -135,7 +127,7 @@ afs_linux_read(struct file *fp, char *buf, size_t count, loff_t * offp)
     code = afs_linux_VerifyVCache(vcp, NULL);
 
     if (code == 0) {
-#if defined(AFS_CACHE_BYPASS) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
        isize = (i_size_read(fp->f_mapping->host) - 1) >> PAGE_CACHE_SHIFT;
         offindex = *offp >> PAGE_CACHE_SHIFT;
         if(offindex > isize) {
@@ -147,7 +139,7 @@ afs_linux_read(struct file *fp, char *buf, size_t count, loff_t * offp)
         * so we optimise by not using it */
        osi_FlushPages(vcp, NULL);      /* ensure stale pages are gone */
        AFS_GUNLOCK();
-#ifdef DO_SYNC_READ
+#ifdef HAVE_LINUX_DO_SYNC_READ
        code = do_sync_read(fp, buf, count, offp);
 #else
        code = generic_file_read(fp, buf, count, offp);
@@ -158,7 +150,7 @@ afs_linux_read(struct file *fp, char *buf, size_t count, loff_t * offp)
     afs_Trace4(afs_iclSetp, CM_TRACE_READOP, ICL_TYPE_POINTER, vcp,
               ICL_TYPE_OFFSET, offp, ICL_TYPE_INT32, count, ICL_TYPE_INT32,
               code);
-#if defined(AFS_CACHE_BYPASS) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 done:
 #endif
     AFS_GUNLOCK();
@@ -227,7 +219,7 @@ afs_linux_readdir(struct file *fp, void *dirbuf, filldir_t filldir)
 {
     struct vcache *avc = VTOAFS(FILE_INODE(fp));
     struct vrequest treq;
-    register struct dcache *tdc;
+    struct dcache *tdc;
     int code;
     int offset;
     int dirpos;
@@ -308,11 +300,13 @@ afs_linux_readdir(struct file *fp, void *dirbuf, filldir_t filldir)
        if (!dirpos)
            break;
 
-       de = afs_dir_GetBlob(tdc, dirpos);
-       if (!de)
+       code = afs_dir_GetBlob(tdc, dirpos, &entry);
+       if (code)
            break;
+       de = (struct DirEntry *)entry.data;
 
-       ino = afs_calc_inum (avc->f.fid.Fid.Volume, ntohl(de->fid.vnode));
+       ino = afs_calc_inum(avc->f.fid.Cell, avc->f.fid.Fid.Volume,
+                           ntohl(de->fid.vnode));
 
        if (de->name)
            len = strlen(de->name);
@@ -531,7 +525,10 @@ afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
     flock.l_pid = flp->fl_pid;
     flock.l_whence = 0;
     flock.l_start = flp->fl_start;
-    flock.l_len = flp->fl_end - flp->fl_start + 1;
+    if (flp->fl_end == OFFSET_MAX)
+       flock.l_len = 0; /* Lock to end of file */
+    else
+       flock.l_len = flp->fl_end - flp->fl_start + 1;
 
     /* Safe because there are no large files, yet */
 #if defined(F_GETLK64) && (F_GETLK != F_GETLK64)
@@ -544,7 +541,7 @@ afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
 #endif /* F_GETLK64 && F_GETLK != F_GETLK64 */
 
     AFS_GLOCK();
-    code = afs_lockctl(vcp, &flock, cmd, credp);
+    code = afs_convert_code(afs_lockctl(vcp, &flock, cmd, credp));
     AFS_GUNLOCK();
 
 #ifdef AFS_LINUX24_ENV
@@ -580,7 +577,7 @@ afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
        if ((conflict = posix_test_lock(fp, flp))) {
            locks_copy_lock(flp, conflict);
            flp->fl_type = F_UNLCK;
-           crfee(credp);
+           crfree(credp);
            return 0;
        }
 # else
@@ -598,10 +595,13 @@ afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
     flp->fl_type = flock.l_type;
     flp->fl_pid = flock.l_pid;
     flp->fl_start = flock.l_start;
-    flp->fl_end = flock.l_start + flock.l_len - 1;
+    if (flock.l_len == 0)
+       flp->fl_end = OFFSET_MAX; /* Lock to end of file */
+    else
+       flp->fl_end = flock.l_start + flock.l_len - 1;
 
     crfree(credp);
-    return afs_convert_code(code);
+    return code;
 }
 
 #ifdef STRUCT_FILE_OPERATIONS_HAS_FLOCK
@@ -617,7 +617,7 @@ afs_linux_flock(struct file *fp, int cmd, struct file_lock *flp) {
     flock.l_pid = flp->fl_pid;
     flock.l_whence = 0;
     flock.l_start = 0;
-    flock.l_len = OFFSET_MAX;
+    flock.l_len = 0;
 
     /* Safe because there are no large files, yet */
 #if defined(F_GETLK64) && (F_GETLK != F_GETLK64)
@@ -630,7 +630,7 @@ afs_linux_flock(struct file *fp, int cmd, struct file_lock *flp) {
 #endif /* F_GETLK64 && F_GETLK != F_GETLK64 */
 
     AFS_GLOCK();
-    code = afs_lockctl(vcp, &flock, cmd, credp);
+    code = afs_convert_code(afs_lockctl(vcp, &flock, cmd, credp));
     AFS_GUNLOCK();
 
     if ((code == 0 || flp->fl_type == F_UNLCK) && 
@@ -651,7 +651,7 @@ afs_linux_flock(struct file *fp, int cmd, struct file_lock *flp) {
     flp->fl_pid = flock.l_pid;
 
     crfree(credp);
-    return afs_convert_code(code);
+    return code;
 }
 #endif
 
@@ -671,9 +671,7 @@ afs_linux_flush(struct file *fp)
     struct vcache *vcp;
     cred_t *credp;
     int code;
-#if defined(AFS_CACHE_BYPASS)
     int bypasscache;
-#endif
 
     AFS_GLOCK();
 
@@ -690,7 +688,6 @@ afs_linux_flush(struct file *fp)
     code = afs_InitReq(&treq, credp);
     if (code)
        goto out;
-#if defined(AFS_CACHE_BYPASS)
        /* If caching is bypassed for this file, or globally, just return 0 */
        if(cache_bypass_strategy == ALWAYS_BYPASS_CACHE)
                bypasscache = 1;
@@ -704,7 +701,6 @@ afs_linux_flush(struct file *fp)
             /* future proof: don't rely on 0 return from afs_InitReq */
             code = 0; goto out;
         }
-#endif
 
     ObtainSharedLock(&vcp->lock, 535);
     if ((vcp->execsOrWriters > 0) && (file_count(fp) == 1)) {
@@ -764,7 +760,7 @@ struct file_operations afs_dir_fops = {
 struct file_operations afs_file_fops = {
   .read =      afs_linux_read,
   .write =     afs_linux_write,
-#ifdef GENERIC_FILE_AIO_READ
+#ifdef HAVE_LINUX_GENERIC_FILE_AIO_READ
   .aio_read =  generic_file_aio_read,
   .aio_write = generic_file_aio_write,
 #endif
@@ -873,7 +869,8 @@ afs_linux_revalidate(struct dentry *dp)
      */
     if (vcp->f.states & CStatd &&
         (!afs_fakestat_enable || vcp->mvstat != 1) &&
-       !afs_nfsexporter) {
+       !afs_nfsexporter &&
+       (vType(vcp) == VDIR || vType(vcp) == VLNK)) {
        code = afs_CopyOutAttrs(vcp, &vattr);
     } else {
         credp = crref();
@@ -1150,7 +1147,7 @@ afs_linux_lookup(struct inode *dip, struct dentry *dp)
        afs_getattr(vcp, &vattr, credp);
        afs_fill_inode(ip, &vattr);
        if (
-#ifdef HAVE_KERNEL_HLIST_UNHASHED
+#ifdef HAVE_LINUX_HLIST_UNHASHED
            hlist_unhashed(&ip->i_hash)
 #else
            ip->i_hash.prev == NULL
@@ -1413,7 +1410,7 @@ afs_linux_ireadlink(struct inode *ip, char *target, int maxlen, uio_seg_t seg)
 {
     int code;
     cred_t *credp = crref();
-    uio_t tuio;
+    struct uio tuio;
     struct iovec iov;
 
     setup_uio(&tuio, &iov, target, (afs_offs_t) 0, maxlen, UIO_READ, seg);
@@ -1515,10 +1512,6 @@ afs_linux_follow_link(struct dentry *dp, struct dentry *basep,
 #endif /* AFS_LINUX24_ENV */
 #endif /* USABLE_KERNEL_PAGE_SYMLINK_CACHE */
 
-#if defined(AFS_CACHE_BYPASS)
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-
 static inline int
 afs_linux_can_bypass(struct inode *ip) {
     switch(cache_bypass_strategy) {
@@ -1530,313 +1523,8 @@ afs_linux_can_bypass(struct inode *ip) {
            if(i_size_read(ip) > cache_bypass_threshold)
                return 1;
        default:
+           return 0;
      }
-     return 0;
-}
-
-static int
-afs_linux_cache_bypass_read(struct file *fp, struct address_space *mapping,
-                           struct list_head *page_list, unsigned num_pages)
-{
-    afs_int32 page_ix;
-    uio_t *auio;
-    afs_offs_t offset;
-    struct iovec* iovecp;
-    struct nocache_read_request *ancr;
-    struct page *pp, *ppt;
-    struct pagevec lrupv;
-    afs_int32 code = 0;        
-
-    cred_t *credp;
-    struct inode *ip = FILE_INODE(fp);
-    struct vcache *avc = VTOAFS(ip);
-    afs_int32 bypasscache = 0; /* bypass for this read */
-    afs_int32 base_index = 0;
-    afs_int32 page_count = 0;
-    afs_int32 isize;
-       
-    /* background thread must free: iovecp, auio, ancr */
-    iovecp = osi_Alloc(num_pages * sizeof(struct iovec));
-
-    auio = osi_Alloc(sizeof(uio_t));
-    auio->uio_iov = iovecp;    
-    auio->uio_iovcnt = num_pages;
-    auio->uio_flag = UIO_READ;
-    auio->uio_seg = AFS_UIOSYS;
-    auio->uio_resid = num_pages * PAGE_SIZE;
-       
-    ancr = osi_Alloc(sizeof(struct nocache_read_request));
-    ancr->auio = auio;
-    ancr->offset = auio->uio_offset;
-    ancr->length = auio->uio_resid;
-       
-    pagevec_init(&lrupv, 0);   
-       
-    for(page_ix = 0; page_ix < num_pages; ++page_ix) {
-       
-       if(list_empty(page_list))
-           break;
-
-       pp = list_entry(page_list->prev, struct page, lru);
-       /* If we allocate a page and don't remove it from page_list,
-        * the page cache gets upset. */
-       list_del(&pp->lru);
-       isize = (i_size_read(fp->f_mapping->host) - 1) >> PAGE_CACHE_SHIFT;
-       if(pp->index > isize) {
-           if(PageLocked(pp))
-               UnlockPage(pp);
-           continue;
-       }
-
-       if(page_ix == 0) {
-           offset = ((loff_t) pp->index) << PAGE_CACHE_SHIFT;
-           auio->uio_offset = offset;
-           base_index = pp->index;
-       }
-        iovecp[page_ix].iov_len = PAGE_SIZE;
-        code = add_to_page_cache(pp, mapping, pp->index, GFP_KERNEL);
-        if(base_index != pp->index) {   
-            if(PageLocked(pp))
-                                UnlockPage(pp);
-            page_cache_release(pp);
-           iovecp[page_ix].iov_base = (void *) 0;
-           base_index++;
-            continue;
-        }
-        base_index++;
-        if(code) {
-           if(PageLocked(pp))
-               UnlockPage(pp);
-           page_cache_release(pp);
-           iovecp[page_ix].iov_base = (void *) 0;
-       } else {
-           page_count++;
-           if(!PageLocked(pp)) {
-               LockPage(pp);
-           }   
-           
-           /* save the page for background map */
-            iovecp[page_ix].iov_base = (void*) pp;
-
-           /* and put it on the LRU cache */
-           if (!pagevec_add(&lrupv, pp))
-               __pagevec_lru_add(&lrupv);
-        }
-    }
-
-    /* If there were useful pages in the page list, make sure all pages
-     * are in the LRU cache, then schedule the read */
-    if(page_count) {
-        pagevec_lru_add(&lrupv);
-       credp = crref();
-        code = afs_ReadNoCache(avc, ancr, credp);
-       crfree(credp);
-    } else {
-        /* If there is nothing for the background thread to handle,
-         * it won't be freeing the things that we never gave it */
-        osi_Free(iovecp, num_pages * sizeof(struct iovec));
-        osi_Free(auio, sizeof(uio_t));
-        osi_Free(ancr, sizeof(struct nocache_read_request));
-    }
-    /* we do not flush, release, or unmap pages--that will be 
-     * done for us by the background thread as each page comes in
-     * from the fileserver */
-out:   
-    return afs_convert_code(code);
-}
-
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */
-#endif /* defined(AFS_CACHE_BYPASS */
-
-static int
-afs_linux_read_cache(struct file *cachefp, struct page *page,
-                    int chunk, struct pagevec *lrupv,
-                    struct afs_pagecopy_task *task) {
-    loff_t offset = page_offset(page);
-    struct page *newpage, *cachepage;
-    struct address_space *cachemapping;
-    int pageindex;
-    int code = 0;
-
-    cachemapping = cachefp->f_dentry->d_inode->i_mapping;
-    newpage = NULL;
-    cachepage = NULL;
-
-    /* From our offset, we now need to work out which page in the disk
-     * file it corresponds to. This will be fun ... */
-    pageindex = (offset - AFS_CHUNKTOBASE(chunk)) >> PAGE_CACHE_SHIFT;
-
-    while (cachepage == NULL) {
-        cachepage = find_get_page(cachemapping, pageindex);
-       if (!cachepage) {
-           if (!newpage)
-               newpage = page_cache_alloc_cold(cachemapping);
-           if (!newpage) {
-               code = -ENOMEM;
-               goto out;
-           }
-
-           code = add_to_page_cache(newpage, cachemapping,
-                                    pageindex, GFP_KERNEL);
-           if (code == 0) {
-               cachepage = newpage;
-               newpage = NULL;
-
-               page_cache_get(cachepage);
-                if (!pagevec_add(lrupv, cachepage))
-                    __pagevec_lru_add_file(lrupv);
-
-           } else {
-               page_cache_release(newpage);
-               newpage = NULL;
-               if (code != -EEXIST)
-                   goto out;
-           }
-        } else {
-           lock_page(cachepage);
-       }
-    }
-
-    if (!PageUptodate(cachepage)) {
-       ClearPageError(cachepage);
-        code = cachemapping->a_ops->readpage(NULL, cachepage);
-       if (!code && !task) {
-           wait_on_page_locked(cachepage);
-       }
-    } else {
-        unlock_page(cachepage);
-    }
-
-    if (!code) {
-       if (PageUptodate(cachepage)) {
-           copy_highpage(page, cachepage);
-           flush_dcache_page(page);
-           SetPageUptodate(page);
-           UnlockPage(page);
-        } else if (task) {
-           afs_pagecopy_queue_page(task, cachepage, page);
-       } else {
-           code = -EIO;
-       }
-    }
-
-    if (code) {
-        UnlockPage(page);
-    }
-
-out:
-    if (cachepage)
-       page_cache_release(cachepage);
-
-    return code;
-}
-
-static int inline
-afs_linux_readpage_fastpath(struct file *fp, struct page *pp, int *codep)
-{
-    loff_t offset = page_offset(pp);
-    struct inode *ip = FILE_INODE(fp);
-    struct vcache *avc = VTOAFS(ip);
-    struct dcache *tdc;
-    struct file *cacheFp = NULL;
-    int code;
-    int dcLocked = 0;
-    struct pagevec lrupv;
-
-    /* Not a UFS cache, don't do anything */
-    if (cacheDiskType != AFS_FCACHE_TYPE_UFS)
-       return 0;
-
-    /* Can't do anything if the vcache isn't statd , or if the read
-     * crosses a chunk boundary.
-     */
-    if (!(avc->f.states & CStatd) ||
-        AFS_CHUNK(offset) != AFS_CHUNK(offset + PAGE_SIZE)) {
-       return 0;
-    }
-
-    ObtainWriteLock(&avc->lock, 911);
-
-    /* XXX - See if hinting actually makes things faster !!! */
-
-    /* See if we have a suitable entry already cached */
-    tdc = avc->dchint;
-
-    if (tdc) {
-        /* We need to lock xdcache, then dcache, to handle situations where
-         * the hint is on the free list. However, we can't safely do this
-         * according to the locking hierarchy. So, use a non blocking lock.
-         */
-       ObtainReadLock(&afs_xdcache);
-       dcLocked = ( 0 == NBObtainReadLock(&tdc->lock));
-
-       if (dcLocked && (tdc->index != NULLIDX)
-           && !FidCmp(&tdc->f.fid, &avc->f.fid)
-           && tdc->f.chunk == AFS_CHUNK(offset)
-           && !(afs_indexFlags[tdc->index] & (IFFree | IFDiscarded))) {
-           /* Bonus - the hint was correct */
-           afs_RefDCache(tdc);
-       } else {
-           /* Only destroy the hint if its actually invalid, not if there's
-            * just been a locking failure */
-           if (dcLocked) {
-               ReleaseReadLock(&tdc->lock);
-               avc->dchint = NULL;
-           }
-
-           tdc = NULL;
-           dcLocked = 0;
-       }
-        ReleaseReadLock(&afs_xdcache);
-    }
-
-    /* No hint, or hint is no longer valid - see if we can get something
-     * directly from the dcache
-     */
-    if (!tdc)
-       tdc = afs_FindDCache(avc, offset);
-
-    if (!tdc) {
-       ReleaseWriteLock(&avc->lock);
-       return 0;
-    }
-
-    if (!dcLocked)
-       ObtainReadLock(&tdc->lock);
-
-    /* Is the dcache we've been given currently up to date */
-    if (!hsame(avc->f.m.DataVersion, tdc->f.versionNo) ||
-       (tdc->dflags & DFFetching)) {
-       ReleaseWriteLock(&avc->lock);
-       ReleaseReadLock(&tdc->lock);
-       afs_PutDCache(tdc);
-       return 0;
-    }
-
-    /* Update our hint for future abuse */
-    avc->dchint = tdc;
-
-    /* Okay, so we've now got a cache file that is up to date */
-
-    /* XXX - I suspect we should be locking the inodes before we use them! */
-    AFS_GUNLOCK();
-    cacheFp = afs_linux_raw_open(&tdc->f.inode, NULL);
-    pagevec_init(&lrupv, 0);
-
-    code = afs_linux_read_cache(cacheFp, pp, tdc->f.chunk, &lrupv, NULL);
-
-    if (pagevec_count(&lrupv))
-       __pagevec_lru_add_file(&lrupv);
-
-    filp_close(cacheFp, NULL);
-    AFS_GLOCK();
-
-    ReleaseReadLock(&tdc->lock);
-    ReleaseWriteLock(&avc->lock);
-    afs_PutDCache(tdc);
-
-    *codep = code;
-    return 1;
 }
 
 /* afs_linux_readpage
@@ -1853,29 +1541,18 @@ afs_linux_readpage(struct file *fp, struct page *pp)
     ulong address = afs_linux_page_address(pp);
     afs_offs_t offset = pageoff(pp);
 #endif
-#if defined(AFS_CACHE_BYPASS)
     afs_int32 bypasscache = 0; /* bypass for this read */
     struct nocache_read_request *ancr;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
     afs_int32 isize;
 #endif
-#endif
-    uio_t *auio;
+    struct uio *auio;
     struct iovec *iovecp;
     struct inode *ip = FILE_INODE(fp);
     afs_int32 cnt = page_count(pp);
     struct vcache *avc = VTOAFS(ip);
     cred_t *credp;
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-    AFS_GLOCK();
-    if (afs_linux_readpage_fastpath(fp, pp, &code)) {
-       AFS_GUNLOCK();
-       return code;
-    }
-    AFS_GUNLOCK();
-#endif
-
     credp = crref();
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
     address = kmap(pp);
@@ -1885,25 +1562,13 @@ afs_linux_readpage(struct file *fp, struct page *pp)
     set_bit(PG_locked, &pp->flags);    /* other bits? See mm.h */
     clear_bit(PG_error, &pp->flags);
 #endif
-#if defined(AFS_CACHE_BYPASS)
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-    /* If the page is past the end of the file, skip it */
-    isize = (i_size_read(fp->f_mapping->host) - 1) >> PAGE_CACHE_SHIFT;
-    if(pp->index > isize) {
-       if(PageLocked(pp))
-           UnlockPage(pp);
-       goto done;
-    }
-#endif
-#endif
     /* if bypasscache, receiver frees, else we do */
-    auio = osi_Alloc(sizeof(uio_t));
+    auio = osi_Alloc(sizeof(struct uio));
     iovecp = osi_Alloc(sizeof(struct iovec));
 
     setup_uio(auio, iovecp, (char *)address, offset, PAGE_SIZE, UIO_READ,
              AFS_UIOSYS);
 
-#if defined(AFS_CACHE_BYPASS)
     bypasscache = afs_linux_can_bypass(ip);
 
     /* In the new incarnation of selective caching, a file's caching policy
@@ -1927,7 +1592,6 @@ afs_linux_readpage(struct file *fp, struct page *pp)
 
        goto done; /* skips release page, doing it in bg thread */
     }
-#endif 
                  
 #ifdef AFS_LINUX24_ENV
     maybe_lock_kernel();
@@ -1972,14 +1636,12 @@ afs_linux_readpage(struct file *fp, struct page *pp)
     free_page(address);
 #endif
 
-#if defined(AFS_CACHE_BYPASS)
     /* do not call afs_GetDCache if cache is bypassed */
     if(bypasscache)
        goto done;
-#endif
 
     /* free if not bypassing cache */
-    osi_Free(auio, sizeof(uio_t));
+    osi_Free(auio, sizeof(struct uio));
     osi_Free(iovecp, sizeof(struct iovec));
 
     if (!code && AFS_CHUNKOFFSET(offset) == 0) {
@@ -2000,116 +1662,11 @@ afs_linux_readpage(struct file *fp, struct page *pp)
        AFS_GUNLOCK();
     }
 
-#if defined(AFS_CACHE_BYPASS)
 done:
-#endif
     crfree(credp);
     return afs_convert_code(code);
 }
 
-/* Readpages reads a number of pages for a particular file. We use
- * this to optimise the reading, by limiting the number of times upon which
- * we have to lookup, lock and open vcaches and dcaches
- */
-
-static int
-afs_linux_readpages(struct file *fp, struct address_space *mapping,
-                   struct list_head *page_list, unsigned int num_pages)
-{
-    struct inode *inode = mapping->host;
-    struct vcache *avc = VTOAFS(inode);
-    struct dcache *tdc;
-    struct file *cacheFp = NULL;
-    int code;
-    unsigned int page_idx;
-    loff_t offset;
-    struct pagevec lrupv;
-    struct afs_pagecopy_task *task;
-
-#if defined(AFS_CACHE_BYPASS)
-    bypasscache = afs_linux_can_bypass(ip);
-
-    /* In the new incarnation of selective caching, a file's caching policy
-     * can change, eg because file size exceeds threshold, etc. */
-    trydo_cache_transition(avc, credp, bypasscache);
-
-    if (bypasscache)
-       return afs_linux_cache_bypass_read(ip, mapping, page_list, num_pages);
-#endif
-
-    AFS_GLOCK();
-    if ((code = afs_linux_VerifyVCache(avc, NULL))) {
-       AFS_GUNLOCK();
-       return code;
-    }
-
-    ObtainWriteLock(&avc->lock, 912);
-    AFS_GUNLOCK();
-
-    task = afs_pagecopy_init_task();
-
-    tdc = NULL;
-    pagevec_init(&lrupv, 0);
-    for (page_idx = 0; page_idx < num_pages; page_idx++) {
-       struct page *page = list_entry(page_list->prev, struct page, lru);
-       list_del(&page->lru);
-       offset = page_offset(page);
-
-       if (tdc && tdc->f.chunk != AFS_CHUNK(offset)) {
-           AFS_GLOCK();
-           ReleaseReadLock(&tdc->lock);
-           afs_PutDCache(tdc);
-           AFS_GUNLOCK();
-           tdc = NULL;
-           if (cacheFp)
-               filp_close(cacheFp, NULL);
-       }
-
-       if (!tdc) {
-           AFS_GLOCK();
-           if ((tdc = afs_FindDCache(avc, offset))) {
-               ObtainReadLock(&tdc->lock);
-               if (!hsame(avc->f.m.DataVersion, tdc->f.versionNo) ||
-                   (tdc->dflags & DFFetching)) {
-                   ReleaseReadLock(&tdc->lock);
-                   afs_PutDCache(tdc);
-                   tdc = NULL;
-               }
-           }
-           AFS_GUNLOCK();
-           if (tdc)
-               cacheFp = afs_linux_raw_open(&tdc->f.inode, NULL);
-       }
-
-       if (tdc && !add_to_page_cache(page, mapping, page->index,
-                                     GFP_KERNEL)) {
-           page_cache_get(page);
-           if (!pagevec_add(&lrupv, page))
-               __pagevec_lru_add_file(&lrupv);
-
-           afs_linux_read_cache(cacheFp, page, tdc->f.chunk, &lrupv, task);
-       }
-       page_cache_release(page);
-    }
-    if (pagevec_count(&lrupv))
-       __pagevec_lru_add_file(&lrupv);
-
-    if (tdc)
-       filp_close(cacheFp, NULL);
-
-    afs_pagecopy_put_task(task);
-
-    AFS_GLOCK();
-    if (tdc) {
-       ReleaseReadLock(&tdc->lock);
-        afs_PutDCache(tdc);
-    }
-
-    ReleaseWriteLock(&avc->lock);
-    AFS_GUNLOCK();
-    return 0;
-}
-
 #if defined(AFS_LINUX24_ENV)
 static int
 afs_linux_writepage_sync(struct inode *ip, struct page *pp,
@@ -2120,7 +1677,7 @@ afs_linux_writepage_sync(struct inode *ip, struct page *pp,
     afs_offs_t base;
     int code = 0;
     cred_t *credp;
-    uio_t tuio;
+    struct uio tuio;
     struct iovec iovec;
     int f_flags = 0;
 
@@ -2230,7 +1787,7 @@ afs_linux_updatepage(struct file *fp, struct page *pp, unsigned long offset,
     u8 *page_addr = (u8 *) afs_linux_page_address(pp);
     int code = 0;
     cred_t *credp;
-    uio_t tuio;
+    struct uio tuio;
     struct iovec iovec;
 
     set_bit(PG_locked, &pp->flags);
@@ -2302,7 +1859,7 @@ afs_linux_permission(struct inode *ip, int mode)
     return afs_convert_code(code);
 }
 
-#if defined(AFS_LINUX24_ENV) && !defined(HAVE_WRITE_BEGIN)
+#if defined(AFS_LINUX24_ENV) && !defined(STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_WRITE_BEGIN)
 static int
 afs_linux_commit_write(struct file *file, struct page *page, unsigned offset,
                       unsigned to)
@@ -2327,7 +1884,7 @@ afs_linux_prepare_write(struct file *file, struct page *page, unsigned from,
 }
 #endif
 
-#if defined(HAVE_WRITE_BEGIN)
+#if defined(STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_WRITE_BEGIN)
 static int
 afs_linux_write_end(struct file *file, struct address_space *mapping,
                                 loff_t pos, unsigned len, unsigned copied,
@@ -2350,7 +1907,7 @@ afs_linux_write_begin(struct file *file, struct address_space *mapping,
 {
     struct page *page;
     pgoff_t index = pos >> PAGE_CACHE_SHIFT;
-#if defined(HAVE_GRAB_CACHE_PAGE_WRITE_BEGIN)
+#if defined(HAVE_LINUX_GRAB_CACHE_PAGE_WRITE_BEGIN)
     page = grab_cache_page_write_begin(mapping, index, flags);
 #else
     page = __grab_cache_page(mapping, index);
@@ -2378,9 +1935,8 @@ static struct inode_operations afs_file_iops = {
 #if defined(AFS_LINUX24_ENV)
 static struct address_space_operations afs_file_aops = {
   .readpage =          afs_linux_readpage,
-  .readpages =                 afs_linux_readpages,
   .writepage =         afs_linux_writepage,
-#if defined (HAVE_WRITE_BEGIN)
+#if defined (STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_WRITE_BEGIN)
   .write_begin =        afs_linux_write_begin,
   .write_end =          afs_linux_write_end,
 #else