moduledir = @moduledir@
modulefsdir = @modulefsdir@
-demo_SCRIPTS = baseclean.sh basesetup.sh obdfsclean.sh obdfssetup.sh \
- obdtest.sh snap3clean.sh snap3set.sh snapclean.sh snapdel.sh \
- snaprest.sh snaprestclean.sh snapsetup.sh snaptest.sh
+demo_SCRIPTS = baseclean.sh basesetup.sh obdfsclean.sh obdfssetup.sh obdtest.sh snap3clean.sh snap3set.sh snapclean.sh snapdel.sh snaprest.sh snaprestclean.sh snapsetup.sh snaptest.sh
demo_DATA = config.sh
EXTRA_DIST = $(demo_SCRIPTS) $(demo_DATA)
if [ "$BASEDEV" ]; then
- echo "No mke2fs!!"
- # 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!!
-LOOPDEV=""
-BASEDEV="/dev/hda5"
+LOOPDEV="/dev/loop0"
+BASEDEV="/dev/loop0"
# The following are mount points for the filesystems during the test.
MNTOBD="/mnt/obd"
plog rmmod obdfs
plog log "CLEANUP/DETACH"
-$OBDDIR/class/obdcontrol -f << EOF
-device /dev/obd0
+$OBDDIR/utils/obdctl << EOF
+device 0
cleanup
detach
quit
EOF
+plog rmmod obdfilter
plog rmmod obdext2
plog rmmod obdclass
#insmod $OBDDIR/ext2obd/obdext2.o
#insmod $OBDDIR/obdfs/obdfs.o
-plog log "ATTACHING /dev/obd0, SETUP $BASEDEV"
-$OBDDIR/class/obdcontrol -f << EOF
-device /dev/obd0
+plog log "ATTACHING device 0 SETUP $BASEDEV"
+$OBDDIR/utils/obdctl << EOF
+device 0
+# attach obdfilter
+# setup $BASEDEV reiserfs
attach obdext2
setup $BASEDEV
quit
plog umount $MNTSNAP2
plog log "CLEANUP /dev/obd3"
-$OBDDIR/class/obdcontrol -f << EOF
+$OBDDIR/utils/obdcontrol -f << EOF
device /dev/obd3
cleanup
detach
sleep 5 # let syslog logs get written
plog log "CREATING /dev/obd3 snapshot"
-$OBDDIR/class/obdcontrol -f << EOF
+$OBDDIR/utils/obdcontrol -f << EOF
snaptable
$SNAPTABLE
a
plog umount $MNTSNAP
plog log "CLEANUP /dev/obd2 /dev/obd1"
-$OBDDIR/class/obdcontrol -f << EOF
+$OBDDIR/utils/obdcontrol -f << EOF
device /dev/obd2
cleanup
detach
sync
sleep 1
plog log "STARTING snapdelete"
-$OBDDIR/class/obdcontrol -f << EOF
+$OBDDIR/utils/obdcontrol -f << EOF
device /dev/obd2
connect
snapdelete
plog log "STARTING snaprestore"
-$OBDDIR/class/obdcontrol -f << EOF
+$OBDDIR/utils/obdcontrol -f << EOF
device /dev/obd1
cleanup
detach
rmmod obdfs
-$OBDDIR/class/obdcontrol -f << EOF
+$OBDDIR/utils/obdcontrol -f << EOF
device /dev/obd2
cleanup
detach
# second will be a snapshot of the filesystem taken "now" (in obd device 2)
# that will remain static (historical read-only) filesystem as changes
# are made to the current snapshot.
-$OBDDIR/class/obdcontrol -f << EOF
+$OBDDIR/utils/obdcontrol -f << EOF
snaptable
$SNAPTABLE
a
obd_count *vallen, void **val);
int (*o_set_info)(struct obd_conn *, obd_count keylen, void *key,
obd_count vallen, void *val);
- int (*o_attach)(struct obd_device *dev, struct obd_ioctl_data *data);
+ int (*o_attach)(struct obd_device *dev, obd_count len, void *data);
int (*o_detach)(struct obd_device *dev);
- int (*o_setup) (struct obd_device *dev, struct obd_ioctl_data *data);
+ int (*o_setup) (struct obd_device *dev, obd_count len, void *data);
int (*o_cleanup)(struct obd_device *dev);
int (*o_connect)(struct obd_conn *conn);
int (*o_disconnect)(struct obd_conn *conn);
#endif
struct ext2_obd {
- struct super_block * ext2_sb;
- struct vfsmount *vfsmnt;
+ struct super_block * e2_sb;
+ struct vfsmount *e2_vfsmnt;
};
struct vfsmount *fo_vfsmnt;
struct run_ctxt fo_ctxt;
__u64 fo_lastino;
+ struct file_operations *fo_fop;
+ struct inode_operations *fo_iop;
+ struct address_space_operations *fo_aops;
};
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 */
/* do the attach */
if ( OBT(obd) && OBP(obd, attach) ) {
- err = OBP(obd, attach)(obd, data);
+ err = OBP(obd, attach)(obd, sizeof(*data), data);
}
if ( err ) {
}
if ( OBT(obd) && OBP(obd, setup) )
- err = OBP(obd, setup)(obd, data);
+ err = OBP(obd, setup)(obd, sizeof(*data), data);
if (!err) {
obd->obd_type->typ_refcnt++;
/*
* linux/fs/ext2_obd/ext2_obd.c
*
- * Copyright (C) 1999 Stelias Computing, Inc.
- * Copyright (C) 1999 Seagate Technology, Inc.
* Copyright (C) 2001 Cluster File Systems, Inc.
*
* This code is issued under the GNU General Public License.
* See the file COPYING in this distribution
*
- * This is the object based disk driver based on ext2
- * written by Peter Braam <braam@clusterfs.com>, Phil Schwan <phil@off.net>
- * Andreas Dilger <adilger@turbolinux.com>
- *
+ * by Peter Braam <braam@clusterfs.com>
*/
#define EXPORT_SYMTAB
#include <linux/obd_class.h>
#include <linux/obd_ext2.h>
-
-
extern struct obd_device obd_dev[MAX_OBD_DEVICES];
long filter_memory;
static void filter_prep(struct obd_device *obddev)
{
struct run_ctxt saved;
+ struct file *file;
+ struct inode *inode;
long rc;
int fd;
struct stat64 buf;
- __u64 lastino = 0;
+ __u64 lastino = 2;
push_ctxt(&saved, &obddev->u.filter.fo_ctxt);
rc = sys_mkdir("O", 0700);
rc = sys_mkdir("P", 0700);
rc = sys_mkdir("D", 0700);
+ rc = sys_mkdir("O/2", 0755);
if ( (fd = sys_open("D/status", O_RDWR | O_CREAT, 0700)) == -1 ) {
printk("OBD filter: cannot create status file\n");
goto out;
} else {
rc = sys_read(fd, (char *)&lastino, sizeof(lastino));
if (rc != sizeof(lastino)) {
- printk("OBD filter: error writing lastino\n");
+ printk("OBD filter: error reading lastino\n");
goto out_close;
}
}
obddev->u.filter.fo_lastino = lastino;
+
+ /* this is also the moment to steal operations */
+ file = filp_open("D/status", O_RDONLY, 0);
+ if (!file || IS_ERR(file)) {
+ EXIT;
+ goto out_close;
+ }
+ inode = file->f_dentry->d_inode;
+ obddev->u.filter.fo_fop = file->f_op;
+ obddev->u.filter.fo_iop = inode->i_op;
+ obddev->u.filter.fo_aops = inode->i_mapping->a_ops;
+ filp_close(file, 0);
out_close:
rc = sys_close(fd);
return gen_disconnect(conn);
} /* ext2obd_disconnect */
-
-
-
-/*
- * to initialize a particular /dev/obdNNN to simulated OBD type
- * *data holds the device of the ext2 disk partition we will use.
- */
-static int filter_setup(struct obd_device *obddev, struct obd_ioctl_data* data)
+/* mount the file system (secretly) */
+static int filter_setup(struct obd_device *obddev, obd_count len,
+ void *buf)
+
{
+ struct obd_ioctl_data* data = buf;
struct vfsmount *mnt;
int err;
ENTRY;
lock_kernel();
-
MOD_DEC_USE_COUNT;
EXIT;
return 0;
}
-static struct inode *inode_from_obdo(struct obd_device *obddev,
+
+static struct file *filter_obj_open(struct obd_device *obddev,
struct obdo *oa)
{
+ struct file *file;
+ int error = 0;
char id[16];
- struct super_block *sb;
- struct inode *inode;
struct run_ctxt saved;
- struct stat64 st;
+ struct super_block *sb;
sb = obddev->u.filter.fo_sb;
if (!sb || !sb->s_dev) {
}
sprintf(id, "O/%Ld", oa->o_id);
-
push_ctxt(&saved, &obddev->u.filter.fo_ctxt);
- if (sys_stat64(id, &st, 0)) {
- EXIT;
+ file = filp_open(id , O_RDONLY, 0);
+ pop_ctxt(&saved);
+
+ if (IS_ERR(file)) {
+ error = PTR_ERR(file);
+ file = NULL;
+ }
+ CDEBUG(D_INODE, "opening obdo %s\n", id);
+
+ if ( file ) {
+ file->f_op = obddev->u.filter.fo_fop;
+ file->f_dentry->d_inode->i_op = obddev->u.filter.fo_iop;
+ file->f_dentry->d_inode->i_mapping->a_ops = obddev->u.filter.fo_aops;
+ } else {
+ printk("Error opening object %s, error %d\n", id, error);
+ }
+ return file;
+}
+
+static struct inode *inode_from_obdo(struct obd_device *obddev,
+ struct obdo *oa)
+{
+ struct file *file;
+ struct inode *inode;
+
+ file = filter_obj_open(obddev, oa);
+ if ( !file ) {
+ printk("inode_from_obdo failed\n");
return NULL;
}
- pop_ctxt(&saved);
- inode = iget(sb, st.st_ino);
- if (!inode || inode->i_nlink == 0 || is_bad_inode(inode)) {
- printk("from obdo - fatal: invalid inode %ld (%s).\n",
- (long)oa->o_id, inode ? inode->i_nlink ? "bad inode" :
- "no links" : "NULL");
- if (inode)
- iput(inode);
- EXIT;
- return NULL;
- }
+ inode = iget(file->f_dentry->d_inode->i_sb, file->f_dentry->d_inode->i_ino);
+ filp_close(file, 0);
return inode;
}
return -ENOENT;
}
+ oa->o_valid &= ~OBD_MD_FLID;
filter_from_inode(oa, inode);
+
iput(inode);
EXIT;
return 0;
struct obd_device *obddev = conn->oc_dev;
struct iattr;
int rc;
+ ENTRY;
if (!gen_client(conn)) {
CDEBUG(D_IOCTL, "invalid client %u\n", conn->oc_id);
return -EINVAL;
}
+ CDEBUG(D_IOCTL, "\n");
conn->oc_dev->u.filter.fo_lastino++;
oa->o_id = conn->oc_dev->u.filter.fo_lastino;
sprintf(name, "O/%Ld", oa->o_id);
push_ctxt(&saved, &obddev->u.filter.fo_ctxt);
- if (sys_mknod(name, 010644, 0)) {
- printk("Error mknod %s\n", name);
+ CDEBUG(D_IOCTL, "\n");
+ if (sys_mknod(name, 0100644, 0)) {
+ printk("Error mknod obj %s\n", name);
return -ENOENT;
}
pop_ctxt(&saved);
+ CDEBUG(D_IOCTL, "\n");
rc = filter_setattr(conn, oa);
if ( rc ) {
EXIT;
return -EINVAL;
}
+ CDEBUG(D_IOCTL, "\n");
/* Set flags for fields we have set in ext2_new_inode */
oa->o_valid |= OBD_MD_FLID | OBD_MD_FLBLKSZ | OBD_MD_FLBLOCKS |
return 0;
}
+/* buffer must lie in user memory here */
static int filter_read(struct obd_conn *conn, struct obdo *oa, char *buf,
obd_size *count, obd_off offset)
{
- struct super_block *sb;
- struct inode * inode;
- struct file * f;
- struct file fake_file;
- struct dentry fake_dentry;
+ struct file * file;
unsigned long retval;
int err;
-
if (!gen_client(conn)) {
CDEBUG(D_IOCTL, "invalid client %u\n", conn->oc_id);
EXIT;
return -EINVAL;
}
- sb = conn->oc_dev->u.ext2.ext2_sb;
- if ( !(inode = inode_from_obdo(conn->oc_dev, oa)) ) {
+ file = filter_obj_open(conn->oc_dev, oa);
+ if (!file || IS_ERR(file)) {
EXIT;
- return -ENOENT;
+ return -PTR_ERR(file);
}
- if (!S_ISREG(inode->i_mode)) {
- iput(inode);
- CDEBUG(D_INODE, "fatal: not regular file %ld (mode=%o).\n",
- inode->i_ino, inode->i_mode);
- EXIT;
- return -EINVAL;
- }
-
- memset(&fake_file, 0, sizeof(fake_file));
- memset(&fake_dentry, 0, sizeof(fake_dentry));
-
- f = &fake_file;
- f->f_dentry = &fake_dentry;
- f->f_dentry->d_inode = inode;
- f->f_flags = O_LARGEFILE;
- f->f_op = &ext2_file_operations;
- inode->i_mapping->a_ops = &ext2_aops;
-
/* count doubles as retval */
- retval = f->f_op->read(f, buf, *count, &offset);
- iput(inode);
+ retval = file->f_op->read(file, buf, *count, &offset);
+ filp_close(file, 0);
+
if ( retval >= 0 ) {
err = 0;
*count = retval;
} /* ext2obd_read */
+/* buffer must lie in user memory here */
static int filter_write(struct obd_conn *conn, struct obdo *oa, char *buf,
obd_size *count, obd_off offset)
{
int err;
- struct super_block *sb;
- struct inode * inode;
- struct file fake_file;
- struct dentry fake_dentry;
- struct file * f;
+ struct file * file;
unsigned long retval;
ENTRY;
-
if (!gen_client(conn)) {
CDEBUG(D_IOCTL, "invalid client %u\n", conn->oc_id);
EXIT;
return -EINVAL;
}
- sb = conn->oc_dev->u.ext2.ext2_sb;
- if ( !(inode = inode_from_obdo(conn->oc_dev, oa)) ) {
+ file = filter_obj_open(conn->oc_dev, oa);
+ if (!file || IS_ERR(file)) {
EXIT;
- return -ENOENT;
+ return -PTR_ERR(file);
}
- if (!S_ISREG(inode->i_mode)) {
- CDEBUG(D_INODE, "fatal: not regular file.\n");
- iput(inode);
- EXIT;
- return -EINVAL;
- }
-
- memset(&fake_file, 0, sizeof(fake_file));
- memset(&fake_dentry, 0, sizeof(fake_dentry));
-
- f = &fake_file;
- f->f_dentry = &fake_dentry;
- f->f_dentry->d_inode = inode;
- f->f_op = &ext2_file_operations;
- f->f_flags = O_LARGEFILE;
- inode->i_mapping->a_ops = &ext2_aops;
-
/* count doubles as retval */
- if (f->f_op->write)
- retval = f->f_op->write(f, buf, *count, &(offset));
- else
- retval = -EINVAL;
- CDEBUG(D_INFO, "Result %ld\n", retval);
-
- oa->o_valid = OBD_MD_FLBLOCKS | OBD_MD_FLCTIME | OBD_MD_FLMTIME;
- obdo_from_inode(oa, inode);
- iput(inode);
+ retval = file->f_op->write(file, buf, *count, &offset);
+ filp_close(file, 0);
if ( retval >= 0 ) {
err = 0;
return err;
} /* ext2obd_write */
-void ___wait_on_page(struct page *page)
-{
- struct task_struct *tsk = current;
- DECLARE_WAITQUEUE(wait, tsk);
-
- add_wait_queue(&page->wait, &wait);
- do {
- run_task_queue(&tq_disk);
- set_task_state(tsk, TASK_UNINTERRUPTIBLE);
- if (!PageLocked(page))
- break;
- schedule();
- } while (PageLocked(page));
- tsk->state = TASK_RUNNING;
- remove_wait_queue(&page->wait, &wait);
-}
-
-static inline int actor_from_kernel(char *dst, char *src, size_t len)
-{
- ENTRY;
- memcpy(dst, src, len);
- EXIT;
- return 0;
-}
-
-int kernel_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
-{
- char *kaddr;
- unsigned long count = desc->count;
- ENTRY;
- if (desc->buf == NULL) {
- printk("ALERT: desc->buf == NULL\n");
- desc->error = -EIO;
- return -EIO;
- }
-
- if (size > count)
- size = count;
-
- kaddr = kmap(page);
- memcpy(desc->buf, kaddr + offset, size);
- kunmap(page);
-
- desc->count = count - size;
- desc->written += size;
- desc->buf += size;
- EXIT;
- return size;
-}
-
static int filter_pgcache_brw(int rw, struct obd_conn *conn,
obd_count num_oa,
struct obdo **oa,
obd_flag *flags)
{
struct super_block *sb;
+ mm_segment_t oldfs;
int onum; /* index to oas */
int pnum; /* index to pages (bufs) */
unsigned long retval;
- int err;
- struct file fake_file;
- struct dentry fake_dentry;
- struct file *f;
+ int error;
+ struct file *file;
ENTRY;
return -EINVAL;
}
- sb = conn->oc_dev->u.ext2.ext2_sb;
+ sb = conn->oc_dev->u.filter.fo_sb;
+ oldfs = get_fs();
+ set_fs(KERNEL_DS);
pnum = 0; /* pnum indexes buf 0..num_pages */
for (onum = 0; onum < num_oa; onum++) {
- struct inode *inode;
int pg;
- if ( rw == READ )
- *flags &= ~OBD_BRW_CREATE;
-
- if (! (inode = inode_from_obdo(conn->oc_dev, oa[onum])) ) {
- EXIT;
- return -ENOENT;
- }
-
- CDEBUG(D_INODE, "ino %ld, i_count %d\n",
- inode->i_ino, atomic_read(&inode->i_count));
- memset(&fake_file, 0, sizeof(fake_file));
- memset(&fake_dentry, 0, sizeof(fake_dentry));
-
- f = &fake_file;
- f->f_dentry = &fake_dentry;
- f->f_dentry->d_inode = inode;
- f->f_op = &ext2_file_operations;
- f->f_flags = O_LARGEFILE;
- inode->i_mapping->a_ops = &ext2_aops;
+ file = filter_obj_open(conn->oc_dev, oa[onum]);
+ if (!file || IS_ERR(file)) {
+ EXIT;
+ error = -ENOENT;
+ goto ERROR;
+ }
/* count doubles as retval */
for (pg = 0; pg < oa_bufs[onum]; pg++) {
CDEBUG(D_INODE, "OP %d obdo no/pno: (%d,%d) (%ld,%ld) off count (%Ld,%Ld)\n",
- rw, onum, pnum, inode->i_ino,
+ rw, onum, pnum, file->f_dentry->d_inode->i_ino,
(unsigned long)offset[pnum] >> PAGE_CACHE_SHIFT,
offset[pnum], count[pnum]);
if (rw == WRITE) {
char *buffer;
off = offset[pnum];
buffer = kmap(pages[pnum]);
- retval = do_generic_file_write
- (f, buffer, count[pnum], &off,
- actor_from_kernel);
+ retval = file->f_op->write(file, buffer, count[pnum], &off);
kunmap(pages[pnum]);
CDEBUG(D_INODE, "retval %ld\n", retval);
} else {
- loff_t off;
- read_descriptor_t desc;
+ loff_t off = offset[pnum];
char *buffer = kmap(pages[pnum]);
- desc.written = 0;
- desc.count = count[pnum];
- desc.buf = buffer;
- desc.error = 0;
- off = offset[pnum];
-
- off = offset[pnum];
- if (off >= inode->i_size) {
- memset(buffer, 0, PAGE_SIZE);
+ if (off >= file->f_dentry->d_inode->i_size) {
+ memset(buffer, 0, count[pnum]);
+ retval = count[pnum];
} else {
- do_generic_file_read
- (f, &off, &desc,
- kernel_read_actor);
+ retval = file->f_op->read(file, buffer, count[pnum], &off);
}
kunmap(pages[pnum]);
- retval = desc.written;
- if ( !retval ) {
- iput(inode);
- retval = desc.error;
+
+ if ( retval != count[pnum] ) {
+ filp_close(file, 0);
+ retval = -EIO;
EXIT;
goto ERROR;
}
}
/* sizes and blocks are set by generic_file_write */
/* ctimes/mtimes will follow with a setattr call */
-
- //oa[onum]->o_blocks = inode->i_blocks;
- //oa[onum]->o_valid = OBD_MD_FLBLOCKS;
- /* perform the setattr on the inode */
- //ext2obd_to_inode(inode, oa[onum]);
- //inode->i_size = oa[onum]->o_size;
- //mark_inode_dirty(inode);
- iput(inode);
+ filp_close(file, 0);
}
EXIT;
ERROR:
- err = (retval >= 0) ? 0 : retval;
- return err;
+ set_fs(oldfs);
+ error = (retval >= 0) ? 0 : retval;
+ return error;
}
static int filter_statfs (struct obd_conn *conn, struct statfs * statfs)
#define PageChecked(page) test_bit(PG_checked, &(page)->flags)
#define SetPageChecked(page) set_bit(PG_checked, &(page)->flags)
-#define PG_checked 13 /* kill me in 2.5.<early>. */
int waitfor_one_page(struct page *page)
{
{
ssize_t retval;
CDEBUG(D_INFO, "Writing inode %ld, %d bytes, offset %Ld\n",
- file->f_dentry->d_inode->i_ino, count, ppos);
+ file->f_dentry->d_inode->i_ino, count, *ppos);
retval = generic_file_write(file, buf, count, ppos);
CDEBUG(D_INFO, "Wrote %d\n", retval);
/* Send a hint to the create method on the type of file to create */
oa->o_mode = mode;
oa->o_valid |= OBD_MD_FLMODE;
-
+ CDEBUG(D_INODE, "\n");
err = IOPS(dir, create)(IID(dir), oa);
+ CDEBUG(D_INODE, "\n");
if ( err ) {
printk("new_inode - fatal: err %d\n", err);
EXIT;
return ERR_PTR(err);
}
+ CDEBUG(D_INODE, "\n");
inode = iget4(dir->i_sb, (ino_t)oa->o_id, NULL, oa);
+ CDEBUG(D_INODE, "\n");
obdo_free(oa);
if (!inode) {
/* page cache support stuff */
+
/*
* Add a page to the dirty page list.
*/
-void __set_page_dirty(struct page *page)
+void set_page_dirty(struct page *page)
{
- struct address_space *mapping;
- spinlock_t *pg_lock;
-
- pg_lock = PAGECACHE_LOCK(page);
- spin_lock(pg_lock);
-
- mapping = page->mapping;
- spin_lock(&mapping->page_lock);
-
- list_del(&page->list);
- list_add(&page->list, &mapping->dirty_pages);
-
- spin_unlock(&mapping->page_lock);
- spin_unlock(pg_lock);
-
- if (mapping->host)
- mark_inode_dirty_pages(mapping->host);
+ if (!test_and_set_bit(PG_dirty, &page->flags)) {
+ struct address_space *mapping = page->mapping;
+
+ if (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.
+ * Remove page from dirty list
*/
void __set_page_clean(struct page *page)
{
+ struct address_space *mapping = page->mapping;
struct inode *inode;
- struct address_space *mapping;
- spinlock_t *pg_lock;
-
- pg_lock = PAGECACHE_LOCK(page);
- spin_lock(pg_lock);
-
- mapping = page->mapping;
- spin_lock(&mapping->page_lock);
+
+ if (!mapping)
+ return;
+ spin_lock(&pagecache_lock);
list_del(&page->list);
list_add(&page->list, &mapping->clean_pages);
- spin_unlock(&mapping->page_lock);
- spin_unlock(pg_lock);
-
inode = mapping->host;
if (list_empty(&mapping->dirty_pages)) {
CDEBUG(D_INODE, "inode clean\n");
inode->i_state &= ~I_DIRTY_PAGES;
}
+ spin_unlock(&pagecache_lock);
EXIT;
}
struct obd_device *obddev;
char *device = NULL;
char *version = NULL;
+ int connected = 0;
int devno;
int err;
unsigned long blocksize;
EXIT;
goto ERR;
}
-
+ connected = 1;
CDEBUG(D_INFO, "\n");
/* list of dirty inodes, and a mutex to hold while modifying it */
INIT_LIST_HEAD(&sbi->osi_inodes);
OBD_FREE(device, strlen(device) + 1);
if (version)
OBD_FREE(version, strlen(version) + 1);
+ if (connected)
+ sbi->osi_ops->o_disconnect(&sbi->osi_conn);
+
if (sbi) {
sbi->osi_super = NULL;
}
--- /dev/null
+--- /usr/src/linux-2.4.16/fs/reiserfs/file.c.obd-orig Thu Dec 13 14:35:00 2001
++++ /usr/src/linux-2.4.16/fs/reiserfs/file.c Thu Dec 13 14:35:08 2001
+@@ -28,8 +28,8 @@
+ struct reiserfs_transaction_handle th ;
+ int windex ;
+
+- if (!S_ISREG (inode->i_mode))
+- BUG ();
++ //if (!S_ISREG (inode->i_mode))
++ //BUG ();
+
+ /* fast out for when nothing needs to be done */
+ if ((atomic_read(&inode->i_count) > 1 ||
+--- /usr/src/linux-2.4.16/fs/namespace.c.obd-orig Tue Dec 11 20:44:15 2001
++++ /usr/src/linux-2.4.16/fs/namespace.c Tue Dec 11 20:44:35 2001
+@@ -332,7 +332,7 @@
+ }
+ }
+
+-static int do_umount(struct vfsmount *mnt, int flags)
++int do_umount(struct vfsmount *mnt, int flags)
+ {
+ struct super_block * sb = mnt->mnt_sb;
+ int retval = 0;
+--- /usr/src/linux-2.4.16/kernel/ksyms.c.obd-orig Tue Dec 11 14:22:09 2001
++++ /usr/src/linux-2.4.16/kernel/ksyms.c Tue Dec 11 18:05:30 2001
+@@ -268,6 +268,7 @@
+ EXPORT_SYMBOL(__pollwait);
+ EXPORT_SYMBOL(poll_freewait);
+ EXPORT_SYMBOL(ROOT_DEV);
++EXPORT_SYMBOL(pagecache_lock);
+ EXPORT_SYMBOL(__find_get_page);
+ EXPORT_SYMBOL(__find_lock_page);
+ EXPORT_SYMBOL(grab_cache_page);
+--- /usr/src/linux-2.4.16/mm/filemap.c.obd-orig Mon Nov 26 06:29:17 2001
++++ /usr/src/linux-2.4.16/mm/filemap.c Tue Dec 11 14:29:50 2001
+@@ -2846,8 +2846,7 @@
+ * file system has to do this all by itself, unfortunately.
+ * okir@monad.swb.de
+ */
+-ssize_t
+-generic_file_write(struct file *file,const char *buf,size_t count, loff_t *ppos)
++ssize_t do_generic_file_write(struct file *file,const char *buf,size_t count,loff_t *ppos, int (*actor)(char *, char *, size_t ))
+ {
+ struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
+ struct inode *inode = mapping->host;
+@@ -2862,8 +2861,10 @@
+ if ((ssize_t) count < 0)
+ return -EINVAL;
+
++#if 0
+ if (!access_ok(VERIFY_READ, buf, count))
+ return -EFAULT;
++#endif
+
+ cached_page = NULL;
+
+@@ -2987,10 +2988,12 @@
+ * same page as we're writing to, without it being marked
+ * up-to-date.
+ */
++#if 0
+ { volatile unsigned char dummy;
+ __get_user(dummy, buf);
+ __get_user(dummy, buf+bytes-1);
+ }
++#endif
+
+ status = -ENOMEM; /* we'll assign it later anyway */
+ page = __grab_cache_page(mapping, index, &cached_page);
+@@ -3006,7 +3009,7 @@
+ status = mapping->a_ops->prepare_write(file, page, offset, offset+bytes);
+ if (status)
+ goto unlock;
+- page_fault = __copy_from_user(kaddr+offset, buf, bytes);
++ page_fault = actor(kaddr+offset, buf, bytes);
+ flush_dcache_page(page);
+ status = mapping->a_ops->commit_write(file, page, offset, offset+bytes);
+ if (page_fault)
+@@ -3072,6 +3075,23 @@
+ goto out_status;
+ }
+
++
++static inline int actor_from_user(char *dst, char *src, size_t len)
++{
++ if (!access_ok(VERIFY_READ, src, len))
++ return -EFAULT;
++
++ return __copy_from_user(dst, src, len);
++}
++
++ssize_t
++generic_file_write(struct file *file,const char *buf,size_t count,loff_t *ppos)
++{
++ return do_generic_file_write(file, buf, count, ppos, &actor_from_user);
++}
++
++
++
+ void __init page_cache_init(unsigned long mempages)
+ {
+ unsigned long htable_size, order;
+--- /usr/src/linux-2.4.16/include/linux/fs.h.obd-orig Tue Dec 11 14:23:29 2001
++++ /usr/src/linux-2.4.16/include/linux/fs.h Tue Dec 11 20:45:00 2001
+@@ -978,8 +978,10 @@
+ extern int register_filesystem(struct file_system_type *);
+ extern int unregister_filesystem(struct file_system_type *);
+ extern struct vfsmount *kern_mount(struct file_system_type *);
++struct vfsmount *do_kern_mount(char *type, int flags, char *name, void *data);
+ extern int may_umount(struct vfsmount *);
+ extern long do_mount(char *, char *, char *, unsigned long, void *);
++int do_umount(struct vfsmount *mnt, int flags);
+
+ #define kern_umount mntput
+
+@@ -1044,6 +1046,35 @@
+
+ asmlinkage long sys_open(const char *, int, int);
+ asmlinkage long sys_close(unsigned int); /* yes, it's really unsigned */
++asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count);
++asmlinkage ssize_t sys_write(unsigned int fd, const char * buf, size_t count);
++asmlinkage long sys_truncate64(const char * path, loff_t length);
++asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length);
++asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
++ unsigned long flags, void * data);
++asmlinkage long sys_umount(char * name, int flags);
++asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf);
++asmlinkage long sys_mknod(const char * filename, int mode, dev_t dev);
++asmlinkage long sys_mkdir(const char * pathname, int mode);
++asmlinkage long sys_rmdir(const char * pathname);
++asmlinkage long sys_unlink(const char * pathname);
++asmlinkage long sys_symlink(const char * oldname, const char * newname);
++asmlinkage long sys_link(const char * oldname, const char * newname);
++asmlinkage long sys_rename(const char * oldname, const char * newname);
++asmlinkage long sys_lstat64(char * filename, struct stat64 * statbuf, long flags);
++asmlinkage long sys_stat64(char * filename, struct stat64 * statbuf, long flags);
++asmlinkage long sys_fstat64(unsigned long fd, struct stat64 * statbuf, long flags);
++
++
++
++
++
++
++
++
++
++
++
+ extern int do_truncate(struct dentry *, loff_t start);
+
+ extern struct file *filp_open(const char *, int, int);
+@@ -1395,6 +1426,8 @@
+ extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *);
+ extern ssize_t generic_file_write(struct file *, const char *, size_t, loff_t *);
+ extern void do_generic_file_read(struct file *, loff_t *, read_descriptor_t *, read_actor_t);
++ssize_t do_generic_file_write(struct file *file,const char *buf,size_t count,loff_t *ppos, int (*actor)(char *, char *, size_t ));
++
+ extern loff_t no_llseek(struct file *file, loff_t offset, int origin);
+ extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin);
+ extern ssize_t generic_read_dir(struct file *, char *, size_t, loff_t *);