Whamcloud - gitweb
Over of the changes:
authorbraam <braam>
Mon, 1 Nov 1999 17:44:11 +0000 (17:44 +0000)
committerbraam <braam>
Mon, 1 Nov 1999 17:44:11 +0000 (17:44 +0000)
    Many bugfixes
    INOFS added
    SNAP added

   See ChangeLog for details

19 files changed:
lustre/.cvsignore [new file with mode: 0644]
lustre/include/linux/obd_class.h
lustre/include/linux/obd_rpc.h [new file with mode: 0644]
lustre/include/linux/obd_snap.h
lustre/include/linux/obd_support.h
lustre/include/linux/obdfs.h
lustre/obdclass/cleanup.sh [new file with mode: 0644]
lustre/obdclass/genops.c
lustre/obdclass/obdcontrol
lustre/obdclass/setup.sh
lustre/obdclass/sysctl.c
lustre/obdfs/Makefile
lustre/obdfs/dir.c
lustre/obdfs/file.c
lustre/obdfs/namei.c
lustre/obdfs/rw.c
lustre/obdfs/super.c
lustre/obdfs/symlink.c [new file with mode: 0644]
lustre/obdfs/sysctl.c

diff --git a/lustre/.cvsignore b/lustre/.cvsignore
new file mode 100644 (file)
index 0000000..15be996
--- /dev/null
@@ -0,0 +1,6 @@
+config.h
+config.out
+config.mk
+.depfiles
+.prereq.ok
+.ready
index 2489e70..3115054 100644 (file)
@@ -3,20 +3,21 @@
 
 #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];
@@ -42,6 +43,7 @@ struct obd_device {
                struct sim_obd sim;
                struct raid1_obd raid1;
                struct snap_obd snap;
+               struct rpc_obd rpc;
                /* struct fc_obd fc; */
        } u;
 };
@@ -62,7 +64,7 @@ struct obd_ops {
        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);
diff --git a/lustre/include/linux/obd_rpc.h b/lustre/include/linux/obd_rpc.h
new file mode 100644 (file)
index 0000000..43d7bc3
--- /dev/null
@@ -0,0 +1,84 @@
+#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
index b846fab..e2a0352 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _OBD_SIM
-#define _OBD_SIM
+#ifndef _OBD_SNAP
+#define _OBD_SNAP
 
 #define OBD_SNAP_MAGIC 0x47224722
 
@@ -21,7 +21,7 @@ struct snap_object_data {
        int od_magic;
        /* id of snaps of object; slot 0 has the current data */
        unsigned long od_ids[SNAP_MAX + 1]; 
-}
+};
 
 
 
index 57163c5..68f12ca 100644 (file)
@@ -1,3 +1,4 @@
+
 #ifndef _OBD_SUPPORT
 #define _OBD_SUPPORT
 #include <linux/malloc.h>
@@ -44,7 +45,7 @@ extern int obd_print_entry;
 
 #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 */
 
@@ -57,16 +58,25 @@ extern int obd_print_entry;
 
 #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__); }}
 
 
@@ -112,7 +122,7 @@ static inline void inode_to_iattr(struct inode *inode, struct iattr *tmp)
        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;
 }
@@ -126,7 +136,7 @@ static inline void inode_cpy(struct inode *dest, struct inode *src)
        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;
 
index 51f9762..2abcb8f 100644 (file)
 #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);
 
diff --git a/lustre/obdclass/cleanup.sh b/lustre/obdclass/cleanup.sh
new file mode 100644 (file)
index 0000000..70a01dc
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+umount /mnt/obd
+rmmod obdfs
+
+./obdcontrol -f << EOF
+cleanup
+quit
+EOF
+
+rmmod obdsim
+rmmod obdclass
+
index eb662b1..982fc35 100644 (file)
@@ -122,13 +122,13 @@ int gen_multi_setup(struct obd_device *obddev, int len, void *data)
 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 */
@@ -167,19 +167,19 @@ int gen_multi_attach(struct obd_device *obddev, int len, void *data)
 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 */
