Whamcloud - gitweb
obdfs/dir.c: add truncate method for directory
authoradilger <adilger>
Thu, 9 Mar 2000 00:51:58 +0000 (00:51 +0000)
committeradilger <adilger>
Thu, 9 Mar 2000 00:51:58 +0000 (00:51 +0000)
obdfs/flushd.c: don't hold list lock when checking page "dirty" bit
obdfs/namei.c: handle block special devices in filesystem

lustre/obdfs/dir.c
lustre/obdfs/file.c
lustre/obdfs/flushd.c
lustre/obdfs/namei.c
lustre/obdfs/rw.c
lustre/obdfs/super.c

index 698b68c..56db69a 100644 (file)
@@ -79,7 +79,7 @@ struct inode_operations obdfs_dir_inode_operations = {
        NULL,                   /* get_block */
        obdfs_readpage,         /* readpage */
        obdfs_writepage,        /* writepage */
-       NULL,                   /* truncate */
+       obdfs_truncate,         /* truncate */
        NULL,                   /* permission */
        NULL                    /* revalidate */
 };
index decec1a..4416161 100644 (file)
@@ -80,7 +80,7 @@ struct file_operations obdfs_file_operations = {
        NULL,                   /* readdir - bad */
        NULL,                   /* poll */
        NULL,                   /* ioctl */
-       generic_file_mmap, 
+       generic_file_mmap,      /* mmap */
        NULL,                   /* open */
        NULL,                   /* flush */
        NULL,                   /* release */
index 638dd54..ec6a1fc 100644 (file)
@@ -34,9 +34,9 @@ struct {
        int interval; /* jiffies delay between pupdate flushes */
        int age_buffer;  /* Time for normal buffer to age before we flush it */
        int age_super;  /* Time for superblock to age before we flush it */
-} pupd_prm = {40, 500, 64, 256, 5*HZ, 30*HZ, 5*HZ };
+} pupd_prm = {40, 1024, 64, 256, 1*HZ, 30*HZ, 5*HZ };
 
-/* Called with the superblock list lock */
+/* Called with the superblock list lock held */
 static int obdfs_enqueue_pages(struct inode *inode, struct obdo **obdo,
                               int nr_slots, struct page **pages, char **bufs,
                               obd_size *counts, obd_off *offsets,
@@ -110,6 +110,7 @@ void obdfs_dequeue_pages(struct inode *inode)
 {
        struct list_head *tmp;
 
+       ENTRY;
        obd_down(&obdfs_i2sbi(inode)->osi_list_mutex);
        tmp = obdfs_islist(inode);
        if ( list_empty(tmp) ) {
@@ -140,6 +141,7 @@ void obdfs_dequeue_pages(struct inode *inode)
 
        /* decrement inode reference for page cache */
        inode->i_count--;
+       EXIT;
 }
 
 /* Remove writeback requests for the superblock */
@@ -171,7 +173,7 @@ int obdfs_flush_reqs(struct list_head *inode_list, unsigned long check_time)
 
        obd_down(&sbi->osi_list_mutex);
        if ( list_empty(inode_list) ) {
-               CDEBUG(D_CACHE, "list empty: memory %ld\n", obd_memory);
+               CDEBUG(D_INFO, "list empty\n");
                obd_up(&sbi->osi_list_mutex);
                EXIT;
                return 0;
@@ -221,12 +223,14 @@ int obdfs_flush_reqs(struct list_head *inode_list, unsigned long check_time)
                                err = res;
                                EXIT;
                                goto BREAK;
-                       } else if (res) {
-                               num_io += res;
-                               total_io += res;
-                               bufs_per_obdo[num_obdos] = res;
-                               num_obdos++;
                        }
+                       if (res == 0)
+                               continue;
+
+                       num_io += res;
+                       total_io += res;
+                       bufs_per_obdo[num_obdos] = res;
+                       num_obdos++;
 
                        if ( num_io == MAX_IOVEC ) {
                                obd_up(&sbi->osi_list_mutex);
@@ -236,7 +240,8 @@ int obdfs_flush_reqs(struct list_head *inode_list, unsigned long check_time)
                                                      offsets, flags);
                                if ( err ) {
                                        CDEBUG(D_INODE,
-                                               "fatal: unable to do vec_wr (err %d)\n", err);
+                                              "fatal: do_vec_wr err=%d\n",
+                                              err);
                                        EXIT;
                                        goto ERR;
                                }
@@ -372,30 +377,36 @@ static int pupdate(void *unused)
                obdfs_flush_dirty_inodes(jiffies - pupd_prm.age_super);
                 */
                dirty_limit = nr_free_buffer_pages() * pupd_prm.nfract / 100;
-               CDEBUG(D_CACHE, "dirty_limit %ld, cache_count %ld, wrote %d\n",
-                      dirty_limit, obdfs_cache_count, wrote);
 
                if (obdfs_cache_count > dirty_limit) {
                        interval = 0;
                        if ( wrote < pupd_prm.ndirty )
                                age >>= 1;
-                       CDEBUG(D_CACHE, "age %ld, interval %d\n",
-                               age, interval);
+                       CDEBUG(D_CACHE, "wrote %d, age %ld, interval %d\n",
+                               wrote, age, interval);
                } else {
                        if ( wrote < pupd_prm.ndirty >> 1 &&
                             obdfs_cache_count < dirty_limit / 2) {
                                interval = pupd_prm.interval;
                                age = pupd_prm.age_buffer;
+                               CDEBUG(D_INFO,
+                                      "wrote %d, age %ld, interval %d\n",
+                                      wrote, age, interval);
                        } else if (obdfs_cache_count > dirty_limit / 2) {
                                interval >>= 1;
                                if ( wrote < pupd_prm.ndirty )
                                        age >>= 1;
-                               CDEBUG(D_CACHE, "age %ld, interval %d\n",
-                                      age, interval);
+                               CDEBUG(D_CACHE,
+                                      "wrote %d, age %ld, interval %d\n",
+                                      wrote, age, interval);
                        }
                }
 
                wrote = obdfs_flush_dirty_pages(jiffies - age);
+               if (wrote)
+                       CDEBUG(D_CACHE,
+                              "dirty_limit %ld, cache_count %ld, wrote %d\n",
+                              dirty_limit, obdfs_cache_count, wrote);
        }
 }
 
