]> git.neil.brown.name Git - LaFS.git/commitdiff
lafs_get_block without page lock.
authorNeilBrown <neilb@suse.de>
Sun, 2 Aug 2009 09:28:52 +0000 (19:28 +1000)
committerNeilBrown <neilb@suse.de>
Sun, 2 Aug 2009 09:28:52 +0000 (19:28 +1000)
We need to be able to lafs_get_block an existing block even if
the page is locked.  So handle that case using ->private_lock.

Also release the page at the end..

block.c
lafs.h

diff --git a/block.c b/block.c
index a13ebb094b4363927c071a1099cdf1cf390aa96e..65519fd35897005e3a18153d3b8bd7f3aa7e7650 100644 (file)
--- a/block.c
+++ b/block.c
@@ -73,9 +73,25 @@ struct datablock *
 lafs_get_block(struct inode *ino, unsigned long index, struct page *p,
               int gfp, REFARG)
 {
-       struct datablock *b;
+       struct datablock *b = NULL;
        int bits = PAGE_SHIFT - ino->i_blkbits;
        int unlock = !p;
+       if (!p) {
+               p = find_get_page(ino->i_mapping, index >> bits);
+               if (p) {
+                       spin_lock(&ino->i_mapping->private_lock);
+                       if (PagePrivate(p)) {
+                               b = (struct datablock *)p->private;
+                               b += index & ((1<<bits)-1);
+                               getdref_locked(b, REF);
+                       }
+                       spin_unlock(&ino->i_mapping->private_lock);
+                       page_cache_release(p);
+                       p = NULL;
+               }
+               if (b)
+                       return b;
+       }
        if (!p)
                p = find_or_create_page(ino->i_mapping, index>>bits, gfp);
        if (!p) {
@@ -134,8 +150,10 @@ lafs_get_block(struct inode *ino, unsigned long index, struct page *p,
        b += index & ((1<<bits)-1);
        getdref_locked(b, REF);
 
-       if (unlock)
+       if (unlock) {
                unlock_page(p);
+               page_cache_release(p);
+       }
        BUG_ON(b->b.inode != ino);
        return b;
 }
diff --git a/lafs.h b/lafs.h
index 3077493da770bcbd736553d16b983226d15b4c45..f92617c38b0ca1ef9c7347d1bcd4410bccb36546 100644 (file)
--- a/lafs.h
+++ b/lafs.h
@@ -376,6 +376,8 @@ static inline struct block *_getref_locked(struct block *b)
                    db->my_inode &&
                    spin_is_locked(&db->my_inode->i_data.private_lock))
                        ok = 1;
+               if (spin_is_locked(&b->inode->i_mapping->private_lock))
+                       ok = 1;
        }
        if (test_bit(B_Dirty, &b->flags) || test_bit(B_Realloc, &b->flags))
                if (spin_is_locked(&fs_from_inode(b->inode)->lock))