From: braam Date: Mon, 1 Nov 1999 17:44:11 +0000 (+0000) Subject: Over of the changes: X-Git-Tag: v1_7_100~6183 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=8bb299c93313daad5d14e4b08b0a672eda144214 Over of the changes: Many bugfixes INOFS added SNAP added See ChangeLog for details --- diff --git a/lustre/.cvsignore b/lustre/.cvsignore new file mode 100644 index 0000000..15be996 --- /dev/null +++ b/lustre/.cvsignore @@ -0,0 +1,6 @@ +config.h +config.out +config.mk +.depfiles +.prereq.ok +.ready diff --git a/lustre/include/linux/obd_class.h b/lustre/include/linux/obd_class.h index 2489e70..3115054 100644 --- a/lustre/include/linux/obd_class.h +++ b/lustre/include/linux/obd_class.h @@ -3,20 +3,21 @@ #include #include - +#include #include #include #include /* #include */ #include +#include #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 index 0000000..43d7bc3 --- /dev/null +++ b/lustre/include/linux/obd_rpc.h @@ -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 diff --git a/lustre/include/linux/obd_snap.h b/lustre/include/linux/obd_snap.h index b846fab..e2a0352 100644 --- a/lustre/include/linux/obd_snap.h +++ b/lustre/include/linux/obd_snap.h @@ -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]; -} +}; diff --git a/lustre/include/linux/obd_support.h b/lustre/include/linux/obd_support.h index 57163c5..68f12ca 100644 --- a/lustre/include/linux/obd_support.h +++ b/lustre/include/linux/obd_support.h @@ -1,3 +1,4 @@ + #ifndef _OBD_SUPPORT #define _OBD_SUPPORT #include @@ -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; diff --git a/lustre/include/linux/obdfs.h b/lustre/include/linux/obdfs.h index 51f9762..2abcb8f 100644 --- a/lustre/include/linux/obdfs.h +++ b/lustre/include/linux/obdfs.h @@ -13,6 +13,10 @@ #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 index 0000000..70a01dc --- /dev/null +++ b/lustre/obdclass/cleanup.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +umount /mnt/obd +rmmod obdfs + +./obdcontrol -f << EOF +cleanup +quit +EOF + +rmmod obdsim +rmmod obdclass + diff --git a/lustre/obdclass/genops.c b/lustre/obdclass/genops.c index eb662b1..982fc35 100644 --- a/lustre/obdclass/genops.c +++ b/lustre/obdclass/genops.c @@ -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 */ diff --git a/lustre/obdclass/obdcontrol b/lustre/obdclass/obdcontrol index 18d3360..07458c0 100755 --- a/lustre/obdclass/obdcontrol +++ b/lustre/obdclass/obdcontrol @@ -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"; } } diff --git a/lustre/obdclass/setup.sh b/lustre/obdclass/setup.sh index 6b5fbba..e88faee 100755 --- a/lustre/obdclass/setup.sh +++ b/lustre/obdclass/setup.sh @@ -10,4 +10,4 @@ attach sim_obd setup quit EOF -mount -t obdfs /dev/loop0 /mnt/obd +mount -t obdfs /dev/obd0 /mnt/obd diff --git a/lustre/obdclass/sysctl.c b/lustre/obdclass/sysctl.c index 3716464..2b67744 100644 --- a/lustre/obdclass/sysctl.c +++ b/lustre/obdclass/sysctl.c @@ -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 diff --git a/lustre/obdfs/Makefile b/lustre/obdfs/Makefile index 46188f1..f677548 100644 --- a/lustre/obdfs/Makefile +++ b/lustre/obdfs/Makefile @@ -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 diff --git a/lustre/obdfs/dir.c b/lustre/obdfs/dir.c index fef4332..fb171ad 100644 --- a/lustre/obdfs/dir.c +++ b/lustre/obdfs/dir.c @@ -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); diff --git a/lustre/obdfs/file.c b/lustre/obdfs/file.c index ec31cef..e3d629f 100644 --- a/lustre/obdfs/file.c +++ b/lustre/obdfs/file.c @@ -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); diff --git a/lustre/obdfs/namei.c b/lustre/obdfs/namei.c index 6d33286..316a17a 100644 --- a/lustre/obdfs/namei.c +++ b/lustre/obdfs/namei.c @@ -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); diff --git a/lustre/obdfs/rw.c b/lustre/obdfs/rw.c index 4016b49..bceef44e 100644 --- a/lustre/obdfs/rw.c +++ b/lustre/obdfs/rw.c @@ -32,6 +32,8 @@ #include <../obd/linux/obd_sim.h> #include +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 */ diff --git a/lustre/obdfs/super.c b/lustre/obdfs/super.c index eddd0c8..f007e91 100644 --- a/lustre/obdfs/super.c +++ b/lustre/obdfs/super.c @@ -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 index 0000000..53bb167 --- /dev/null +++ b/lustre/obdfs/symlink.c @@ -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 + +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/lustre/obdfs/sysctl.c b/lustre/obdfs/sysctl.c index e5c263a..6b1752d 100644 --- a/lustre/obdfs/sysctl.c +++ b/lustre/obdfs/sysctl.c @@ -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);