Whamcloud - gitweb
obdfs/super.c: add call to flush pages when unmounting filesystem
[fs/lustre-release.git] / lustre / obdfs / rw.c
index 1f451d8..9bcc915 100644 (file)
@@ -5,7 +5,7 @@
  * Copryright (C) 1999 Stelias Computing Inc, 
  *                (author Peter J. Braam <braam@stelias.com>)
  * Copryright (C) 1999 Seagate Technology Inc.
- */
+*/
 
 
 #include <linux/config.h>
 #include <linux/obdfs.h>
 
 
-int obdfs_flush_reqs(struct list_head *page_list, 
-                    int flush_inode, int check_time);
-
-void obdfs_flush_dirty_pages(int check_time);
-
 /* SYNCHRONOUS I/O for an inode */
 static int obdfs_brw(int rw, struct inode *inode, struct page *page, int create)
 {
-       obd_count        num_oa = 1;
-       obd_count        oa_bufs = 1;
+       obd_count        num_obdo = 1;
+       obd_count        bufs_per_obdo = 1;
        struct obdo     *oa;
        char            *buf = (char *)page_address(page);
        obd_size         count = PAGE_SIZE;
@@ -59,8 +54,8 @@ static int obdfs_brw(int rw, struct inode *inode, struct page *page, int create)
        }
        obdfs_from_inode(oa, inode);
 
-       err = IOPS(inode, brw)(rw, IID(inode), num_oa, &oa, &oa_bufs, &buf,
-                              &count, &offset, &flags);
+       err = IOPS(inode, brw)(rw, IID(inode), num_obdo, &oa, &bufs_per_obdo,
+                              &buf, &count, &offset, &flags);
 
        if ( !err )
                obdfs_to_inode(inode, oa); /* copy o_blocks to i_blocks */
@@ -90,6 +85,8 @@ int obdfs_readpage(struct dentry *dentry, struct page *page)
 } /* obdfs_readpage */
 
 static kmem_cache_t *obdfs_pgrq_cachep = NULL;
+
+/* XXX should probably have one of these per superblock */
 static int obdfs_cache_count = 0;
 
 int obdfs_init_pgrqcache(void)
@@ -119,7 +116,8 @@ int obdfs_init_pgrqcache(void)
 inline void obdfs_pgrq_del(struct obdfs_pgrq *pgrq)
 {
        obdfs_cache_count--;
-       CDEBUG(D_INODE, "deleting page %p from list [count %d]\n", pgrq->rq_page, obdfs_cache_count);
+       CDEBUG(D_INODE, "deleting page %p from list [count %d]\n",
+              pgrq->rq_page, obdfs_cache_count);
        list_del(&pgrq->rq_plist);
        kmem_cache_free(obdfs_pgrq_cachep, pgrq);
 }
@@ -142,6 +140,7 @@ void obdfs_cleanup_pgrqcache(void)
 /*
  * Find a specific page in the page cache.  If it is found, we return
  * the write request struct associated with it, if not found return NULL.
+ * Called with the list lock held.
  */
 static struct obdfs_pgrq *
 obdfs_find_in_page_list(struct inode *inode, struct page *page)
@@ -155,6 +154,7 @@ obdfs_find_in_page_list(struct inode *inode, struct page *page)
        OIDEBUG(inode);
 
        if (list_empty(page_list)) {
+               CDEBUG(D_INODE, "empty list\n");
                EXIT;
                return NULL;
        }
@@ -175,8 +175,9 @@ obdfs_find_in_page_list(struct inode *inode, struct page *page)
 } /* obdfs_find_in_page_list */
 
 
