--- /dev/null
+config.h
+config.out
+config.mk
+.depfiles
+.prereq.ok
+.ready
#include <linux/fs.h>
#include <linux/ext2_fs.h>
-
+#include <linux/time.h>
#include <linux/obd.h>
#include <linux/obd_sim.h>
#include <linux/obd_snap.h>
/* #include <linux/obd_fc.h> */
#include <linux/obd_raid1.h>
+#include <linux/obd_rpc.h>
#define OBD_PSDEV_MAJOR 120
#define MAX_OBD_DEVICES 2
#define MAX_MULTI 16
-typedef unsigned long objid;
+typedef int objid;
typedef struct inode obdattr;
extern struct obd_device obd_dev[MAX_OBD_DEVICES];
struct sim_obd sim;
struct raid1_obd raid1;
struct snap_obd snap;
+ struct rpc_obd rpc;
/* struct fc_obd fc; */
} u;
};
unsigned long (*o_read)(unsigned int conn_id, unsigned long ino, char *buf, unsigned long count, loff_t offset, int *err);
unsigned long (*o_read2)(unsigned int conn_id, unsigned long ino, char *buf, unsigned long count, loff_t offset, int *err);
unsigned long (*o_write)(unsigned int conn_id, unsigned long ino, char *buf, unsigned long count, loff_t offset, int *err);
- int (*o_brw)(int rw, int conn, int objectid, struct page *page, int create);
+ int (*o_brw)(int rw, int conn, obdattr *obj, struct page *page, int create);
long (*o_preallocate)(unsigned int conn_id, int req, long inodes[32], int *err);
int (*o_cleanup_device)(struct obd_device *);
int (*o_get_info)(unsigned int conn_id, int keylen, void *key, int *vallen, void **val);
--- /dev/null
+#ifndef __OBD_RPC_H
+#define __OBD_RPC_H
+
+#define OBD_TGT_VERSION 001
+
+#define OBD_TGT_TCP 0x1
+#define OBD_TGT_INTR 0x2
+#define OBD_TGT_SOFT 0x4
+
+
+
+
+/* error codes */
+
+enum obd_stat {
+ OBD_OK = 0,
+ OBDERR_PERM = 1,
+ OBDERR_NOENT = 2,
+ OBDERR_IO = 5,
+ OBDERR_NXIO = 6,
+ OBDERR_ACCESS = 13,
+ OBDERR_EXIST = 17,
+ OBDERR_XDEV = 18,
+ OBDERR_NODEV = 19,
+ OBDERR_INVAL = 22,
+ OBDERR_FBIG = 27,
+ OBDERR_NOSPC = 28,
+ OBDERR_ROFS = 30,
+ OBDERR_OPNOTSUPP = 45,
+ OBDERR_DQUOT = 69
+};
+
+
+
+#define OBD_PROGRAM 100003
+#define OBD_VERSION 2
+#define OBDPROC_NULL 0
+#define OBDPROC_GETATTR 1
+#define OBDPROC_SETATTR 2
+#define OBDPROC_ROOT 3
+#define OBDPROC_LOOKUP 4
+#define OBDPROC_READLINK 5
+#define OBDPROC_READ 6
+#define OBDPROC_WRITECACHE 7
+#define OBDPROC_WRITE 8
+#define OBDPROC_CREATE 9
+#define OBDPROC_REMOVE 10
+#define OBDPROC_RENAME 11
+#define OBDPROC_LINK 12
+#define OBDPROC_SYMLINK 13
+#define OBDPROC_MKDIR 14
+
+
+
+extern struct rpc_program obd_program;
+
+
+
+
+
+
+struct obd_target {
+ struct sockaddr_in tgt_addr;
+ int tgt_flags;
+ int tgt_timeo;
+ int tgt_retrans;
+ int tgt_hostnamelen;
+ char tgt_hostname[0];
+
+};
+
+
+struct rpc_obd {
+ struct rpc_clnt * client; /* RPC client handle */
+ struct sockaddr_in addr;
+ int flags; /* various flags */
+ int rsize; /* read size */
+ int wsize; /* write size */
+ unsigned int bsize; /* server block size */
+ char * hostname; /* remote hostname */
+};
+
+
+#endif
-#ifndef _OBD_SIM
-#define _OBD_SIM
+#ifndef _OBD_SNAP
+#define _OBD_SNAP
#define OBD_SNAP_MAGIC 0x47224722
int od_magic;
/* id of snaps of object; slot 0 has the current data */
unsigned long od_ids[SNAP_MAX + 1];
-}
+};
+
#ifndef _OBD_SUPPORT
#define _OBD_SUPPORT
#include <linux/malloc.h>
#define EXIT \
if (obd_print_entry) \
- printk("Process %d leaving %s\n", current->pid, __FUNCTION__)
+ printk("Process %d leaving %s [%d]\n", current->pid, __FUNCTION__, __LINE__)
#else /* SIM_OBD_DEBUG */
#define CMD(cmd) (( cmd == READ ) ? "read" : "write")
+#define IDEBUG(inode) { \
+ if ( !list_empty(&inode->i_data.pages) || inode->i_data.nrpages ) {\
+ struct page * page;\
+ printk("XXXXX: func %s line %d ino %ld list not empty, pages %ld\n", __FUNCTION__ , __LINE__,\
+ inode->i_ino, inode->i_data.nrpages);\
+ page = list_entry(inode->i_data.pages.next, struct page , list);\
+ PDEBUG(page, "READ INODE");\
+ }}
+
+
#define PDEBUG(page,cmd) {if (page){\
char *uptodate = (Page_Uptodate(page)) ? "yes" : "no";\
char *locked = (PageLocked(page)) ? "yes" : "no";\
int count = page->count.counter;\
- long ino = (page->inode) ? page->inode->i_ino : -1;\
- long offset = page->offset / PAGE_SIZE;\
+ long offset = page->offset;\
\
- CDEBUG(D_IOCTL, " ** %s, cmd: %s, ino: %ld, off %ld, uptodate: %s, "\
- "locked: %s, cnt %d page %p ** \n", __FUNCTION__,\
- cmd, ino, offset, uptodate, locked, count, page);\
+ CDEBUG(D_IOCTL, " ** %s, cmd: %s, off %ld, uptodate: %s, "\
+ "locked: %s, cnt %d page %p pages %ld** \n", __FUNCTION__,\
+ cmd, offset, uptodate, locked, count, page, page->mapping->nrpages);\
} else { CDEBUG(D_IOCTL, "** %s, no page\n", __FUNCTION__); }}
tmp->ia_atime = inode->i_atime;
tmp->ia_mtime = inode->i_mtime;
tmp->ia_ctime = inode->i_ctime;
- tmp->ia_attr_flags = inode->i_flags;
+ /* tmp->ia_flags = inode->i_flags; */
tmp->ia_valid = ~0;
}
dest->i_atime = src->i_atime;
dest->i_mtime = src->i_mtime;
dest->i_ctime = src->i_ctime;
- dest->i_attr_flags = src->i_flags;
+ dest->i_flags = src->i_flags;
/* allocation of space */
dest->i_blocks = src->i_blocks;
#define OBDFS_H
#include <../obd/linux/obd_class.h>
+/* super.c */
+void obdfs_read_inode(struct inode *inode);
+
+
/* file.c */
ssize_t obdfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos);
--- /dev/null
+#!/bin/sh
+
+umount /mnt/obd
+rmmod obdfs
+
+./obdcontrol -f << EOF
+cleanup
+quit
+EOF
+
+rmmod obdsim
+rmmod obdclass
+
int gen_multi_cleanup(struct obd_device * obddev)
{
int i;
- struct obd_device *rdev = obddev->obd_multi_dev[0];
+ struct obd_device **rdev = obddev->obd_multi_dev;
for (i = 0 ; i < obddev->obd_multi_count ; i++ ) {
int rc;
- struct obd_device *child = rdev + i;
+ struct obd_device *child = *(rdev + i);
rc = OBP(child, cleanup)(child);
- *child = -1;
+ *(rdev + i) = NULL;
if ( rc != 0 ) {
/* XXX disconnect others */
int gen_multi_cleanup_device(struct obd_device *obddev)
{
int i;
- struct obd_device *rdev;
+ struct obd_device **rdev;
- rdev = obddev->obd_multi_dev[0];
+ rdev = obddev->obd_multi_dev;
for (i = 0 ; i < obddev->obd_multi_count ; i++ ) {
int rc;
- struct obd_device *child = rdev + i;
+ struct obd_device *child = *(rdev + i);
rc = OBP(child, disconnect)
(obddev->obd_multi_conns[i].conn_id);
if ( rc != 0 ) {
printk("OBD multi cleanup dev: disconnect failure %d\n", child->obd_minor);
}
- *child = 0;
+ *(rdev + i) = NULL;
}
return 0;
} /* gen_multi_cleanup_device */
sub Cleanup {
my $err = "0";
- my $rc = ioctl(DEV_OBD, &OBD_IOC_CLEANUP_OBDDEV, $err);
+ my $rc = ioctl(DEV_OBD, &OBD_IOC_CLEANUP, $err);
if (!defined $rc) {
print STDERR "ioctl failed: $!\n";
for ($i = 0; $i < scalar($arg); $i++) {
$rc = ioctl(DEV_OBD, &OBD_IOC_CREATE, $packed);
my $ino = unpack("L", $packed);
- if (!($rc eq "0 but true") || $packed == 0) {
+ if (!($rc eq "0 but true")) {
last;
+ $packed = pack("IL", $::client_id, $prealloc);
} elsif (!defined($quiet)) {
+ $packed = pack("IL", $::client_id, $prealloc);
print "Created object #$ino.\n";
}
}
setup
quit
EOF
-mount -t obdfs /dev/loop0 /mnt/obd
+mount -t obdfs /dev/obd0 /mnt/obd
{ 0 }
};
+#if 0
static ctl_table jukebox_table[] = {
{OBD_SYSCTL, "obd", NULL, 0, 0555, obd_table},
{0}
};
-
+#endif
void obd_sysctl_init (void)
{
#ifdef CONFIG_SYSCTL
-I. -I$(LINUX)/include $(SMPFLAG)
COFLAGS = -kv
+ifeq ($(CONFIG_MODVERSIONS),"y")
CFLAGS= $(KFLAGS) $(MFLAG)
+else
+CFLAGS= $(KFLAGS)
+endif
-SRCS=file.c dir.c sysctl.c super.c rw.c namei.c
+SRCS=file.c dir.c sysctl.c super.c rw.c namei.c # symlink.c
OBJS=$(SRCS:%.c=%.o)
MODULES = obdfs.o
unsigned long offset)
{
const char * error_msg = NULL;
+ return 1;
ENTRY;
if ( !de ) {
offset = filp->f_pos & (PAGE_SIZE - 1);
while (!error && !stored && filp->f_pos < inode->i_size) {
- page = obdfs_getpage(inode, offset, 0, NOLOCK);
+ IDEBUG(inode);
+ page = obdfs_getpage(inode, offset, 0, LOCKED);
PDEBUG(page, "readdir");
if (!page) {
ext2_error (sb, "ext2_readdir",
filp->f_pos += le16_to_cpu(de->rec_len);
}
offset = 0;
+ UnlockPage(page);
page_cache_release(page);
}
UPDATE_ATIME(inode);
retval = generic_file_write(file, buf, count,
ppos, obdfs_write_one_page);
+ CDEBUG(D_INODE, "Wrote %d\n", retval);
if (retval > 0) {
struct inode *inode = file->f_dentry->d_inode;
remove_suid(inode);
unsigned long offset;
struct page * page;
ENTRY;
+ CDEBUG(D_INODE, "find entry for %*s\n", namelen, name);
*res_dir = NULL;
sb = dir->i_sb;
if (namelen > EXT2_NAME_LEN)
return NULL;
- for (page = 0, offset = 0; offset < dir->i_size; page++) {
+ CDEBUG(D_INODE, "dirsize is %ld\n", dir->i_size);
+
+ page = 0;
+ offset = 0;
+ while ( offset < dir->i_size ) {
struct ext2_dir_entry_2 * de;
char * dlimit;
page = obdfs_getpage(dir, offset, 0, lock);
- if ( !page )
+
+ if ( !page ) {
+ CDEBUG(D_INODE, "No page, offset %lx\n", offset);
return NULL;
+ }
de = (struct ext2_dir_entry_2 *) page_address(page);
dlimit = (char *)page_address(page) + PAGE_SIZE;
/* this code is executed quadratically often */
/* do minimal checking `by hand' */
int de_len;
+ CDEBUG(D_INODE, "Entry %p len %d, page at %#lx - %#lx , offset %lx\n",
+ de, le16_to_cpu(de->rec_len), page_address(page), page_address(page) +
+ PAGE_SIZE, offset);
if ((char *) de + namelen <= dlimit &&
ext2_match (namelen, name, de)) {
}
/* prevent looping on a bad block */
de_len = le16_to_cpu(de->rec_len);
- if (de_len <= 0)
+ if (de_len <= 0) {
+ CDEBUG(D_INODE, "Bad entry: at %p len %d\n",
+ de, de_len);
goto failure;
+ }
offset += de_len;
de = (struct ext2_dir_entry_2 *)
((char *) de + de_len);
+ CDEBUG(D_INODE, "Next while %lx\n", offset);
}
+ if ( lock )
+ UnlockPage(page);
page_cache_release(page);
+ page = NULL;
+ CDEBUG(D_INODE, "Next for %lx\n", offset);
}
failure:
- page_cache_release(page);
+ CDEBUG(D_INODE, "Negative case, page %p, offset %ld\n", page, offset);
+ if (page) {
+ if (lock)
+ UnlockPage(page);
+ page_cache_release(page);
+ }
EXIT;
return NULL;
}
if (dentry->d_name.len > EXT2_NAME_LEN)
return ERR_PTR(-ENAMETOOLONG);
- page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, NOLOCK);
+ page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, LOCKED);
inode = NULL;
if ( !page )
CDEBUG(D_INODE, "No page - negative entry.\n");
}
if (page) {
unsigned long ino = le32_to_cpu(de->inode);
+ UnlockPage(page);
page_cache_release(page);
inode = iget(dir->i_sb, ino);
* may not sleep between calling this and putting something into
* the entry, as someone else might have used it while you slept.
- * returns a locked page
+ * returns a locked and held page upon success
*/
static struct page *obdfs_add_entry (struct inode * dir,
const char * name, int namelen,
ENTRY;
*err = -EINVAL;
*res_dir = NULL;
- if (!dir || !dir->i_nlink)
+ if (!dir || !dir->i_nlink) {
+ EXIT;
return NULL;
+ }
sb = dir->i_sb;
- if (!namelen)
+ if (!namelen) {
+ EXIT;
return NULL;
+ }
/*
* Is this a busy deleted directory? Can't create new files if so
*/
if (dir->i_size == 0)
{
+ EXIT;
*err = -ENOENT;
return NULL;
}
return NULL;
}
rec_len = EXT2_DIR_REC_LEN(namelen);
+ CDEBUG(D_INODE, "reclen: %d\n", rec_len);
offset = 0;
de = (struct ext2_dir_entry_2 *) page_address(page);
*err = -ENOSPC;
while (1) {
+ CDEBUG(D_INODE, "Considering entry at %p, (page at %#lx - %#lx), offset %ld\n",
+ de, page_address(page), page_address(page) + PAGE_SIZE, offset);
if ((char *)de >= PAGE_SIZE + (char *)page_address(page)) {
UnlockPage(page);
page_cache_release(page);
page = obdfs_getpage(dir, offset, 1, LOCKED);
- if (!page)
+ if (!page) {
+ EXIT;
return NULL;
+ }
if (dir->i_size <= offset) {
if (dir->i_size == 0) {
*err = -ENOENT;
+ EXIT;
return NULL;
}
- ext2_debug ("creating next block\n");
+ CDEBUG(D_INODE, "creating next block\n");
de = (struct ext2_dir_entry_2 *) page_address(page);
de->inode = 0;
if (!obdfs_check_dir_entry ("ext2_add_entry", dir, de, page,
offset)) {
*err = -ENOENT;
+ UnlockPage(page);
page_cache_release(page);
EXIT;
return NULL;
EXIT;
return NULL;
}
- CDEBUG(D_INODE, "\n");
- if ((le32_to_cpu(de->inode) == 0 && le16_to_cpu(de->rec_len) >= rec_len) ||
- (le16_to_cpu(de->rec_len) >= EXT2_DIR_REC_LEN(de->name_len) + rec_len)) {
+ CDEBUG(D_INODE, "Testing for enough space at de %p\n", de);
+ if ( (le32_to_cpu(de->inode) == 0 &&
+ le16_to_cpu(de->rec_len) >= rec_len) ||
+ (le16_to_cpu(de->rec_len) >=
+ EXT2_DIR_REC_LEN(de->name_len) + rec_len)) {
offset += le16_to_cpu(de->rec_len);
+ CDEBUG(D_INODE, "Found enough space de %p, offset %#lx\n", de, offset);
if (le32_to_cpu(de->inode)) {
+ CDEBUG(D_INODE, "Inserting new in %p\n", de);
de1 = (struct ext2_dir_entry_2 *) ((char *) de +
EXT2_DIR_REC_LEN(de->name_len));
+ CDEBUG(D_INODE, "-- de1 at %p\n", de1);
de1->rec_len = cpu_to_le16(le16_to_cpu(de->rec_len) -
EXT2_DIR_REC_LEN(de->name_len));
de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(de->name_len));
de = de1;
}
- CDEBUG(D_INODE, "\n");
+ CDEBUG(D_INODE, "Reclen adjusted; copy %d bytes to %p, page at %#lx EOP at %#lx\n", namelen, de->name, page_address(page), page_address(page) + PAGE_SIZE);
de->inode = 0;
de->name_len = namelen;
de->file_type = 0;
memcpy (de->name, name, namelen);
- CDEBUG(D_INODE, "\n");
+ CDEBUG(D_INODE, "Copy done\n");
/*
* XXX shouldn't update any times until successful
* completion of syscall, but too many callers depend
*res_dir = de;
*err = 0;
PDEBUG(page, "addentry");
+ CDEBUG(D_INODE, "Regular exit from add_entry");
EXIT;
return page;
}
CDEBUG(D_INODE, "\n");
offset += le16_to_cpu(de->rec_len);
de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
+
}
CDEBUG(D_INODE, "\n");
de->file_type = EXT2_FT_DIR;
}
+
+/*
+ * Display all dentries holding the specified inode.
+ */
+static void show_dentry(struct list_head * dlist, int subdirs)
+{
+ struct list_head *tmp = dlist;
+
+ while ((tmp = tmp->next) != dlist) {
+ struct dentry * dentry;
+ const char * unhashed = "";
+
+ if ( subdirs )
+ dentry = list_entry(tmp, struct dentry, d_child);
+ else
+ dentry = list_entry(tmp, struct dentry, d_alias);
+
+ if (list_empty(&dentry->d_hash))
+ unhashed = "(unhashed)";
+
+ if ( dentry->d_inode )
+ printk("show_dentry: %s/%s, d_count=%d%s (ino %ld, dev %d, ct %d)\n",
+ dentry->d_parent->d_name.name,
+ dentry->d_name.name, dentry->d_count,
+ unhashed, dentry->d_inode->i_ino,
+ dentry->d_inode->i_dev,
+ dentry->d_inode->i_count);
+ else
+ printk("show_dentry: %s/%s, d_count=%d%s \n",
+ dentry->d_parent->d_name.name,
+ dentry->d_name.name, dentry->d_count,
+ unhashed);
+ }
+}
+
+
/*
* By the time this is called, we already have created
* the directory cache entry for the new file, but it
* N.B. Several error exits in ext2_new_inode don't set err.
*/
ino = sbi->osi_ops->o_create(sbi->osi_conn_info.conn_id, 0, &err);
- if ( ino == -1 )
- return -1;
+ if ( err )
+ return err;
+ err = -EIO;
inode = iget(dir->i_sb, ino);
- if (!inode) {
+ if (!inode || !list_empty(&inode->i_dentry)) {
CDEBUG(D_INODE, "No inode, ino %ld\n", ino);
+ EXIT;
return err;
}
ext2_set_de_type(dir->i_sb, de, S_IFREG);
dir->i_version = ++event;
sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id,
- dir->i_ino, page, 0);
+ dir, page, 0);
UnlockPage(page);
#if 0
if (IS_SYNC(dir)) {
ext2_set_de_type(dir->i_sb, de, inode->i_mode);
mark_inode_dirty(inode);
sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id,
- dir->i_ino, page, 0);
+ dir, page, 0);
UnlockPage(page);
#if 0
strcpy (de->name, "..");
ext2_set_de_type(dir->i_sb, de, S_IFDIR);
- iops(dir)->o_brw(WRITE, sbi->osi_conn_info.conn_id, child->i_ino, child_page, 1);
+ iops(dir)->o_brw(WRITE, sbi->osi_conn_info.conn_id, child, child_page, 1);
UnlockPage(child_page);
page_cache_release(child_page);
dir->i_nlink++;
dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
mark_inode_dirty(dir);
- iops(dir)->o_brw(WRITE, sbi->osi_conn_info.conn_id, dir->i_ino, page, 1);
+ iops(dir)->o_brw(WRITE, sbi->osi_conn_info.conn_id, dir, page, 1);
UnlockPage(page);
page_cache_release(page);
d_instantiate(dentry, child);
sb = inode->i_sb;
if (inode->i_size < EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2) ||
- !(page = obdfs_getpage (inode, 0, 0, NOLOCK))) {
+ !(page = obdfs_getpage (inode, 0, 0, LOCKED))) {
ext2_warning (inode->i_sb, "empty_dir",
"bad directory (dir #%lu) - no data block",
inode->i_ino);
de = (struct ext2_dir_entry_2 *) ((char *) de1 + le16_to_cpu(de1->rec_len));
while (offset < inode->i_size ) {
if (!page || (void *) de >= (void *) (page_address(page) + PAGE_SIZE)) {
- if (page)
+ if (page) {
+ UnlockPage(page);
page_cache_release(page);
- page = obdfs_getpage(inode, offset, 0, NOLOCK);
+ }
+ page = obdfs_getpage(inode, offset, 0, LOCKED);
if (!page) {
#if 0
ext2_error (sb, "empty_dir",
}
if (!obdfs_check_dir_entry ("empty_dir", inode, de, page,
offset)) {
+ UnlockPage(page);
page_cache_release(page);
return 1;
}
if (le32_to_cpu(de->inode)) {
+ UnlockPage(page);
page_cache_release(page);
return 0;
}
offset += le16_to_cpu(de->rec_len);
de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
}
+ UnlockPage(page);
page_cache_release(page);
return 1;
}
dir->i_version = ++event;
if (retval)
goto end_rmdir;
- sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id,
- dir->i_ino, page, 0);
+ sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id, dir, page, 0);
UnlockPage(page);
#if 0
if (IS_SYNC(dir)) {
if (retval)
goto end_unlink;
dir->i_version = ++event;
- sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id,
- dir->i_ino, page, 0);
+ sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id, dir, page, 0);
UnlockPage(page);
#if 0
if (IS_SYNC(dir)) {
;
if (l >= sizeof (inode->u.ext2_i.i_data)) {
- ext2_debug ("l=%d, normal symlink\n", l);
+ CDEBUG(D_INODE, "l=%d, normal symlink\n", l);
name_page = obdfs_getpage(inode, 0, 1, LOCKED);
if (!name_page) {
} else {
link = (char *) inode->u.ext2_i.i_data;
- ext2_debug ("l=%d, fast symlink\n", l);
+ CDEBUG(D_INODE, "l=%d, fast symlink\n", l);
}
i = 0;
link[i] = 0;
if (name_page) {
sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id,
- inode->i_ino, name_page, 1);
+ inode, name_page, 1);
PDEBUG(name_page, "symlink");
UnlockPage(name_page);
page_cache_release(name_page);
ext2_set_de_type(dir->i_sb, de, S_IFLNK);
dir->i_version = ++event;
sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id,
- dir->i_ino, page, 1);
+ dir, page, 1);
UnlockPage(page);
#if 0
if (IS_SYNC(dir)) {
ext2_set_de_type(dir->i_sb, de, inode->i_mode);
dir->i_version = ++event;
sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id,
- dir->i_ino, page, 0);
+ dir, page, 0);
UnlockPage(page);
#if 0
if (dir_page) {
PARENT_INO(page_address(dir_page)) = le32_to_cpu(new_dir->i_ino);
sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id,
- old_inode->i_ino, dir_page, 0);
+ old_inode, dir_page, 0);
old_dir->i_nlink--;
mark_inode_dirty(old_dir);
if (new_inode) {
old_page = obdfs_getpage(old_dir, offset, 0, LOCKED);
CDEBUG(D_INODE, "old_page at %p\n", old_page);
sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id,
- old_dir->i_ino, old_page, 0);
+ old_dir, old_page, 0);
}
#if 0
if (IS_SYNC(old_dir)) {
}
#endif
sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id,
- new_dir->i_ino, new_page, 0);
+ new_dir, new_page, 0);
#if 0
if (IS_SYNC(new_dir)) {
ll_rw_block (WRITE, 1, &new_bh);
#include <../obd/linux/obd_sim.h>
#include <obdfs.h>
+int console_loglevel;
+
/* VFS super_block ops */
/* returns the page unlocked, but with a reference */
sbi = sb->u.generic_sbp;
PDEBUG(page, "READ");
rc = sbi->osi_ops->o_brw(READ, sbi->osi_conn_info.conn_id,
- file->f_dentry->d_inode->i_ino, page, 0);
+ file->f_dentry->d_inode, page, 0);
if (rc == PAGE_SIZE ) {
SetPageUptodate(page);
UnlockPage(page);
if ( !Page_Uptodate(page) ) {
status = sbi->osi_ops->o_brw(READ,
sbi->osi_conn_info.conn_id,
- file->f_dentry->d_inode->i_ino,
+ file->f_dentry->d_inode,
page, 1);
if (status == PAGE_SIZE ) {
SetPageUptodate(page);
status = -EFAULT;
if (bytes) {
+
lock_kernel();
status = obdfs_writepage(file, page);
unlock_kernel();
/* XXX flush stuff */
rc = sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id,
- file->f_dentry->d_inode->i_ino, page, 1);
+ file->f_dentry->d_inode, page, 1);
+
SetPageUptodate(page);
PDEBUG(page,"WRITEPAGE");
return rc;
}
+void report_inode(struct page * page) {
+ struct inode *inode = (struct inode *)0;
+ int offset = (int)&inode->i_data;
+ inode = (struct inode *)( (char *)page->mapping - offset);
+ if ( inode->i_sb->s_magic == 0x4711 )
+ printk("----> ino %ld , dev %d\n", inode->i_ino, inode->i_dev);
+}
+
/*
- page is returned unlocked, with the up to date flag set,
- and held, i.e. caller must do a page_put
+ return an up to date page:
+ - if locked is true then is returned locked
+ - if create is true the corresponding disk blocks are created
+ - page is held, i.e. caller must release the page
+
+ modeled on NFS code.
*/
struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create, int locked)
{
- unsigned long new_page;
+ struct page *page_cache;
struct page ** hash;
- struct page * page;
+ struct page * page;
struct obdfs_sb_info *sbi;
struct super_block *sb = inode->i_sb;
+ int rc;
ENTRY;
+ offset = offset & PAGE_CACHE_MASK;
sbi = sb->u.generic_sbp;
+ CDEBUG(D_INODE, "\n");
- page = find_lock_page(inode, offset);
- if (page && Page_Uptodate(page)) {
- PDEBUG(page,"GETPAGE");
+ page = NULL;
+ page_cache = page_cache_alloc();
+ if ( ! page_cache )
+ return NULL;
+ CDEBUG(D_INODE, "page_cache %p\n", page_cache);
+
+ hash = page_hash(&inode->i_data, offset);
+ repeat:
+ CDEBUG(D_INODE, "Finding page\n");
+ IDEBUG(inode);
+
+ page = __find_lock_page(&inode->i_data, offset, hash);
+ if ( page ) {
+ CDEBUG(D_INODE, "Page found freeing\n");
+ page_cache_free(page_cache);
+ } else {
+ page = page_cache;
+ if ( page->buffers ) {
+ PDEBUG(page, "GETPAGE: buffers bug\n");
+ UnlockPage(page);
+ return NULL;
+ }
+ if (add_to_page_cache_unique(page, &inode->i_data, offset, hash)) {
+ page_cache_release(page);
+ CDEBUG(D_INODE, "Someone raced: try again\n");
+ goto repeat;
+ }
+ }
+
+ PDEBUG(page, "GETPAGE: got page - before reading\n");
+ /* now check if the data in the page is up to date */
+ if ( Page_Uptodate(page)) {
if (!locked)
UnlockPage(page);
EXIT;
return page;
}
-
- if (page && !Page_Uptodate(page) ) {
- CDEBUG(D_INODE, "Page found but not up to date\n");
- }
- /* page_cache_alloc returns the VM address of page */
- new_page = page_cache_alloc();
- if (!new_page)
- return NULL;
-
- /* corresponding struct page in the mmap */
- hash = page_hash(inode, offset);
- page = page_cache_entry(new_page);
- if (!add_to_page_cache_unique(page, inode, offset, hash)) {
- CDEBUG(D_INODE, "Page not found. Reading it.\n");
- PDEBUG(page,"GETPAGE - before reading");
- sbi->osi_ops->o_brw(READ, sbi->osi_conn_info.conn_id,
- inode->i_ino, page, create);
- if ( !locked )
- UnlockPage(page);
- SetPageUptodate(page);
- PDEBUG(page,"GETPAGE - after reading");
- EXIT;
+ /* it's not: read it */
+ if (! page) {
+ printk("get_page_map says no dice ...\n");
+ return 0;
+ }
+
+
+
+ rc = sbi->osi_ops->o_brw(READ, sbi->osi_conn_info.conn_id,
+ inode, page, create);
+ if ( rc != PAGE_SIZE ) {
+ SetPageError(page);
+ UnlockPage(page);
return page;
}
- /*
- * We arrive here in the unlikely event that someone
- * raced with us and added our page to the cache first.
- */
- CDEBUG(D_INODE, "Page not found. Someone raced us.\n");
- PDEBUG(page,"GETPAGE");
+
+ if ( !locked )
+ UnlockPage(page);
+ SetPageUptodate(page);
+ PDEBUG(page,"GETPAGE - after reading");
EXIT;
return page;
}
-
struct file_operations obdfs_file_ops = {
NULL, /* lseek - default */
generic_file_read, /* read */
/* VFS super_block ops */
static struct super_block *obdfs_read_super(struct super_block *, void *, int);
-static void obdfs_read_inode(struct inode *);
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 *);
}
+
lock_super(sb);
sb->u.generic_sbp = sbi;
unlock_super(sb);
goto error;
}
+
- printk("obdfs_read_super: rootinode is %ld dev %d\n",
- root->i_ino, root->i_dev);
+ printk("obdfs_read_super: sbdev %d, rootinode is %ld dev %d, blocksize %ld, "
+ "blocksize bits %ld\n",
+ sb->s_dev, root->i_ino, root->i_dev, blocksize, blocksize_bits);
sb->s_root = d_alloc_root(root);
unlock_super(sb);
EXIT;
extern struct inode_operations obdfs_inode_ops;
/* all filling in of inodes postponed until lookup */
-static void obdfs_read_inode(struct inode *inode)
+void obdfs_read_inode(struct inode *inode)
{
int error;
struct obdfs_sb_info *sbi = inode->i_sb->u.generic_sbp;
error = sbi->osi_ops->o_getattr(sbi->osi_conn_info.conn_id,
inode->i_ino, inode);
if (error) {
- printk("obdfs_read_inode: ibd_getattr fails (%d)\n", error);
+ printk("obdfs_read_inode: obd_getattr fails (%d)\n", error);
return;
}
+ IDEBUG(inode);
inode->i_op = &obdfs_inode_ops;
return;
}
error = sbi->osi_ops->o_setattr(sbi->osi_conn_info.conn_id,
inode->i_ino, inode);
if (error) {
- printk("obdfs_write_inode: ibd_setattr fails (%d)\n", error);
+ printk("obdfs_write_inode: obd_setattr fails (%d)\n", error);
return;
}
--- /dev/null
+/*
+ * linux/fs/ext2/symlink.c
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ * from
+ *
+ * linux/fs/minix/symlink.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * ext2 symlink handling code
+ *
+ * Modified for OBDFS:
+ * Copyright (C) 1999 Seagate Technology Inc. (author: braam@stelias.com)
+ */
+
+#include <asm/uaccess.h>
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/ext2_fs.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/stat.h>
+
+static int obdfs_readlink (struct dentry *, char *, int);
+static struct dentry *obdfs_follow_link(struct dentry *, struct dentry *, unsigned int);
+
+static struct dentry * ext2_follow_link(struct dentry * dentry,
+ struct dentry *base,
+ unsigned int follow)
+{
+ struct inode *inode = dentry->d_inode;
+ struct page *page = NULL;
+ int error;
+ char * link;
+
+ link = (char *) inode->u.ext2_i.i_data;
+ if (inode->i_blocks) {
+ if (!(page = obdfs_getpage(inode, 0, 0, &error))) {
+ dput(base);
+ return ERR_PTR(-EIO);
+ }
+ link = bh->b_data;
+ }
+ UPDATE_ATIME(inode);
+ base = lookup_dentry(link, base, follow);
+ if (bh)
+ brelse(bh);
+ return base;
+}
+
+static int ext2_readlink (struct dentry * dentry, char * buffer, int buflen)
+{
+ struct inode *inode = dentry->d_inode;
+ struct buffer_head * bh = NULL;
+ char * link;
+ int i;
+
+ if (buflen > inode->i_sb->s_blocksize - 1)
+ buflen = inode->i_sb->s_blocksize - 1;
+
+ link = (char *) inode->u.ext2_i.i_data;
+ if (inode->i_blocks) {
+ int err;
+ bh = ext2_bread (inode, 0, 0, &err);
+ if (!bh) {
+ if(err < 0) /* indicate type of error */
+ return err;
+ return 0;
+ }
+ link = bh->b_data;
+ }
+
+ i = 0;
+ while (i < buflen && link[i])
+ i++;
+ if (copy_to_user(buffer, link, i))
+ i = -EFAULT;
+ if (bh)
+ brelse (bh);
+ return i;
+}
#define OBDFS_RESET 7
#define OBDFS_VARS_SLOT 2
+#if 0
static ctl_table obdfs_table[] = {
{OBDFS_DEBUG, "debug", &obdfs_debug_level, sizeof(int), 0644, NULL, &proc_dointvec},
{OBDFS_SYSCTL, "obdfs", NULL, 0, 0555, obdfs_table},
{0}
};
+#endif
void obdfs_sysctl_init (void)
{
+
#ifdef CONFIG_SYSCTL
if ( !obdfs_table_header )
obdfs_table_header = register_sysctl_table(jukebox_table, 0);