Whamcloud - gitweb
Lots of bug fixes:
authorbraam <braam>
Tue, 25 Jan 2000 01:54:21 +0000 (01:54 +0000)
committerbraam <braam>
Tue, 25 Jan 2000 01:54:21 +0000 (01:54 +0000)
 - directories greater than 4k
 - iget to hold inodes while they are in the WB cache
 - generic_file_mmap for executables

lustre/demos/obdfssetup.sh
lustre/include/linux/obd_support.h
lustre/include/linux/obdfs.h
lustre/obdfs/file.c
lustre/obdfs/flushd.c
lustre/obdfs/namei.c
lustre/obdfs/rw.c
lustre/obdfs/super.c

index 0c1dd5d..bf37c39 100755 (executable)
@@ -4,6 +4,7 @@ OBDDIR="`dirname $0`/.."
 .  $OBDDIR/demos/config.sh
 
 $OBDDIR/demos/basesetup.sh
+#losetup /dev/loop0 /tmp/obdfs.tmpfile
 
 if [ x$? != x0 ]; then 
     echo "Error running basesetup.sh"
index a37aa93..a9eafc2 100644 (file)
@@ -65,9 +65,9 @@ extern int obd_print_entry;
               "size %Ld, blocks %ld\n", __FUNCTION__ , __LINE__,\
               inode->i_ino, inode->i_atime, inode->i_mtime, inode->i_ctime,\
               inode->i_size, inode->i_blocks);\
-       printk("]]%s line %d[[ mode %o, uid %d, gid %d, nlnk %d\n",\
+       printk("]]%s line %d[[ mode %o, uid %d, gid %d, nlnk %d, count %d\n",\
               __FUNCTION__, __LINE__, inode->i_mode, inode->i_uid,\
-              inode->i_gid, inode->i_nlink);\
+              inode->i_gid, inode->i_nlink, inode->i_count);\
 }
 
 /* Ext2 inode information */
@@ -84,7 +84,7 @@ extern int obd_print_entry;
 #define OIDEBUG(inode) { \
        ICDEBUG(inode);\
        printk("oinfo: flags 0x%08x\n", OBDFS_INFO(inode)->oi_flags);\
-       obdfs_print_plist(inode);\
+       /* obdfs_print_plist(inode); */\
 }
 
 #define ODEBUG(obdo) { \
