From 3fea23a1fdab088fbae7b264c804a25127fbfde4 Mon Sep 17 00:00:00 2001 From: adilger Date: Tue, 7 Mar 2000 15:59:16 +0000 Subject: [PATCH] obdfs/*.c: finished truncate implementation --- lustre/obdfs/file.c | 2 +- lustre/obdfs/flushd.c | 89 +++++++++++++++++++++++++++++++-------------------- lustre/obdfs/namei.c | 5 +++ lustre/obdfs/rw.c | 64 +++++++++++++++++++++++++++++++++--- lustre/obdfs/super.c | 59 ++++++++++++---------------------- 5 files changed, 140 insertions(+), 79 deletions(-) diff --git a/lustre/obdfs/file.c b/lustre/obdfs/file.c index 87d6b0e..decec1a 100644 --- a/lustre/obdfs/file.c +++ b/lustre/obdfs/file.c @@ -105,7 +105,7 @@ struct inode_operations obdfs_file_inode_operations = { NULL, /* get_block */ obdfs_readpage, /* readpage */ obdfs_writepage, /* writepage */ - NULL /* XXX add XXX */, /* truncate */ + obdfs_truncate, /* truncate */ NULL, /* permission */ NULL /* revalidate */ }; diff --git a/lustre/obdfs/flushd.c b/lustre/obdfs/flushd.c index 5d8367e..f13952c 100644 --- a/lustre/obdfs/flushd.c +++ b/lustre/obdfs/flushd.c @@ -8,27 +8,9 @@ * */ #define __NO_VERSION__ -#include -#include #include -#include #include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include #include #include @@ -118,6 +100,43 @@ static int obdfs_enqueue_pages(struct inode *inode, struct obdo **obdo, return num; } /* obdfs_enqueue_pages */ +/* Dequeue cached pages for a dying inode without writing them to disk. */ +void obdfs_dequeue_pages(struct inode *inode) +{ + struct list_head *tmp; + + obd_down(&obdfs_i2sbi(inode)->osi_list_mutex); + tmp = obdfs_islist(inode); + if ( list_empty(tmp) ) { + CDEBUG(D_INFO, "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->prev) != 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); + + /* decrement inode reference for page cache */ + inode->i_count--; +} + /* Remove writeback requests for the superblock */ int obdfs_flush_reqs(struct list_head *inode_list, unsigned long check_time) { @@ -147,8 +166,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, inodes %d, pages %d\n", - obd_memory, obd_inodes, obd_pages); + CDEBUG(D_CACHE, "list empty: memory %ld\n", obd_memory); obd_up(&sbi->osi_list_mutex); EXIT; return 0; @@ -348,34 +366,35 @@ static int pupdate(void *unused) /* asynchronous setattr etc for the future ... obdfs_flush_dirty_inodes(jiffies - pupd_prm.age_super); */ + /* XXX for debugging dirty_limit = nr_free_buffer_pages() * pupd_prm.nfract / 100; - CDEBUG(D_CACHE, "dirty_limit %ld, cache_count %ld\n", - dirty_limit, obdfs_cache_count); + * XXX */ + dirty_limit = 16384 * 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); } else { - int isave = interval; - int asave = age; - - if ( wrote < pupd_prm.ndirty >> 1 ) + if ( wrote < pupd_prm.ndirty >> 1 && + obdfs_cache_count < dirty_limit / 2) { interval = pupd_prm.interval; - else - interval = isave >> 1; - - if (obdfs_cache_count > dirty_limit / 3) { - age = asave >> 1; - interval = isave >> 1; - } else age = pupd_prm.age_buffer; + } 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, "age %ld, interval %d\n", age, interval); wrote = obdfs_flush_dirty_pages(jiffies - age); } - } diff --git a/lustre/obdfs/namei.c b/lustre/obdfs/namei.c index fcf50cb..c3f12e0 100644 --- a/lustre/obdfs/namei.c +++ b/lustre/obdfs/namei.c @@ -457,6 +457,11 @@ static struct inode *obdfs_new_inode(struct inode *dir, int mode) int err; ENTRY; + if (IOPS(dir, create) == NULL) { + printk(KERN_ERR __FUNCTION__ ": no create method!\n"); + EXIT; + return ERR_PTR(-EIO); + } oa = obdo_alloc(); if (!oa) { EXIT; diff --git a/lustre/obdfs/rw.c b/lustre/obdfs/rw.c index 56adb90..be52f79 100644 --- a/lustre/obdfs/rw.c +++ b/lustre/obdfs/rw.c @@ -47,6 +47,12 @@ static int obdfs_brw(int rw, struct inode *inode, struct page *page, int create) int err; ENTRY; + if (IOPS(inode, brw) == NULL) { + printk(KERN_ERR __FUNCTION__ ": no brw method!\n"); + EXIT; + return -EIO; + } + oa = obdo_fromid(IID(inode), inode->i_ino, OBD_MD_FLNOTOBD); if ( IS_ERR(oa) ) { EXIT; @@ -218,11 +224,15 @@ int obdfs_do_vec_wr(struct inode **inodes, obd_count num_io, obd_count *oa_bufs, struct page **pages, char **bufs, obd_size *counts, obd_off *offsets, obd_flag *flags) { - struct super_block *sb = inodes[0]->i_sb; - struct obdfs_sb_info *sbi = (struct obdfs_sb_info *)&sb->u.generic_sbp; int err; ENTRY; + if (IOPS(inodes[0], brw) == NULL) { + printk(KERN_ERR __FUNCTION__ ": no brw method!\n"); + EXIT; + return -EIO; + } + CDEBUG(D_INFO, "writing %d page(s), %d obdo(s) in vector\n", num_io, num_obdos); { /* DEBUGGING */ @@ -237,8 +247,8 @@ int obdfs_do_vec_wr(struct inode **inodes, obd_count num_io, printk("\n"); } - err = OPS(sb, brw)(WRITE, &sbi->osi_conn, num_obdos, obdos, oa_bufs, - bufs, counts, offsets, flags); + err = IOPS(inodes[0], brw)(WRITE, IID(inodes[0]), num_obdos, obdos, + oa_bufs, bufs, counts, offsets, flags); CDEBUG(D_CACHE, "BRW done\n"); /* release the pages from the page cache */ @@ -384,7 +394,7 @@ int obdfs_write_one_page(struct file *file, struct page *page, if (copy_from_user((u8*)page_address(page) + offset, buf, bytes)) return -EFAULT; - lock_kernel(); /* XXX do we really need to lock the kernel to write? */ + lock_kernel(); err = obdfs_writepage(file->f_dentry, page); unlock_kernel(); @@ -457,3 +467,47 @@ struct page *obdfs_getpage(struct inode *inode, unsigned long offset, } /* obdfs_getpage */ +void obdfs_truncate(struct inode *inode) +{ + struct obdo *oa; + int err; + ENTRY; + + obdfs_dequeue_pages(inode); + + if (IOPS(inode, punch) == NULL) { + printk(KERN_ERR __FUNCTION__ ": no punch method!\n"); + EXIT; + return; + } + oa = obdo_alloc(); + if ( !oa ) { + /* XXX This would give an inconsistent FS, so deal with it as + * best we can for now - an obdo on the stack is not pretty. + */ + struct obdo obdo; + + printk(__FUNCTION__ ": obdo_alloc failed - using stack!\n"); + + obdo.o_valid = OBD_MD_FLNOTOBD; + obdfs_from_inode(&obdo, inode); + + err = IOPS(inode, punch)(IID(inode), &obdo, obdo.o_size, 0); + } else { + oa->o_valid = OBD_MD_FLNOTOBD; + obdfs_from_inode(oa, inode); + + CDEBUG(D_PUNCH, "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); + + obdo_free(oa); + } + + if (err) { + printk(__FUNCTION__ ": obd_truncate fails (%d)\n", err); + EXIT; + return; + } + EXIT; +} diff --git a/lustre/obdfs/super.c b/lustre/obdfs/super.c index 972b27b..f092c88 100644 --- a/lustre/obdfs/super.c +++ b/lustre/obdfs/super.c @@ -320,6 +320,11 @@ static void obdfs_write_inode(struct inode *inode) int err; ENTRY; + if (IOPS(inode, setattr) == NULL) { + printk(KERN_ERR __FUNCTION__ ": no setattr method!\n"); + EXIT; + return; + } oa = obdo_alloc(); if ( !oa ) { printk(__FUNCTION__ ": obdo_alloc failed\n"); @@ -346,54 +351,21 @@ 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 +/* This routine is called from iput() (for each unlink on the inode). + * We can't put this call 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_INFO, "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->prev) != 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--; - + obdfs_dequeue_pages(inode); EXIT; - obd_up(&obdfs_i2sbi(inode)->osi_list_mutex); } /* obdfs_put_inode */ @@ -401,11 +373,18 @@ static void obdfs_delete_inode(struct inode *inode) { struct obdo *oa; int err; + ENTRY; + if (IOPS(inode, destroy) == NULL) { + printk(KERN_ERR __FUNCTION__ ": no destroy method!\n"); + EXIT; + return; + } oa = obdo_alloc(); if ( !oa ) { printk(__FUNCTION__ ": obdo_alloc failed\n"); + EXIT; return; } oa->o_valid = OBD_MD_FLNOTOBD; @@ -431,6 +410,11 @@ static int obdfs_notify_change(struct dentry *de, struct iattr *attr) int err; ENTRY; + if (IOPS(inode, setattr) == NULL) { + printk(KERN_ERR __FUNCTION__ ": no setattr method!\n"); + EXIT; + return -EIO; + } oa = obdo_alloc(); if ( !oa ) { printk(__FUNCTION__ ": obdo_alloc failed\n"); @@ -528,8 +512,7 @@ void cleanup_module(void) obdfs_sysctl_clean(); obdfs_cleanup_pgrqcache(); unregister_filesystem(&obdfs_fs_type); - CDEBUG(D_MALLOC, "OBDFS mem used %ld, inodes %d, pages %d\n", - obd_memory, obd_inodes, obd_pages); + CDEBUG(D_MALLOC, "OBDFS mem used %ld\n", obd_memory); EXIT; } -- 1.8.3.1