NULL, /* get_block */
obdfs_readpage, /* readpage */
obdfs_writepage, /* writepage */
- NULL /* XXX add XXX */, /* truncate */
+ obdfs_truncate, /* truncate */
NULL, /* permission */
NULL /* revalidate */
};
*
*/
#define __NO_VERSION__
-#include <linux/module.h>
-#include <linux/sched.h>
#include <linux/fs.h>
-#include <linux/malloc.h>
#include <linux/locks.h>
-#include <linux/errno.h>
#include <linux/swap.h>
-#include <linux/smp_lock.h>
-#include <linux/vmalloc.h>
-#include <linux/blkdev.h>
-#include <linux/sysrq.h>
-#include <linux/file.h>
-#include <linux/init.h>
-#include <linux/quotaops.h>
-#include <linux/iobuf.h>
-#include <linux/highmem.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/bitops.h>
-#include <asm/mmu_context.h>
#include <linux/obd_support.h>
#include <linux/obd_class.h>
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)
{
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;
/* 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);
}
-
}
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;
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;
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 */
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 */
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();
} /* 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;
+}
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");
} /* 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 */
{
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;
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");
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;
}