index 67a0ed1..62be45e 100644 (file)
@@ -76,6 +76,7 @@ struct obdfs_sb_info {
        ino_t                    osi_rootino;   /* number of root inode */
        int                      osi_minor;     /* minor of /dev/obdX */
        struct list_head         osi_inodes;    /* list of dirty inodes */
+       struct semaphore         osi_list_mutex;
 };
 
 struct obdfs_inode_info {
@@ -87,6 +88,14 @@ struct obdfs_inode_info {
 
 #define OBDFS_INFO(inode) ((struct obdfs_inode_info *)(&(inode)->u.generic_ip))
 
+static inline struct obdfs_sb_info *obdfs_i2sbi(struct inode *inode)
+{
+       struct obdfs_sb_info *sbi;
+
+       sbi = (struct obdfs_sb_info *) &(inode->i_sb->u.generic_sbp);
+       return sbi;
+}
+
 static inline struct list_head *obdfs_iplist(struct inode *inode) 
 {
        struct obdfs_inode_info *info = (struct obdfs_inode_info *)&inode->u.generic_ip;
@@ -101,18 +110,32 @@ static inline struct list_head *obdfs_islist(struct inode *inode)
        return &info->oi_inodes;
 }
 
-static inline struct list_head *obdfs_slist(struct inode *inode) {
-       struct obdfs_sb_info *sbi = (struct obdfs_sb_info *)(&inode->i_sb->u.generic_sbp);
+static inline struct list_head *obdfs_slist(struct inode *inode) 
+{
+       struct obdfs_sb_info *sbi = obdfs_i2sbi(inode);
        return &sbi->osi_inodes;
 }
 
-static inline void obdfs_print_plist(struct inode *inode) {
+#define obd_down(mutex) {\
+       CDEBUG(D_INODE, "got lock at %s, %d\n", __FUNCTION__, __LINE__);\
+       down(mutex);\
+}
+
+#define obd_up(mutex) {\
+       up(mutex);\
+       CDEBUG(D_INODE, "free lock at %s, %d\n", __FUNCTION__, __LINE__);\
+}
+
+static inline void obdfs_print_plist(struct inode *inode) 
+{
        struct list_head *page_list = obdfs_iplist(inode);
        struct list_head *tmp;
 
        CDEBUG(D_INODE, "inode %ld: page", inode->i_ino);
+       /* obd_down(&obdfs_i2sbi(inode)->osi_list_mutex); */
        if (list_empty(page_list)) {
                printk(" list empty\n");
+               obd_up(&obdfs_i2sbi(inode)->osi_list_mutex);
                return;
        }
 
@@ -123,6 +146,7 @@ static inline void obdfs_print_plist(struct inode *inode) {
                printk(" %p", pgrq->rq_page);
        }
        printk("\n");
+       /* obd_up(&obdfs_i2sbi(inode)->osi_list_mutex); */
 }
 
 void obdfs_sysctl_init(void);
index 75c8617..b41f54f 100644 (file)
@@ -79,7 +79,7 @@ struct file_operations obdfs_file_operations = {
        NULL,                   /* readdir - bad */
        NULL,                   /* poll - default */
        NULL,                   /* ioctl */
-       generic_file_mmap,      /* mmap */
+       generic_file_mmap, 
        NULL,                   /* no special open code */
        NULL,                   /* flush */
        NULL,                   /* no special release code */
index 7d6f798..c090a0c 100644 (file)
@@ -51,14 +51,8 @@ struct {
 /* } pupd_prm = {40, 500, 64, 256, 5*HZ, 30*HZ, 5*HZ };  */
 } pupd_prm = {40, 500, 64, 256, 10*HZ, 30*HZ, 5*HZ }; 
 
-#if 0
-static void obdfs_lock_page(struct page *page)
-{
-        while (TryLockPage(page))
-                ___wait_on_page(page);
-}
-#endif
 
+/* Called with the superblock list lock */
 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,
@@ -97,9 +91,6 @@ static int obdfs_enqueue_pages(struct inode *inode, struct obdo **obdo,
                 * Note that obdfs_pgrq_del() also deletes the request.
                 */
                obdfs_pgrq_del(req);
-               /* 
-               obdfs_lock_page(page);
-               */
                if ( !page ) {
                        CDEBUG(D_INODE, "no page \n");
                        continue;
@@ -128,8 +119,10 @@ void obdfs_dequeue_reqs(struct inode *inode)
 
        struct list_head *tmp;
 
+       obd_down(&obdfs_i2sbi(inode)->osi_list_mutex);
        tmp = obdfs_islist(inode);
        if ( list_empty(tmp) ) {
+               obd_up(&obdfs_i2sbi(inode)->osi_list_mutex);
                EXIT;
                return;
        }
@@ -150,14 +143,14 @@ void obdfs_dequeue_reqs(struct inode *inode)
                /* now put the page away */
                put_page(page);
        }
-
+       iput(inode);
+       obd_up(&obdfs_i2sbi(inode)->osi_list_mutex);
 }
 
-
 /* Remove writeback requests for the superblock */
 int obdfs_flush_reqs(struct list_head *inode_list, int check_time)
 {
-       struct list_head *tmp = inode_list;
+       struct list_head *tmp;
        int               total_io = 0;
        obd_count         num_io = 0;
        obd_count         num_obdos = 0;
@@ -170,6 +163,8 @@ int obdfs_flush_reqs(struct list_head *inode_list, int check_time)
        obd_flag          flags[MAX_IOVEC];
        obd_count         bufs_per_obdo[MAX_IOVEC];
        int               err = 0;
+       struct obdfs_sb_info *sbi;
+
 
        ENTRY;
 
@@ -179,14 +174,21 @@ int obdfs_flush_reqs(struct list_head *inode_list, int check_time)
                return 0;
        }
 
+       sbi = list_entry(inode_list, struct obdfs_sb_info, osi_inodes);
+
+       obd_down(&sbi->osi_list_mutex);
        if ( list_empty(inode_list)) {
                CDEBUG(D_INODE, "list empty\n");
+               obd_up(&sbi->osi_list_mutex);
                EXIT;
                return 0;
        }
 
-       /* add each inode's outstanding pages to a write vector, and write it */
-       while ( (tmp = tmp->next) != inode_list && total_io < pupd_prm.ndirty) {
+       /* add each inode's dirty pages to a write vector, and write it */
+ again:
+       tmp = inode_list;
+       while ( (tmp = tmp->next) != inode_list && 
+               total_io < pupd_prm.ndirty) {
                struct obdfs_inode_info *ii;
                struct inode *inode;
                int res;
@@ -194,6 +196,7 @@ int obdfs_flush_reqs(struct list_head *inode_list, int check_time)
                ii = list_entry(tmp, struct obdfs_inode_info, oi_inodes);
                inode = list_entry(ii, struct inode, u);
                inodes[num_obdos] = inode;
+               CDEBUG(D_INODE, "checking inode %ld pages\n", inode->i_ino);
 
                res = 1;
 
@@ -209,10 +212,11 @@ int obdfs_flush_reqs(struct list_head *inode_list, int check_time)
                                                  &pages[num_io], &bufs[num_io],
                                                  &counts[num_io],
                                                  &offsets[num_io],
-                                                 &flags[num_obdos],1);
+                                                 &flags[num_obdos], 1);
                        CDEBUG(D_INODE, "FLUSHED inode %ld, pages flushed: %d\n", 
                               inode->i_ino, res);
                        if ( res < 0 ) {
+                               obd_up(&sbi->osi_list_mutex);
                                err = res;
                                goto ERR;
                        }
@@ -223,6 +227,7 @@ int obdfs_flush_reqs(struct list_head *inode_list, int check_time)
                        num_obdos++;
 
                        if ( num_io == MAX_IOVEC ) {
+                               obd_up(&sbi->osi_list_mutex);
                                err = obdfs_do_vec_wr(inodes, num_io, num_obdos,
                                                      obdos, bufs_per_obdo,
                                                      pages, bufs, counts,
@@ -234,28 +239,45 @@ int obdfs_flush_reqs(struct list_head *inode_list, int check_time)
                                inodes[0] = inode;
                                num_io = 0;
                                num_obdos = 0;
+                               obd_down(&sbi->osi_list_mutex);
+                               goto again;
                        }
                }
+       }
 
-               /* Remove inode from superblock dirty list when no more pages.
-                * Make sure we don't point at the current inode with tmp
-                * when we re-init the list on the inode, or we will loop.
-                */
+       obd_up(&sbi->osi_list_mutex);
+
+       /* flush any remaining I/Os */
+       if ( num_io ) {
+               err = obdfs_do_vec_wr(inodes, num_io, num_obdos, obdos,
+                                     bufs_per_obdo, pages, bufs, counts,
+                                     offsets, flags);
+       }
+
+       /* Remove inode from superblock dirty list when no more pages.
+        * Make sure we don't point at the current inode with tmp
+        * when we re-init the list on the inode, or we will loop.
+        */
+       obd_down(&sbi->osi_list_mutex);
+       tmp = inode_list;
+       while ( (tmp = tmp->next) != inode_list ) {
+               struct obdfs_inode_info *ii;
+               struct inode *inode;
+
+               ii = list_entry(tmp, struct obdfs_inode_info, oi_inodes);
+               inode = list_entry(ii, struct inode, u);
+               CDEBUG(D_INODE, "checking inode %ld empty\n", inode->i_ino);
                if (list_empty(obdfs_iplist(inode))) {
                        CDEBUG(D_INODE, "remove inode %ld from dirty list\n",
                               inode->i_ino);
                        tmp = tmp->prev;
                        list_del(obdfs_islist(inode));
+                       iput(inode);
                        INIT_LIST_HEAD(obdfs_islist(inode));
                }
        }
+       obd_up(&sbi->osi_list_mutex);
 
-       /* flush any remaining I/Os */
-       if ( num_io ) {
-               err = obdfs_do_vec_wr(inodes, num_io, num_obdos, obdos,
-                                     bufs_per_obdo, pages, bufs, counts,
-                                     offsets, flags);
-       }
        CDEBUG(D_INODE, "flushed %d pages in total\n", total_io);
        EXIT;
 ERR:
index ea94b01..c8fde32 100644 (file)
@@ -198,12 +198,14 @@ struct dentry *obdfs_lookup(struct inode *dir, struct dentry *dentry)
  * NOTE!! The inode part of 'de' is left at 0 - which means you
  * may not sleep between calling this and putting something into
  * the entry, as someone else might have used it while you slept.
-
+ *
  * returns a locked and held page upon success 
  */
 
 
-/* We do this with a locked page: that's not necessary, since the semaphore on the inode protects this page as well. */
+/* We do this with a locked page: that's not necessary, since the semaphore
+ * on the inode protects this page as well.
+ */
 static struct page *obdfs_add_entry (struct inode * dir,
                                     const char * name, int namelen,
                                     struct ext2_dir_entry_2 ** res_dir,
index 1f451d8..78bc0b0 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>
@@ -142,6 +142,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 +156,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 +177,8 @@ 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 +186,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 +201,7 @@ 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 in list, index %ld\n", page, index);
                        EXIT;
                        return page;
                }
@@ -206,10 +209,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,
@@ -229,9 +232,6 @@ int obdfs_do_vec_wr(struct inode **inodes, obd_count num_io,
        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]);
-               */
                put_page(pages[num_io]);
        }
 
