From 67576c26417406903d5ea859d145aacaa2f7abf5 Mon Sep 17 00:00:00 2001 From: adilger Date: Fri, 25 Feb 2000 06:34:22 +0000 Subject: [PATCH] obdfs/*.c: fixed bug with flushing of cache of deleted obdo --- lustre/obdfs/dir.c | 3 +- lustre/obdfs/file.c | 3 +- lustre/obdfs/flushd.c | 42 ++------------------- lustre/obdfs/rw.c | 11 +++++- lustre/obdfs/super.c | 100 ++++++++++++++++++++++++++++++++++--------------- lustre/obdfs/symlink.c | 7 ++-- lustre/obdfs/sysctl.c | 2 +- 7 files changed, 89 insertions(+), 79 deletions(-) diff --git a/lustre/obdfs/dir.c b/lustre/obdfs/dir.c index ab5174d..7c8f96a 100644 --- a/lustre/obdfs/dir.c +++ b/lustre/obdfs/dir.c @@ -60,8 +60,7 @@ struct file_operations obdfs_dir_operations = { NULL, /* no special release code */ NULL, /* fsync */ NULL, /* fasync */ - NULL, /* check_media_change */ - NULL /* revalidate */ + NULL /* lock */ }; struct inode_operations obdfs_dir_inode_operations = { diff --git a/lustre/obdfs/file.c b/lustre/obdfs/file.c index b41f54f..1bbb190 100644 --- a/lustre/obdfs/file.c +++ b/lustre/obdfs/file.c @@ -85,8 +85,7 @@ struct file_operations obdfs_file_operations = { NULL, /* no special release code */ NULL, /* fsync */ NULL, /* fasync */ - NULL, /* check_media_change */ - NULL /* revalidate */ + NULL /* lock */ }; struct inode_operations obdfs_file_inode_operations = { diff --git a/lustre/obdfs/flushd.c b/lustre/obdfs/flushd.c index ba1c1cb..0a47e7f 100644 --- a/lustre/obdfs/flushd.c +++ b/lustre/obdfs/flushd.c @@ -111,39 +111,6 @@ static int obdfs_enqueue_pages(struct inode *inode, struct obdo **obdo, return num; } /* obdfs_enqueue_pages */ -/* dequeue requests for a dying inode */ -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; - } - - /* take it out of the super list */ - list_del(tmp); - INIT_LIST_HEAD(obdfs_islist(inode)); - - tmp = obdfs_iplist(inode); - while ( (tmp = tmp->next) != obdfs_iplist(inode) ) { - struct obdfs_pgrq *req; - struct page *page; - - req = list_entry(tmp, struct obdfs_pgrq, rq_plist); - page = req->rq_page; - /* take it out of the list and free */ - obdfs_pgrq_del(req); - /* now put the page away */ - put_page(page); - } - obd_up(&obdfs_i2sbi(inode)->osi_list_mutex); -} /* obdfs_dequeue_reqs */ - /* Remove writeback requests for the superblock */ int obdfs_flush_reqs(struct list_head *inode_list, int check_time) { @@ -162,9 +129,7 @@ int obdfs_flush_reqs(struct list_head *inode_list, int check_time) int err = 0; struct obdfs_sb_info *sbi; - ENTRY; - if (!inode_list) { CDEBUG(D_INODE, "no list\n"); EXIT; @@ -270,7 +235,8 @@ int obdfs_flush_reqs(struct list_head *inode_list, int check_time) inode->i_ino); tmp = tmp->prev; list_del(obdfs_islist(inode)); - iput(inode); + /* decrement inode reference for page cache */ + inode->i_count--; INIT_LIST_HEAD(obdfs_islist(inode)); } } @@ -280,7 +246,7 @@ int obdfs_flush_reqs(struct list_head *inode_list, int check_time) EXIT; ERR: return err; -} /* obdfs_remove_pages_from_cache */ +} /* obdfs_flush_reqs */ void obdfs_flush_dirty_pages(int check_time) @@ -297,7 +263,7 @@ void obdfs_flush_dirty_pages(int check_time) obdfs_flush_reqs(&sbi->osi_inodes, check_time); } EXIT; -} +} /* obdfs_flush_dirty_pages */ static struct task_struct *pupdated; diff --git a/lustre/obdfs/rw.c b/lustre/obdfs/rw.c index 91f270f..5bd837e 100644 --- a/lustre/obdfs/rw.c +++ b/lustre/obdfs/rw.c @@ -283,9 +283,16 @@ static int obdfs_add_page_to_cache(struct inode *inode, struct page *page) /* 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 ut_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)) ) { - iget(inode->i_sb, inode->i_ino); + inode->i_count++; 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)); @@ -314,7 +321,7 @@ int obdfs_do_writepage(struct inode *inode, struct page *page, int sync) err = obdfs_brw(WRITE, inode, page, 1); else { err = obdfs_add_page_to_cache(inode, page); - CDEBUG(D_IOCTL, "DO_WR ino: %ld, page %p, err %d, uptodata %d\n", inode->i_ino, page, err, Page_Uptodate(page)); + CDEBUG(D_IOCTL, "DO_WR ino: %ld, page %p, err %d, uptodate %d\n", inode->i_ino, page, err, Page_Uptodate(page)); } if ( !err ) diff --git a/lustre/obdfs/super.c b/lustre/obdfs/super.c index 2358705..3fe0f78 100644 --- a/lustre/obdfs/super.c +++ b/lustre/obdfs/super.c @@ -32,30 +32,8 @@ #include #include -/* VFS super_block ops */ -static struct super_block *obdfs_read_super(struct super_block *, void *, int); -static int obdfs_notify_change(struct dentry *dentry, struct iattr *attr); -static void obdfs_write_inode(struct inode *); -static void obdfs_delete_inode(struct inode *); -static void obdfs_put_super(struct super_block *); -static int obdfs_statfs(struct super_block *sb, struct statfs *buf, - int bufsiz); - -/* exported operations */ -struct super_operations obdfs_super_operations = -{ - obdfs_read_inode, /* read_inode */ - obdfs_write_inode, /* write_inode */ - NULL, /* put_inode */ - obdfs_delete_inode, /* delete_inode */ - obdfs_notify_change, /* notify_change */ - obdfs_put_super, /* put_super */ - NULL, /* write_super */ - obdfs_statfs, /* statfs */ - NULL /* remount_fs */ -}; - struct list_head obdfs_super_list; +struct super_operations obdfs_super_operations; static char *obdfs_read_opt(const char *opt, char *data) { @@ -81,7 +59,7 @@ static char *obdfs_read_opt(const char *opt, char *data) return retval; } -void obdfs_options(char *options, char **dev, char **vers) +static void obdfs_options(char *options, char **dev, char **vers) { char *this_char; @@ -123,7 +101,6 @@ static int obdfs_getdev(char *devpath, int *dev) } -/* XXX allocate a super_entry, and add the super to the obdfs_super_list */ static struct super_block * obdfs_read_super(struct super_block *sb, void *data, int silent) { @@ -265,7 +242,7 @@ ERR: } sb->s_dev = 0; return NULL; -} +} /* obdfs_read_super */ static void obdfs_put_super(struct super_block *sb) @@ -290,7 +267,7 @@ static void obdfs_put_super(struct super_block *sb) /* all filling in of inodes postponed until lookup */ -void obdfs_read_inode(struct inode *inode) +static void obdfs_read_inode(struct inode *inode) { struct obdo *oa; @@ -361,6 +338,58 @@ static void obdfs_write_inode(struct inode *inode) } /* obdfs_write_inode */ +/* Dequeue cached pages for a dying inode without writing them to disk. + * + * This routine is called from iput() (for each unlink on the inode). + * We can't put this code into delete_inode() since that is called only + * when i_count == 0, and we need to keep a reference on the inode while + * it is in the page cache, which means i_count > 0. Catch 22. + */ +static void obdfs_put_inode(struct inode *inode) +{ + struct list_head *tmp; + + ENTRY; + if (inode->i_nlink) { + EXIT; + return; + } + + obd_down(&obdfs_i2sbi(inode)->osi_list_mutex); + tmp = obdfs_islist(inode); + if ( list_empty(tmp) ) { + CDEBUG(D_INODE, __FUNCTION__ ": no dirty pages for inode %ld\n", + inode->i_ino); + obd_up(&obdfs_i2sbi(inode)->osi_list_mutex); + EXIT; + return; + } + + /* take it out of the super list */ + list_del(tmp); + INIT_LIST_HEAD(obdfs_islist(inode)); + + tmp = obdfs_iplist(inode); + while ( (tmp = tmp->next) != obdfs_iplist(inode) ) { + struct obdfs_pgrq *req; + struct page *page; + + req = list_entry(tmp, struct obdfs_pgrq, rq_plist); + page = req->rq_page; + /* take it out of the list and free */ + obdfs_pgrq_del(req); + /* now put the page away */ + put_page(page); + } + + /* decrement inode reference for page cache */ + inode->i_count--; + + EXIT; + obd_up(&obdfs_i2sbi(inode)->osi_list_mutex); +} /* obdfs_put_inode */ + + static void obdfs_delete_inode(struct inode *inode) { struct obdo *oa; @@ -375,9 +404,6 @@ static void obdfs_delete_inode(struct inode *inode) oa->o_valid = OBD_MD_FLNOTOBD; obdfs_from_inode(oa, inode); - /* free the cache pages that might be hangning around */ - obdfs_dequeue_reqs(inode); - err = IOPS(inode, destroy)(IID(inode), oa); obdo_free(oa); @@ -445,6 +471,20 @@ static int obdfs_statfs(struct super_block *sb, struct statfs *buf, return err; } +/* exported operations */ +struct super_operations obdfs_super_operations = +{ + obdfs_read_inode, /* read_inode */ + obdfs_write_inode, /* write_inode */ + obdfs_put_inode, /* put_inode */ + obdfs_delete_inode, /* delete_inode */ + obdfs_notify_change, /* notify_change */ + obdfs_put_super, /* put_super */ + NULL, /* write_super */ + obdfs_statfs, /* statfs */ + NULL /* remount_fs */ +}; + struct file_system_type obdfs_fs_type = { "obdfs", 0, obdfs_read_super, NULL }; diff --git a/lustre/obdfs/symlink.c b/lustre/obdfs/symlink.c index 7aa2959..f1e0a5d 100644 --- a/lustre/obdfs/symlink.c +++ b/lustre/obdfs/symlink.c @@ -30,8 +30,8 @@ #include /* for ENTRY and EXIT only */ #include -/* static */ -struct dentry * obdfs_follow_link(struct dentry * dentry, struct dentry *base, +static struct dentry * obdfs_follow_link(struct dentry * dentry, + struct dentry *base, unsigned int follow) { struct inode *inode = dentry->d_inode; @@ -60,8 +60,7 @@ struct dentry * obdfs_follow_link(struct dentry * dentry, struct dentry *base, return base; } -/* static */ -int obdfs_readlink (struct dentry * dentry, char * buffer, int buflen) +static int obdfs_readlink (struct dentry * dentry, char * buffer, int buflen) { struct inode *inode = dentry->d_inode; struct page *page = NULL; diff --git a/lustre/obdfs/sysctl.c b/lustre/obdfs/sysctl.c index 6b1752d..4970ce3 100644 --- a/lustre/obdfs/sysctl.c +++ b/lustre/obdfs/sysctl.c @@ -14,7 +14,7 @@ struct ctl_table_header *obdfs_table_header = NULL; -int obdfs_debug_level = 4095; +int obdfs_debug_level = 0; int obdfs_print_entry = 1; -- 1.8.3.1