index c3f12e0..c474514 100644 (file)
@@ -257,7 +257,7 @@ static struct page *obdfs_add_entry (struct inode * dir,
                                EXIT;
                                return NULL;
                        }
-                       PDEBUG(page, "new directory page");
+                       /* PDEBUG(page, "new directory page"); */
                        if (dir->i_size <= offset) {
                                if (dir->i_size == 0) {
                                        *err = -ENOENT;
@@ -275,7 +275,7 @@ static struct page *obdfs_add_entry (struct inode * dir,
                                mark_inode_dirty(dir);
                        } else {
 
-                               ext2_debug ("skipping to next block\n");
+                               CDEBUG(D_INFO, "skipping to next block\n");
 
                                de = (struct ext2_dir_entry_2 *) page_address(page);
                        }
@@ -346,7 +346,6 @@ static struct page *obdfs_add_entry (struct inode * dir,
                }
                offset += le16_to_cpu(de->rec_len);
                de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
-               
        }
 
        UnlockPage(page);
@@ -556,6 +555,7 @@ int obdfs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
        struct inode * inode;
        struct page *page;
        struct ext2_dir_entry_2 * de;
+       struct obdfs_inode_info *oinfo;
        int err;
 
         ENTRY;
@@ -567,6 +567,10 @@ int obdfs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
 
        inode->i_uid = current->fsuid;
        init_special_inode(inode, mode, rdev);
+       oinfo = obdfs_i2info(inode);
+       ((obd_count *)oinfo->oi_inline)[0] = rdev;
+       oinfo->oi_flags |= OBD_FL_INLINEDATA;
+
        page = obdfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
        if (!page)
                goto out_no_entry;
index 7a2dab7..8eac82e 100644 (file)
@@ -121,8 +121,8 @@ inline void obdfs_pgrq_del(struct obdfs_pgrq *pgrq)
        --obdfs_cache_count;
        CDEBUG(D_INFO, "deleting page %p from list [count %ld]\n",
               pgrq->rq_page, obdfs_cache_count);
-       OBDClearCachePage(pgrq->rq_page);
        list_del(&pgrq->rq_plist);
+       OBDClearCachePage(pgrq->rq_page);
        kmem_cache_free(obdfs_pgrq_cachep, pgrq);
 }
 
@@ -143,46 +143,6 @@ void obdfs_cleanup_pgrqcache(void)
 } /* obdfs_cleanup_wreqcache */
 
 
