From 9df089d4803a1ba44299d5cb30fb4e31c83f7db2 Mon Sep 17 00:00:00 2001 From: braam Date: Tue, 25 Jan 2000 01:54:21 +0000 Subject: [PATCH] Lots of bug fixes: - directories greater than 4k - iget to hold inodes while they are in the WB cache - generic_file_mmap for executables --- lustre/demos/obdfssetup.sh | 1 + lustre/include/linux/obd_support.h | 6 ++-- lustre/include/linux/obdfs.h | 30 ++++++++++++++-- lustre/obdfs/file.c | 2 +- lustre/obdfs/flushd.c | 74 ++++++++++++++++++++++++-------------- lustre/obdfs/namei.c | 6 ++-- lustre/obdfs/rw.c | 57 ++++++++++++++++------------- lustre/obdfs/super.c | 2 ++ 8 files changed, 119 insertions(+), 59 deletions(-) diff --git a/lustre/demos/obdfssetup.sh b/lustre/demos/obdfssetup.sh index 0c1dd5d..bf37c39 100755 --- a/lustre/demos/obdfssetup.sh +++ b/lustre/demos/obdfssetup.sh @@ -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" diff --git a/lustre/include/linux/obd_support.h b/lustre/include/linux/obd_support.h index a37aa93..a9eafc2 100644 --- a/lustre/include/linux/obd_support.h +++ b/lustre/include/linux/obd_support.h @@ -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) { \ diff --git a/lustre/include/linux/obdfs.h b/lustre/include/linux/obdfs.h index 67a0ed1..62be45e 100644 --- a/lustre/include/linux/obdfs.h +++ b/lustre/include/linux/obdfs.h @@ -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); diff --git a/lustre/obdfs/file.c b/lustre/obdfs/file.c index 75c8617..b41f54f 100644 --- a/lustre/obdfs/file.c +++ b/lustre/obdfs/file.c @@ -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 */ diff --git a/lustre/obdfs/flushd.c b/lustre/obdfs/flushd.c index 7d6f798..c090a0c 100644 --- a/lustre/obdfs/flushd.c +++ b/lustre/obdfs/flushd.c @@ -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: diff --git a/lustre/obdfs/namei.c b/lustre/obdfs/namei.c index ea94b011..c8fde32 100644 --- a/lustre/obdfs/namei.c +++ b/lustre/obdfs/namei.c @@ -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, diff --git a/lustre/obdfs/rw.c b/lustre/obdfs/rw.c index 1f451d8..78bc0b0 100644 --- a/lustre/obdfs/rw.c +++ b/lustre/obdfs/rw.c @@ -5,7 +5,7 @@ * Copryright (C) 1999 Stelias Computing Inc, * (author Peter J. Braam ) * Copryright (C) 1999 Seagate Technology Inc. - */ +*/ #include @@ -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); } diff --git a/lustre/obdfs/super.c b/lustre/obdfs/super.c index e5d04a7..f4cdf0c 100644 --- a/lustre/obdfs/super.c +++ b/lustre/obdfs/super.c @@ -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); */ -- 1.8.3.1