-static struct page*
-obdfs_find_page_index(struct inode *inode, unsigned long index)
+/* called with the list lock held */
+static struct page* obdfs_find_page_index(struct inode *inode,
+                                         unsigned long index)
 {
        struct list_head *page_list = obdfs_iplist(inode);
        struct list_head *tmp;
@@ -184,7 +185,8 @@ obdfs_find_page_index(struct inode *inode, unsigned long index)
 
        ENTRY;
 
-       CDEBUG(D_INODE, "looking for inode %ld pageindex %ld\n", inode->i_ino, index);
+       CDEBUG(D_INODE, "looking for inode %ld pageindex %ld\n",
+              inode->i_ino, index);
        OIDEBUG(inode);
 
        if (list_empty(page_list)) {
@@ -198,7 +200,9 @@ obdfs_find_page_index(struct inode *inode, unsigned long index)
                pgrq = list_entry(tmp, struct obdfs_pgrq, rq_plist);
                page = pgrq->rq_page;
                if (index == page->index) {
-                       CDEBUG(D_INODE, "INDEX SEARC found page %p in list, index %ld\n", page, index);
+                       CDEBUG(D_INODE,
+                              "INDEX SEARCH found page %p, index %ld\n",
+                              page, index);
                        EXIT;
                        return page;
                }
@@ -206,10 +210,10 @@ obdfs_find_page_index(struct inode *inode, unsigned long index)
 
        EXIT;
        return NULL;
-} /* obdfs_find_in_page_list */
+} /* obdfs_find_page_index */
 
 
-/* call and free pages from Linux page cache */
+/* call and free pages from Linux page cache: called with io lock on inodes */
 int obdfs_do_vec_wr(struct inode **inodes, obd_count num_io,
                    obd_count num_obdos, struct obdo **obdos,
                    obd_count *oa_bufs, struct page **pages, char **bufs,
@@ -228,10 +232,8 @@ int obdfs_do_vec_wr(struct inode **inodes, obd_count num_io,
        /* release the pages from the page cache */
        while ( num_io > 0 ) {
                num_io--;
-               CDEBUG(D_INODE, "calling put_page for %p, index %ld\n", pages[num_io], pages[num_io]->index);
-               /*
-               UnlockPage(pages[num_io]);
-               */
+               CDEBUG(D_INODE, "calling put_page for %p, index %ld\n",
+                      pages[num_io], pages[num_io]->index);
                put_page(pages[num_io]);
        }
 
@@ -258,6 +260,7 @@ static int obdfs_add_page_to_cache(struct inode *inode, struct page *page)
        ENTRY;
 
        /* If this page isn't already in the inode page list, add it */
+       obd_down(&obdfs_i2sbi(inode)->osi_list_mutex);
        if ( !obdfs_find_in_page_list(inode, page) ) {
                struct obdfs_pgrq *pgrq;
                pgrq = kmem_cache_alloc(obdfs_pgrq_cachep, SLAB_KERNEL);
@@ -265,6 +268,7 @@ static int obdfs_add_page_to_cache(struct inode *inode, struct page *page)
                       inode->i_ino, page, pgrq, obdfs_cache_count);
                if (!pgrq) {
                        EXIT;
+                       obd_up(&obdfs_i2sbi(inode)->osi_list_mutex);
                        return -ENOMEM;
                }
                memset(pgrq, 0, sizeof(*pgrq)); 
@@ -272,25 +276,28 @@ static int obdfs_add_page_to_cache(struct inode *inode, struct page *page)
                pgrq->rq_page = page;
                get_page(pgrq->rq_page);
                list_add(&pgrq->rq_plist, obdfs_iplist(inode));
+               obdfs_cache_count++;
        }
 
-       /* If inode isn't already on the superblock inodes list, add it */
+       /* If inode isn't already on the superblock inodes list, add it,
+        * and increase ref count on inode so it doesn't disappear on us.
+        */
        if ( list_empty(obdfs_islist(inode)) ) {
+               iget(inode->i_sb, inode->i_ino);
                CDEBUG(D_INODE, "adding inode %ld to superblock list %p\n",
                       inode->i_ino, obdfs_slist(inode));
                list_add(obdfs_islist(inode), obdfs_slist(inode));
        }
 
-
        /* XXX For testing purposes, we write out the page here.
         *     In the future, a flush daemon will write out the page.
        res = obdfs_flush_reqs(obdfs_slist(inode), 0);
        obdfs_flush_dirty_pages(1);
         */
+       obd_up(&obdfs_i2sbi(inode)->osi_list_mutex);
 
        EXIT;
        return res;
-       /*return 0;*/
 } /* obdfs_add_page_to_cache */
 
 
@@ -359,16 +366,18 @@ int obdfs_write_one_page(struct file *file, struct page *page,
 } /* obdfs_write_one_page */
 
 /* 
-   return an up to date page:
-    - if locked is true then is returned locked
-    - if create is true the corresponding disk blocks are created 
-    - page is held, i.e. caller must release the page
-
-   modeled on NFS code.
-*/
-struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create, int locked)
+ * return an up to date page:
+ *  - if locked is true then is returned locked
+ *  - if create is true the corresponding disk blocks are created 
+ *  - page is held, i.e. caller must release the page
+ *
+ * modeled on NFS code.
+ */
+struct page *obdfs_getpage(struct inode *inode, unsigned long offset,
+                          int create, int locked)
 {
        struct page *page_cache;
+       int index;
        struct page ** hash;
        struct page * page;
        int err;
@@ -376,8 +385,11 @@ struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create
        ENTRY;
 
        offset = offset & PAGE_CACHE_MASK;
-       CDEBUG(D_INODE, "\n");
-       
+       CDEBUG(D_INODE, "ino: %ld, offset %ld, create %d, locked %d\n",
+              inode->i_ino, offset, create, locked);
+       index = offset >> PAGE_CACHE_SHIFT;
+
+
        page = NULL;
        page_cache = page_cache_alloc();
        if ( ! page_cache ) {
@@ -386,8 +398,8 @@ struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create
        }
        CDEBUG(D_INODE, "page_cache %p\n", page_cache);
 
-       hash = page_hash(&inode->i_data, offset);
-       page = grab_cache_page(&inode->i_data, offset);
+       hash = page_hash(&inode->i_data, index);
+       page = grab_cache_page(&inode->i_data, index);
 
        /* Yuck, no page */
        if (! page) {
@@ -406,8 +418,9 @@ struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create
        } 
 
 
-       if ( obdfs_find_page_index(inode, offset) ) {
-               printk("OVERWRITE: found dirty page %p, index %ld\n", page, page->index);
+       if ( obdfs_find_page_index(inode, index) ) {
+               CDEBUG(D_INODE, "OVERWRITE: found dirty page %p, index %ld\n",
+                      page, page->index);
        }
 
        err = obdfs_brw(READ, inode, page, create);