@@ -258,6 +258,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 +266,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)); 
@@ -274,19 +276,22 @@ static int obdfs_add_page_to_cache(struct inode *inode, struct page *page)
                list_add(&pgrq->rq_plist, obdfs_iplist(inode));
        }
 
-       /* 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;
@@ -359,16 +364,17 @@ 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.
-*/
* 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 +382,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 +395,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,7 +415,7 @@ struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create
        } 
 
 
-       if ( obdfs_find_page_index(inode, offset) ) {
+       if ( obdfs_find_page_index(inode, index) ) {
                printk("OVERWRITE: found dirty page %p, index %ld\n", page, page->index);
        }
 
index e5d04a7..f4cdf0c 100644 (file)
@@ -196,6 +196,7 @@ static struct super_block * obdfs_read_super(struct super_block *sb,
        }
 
        INIT_LIST_HEAD(&sbi->osi_inodes);
+       sema_init(&sbi->osi_list_mutex, 1);
 
        sbi->osi_super = sb;
 
@@ -307,6 +308,7 @@ void obdfs_read_inode(struct inode *inode)
        INIT_LIST_HEAD(obdfs_iplist(inode)); /* list of dirty pages on inode */
        INIT_LIST_HEAD(obdfs_islist(inode)); /* list of inodes in superblock */
 
+
        obdo_free(oa);
        /* OIDEBUG(inode); */