vserver 1.9.5.x5
[linux-2.6.git] / fs / jfs / jfs_metapage.c
index 8c94bb0..1cd9bdf 100644 (file)
 #include "jfs_txnmgr.h"
 #include "jfs_debug.h"
 
-static spinlock_t meta_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(meta_lock);
 
 #ifdef CONFIG_JFS_STATISTICS
-struct {
+static struct {
        uint    pagealloc;      /* # of page allocations */
        uint    pagefree;       /* # of page frees */
        uint    lockwait;       /* # of sleeping lock_metapage() calls */
@@ -108,9 +108,9 @@ static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
        }
 }
 
-static inline struct metapage *alloc_metapage(int no_wait)
+static inline struct metapage *alloc_metapage(int gfp_mask)
 {
-       return mempool_alloc(metapage_mempool, no_wait ? GFP_ATOMIC : GFP_NOFS);
+       return mempool_alloc(metapage_mempool, gfp_mask);
 }
 
 static inline void free_metapage(struct metapage *mp)
@@ -225,8 +225,16 @@ struct metapage *__get_metapage(struct inode *inode, unsigned long lblock,
 
        if (absolute)
                mapping = inode->i_sb->s_bdev->bd_inode->i_mapping;
-       else
+       else {
+               /*
+                * If an nfs client tries to read an inode that is larger
+                * than any existing inodes, we may try to read past the
+                * end of the inode map
+                */
+               if ((lblock << inode->i_blkbits) >= inode->i_size)
+                       return NULL;
                mapping = inode->i_mapping;
+       }
 
        hash_ptr = meta_hash(mapping, lblock);
 again:
@@ -281,7 +289,7 @@ again:
                 */
                mp = NULL;
                if (JFS_IP(inode)->fileset == AGGREGATE_I) {
-                       mp =  mempool_alloc(metapage_mempool, GFP_ATOMIC);
+                       mp = alloc_metapage(GFP_ATOMIC);
                        if (!mp) {
                                /*
                                 * mempool is supposed to protect us from
@@ -298,7 +306,7 @@ again:
                        struct metapage *mp2;
 
                        spin_unlock(&meta_lock);
-                       mp =  mempool_alloc(metapage_mempool, GFP_NOFS);
+                       mp = alloc_metapage(GFP_NOFS);
                        spin_lock(&meta_lock);
 
                        /* we dropped the meta_lock, we need to search the
@@ -320,7 +328,7 @@ again:
                atomic_set(&mp->nohomeok,0);
                mp->mapping = mapping;
                mp->index = lblock;
-               mp->page = 0;
+               mp->page = NULL;
                mp->logical_size = size;
                add_to_hash(mp, hash_ptr);
                spin_unlock(&meta_lock);
@@ -388,14 +396,6 @@ static void __write_metapage(struct metapage * mp)
 
        jfs_info("__write_metapage: mp = 0x%p", mp);
 
-       if (test_bit(META_discard, &mp->flag)) {
-               /*
-                * This metadata is no longer valid
-                */
-               clear_bit(META_dirty, &mp->flag);
-               return;
-       }
-
        page_index = mp->page->index;
        page_offset =
            (mp->index - (page_index << l2BlocksPerPage)) << l2bsize;
@@ -465,7 +465,7 @@ void release_metapage(struct metapage * mp)
                set_bit(META_stale, &mp->flag);
                spin_unlock(&meta_lock);
                kunmap(mp->page);
-               mp->data = 0;
+               mp->data = NULL;
                if (test_bit(META_dirty, &mp->flag))
                        __write_metapage(mp);
                if (test_bit(META_sync, &mp->flag)) {
@@ -491,7 +491,7 @@ void release_metapage(struct metapage * mp)
                 */
                log = mp->log;
                LOGSYNC_LOCK(log);
-               mp->log = 0;
+               mp->log = NULL;
                mp->lsn = 0;
                mp->clsn = 0;
                log->count--;
@@ -541,6 +541,7 @@ again:
                                goto again;
                        }
 
+                       clear_bit(META_dirty, &mp->flag);
                        set_bit(META_discard, &mp->flag);
                        spin_unlock(&meta_lock);
                } else {
@@ -549,6 +550,7 @@ again:
                        if (page) {
                                block_invalidatepage(page, 0);
                                unlock_page(page);
+                               page_cache_release(page);
                        }
                }
        }