-/*
- * See whether a specific page in the page cache.
- * Called with the list lock held.
- */
-#ifdef PG_obdcache
-#define obdfs_find_in_page_list(inode, page) OBDAddCachePage(page)
-#else
-static int obdfs_find_in_page_list(struct inode *inode, struct page *page)
-{
-       struct list_head *page_list = obdfs_iplist(inode);
-       struct list_head *tmp;
-
-       ENTRY;
-
-       CDEBUG(D_INFO, "looking for inode %ld page %p\n", inode->i_ino, page);
-       OIDEBUG(inode);
-
-       if (list_empty(page_list)) {
-               CDEBUG(D_INFO, "empty list\n");
-               EXIT;
-               return 0;
-       }
-       tmp = page_list;
-       while ( (tmp = tmp->next) != page_list ) {
-               struct obdfs_pgrq *pgrq;
-
-               pgrq = list_entry(tmp, struct obdfs_pgrq, rq_plist);
-               if (pgrq->rq_page == page) {
-                       CDEBUG(D_INFO, "found page %p in list\n", page);
-                       EXIT;
-                       return 1;
-               }
-       } 
-
-       EXIT;
-       return 0;
-} /* obdfs_find_in_page_list */
-#endif
-
-
 /* called with the list lock held */
 static struct page *obdfs_find_page_index(struct inode *inode,
                                          unsigned long index)
