From 5066d0252672ee7b02c565500bf9ddbbf0e42e3b Mon Sep 17 00:00:00 2001 From: adilger Date: Thu, 9 Mar 2000 00:51:58 +0000 Subject: [PATCH] obdfs/dir.c: add truncate method for directory 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 | 2 +- lustre/obdfs/file.c | 2 +- lustre/obdfs/flushd.c | 41 ++++++++++------- lustre/obdfs/namei.c | 10 +++-- lustre/obdfs/rw.c | 121 ++++++++++++++++++-------------------------------- lustre/obdfs/super.c | 5 ++- 6 files changed, 82 insertions(+), 99 deletions(-) diff --git a/lustre/obdfs/dir.c b/lustre/obdfs/dir.c index 698b68c..56db69a 100644 --- a/lustre/obdfs/dir.c +++ b/lustre/obdfs/dir.c @@ -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 */ }; diff --git a/lustre/obdfs/file.c b/lustre/obdfs/file.c index decec1a..4416161 100644 --- a/lustre/obdfs/file.c +++ b/lustre/obdfs/file.c @@ -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 */ diff --git a/lustre/obdfs/flushd.c b/lustre/obdfs/flushd.c index 638dd54..ec6a1fc 100644 --- a/lustre/obdfs/flushd.c +++ b/lustre/obdfs/flushd.c @@ -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); } } diff --git a/lustre/obdfs/namei.c b/lustre/obdfs/namei.c index c3f12e0..c474514 100644 --- a/lustre/obdfs/namei.c +++ b/lustre/obdfs/namei.c @@ -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; diff --git a/lustre/obdfs/rw.c b/lustre/obdfs/rw.c index 7a2dab7..8eac82e 100644 --- a/lustre/obdfs/rw.c +++ b/lustre/obdfs/rw.c @@ -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); diff --git a/lustre/obdfs/super.c b/lustre/obdfs/super.c index f092c88..87f76c2 100644 --- a/lustre/obdfs/super.c +++ b/lustre/obdfs/super.c @@ -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); -- 1.8.3.1