index 18d3360..07458c0 100755 (executable)
@@ -296,7 +296,7 @@ sub Setup {
 
 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";
@@ -380,9 +380,11 @@ sub Create {
        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";
            }
        }
index 6b5fbba..e88faee 100755 (executable)
@@ -10,4 +10,4 @@ attach sim_obd
 setup
 quit
 EOF
-mount -t obdfs /dev/loop0 /mnt/obd
+mount -t obdfs /dev/obd0 /mnt/obd
index 3716464..2b67744 100644 (file)
@@ -46,12 +46,13 @@ static ctl_table obd_table[] = {
        { 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
index 46188f1..f677548 100644 (file)
@@ -15,9 +15,13 @@ CPPFLAGS = $(PCDEBUG) -D__KERNEL__ -DMODULE -I../include \
           -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
index fef4332..fb171ad 100644 (file)
@@ -55,6 +55,7 @@ int obdfs_check_dir_entry (const char * function, struct inode * dir,
                          unsigned long offset)
 {
        const char * error_msg = NULL;
+       return 1;
 
        ENTRY;
        if ( !de ) {
@@ -106,7 +107,8 @@ int obdfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
        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",
@@ -182,6 +184,7 @@ revalidate:
                        filp->f_pos += le16_to_cpu(de->rec_len);
                }
                offset = 0;
+               UnlockPage(page);
                page_cache_release(page);
        }
        UPDATE_ATIME(inode);
index ec31cef..e3d629f 100644 (file)
@@ -60,6 +60,7 @@ ssize_t obdfs_file_write(struct file *file, const char *buf, size_t count, loff_
 
        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);
index 6d33286..316a17a 100644 (file)
@@ -78,6 +78,7 @@ struct page * obdfs_find_entry (struct inode * dir,
        unsigned long offset;
        struct page * page;
        ENTRY;
+       CDEBUG(D_INODE, "find entry for %*s\n", namelen, name);
 
        *res_dir = NULL;
        sb = dir->i_sb;
@@ -85,13 +86,20 @@ struct page * obdfs_find_entry (struct inode * dir,
        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; 
@@ -99,6 +107,9 @@ struct page * obdfs_find_entry (struct inode * dir,
                        /* 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)) {
@@ -113,17 +124,30 @@ struct page * obdfs_find_entry (struct inode * dir,
                        }
                        /* 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;
 }
@@ -138,7 +162,7 @@ struct dentry *obdfs_lookup(struct inode * dir, struct dentry *dentry)
        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");
@@ -148,6 +172,7 @@ struct dentry *obdfs_lookup(struct inode * dir, struct dentry *dentry)
        }
        if (page) {
                unsigned long ino = le32_to_cpu(de->inode);
+               UnlockPage(page);
                page_cache_release(page);
                inode = iget(dir->i_sb, ino);
 
@@ -173,7 +198,7 @@ struct dentry *obdfs_lookup(struct inode * dir, struct dentry *dentry)
  * 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,
@@ -189,17 +214,22 @@ static struct page *obdfs_add_entry (struct inode * dir,
        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;
        }
@@ -209,23 +239,29 @@ static struct page *obdfs_add_entry (struct inode * dir,
                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;
@@ -244,6 +280,7 @@ static struct page *obdfs_add_entry (struct inode * dir,
                if (!obdfs_check_dir_entry ("ext2_add_entry", dir, de, page,
                                           offset)) {
                        *err = -ENOENT;
+                       UnlockPage(page);
                        page_cache_release(page);
                        EXIT;
                        return NULL;
@@ -256,24 +293,29 @@ static struct page *obdfs_add_entry (struct inode * dir,
                                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
@@ -292,12 +334,14 @@ static struct page *obdfs_add_entry (struct inode * dir,
                        *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");
 
@@ -361,6 +405,42 @@ static inline void ext2_set_de_type(struct super_block *sb,
                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
@@ -385,11 +465,13 @@ int obdfs_create (struct inode * dir, struct dentry * dentry, int mode)
         * 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;
        }
 
@@ -408,7 +490,7 @@ int obdfs_create (struct inode * dir, struct dentry * dentry, int mode)
        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)) {
@@ -455,7 +537,7 @@ int obdfs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
        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
@@ -529,7 +611,7 @@ int obdfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
        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);
 
@@ -558,7 +640,7 @@ int obdfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
        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);
@@ -588,7 +670,7 @@ static int empty_dir (struct inode * inode)
 
        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);
@@ -608,9 +690,11 @@ static int empty_dir (struct inode * inode)
        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",
@@ -624,16 +708,19 @@ static int empty_dir (struct inode * inode)
                }
                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;
 }
@@ -669,8 +756,7 @@ int obdfs_rmdir (struct inode * dir, struct dentry *dentry)
        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)) {
@@ -732,8 +818,7 @@ int obdfs_unlink(struct inode * dir, struct dentry *dentry)
        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)) {
@@ -788,7 +873,7 @@ int obdfs_symlink (struct inode * dir, struct dentry *dentry, const char * symna
                ;
        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) {
@@ -801,7 +886,7 @@ int obdfs_symlink (struct inode * dir, struct dentry *dentry, const char * symna
        } 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;
@@ -810,7 +895,7 @@ int obdfs_symlink (struct inode * dir, struct dentry *dentry, const char * symna
        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);
@@ -825,7 +910,7 @@ int obdfs_symlink (struct inode * dir, struct dentry *dentry, const char * symna
        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)) {
@@ -871,7 +956,7 @@ int obdfs_link (struct dentry * old_dentry,
        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
@@ -992,7 +1077,7 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry,
        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) {
@@ -1012,7 +1097,7 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry,
                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)) {
@@ -1021,7 +1106,7 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry,
        }
 #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);
index 4016b49..bceef44 100644 (file)
@@ -32,6 +32,8 @@
 #include <../obd/linux/obd_sim.h>
 #include <obdfs.h>
 
+int console_loglevel;
+
 /* VFS super_block ops */
 
 /* returns the page unlocked, but with a reference */
@@ -47,7 +49,7 @@ int obdfs_readpage(struct file *file, struct page *page)
        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);
@@ -77,7 +79,7 @@ int obdfs_write_one_page(struct file *file, struct page *page, unsigned long off
        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);
@@ -89,6 +91,7 @@ int obdfs_write_one_page(struct file *file, struct page *page, unsigned long off
        status = -EFAULT;
 
        if (bytes) {
+
                lock_kernel();
                status = obdfs_writepage(file, page);
                unlock_kernel();
@@ -114,74 +117,108 @@ int obdfs_writepage(struct file *file, struct page *page)
        /* 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 */
index eddd0c8..f007e91 100644 (file)
@@ -35,7 +35,6 @@
 
 /* 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 *);
@@ -130,6 +129,7 @@ static struct super_block * obdfs_read_super(struct super_block *sb,
        }
        
 
+
         lock_super(sb);
         sb->u.generic_sbp = sbi;
        
@@ -147,9 +147,11 @@ static struct super_block * obdfs_read_super(struct super_block *sb,
            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;  
@@ -194,7 +196,7 @@ static void obdfs_put_super(struct super_block *sb)
 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;
@@ -203,10 +205,11 @@ static void obdfs_read_inode(struct inode *inode)
        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;
 }
@@ -220,7 +223,7 @@ static void obdfs_write_inode(struct inode *inode)
        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;
        }
 
diff --git a/lustre/obdfs/symlink.c b/lustre/obdfs/symlink.c
new file mode 100644 (file)
index 0000000..53bb167
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ *  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;
+}
index e5c263a..6b1752d 100644 (file)
@@ -29,6 +29,7 @@ int obdfs_print_entry = 1;
 #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},
@@ -40,9 +41,11 @@ static ctl_table jukebox_table[] = {
        {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);