@@ -238,7 +198,7 @@ int obdfs_do_vec_wr(struct inode **inodes, obd_count num_io,
 
        CDEBUG(D_INFO, "writing %d page(s), %d obdo(s) in vector\n",
               num_io, num_obdos);
-       { /* DEBUGGING */
+       if (obd_debug_level & D_INFO) { /* DEBUGGING */
                int i;
                printk("OBDOS: ");
                for (i = 0; i < num_obdos; i++)
@@ -253,7 +213,7 @@ int obdfs_do_vec_wr(struct inode **inodes, obd_count num_io,
        err = IOPS(inodes[0], brw)(WRITE, IID(inodes[0]), num_obdos, obdos,
                                  oa_bufs, bufs, counts, offsets, flags);
 
-       CDEBUG(D_CACHE, "BRW done\n");
+       CDEBUG(D_INFO, "BRW done\n");
        /* release the pages from the page cache */
        while ( num_io > 0 ) {
                --num_io;
@@ -263,7 +223,7 @@ int obdfs_do_vec_wr(struct inode **inodes, obd_count num_io,
                put_page(pages[num_io]);
                /* PDEBUG(pages[num_io], "do_vec_wr"); */
        }
-       CDEBUG(D_CACHE, "put_page done\n");
+       CDEBUG(D_INFO, "put_page done\n");
 
        while ( num_obdos > 0) {
                --num_obdos;
@@ -271,69 +231,76 @@ int obdfs_do_vec_wr(struct inode **inodes, obd_count num_io,
                obdfs_to_inode(inodes[num_obdos], obdos[num_obdos]);
                obdo_free(obdos[num_obdos]);
        }
-       CDEBUG(D_CACHE, "obdo_free done\n");
+       CDEBUG(D_INFO, "obdo_free done\n");
        EXIT;
        return err;
 }
 
 
 /*
- * Add a page to the write request cache list for later writing
+ * Add a page to the write request cache list for later writing.
  * ASYNCHRONOUS write method.
  */
 static int obdfs_add_page_to_cache(struct inode *inode, struct page *page)
 {
-       int res = 0;
-
+       int err = 0;
        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) ) {
+       /* The PG_obdcache bit is cleared by obdfs_pgrq_del() BEFORE the page
+        * is written, so at worst we will write the page out twice.
+        *
+        * If the page has the PG_obdcache bit set, then the inode MUST be
+        * on the superblock dirty list so we don't need to check this.
+        * Dirty inodes are removed from the superblock list ONLY when they
+        * don't have any more cached pages.  It is possible to have an inode
+        * with no dirty pages on the superblock list, but not possible to
+        * have an inode with dirty pages NOT on the superblock dirty list.
+        */
+       if (!OBDAddCachePage(page)) {
                struct obdfs_pgrq *pgrq;
                pgrq = kmem_cache_alloc(obdfs_pgrq_cachep, SLAB_KERNEL);
                if (!pgrq) {
+                       OBDClearCachePage(page);
                        EXIT;
-                       obd_up(&obdfs_i2sbi(inode)->osi_list_mutex);
                        return -ENOMEM;
                }
+               /* not really necessary since we set all pgrq fields here
                memset(pgrq, 0, sizeof(*pgrq)); 
+               */
                
                pgrq->rq_page = page;
                pgrq->rq_jiffies = jiffies;
                get_page(pgrq->rq_page);
+
+               obd_down(&obdfs_i2sbi(inode)->osi_list_mutex);
                list_add(&pgrq->rq_plist, obdfs_iplist(inode));
                obdfs_cache_count++;
-               CDEBUG(D_INFO,
-                      "added inode %ld page %p, pgrq: %p, cache count [%ld]\n",
-                      inode->i_ino, page, pgrq, obdfs_cache_count);
-       }
 
-       /* 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.
-        *
-        * We increment the reference count on the inode to keep it from
-        * being freed from memory.  This _should_ be an iget() with an
-        * iput() in both flush_reqs() and put_inode(), but since put_inode()
-        * is called from iput() we can't call iput() again there.  Instead
-        * we just increment/decrement i_count, which is essentially what
-        * iget/iput do for an inode already in memory.
-        */
-       if ( list_empty(obdfs_islist(inode)) ) {
-               inode->i_count++;
-               CDEBUG(D_INFO, "adding inode %ld to superblock list %p\n",
-                      inode->i_ino, obdfs_slist(inode));
-               list_add(obdfs_islist(inode), obdfs_slist(inode));
+               /* If inode isn't already on superblock inodes list, add it.
+                *
+                * We increment the reference count on the inode to keep it
+                * from being freed from memory.  This _should_ be an iget()
+                * with an iput() in both flush_reqs() and put_inode(), but
+                * since put_inode() is called from iput() we can't call iput()
+                * again there.  Instead we just increment/decrement i_count,
+                * which is mostly what iget/iput do for an inode in memory.
+                */
+               if ( list_empty(obdfs_islist(inode)) ) {
+                       inode->i_count++;
+                       CDEBUG(D_INFO,
+                              "adding inode %ld to superblock list %p\n",
+                              inode->i_ino, obdfs_slist(inode));
+                       list_add(obdfs_islist(inode), obdfs_slist(inode));
+               }
+               obd_up(&obdfs_i2sbi(inode)->osi_list_mutex);
        }
-       obd_up(&obdfs_i2sbi(inode)->osi_list_mutex);
 
-       /* 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), ~0UL);
+       /* XXX For testing purposes, we can write out the page here.
+       err = obdfs_flush_reqs(obdfs_slist(inode), ~0UL);
         */
 
        EXIT;
-       return res;
+       return err;
 } /* obdfs_add_page_to_cache */
 
 
@@ -500,7 +467,7 @@ void obdfs_truncate(struct inode *inode)
                oa->o_valid = OBD_MD_FLNOTOBD;
                obdfs_from_inode(oa, inode);
 
-               CDEBUG(D_PUNCH, "calling punch for %ld (%Lu bytes at 0)\n",
+               CDEBUG(D_INFO, "calling punch for %ld (%Lu bytes at 0)\n",
                       (long)oa->o_id, oa->o_size);
                err = IOPS(inode, punch)(IID(inode), oa, oa->o_size, 0);
 
index f092c88..87f76c2 100644 (file)
@@ -35,6 +35,7 @@
 struct list_head obdfs_super_list;
 struct super_operations obdfs_super_operations;
 long obdfs_cache_count = 0;
+long obdfs_mutex_start = 0;
 long obd_memory = 0;
 
 static char *obdfs_read_opt(const char *opt, char *data)
@@ -307,8 +308,7 @@ static void obdfs_read_inode(struct inode *inode)
                EXIT;
        } else {
                init_special_inode(inode, inode->i_mode,
-                                  /* XXX need to fill in the ext2 side */
-                                  ((long *)obdfs_i2info(inode)->oi_inline)[0]);
+                                  ((int *)obdfs_i2info(inode)->oi_inline)[0]);
        }
 
        return;
@@ -390,6 +390,7 @@ static void obdfs_delete_inode(struct inode *inode)
        oa->o_valid = OBD_MD_FLNOTOBD;
        obdfs_from_inode(oa, inode);
 
+       ODEBUG(oa);
        err = IOPS(inode, destroy)(IID(inode), oa);
        obdo_free(oa);