NFS: Calculate page offsets algorithmically
[linux-2.6-microblaze.git] / fs / nfs / dir.c
index 1dfbd05..6f0a38d 100644 (file)
@@ -69,18 +69,15 @@ const struct address_space_operations nfs_dir_aops = {
        .freepage = nfs_readdir_clear_array,
 };
 
-static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir)
+static struct nfs_open_dir_context *
+alloc_nfs_open_dir_context(struct inode *dir)
 {
        struct nfs_inode *nfsi = NFS_I(dir);
        struct nfs_open_dir_context *ctx;
-       ctx = kmalloc(sizeof(*ctx), GFP_KERNEL_ACCOUNT);
+
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL_ACCOUNT);
        if (ctx != NULL) {
-               ctx->duped = 0;
                ctx->attr_gencount = nfsi->attr_gencount;
-               ctx->dir_cookie = 0;
-               ctx->dup_cookie = 0;
-               ctx->page_index = 0;
-               ctx->eof = false;
                spin_lock(&dir->i_lock);
                if (list_empty(&nfsi->open_files) &&
                    (nfsi->cache_validity & NFS_INO_DATA_INVAL_DEFER))
@@ -252,17 +249,20 @@ static const char *nfs_readdir_copy_name(const char *name, unsigned int len)
        return ret;
 }
 
+static size_t nfs_readdir_array_maxentries(void)
+{
+       return (PAGE_SIZE - sizeof(struct nfs_cache_array)) /
+              sizeof(struct nfs_cache_array_entry);
+}
+
 /*
  * Check that the next array entry lies entirely within the page bounds
  */
 static int nfs_readdir_array_can_expand(struct nfs_cache_array *array)
 {
-       struct nfs_cache_array_entry *cache_entry;
-
        if (array->page_full)
                return -ENOSPC;
-       cache_entry = &array->array[array->size + 1];
-       if ((char *)cache_entry - (char *)array > PAGE_SIZE) {
+       if (array->size == nfs_readdir_array_maxentries()) {
                array->page_full = 1;
                return -ENOSPC;
        }
@@ -321,6 +321,11 @@ static struct page *nfs_readdir_page_get_locked(struct address_space *mapping,
        return page;
 }
 
+static loff_t nfs_readdir_page_offset(struct page *page)
+{
+       return (loff_t)page->index * (loff_t)nfs_readdir_array_maxentries();
+}
+
 static u64 nfs_readdir_page_last_cookie(struct page *page)
 {
        struct nfs_cache_array *array;
@@ -451,7 +456,7 @@ static int nfs_readdir_search_for_cookie(struct nfs_cache_array *array,
                if (array->array[i].cookie == desc->dir_cookie) {
                        struct nfs_inode *nfsi = NFS_I(file_inode(desc->file));
 
-                       new_pos = desc->current_index + i;
+                       new_pos = nfs_readdir_page_offset(desc->page) + i;
                        if (desc->attr_gencount != nfsi->attr_gencount ||
                            !nfs_readdir_inode_mapping_valid(nfsi)) {
                                desc->duped = 0;