if [ "$BASEDEV" ]; then
- mke2fs -r 0 -b 4096 $BASEDEV
+ echo "No mke2fs!!"
+ # mke2fs -r 0 -b 4096 $BASEDEV
else
echo "\$BASEDEV not defined in demos/config.sh. Please fix!"
[ "$LOOPDEV" ] && losetup -d $LOOPDEV
# If LOOPDEV is empty, then it is assumed that BASEDEV is a real block device
# that doesn't mind being overwritten - don't use a partition with data on it!!
-BASEDEV="$LOOPDEV"
+BASEDEV="/dev/hda5"
# The following are mount points for the filesystems during the test.
MNTOBD="/mnt/obd"
int obd_flags;
int obd_refcnt;
obd_devicename obd_fsname;
+ kdev_t obd_rdev;
+ char * obd_user_name;
struct proc_dir_entry *obd_proc_entry;
int obd_multi_count;
struct obd_conn obd_multi_conn[MAX_MULTI];
dst->o_valid |= src->o_valid;
}
+/* WARNING: the file systems must take care not to tinker with
+ attributes they don't manage (such as blocks). */
+
static __inline__ void obdo_from_inode(struct obdo *dst, struct inode *src)
{
if ( dst->o_valid & OBD_MD_FLID )
return &sbi->osi_inodes;
}
+static void inline obdfs_set_size (struct inode *inode, obd_size size)
+{
+ inode->i_size = size;
+ inode->i_blocks = (inode->i_size + inode->i_sb->s_blocksize - 1) >>
+ inode->i_sb->s_blocksize_bits;
+ inode->i_bytes = inode->i_size &
+ ((1 << inode->i_sb->s_blocksize_bits) - 1);
+} /* obdfs_set_size */
+
+
#define obd_down(mutex) { \
/* CDEBUG(D_INFO, "get lock\n"); */ \
obdfs_mutex_start = jiffies; \
return 0;
}
-
-static int obd_devicename_from_path(obd_devicename* whoami,
- uint32_t klen,
- char* kname, char *user_path)
-{
- int err;
- struct nameidata nd;
- whoami->len = klen;
- whoami->name = kname;
-
-#if (LINUX_VERSION_CODE <= 0x20403)
-
- err = user_path_walk(user_path, &nd);
- if (!err) {
- CDEBUG(D_INFO, "found dentry for %s\n", kname);
- whoami->dentry = nd.dentry;
- path_release(&nd);
- }
- return err;
-#endif
- return 0;
-}
-
-
-
/* to control /dev/obdNNN */
static int obd_class_ioctl (struct inode * inode, struct file * filp,
unsigned int cmd, unsigned long arg)
/* have we attached a type to this device */
if ( obddev->obd_type ||
(obddev->obd_flags & OBD_ATTACHED) ){
+ char *name;
+ if (obddev->obd_type->typ_name)
+ name = obddev->obd_type->typ_name;
+ else
+ name = "";
CDEBUG(D_IOCTL,
"OBD Device %d already attached to type %s.\n",
- dev, obddev->obd_type->typ_name);
+ dev, name);
EXIT;
return -EBUSY;
}
case OBD_IOC_SETUP: {
struct ioc_setup {
int setup_datalen;
+ int setup_rdev;
void *setup_data;
} *setup;
char *user_path;
return -EBUSY;
}
-
-
/* get main structure */
err = copy_from_user(setup, (void *) arg, sizeof(*setup));
if (err) {
EXIT;
return err;
}
+ obddev->obd_rdev = setup->setup_rdev;
+ obddev->obd_user_name = user_path;
- err = obd_devicename_from_path(&(obddev->obd_fsname),
- setup->setup_datalen,
- (char*) setup->setup_data,
- user_path);
- if (err) {
- memset(&(obddev->obd_fsname), 0, sizeof(obd_devicename));
- EXIT;
- return err;
- }
-
/* do the setup */
- CDEBUG(D_PSDEV, "Setup %d, type %s\n", dev,
- obddev->obd_type->typ_name);
+ CDEBUG(D_PSDEV, "Setup %d, type %s device %x\n", dev,
+ obddev->obd_type->typ_name, setup->setup_rdev);
if ( !OBT(obddev) || !OBP(obddev, setup) ) {
obddev->obd_type->typ_refcnt++;
CDEBUG(D_PSDEV, "Dev %d refcount now %d\n",
OBP(obddev, disconnect)(&conn);
return 0;
+
+ case OBD_IOC_DEC_USE_COUNT:
+ MOD_DEC_USE_COUNT;
+ return 0;
case OBD_IOC_SYNC: {
struct oic_range_s *range = tmp_buf;
# Get going....
-#Device($::device);
+# $::device = "/dev/obd0" unless defined $::device;
+Device($::device);
sub readl {
if ( $file ) {
print "$arg is not a valid device\n";
return -1;
}
-
+
+ printf "setting up %s, device %x\n", $arg, $::st->rdev();
if ( $arg ) {
$data = $arg;
- $datalen = length($arg)+1; # need null character also
+ $datalen = 4 + length($arg)+1; # need null character also
}
- my $packed = pack("ip", $datalen, $data);
+ my $packed = pack("iip", $datalen, $::st->rdev(), $data);
if (! defined $::dev_obd) {
print "No current device.\n";
return -1;
MODULE = obdfs
modulefs_DATA = obdfs.o
EXTRA_PROGRAMS = obdfs
-obdfs_SOURCES = flushd.c rw.c file.c dir.c sysctl.c super.c namei.c symlink.c
+# obdfs_SOURCES = flushd.c rw.c file.c dir.c sysctl.c super.c namei.c symlink.c
+obdfs_SOURCES = rw.c file.c dir.c sysctl.c super.c namei.c symlink.c
include $(top_srcdir)/Rules
MODULE = obdfs
modulefs_DATA = obdfs.o
EXTRA_PROGRAMS = obdfs
-obdfs_SOURCES = flushd.c rw.c file.c dir.c sysctl.c super.c namei.c symlink.c
+# obdfs_SOURCES = flushd.c rw.c file.c dir.c sysctl.c super.c namei.c symlink.c
+obdfs_SOURCES = rw.c file.c dir.c sysctl.c super.c namei.c symlink.c
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_CLEAN_FILES =
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
-obdfs_OBJECTS = flushd.o rw.o file.o dir.o sysctl.o super.o namei.o \
-symlink.o
+obdfs_OBJECTS = rw.o file.o dir.o sysctl.o super.o namei.o symlink.o
obdfs_LDADD = $(LDADD)
obdfs_DEPENDENCIES =
obdfs_LDFLAGS =
TAR = gtar
GZIP_ENV = --best
-DEP_FILES = .deps/dir.P .deps/file.P .deps/flushd.P .deps/namei.P \
-.deps/rw.P .deps/super.P .deps/symlink.P .deps/sysctl.P
+DEP_FILES = .deps/dir.P .deps/file.P .deps/namei.P .deps/rw.P \
+.deps/super.P .deps/symlink.P .deps/sysctl.P
SOURCES = $(obdfs_SOURCES)
OBJECTS = $(obdfs_OBJECTS)
struct ext2_dir_entry_2 * de;
char *base;
int err;
+ ENTRY;
if (!page)
return -ENOMEM;
fail:
UnlockPage(page);
page_cache_release(page);
+ ENTRY;
return err;
}
#include <linux/obd_support.h>
#include <linux/obdfs.h>
+extern int obdfs_setattr(struct dentry *de, struct iattr *attr);
void obdfs_change_inode(struct inode *inode);
static inline void obdfs_remove_suid(struct inode *inode)
mode &= inode->i_mode;
if (mode && !capable(CAP_FSETID)) {
inode->i_mode &= ~mode;
- obdfs_change_inode(inode);
+ // XXX careful here - we cannot change the size
+ //obdfs_change_inode(inode);
}
}
retval = generic_file_write(file, buf, count, ppos);
CDEBUG(D_INFO, "Wrote %d\n", retval);
+
+ /* update mtime/ctime/atime here, NOT size */
if (retval > 0) {
- struct inode *inode = file->f_dentry->d_inode;
- obdfs_remove_suid(inode);
- inode->i_ctime = inode->i_mtime = CURRENT_TIME;
- obdfs_change_inode(inode);
+ struct iattr attr;
+ attr.ia_valid = ATTR_MTIME | ATTR_CTIME | ATTR_ATIME;
+ attr.ia_mtime = attr.ia_ctime = attr.ia_atime =
+ CURRENT_TIME;
+ obdfs_setattr(file->f_dentry, &attr);
}
EXIT;
return retval;
}
+
+/* XXX this does not need to do anything for data, it _does_ need to
+ call setattr */
+int obdfs_fsync(struct file *file, struct dentry *dentry, int data)
+{
+ return 0;
+}
+
struct file_operations obdfs_file_operations = {
- read: generic_file_read, /* read */
- write: obdfs_file_write, /* write */
- mmap: generic_file_mmap, /* mmap */
+ read: generic_file_read,
+ write: obdfs_file_write,
+ mmap: generic_file_mmap,
+ fsync: NULL
};
-extern int obdfs_setattr(struct dentry *de, struct iattr *attr);
+
struct inode_operations obdfs_file_inode_operations = {
truncate: obdfs_truncate,
setattr: obdfs_setattr
{
struct inode * inode;
int err = -EMLINK;
+ ENTRY;
if (dir->i_nlink >= EXT2_LINK_MAX)
goto out;
d_instantiate(dentry, inode);
out:
+ EXIT;
return err;
out_fail:
ext2_dec_count(inode);
ext2_dec_count(inode);
iput(inode);
+ EXIT;
out_dir:
ext2_dec_count(dir);
+ EXIT;
goto out;
}
void obdfs_change_inode(struct inode *inode);
+static int cache_writes = 0;
+
+
+/* page cache support stuff */
+
+/*
+ * Add a page to the dirty page list.
+ */
+void __set_page_dirty(struct page *page)
+{
+ struct address_space *mapping = page->mapping;
+
+ spin_lock(&pagecache_lock);
+ list_del(&page->list);
+ list_add(&page->list, &mapping->dirty_pages);
+ spin_unlock(&pagecache_lock);
+
+ if (mapping->host)
+ mark_inode_dirty_pages(mapping->host);
+}
+
+/*
+ * Add a page to the dirty page list.
+ */
+void __set_page_clean(struct page *page)
+{
+ struct address_space *mapping = page->mapping;
+ struct inode *inode;
+ ENTRY;
+
+ spin_lock(&pagecache_lock);
+ list_del(&page->list);
+ list_add(&page->list, &mapping->clean_pages);
+ spin_unlock(&pagecache_lock);
+
+ inode = mapping->host;
+ if (list_empty(&mapping->dirty_pages)) {
+ CDEBUG(D_INODE, "inode clean\n");
+ inode->i_state &= ~I_DIRTY_PAGES;
+ }
+ EXIT;
+}
+
+inline void set_page_clean(struct page *page)
+{
+ if (PageDirty(page)) {
+ ClearPageDirty(page);
+ __set_page_clean(page);
+ }
+}
+
/* SYNCHRONOUS I/O to object storage for an inode -- object attr will be updated too */
static int obdfs_brw(int rw, struct inode *inode, struct page *page, int create)
{
err = IOPS(inode, brw)(rw, IID(inode), num_obdo, &oa, &bufs_per_obdo,
&page, &count, &offset, &flags);
- if ( !err )
- obdfs_to_inode(inode, oa); /* copy o_blocks to i_blocks */
+ //if ( !err )
+ // obdfs_to_inode(inode, oa); /* copy o_blocks to i_blocks */
obdo_free(oa);
EXIT;
return err;
} /* obdfs_brw */
+extern void set_page_clean(struct page *);
+
+/* SYNCHRONOUS I/O to object storage for an inode -- object attr will be updated too */
+static int obdfs_commit_page(struct page *page, int create, int from, int to)
+{
+ struct inode *inode = page->mapping->host;
+ obd_count num_obdo = 1;
+ obd_count bufs_per_obdo = 1;
+ struct obdo *oa;
+ obd_size count = to;
+ obd_off offset = (((obd_off)page->index) << PAGE_SHIFT);
+ obd_flag flags = create ? OBD_BRW_CREATE : 0;
+ int err;
+
+ ENTRY;
+ if (IOPS(inode, brw) == NULL) {
+ printk(KERN_ERR __FUNCTION__ ": no brw method!\n");
+ EXIT;
+ return -EIO;
+ }
+
+ oa = obdo_alloc();
+ if ( !oa ) {
+ EXIT;
+ return -ENOMEM;
+ }
+ oa->o_valid = OBD_MD_FLNOTOBD;
+ obdfs_from_inode(oa, inode);
+
+ CDEBUG(D_INODE, "commit_page writing (at %d) to %d, count %ld\n",
+ from, to, (unsigned long )count);
+
+ err = IOPS(inode, brw)(WRITE, IID(inode), num_obdo, &oa, &bufs_per_obdo,
+ &page, &count, &offset, &flags);
+ if ( !err ) {
+ SetPageUptodate(page);
+ set_page_clean(page);
+ }
+
+ //if ( !err )
+ // obdfs_to_inode(inode, oa); /* copy o_blocks to i_blocks */
+
+ obdo_free(oa);
+ EXIT;
+ return err;
+} /* obdfs_brw */
+
+
/* returns the page unlocked, but with a reference */
int obdfs_readpage(struct file *file, struct page *page)
{
{
struct inode *inode = page->mapping->host;
obd_off offset = ((obd_off)page->index) << PAGE_SHIFT;
- int rc;
+ int rc = 0;
ENTRY;
kmap(page);
- /* PDEBUG(page, "READ"); */
if (Page_Uptodate(page)) {
EXIT;
- return 0;
+ goto prepare_done;
}
if ( (from <= offset) && (to >= offset + PAGE_SIZE) ) {
rc = obdfs_brw(READ, inode, page, 0);
if ( !rc ) {
SetPageUptodate(page);
- /* obd_unlock_page(page); */
}
- /* PDEBUG(page, "READ"); */
+
+ prepare_done:
+ set_page_dirty(page);
+ //SetPageDirty(page);
EXIT;
return rc;
}
+
+
static kmem_cache_t *obdfs_pgrq_cachep = NULL;
int obdfs_init_pgrqcache(void)
--num_obdos;
CDEBUG(D_INFO, "free obdo %ld\n",(long)obdos[num_obdos]->o_id);
/* copy o_blocks to i_blocks */
- obdfs_to_inode(inodes[num_obdos], obdos[num_obdos]);
+ obdfs_set_size (inodes[num_obdos], obdos[num_obdos]->o_size);
+ //obdfs_to_inode(inodes[num_obdos], obdos[num_obdos]);
obdo_free(obdos[num_obdos]);
}
CDEBUG(D_INFO, "obdo_free done\n");
obd_down(&obdfs_i2sbi(inode)->osi_list_mutex);
list_add(&pgrq->rq_plist, obdfs_iplist(inode));
obdfs_cache_count++;
+ //printk("-- count %d\n", obdfs_cache_count);
/* If inode isn't already on superblock inodes list, add it.
*
list_add(obdfs_islist(inode), obdfs_slist(inode));
}
obd_up(&obdfs_i2sbi(inode)->osi_list_mutex);
+
}
/* XXX For testing purposes, we can write out the page here.
return err;
} /* obdfs_add_page_to_cache */
+void rebalance(void)
+{
+ if (obdfs_cache_count > 60000) {
+ printk("-- count %ld\n", obdfs_cache_count);
+ //obdfs_flush_dirty_pages(~0UL);
+ printk("-- count %ld\n", obdfs_cache_count);
+ }
+}
/* select between SYNC and ASYNC I/O methods */
int obdfs_do_writepage(struct page *page, int sync)
inode->i_ino, page, err, Page_Uptodate(page));
}
- if ( !err )
+ if ( !err ) {
SetPageUptodate(page);
+ set_page_clean(page);
+ }
/* PDEBUG(page,"WRITEPAGE"); */
EXIT;
return err;
/* returns the page unlocked, but with a reference */
int obdfs_writepage(struct page *page)
{
- return obdfs_do_writepage(page, 0);
+ int rc;
+ struct inode *inode = page->mapping->host;
+ ENTRY;
+ printk("---> writepage called ino %ld!\n", inode->i_ino);
+ BUG();
+ rc = obdfs_do_writepage(page, 1);
+ if ( !rc ) {
+ set_page_clean(page);
+ } else {
+ CDEBUG(D_INODE, "--> GRR %d\n", rc);
+ }
+ EXIT;
+ return rc;
}
+void write_inode_pages(struct inode *inode)
+{
+ struct list_head *tmp = &inode->i_mapping->dirty_pages;
+
+ while ( (tmp = tmp->next) != &inode->i_mapping->dirty_pages) {
+ struct page *page;
+ page = list_entry(tmp, struct page, list);
+ obdfs_writepage(page);
+ }
+}
+
+
int obdfs_commit_write(struct file *file, struct page *page, unsigned from, unsigned to)
{
- int rc;
struct inode *inode = page->mapping->host;
- loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
- rc = obdfs_do_writepage(page, 0);
- kunmap(page);
- if (pos > inode->i_size) {
- inode->i_size = pos;
- obdfs_change_inode(inode);
+ int rc = 0;
+ loff_t len = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+ ENTRY;
+ CDEBUG(D_INODE, "commit write ino %ld (end at %Ld) from %d to %d ,ind %ld\n",
+ inode->i_ino, len, from, to, page->index);
+
+
+ if (cache_writes == 0) {
+ rc = obdfs_commit_page(page, 1, from, to);
+ kunmap(page);
+ }
+
+ if (len > inode->i_size) {
+ obdfs_set_size(inode, len);
}
- return 0;
+
+ kunmap(page);
+ EXIT;
+ return rc;
}
int err;
ENTRY;
- obdfs_dequeue_pages(inode);
+ //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
}
EXIT;
} /* obdfs_truncate */
+
+struct address_space_operations obdfs_aops = {
+ readpage: obdfs_readpage,
+ writepage: obdfs_writepage,
+ sync_page: block_sync_page,
+ prepare_write: obdfs_prepare_write,
+ commit_write: obdfs_commit_write,
+ bmap: NULL
+};
}
CDEBUG(D_INFO, "\n");
- sb->s_blocksize = blocksize;
- sb->s_blocksize_bits = (unsigned char)blocksize_bits;
+ sb->s_blocksize = PAGE_SIZE;
+ sb->s_blocksize_bits = (unsigned char)PAGE_SHIFT;
sb->s_magic = OBDFS_SUPER_MAGIC;
sb->s_op = &obdfs_super_operations;
sb->s_dev = 0;
sbi = (struct obdfs_sb_info *) &sb->u.generic_sbp;
- obdfs_flush_reqs(&sbi->osi_inodes, ~0UL);
+ //obdfs_flush_reqs(&sbi->osi_inodes, ~0UL);
OPS(sb,disconnect)(ID(sb));
list_del(&sbi->osi_list);
} /* obdfs_put_super */
-void obdfs_do_change_inode(struct inode *inode, int mask)
+void obdfs_do_change_inode(struct inode *inode, int valid)
{
struct obdo *oa;
int err;
return;
}
- oa->o_valid = OBD_MD_FLNOTOBD & (~mask);
+ oa->o_valid = OBD_MD_FLNOTOBD & (valid | OBD_MD_FLID);
obdfs_from_inode(oa, inode);
err = IOPS(inode, setattr)(IID(inode), oa);
}
-
+extern void write_inode_pages(struct inode *);
/* 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
static void obdfs_put_inode(struct inode *inode)
{
ENTRY;
- if (inode->i_nlink) {
+ if (inode->i_nlink && (atomic_read(&inode->i_count) == 1)) {
+ write_inode_pages(inode);
EXIT;
return;
}
- obdfs_dequeue_pages(inode);
+ //obdfs_dequeue_pages(inode);
EXIT;
} /* obdfs_put_inode */
static void obdfs_delete_inode(struct inode *inode)
{
- obdfs_do_change_inode(inode, 0);
+ obdfs_do_change_inode(inode, ~0);
clear_inode(inode);
}
#if 0
#endif
-int inode_copy_attr(struct inode * inode, struct iattr * attr)
+static int obdfs_attr2inode(struct inode * inode, struct iattr * attr)
{
unsigned int ia_valid = attr->ia_valid;
int error = 0;
return -ENOMEM;
}
- inode_copy_attr(inode, attr);
+ obdfs_attr2inode(inode, attr);
oa->o_id = inode->i_ino;
obdo_from_iattr(oa, attr);
err = IOPS(inode, setattr)(IID(inode), oa);
obdfs_sysctl_init();
INIT_LIST_HEAD(&obdfs_super_list);
- err = obdfs_init_pgrqcache();
- if (err)
- return err;
+ //err = obdfs_init_pgrqcache();
+ //if (err)
+ //return err;
- obdfs_flushd_init();
+ //obdfs_flushd_init();
return register_filesystem(&obdfs_fs_type);
}
-struct address_space_operations obdfs_aops = {
- readpage: obdfs_readpage,
- writepage: obdfs_writepage,
- sync_page: block_sync_page,
- prepare_write: obdfs_prepare_write,
- commit_write: obdfs_commit_write,
- bmap: NULL
-};
#ifdef MODULE
{
ENTRY;
- obdfs_flushd_cleanup();
+ //obdfs_flushd_cleanup();
obdfs_sysctl_clean();
- obdfs_cleanup_pgrqcache();
+ //obdfs_cleanup_pgrqcache();
unregister_filesystem(&obdfs_fs_type);
CDEBUG(D_MALLOC, "OBDFS mem used %ld\n", obd_memory);
EXIT;