From 3146d280a803ae5f9749bab8cde36105de43fcb9 Mon Sep 17 00:00:00 2001 From: braam Date: Thu, 21 Oct 1999 18:39:47 +0000 Subject: [PATCH] New files: for raid1 for snap shots OLVM a technical description of the logical volume management genops generic operations useful to many obd clients Fixes: numerous fixes to the file system several fixes to OBD and obdcontrol Current state: does not compile --- lustre/include/linux/obd.h | 19 ++++ lustre/include/linux/obd_class.h | 62 ++++++++--- lustre/include/linux/obd_raid1.h | 98 +++++++++++++++++ lustre/include/linux/obd_sim.h | 3 - lustre/include/linux/obd_snap.h | 28 +++++ lustre/include/linux/obd_support.h | 15 ++- lustre/include/linux/obdfs.h | 4 + lustre/obdclass/class_obd.c | 60 +++++++---- lustre/obdclass/genops.c | 209 +++++++++++++++++++++++++++++++++++++ lustre/obdclass/obdcontrol | 54 +++++++--- lustre/obdclass/setup.sh | 13 +++ lustre/obdfs/dir.c | 24 +++-- lustre/obdfs/file.c | 3 +- lustre/obdfs/namei.c | 130 ++++++++++++++++------- lustre/obdfs/rw.c | 12 ++- lustre/obdfs/super.c | 9 +- lustre/patches/patch-2.3.21 | 60 +++++++++++ 17 files changed, 686 insertions(+), 117 deletions(-) create mode 100644 lustre/include/linux/obd.h create mode 100644 lustre/include/linux/obd_raid1.h create mode 100644 lustre/include/linux/obd_snap.h create mode 100644 lustre/obdclass/genops.c create mode 100755 lustre/obdclass/setup.sh create mode 100644 lustre/patches/patch-2.3.21 diff --git a/lustre/include/linux/obd.h b/lustre/include/linux/obd.h new file mode 100644 index 0000000..03add50 --- /dev/null +++ b/lustre/include/linux/obd.h @@ -0,0 +1,19 @@ +#ifndef __OBD_H +#define __OBD_H + + +struct obd_conn_info { + unsigned int conn_id; /* handle */ +}; + +struct obd_type { + struct list_head typ_chain; + struct obd_ops *typ_ops; + char *typ_name; + int typ_refcnt; +}; + + + + +#endif diff --git a/lustre/include/linux/obd_class.h b/lustre/include/linux/obd_class.h index 200e45b..2489e70 100644 --- a/lustre/include/linux/obd_class.h +++ b/lustre/include/linux/obd_class.h @@ -1,27 +1,27 @@ -#ifndef __LINUX_SIM_OBD_H -#define __LINUX_SIM_OBD_H +#ifndef __LINUX_CLASS_OBD_H +#define __LINUX_CLASS_OBD_H #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 struct inode obdattr; extern struct obd_device obd_dev[MAX_OBD_DEVICES]; -struct obd_conn_info { - unsigned int conn_id; /* handle */ -}; -struct obd_type { - struct list_head typ_chain; - struct obd_ops *typ_ops; - char *typ_name; - int typ_refcnt; -}; #define OBD_ATTACHED 0x1 #define OBD_SET_UP 0x2 @@ -32,8 +32,16 @@ struct obd_device { int obd_minor; int obd_flags; int obd_refcnt; + int obd_multi_count; + struct obd_device *obd_multi_dev[MAX_MULTI]; + struct obd_conn_info obd_multi_conns[MAX_MULTI]; + unsigned int obd_gen_last_id; + unsigned long obd_gen_prealloc_quota; + struct list_head obd_gen_clients; union { struct sim_obd sim; + struct raid1_obd raid1; + struct snap_obd snap; /* struct fc_obd fc; */ } u; }; @@ -49,18 +57,20 @@ struct obd_ops { int (*o_setattr)(unsigned int conn_id, unsigned long id, struct inode *iattr); int (*o_getattr)(unsigned int conn_id, unsigned long id, struct inode *iattr); int (*o_statfs)(unsigned int conn_id, struct statfs *statfs); - int (*o_create)(struct obd_device *, int prealloc_ino, int *er); + int (*o_create)(int conn_id, int prealloc_ino, int *er); int (*o_destroy)(unsigned int conn_id, unsigned long ino); 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); long (*o_preallocate)(unsigned int conn_id, int req, long inodes[32], int *err); - void (*o_cleanup_device)(int dev); + int (*o_cleanup_device)(struct obd_device *); int (*o_get_info)(unsigned int conn_id, int keylen, void *key, int *vallen, void **val); int (*o_set_info)(unsigned int conn_id, int keylen, void *key, int vallen, void *val); }; +#define OBP(dev,op) dev->obd_type->typ_ops->o_ ## op + int obd_register_type(struct obd_ops *ops, char *nm); int obd_unregister_type(char *nm); @@ -77,6 +87,19 @@ struct obd_prealloc_inode { unsigned long inode; }; +/* generic operations shared by various OBD types */ +int gen_connect (struct obd_device *obddev, + struct obd_conn_info * conninfo); +int gen_disconnect(unsigned int conn_id); +int gen_multi_setup(struct obd_device *obddev, int len, void *data); +int gen_multi_cleanup(struct obd_device *obddev); +int gen_multi_attach(struct obd_device *obddev, int len, void *data); +struct obd_client *gen_client(int cli_id); +int gen_multi_cleanup_device(struct obd_device *obddev); +int gen_cleanup(struct obd_device *obddev); + + + /* * ioctl commands */ @@ -94,10 +117,15 @@ struct oic_prealloc_s { * of succesfully preallocated inodes */ long inodes[32]; /* actual inode numbers */ }; -struct oic_attr_s { + +struct oic_create_s { unsigned int conn_id; - unsigned long inode; + unsigned long prealloc; +}; +struct oic_attr_s { + unsigned int conn_id; + unsigned long ino; struct iattr iattr; }; struct oic_rw_s { @@ -115,7 +143,7 @@ struct oic_partition { #define OBD_IOC_CREATE _IOR ('f', 3, long) #define OBD_IOC_SETUP_OBDDEV _IOW ('f', 4, long) -#define OBD_IOC_CLEANUP_OBDDEV _IO ('f', 5 ) +#define OBD_IOC_CLEANUP _IO ('f', 5 ) #define OBD_IOC_DESTROY _IOW ('f', 6, long) #define OBD_IOC_PREALLOCATE _IOWR('f', 7, long) #define OBD_IOC_DEC_USE_COUNT _IO ('f', 8 ) @@ -140,4 +168,4 @@ extern void obd_sysctl_init (void); extern void obd_sysctl_clean (void); -#endif /* __LINUX_SIM_OBD_H */ +#endif /* __LINUX_CLASS_OBD_H */ diff --git a/lustre/include/linux/obd_raid1.h b/lustre/include/linux/obd_raid1.h new file mode 100644 index 0000000..cebe311 --- /dev/null +++ b/lustre/include/linux/obd_raid1.h @@ -0,0 +1,98 @@ +#ifndef _OBD_RAID1 +#define _OBD_RAID1 + +#include + +#define MAX_RAID1 16 + + +struct raid1_obd { + unsigned int raid1_count; /* how many replicas */ + /* devices to replicate on */ + struct obd_device *raid1_devlist[MAX_RAID1]; + /* connections we make */ + struct obd_conn_info raid1_connections[MAX_RAID1]; + struct list_head raid1_clients; /* clients we have */ +}; + + +/* development definitions */ +extern struct obdfs_sb_info *obd_sbi; +extern struct file_operations *obd_fso; + +/* obd_raid1.c */ +extern struct obd_ops raid1_obd_ops; +inline long ext2_block_map (struct inode * inode, long block); + +/* balloc.c */ +int ext2_new_block (const struct inode * inode, unsigned long goal, + u32 * prealloc_count, u32 * prealloc_block, int * err); +void ext2_free_blocks (const struct inode * inode, unsigned long block, + unsigned long count); +unsigned long ext2_count_free_blocks (struct super_block * sb); +int ext2_group_sparse(int group); +struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb, + unsigned int block_group, + struct buffer_head ** bh); + +/* bitmap.c */ +unsigned long ext2_count_free(struct buffer_head * map, unsigned int numchars); + +/* fsync.c */ +extern int obd_sync_file(struct file * file, struct dentry *dentry); + +/* ialloc.c */ +extern void ext2_free_inode (struct inode * inode); +extern struct inode * ext2_new_inode (const struct inode * dir, int mode, + int * err); +extern unsigned long ext2_count_free_inodes (struct super_block * sb); +extern void ext2_check_inodes_bitmap (struct super_block * sb); +extern int load_inode_bitmap (struct super_block * sb, + unsigned int block_group); + +/* inode.c */ +void obd_read_inode (struct inode * inode); +void obd_write_inode (struct inode * inode); +void obd_put_inode (struct inode * inode); +void obd_delete_inode (struct inode * inode); +void obd_discard_prealloc_blocks (struct inode * inode); +int obd_sync_inode (struct inode *inode); +struct buffer_head * obd_bread (struct inode * inode, int block, + int create, int *err); +struct buffer_head * obd_getblk (struct inode * inode, long block, + int create, int * err); + + +/* super.c */ +#define ext2_warning obd_warning +#undef ext2_error +#define ext2_error obd_warning +#define ext2_panic obd_warning +#ifdef EXT2FS_DEBUG +# undef ext2_debug +# define ext2_debug(format, a...) CDEBUG(D_EXT2, format, ## a) +#endif + +#define obd_error obd_warning +#define obd_panic obd_warning +#define obd_warning(sb, func, format, a...) CDEBUG(D_WARNING, format, ## a) + +int obd_remount (struct super_block * sb, int * flags, char * data); +struct super_block * ext2_read_super (struct super_block * sb, void * data, + int silent); + +/* truncate.c */ +void obd_truncate (struct inode * inode); + +/* operations */ +/* dir.c */ +extern struct inode_operations ext2_dir_inode_operations; + +/* file.c */ +extern struct file_operations ext2_file_operations; +extern struct inode_operations ext2_file_inode_operations; + +/* super.c */ +extern struct super_operations ext2_sops; + +#endif diff --git a/lustre/include/linux/obd_sim.h b/lustre/include/linux/obd_sim.h index 6b56399..b973e0b 100644 --- a/lustre/include/linux/obd_sim.h +++ b/lustre/include/linux/obd_sim.h @@ -3,9 +3,6 @@ struct sim_obd { struct super_block * sim_sb; - unsigned int sim_last_id; - unsigned long sim_prealloc_quota; - struct list_head sim_clients; }; diff --git a/lustre/include/linux/obd_snap.h b/lustre/include/linux/obd_snap.h new file mode 100644 index 0000000..b846fab --- /dev/null +++ b/lustre/include/linux/obd_snap.h @@ -0,0 +1,28 @@ +#ifndef _OBD_SIM +#define _OBD_SIM + +#define OBD_SNAP_MAGIC 0x47224722 + +#define SNAP_MAX 8 /* must fit in "u" area of struct inode */ +struct snap_obd_data { + int snap_dev; /* which device contains the data */ + unsigned int snap_no; /* which snapshot are we accessing */ + unsigned int snap_count; /* how many snapshots exist */ + time_t snap_times[SNAP_MAX]; +}; + +struct snap_obd { + unsigned int snap_no; /* which snapshot are we accessing */ + unsigned int snap_count; /* how many snapshots exist */ + time_t snap_times[SNAP_MAX]; +}; + +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]; +} + + + +#endif diff --git a/lustre/include/linux/obd_support.h b/lustre/include/linux/obd_support.h index 4e2c6e5..57163c5 100644 --- a/lustre/include/linux/obd_support.h +++ b/lustre/include/linux/obd_support.h @@ -5,6 +5,10 @@ #define SIM_OBD_DEBUG + +#define MIN(a,b) (((a)<(b)) ? (a): (b)) +#define MAX(a,b) (((a)>(b)) ? (a): (b)) + /* * Debug code */ @@ -53,7 +57,7 @@ extern int obd_print_entry; #define CMD(cmd) (( cmd == READ ) ? "read" : "write") -#define PDEBUG(page,cmd) {\ +#define PDEBUG(page,cmd) {if (page){\ char *uptodate = (Page_Uptodate(page)) ? "yes" : "no";\ char *locked = (PageLocked(page)) ? "yes" : "no";\ int count = page->count.counter;\ @@ -61,9 +65,9 @@ extern int obd_print_entry; long offset = page->offset / PAGE_SIZE;\ \ CDEBUG(D_IOCTL, " ** %s, cmd: %s, ino: %ld, off %ld, uptodate: %s, "\ - "locked: %s, cnt %d ** \n", __FUNCTION__,\ - cmd, ino, offset, uptodate, locked, count);\ - } + "locked: %s, cnt %d page %p ** \n", __FUNCTION__,\ + cmd, ino, offset, uptodate, locked, count, page);\ + } else { CDEBUG(D_IOCTL, "** %s, no page\n", __FUNCTION__); }} #define OBD_ALLOC(ptr, cast, size) \ @@ -126,7 +130,8 @@ static inline void inode_cpy(struct inode *dest, struct inode *src) /* allocation of space */ dest->i_blocks = src->i_blocks; - memcpy(&dest->u, &src->u, sizeof(src->u)); + if ( !dest->i_blocks) + memcpy(&dest->u, &src->u, sizeof(src->u)); } diff --git a/lustre/include/linux/obdfs.h b/lustre/include/linux/obdfs.h index 109c706..51f9762 100644 --- a/lustre/include/linux/obdfs.h +++ b/lustre/include/linux/obdfs.h @@ -34,6 +34,10 @@ int obdfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dent int obdfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry); /* dir.c */ int obdfs_readdir(struct file * filp, void * dirent, filldir_t filldir); +int obdfs_check_dir_entry (const char * function, struct inode * dir, + struct ext2_dir_entry_2 * de, + struct page * page, + unsigned long offset); struct obdfs_sb_info { struct obd_conn_info osi_conn_info; diff --git a/lustre/obdclass/class_obd.c b/lustre/obdclass/class_obd.c index bb76677..6973101 100644 --- a/lustre/obdclass/class_obd.c +++ b/lustre/obdclass/class_obd.c @@ -199,8 +199,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, CDEBUG(D_IOCTL, "Attach %d, type %s\n", dev, obddev->obd_type->typ_name); - if (!obddev->obd_type->typ_ops || - !obddev->obd_type->typ_ops->o_attach ) { + if (!obddev->obd_type->typ_ops || !OBP(obddev,attach)) { obddev->obd_flags |= OBD_ATTACHED; type->typ_refcnt++; MOD_INC_USE_COUNT; @@ -208,8 +207,8 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, } /* do the attach */ - err = obddev->obd_type->typ_ops->o_attach - (obddev, input.att_datalen, &input.att_data); + err = OBP(obddev,attach)(obddev, + input.att_datalen, &input.att_data); OBD_FREE(input.att_data, input.att_datalen); if ( err ) { @@ -322,8 +321,10 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, CDEBUG(D_IOCTL, "Setup %d, type %s\n", dev, obddev->obd_type->typ_name); if ( !obddev->obd_type->typ_ops || - !obddev->obd_type->typ_ops->o_setup ) - return -EOPNOTSUPP; + !obddev->obd_type->typ_ops->o_setup ) { + obddev->obd_flags |= OBD_SET_UP; + return 0; + } err = obddev->obd_type->typ_ops->o_setup (obddev, input.setup_datalen, input.setup_data); @@ -334,7 +335,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, obddev->obd_flags |= OBD_SET_UP; return err; } - case OBD_IOC_CLEANUP_OBDDEV: { + case OBD_IOC_CLEANUP: { int rc; /* has this minor been registered? */ @@ -348,7 +349,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, goto cleanup_out; /* cleanup has no argument */ - rc = obddev->obd_type->typ_ops->o_cleanup(obddev); + rc = OBP(obddev, cleanup)(obddev); if ( rc ) return rc; @@ -383,10 +384,10 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, get_user(cli_id, (int *) arg); - obddev->obd_type->typ_ops->o_disconnect(cli_id); + OBP(obddev, disconnect)(cli_id); return 0; - case OBD_IOC_SYNC: + case OBD_IOC_SYNC: { /* sync doesn't need a connection ID, because it knows * what device it was called on, and can thus get the * superblock that it needs. */ @@ -405,12 +406,17 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, } return put_user(err, (int *) arg); - case OBD_IOC_CREATE: - /* similarly, create doesn't need a connection ID for - * the same reasons. */ + } + case OBD_IOC_CREATE: { + int err; + struct oic_create_s foo; + + if ( copy_from_user(&foo, (const void *)arg, sizeof(foo)) ) + return -EFAULT; /* has this minor been registered? */ - if (!obddev->obd_type) + if ( !(obddev->obd_flags & OBD_ATTACHED) || + !(obddev->obd_flags & OBD_SET_UP)) return -ENODEV; @@ -419,7 +425,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, return put_user(-EINVAL, (int *) arg); } - i_ino = obddev->obd_type->typ_ops->o_create(obddev, 0, &err); + i_ino = OBP(obddev, create)(foo.conn_id, foo.prealloc, &err); if (err) { CDEBUG(D_IOCTL, "create: obd_inode_new failure\n"); /* 0 is the only error value */ @@ -427,6 +433,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, } return put_user(i_ino, (int *) arg); + } case OBD_IOC_DESTROY: { struct destroy_s { @@ -449,18 +456,15 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, case OBD_IOC_SETATTR: { int err; - struct tmp { - unsigned int conn_id; - unsigned long ino; - struct iattr iattr; - } foo; + struct oic_attr_s foo; struct inode holder; + /* has this minor been registered? */ if (!obddev->obd_type) return -ENODEV; - err= copy_from_user(&foo, (int *)arg, sizeof(struct tmp)); + err= copy_from_user(&foo, (int *)arg, sizeof(foo)); if (err) return err; @@ -715,7 +719,7 @@ int init_obd(void) for (i = 0; i < MAX_OBD_DEVICES; i++) { memset(&(obd_dev[i]), 0, sizeof(obd_dev[i])); - INIT_LIST_HEAD(&obd_dev[i].u.sim.sim_clients); + INIT_LIST_HEAD(&obd_dev[i].obd_gen_clients); } obd_sysctl_init(); @@ -730,6 +734,16 @@ EXPORT_SYMBOL(obd_print_entry); EXPORT_SYMBOL(obd_debug_level); EXPORT_SYMBOL(obd_dev); +EXPORT_SYMBOL(gen_connect); +EXPORT_SYMBOL(gen_client); +EXPORT_SYMBOL(gen_cleanup); +EXPORT_SYMBOL(gen_disconnect); + +EXPORT_SYMBOL(gen_multi_attach); +EXPORT_SYMBOL(gen_multi_setup); +EXPORT_SYMBOL(gen_multi_cleanup); + + #ifdef MODULE int init_module(void) { @@ -746,7 +760,7 @@ void cleanup_module(void) struct obd_device *obddev = &obd_dev[i]; if ( obddev->obd_type && obddev->obd_type->typ_ops->o_cleanup_device ) - return obddev->obd_type->typ_ops->o_cleanup_device(i); + OBP(obddev, cleanup_device)(obddev); } obd_sysctl_clean(); diff --git a/lustre/obdclass/genops.c b/lustre/obdclass/genops.c new file mode 100644 index 0000000..eb662b1 --- /dev/null +++ b/lustre/obdclass/genops.c @@ -0,0 +1,209 @@ +/* + * linux/fs/sim_obd/sim_obd.c + * + * These are the only exported functions; they provide the simulated object- + * oriented disk. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +extern struct obd_device obd_dev[MAX_OBD_DEVICES]; + +/* map connection to client */ +struct obd_client *gen_client(int cli_id) +{ + struct obd_device * obddev; + struct list_head * lh, * next; + struct obd_client * cli; + int a; + + for (a = 0; a < MAX_OBD_DEVICES; a++) { + obddev = &obd_dev[a]; + + lh = next = &obddev->obd_gen_clients; + while ((lh = lh->next) != &obddev->obd_gen_clients) { + cli = list_entry(lh, struct obd_client, cli_chain); + + if (cli->cli_id == cli_id) + return cli; + } + } + + return NULL; +} /* obd_client */ + + + +/* a connection defines a context in which preallocation can be managed. */ +int gen_connect (struct obd_device *obddev, + struct obd_conn_info * conninfo) +{ + struct obd_client * cli; + + OBD_ALLOC(cli, struct obd_client *, sizeof(struct obd_client)); + if ( !cli ) { + printk("obd_connect (minor %d): no memory!\n", + obddev->obd_minor); + return -ENOMEM; + } + + INIT_LIST_HEAD(&cli->cli_prealloc_inodes); + /* this should probably spinlocked? */ + cli->cli_id = ++obddev->obd_gen_last_id; + cli->cli_prealloc_quota = 0; + cli->cli_obd = obddev; + list_add(&(cli->cli_chain), obddev->obd_gen_clients.prev); + + CDEBUG(D_IOCTL, "connect: new ID %u\n", cli->cli_id); + conninfo->conn_id = cli->cli_id; + return 0; +} /* gen_obd_connect */ + + +int gen_disconnect(unsigned int conn_id) +{ + struct obd_client * cli; + + ENTRY; + + if (!(cli = gen_client(conn_id))) { + CDEBUG(D_IOCTL, "disconnect: attempting to free " + "nonexistent client %u\n", conn_id); + return -EINVAL; + } + + list_del(&(cli->cli_chain)); + OBD_FREE(cli, sizeof(struct obd_client)); + + CDEBUG(D_IOCTL, "disconnect: ID %u\n", conn_id); + + EXIT; + return 0; +} /* gen_obd_disconnect */ + + +/* + * raid1 defines a number of connections to child devices, + * used to make calls to these devices. + * data holds nothing + */ +int gen_multi_setup(struct obd_device *obddev, int len, void *data) +{ + int i; + struct obd_device *rdev = obddev->obd_multi_dev[0]; + + for (i = 0 ; i < obddev->obd_multi_count ; i++ ) { + int rc; + struct obd_device *child = rdev + i; + rc = OBP(child, connect)(child, &rdev->obd_multi_conns[i]); + + if ( rc != 0 ) { + /* XXX disconnect others */ + return -EINVAL; + } + } + return 0; +} + +int gen_multi_cleanup(struct obd_device * obddev) +{ + int i; + struct obd_device *rdev = obddev->obd_multi_dev[0]; + + for (i = 0 ; i < obddev->obd_multi_count ; i++ ) { + int rc; + struct obd_device *child = rdev + i; + rc = OBP(child, cleanup)(child); + *child = -1; + + if ( rc != 0 ) { + /* XXX disconnect others */ + return -EINVAL; + } + } + gen_cleanup(obddev); + return 0; +} /* sim_cleanup_obddev */ + + +int gen_multi_attach(struct obd_device *obddev, int len, void *data) +{ + int i; + int count; + struct obd_device *rdev = obddev->obd_multi_dev[0]; + + count = len/sizeof(int); + obddev->obd_multi_count = count; + for (i=0 ; iobd_type->typ_name); + } + return 0; +} + + + +/* + * remove all connections to this device + * close all connections to lower devices + * needed for forced unloads of OBD client drivers + */ +int gen_multi_cleanup_device(struct obd_device *obddev) +{ + int i; + struct obd_device *rdev; + + rdev = obddev->obd_multi_dev[0]; + for (i = 0 ; i < obddev->obd_multi_count ; i++ ) { + int rc; + 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; + } + return 0; +} /* gen_multi_cleanup_device */ + + +/* + * forced cleanup of the device: + * - remove connections from the device + * - cleanup the device afterwards + */ +int gen_cleanup(struct obd_device * obddev) +{ + struct list_head * lh, * tmp; + struct obd_client * cli; + + ENTRY; + + lh = tmp = &obddev->obd_gen_clients; + while ((tmp = tmp->next) != lh) { + cli = list_entry(tmp, struct obd_client, cli_chain); + CDEBUG(D_IOCTL, "Disconnecting obd_connection %d, at %p\n", + cli->cli_id, cli); + OBP(obddev, disconnect)(cli->cli_id); + } + + return OBP(obddev, cleanup_device)(obddev); +} /* sim_cleanup_device */ diff --git a/lustre/obdclass/obdcontrol b/lustre/obdclass/obdcontrol index 1928220..18d3360 100755 --- a/lustre/obdclass/obdcontrol +++ b/lustre/obdclass/obdcontrol @@ -23,8 +23,8 @@ eval 'sub OBD_IOC_CREATE () { &_IOC(2, ord(\'f\'), 3, 4);}' unless defined(&OBD_IOC_CREATE); eval 'sub OBD_IOC_SETUP_OBDDEV () { &_IOC(1, ord(\'f\'), 4, 4);}' unless defined(&OBD_IOC_SETUP_OBDDEV); -eval 'sub OBD_IOC_CLEANUP_OBDDEV () { &_IOC(0, ord(\'f\'), 5, 0);}' unless - defined(&OBD_IOC_CLEANUP_OBDDEV); +eval 'sub OBD_IOC_CLEANUP () { &_IOC(0, ord(\'f\'), 5, 0);}' unless + defined(&OBD_IOC_CLEANUP); eval 'sub OBD_IOC_DESTROY () { &_IOC(1, ord(\'f\'), 6, 4);}' unless defined(&OBD_IOC_DESTROY); eval 'sub OBD_IOC_PREALLOCATE () { &_IOC(3, ord(\'f\'), 7, 4);}' unless @@ -71,22 +71,19 @@ use Carp; use Term::ReadLine; use IO::Handle; -my ($device, $filesystem); + +my ($device, $filesystem, $file); # startup options (I'll replace these when I have some to replace with) -GetOptions("device=s" => \$device, "fs=s" => $filesystem) || die "Getoptions"; +GetOptions("f!" => \$file, "device=s" => \$device, "fs=s" => $filesystem) || die "Getoptions"; # genuine new simulated OBD device -$device = "/dev/obd" unless $device; +$device = "/dev/obd0" unless $device; # object store in the ext2 formatted block device $filesystem = "/dev/loop0" unless $filesystem; -# get a console for the app -my $term = new Term::ReadLine 'obdcontrol '; -my $attribs = $term->Attribs; -$term->ornaments('md,me,,'); # bold face prompt -# make sure stdout is not buffered -STDOUT->autoflush(1); + +# get a console for the app my $line; my $command; @@ -121,7 +118,6 @@ my %commands = # my @jcm_cmd_list = keys %commands; -$attribs->{attempted_completion_function} = \&completeme; #------------------------------------------------------------------------------ # Open the device, as we need an FD for the ioctl sysopen(DEV_OBD, $device, 0) || die "Cannot open $device"; @@ -130,8 +126,26 @@ if (!defined($::st = stat($filesystem))) { die "Unable to stat $filesystem.\n"; } -# Get on with the show -process_line(); +my $term, $attribs; + +if ( $file ) { + while ( ) { + print $_; + execute_line($_); + } + exit 0; +} else { + $term = new Term::ReadLine 'obdcontrol '; + $attribs = $term->Attribs; + $attribs->{attempted_completion_function} = \&completeme; + $term->ornaments('md,me,,'); # bold face prompt + + # make sure stdout is not buffered + STDOUT->autoflush(1); + + # Get on with the show + process_line(); +} #------------------------------------------------------------------------------ sub completeme { @@ -168,7 +182,12 @@ sub execute_line { my @arg = split(' ', $line); my $word = shift @arg; - my $cmd = find_command($word); + my $cmd; + if ( $file ) { + $cmd = $word; + } else { + $cmd = find_command($word); + } unless ($cmd) { printf STDERR "$word: No such command, or not unique.\n"; return (-1); @@ -283,6 +302,7 @@ sub Cleanup { print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { print "Finished (success)\n"; + $::client_id = 0; } else { print "ioctl returned error code $rc.\n"; } @@ -338,16 +358,16 @@ sub Create { my $arg = shift; my $quiet = shift; my $rc; + my $prealloc = 0; if (defined($quiet) && !($quiet eq "quiet")) { print "syntax: create [number of objects [quiet]]\n"; return; } - my $packed = pack("I", $::client_id); + my $packed = pack("IL", $::client_id, $prealloc); if (!defined($arg) || scalar($arg) < 2) { print "Creating 1 object...\n"; - my $packed = pack("I", 0); $rc = ioctl(DEV_OBD, &OBD_IOC_CREATE, $packed); if (!defined($quiet)) { my $ino = unpack("L", $packed); diff --git a/lustre/obdclass/setup.sh b/lustre/obdclass/setup.sh new file mode 100755 index 0000000..6b5fbba --- /dev/null +++ b/lustre/obdclass/setup.sh @@ -0,0 +1,13 @@ +#! /bin/bash + +insmod loop +losetup /dev/loop0 /tmp/fs +insmod obdclass.o +insmod obdsim.o +insmod ../obdfs/obdfs.o +./obdcontrol -f << EOF +attach sim_obd +setup +quit +EOF +mount -t obdfs /dev/loop0 /mnt/obd diff --git a/lustre/obdfs/dir.c b/lustre/obdfs/dir.c index 0c0fe1c..fef4332 100644 --- a/lustre/obdfs/dir.c +++ b/lustre/obdfs/dir.c @@ -47,37 +47,46 @@ static ssize_t obdfs_dir_read (struct file * filp, char * buf, { return -EISDIR; } +#endif - -int ext2_check_dir_entry (const char * function, struct inode * dir, +int obdfs_check_dir_entry (const char * function, struct inode * dir, struct ext2_dir_entry_2 * de, - struct buffer_head * bh, + struct page * page, unsigned long offset) { const char * error_msg = NULL; + ENTRY; + if ( !de ) { + error_msg = "null de passed"; + return 1; + } + if (le16_to_cpu(de->rec_len) < EXT2_DIR_REC_LEN(1)) error_msg = "rec_len is smaller than minimal"; else if (le16_to_cpu(de->rec_len) % 4 != 0) error_msg = "rec_len % 4 != 0"; else if (le16_to_cpu(de->rec_len) < EXT2_DIR_REC_LEN(de->name_len)) error_msg = "rec_len is too small for name_len"; - else if (dir && ((char *) de - bh->b_data) + le16_to_cpu(de->rec_len) > + else if (dir && ((char *) de - (char *)page_address(page)) + le16_to_cpu(de->rec_len) > dir->i_sb->s_blocksize) error_msg = "directory entry across blocks"; - else if (dir && le32_to_cpu(de->inode) > le32_to_cpu(dir->i_sb->u.ext2_sb.s_es->s_inodes_count)) - error_msg = "inode out of bounds"; +#if 0 /* this one doesn't yet work for OBDFS */ + else +if (dir && le32_to_cpu(de->inode) > le32_to_cpu(dir->i_sb->u.ext2_sb.s_es->s_inodes_count)) + error_msg = "inode out of bounds"; +#endif if (error_msg != NULL) ext2_error (dir->i_sb, function, "bad entry in directory #%lu: %s - " "offset=%lu, inode=%lu, rec_len=%d, name_len=%d", dir->i_ino, error_msg, offset, (unsigned long) le32_to_cpu(de->inode), le16_to_cpu(de->rec_len), de->name_len); + EXIT; return error_msg == NULL ? 1 : 0; } -#endif int obdfs_readdir(struct file * filp, void * dirent, filldir_t filldir) { @@ -98,6 +107,7 @@ int obdfs_readdir(struct file * filp, void * dirent, filldir_t filldir) while (!error && !stored && filp->f_pos < inode->i_size) { page = obdfs_getpage(inode, offset, 0, NOLOCK); + PDEBUG(page, "readdir"); if (!page) { ext2_error (sb, "ext2_readdir", "directory #%lu contains a hole at offset %lu", diff --git a/lustre/obdfs/file.c b/lustre/obdfs/file.c index fb6b916..ec31cef 100644 --- a/lustre/obdfs/file.c +++ b/lustre/obdfs/file.c @@ -56,7 +56,7 @@ static inline void remove_suid(struct inode *inode) ssize_t obdfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { ssize_t retval; - CDEBUG(D_INODE, "Writing %d bytes, offset %ld\n", count, (long)*ppos); + CDEBUG(D_INODE, "Writing inode %ld, %d bytes, offset %ld\n", file->f_dentry->d_inode->i_ino, count, (long)*ppos); retval = generic_file_write(file, buf, count, ppos, obdfs_write_one_page); @@ -66,5 +66,6 @@ ssize_t obdfs_file_write(struct file *file, const char *buf, size_t count, loff_ inode->i_ctime = inode->i_mtime = CURRENT_TIME; mark_inode_dirty(inode); } + EXIT; return retval; } diff --git a/lustre/obdfs/namei.c b/lustre/obdfs/namei.c index 9738874..6d33286 100644 --- a/lustre/obdfs/namei.c +++ b/lustre/obdfs/namei.c @@ -72,11 +72,12 @@ static inline int ext2_match (int len, const char * const name, */ struct page * obdfs_find_entry (struct inode * dir, const char * const name, int namelen, - struct ext2_dir_entry_2 ** res_dir) + struct ext2_dir_entry_2 ** res_dir, int lock) { struct super_block * sb; unsigned long offset; struct page * page; + ENTRY; *res_dir = NULL; sb = dir->i_sb; @@ -88,7 +89,7 @@ struct page * obdfs_find_entry (struct inode * dir, struct ext2_dir_entry_2 * de; char * dlimit; - page = obdfs_getpage(dir, offset, 0, NOLOCK); + page = obdfs_getpage(dir, offset, 0, lock); if ( !page ) return NULL; @@ -103,12 +104,11 @@ struct page * obdfs_find_entry (struct inode * dir, ext2_match (namelen, name, de)) { /* found a match - just to be sure, do a full check */ -#if 0 - if (!ext2_check_dir_entry("ext2_find_entry", - dir, de, bh, offset)) + if (!obdfs_check_dir_entry("ext2_find_entry", + dir, de, page, offset)) goto failure; -#endif *res_dir = de; + EXIT; return page; } /* prevent looping on a bad block */ @@ -124,6 +124,7 @@ struct page * obdfs_find_entry (struct inode * dir, failure: page_cache_release(page); + EXIT; return NULL; } @@ -132,21 +133,32 @@ struct dentry *obdfs_lookup(struct inode * dir, struct dentry *dentry) struct inode * inode; struct ext2_dir_entry_2 * de; struct page * page; + ENTRY; 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); + page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, NOLOCK); inode = NULL; + if ( !page ) + CDEBUG(D_INODE, "No page - negative entry.\n"); + if ( page && !de ) { + CDEBUG(D_INODE, "Danger: PAGE but de.\n"); + return ERR_PTR(-ENOENT); + } if (page) { unsigned long ino = le32_to_cpu(de->inode); page_cache_release(page); inode = iget(dir->i_sb, ino); - if (!inode) + if (!inode) { + CDEBUG(D_INODE, "No inode.\n"); + EXIT; return ERR_PTR(-EACCES); + } } d_add(dentry, inode); + EXIT; return NULL; } @@ -174,6 +186,7 @@ static struct page *obdfs_add_entry (struct inode * dir, struct ext2_dir_entry_2 * de, * de1; struct super_block * sb; + ENTRY; *err = -EINVAL; *res_dir = NULL; if (!dir || !dir->i_nlink) @@ -191,8 +204,10 @@ static struct page *obdfs_add_entry (struct inode * dir, return NULL; } page = obdfs_getpage(dir, 0, 0, LOCKED); - if (!page) + if (!page) { + EXIT; return NULL; + } rec_len = EXT2_DIR_REC_LEN(namelen); offset = 0; de = (struct ext2_dir_entry_2 *) page_address(page); @@ -202,7 +217,7 @@ static struct page *obdfs_add_entry (struct inode * dir, UnlockPage(page); page_cache_release(page); page = obdfs_getpage(dir, offset, 1, LOCKED); - if (page) + if (!page) return NULL; if (dir->i_size <= offset) { if (dir->i_size == 0) { @@ -214,7 +229,7 @@ static struct page *obdfs_add_entry (struct inode * dir, de = (struct ext2_dir_entry_2 *) page_address(page); de->inode = 0; - de->rec_len = le16_to_cpu(sb->s_blocksize); + de->rec_len = le16_to_cpu(PAGE_SIZE); dir->i_size = offset + PAGE_SIZE; dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; mark_inode_dirty(dir); @@ -225,20 +240,23 @@ static struct page *obdfs_add_entry (struct inode * dir, de = (struct ext2_dir_entry_2 *) page_address(page); } } -#if 0 - if (!ext2_check_dir_entry ("ext2_add_entry", dir, de, bh, + CDEBUG(D_INODE, "\n"); + if (!obdfs_check_dir_entry ("ext2_add_entry", dir, de, page, offset)) { *err = -ENOENT; - brelse (bh); + page_cache_release(page); + EXIT; return NULL; } -#endif + CDEBUG(D_INODE, "\n"); if (ext2_match (namelen, name, de)) { *err = -EEXIST; UnlockPage(page); page_cache_release(page); + 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)) { offset += le16_to_cpu(de->rec_len); @@ -250,10 +268,12 @@ static struct page *obdfs_add_entry (struct inode * dir, de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(de->name_len)); de = de1; } + CDEBUG(D_INODE, "\n"); de->inode = 0; de->name_len = namelen; de->file_type = 0; memcpy (de->name, name, namelen); + CDEBUG(D_INODE, "\n"); /* * XXX shouldn't update any times until successful * completion of syscall, but too many callers depend @@ -272,11 +292,14 @@ static struct page *obdfs_add_entry (struct inode * dir, *res_dir = de; *err = 0; PDEBUG(page, "addentry"); + 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"); UnlockPage(page); page_cache_release(page); @@ -299,11 +322,9 @@ static int obdfs_delete_entry (struct ext2_dir_entry_2 * dir, pde = NULL; de = (struct ext2_dir_entry_2 *) page_address(page); while (i < PAGE_SIZE) { -#if 0 - if (!ext2_check_dir_entry ("ext2_delete_entry", NULL, - de, bh, i)) + if (!obdfs_check_dir_entry ("ext2_delete_entry", NULL, + de, page, i)) return -EIO; -#endif if (de == dir) { if (pde) pde->rec_len = @@ -363,12 +384,14 @@ 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_obd, 0, &err); + ino = sbi->osi_ops->o_create(sbi->osi_conn_info.conn_id, 0, &err); if ( ino == -1 ) return -1; inode = iget(dir->i_sb, ino); - if (!inode) + if (!inode) { + CDEBUG(D_INODE, "No inode, ino %ld\n", ino); return err; + } inode->i_op = &obdfs_inode_ops; inode->i_mode = mode; @@ -378,6 +401,7 @@ int obdfs_create (struct inode * dir, struct dentry * dentry, int mode) inode->i_nlink--; mark_inode_dirty(inode); iput (inode); + EXIT; return err; } de->inode = cpu_to_le32(inode->i_ino); @@ -394,6 +418,7 @@ int obdfs_create (struct inode * dir, struct dentry * dentry, int mode) #endif page_cache_release(page); d_instantiate(dentry, inode); + EXIT; return 0; } @@ -413,7 +438,7 @@ int obdfs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev) /* * N.B. Several error exits in ext2_new_inode don't set err. */ - ino = sbi->osi_ops->o_create(sbi->osi_obd, 0, &err); + ino = sbi->osi_ops->o_create(sbi->osi_conn_info.conn_id, 0, &err); if ( ino == -1 ) return -1; inode = iget(dir->i_sb, ino); @@ -469,7 +494,7 @@ int obdfs_mkdir(struct inode * dir, struct dentry * dentry, int mode) goto out; err = -EIO; - ino = iops(dir)->o_create(sbi->osi_obd, 0, &err); + ino = iops(dir)->o_create(sbi->osi_conn_info.conn_id, 0, &err); if ( ino == -1 ) return -1; child = iget(dir->i_sb, ino); @@ -499,7 +524,7 @@ int obdfs_mkdir(struct inode * dir, struct dentry * dentry, int mode) de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); de->inode = cpu_to_le32(dir->i_ino); - de->rec_len = cpu_to_le16(child->i_sb->s_blocksize - EXT2_DIR_REC_LEN(1)); + de->rec_len = cpu_to_le16(PAGE_SIZE - EXT2_DIR_REC_LEN(1)); de->name_len = 2; strcpy (de->name, ".."); ext2_set_de_type(dir->i_sb, de, S_IFDIR); @@ -546,6 +571,7 @@ out_no_entry: child->i_nlink = 0; mark_inode_dirty(child); iput (child); + EXIT; goto out; } @@ -596,13 +622,11 @@ static int empty_dir (struct inode * inode) } de = (struct ext2_dir_entry_2 *) page_address(page); } -#if 0 - if (!ext2_check_dir_entry ("empty_dir", inode, de, bh, + if (!obdfs_check_dir_entry ("empty_dir", inode, de, page, offset)) { - brelse (bh); + page_cache_release(page); return 1; } -#endif if (le32_to_cpu(de->inode)) { page_cache_release(page); return 0; @@ -626,7 +650,7 @@ int obdfs_rmdir (struct inode * dir, struct dentry *dentry) sbi = dir->i_sb->u.generic_sbp; retval = -ENOENT; - page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de); + page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, LOCKED); if (!page) goto end_rmdir; @@ -671,6 +695,7 @@ int obdfs_rmdir (struct inode * dir, struct dentry *dentry) end_rmdir: if ( page ) page_cache_release(page); + EXIT; return retval; } @@ -686,7 +711,7 @@ int obdfs_unlink(struct inode * dir, struct dentry *dentry) sbi = dir->i_sb->u.generic_sbp; retval = -ENOENT; - page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de); + page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, LOCKED); if (!page) goto end_unlink; @@ -728,6 +753,7 @@ int obdfs_unlink(struct inode * dir, struct dentry *dentry) end_unlink: if (page) page_cache_release(page); + EXIT; return retval; } @@ -748,7 +774,7 @@ int obdfs_symlink (struct inode * dir, struct dentry *dentry, const char * symna /* * N.B. Several error exits in ext2_new_inode don't set err. */ - ino = sbi->osi_ops->o_create(sbi->osi_obd, 0, &err); + ino = sbi->osi_ops->o_create(sbi->osi_conn_info.conn_id, 0, &err); if ( ino == -1 ) return -1; inode = iget(dir->i_sb, ino); @@ -872,7 +898,7 @@ int obdfs_link (struct dentry * old_dentry, * higher-level routines. */ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry, - struct inode * new_dir,struct dentry *new_dentry) + struct inode * new_dir, struct dentry *new_dentry) { struct inode * old_inode, * new_inode; struct page * old_page, * new_page, * dir_page; @@ -885,7 +911,9 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry, new_page = dir_page = NULL; - old_page = obdfs_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de); + /* does the old entry exist? - if not get out */ + old_page = obdfs_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de, NOLOCK); + PDEBUG(old_page, "rename - old page"); /* * Check for inode number is _not_ due to possible IO errors. * We might rmdir the source, keep it as pwd of some process @@ -897,9 +925,11 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry, if (!old_page || le32_to_cpu(old_de->inode) != old_inode->i_ino) goto end_rename; + /* find new inode */ new_inode = new_dentry->d_inode; new_page = obdfs_find_entry (new_dir, new_dentry->d_name.name, - new_dentry->d_name.len, &new_de); + new_dentry->d_name.len, &new_de, NOLOCK); + PDEBUG(new_page, "rename - new page "); if (new_page) { if (!new_inode) { page_cache_release(new_page); @@ -908,7 +938,9 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry, DQUOT_INIT(new_inode); } } + /* in this case we to check more ... */ if (S_ISDIR(old_inode->i_mode)) { + /* can only rename into empty new directory */ if (new_inode) { retval = -ENOTEMPTY; if (!empty_dir (new_inode)) @@ -916,6 +948,8 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry, } retval = -EIO; dir_page= obdfs_getpage (old_inode, 0, 0, LOCKED); + PDEBUG(dir_page, "rename dir page"); + if (!dir_page) goto end_rename; if (le32_to_cpu(PARENT_INO(page_address(dir_page))) != old_dir->i_ino) @@ -925,17 +959,19 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry, new_dir->i_nlink >= EXT2_LINK_MAX) goto end_rename; } + /* create the target dir entry */ if (!new_page) { new_page = obdfs_add_entry (new_dir, new_dentry->d_name.name, new_dentry->d_name.len, &new_de, &retval); + PDEBUG(new_page, "rename new page"); if (!new_page) goto end_rename; } new_dir->i_version = ++event; /* - * ok, that's it + * remove the old entry */ new_de->inode = le32_to_cpu(old_inode->i_ino); if (EXT2_HAS_INCOMPAT_FEATURE(new_dir->i_sb, @@ -956,7 +992,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, - new_dir->i_ino, dir_page, 0); + old_inode->i_ino, dir_page, 0); old_dir->i_nlink--; mark_inode_dirty(old_dir); if (new_inode) { @@ -968,8 +1004,16 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry, mark_inode_dirty(new_dir); } } - sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id, - old_inode->i_ino, old_page, 0); + if ( old_page != new_page ) { + unsigned long offset = old_page->offset; + /* lock the old_page and release unlocked copy */ + CDEBUG(D_INODE, "old_page at %p\n", old_page); + page_cache_release(old_page); + 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); + } #if 0 if (IS_SYNC(old_dir)) { ll_rw_block (WRITE, 1, &old_bh); @@ -977,7 +1021,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_inode->i_ino, new_page, 0); + new_dir->i_ino, new_page, 0); #if 0 if (IS_SYNC(new_dir)) { ll_rw_block (WRITE, 1, &new_bh); @@ -988,11 +1032,19 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry, retval = 0; end_rename: + if (old_page && PageLocked(old_page) ) + UnlockPage(old_page); if (old_page) page_cache_release(old_page); + if (new_page && PageLocked(new_page) ) + UnlockPage(new_page); if (new_page) page_cache_release(new_page); + if (dir_page && PageLocked(dir_page) ) + UnlockPage(dir_page); if (dir_page) page_cache_release(dir_page); + + return retval; } diff --git a/lustre/obdfs/rw.c b/lustre/obdfs/rw.c index ff06852..4016b49 100644 --- a/lustre/obdfs/rw.c +++ b/lustre/obdfs/rw.c @@ -73,6 +73,7 @@ int obdfs_write_one_page(struct file *file, struct page *page, unsigned long off long status; struct obdfs_sb_info *sbi = file->f_dentry->d_inode->i_sb->u.generic_sbp; + ENTRY; if ( !Page_Uptodate(page) ) { status = sbi->osi_ops->o_brw(READ, sbi->osi_conn_info.conn_id, @@ -92,6 +93,7 @@ int obdfs_write_one_page(struct file *file, struct page *page, unsigned long off status = obdfs_writepage(file, page); unlock_kernel(); } + EXIT; if ( status != PAGE_SIZE ) return status; else @@ -140,6 +142,7 @@ struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create PDEBUG(page,"GETPAGE"); if (!locked) UnlockPage(page); + EXIT; return page; } @@ -147,7 +150,7 @@ struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create CDEBUG(D_INODE, "Page found but not up to date\n"); } - /* page_cache_alloc returns address of page */ + /* page_cache_alloc returns the VM address of page */ new_page = page_cache_alloc(); if (!new_page) return NULL; @@ -155,16 +158,16 @@ struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create /* corresponding struct page in the mmap */ hash = page_hash(inode, offset); page = page_cache_entry(new_page); - PDEBUG(page, "GETPAGE"); if (!add_to_page_cache_unique(page, inode, offset, hash)) { CDEBUG(D_INODE, "Page not found. Reading it.\n"); - PDEBUG(page,"GETPAGE"); + 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"); + PDEBUG(page,"GETPAGE - after reading"); + EXIT; return page; } /* @@ -173,6 +176,7 @@ struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create */ CDEBUG(D_INODE, "Page not found. Someone raced us.\n"); PDEBUG(page,"GETPAGE"); + EXIT; return page; } diff --git a/lustre/obdfs/super.c b/lustre/obdfs/super.c index 0072f36..eddd0c8 100644 --- a/lustre/obdfs/super.c +++ b/lustre/obdfs/super.c @@ -66,6 +66,7 @@ static struct super_block * obdfs_read_super(struct super_block *sb, { struct inode *root = 0; struct obdfs_sb_info *sbi = NULL; + struct obd_device *obddev; int error = 0; unsigned long blocksize; unsigned long blocksize_bits; @@ -83,8 +84,14 @@ static struct super_block * obdfs_read_super(struct super_block *sb, MOD_DEC_USE_COUNT; return NULL; } + + obddev = &obd_dev[obd_minor]; + + if ( ! (obddev->obd_flags & OBD_ATTACHED) || + ! (obddev->obd_flags & OBD_SET_UP) ) + return NULL; - sbi->osi_obd = &obd_dev[obd_minor]; + sbi->osi_obd = obddev; sbi->osi_ops = sbi->osi_obd->obd_type->typ_ops; error = sbi->osi_ops->o_connect(sbi->osi_obd, &sbi->osi_conn_info); diff --git a/lustre/patches/patch-2.3.21 b/lustre/patches/patch-2.3.21 new file mode 100644 index 0000000..b0c4712 --- /dev/null +++ b/lustre/patches/patch-2.3.21 @@ -0,0 +1,60 @@ +--- linux/kernel/ksyms.c.or Tue Oct 12 10:40:21 1999 ++++ linux/kernel/ksyms.c Tue Oct 12 11:22:45 1999 +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -118,6 +119,8 @@ + EXPORT_SYMBOL(update_atime); + EXPORT_SYMBOL(get_super); + EXPORT_SYMBOL(get_fs_type); ++EXPORT_SYMBOL(get_empty_super); ++EXPORT_SYMBOL(remove_vfsmnt); + EXPORT_SYMBOL(getname); + EXPORT_SYMBOL(_fput); + EXPORT_SYMBOL(igrab); +@@ -140,6 +143,9 @@ + EXPORT_SYMBOL(d_path); + EXPORT_SYMBOL(__mark_buffer_dirty); + EXPORT_SYMBOL(__mark_inode_dirty); ++EXPORT_SYMBOL(free_kiovec); ++EXPORT_SYMBOL(brw_kiovec); ++EXPORT_SYMBOL(alloc_kiovec); + EXPORT_SYMBOL(get_empty_filp); + EXPORT_SYMBOL(init_private_file); + EXPORT_SYMBOL(filp_open); +--- linux/fs/super.c.or Tue Oct 12 10:39:05 1999 ++++ linux/fs/super.c Tue Oct 12 11:18:14 1999 +@@ -135,7 +135,7 @@ + return lptr; + } + +-static void remove_vfsmnt(kdev_t dev) ++void remove_vfsmnt(kdev_t dev) + { + struct vfsmount *lptr, *tofree; + +@@ -508,7 +508,7 @@ + /* + * Find a super_block with no device assigned. + */ +-static struct super_block *get_empty_super(void) ++struct super_block *get_empty_super(void) + { + struct super_block *s; + +--- linux/include/linux/fs.h.or Tue Oct 12 10:39:59 1999 ++++ linux/include/linux/fs.h Tue Oct 12 11:32:46 1999 +@@ -934,6 +934,8 @@ + + + extern struct super_block *get_super(kdev_t); ++struct super_block *get_empty_super(void); ++void remove_vfsmnt(kdev_t dev); + extern void put_super(kdev_t); + unsigned long generate_cluster(kdev_t, int b[], int); + unsigned long generate_cluster_swab32(kdev_t, int b[], int); -- 1.8.3.1