- Documentation/filesystems/ext2.txt | 16 ++
fs/ext3/inode.c | 3
fs/ext3/iopen.c | 239 +++++++++++++++++++++++++++++++++++++
fs/ext3/iopen.h | 15 ++
include/linux/ext3_fs.h | 2
7 files changed, 304 insertions(+), 1 deletion(-)
-Index: linux-2.6.4-51.1/fs/ext3/inode.c
+Index: linux-stage/fs/ext3/Makefile
===================================================================
---- linux-2.6.4-51.1.orig/fs/ext3/inode.c 2004-04-06 00:31:14.000000000 -0400
-+++ linux-2.6.4-51.1/fs/ext3/inode.c 2004-04-06 00:31:24.000000000 -0400
+--- linux-stage.orig/fs/ext3/Makefile 2004-05-07 16:00:16.000000000 -0400
++++ linux-stage/fs/ext3/Makefile 2004-05-07 16:00:17.000000000 -0400
+@@ -4,7 +4,7 @@
+
+ obj-$(CONFIG_EXT3_FS) += ext3.o
+
+-ext3-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
++ext3-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
+ ioctl.o namei.o super.o symlink.o hash.o
+
+ ext3-$(CONFIG_EXT3_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
+Index: linux-stage/fs/ext3/inode.c
+===================================================================
+--- linux-stage.orig/fs/ext3/inode.c 2004-05-07 16:00:16.000000000 -0400
++++ linux-stage/fs/ext3/inode.c 2004-05-07 17:21:59.000000000 -0400
@@ -37,6 +37,7 @@
#include <linux/mpage.h>
#include <linux/uio.h>
#include "acl.h"
/*
-@@ -2472,6 +2473,8 @@
+@@ -2472,6 +2473,9 @@
ei->i_acl = EXT3_ACL_NOT_CACHED;
ei->i_default_acl = EXT3_ACL_NOT_CACHED;
#endif
+ if (ext3_iopen_get_inode(inode))
+ return;
++
if (ext3_get_inode_loc(inode, &iloc, 0))
goto bad_inode;
bh = iloc.bh;
-Index: linux-2.6.4-51.1/fs/ext3/iopen.c
+Index: linux-stage/fs/ext3/iopen.c
===================================================================
---- linux-2.6.4-51.1.orig/fs/ext3/iopen.c 2004-04-06 00:31:24.000000000 -0400
-+++ linux-2.6.4-51.1/fs/ext3/iopen.c 2004-04-06 00:31:24.000000000 -0400
-@@ -0,0 +1,223 @@
-+
-+
+--- linux-stage.orig/fs/ext3/iopen.c 2004-05-07 16:00:17.000000000 -0400
++++ linux-stage/fs/ext3/iopen.c 2004-05-07 17:22:37.000000000 -0400
+@@ -0,0 +1,272 @@
+/*
+ * linux/fs/ext3/iopen.c
+ *
+ *
+ * This file may be redistributed under the terms of the GNU General
+ * Public License.
++ *
++ *
++ * Invariants:
++ * - there is only ever a single DCACHE_NFSD_DISCONNECTED dentry alias
++ * for an inode at one time.
++ * - there are never both connected and DCACHE_NFSD_DISCONNECTED dentry
++ * aliases on an inode at the same time.
++ *
++ * If we have any connected dentry aliases for an inode, use one of those
++ * in iopen_lookup(). Otherwise, we instantiate a single NFSD_DISCONNECTED
++ * dentry for this inode, which thereafter will be found by the dcache
++ * when looking up this inode number in __iopen__, so we don't return here
++ * until it is gone.
++ *
++ * If we get an inode via a regular name lookup, then we "rename" the
++ * NFSD_DISCONNECTED dentry to the proper name and parent. This ensures
++ * existing users of the disconnected dentry will continue to use the same
++ * dentry as the connected users, and there will never be both kinds of
++ * dentry aliases at one time.
+ */
+
+#include <linux/sched.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/smp_lock.h>
++#include <linux/dcache.h>
++#include <linux/security.h>
+#include "iopen.h"
+
+#ifndef assert
+/*
+ * This implements looking up an inode by number.
+ */
-+static struct dentry *iopen_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
++static struct dentry *iopen_lookup(struct inode * dir, struct dentry *dentry,
++ struct nameidata *nd)
+{
-+ struct inode * inode;
++ struct inode *inode;
+ unsigned long ino;
+ struct list_head *lp;
+ struct dentry *alternate;
+ char buf[IOPEN_NAME_LEN];
-+
++
+ if (dentry->d_name.len >= IOPEN_NAME_LEN)
+ return ERR_PTR(-ENAMETOOLONG);
+
+ return ERR_PTR(-ENOENT);
+ }
+
++ assert(list_empty(&dentry->d_alias)); /* d_instantiate */
++ assert(d_unhashed(dentry)); /* d_rehash */
++
+ /* preferrably return a connected dentry */
+ spin_lock(&dcache_lock);
+ list_for_each(lp, &inode->i_dentry) {
+ return alternate;
+ }
+ dentry->d_flags |= DCACHE_DISCONNECTED;
++
++ /* d_add(), but don't drop dcache_lock before adding dentry to inode */
++ list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */
++ dentry->d_inode = inode;
++
++ __d_rehash(dentry, 0); /* d_rehash */
+ spin_unlock(&dcache_lock);
+
-+ d_add(dentry, inode);
+ return NULL;
+}
+
+ __typeof__ (x) __tmp = x; \
+ x = y; y = __tmp; } while (0)
+
-+static inline void switch_names(struct dentry * dentry, struct dentry * target)
++static inline void switch_names(struct dentry *dentry, struct dentry *target)
+{
+ const unsigned char *old_name, *new_name;
+
+ dentry->d_name.name = old_name;
+}
+
-+
-+struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode)
++/* This function is spliced into ext3_lookup and does the move of a
++ * disconnected dentry (if it exists) to a connected dentry.
++ */
++struct dentry *iopen_connect_dentry(struct dentry *dentry, struct inode *inode,
++ int rehash)
+{
+ struct dentry *tmp, *goal = NULL;
+ struct list_head *lp;
+
-+ /* preferrably return a connected dentry */
-+ spin_lock(&dcache_lock);
+ /* verify this dentry is really new */
-+ assert(!de->d_inode);
-+ assert(list_empty(&de->d_subdirs));
-+ assert(list_empty(&de->d_alias));
++ assert(dentry->d_inode == NULL);
++ assert(list_empty(&dentry->d_alias)); /* d_instantiate */
++ if (rehash)
++ assert(d_unhashed(dentry)); /* d_rehash */
++ assert(list_empty(&dentry->d_subdirs));
+
++ spin_lock(&dcache_lock);
++ if (!inode)
++ goto do_rehash;
+
++ /* preferrably return a connected dentry */
+ list_for_each(lp, &inode->i_dentry) {
+ tmp = list_entry(lp, struct dentry, d_alias);
+ if (tmp->d_flags & DCACHE_DISCONNECTED) {
+ break;
+ }
+ }
-+ spin_unlock(&dcache_lock);
+
+ if (!goal)
-+ return NULL;
++ goto do_instantiate;
+
-+ goal->d_flags &= ~DCACHE_DISCONNECTED;
-+ d_rehash(de);
-+ d_move(goal, de);
++ /* Move the goal to the de hash queue */
++ goal->d_flags &= ~ DCACHE_DISCONNECTED;
++ security_d_instantiate(goal, inode);
++ __d_rehash(dentry, 0);
++ __d_move(goal, dentry);
++ spin_unlock(&dcache_lock);
++ iput(inode);
+
+ return goal;
++
++ /* d_add(), but don't drop dcache_lock before adding dentry to inode */
++do_instantiate:
++ list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */
++ dentry->d_inode = inode;
++do_rehash:
++ if (rehash)
++ __d_rehash(dentry, 0); /* d_rehash */
++ spin_unlock(&dcache_lock);
++
++ return NULL;
+}
+
+/*
+ * This function is spliced into ext3_lookup and returns 1 the file
+ * name is __iopen__ and dentry has been filled in appropriately.
+ */
-+int ext3_check_for_iopen(struct inode * dir, struct dentry *dentry)
++int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry)
+{
-+ struct inode * inode;
++ struct inode *inode;
+
+ if (dir->i_ino != EXT3_ROOT_INO ||
+ !test_opt(dir->i_sb, IOPEN) ||
+ * number is the one for /__iopen__, in which case the inode is filled
+ * in appropriately. Otherwise, this fuction returns 0.
+ */
-+int ext3_iopen_get_inode(struct inode * inode)
++int ext3_iopen_get_inode(struct inode *inode)
+{
+ if (inode->i_ino != EXT3_BAD_INO)
+ return 0;
+
+ return 1;
+}
-Index: linux-2.6.4-51.1/fs/ext3/iopen.h
+Index: linux-stage/fs/ext3/iopen.h
===================================================================
---- linux-2.6.4-51.1.orig/fs/ext3/iopen.h 2004-04-06 00:31:24.000000000 -0400
-+++ linux-2.6.4-51.1/fs/ext3/iopen.h 2004-04-06 00:31:24.000000000 -0400
+--- linux-stage.orig/fs/ext3/iopen.h 2004-05-07 16:00:17.000000000 -0400
++++ linux-stage/fs/ext3/iopen.h 2004-05-07 16:00:17.000000000 -0400
@@ -0,0 +1,15 @@
+/*
+ * iopen.h
+ * Public License.
+ */
+
-+extern int ext3_check_for_iopen(struct inode * dir, struct dentry *dentry);
-+extern int ext3_iopen_get_inode(struct inode * inode);
-+
-+
-Index: linux-2.6.4-51.1/fs/ext3/namei.c
++extern int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry);
++extern int ext3_iopen_get_inode(struct inode *inode);
++extern struct dentry *iopen_connect_dentry(struct dentry *dentry,
++ struct inode *inode, int rehash);
+Index: linux-stage/fs/ext3/namei.c
===================================================================
---- linux-2.6.4-51.1.orig/fs/ext3/namei.c 2004-04-06 00:31:11.000000000 -0400
-+++ linux-2.6.4-51.1/fs/ext3/namei.c 2004-04-06 00:31:24.000000000 -0400
+--- linux-stage.orig/fs/ext3/namei.c 2004-05-07 16:00:16.000000000 -0400
++++ linux-stage/fs/ext3/namei.c 2004-05-07 16:00:17.000000000 -0400
@@ -37,6 +37,7 @@
#include <linux/buffer_head.h>
#include <linux/smp_lock.h>
#include "acl.h"
/*
-@@ -970,15 +971,21 @@
- }
- #endif
-
-+struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode);
-+
- static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
- {
- struct inode * inode;
- struct ext3_dir_entry_2 * de;
- struct buffer_head * bh;
-+ struct dentry *alternate = NULL;
-
+@@ -979,6 +980,9 @@
if (dentry->d_name.len > EXT3_NAME_LEN)
return ERR_PTR(-ENAMETOOLONG);
-+ if (ext3_check_for_iopen(dir, dentry))
-+ return NULL;
++ if (ext3_check_for_iopen(dir, dentry))
++ return NULL;
+
bh = ext3_find_entry(dentry, &de);
inode = NULL;
if (bh) {
-@@ -989,8 +996,14 @@
+@@ -989,10 +993,8 @@
if (!inode)
return ERR_PTR(-EACCES);
}
-+ if (inode && (alternate = iopen_connect_dentry(dentry, inode))) {
-+ iput(inode);
-+ return alternate;
-+ }
+- if (inode)
+- return d_splice_alias(inode, dentry);
+- d_add(dentry, inode);
+- return NULL;
+
- if (inode)
- return d_splice_alias(inode, dentry);
++ return iopen_connect_dentry(dentry, inode, 1);
+ }
+
+
+@@ -2019,10 +2021,6 @@
+ inode->i_nlink);
+ inode->i_version++;
+ inode->i_nlink = 0;
+- /* There's no need to set i_disksize: the fact that i_nlink is
+- * zero will ensure that the right thing happens during any
+- * recovery. */
+- inode->i_size = 0;
+ ext3_orphan_add(handle, inode);
+ inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ ext3_mark_inode_dirty(handle, inode);
+@@ -2139,6 +2137,23 @@
+ return err;
+ }
+
++/* Like ext3_add_nondir() except for call to iopen_connect_dentry */
++static int ext3_add_link(handle_t *handle, struct dentry *dentry,
++ struct inode *inode)
++{
++ int err = ext3_add_entry(handle, dentry, inode);
++ if (!err) {
++ err = ext3_mark_inode_dirty(handle, inode);
++ if (err == 0) {
++ (void)iopen_connect_dentry(dentry, inode, 0);
++ return 0;
++ }
++ }
++ ext3_dec_count(handle, inode);
++ iput(inode);
++ return err;
++}
+
- d_add(dentry, inode);
- return NULL;
+ static int ext3_link (struct dentry * old_dentry,
+ struct inode * dir, struct dentry *dentry)
+ {
+@@ -2161,7 +2176,8 @@
+ ext3_inc_count(handle, inode);
+ atomic_inc(&inode->i_count);
+
+- err = ext3_add_nondir(handle, dentry, inode);
++ err = ext3_add_link(handle, dentry, inode);
++ ext3_orphan_del(handle,inode);
+ ext3_journal_stop(handle);
+ return err;
}
-Index: linux-2.6.4-51.1/fs/ext3/super.c
+Index: linux-stage/fs/ext3/super.c
===================================================================
---- linux-2.6.4-51.1.orig/fs/ext3/super.c 2004-04-06 00:31:14.000000000 -0400
-+++ linux-2.6.4-51.1/fs/ext3/super.c 2004-04-06 00:31:24.000000000 -0400
+--- linux-stage.orig/fs/ext3/super.c 2004-05-07 16:00:16.000000000 -0400
++++ linux-stage/fs/ext3/super.c 2004-05-07 17:21:59.000000000 -0400
@@ -536,7 +536,7 @@
Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, Opt_noload,
Opt_commit, Opt_journal_update, Opt_journal_inum,
set_opt(sbi->s_mount_opt, ABORT);
break;
+ case Opt_iopen:
-+ set_opt (sbi->s_mount_opt, IOPEN);
-+ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
++ set_opt (sbi->s_mount_opt, IOPEN);
++ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
+ break;
+ case Opt_noiopen:
+ clear_opt (sbi->s_mount_opt, IOPEN);
-+ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
++ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
+ break;
+ case Opt_iopen_nopriv:
-+ set_opt (sbi->s_mount_opt, IOPEN);
-+ set_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
++ set_opt (sbi->s_mount_opt, IOPEN);
++ set_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
+ break;
case Opt_ignore:
break;
default:
-Index: linux-2.6.4-51.1/include/linux/ext3_fs.h
+Index: linux-stage/include/linux/ext3_fs.h
===================================================================
---- linux-2.6.4-51.1.orig/include/linux/ext3_fs.h 2004-04-06 00:31:11.000000000 -0400
-+++ linux-2.6.4-51.1/include/linux/ext3_fs.h 2004-04-06 00:31:24.000000000 -0400
+--- linux-stage.orig/include/linux/ext3_fs.h 2004-05-07 16:00:16.000000000 -0400
++++ linux-stage/include/linux/ext3_fs.h 2004-05-07 16:00:17.000000000 -0400
@@ -325,6 +325,8 @@
#define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */
#define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
#ifndef _LINUX_EXT2_FS_H
-Index: linux-2.6.4-51.1/fs/ext3/Makefile
-===================================================================
---- linux-2.6.4-51.1.orig/fs/ext3/Makefile 2004-04-06 00:27:21.000000000 -0400
-+++ linux-2.6.4-51.1/fs/ext3/Makefile 2004-04-06 00:31:42.000000000 -0400
-@@ -5,7 +5,7 @@
- obj-$(CONFIG_EXT3_FS) += ext3.o
-
- ext3-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
-- ioctl.o namei.o super.o symlink.o hash.o
-+ ioctl.o namei.o super.o symlink.o hash.o iopen.o
-
- ext3-$(CONFIG_EXT3_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
- ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o
{
CDEBUG (D_NET, "yield\n");
- if (current->need_resched)
+ if (need_resched())
schedule();
return;
}
/**********************************************************************/
/* Spawn scheduling threads */
- for (i = 0; i < smp_num_cpus; i++)
- {
+ for (i = 0; i < num_online_cpus(); i++) {
rc = kqswnal_thread_start (kqswnal_scheduler, NULL);
if (rc != 0)
{
* along with Lustre; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Basic library routines.
+ * Basic library routines.
*
*/
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/errno.h>
-#include <linux/locks.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#include <linux/locks.h> /* wait_on_buffer */
+#else
+#include <linux/buffer_head.h> /* wait_on_buffer */
+#endif
#include <linux/unistd.h>
#include <net/sock.h>
#include <linux/uio.h>
!list_empty(&kqswnal_data.kqn_delayedtxds) ||
!list_empty(&kqswnal_data.kqn_delayedfwds));
LASSERT (rc == 0);
- } else if (current->need_resched)
+ } else if (need_resched())
schedule ();
spin_lock_irqsave (&kqswnal_data.kqn_sched_lock, flags);
- don't crash in mdc_close for bad permissions on open (3285)
- zero i_rdev for non-device files (3147)
- clear page->private before handing to FS, better assertion (3119)
+ - fix incorrect decref of invalidated dentry (2350)
+ - don't hold journal transaction open across create RPC (3313)
+ - update atime on MDS at close time (3265)
+ - close LDAP connection when recovering to avoid server load (3315)
+ - update iopen-2.6 patch with fixes from 2399,2517,2904 (3301)
+ - don't leak open file on MDS after open resend (3325)
+ - serialize filter_precreate and filter_destroy_precreated (3329)
* miscellania
- allow default OST striping configuration per directory (1414)
+ - fix compilation for qswnal for 2.6 kernels (3125)
- increase maximum number of MDS request buffers for large systems
+ - change liblustreapi to be useful for external progs like lfsck (3098)
2004-03-22 Cluster File Systems, Inc. <info@clusterfs.com>
* version 1.2.1
AC_INIT
AC_CANONICAL_SYSTEM
-AM_INIT_AUTOMAKE(lustre, 1.2.1.10)
+AM_INIT_AUTOMAKE(lustre, 1.2.1.12)
# AM_MAINTAINER_MODE
# Four main targets: lustre kernel modules, utilities, tests, and liblustre
/*
* GENERAL STUFF
*/
-struct obd_uuid {
- __u8 uuid[40];
-};
-
-static inline int obd_uuid_equals(struct obd_uuid *u1, struct obd_uuid *u2)
-{
- return strcmp(u1->uuid, u2->uuid) == 0;
-}
-
-static inline void obd_str2uuid(struct obd_uuid *uuid, char *tmp)
-{
- strncpy(uuid->uuid, tmp, sizeof(*uuid));
- uuid->uuid[sizeof(*uuid) - 1] = '\0';
-}
-
/* FOO_REQUEST_PORTAL is for incoming requests on the FOO
* FOO_REPLY_PORTAL is for incoming replies on the FOO
* FOO_BULK_PORTAL is for incoming bulk on the FOO
__u32 f_type;
};
-struct ll_recreate_obj {
- __u64 lrc_id;
- __u32 lrc_ost_idx;
-};
-
extern void lustre_swab_ll_fid (struct ll_fid *fid);
#define MDS_STATUS_CONN 1
unsigned long *fo_last_rcvd_slots;
__u64 fo_mount_count;
+ unsigned int fo_destroy_in_progress:1;
+ struct semaphore fo_create_lock;
+
struct file_operations *fo_fop;
struct inode_operations *fo_iop;
struct address_space_operations *fo_aops;
#include <lustre/lustre_user.h>
/* liblustreapi.c */
-extern int op_create_file(char *name, long stripe_size, int stripe_offset,
- int stripe_count);
-extern int op_find(char *path, struct obd_uuid *obduuid, int recursive,
- int verbose, int quiet);
-extern int op_check(int type_num, char **obd_type_p, char *dir);
-extern int op_catinfo(char *dir, char *keyword, char *node_name);
-extern int get_file_stripe(char *path, struct lov_user_md *lum);
+extern int llapi_file_create(char *name, long stripe_size, int stripe_offset,
+ int stripe_count, int stripe_pattern);
+extern int llapi_file_get_stripe(char *path, struct lov_user_md *lum);
+extern int llapi_find(char *path, struct obd_uuid *obduuid, int recursive,
+ int verbose, int quiet);
+extern int llapi_target_check(int num_types, char **obd_types, char *dir);
+extern int llapi_catinfo(char *dir, char *keyword, char *node_name);
+extern int llapi_lov_get_uuids(int fd, struct obd_uuid *uuidp, int *ost_count);
extern int llapi_is_lustre_mnttype(char *type);
#endif
#ifndef _LUSTRE_USER_H
#define _LUSTRE_USER_H
#include <asm/types.h>
+#ifdef __KERNEL__
+#include <linux/string.h>
+#else
+#include <string.h>
+#endif
#define LL_IOC_GETFLAGS _IOR ('f', 151, long)
#define LL_IOC_SETFLAGS _IOW ('f', 152, long)
struct lov_user_ost_data_v1 { /* per-stripe data structure */
__u64 l_object_id; /* OST object ID */
__u64 l_object_gr; /* OST object group (creating MDS number) */
- __u32 l_ost_generation; /* generation of this OST index */
- __u16 l_ost_idx; /* OST index in LOV */
- __u16 l_reserved2;
+ __u32 l_ost_gen; /* generation of this OST index */
+ __u32 l_ost_idx; /* OST index in LOV */
} __attribute__((packed));
#define lov_user_md lov_user_md_v1
struct lov_user_ost_data_v1 lmm_objects[0]; /* per-stripe data */
} __attribute__((packed));
+struct ll_recreate_obj {
+ __u64 lrc_id;
+ __u32 lrc_ost_idx;
+};
+
+struct obd_uuid {
+ __u8 uuid[40];
+};
+
+static inline int obd_uuid_equals(struct obd_uuid *u1, struct obd_uuid *u2)
+{
+ return strcmp(u1->uuid, u2->uuid) == 0;
+}
+
+static inline void obd_str2uuid(struct obd_uuid *uuid, char *tmp)
+{
+ strncpy(uuid->uuid, tmp, sizeof(*uuid));
+ uuid->uuid[sizeof(*uuid) - 1] = '\0';
+}
+
#endif /* _LUSTRE_USER_H */
_
Index: linux-ia64/mm/filemap.c
===================================================================
---- linux-ia64.orig/mm/filemap.c 2004-04-27 12:35:18.000000000 -0700
-+++ linux-ia64/mm/filemap.c 2004-04-27 12:42:47.000000000 -0700
+--- linux-ia64.orig/mm/filemap.c 2004-04-27 12:35:18.000000000 -0700
++++ linux-ia64/mm/filemap.c 2004-04-27 12:42:47.000000000 -0700
@@ -676,6 +676,7 @@ static inline void __add_to_page_cache(s
page_cache_get(page);
page->index = offset;
@@ -12,7 +12,8 @@ O_TARGET := ext3.o
export-objs := ext3-exports.o
- obj-y := balloc.o iopen.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
+ obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
- ioctl.o namei.o super.o symlink.o xattr.o hash.o ext3-exports.o
+ ioctl.o namei.o super.o symlink.o xattr.o hash.o ext3-exports.o \
+ extents.o
@@ -12,7 +12,8 @@
export-objs := ext3-exports.o
- obj-y := balloc.o iopen.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
+ obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
- ioctl.o namei.o super.o symlink.o xattr.o ext3-exports.o
+ ioctl.o namei.o super.o symlink.o xattr.o ext3-exports.o \
+ extents.o
include/linux/ext3_fs.h | 2
8 files changed, 318 insertions(+), 1 deletion(-)
---- linux-2.4.18-p4smp/Documentation/filesystems/ext2.txt~iopen-2.4.18 2003-07-09 12:17:30.000000000 -0600
-+++ linux-2.4.18-p4smp-braam/Documentation/filesystems/ext2.txt 2003-07-09 17:13:02.000000000 -0600
-@@ -35,6 +35,22 @@ resgid=n The group ID which may use th
+Index: linux-aed/Documentation/filesystems/ext2.txt
+===================================================================
+--- linux-aed.orig/Documentation/filesystems/ext2.txt Tue May 4 13:14:35 2004
++++ linux-aed/Documentation/filesystems/ext2.txt Tue May 4 19:17:12 2004
+@@ -35,6 +35,22 @@
sb=n Use alternate superblock at this location.
grpquota,noquota,quota,usrquota Quota options are silently ignored by ext2.
---- linux-2.4.18-p4smp/fs/ext3/Makefile~iopen-2.4.18 2003-07-09 17:12:12.000000000 -0600
-+++ linux-2.4.18-p4smp-braam/fs/ext3/Makefile 2003-07-09 17:13:15.000000000 -0600
-@@ -11,7 +11,7 @@ O_TARGET := ext3.o
+Index: linux-aed/fs/ext3/Makefile
+===================================================================
+--- linux-aed.orig/fs/ext3/Makefile Tue May 4 19:16:51 2004
++++ linux-aed/fs/ext3/Makefile Tue May 4 19:17:12 2004
+@@ -11,7 +11,7 @@
- export-objs := super.o inode.o xattr.o ext3-exports.o
+ export-objs := ext3-exports.o
-obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
-+obj-y := balloc.o iopen.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
++obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
ioctl.o namei.o super.o symlink.o xattr.o hash.o ext3-exports.o
obj-m := $(O_TARGET)
---- linux-2.4.18-p4smp/fs/ext3/inode.c~iopen-2.4.18 2003-07-09 17:11:19.000000000 -0600
-+++ linux-2.4.18-p4smp-braam/fs/ext3/inode.c 2003-07-09 17:13:02.000000000 -0600
+Index: linux-aed/fs/ext3/inode.c
+===================================================================
+--- linux-aed.orig/fs/ext3/inode.c Tue May 4 19:17:09 2004
++++ linux-aed/fs/ext3/inode.c Tue May 4 19:17:12 2004
@@ -31,6 +31,7 @@
#include <linux/highuid.h>
#include <linux/quotaops.h>
/*
* SEARCH_FROM_ZERO forces each block allocation to search from the start
-@@ -2165,6 +2166,9 @@ void ext3_read_inode(struct inode * inod
+@@ -2277,6 +2278,9 @@
struct buffer_head *bh;
int block;
if(ext3_get_inode_loc(inode, &iloc))
goto bad_inode;
bh = iloc.bh;
---- /dev/null 2003-01-30 03:24:37.000000000 -0700
-+++ linux-2.4.18-p4smp-braam/fs/ext3/iopen.c 2003-07-09 17:13:02.000000000 -0600
-@@ -0,0 +1,258 @@
+Index: linux-aed/fs/ext3/iopen.c
+===================================================================
+--- linux-aed.orig/fs/ext3/iopen.c Tue May 4 13:14:35 2004
++++ linux-aed/fs/ext3/iopen.c Tue May 4 19:17:12 2004
+@@ -0,0 +1,282 @@
+/*
+ * linux/fs/ext3/iopen.c
+ *
+
+/* This function is spliced into ext3_lookup and does the move of a
+ * disconnected dentry (if it exists) to a connected dentry.
-+ * Caller must hold dcache_lock.
+ */
-+struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode)
++struct dentry *iopen_connect_dentry(struct dentry *dentry, struct inode *inode,
++ int rehash)
+{
+ struct dentry *tmp, *goal = NULL;
+ struct list_head *lp;
+
++ /* verify this dentry is really new */
++ assert(dentry->d_inode == NULL);
++ assert(list_empty(&dentry->d_alias)); /* d_instantiate */
++ if (rehash)
++ assert(list_empty(&dentry->d_hash)); /* d_rehash */
++ assert(list_empty(&dentry->d_subdirs));
++
++ spin_lock(&dcache_lock);
++ if (!inode)
++ goto do_rehash;
++
+ /* preferrably return a connected dentry */
+ list_for_each(lp, &inode->i_dentry) {
+ tmp = list_entry(lp, struct dentry, d_alias);
+ }
+
+ if (!goal)
-+ return NULL;
++ goto do_instantiate;
+
+ /* Move the goal to the de hash queue - like d_move() */
+ goal->d_flags &= ~DCACHE_NFSD_DISCONNECTED;
+ list_del_init(&goal->d_hash);
+
+ list_del(&goal->d_child);
-+ list_del(&de->d_child);
++ list_del(&dentry->d_child);
+
+ /* Switch the parents and the names.. */
-+ switch_names(goal, de);
-+ do_switch(goal->d_parent, de->d_parent);
-+ do_switch(goal->d_name.len, de->d_name.len);
-+ do_switch(goal->d_name.hash, de->d_name.hash);
++ switch_names(goal, dentry);
++ do_switch(goal->d_parent, dentry->d_parent);
++ do_switch(goal->d_name.len, dentry->d_name.len);
++ do_switch(goal->d_name.hash, dentry->d_name.hash);
+
+ /* And add them back to the (new) parent lists */
+ list_add(&goal->d_child, &goal->d_parent->d_subdirs);
-+ list_add(&de->d_child, &de->d_parent->d_subdirs);
++ list_add(&dentry->d_child, &dentry->d_parent->d_subdirs);
+ __d_rehash(goal, 0);
++ spin_unlock(&dcache_lock);
++ iput(inode);
+
+ return goal;
++
++ /* d_add(), but don't drop dcache_lock before adding dentry to inode */
++do_instantiate:
++ list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */
++ dentry->d_inode = inode;
++do_rehash:
++ if (rehash)
++ __d_rehash(dentry, 0); /* d_rehash */
++ spin_unlock(&dcache_lock);
++
++ return NULL;
+}
+
+/*
+
+ return 1;
+}
---- /dev/null 2003-01-30 03:24:37.000000000 -0700
-+++ linux-2.4.18-p4smp-braam/fs/ext3/iopen.h 2003-07-09 17:13:02.000000000 -0600
+Index: linux-aed/fs/ext3/iopen.h
+===================================================================
+--- linux-aed.orig/fs/ext3/iopen.h Tue May 4 13:14:35 2004
++++ linux-aed/fs/ext3/iopen.h Tue May 4 19:17:12 2004
@@ -0,0 +1,15 @@
+/*
+ * iopen.h
+
+extern int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry);
+extern int ext3_iopen_get_inode(struct inode *inode);
-+extern struct dentry *iopen_connect_dentry(struct dentry *de,
-+ struct inode *inode);
---- linux-2.4.18-p4smp/fs/ext3/namei.c~iopen-2.4.18 2003-07-09 13:32:38.000000000 -0600
-+++ linux-2.4.18-p4smp-braam/fs/ext3/namei.c 2003-07-09 17:13:02.000000000 -0600
++extern struct dentry *iopen_connect_dentry(struct dentry *dentry,
++ struct inode *inode, int rehash);
+Index: linux-aed/fs/ext3/namei.c
+===================================================================
+--- linux-aed.orig/fs/ext3/namei.c Tue May 4 19:17:05 2004
++++ linux-aed/fs/ext3/namei.c Tue May 4 19:17:12 2004
@@ -34,6 +34,7 @@
#include <linux/locks.h>
#include <linux/quotaops.h>
/*
* define how far ahead to read directories while searching them.
-@@ -709,10 +710,14 @@ cleanup_and_exit:
- struct inode * inode;
- struct ext3_dir_entry_2 * de;
- struct buffer_head * bh;
-+ struct dentry *alternate = NULL;
-
+@@ -713,6 +714,9 @@
if (dentry->d_name.len > EXT3_NAME_LEN)
return ERR_PTR(-ENAMETOOLONG);
bh = ext3_find_entry(dentry, &de);
inode = NULL;
if (bh) {
-@@ -723,7 +729,28 @@ static struct dentry *ext3_lookup(struct
+@@ -723,8 +727,8 @@
if (!inode)
return ERR_PTR(-EACCES);
}
- d_add(dentry, inode);
+- return NULL;
+
-+ /* verify this dentry is really new */
-+ assert(!dentry->d_inode);
-+ assert(list_empty(&dentry->d_alias)); /* d_instantiate */
-+ assert(list_empty(&dentry->d_hash)); /* d_rehash */
-+ assert(list_empty(&dentry->d_subdirs));
-+
-+ spin_lock(&dcache_lock);
-+ if (inode && (alternate = iopen_connect_dentry(dentry, inode))) {
-+ spin_unlock(&dcache_lock);
-+ iput(inode);
-+ return alternate;
++ return iopen_connect_dentry(dentry, inode, 1);
+ }
+
+ #define S_SHIFT 12
+@@ -1588,10 +1592,6 @@
+ inode->i_nlink);
+ inode->i_version = ++event;
+ inode->i_nlink = 0;
+- /* There's no need to set i_disksize: the fact that i_nlink is
+- * zero will ensure that the right thing happens during any
+- * recovery. */
+- inode->i_size = 0;
+ ext3_orphan_add(handle, inode);
+ ext3_mark_inode_dirty(handle, inode);
+ dir->i_nlink--;
+@@ -1711,6 +1711,23 @@
+ goto out_stop;
+ }
+
++/* Like ext3_add_nondir() except for call to iopen_connect_dentry */
++static int ext3_add_link(handle_t *handle, struct dentry *dentry,
++ struct inode *inode)
++{
++ int err = ext3_add_entry(handle, dentry, inode);
++ if (!err) {
++ err = ext3_mark_inode_dirty(handle, inode);
++ if (err == 0) {
++ (void)iopen_connect_dentry(dentry, inode, 0);
++ return 0;
++ }
+ }
++ ext3_dec_count(handle, inode);
++ iput(inode);
++ return err;
++}
+
-+ /* d_add(), but don't drop dcache_lock before adding dentry to inode */
-+ if (inode) /* d_instantiate */
-+ list_add(&dentry->d_alias, &inode->i_dentry);
-+ dentry->d_inode = inode;
-+
-+ __d_rehash(dentry, 0); /* d_rehash */
-+ spin_unlock(&dcache_lock);
-+
- return NULL;
- }
+ static int ext3_link (struct dentry * old_dentry,
+ struct inode * dir, struct dentry *dentry)
+ {
+@@ -1736,7 +1753,8 @@
+ ext3_inc_count(handle, inode);
+ atomic_inc(&inode->i_count);
---- linux-2.4.18-p4smp/fs/ext3/super.c~iopen-2.4.18 2003-07-09 13:32:38.000000000 -0600
-+++ linux-2.4.18-p4smp-braam/fs/ext3/super.c 2003-07-09 17:13:02.000000000 -0600
-@@ -831,6 +831,18 @@ static int parse_options (char * options
+- err = ext3_add_nondir(handle, dentry, inode);
++ err = ext3_add_link(handle, dentry, inode);
++ ext3_orphan_del(handle, inode);
+ ext3_mark_inode_dirty(handle, inode);
+ ext3_journal_stop(handle, dir);
+ return err;
+Index: linux-aed/fs/ext3/super.c
+===================================================================
+--- linux-aed.orig/fs/ext3/super.c Tue May 4 19:17:01 2004
++++ linux-aed/fs/ext3/super.c Tue May 4 19:17:12 2004
+@@ -834,6 +834,18 @@
|| !strcmp (this_char, "quota")
|| !strcmp (this_char, "usrquota"))
/* Don't do anything ;-) */ ;
else if (!strcmp (this_char, "journal")) {
/* @@@ FIXME */
/* Eventually we will want to be able to create
---- linux-2.4.18-p4smp/include/linux/ext3_fs.h~iopen-2.4.18 2003-07-09 13:32:38.000000000 -0600
-+++ linux-2.4.18-p4smp-braam/include/linux/ext3_fs.h 2003-07-09 17:13:02.000000000 -0600
-@@ -321,6 +321,8 @@ struct ext3_inode {
+Index: linux-aed/include/linux/ext3_fs.h
+===================================================================
+--- linux-aed.orig/include/linux/ext3_fs.h Tue May 4 19:17:08 2004
++++ linux-aed/include/linux/ext3_fs.h Tue May 4 19:17:12 2004
+@@ -321,6 +321,8 @@
#define EXT3_MOUNT_WRITEBACK_DATA 0x0C00 /* No data ordering */
#define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */
#define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */
#define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */
/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
-
-_
include/linux/ext3_fs.h | 2
8 files changed, 318 insertions(+), 1 deletion(-)
---- linux-2.4.18-p4smp/Documentation/filesystems/ext2.txt~iopen-2.4.18 2003-07-09 12:17:30.000000000 -0600
-+++ linux-2.4.18-p4smp-braam/Documentation/filesystems/ext2.txt 2003-07-09 17:13:02.000000000 -0600
-@@ -35,6 +35,22 @@ resgid=n The group ID which may use th
+Index: linux-aed/Documentation/filesystems/ext2.txt
+===================================================================
+--- linux-aed.orig/Documentation/filesystems/ext2.txt Tue May 4 13:14:35 2004
++++ linux-aed/Documentation/filesystems/ext2.txt Tue May 4 19:17:12 2004
+@@ -35,6 +35,22 @@
sb=n Use alternate superblock at this location.
grpquota,noquota,quota,usrquota Quota options are silently ignored by ext2.
---- linux-2.4.18-p4smp/fs/ext3/Makefile~iopen-2.4.18 2003-07-09 17:12:12.000000000 -0600
-+++ linux-2.4.18-p4smp-braam/fs/ext3/Makefile 2003-07-09 17:13:15.000000000 -0600
-@@ -11,7 +11,7 @@ O_TARGET := ext3.o
+Index: linux-aed/fs/ext3/Makefile
+===================================================================
+--- linux-aed.orig/fs/ext3/Makefile Tue May 4 19:16:51 2004
++++ linux-aed/fs/ext3/Makefile Tue May 4 19:17:12 2004
+@@ -11,7 +11,7 @@
- export-objs := super.o inode.o xattr.o ext3-exports.o
+ export-objs := ext3-exports.o
-obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
-+obj-y := balloc.o iopen.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
++obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
ioctl.o namei.o super.o symlink.o xattr.o ext3-exports.o
obj-m := $(O_TARGET)
---- linux-2.4.18-p4smp/fs/ext3/inode.c~iopen-2.4.18 2003-07-09 17:11:19.000000000 -0600
-+++ linux-2.4.18-p4smp-braam/fs/ext3/inode.c 2003-07-09 17:13:02.000000000 -0600
+Index: linux-aed/fs/ext3/inode.c
+===================================================================
+--- linux-aed.orig/fs/ext3/inode.c Tue May 4 19:17:09 2004
++++ linux-aed/fs/ext3/inode.c Tue May 4 19:17:12 2004
@@ -31,6 +31,7 @@
#include <linux/highuid.h>
#include <linux/quotaops.h>
/*
* SEARCH_FROM_ZERO forces each block allocation to search from the start
-@@ -2165,6 +2166,9 @@ void ext3_read_inode(struct inode * inod
+@@ -2277,6 +2278,9 @@
struct buffer_head *bh;
int block;
if(ext3_get_inode_loc(inode, &iloc))
goto bad_inode;
bh = iloc.bh;
---- /dev/null 2003-01-30 03:24:37.000000000 -0700
-+++ linux-2.4.18-p4smp-braam/fs/ext3/iopen.c 2003-07-09 17:13:02.000000000 -0600
-@@ -0,0 +1,258 @@
+Index: linux-aed/fs/ext3/iopen.c
+===================================================================
+--- linux-aed.orig/fs/ext3/iopen.c Tue May 4 13:14:35 2004
++++ linux-aed/fs/ext3/iopen.c Tue May 4 19:17:12 2004
+@@ -0,0 +1,282 @@
+/*
+ * linux/fs/ext3/iopen.c
+ *
+
+/* This function is spliced into ext3_lookup and does the move of a
+ * disconnected dentry (if it exists) to a connected dentry.
-+ * Caller must hold dcache_lock.
+ */
-+struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode)
++struct dentry *iopen_connect_dentry(struct dentry *dentry, struct inode *inode,
++ int rehash)
+{
+ struct dentry *tmp, *goal = NULL;
+ struct list_head *lp;
+
++ /* verify this dentry is really new */
++ assert(dentry->d_inode == NULL);
++ assert(list_empty(&dentry->d_alias)); /* d_instantiate */
++ if (rehash)
++ assert(list_empty(&dentry->d_hash)); /* d_rehash */
++ assert(list_empty(&dentry->d_subdirs));
++
++ spin_lock(&dcache_lock);
++ if (!inode)
++ goto do_rehash;
++
+ /* preferrably return a connected dentry */
+ list_for_each(lp, &inode->i_dentry) {
+ tmp = list_entry(lp, struct dentry, d_alias);
+ }
+
+ if (!goal)
-+ return NULL;
++ goto do_instantiate;
+
+ /* Move the goal to the de hash queue - like d_move() */
+ goal->d_flags &= ~DCACHE_NFSD_DISCONNECTED;
+ list_del_init(&goal->d_hash);
+
+ list_del(&goal->d_child);
-+ list_del(&de->d_child);
++ list_del(&dentry->d_child);
+
+ /* Switch the parents and the names.. */
-+ switch_names(goal, de);
-+ do_switch(goal->d_parent, de->d_parent);
-+ do_switch(goal->d_name.len, de->d_name.len);
-+ do_switch(goal->d_name.hash, de->d_name.hash);
++ switch_names(goal, dentry);
++ do_switch(goal->d_parent, dentry->d_parent);
++ do_switch(goal->d_name.len, dentry->d_name.len);
++ do_switch(goal->d_name.hash, dentry->d_name.hash);
+
+ /* And add them back to the (new) parent lists */
+ list_add(&goal->d_child, &goal->d_parent->d_subdirs);
-+ list_add(&de->d_child, &de->d_parent->d_subdirs);
++ list_add(&dentry->d_child, &dentry->d_parent->d_subdirs);
+ __d_rehash(goal, 0);
++ spin_unlock(&dcache_lock);
++ iput(inode);
+
+ return goal;
++
++ /* d_add(), but don't drop dcache_lock before adding dentry to inode */
++do_instantiate:
++ list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */
++ dentry->d_inode = inode;
++do_rehash:
++ if (rehash)
++ __d_rehash(dentry, 0); /* d_rehash */
++ spin_unlock(&dcache_lock);
++
++ return NULL;
+}
+
+/*
+
+ return 1;
+}
---- /dev/null 2003-01-30 03:24:37.000000000 -0700
-+++ linux-2.4.18-p4smp-braam/fs/ext3/iopen.h 2003-07-09 17:13:02.000000000 -0600
+Index: linux-aed/fs/ext3/iopen.h
+===================================================================
+--- linux-aed.orig/fs/ext3/iopen.h Tue May 4 13:14:35 2004
++++ linux-aed/fs/ext3/iopen.h Tue May 4 19:17:12 2004
@@ -0,0 +1,15 @@
+/*
+ * iopen.h
+
+extern int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry);
+extern int ext3_iopen_get_inode(struct inode *inode);
-+extern struct dentry *iopen_connect_dentry(struct dentry *de,
-+ struct inode *inode);
---- linux-2.4.18-p4smp/fs/ext3/namei.c~iopen-2.4.18 2003-07-09 13:32:38.000000000 -0600
-+++ linux-2.4.18-p4smp-braam/fs/ext3/namei.c 2003-07-09 17:13:02.000000000 -0600
++extern struct dentry *iopen_connect_dentry(struct dentry *dentry,
++ struct inode *inode, int rehash);
+Index: linux-aed/fs/ext3/namei.c
+===================================================================
+--- linux-aed.orig/fs/ext3/namei.c Tue May 4 19:17:05 2004
++++ linux-aed/fs/ext3/namei.c Tue May 4 19:17:12 2004
@@ -34,6 +34,7 @@
#include <linux/locks.h>
#include <linux/quotaops.h>
/*
* define how far ahead to read directories while searching them.
-@@ -703,10 +704,14 @@ cleanup_and_exit:
- struct inode * inode;
- struct ext3_dir_entry_2 * de;
- struct buffer_head * bh;
-+ struct dentry *alternate = NULL;
-
+@@ -713,6 +714,9 @@
if (dentry->d_name.len > EXT3_NAME_LEN)
return ERR_PTR(-ENAMETOOLONG);
bh = ext3_find_entry(dentry, &de);
inode = NULL;
if (bh) {
-@@ -723,7 +729,28 @@ static struct dentry *ext3_lookup(struct
+@@ -723,8 +727,8 @@
if (!inode)
return ERR_PTR(-EACCES);
}
- d_add(dentry, inode);
+- return NULL;
+
-+ /* verify this dentry is really new */
-+ assert(!dentry->d_inode);
-+ assert(list_empty(&dentry->d_alias)); /* d_instantiate */
-+ assert(list_empty(&dentry->d_hash)); /* d_rehash */
-+ assert(list_empty(&dentry->d_subdirs));
-+
-+ spin_lock(&dcache_lock);
-+ if (inode && (alternate = iopen_connect_dentry(dentry, inode))) {
-+ spin_unlock(&dcache_lock);
-+ iput(inode);
-+ return alternate;
++ return iopen_connect_dentry(dentry, inode, 1);
+ }
+
+ #define S_SHIFT 12
+@@ -1588,10 +1592,6 @@
+ inode->i_nlink);
+ inode->i_version = ++event;
+ inode->i_nlink = 0;
+- /* There's no need to set i_disksize: the fact that i_nlink is
+- * zero will ensure that the right thing happens during any
+- * recovery. */
+- inode->i_size = 0;
+ ext3_orphan_add(handle, inode);
+ ext3_mark_inode_dirty(handle, inode);
+ dir->i_nlink--;
+@@ -1711,6 +1711,23 @@
+ goto out_stop;
+ }
+
++/* Like ext3_add_nondir() except for call to iopen_connect_dentry */
++static int ext3_add_link(handle_t *handle, struct dentry *dentry,
++ struct inode *inode)
++{
++ int err = ext3_add_entry(handle, dentry, inode);
++ if (!err) {
++ err = ext3_mark_inode_dirty(handle, inode);
++ if (err == 0) {
++ (void)iopen_connect_dentry(dentry, inode, 0);
++ return 0;
++ }
+ }
++ ext3_dec_count(handle, inode);
++ iput(inode);
++ return err;
++}
+
-+ /* d_add(), but don't drop dcache_lock before adding dentry to inode */
-+ if (inode) /* d_instantiate */
-+ list_add(&dentry->d_alias, &inode->i_dentry);
-+ dentry->d_inode = inode;
-+
-+ __d_rehash(dentry, 0); /* d_rehash */
-+ spin_unlock(&dcache_lock);
-+
- return NULL;
- }
+ static int ext3_link (struct dentry * old_dentry,
+ struct inode * dir, struct dentry *dentry)
+ {
+@@ -1736,7 +1753,8 @@
+ ext3_inc_count(handle, inode);
+ atomic_inc(&inode->i_count);
---- linux-2.4.18-p4smp/fs/ext3/super.c~iopen-2.4.18 2003-07-09 13:32:38.000000000 -0600
-+++ linux-2.4.18-p4smp-braam/fs/ext3/super.c 2003-07-09 17:13:02.000000000 -0600
-@@ -831,6 +831,18 @@ static int parse_options (char * options
+- err = ext3_add_nondir(handle, dentry, inode);
++ err = ext3_add_link(handle, dentry, inode);
++ ext3_orphan_del(handle, inode);
+ ext3_mark_inode_dirty(handle, inode);
+ ext3_journal_stop(handle, dir);
+ return err;
+Index: linux-aed/fs/ext3/super.c
+===================================================================
+--- linux-aed.orig/fs/ext3/super.c Tue May 4 19:17:01 2004
++++ linux-aed/fs/ext3/super.c Tue May 4 19:17:12 2004
+@@ -834,6 +834,18 @@
|| !strcmp (this_char, "quota")
|| !strcmp (this_char, "usrquota"))
/* Don't do anything ;-) */ ;
else if (!strcmp (this_char, "journal")) {
/* @@@ FIXME */
/* Eventually we will want to be able to create
---- linux-2.4.18-p4smp/include/linux/ext3_fs.h~iopen-2.4.18 2003-07-09 13:32:38.000000000 -0600
-+++ linux-2.4.18-p4smp-braam/include/linux/ext3_fs.h 2003-07-09 17:13:02.000000000 -0600
-@@ -321,6 +321,8 @@ struct ext3_inode {
+Index: linux-aed/include/linux/ext3_fs.h
+===================================================================
+--- linux-aed.orig/include/linux/ext3_fs.h Tue May 4 19:17:08 2004
++++ linux-aed/include/linux/ext3_fs.h Tue May 4 19:17:12 2004
+@@ -321,6 +321,8 @@
#define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */
#define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */
#define EXT3_MOUNT_INDEX 0x4000 /* Enable directory index */
#define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */
/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
-
-_
- Documentation/filesystems/ext2.txt | 16 ++
fs/ext3/inode.c | 3
fs/ext3/iopen.c | 239 +++++++++++++++++++++++++++++++++++++
fs/ext3/iopen.h | 15 ++
include/linux/ext3_fs.h | 2
7 files changed, 304 insertions(+), 1 deletion(-)
-Index: linux-2.6.4-51.1/fs/ext3/inode.c
+Index: linux-stage/fs/ext3/Makefile
===================================================================
---- linux-2.6.4-51.1.orig/fs/ext3/inode.c 2004-04-06 00:31:14.000000000 -0400
-+++ linux-2.6.4-51.1/fs/ext3/inode.c 2004-04-06 00:31:24.000000000 -0400
+--- linux-stage.orig/fs/ext3/Makefile 2004-05-07 16:00:16.000000000 -0400
++++ linux-stage/fs/ext3/Makefile 2004-05-07 16:00:17.000000000 -0400
+@@ -4,7 +4,7 @@
+
+ obj-$(CONFIG_EXT3_FS) += ext3.o
+
+-ext3-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
++ext3-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
+ ioctl.o namei.o super.o symlink.o hash.o
+
+ ext3-$(CONFIG_EXT3_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
+Index: linux-stage/fs/ext3/inode.c
+===================================================================
+--- linux-stage.orig/fs/ext3/inode.c 2004-05-07 16:00:16.000000000 -0400
++++ linux-stage/fs/ext3/inode.c 2004-05-07 17:21:59.000000000 -0400
@@ -37,6 +37,7 @@
#include <linux/mpage.h>
#include <linux/uio.h>
#include "acl.h"
/*
-@@ -2472,6 +2473,8 @@
+@@ -2472,6 +2473,9 @@
ei->i_acl = EXT3_ACL_NOT_CACHED;
ei->i_default_acl = EXT3_ACL_NOT_CACHED;
#endif
+ if (ext3_iopen_get_inode(inode))
+ return;
++
if (ext3_get_inode_loc(inode, &iloc, 0))
goto bad_inode;
bh = iloc.bh;
-Index: linux-2.6.4-51.1/fs/ext3/iopen.c
+Index: linux-stage/fs/ext3/iopen.c
===================================================================
---- linux-2.6.4-51.1.orig/fs/ext3/iopen.c 2004-04-06 00:31:24.000000000 -0400
-+++ linux-2.6.4-51.1/fs/ext3/iopen.c 2004-04-06 00:31:24.000000000 -0400
-@@ -0,0 +1,223 @@
-+
-+
+--- linux-stage.orig/fs/ext3/iopen.c 2004-05-07 16:00:17.000000000 -0400
++++ linux-stage/fs/ext3/iopen.c 2004-05-07 17:22:37.000000000 -0400
+@@ -0,0 +1,272 @@
+/*
+ * linux/fs/ext3/iopen.c
+ *
+ *
+ * This file may be redistributed under the terms of the GNU General
+ * Public License.
++ *
++ *
++ * Invariants:
++ * - there is only ever a single DCACHE_NFSD_DISCONNECTED dentry alias
++ * for an inode at one time.
++ * - there are never both connected and DCACHE_NFSD_DISCONNECTED dentry
++ * aliases on an inode at the same time.
++ *
++ * If we have any connected dentry aliases for an inode, use one of those
++ * in iopen_lookup(). Otherwise, we instantiate a single NFSD_DISCONNECTED
++ * dentry for this inode, which thereafter will be found by the dcache
++ * when looking up this inode number in __iopen__, so we don't return here
++ * until it is gone.
++ *
++ * If we get an inode via a regular name lookup, then we "rename" the
++ * NFSD_DISCONNECTED dentry to the proper name and parent. This ensures
++ * existing users of the disconnected dentry will continue to use the same
++ * dentry as the connected users, and there will never be both kinds of
++ * dentry aliases at one time.
+ */
+
+#include <linux/sched.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/smp_lock.h>
++#include <linux/dcache.h>
++#include <linux/security.h>
+#include "iopen.h"
+
+#ifndef assert
+/*
+ * This implements looking up an inode by number.
+ */
-+static struct dentry *iopen_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
++static struct dentry *iopen_lookup(struct inode * dir, struct dentry *dentry,
++ struct nameidata *nd)
+{
-+ struct inode * inode;
++ struct inode *inode;
+ unsigned long ino;
+ struct list_head *lp;
+ struct dentry *alternate;
+ char buf[IOPEN_NAME_LEN];
-+
++
+ if (dentry->d_name.len >= IOPEN_NAME_LEN)
+ return ERR_PTR(-ENAMETOOLONG);
+
+ return ERR_PTR(-ENOENT);
+ }
+
++ assert(list_empty(&dentry->d_alias)); /* d_instantiate */
++ assert(d_unhashed(dentry)); /* d_rehash */
++
+ /* preferrably return a connected dentry */
+ spin_lock(&dcache_lock);
+ list_for_each(lp, &inode->i_dentry) {
+ return alternate;
+ }
+ dentry->d_flags |= DCACHE_DISCONNECTED;
++
++ /* d_add(), but don't drop dcache_lock before adding dentry to inode */
++ list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */
++ dentry->d_inode = inode;
++
++ __d_rehash(dentry, 0); /* d_rehash */
+ spin_unlock(&dcache_lock);
+
-+ d_add(dentry, inode);
+ return NULL;
+}
+
+ __typeof__ (x) __tmp = x; \
+ x = y; y = __tmp; } while (0)
+
-+static inline void switch_names(struct dentry * dentry, struct dentry * target)
++static inline void switch_names(struct dentry *dentry, struct dentry *target)
+{
+ const unsigned char *old_name, *new_name;
+
+ dentry->d_name.name = old_name;
+}
+
-+
-+struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode)
++/* This function is spliced into ext3_lookup and does the move of a
++ * disconnected dentry (if it exists) to a connected dentry.
++ */
++struct dentry *iopen_connect_dentry(struct dentry *dentry, struct inode *inode,
++ int rehash)
+{
+ struct dentry *tmp, *goal = NULL;
+ struct list_head *lp;
+
-+ /* preferrably return a connected dentry */
-+ spin_lock(&dcache_lock);
+ /* verify this dentry is really new */
-+ assert(!de->d_inode);
-+ assert(list_empty(&de->d_subdirs));
-+ assert(list_empty(&de->d_alias));
++ assert(dentry->d_inode == NULL);
++ assert(list_empty(&dentry->d_alias)); /* d_instantiate */
++ if (rehash)
++ assert(d_unhashed(dentry)); /* d_rehash */
++ assert(list_empty(&dentry->d_subdirs));
+
++ spin_lock(&dcache_lock);
++ if (!inode)
++ goto do_rehash;
+
++ /* preferrably return a connected dentry */
+ list_for_each(lp, &inode->i_dentry) {
+ tmp = list_entry(lp, struct dentry, d_alias);
+ if (tmp->d_flags & DCACHE_DISCONNECTED) {
+ break;
+ }
+ }
-+ spin_unlock(&dcache_lock);
+
+ if (!goal)
-+ return NULL;
++ goto do_instantiate;
+
-+ goal->d_flags &= ~DCACHE_DISCONNECTED;
-+ d_rehash(de);
-+ d_move(goal, de);
++ /* Move the goal to the de hash queue */
++ goal->d_flags &= ~ DCACHE_DISCONNECTED;
++ security_d_instantiate(goal, inode);
++ __d_rehash(dentry, 0);
++ __d_move(goal, dentry);
++ spin_unlock(&dcache_lock);
++ iput(inode);
+
+ return goal;
++
++ /* d_add(), but don't drop dcache_lock before adding dentry to inode */
++do_instantiate:
++ list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */
++ dentry->d_inode = inode;
++do_rehash:
++ if (rehash)
++ __d_rehash(dentry, 0); /* d_rehash */
++ spin_unlock(&dcache_lock);
++
++ return NULL;
+}
+
+/*
+ * This function is spliced into ext3_lookup and returns 1 the file
+ * name is __iopen__ and dentry has been filled in appropriately.
+ */
-+int ext3_check_for_iopen(struct inode * dir, struct dentry *dentry)
++int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry)
+{
-+ struct inode * inode;
++ struct inode *inode;
+
+ if (dir->i_ino != EXT3_ROOT_INO ||
+ !test_opt(dir->i_sb, IOPEN) ||
+ * number is the one for /__iopen__, in which case the inode is filled
+ * in appropriately. Otherwise, this fuction returns 0.
+ */
-+int ext3_iopen_get_inode(struct inode * inode)
++int ext3_iopen_get_inode(struct inode *inode)
+{
+ if (inode->i_ino != EXT3_BAD_INO)
+ return 0;
+
+ return 1;
+}
-Index: linux-2.6.4-51.1/fs/ext3/iopen.h
+Index: linux-stage/fs/ext3/iopen.h
===================================================================
---- linux-2.6.4-51.1.orig/fs/ext3/iopen.h 2004-04-06 00:31:24.000000000 -0400
-+++ linux-2.6.4-51.1/fs/ext3/iopen.h 2004-04-06 00:31:24.000000000 -0400
+--- linux-stage.orig/fs/ext3/iopen.h 2004-05-07 16:00:17.000000000 -0400
++++ linux-stage/fs/ext3/iopen.h 2004-05-07 16:00:17.000000000 -0400
@@ -0,0 +1,15 @@
+/*
+ * iopen.h
+ * Public License.
+ */
+
-+extern int ext3_check_for_iopen(struct inode * dir, struct dentry *dentry);
-+extern int ext3_iopen_get_inode(struct inode * inode);
-+
-+
-Index: linux-2.6.4-51.1/fs/ext3/namei.c
++extern int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry);
++extern int ext3_iopen_get_inode(struct inode *inode);
++extern struct dentry *iopen_connect_dentry(struct dentry *dentry,
++ struct inode *inode, int rehash);
+Index: linux-stage/fs/ext3/namei.c
===================================================================
---- linux-2.6.4-51.1.orig/fs/ext3/namei.c 2004-04-06 00:31:11.000000000 -0400
-+++ linux-2.6.4-51.1/fs/ext3/namei.c 2004-04-06 00:31:24.000000000 -0400
+--- linux-stage.orig/fs/ext3/namei.c 2004-05-07 16:00:16.000000000 -0400
++++ linux-stage/fs/ext3/namei.c 2004-05-07 16:00:17.000000000 -0400
@@ -37,6 +37,7 @@
#include <linux/buffer_head.h>
#include <linux/smp_lock.h>
#include "acl.h"
/*
-@@ -970,15 +971,21 @@
- }
- #endif
-
-+struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode);
-+
- static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
- {
- struct inode * inode;
- struct ext3_dir_entry_2 * de;
- struct buffer_head * bh;
-+ struct dentry *alternate = NULL;
-
+@@ -979,6 +980,9 @@
if (dentry->d_name.len > EXT3_NAME_LEN)
return ERR_PTR(-ENAMETOOLONG);
-+ if (ext3_check_for_iopen(dir, dentry))
-+ return NULL;
++ if (ext3_check_for_iopen(dir, dentry))
++ return NULL;
+
bh = ext3_find_entry(dentry, &de);
inode = NULL;
if (bh) {
-@@ -989,8 +996,14 @@
+@@ -989,10 +993,8 @@
if (!inode)
return ERR_PTR(-EACCES);
}
-+ if (inode && (alternate = iopen_connect_dentry(dentry, inode))) {
-+ iput(inode);
-+ return alternate;
-+ }
+- if (inode)
+- return d_splice_alias(inode, dentry);
+- d_add(dentry, inode);
+- return NULL;
+
- if (inode)
- return d_splice_alias(inode, dentry);
++ return iopen_connect_dentry(dentry, inode, 1);
+ }
+
+
+@@ -2019,10 +2021,6 @@
+ inode->i_nlink);
+ inode->i_version++;
+ inode->i_nlink = 0;
+- /* There's no need to set i_disksize: the fact that i_nlink is
+- * zero will ensure that the right thing happens during any
+- * recovery. */
+- inode->i_size = 0;
+ ext3_orphan_add(handle, inode);
+ inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ ext3_mark_inode_dirty(handle, inode);
+@@ -2139,6 +2137,23 @@
+ return err;
+ }
+
++/* Like ext3_add_nondir() except for call to iopen_connect_dentry */
++static int ext3_add_link(handle_t *handle, struct dentry *dentry,
++ struct inode *inode)
++{
++ int err = ext3_add_entry(handle, dentry, inode);
++ if (!err) {
++ err = ext3_mark_inode_dirty(handle, inode);
++ if (err == 0) {
++ (void)iopen_connect_dentry(dentry, inode, 0);
++ return 0;
++ }
++ }
++ ext3_dec_count(handle, inode);
++ iput(inode);
++ return err;
++}
+
- d_add(dentry, inode);
- return NULL;
+ static int ext3_link (struct dentry * old_dentry,
+ struct inode * dir, struct dentry *dentry)
+ {
+@@ -2161,7 +2176,8 @@
+ ext3_inc_count(handle, inode);
+ atomic_inc(&inode->i_count);
+
+- err = ext3_add_nondir(handle, dentry, inode);
++ err = ext3_add_link(handle, dentry, inode);
++ ext3_orphan_del(handle,inode);
+ ext3_journal_stop(handle);
+ return err;
}
-Index: linux-2.6.4-51.1/fs/ext3/super.c
+Index: linux-stage/fs/ext3/super.c
===================================================================
---- linux-2.6.4-51.1.orig/fs/ext3/super.c 2004-04-06 00:31:14.000000000 -0400
-+++ linux-2.6.4-51.1/fs/ext3/super.c 2004-04-06 00:31:24.000000000 -0400
+--- linux-stage.orig/fs/ext3/super.c 2004-05-07 16:00:16.000000000 -0400
++++ linux-stage/fs/ext3/super.c 2004-05-07 17:21:59.000000000 -0400
@@ -536,7 +536,7 @@
Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, Opt_noload,
Opt_commit, Opt_journal_update, Opt_journal_inum,
set_opt(sbi->s_mount_opt, ABORT);
break;
+ case Opt_iopen:
-+ set_opt (sbi->s_mount_opt, IOPEN);
-+ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
++ set_opt (sbi->s_mount_opt, IOPEN);
++ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
+ break;
+ case Opt_noiopen:
+ clear_opt (sbi->s_mount_opt, IOPEN);
-+ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
++ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
+ break;
+ case Opt_iopen_nopriv:
-+ set_opt (sbi->s_mount_opt, IOPEN);
-+ set_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
++ set_opt (sbi->s_mount_opt, IOPEN);
++ set_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
+ break;
case Opt_ignore:
break;
default:
-Index: linux-2.6.4-51.1/include/linux/ext3_fs.h
+Index: linux-stage/include/linux/ext3_fs.h
===================================================================
---- linux-2.6.4-51.1.orig/include/linux/ext3_fs.h 2004-04-06 00:31:11.000000000 -0400
-+++ linux-2.6.4-51.1/include/linux/ext3_fs.h 2004-04-06 00:31:24.000000000 -0400
+--- linux-stage.orig/include/linux/ext3_fs.h 2004-05-07 16:00:16.000000000 -0400
++++ linux-stage/include/linux/ext3_fs.h 2004-05-07 16:00:17.000000000 -0400
@@ -325,6 +325,8 @@
#define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */
#define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
#ifndef _LINUX_EXT2_FS_H
-Index: linux-2.6.4-51.1/fs/ext3/Makefile
-===================================================================
---- linux-2.6.4-51.1.orig/fs/ext3/Makefile 2004-04-06 00:27:21.000000000 -0400
-+++ linux-2.6.4-51.1/fs/ext3/Makefile 2004-04-06 00:31:42.000000000 -0400
-@@ -5,7 +5,7 @@
- obj-$(CONFIG_EXT3_FS) += ext3.o
-
- ext3-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
-- ioctl.o namei.o super.o symlink.o hash.o
-+ ioctl.o namei.o super.o symlink.o hash.o iopen.o
-
- ext3-$(CONFIG_EXT3_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
- ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o
-Index: linux-2.6.0/Documentation/filesystems/ext2.txt
+Index: linux-2.6.4-51.0/Documentation/filesystems/ext2.txt
===================================================================
---- linux-2.6.0.orig/Documentation/filesystems/ext2.txt 2002-11-11 06:28:06.000000000 +0300
-+++ linux-2.6.0/Documentation/filesystems/ext2.txt 2004-01-07 17:12:07.000000000 +0300
+--- linux-2.6.4-51.0.orig/Documentation/filesystems/ext2.txt 2004-05-06 22:21:26.000000000 -0400
++++ linux-2.6.4-51.0/Documentation/filesystems/ext2.txt 2004-05-06 22:24:42.000000000 -0400
@@ -35,6 +35,22 @@
sb=n Use alternate superblock at this location.
grpquota,noquota,quota,usrquota Quota options are silently ignored by ext2.
+Index: linux-2.6.4-51.0/fs/dcache.c
+===================================================================
+--- linux-2.6.4-51.0.orig/fs/dcache.c 2004-05-06 22:24:42.000000000 -0400
++++ linux-2.6.4-51.0/fs/dcache.c 2004-05-06 22:58:37.000000000 -0400
+@@ -1195,12 +1195,11 @@
+ * dcache entries should not be moved in this way.
+ */
+
+-void d_move(struct dentry * dentry, struct dentry * target)
++void __d_move(struct dentry * dentry, struct dentry * target)
+ {
+ if (!dentry->d_inode)
+ printk(KERN_WARNING "VFS: moving negative dcache entry\n");
+
+- spin_lock(&dcache_lock);
+ write_seqlock(&rename_lock);
+ /*
+ * XXXX: do we really need to take target->d_lock?
+@@ -1253,6 +1252,14 @@
+ spin_unlock(&target->d_lock);
+ spin_unlock(&dentry->d_lock);
+ write_sequnlock(&rename_lock);
++}
++
++EXPORT_SYMBOL(__d_move);
++
++void d_move(struct dentry *dentry, struct dentry *target)
++{
++ spin_lock(&dcache_lock);
++ __d_move(dentry, target);
+ spin_unlock(&dcache_lock);
+ }
+
+Index: linux-2.6.4-51.0/include/linux/dcache.h
+===================================================================
+--- linux-2.6.4-51.0.orig/include/linux/dcache.h 2004-05-06 22:24:42.000000000 -0400
++++ linux-2.6.4-51.0/include/linux/dcache.h 2004-05-06 23:03:43.000000000 -0400
+@@ -234,6 +234,7 @@
+ * This adds the entry to the hash queues.
+ */
+ extern void d_rehash(struct dentry *);
++extern void __d_rehash(struct dentry *, int lock);
+
+ /**
+ * d_add - add dentry to hash queues
+@@ -252,6 +253,7 @@
+
+ /* used for rename() and baskets */
+ extern void d_move(struct dentry *, struct dentry *);
++extern void __d_move(struct dentry *, struct dentry *);
+
+ /* appendix may either be NULL or be used for transname suffixes */
+ extern struct dentry * d_lookup(struct dentry *, struct qstr *);
-
-
+Version 36: don't dput dentry in link_path_walk_it after lookup error (b=2350)
+Version 35: pass intent to real_lookup after revalidate failure (b=3285)
+Version 34: fix ext3 iopen assertion failure (b=2517, b=2399)
include/linux/lustre_version.h | 1 +
1 files changed, 1 insertion(+)
--- /dev/null Fri Aug 30 17:31:37 2002
+++ linux-2.4.18-18.8.0-l12-braam/include/linux/lustre_version.h Thu Feb 13 07:58:33 2003
@@ -0,0 +1 @@
-+#define LUSTRE_KERNEL_VERSION 35
++#define LUSTRE_KERNEL_VERSION 36
_
+ break;
+ new = real_lookup(dentry->d_parent,
+ &dentry->d_name, 0, it);
-+ d_invalidate(dentry);
-+ dput(dentry);
+ if (IS_ERR(new)) {
+ err = PTR_ERR(new);
+ break;
+ }
++ d_invalidate(dentry);
++ dput(dentry);
+ nd->dentry = new;
+ }
+ if (!nd->dentry->d_inode)
+ break;
+ new = real_lookup(dentry->d_parent,
+ &dentry->d_name, 0, it);
-+ d_invalidate(dentry);
-+ dput(dentry);
+ if (IS_ERR(new)) {
+ err = PTR_ERR(new);
+ break;
+ }
++ d_invalidate(dentry);
++ dput(dentry);
+ nd->dentry = new;
+ }
+ } else
+ break;
+ new = real_lookup(dentry->d_parent,
+ &dentry->d_name, 0, it);
-+ d_invalidate(dentry);
-+ dput(dentry);
+ if (IS_ERR(new)) {
+ err = PTR_ERR(new);
+ break;
+ }
++ d_invalidate(dentry);
++ dput(dentry);
+ nd->dentry = new;
+ }
+ } else
+ break;
+ new = real_lookup(dentry->d_parent,
+ &dentry->d_name, 0, it);
-+ d_invalidate(dentry);
-+ dput(dentry);
+ if (IS_ERR(new)) {
+ err = PTR_ERR(new);
+ break;
+ }
++ d_invalidate(dentry);
++ dput(dentry);
+ nd->dentry = new;
+ }
+ if (!nd->dentry->d_inode)
+ break;
+ new = real_lookup(dentry->d_parent,
+ &dentry->d_name, 0, it);
-+ d_invalidate(dentry);
-+ dput(dentry);
+ if (IS_ERR(new)) {
+ err = PTR_ERR(new);
+ break;
+ }
++ d_invalidate(dentry);
++ dput(dentry);
+ nd->dentry = new;
+ }
+ if (!nd->dentry->d_inode)
+ break;
+ new = real_lookup(dentry->d_parent,
+ &dentry->d_name, 0, it);
-+ d_invalidate(dentry);
-+ dput(dentry);
+ if (IS_ERR(new)) {
+ err = PTR_ERR(new);
+ break;
+ }
++ d_invalidate(dentry);
++ dput(dentry);
+ nd->dentry = new;
+ }
+ if (!nd->dentry->d_inode)
+ break;
+ new = real_lookup(dentry->d_parent,
+ &dentry->d_name, 0, it);
-+ d_invalidate(dentry);
-+ dput(dentry);
+ if (IS_ERR(new)) {
+ err = PTR_ERR(new);
+ break;
+ }
++ d_invalidate(dentry);
++ dput(dentry);
+ nd->dentry = new;
+ }
+ if (!nd->dentry->d_inode)
+ break;
+ new = real_lookup(dentry->d_parent,
+ &dentry->d_name, 0, it);
-+ d_invalidate(dentry);
-+ dput(dentry);
+ if (IS_ERR(new)) {
+ err = PTR_ERR(new);
+ break;
+ }
++ d_invalidate(dentry);
++ dput(dentry);
+ nd->dentry = new;
+ }
+ } else
+ break;
+ new = real_lookup(dentry->d_parent,
+ &dentry->d_name, 0, it);
-+ d_invalidate(dentry);
-+ dput(dentry);
+ if (IS_ERR(new)) {
+ err = PTR_ERR(new);
+ break;
+ }
++ d_invalidate(dentry);
++ dput(dentry);
+ nd->dentry = new;
+ }
+ if (!nd->dentry->d_inode)
+ break;
+ new = real_lookup(dentry->d_parent,
+ &dentry->d_name, 0, it);
-+ d_invalidate(dentry);
-+ dput(dentry);
+ if (IS_ERR(new)) {
+ err = PTR_ERR(new);
+ break;
+ }
++ d_invalidate(dentry);
++ dput(dentry);
+ nd->dentry = new;
+ }
+ } else
}
}
return result;
-@@ -563,6 +580,31 @@
+@@ -563,6 +580,33 @@
return PTR_ERR(dentry);
}
+ if ((err = permission(dentry->d_parent->d_inode, MAY_EXEC, nd)))
+ return err;
+ new = real_lookup(dentry->d_parent, &dentry->d_name, nd);
++ if (IS_ERR(new))
++ return PTR_ERR(new);
+ d_invalidate(dentry);
+ dput(dentry);
+ nd->dentry = dentry = new;
int rq_portal, rp_portal, connect_op;
char *name = obddev->obd_type->typ_name;
char *mgmt_name = NULL;
- int rc = 0;
+ int rc;
struct obd_device *mgmt_obd;
mgmtcli_register_for_events_t register_f;
ENTRY;
cli->cl_max_pages_per_rpc = PTLRPC_MAX_BRW_PAGES;
cli->cl_max_rpcs_in_flight = OSC_MAX_RIF_DEFAULT;
- ldlm_get_ref();
+ rc = ldlm_get_ref();
if (rc) {
CERROR("ldlm_get_ref failed: %d\n", rc);
GOTO(err, rc);
rc = kernel_thread(ldlm_bl_thread_main, &bltd, 0);
if (rc < 0) {
CERROR("cannot start LDLM thread #%d: rc %d\n", i, rc);
- LBUG();
GOTO(out_thread, rc);
}
wait_for_completion(&blp->blp_comp);
rc = ptlrpc_start_n_threads(NULL, ldlm_state->ldlm_cancel_service,
LDLM_NUM_THREADS, "ldlm_cn");
- if (rc) {
- LBUG();
+ if (rc)
GOTO(out_thread, rc);
- }
rc = ptlrpc_start_n_threads(NULL, ldlm_state->ldlm_cb_service,
LDLM_NUM_THREADS, "ldlm_cb");
- if (rc) {
- LBUG();
+ if (rc)
GOTO(out_thread, rc);
- }
INIT_LIST_HEAD(&expired_lock_thread.elt_expired_locks);
spin_lock_init(&expired_lock_thread.elt_lock);
unsigned long count, void *data)
{
struct ldlm_namespace *ns = data;
- char dummy[MAX_STRING_SIZE + 1];
+ char dummy[MAX_STRING_SIZE + 1], *end;
unsigned long tmp;
dummy[MAX_STRING_SIZE] = '\0';
return count;
}
- tmp = simple_strtoul(dummy, NULL, 0);
+ tmp = simple_strtoul(dummy, &end, 0);
+ if (tmp == 0 && *end) {
+ CERROR("invalid value written\n");
+ return -EINVAL;
+ }
+
CDEBUG(D_DLMTRACE, "changing namespace %s max_unused from %u to %u\n",
ns->ns_name, ns->ns_max_unused, (unsigned int)tmp);
ns->ns_max_unused = (unsigned int)tmp;
int rc, valid;
ENTRY;
- valid = OBD_MD_FLID;
+ obdo.o_id = lli->lli_st_ino;
+ obdo.o_valid = OBD_MD_FLID;
+ valid = OBD_MD_FLTYPE | OBD_MD_FLMODE | OBD_MD_FLSIZE |OBD_MD_FLBLOCKS |
+ OBD_MD_FLATIME | OBD_MD_FLMTIME | OBD_MD_FLCTIME;
if (test_bit(LLI_F_HAVE_OST_SIZE_LOCK, &lli->lli_flags))
valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS;
- memset(&obdo, 0, sizeof(obdo));
- obdo.o_id = lli->lli_st_ino;
- obdo.o_mode = lli->lli_st_mode;
- obdo.o_size = lli->lli_st_size;
- obdo.o_blocks = lli->lli_st_blocks;
+ obdo_from_inode(&obdo, inode, valid);
+
if (0 /* ll_is_inode_dirty(inode) */) {
obdo.o_flags = MDS_BFLAG_UNCOMMITTED_WRITES;
- valid |= OBD_MD_FLFLAGS;
+ obdo.o_valid |= OBD_MD_FLFLAGS;
}
- obdo.o_valid = valid;
rc = mdc_close(mdc_exp, &obdo, och, &req);
if (rc == EAGAIN) {
/* We are the last writer, so the MDS has instructed us to get
//ll_queue_done_writing(inode);
rc = 0;
} else if (rc) {
- CERROR("inode %lu close failed: rc = %d\n", lli->lli_st_ino, rc);
+ CERROR("inode %lu close failed: rc %d\n", lli->lli_st_ino, rc);
} else {
rc = llu_objects_destroy(req, inode);
if (rc)
ctxt->gid1 = -1;
if (i2) {
- lli2 = llu_i2info(i2);
+ lli2 = llu_i2info(i2);
if (in_group_p(lli2->lli_st_gid))
ctxt->gid2 = lli2->lli_st_gid;
else
ctxt->gid2 = -1;
- } else
- ctxt->gid2 = 0;
+ } else {
+ ctxt->gid2 = -1;
+ }
}
EXIT;
}
+/* should NOT be called with the dcache lock, see fs/dcache.c */
+static int ll_ddelete(struct dentry *de)
+{
+ ENTRY;
+ LASSERT(de);
+ CDEBUG(D_DENTRY, "%s dentry %*s (%p, parent %p, inode %p) %s%s\n",
+ (de->d_flags & DCACHE_LUSTRE_INVALID ? "keeping" : "deleting"),
+ de->d_name.len, de->d_name.name, de, de->d_parent, de->d_inode,
+ d_unhashed(de) ? "" : "hashed,",
+ list_empty(&de->d_subdirs) ? "" : "subdirs");
+ //RETURN(de->d_flags & DCACHE_LUSTRE_INVALID);
+ RETURN(0);
+}
+
void ll_set_dd(struct dentry *de)
{
ENTRY;
LASSERT(de != NULL);
+ CDEBUG(D_DENTRY, "ldd on dentry %*s (%p) parent %p inode %p refc %d\n",
+ de->d_name.len, de->d_name.name, de, de->d_parent, de->d_inode,
+ atomic_read(&de->d_count));
lock_kernel();
if (de->d_fsdata == NULL) {
OBD_ALLOC(de->d_fsdata, sizeof(struct ll_dentry_data));
struct ll_sb_info *sbi;
ENTRY;
- sbi = ll_i2sbi(inode);
-
- CDEBUG(D_INODE, "marking dentries for ino %lu/%u(%p) invalid\n",
- inode->i_ino, inode->i_generation, inode);
-
if (inode == NULL) {
CERROR("unexpected NULL inode, tell phil\n");
return;
}
+
+ CDEBUG(D_INODE, "marking dentries for ino %lu/%u(%p) invalid\n",
+ inode->i_ino, inode->i_generation, inode);
+
+ sbi = ll_i2sbi(inode);
head = &inode->i_dentry;
restart:
spin_lock(&dcache_lock);
tmp = head;
while ((tmp = tmp->next) != head) {
struct dentry *dentry = list_entry(tmp, struct dentry, d_alias);
- if (!atomic_read(&dentry->d_count)) {
+ if (atomic_read(&dentry->d_count) == 0) {
+ CDEBUG(D_DENTRY, "deleting dentry %*s (%p) parent %p "
+ "inode %p\n", dentry->d_name.len,
+ dentry->d_name.name, dentry, dentry->d_parent,
+ dentry->d_inode);
dget_locked(dentry);
__d_drop(dentry);
spin_unlock(&dcache_lock);
dput(dentry);
goto restart;
- } else {
+ } else if (!(dentry->d_flags & DCACHE_LUSTRE_INVALID)) {
+ CDEBUG(D_DENTRY, "unhashing dentry %*s (%p) parent %p "
+ "inode %p refc %d\n", dentry->d_name.len,
+ dentry->d_name.name, dentry, dentry->d_parent,
+ dentry->d_inode, atomic_read(&dentry->d_count));
hlist_del_init(&dentry->d_hash);
dentry->d_flags |= DCACHE_LUSTRE_INVALID;
hlist_add_head(&dentry->d_hash,
ptlrpc_req_finished(req);
if (rc == 0) {
ll_unhash_aliases(de->d_inode);
- de->d_flags |= DCACHE_LUSTRE_INVALID;
+ /* done in ll_unhash_aliases()
+ dentry->d_flags |= DCACHE_LUSTRE_INVALID; */
} else {
+ CDEBUG(D_DENTRY, "revalidated dentry %*s (%p) parent %p "
+ "inode %p refc %d\n", de->d_name.len,
+ de->d_name.name, de, de->d_parent, de->d_inode,
+ atomic_read(&de->d_count));
ll_lookup_finish_locks(it, de);
de->d_flags &= ~DCACHE_LUSTRE_INVALID;
}
.d_revalidate_it = ll_revalidate_it,
#endif
.d_release = ll_release,
+ .d_delete = ll_ddelete,
#if 0
.d_pin = ll_pin,
.d_unpin = ll_unpin,
int ll_dir_open(struct inode *inode, struct file *file)
{
- return ll_file_open(inode, file);
+ ENTRY;
+ RETURN(ll_file_open(inode, file));
}
int ll_dir_release(struct inode *inode, struct file *file)
{
- return ll_file_release(inode, file);
+ ENTRY;
+ RETURN(ll_file_release(inode, file));
}
struct file_operations ll_dir_operations = {
struct ptlrpc_request *req = NULL;
struct obd_client_handle *och = &fd->fd_mds_och;
struct obdo obdo;
- int rc, valid;
+ int rc;
ENTRY;
- valid = OBD_MD_FLID;
-
- memset(&obdo, 0, sizeof(obdo));
obdo.o_id = inode->i_ino;
- obdo.o_mode = inode->i_mode;
- obdo.o_size = inode->i_size;
- obdo.o_blocks = inode->i_blocks;
+ obdo.o_valid = OBD_MD_FLID;
+ obdo_from_inode(&obdo, inode, OBD_MD_FLTYPE | OBD_MD_FLMODE |
+ OBD_MD_FLSIZE | OBD_MD_FLBLOCKS |
+ OBD_MD_FLATIME | OBD_MD_FLMTIME |
+ OBD_MD_FLCTIME);
if (0 /* ll_is_inode_dirty(inode) */) {
obdo.o_flags = MDS_BFLAG_UNCOMMITTED_WRITES;
- valid |= OBD_MD_FLFLAGS;
+ obdo.o_valid |= OBD_MD_FLFLAGS;
}
- obdo.o_valid = valid;
rc = mdc_close(mdc_exp, &obdo, och, &req);
if (rc == EAGAIN) {
/* We are the last writer, so the MDS has instructed us to get
spin_lock(&dcache_lock);
hlist_for_each_safe(tmp, next, &sbi->ll_orphan_dentry_list) {
struct dentry *dentry = hlist_entry(tmp, struct dentry, d_hash);
+ CWARN("orphan dentry %*s (%p) at unmount\n",
+ dentry->d_name.len, dentry->d_name.name, dentry);
shrink_dcache_parent(dentry);
}
spin_unlock(&dcache_lock);
}
-#if 0
-static int ll_rd_path(char *page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-#endif
-
static int ll_rd_fstype(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
md->body->ino, md->body->generation);
}
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+ if (inode->i_ino != md->body->ino)
+ return 0;
+#endif
if (inode->i_generation != md->body->generation)
return 0;
atomic_inc(&dentry->d_count);
iput(inode);
dentry->d_flags &= ~DCACHE_LUSTRE_INVALID;
+ CDEBUG(D_DENTRY, "alias dentry %*s (%p) parent %p inode %p "
+ "refc %d\n", de->d_name.len, de->d_name.name, de,
+ de->d_parent, de->d_inode, atomic_read(&de->d_count));
return dentry;
}
void mdc_rename_pack(struct ptlrpc_request *req, int offset,
struct mdc_op_data *data,
const char *old, int oldlen, const char *new, int newlen);
+void mdc_close_pack(struct ptlrpc_request *req, int offset, struct obdo *oa,
+ int valid, struct obd_client_handle *och);
struct mdc_open_data {
struct obd_client_handle *mod_och;
}
}
+void mdc_close_pack(struct ptlrpc_request *req, int offset, struct obdo *oa,
+ int valid, struct obd_client_handle *och)
+{
+ struct mds_body *body;
+
+ body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof(*body));
+
+ mdc_pack_fid(&body->fid1, oa->o_id, 0, oa->o_mode);
+ memcpy(&body->handle, &och->och_fh, sizeof(body->handle));
+ if (oa->o_valid & OBD_MD_FLATIME) {
+ body->atime = oa->o_atime;
+ body->valid |= OBD_MD_FLATIME;
+ }
+ if (oa->o_valid & OBD_MD_FLMTIME) {
+ body->mtime = oa->o_mtime;
+ body->valid |= OBD_MD_FLMTIME;
+ }
+ if (oa->o_valid & OBD_MD_FLCTIME) {
+ body->ctime = oa->o_ctime;
+ body->valid |= OBD_MD_FLCTIME;
+ }
+ if (oa->o_valid & OBD_MD_FLSIZE) {
+ body->size = oa->o_size;
+ body->valid |= OBD_MD_FLSIZE;
+ }
+ if (oa->o_valid & OBD_MD_FLBLOCKS) {
+ body->blocks = oa->o_blocks;
+ body->valid |= OBD_MD_FLBLOCKS;
+ }
+ if (oa->o_valid & OBD_MD_FLFLAGS) {
+ body->flags = oa->o_flags;
+ body->valid |= OBD_MD_FLFLAGS;
+ }
+}
ENTRY;
LASSERT(it);
- CDEBUG(D_DLMTRACE, "name: %*s in %ld, intent: %s\n", len, name,
+ CDEBUG(D_DLMTRACE, "name: %*s in inode %ld, intent: %s\n", len, name,
(unsigned long)pfid->id, ldlm_it2str(it->it_op));
if (cfid && (it->it_op == IT_LOOKUP || it->it_op == IT_GETATTR)) {
return 0;
}
-int mdc_close(struct obd_export *exp, struct obdo *obdo,
+int mdc_close(struct obd_export *exp, struct obdo *oa,
struct obd_client_handle *och, struct ptlrpc_request **request)
{
- struct mds_body *body;
struct obd_device *obd = class_exp2obd(exp);
- int reqsize = sizeof(*body);
- int rc, repsize[3] = {sizeof(*body),
+ int reqsize = sizeof(struct mds_body);
+ int rc, repsize[3] = {sizeof(struct mds_body),
obd->u.cli.cl_max_mds_easize,
obd->u.cli.cl_max_mds_cookiesize};
struct ptlrpc_request *req;
CDEBUG(D_HA, "couldn't find open req; expecting close error\n");
}
- body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof(*body));
- mdc_pack_fid(&body->fid1, obdo->o_id, 0, obdo->o_mode);
- memcpy(&body->handle, &och->och_fh, sizeof(body->handle));
- body->size = obdo->o_size;
- body->blocks = obdo->o_blocks;
- body->flags = obdo->o_flags;
- body->valid = obdo->o_valid;
+ mdc_close_pack(req, 0, oa, oa->o_valid, och);
req->rq_replen = lustre_msg_size(3, repsize);
req->rq_commit_cb = mdc_commit_close;
if (req->rq_repmsg == NULL) {
CDEBUG(D_HA, "request failed to send: %p, %d\n", req,
req->rq_status);
- rc = req->rq_status ? req->rq_status : -EIO;
+ if (rc == 0)
+ rc = req->rq_status ? req->rq_status : -EIO;
} else if (rc == 0) {
rc = req->rq_repmsg->status;
if (req->rq_repmsg->type == PTL_RPC_MSG_ERR) {
list_del(&mfd->mfd_list);
spin_unlock(&med->med_open_lock);
+ /* If you change this message, be sure to update
+ * replay_single:test_46 */
CERROR("force closing client file handle for %*s (%s:%lu)\n",
dentry->d_name.len, dentry->d_name.name,
ll_bdevname(dentry->d_inode->i_sb, btmp),
obd = req->rq_export->exp_obd;
mds = &obd->u.mds;
+
+ /* sanity check: if the xid matches, the request must
+ * be marked as a resent or replayed */
+ if (req->rq_xid == med->med_mcd->mcd_last_xid)
+ LASSERTF(lustre_msg_get_flags(req->rq_reqmsg) &
+ (MSG_RESENT | MSG_REPLAY),
+ "rq_xid "LPU64" matches last_xid, "
+ "expected RESENT flag\n",
+ req->rq_xid);
+ /* else: note the opposite is not always true; a
+ * RESENT req after a failover will usually not match
+ * the last_xid, since it was likely never
+ * committed. A REPLAYed request will almost never
+ * match the last xid, however it could for a
+ * committed, but still retained, open. */
+
/* Check for aborted recovery. */
spin_lock_bh(&obd->obd_processing_task_lock);
abort_recovery = obd->obd_abort_recovery;
}
l_unlock(&obd->obd_namespace->ns_lock);
+ /* If the xid matches, then we know this is a resent request,
+ * and allow it. (It's probably an OPEN, for which we don't
+ * send a lock */
+ if (req->rq_xid == exp->exp_mds_data.med_mcd->mcd_last_xid)
+ return;
+
/* This remote handle isn't enqueued, so we never received or
* processed this request. Clear MSG_RESENT, because it can
* be handled like any normal request now. */
#include <linux/lustre_mds.h>
+#define MAX_ATIME_DIFF 60
+
struct mds_filter_data {
__u64 io_epoch;
};
RETURN(-ENOMEM);
oti.oti_objid = *ids;
- if (*handle == NULL)
- *handle = fsfilt_start(obd, inode, FSFILT_OP_CREATE, NULL);
- if (IS_ERR(*handle)) {
- rc = PTR_ERR(*handle);
- *handle = NULL;
- GOTO(out_ids, rc);
- }
-
/* replay case */
if(lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY) {
LASSERT (rec->ur_fid2->id);
lmm = rec->ur_eadata;
LASSERT(lmm);
+ if (*handle == NULL)
+ *handle = fsfilt_start(obd,inode,FSFILT_OP_CREATE,NULL);
+ if (IS_ERR(*handle)) {
+ rc = PTR_ERR(*handle);
+ *handle = NULL;
+ GOTO(out_ids, rc);
+ }
+
mds_objids_from_lmm(*ids, lmm, &mds->mds_lov_desc);
lmm_buf = lustre_msg_buf(req->rq_repmsg, offset, 0);
lmm, &lmm_size, 1);
if (rc > 0)
rc = obd_iocontrol(OBD_IOC_LOV_SETSTRIPE,
- mds->mds_osc_exp,
+ mds->mds_osc_exp,
0, &lsm, lmm);
OBD_FREE(lmm, mds->mds_max_mdsize);
if (rc)
LASSERT(rc >= 0);
lmm_size = rc;
body->eadatasize = rc;
+
+ if (*handle == NULL)
+ *handle = fsfilt_start(obd, inode, FSFILT_OP_CREATE, NULL);
+ if (IS_ERR(*handle)) {
+ rc = PTR_ERR(*handle);
+ *handle = NULL;
+ GOTO(out_ids, rc);
+ }
+
rc = fsfilt_set_md(obd, inode, *handle, lmm, lmm_size);
lmm_buf = lustre_msg_buf(req->rq_repmsg, offset, 0);
lmm_bufsize = req->rq_repmsg->buflens[offset];
GOTO(out_dput, req->rq_status = -ENOMEM);
}
put_child = 0;
+ } else {
+ body->handle.cookie = mfd->mfd_handle.h_cookie;
+ CDEBUG(D_INODE, "resend mfd %p, cookie "LPX64"\n", mfd,
+ mfd->mfd_handle.h_cookie);
}
out_dput:
if (rc)
CERROR("error on parent setattr: rc = %d\n", rc);
- acc_mode = 0; /* Don't check for permissions */
+ rc = mds_finish_transno(mds, dchild->d_inode, handle, req, 0,
+ rep ? rep->lock_policy_res1 : 0);
+ handle = NULL;
+ acc_mode = 0; /* Don't check for permissions */
}
LASSERT(!mds_inode_is_orphan(dchild->d_inode));
void *handle = NULL;
struct mds_body *request_body = NULL, *reply_body = NULL;
struct dentry_params dp;
+ struct iattr iattr = { 0 };
ENTRY;
- if (req != NULL) {
+ if (req && req->rq_reqmsg != NULL)
request_body = lustre_msg_buf(req->rq_reqmsg, 0,
sizeof(*request_body));
+ if (req && req->rq_repmsg != NULL)
reply_body = lustre_msg_buf(req->rq_repmsg, 0,
sizeof(*reply_body));
- }
fidlen = ll_fid2str(fidname, inode->i_ino, inode->i_generation);
LASSERT(pending_child->d_inode != NULL);
cleanup_phase = 2; /* dput(pending_child) when finished */
- if (req != NULL) {
+ if (req != NULL && req->rq_repmsg != NULL) {
lmm = lustre_msg_buf(req->rq_repmsg, 1, 0);
stripe_count = le32_to_cpu(lmm->lmm_stripe_count);
}
GOTO(cleanup, rc);
}
- if (req != NULL && (reply_body->valid & OBD_MD_FLEASIZE) &&
+ if (req != NULL && req->rq_repmsg != NULL &&
+ (reply_body->valid & OBD_MD_FLEASIZE) &&
mds_log_op_unlink(obd, pending_child->d_inode, lmm,
req->rq_repmsg->buflens[1],
lustre_msg_buf(req->rq_repmsg, 2, 0),
rc = vfs_unlink(pending_dir, pending_child);
if (rc)
CERROR("error unlinking orphan %s: rc %d\n",fidname,rc);
- } else if (mfd->mfd_mode & FMODE_WRITE && rc == 0) {
+
+ goto out; /* Don't bother updating attrs on unlinked inode */
+ }
+
+ if (request_body != NULL && mfd->mfd_mode & FMODE_WRITE && rc == 0) {
/* Update the on-disk attributes if this was the last write
* close, and all information was provided (i.e., rc == 0)
*
* XXX this should probably be abstracted with mds_reint_setattr
*/
+
#if 0
- struct iattr iattr;
+ if (request_body->valid & OBD_MD_FLMTIME &&
+ LTIME_S(iattr.ia_mtime) > LTIME_S(inode->i_mtime)) {
+ LTIME_S(iattr.ia_mtime) = request_body->mtime;
+ iattr.ia_valid |= ATTR_MTIME;
+ }
+ if (request_body->valid & OBD_MD_FLCTIME &&
+ LTIME_S(iattr.ia_ctime) > LTIME_S(inode->i_ctime)) {
+ LTIME_S(iattr.ia_ctime) = request_body->ctime;
+ iattr.ia_valid |= ATTR_CTIME;
+ }
/* XXX can't set block count with fsfilt_setattr (!) */
- iattr.ia_valid = ATTR_CTIME | ATTR_ATIME |
- ATTR_MTIME | ATTR_SIZE;
- iattr.ia_atime = request_body->atime;
- iattr.ia_ctime = request_body->ctime;
- iattr.ia_mtime = request_body->mtime;
- iattr.ia_size = request_body->size;
+ if (request_body->valid & OBD_MD_FLSIZE) {
+ iattr.ia_valid |= ATTR_SIZE;
+ iattr.ia_size = request_body->size;
+ }
/* iattr.ia_blocks = request_body->blocks */
+#endif
+ }
+ if (request_body != NULL && request_body->valid & OBD_MD_FLATIME) {
+ /* Only start a transaction to write out only the atime if
+ * it is more out-of-date than the specified limit. If we
+ * are already going to write out the atime then do it anyway.
+ * */
+ LTIME_S(iattr.ia_atime) = request_body->atime;
+ if ((LTIME_S(iattr.ia_atime) >
+ LTIME_S(inode->i_atime) + MAX_ATIME_DIFF) ||
+ (iattr.ia_valid != 0 &&
+ LTIME_S(iattr.ia_atime) > LTIME_S(inode->i_atime)))
+ iattr.ia_valid |= ATTR_ATIME;
+ }
+
+ if (iattr.ia_valid != 0) {
handle = fsfilt_start(obd, inode, FSFILT_OP_SETATTR, NULL);
if (IS_ERR(handle))
GOTO(cleanup, rc = PTR_ERR(handle));
rc = fsfilt_setattr(obd, mfd->mfd_dentry, handle, &iattr, 0);
if (rc)
CERROR("error in setattr(%s): rc %d\n", fidname, rc);
-#endif
}
+out:
/* If other clients have this file open for write, rc will be > 0 */
if (rc > 0)
rc = 0;
cleanup:
atomic_dec(&mds->mds_open_count);
- if (req) {
+ if (req != NULL && reply_body != NULL) {
rc = mds_finish_transno(mds, pending_dir, handle, req, rc, 0);
} else if (handle) {
int err = fsfilt_commit(obd, pending_dir, handle, 0);
spin_unlock(&med->med_open_lock);
push_ctxt(&saved, &obd->obd_ctxt, NULL);
- req->rq_status = mds_mfd_close(rc ? NULL : req, obd, mfd, 1);
+ req->rq_status = mds_mfd_close(req, obd, mfd, 1);
pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ mds_mfd_put(mfd);
if (OBD_FAIL_CHECK(OBD_FAIL_MDS_CLOSE_PACK)) {
CERROR("test case OBD_FAIL_MDS_CLOSE_PACK\n");
req->rq_status = -ENOMEM;
- mds_mfd_put(mfd);
RETURN(-ENOMEM);
}
- mds_mfd_put(mfd);
RETURN(0);
}
/* Check that we're building against the appropriate version of the Lustre
* kernel patch */
#include <linux/lustre_version.h>
-#define LUSTRE_MIN_VERSION 28
-#define LUSTRE_MAX_VERSION 35
+#define LUSTRE_MIN_VERSION 32
+#define LUSTRE_MAX_VERSION 36
#if (LUSTRE_KERNEL_VERSION < LUSTRE_MIN_VERSION)
# error Cannot continue: Your Lustre kernel patch is older than the sources
#elif (LUSTRE_KERNEL_VERSION > LUSTRE_MAX_VERSION)
if (rc)
GOTO(err_mntput, rc);
+
+ filter->fo_destroy_in_progress = 0;
+ sema_init(&filter->fo_create_lock, 1);
+
spin_lock_init(&filter->fo_translock);
spin_lock_init(&filter->fo_objidlock);
INIT_LIST_HEAD(&filter->fo_export_list);
}
if (dchild->d_inode == NULL) {
- CERROR("%s on non-existent object: "LPU64"\n", what, oa->o_id);
+ CERROR("%s: %s on non-existent object: "LPU64"\n",
+ obd->obd_name, what, oa->o_id);
f_dput(dchild);
RETURN(ERR_PTR(-ENOENT));
}
}
doa.o_mode = S_IFREG;
+ filter->fo_destroy_in_progress = 1;
+ down(&filter->fo_create_lock);
+ if (!filter->fo_destroy_in_progress) {
+ CERROR("%s: destroy_in_progress already cleared\n",
+ exp->exp_obd->obd_name);
+ up(&filter->fo_create_lock);
+ EXIT;
+ return;
+ }
+
last = filter_last_id(filter, &doa);
CWARN("%s: deleting orphan objects from "LPU64" to "LPU64"\n",
exp->exp_obd->obd_name, oa->o_id + 1, last);
spin_lock(&filter->fo_objidlock);
filter->fo_last_objids[doa.o_gr] = oa->o_id;
spin_unlock(&filter->fo_objidlock);
+
+ filter->fo_destroy_in_progress = 0;
+ up(&filter->fo_create_lock);
+
EXIT;
}
static int filter_precreate(struct obd_device *obd, struct obdo *oa,
obd_gr group, int *num)
{
- struct dentry *dchild = NULL;
+ struct dentry *dchild = NULL, *dparent = NULL;
struct filter_obd *filter;
- struct dentry *dparent;
- int err = 0, rc = 0, i;
+ int err = 0, rc = 0, recreate_obj = 0, i;
__u64 next_id;
- int recreate_obj = 0;
void *handle = NULL;
ENTRY;
recreate_obj = 1;
}
- CDEBUG(D_HA, "%s: precreating %d objects\n", obd->obd_name, *num);
+ CDEBUG(D_HA, "%s: precreating %d objects\n", obd->obd_name, *num);
+
+ down(&filter->fo_create_lock);
for (i = 0; i < *num && err == 0; i++) {
int cleanup_phase = 0;
+ if (filter->fo_destroy_in_progress) {
+ CWARN("%s: precreate aborted by destroy\n",
+ obd->obd_name);
+ break;
+ }
+
if (recreate_obj) {
__u64 last_id;
next_id = oa->o_id;
CERROR("Error: Trying to recreate obj greater"
"than last id "LPD64" > "LPD64"\n",
next_id, last_id);
- RETURN(-EINVAL);
+ GOTO(cleanup, rc = -EINVAL);
}
} else
next_id = filter_last_id(filter, oa) + 1;
if (recreate_obj) {
CERROR("%s: Serious error: recreating obj %*s "
"but obj already exists \n",
- obd->obd_name, dchild->d_name.len,
+ obd->obd_name, dchild->d_name.len,
dchild->d_name.name);
LBUG();
} else {
CERROR("%s: Serious error: objid %*s already "
"exists; is this filesystem corrupt?\n",
- obd->obd_name, dchild->d_name.len,
+ obd->obd_name, dchild->d_name.len,
dchild->d_name.name);
LBUG();
}
}
*num = i;
+ up(&filter->fo_create_lock);
+
CDEBUG(D_HA, "%s: server last_objid for group "LPU64": "LPU64"\n",
obd->obd_name, group, filter->fo_last_objids[group]);
- CDEBUG(D_HA, "%s: filter_precreate() created %d objects\n",
+ CDEBUG(D_HA, "%s: filter_precreate() created %d objects\n",
obd->obd_name, i);
RETURN(rc);
}
{
struct obd_device *dev = data;
struct client_obd *cli = &dev->u.cli;
- int val;
- int rc;
+ unsigned val;
spin_lock(&cli->cl_loi_list_lock);
val = cli->cl_dirty_max >> 20;
- rc = snprintf(page, count, "%d\n", val);
spin_unlock(&cli->cl_loi_list_lock);
- return rc;
+
+ return snprintf(page, count, "%u\n", val);
}
int osc_wr_max_dirty_mb(struct file *file, const char *buffer,
spin_unlock(&oscc->oscc_lock);
osc_invalid = oscc->oscc_obd->u.cli.cl_import->imp_invalid;
-
+
return have_objs || ost_full || osc_invalid;
}
it is finished before we can continue with create. */
if (oscc_recovering(oscc)) {
struct l_wait_info lwi;
-
+
CDEBUG(D_HA,"%p: oscc recovery in progress, waiting\n",
oscc);
-
- lwi = LWI_TIMEOUT(MAX(obd_timeout * HZ, 1), NULL, NULL);
- rc = l_wait_event(oscc->oscc_waitq,
+
+ lwi = LWI_TIMEOUT(MAX(obd_timeout*HZ/4, 1), NULL, NULL);
+ rc = l_wait_event(oscc->oscc_waitq,
!oscc_recovering(oscc), &lwi);
LASSERT(rc == 0 || rc == -ETIMEDOUT);
if (rc == -ETIMEDOUT) {
- CDEBUG(D_HA, "%p: timed out waiting for "
- "recovery\n",
+ CDEBUG(D_HA,"%p: timeout waiting on recovery\n",
oscc);
RETURN(rc);
}
CDEBUG(D_HA, "%p: oscc recovery over, waking up\n",
oscc);
}
-
+
spin_lock(&oscc->oscc_lock);
if (oscc->oscc_last_id >= oscc->oscc_next_id) {
memcpy(oa, &oscc->oscc_oa, sizeof(*oa));
{
CDEBUG (D_NET, "yield\n");
- if (current->need_resched)
+ if (need_resched())
schedule();
return;
}
/**********************************************************************/
/* Spawn scheduling threads */
- for (i = 0; i < smp_num_cpus; i++)
- {
+ for (i = 0; i < num_online_cpus(); i++) {
rc = kqswnal_thread_start (kqswnal_scheduler, NULL);
if (rc != 0)
{
* along with Lustre; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Basic library routines.
+ * Basic library routines.
*
*/
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/errno.h>
-#include <linux/locks.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#include <linux/locks.h> /* wait_on_buffer */
+#else
+#include <linux/buffer_head.h> /* wait_on_buffer */
+#endif
#include <linux/unistd.h>
#include <net/sock.h>
#include <linux/uio.h>
!list_empty(&kqswnal_data.kqn_delayedtxds) ||
!list_empty(&kqswnal_data.kqn_delayedfwds));
LASSERT (rc == 0);
- } else if (current->need_resched)
+ } else if (need_resched())
schedule ();
spin_lock_irqsave (&kqswnal_data.kqn_sched_lock, flags);
void
+__attribute__((format(printf, 1, 2)))
prt(char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(stdout, fmt, args);
- if (fsxlogf)
- vfprintf(fsxlogf, fmt, args);
va_end(args);
+
+ if (fsxlogf) {
+ va_start(args, fmt);
+ vfprintf(fsxlogf, fmt, args);
+ va_end(args);
+ }
}
void
int len;
len = snprintf(&dummy, 0, "%u ", highest);
- if (len < 0) {
+ if (len < 1) {
prterr("finding max tf_buf");
exit(1);
}
- tf_buf = malloc(len + 1);
+ len++;
+ tf_buf = malloc(len);
if (tf_buf == NULL) {
prterr("allocating tf_buf");
exit(1);
}
- max_tf_len = sprintf(tf_buf, "%u ", highest);
+ max_tf_len = snprintf(tf_buf, len, "%u ", highest);
+ if (max_tf_len < 1) {
+ prterr("fiding max_tv_len\n");
+ exit(1);
+ }
+ if (max_tf_len != len - 1) {
+ warn("snprintf() gave %d instead of %d?\n",
+ max_tf_len, len - 1);
+ exit(1);
+ }
}
-char *
+char *
fill_tf_buf(struct test_file *tf)
{
if (tf_buf == NULL)
alloc_tf_buf();
- sprintf(tf_buf,"%u ", (int)(tf - test_files));
+ sprintf(tf_buf,"%lu ", (unsigned long)(tf - test_files));
return tf_buf;
}
void
-output_line(struct test_file *tf, int op, unsigned long offset,
- unsigned long size, struct timeval *tv)
+output_line(struct test_file *tf, int op, unsigned offset,
+ unsigned size, struct timeval *tv)
{
char *tf_num = "";
if (iret == -1)
prterr("writefileimage: write");
else
- prt("short write: 0x%x bytes instead of 0x%llx\n",
- iret, (unsigned long long)file_size);
+ prt("short write: 0x%lx bytes instead of 0x%llx\n",
+ (unsigned long)iret,
+ (unsigned long long)file_size);
report_failure(172);
}
if (lite ? 0 : ftruncate(fd, file_size) == -1) {
. ${CONFIG:=$LUSTRE/tests/cfg/insanity-local.sh}
-ALWAYS_EXCEPT="10"
+ALWAYS_EXCEPT="0 10"
build_test_filter
wait_for mds
start mds $MDSLCONFARGS ${REFORMAT}
while ! do_node $CLIENTS "ls -d $LUSTRE" > /dev/null; do sleep 5; done
- zconf_mount $CLIENTS $MOUNT
+ grep " $MOUNT " /proc/mounts || zconf_mount $CLIENTS $MOUNT
}
multiop $DIR/$tfile O_c &
pid=$!
+ sleep 1
# allow the open to complete
usleep 500
}
run_test 45 "Handle failed close"
+test_46() {
+ dmesg -c >/dev/null
+ drop_reply "touch $DIR/$tfile"
+ fail mds
+ # ironically, the previous test, 45, will cause a real forced close,
+ # so just look for one for this test
+ dmesg | grep -i "force closing client file handle for $tfile" && return 1
+ return 0
+}
+run_test 46 "Don't leak file handle after open resend (3325)"
+
equals_msg test complete, cleaning up
$CLEANUP
set -e
ONLY=${ONLY:-"$*"}
-# bug number for skipped test:
-ALWAYS_EXCEPT=${ALWAYS_EXCEPT:-""}
+# bug number for skipped test: 2108
+ALWAYS_EXCEPT=${ALWAYS_EXCEPT:-"42a"}
# UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
case `uname -r` in
-2.6.*) ALWAYS_EXCEPT="$ALWAYS_EXCEPT 54c" # bug 3117
+2.6.*) ALWAYS_EXCEPT="$ALWAYS_EXCEPT 54c 55" # bug 3117
esac
[ "$ALWAYS_EXCEPT$EXCEPT" ] && echo "Skipping tests: $ALWAYS_EXCEPT $EXCEPT"
lctl mark "$*" 2> /dev/null || true
}
+trace() {
+ log "STARTING: $*"
+ strace -o $TMP/$1.strace -ttt $*
+ RC=$?
+ log "FINISHED: $*: rc $RC"
+ return 1
+}
+TRACE=${TRACE:-""}
+
+check_kernel_version() {
+ VERSION_FILE=/proc/fs/lustre/kernel_version
+ WANT_VER=$1
+ [ ! -f $VERSION_FILE ] && echo "can't find kernel version" && return 1
+ GOT_VER=`cat $VERSION_FILE`
+ [ $GOT_VER -ge $WANT_VER ] && return 0
+ log "test needs at least kernel version $WANT_VER, running $GOT_VER"
+ return 1
+}
+
run_one() {
if ! mount | grep -q $DIR; then
$START
run_test 36d "non-root OST utime check (open, utime) ==========="
test_36e() {
- [ $RUNAS_ID -eq $UID ] && return
+ [ $RUNAS_ID -eq $UID ] && echo "skipping test 36e" && return
[ ! -d $DIR/d36 ] && mkdir $DIR/d36
touch $DIR/d36/f36e
$RUNAS utime $DIR/d36/f36e && error "utime worked, want failure" || true
run_test 47 "Device nodes check ================================"
test_48a() { # bug 2399
- mkdir $DIR/d48a
+ check_kernel_version 34 || return 0
+ mkdir -p $DIR/d48a
cd $DIR/d48a
mv $DIR/d48a $DIR/d48.new || error "move directory failed"
mkdir $DIR/d48a || error "recreate directory failed"
mkdir . && error "'mkdir .' worked after recreating cwd"
rmdir . && error "'rmdir .' worked after recreating cwd"
ln -s . baz || error "'ln -s .' failed after recreating cwd"
+ cd .. || error "'cd ..' failed after recreating cwd"
}
run_test 48a "Access renamed working dir (should return errors)="
test_48b() { # bug 2399
- mkdir $DIR/d48b
+ check_kernel_version 34 || return 0
+ mkdir -p $DIR/d48b
cd $DIR/d48b
rmdir $DIR/d48b || error "remove cwd $DIR/d48b failed"
touch foo && error "'touch foo' worked after removing cwd"
mkdir foo && error "'mkdir foo' worked after removing cwd"
ls . && error "'ls .' worked after removing cwd"
ls .. || error "'ls ..' failed after removing cwd"
- cd . && error "'cd .' worked after recreate cwd"
+ cd . && error "'cd .' worked after removing cwd"
mkdir . && error "'mkdir .' worked after removing cwd"
rmdir . && error "'rmdir .' worked after removing cwd"
ln -s . foo && error "'ln -s .' worked after removing cwd" || true
+ cd .. || error "'cd ..' failed after removing cwd"
}
run_test 48b "Access removed working dir (should return errors)="
+test_48c() { # bug 2350
+ check_kernel_version 36 || return 0
+ #sysctl -w portals.debug=-1
+ #set -vx
+ mkdir -p $DIR/d48c/dir
+ cd $DIR/d48c/dir
+ rmdir $DIR/d48c/dir || error "remove cwd $DIR/d48c/dir failed"
+ $TRACE touch foo && error "'touch foo' worked after removing cwd"
+ $TRACE mkdir foo && error "'mkdir foo' worked after removing cwd"
+ $TRACE ls . && error "'ls .' worked after removing cwd"
+ $TRACE ls .. || error "'ls ..' failed after removing cwd"
+ $TRACE cd . && error "'cd .' worked after removing cwd"
+ $TRACE mkdir . && error "'mkdir .' worked after removing cwd"
+ $TRACE rmdir . && error "'rmdir .' worked after removing cwd"
+ $TRACE ln -s . foo && error "'ln -s .' worked after removing cwd" ||true
+ $TRACE cd .. || error "'cd ..' failed after removing cwd"
+}
+run_test 48c "Access removed working subdir (should return errors)"
+
+test_48d() { # bug 2350
+ check_kernel_version 36 || return 0
+ #sysctl -w portals.debug=-1
+ #set -vx
+ mkdir -p $DIR/d48d/dir
+ cd $DIR/d48d/dir
+ rm -r $DIR/d48d || error "remove cwd and parent $DIR/d48d failed"
+ $TRACE touch foo && error "'touch foo' worked after removing cwd"
+ $TRACE mkdir foo && error "'mkdir foo' worked after removing cwd"
+ $TRACE ls . && error "'ls .' worked after removing cwd"
+ $TRACE ls .. && error "'ls ..' worked after removing cwd"
+ $TRACE cd . && error "'cd .' worked after recreate cwd"
+ $TRACE mkdir . && error "'mkdir .' worked after removing cwd"
+ $TRACE rmdir . && error "'rmdir .' worked after removing cwd"
+ $TRACE ln -s . foo && error "'ln -s .' worked after removing cwd" ||true
+ $TRACE cd .. && error "'cd ..' worked after recreate cwd" || true
+}
+run_test 48d "Access removed parent subdir (should return errors)"
+
test_50() {
# bug 1485
mkdir $DIR/d50
test_55() {
rm -rf $DIR/d55
mkdir $DIR/d55
- mount -t ext3 -o loop,iopen $EXT3_DEV $DIR/d55 || error
+ mount -t ext3 -o loop,iopen $EXT3_DEV $DIR/d55 || error "mounting"
touch $DIR/d55/foo
- $IOPENTEST1 $DIR/d55/foo $DIR/d55 || error
- $IOPENTEST2 $DIR/d55 || error
+ $IOPENTEST1 $DIR/d55/foo $DIR/d55 || error "running $IOPENTEST1"
+ $IOPENTEST2 $DIR/d55 || error "running $IOPENTEST2"
echo "check for $EXT3_DEV. Please wait..."
rm -rf $DIR/d55/*
- umount $DIR/d55 || error
+ umount $DIR/d55 || error "unmounting"
}
run_test 55 "check iopen_connect_dentry() ======================"
# bug 2319 - oig_wait() interrupted causes crash because of invalid waitq.
test_63() {
- MAX_DIRTY_MB=`cat /proc/fs/lustre/osc/*/max_dirty_mb | head -1`
+ MAX_DIRTY_MB=`cat /proc/fs/lustre/osc/*/max_dirty_mb | head -n 1`
for i in /proc/fs/lustre/osc/*/max_dirty_mb ; do
echo 0 > $i
done
}
run_test 66 "update inode blocks count on client ==============="
+test_67() { # bug 3285 - supplementary group fails on MDS, passes on client
+ [ "$RUNAS_ID" = "$UID" ] && echo "skipping test 67" && return
+ check_kernel_version 35 || return 0
+ mkdir $DIR/d67
+ chmod 771 $DIR/d67
+ chgrp $RUNAS_ID $DIR/d67
+ $RUNAS -g $((RUNAS_ID + 1)) -G1,2,$RUNAS_ID ls $DIR/d67 && error || true
+}
+run_test 67 "supplementary group failure (should return error) ="
+
# on the LLNL clusters, runas will still pick up root's $TMP settings,
# which will not be writable for the runas user, and then you get a CVS
# error message with a corrupt path string (CVS bug) and panic.
set -e
ONLY=${ONLY:-"$*"}
-# bug number for skipped test: 1768 1557
-ALWAYS_EXCEPT=${ALWAYS_EXCEPT:-"4 8 14b"}
+# bug number for skipped test: 1768
+ALWAYS_EXCEPT=${ALWAYS_EXCEPT:-"4 14b"}
# UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
[ "$ALWAYS_EXCEPT$EXCEPT" ] && echo "Skipping tests: $ALWAYS_EXCEPT $EXCEPT"
self.dom_node = dom
self.root_node = root_node
+ def close(self):
+ # do nothing
+ return None
+
def xmltext(self, dom_node, tag):
list = dom_node.getElementsByTagName(tag)
if len(list) > 0:
quit""" % (type, name, uuid)
self.run(cmds)
- def setup(self, name, setup = ""):
+ def setup(self, name, setup = ""):
cmds = """
cfg_device %s
setup %s
log(e)
elif net_type == 'gm':
fixme("automatic local address for GM")
- elif net_type == 'scimac':
- scinode="/opt/scali/sbin/scinode"
- if os.path.exists(scinode):
- (rc,local) = run(scinode)
- else:
- panic (scinode, " not found on node with scimac networking")
- if rc:
- panic (scinode, " failed")
- local=string.rstrip(local[0])
return local
self.add_portals_module("knals/qswnal", 'kqswnal')
if self.net_type == 'gm':
self.add_portals_module("knals/gmnal", 'kgmnal')
- if self.net_type == 'scimac':
- self.add_portals_module("knals/scimacnal", 'kscimacnal')
def nid_to_uuid(self, nid):
return "NID_%s_UUID" %(nid,)
self.name = "lov_%s" % name_override
self.add_lustre_module('lov', 'lov')
self.mds_uuid = self.db.get_first_ref('mds')
- self.stripe_sz = self.db.get_val_int('stripesize', 65536)
+ self.stripe_sz = self.db.get_val_int('stripesize', 1048576)
self.stripe_off = self.db.get_val_int('stripeoffset', 0)
self.pattern = self.db.get_val_int('stripepattern', 0)
self.devlist = self.db.get_refs('obd')
self.target_dev_uuid = self.uuid
self.uuid = target_uuid
- # modules
+
+ # loading modules
self.add_lustre_module('mdc', 'mdc')
self.add_lustre_module('osc', 'osc')
self.add_lustre_module('lov', 'lov')
def mgmt_uuid_for_fs(mtpt_name):
if not mtpt_name:
return ''
- mtpt_db = toplevel.lookup_name(mtpt_name)
+ mtpt_db = toplustreDB.lookup_name(mtpt_name)
fs_uuid = mtpt_db.get_first_ref('filesystem')
- fs = toplevel.lookup(fs_uuid)
+ fs = toplustreDB.lookup(fs_uuid)
if not fs:
return ''
return fs.get_first_ref('mgmt')
prof_list = node_db.get_refs('profile')
if config.write_conf:
+ lustreDB.close()
for_each_profile(node_db, prof_list, doModules)
sys_make_devices()
for_each_profile(node_db, prof_list, doWriteconf)
for_each_profile(node_db, prof_list, doCleanup)
for_each_profile(node_db, prof_list, doUnloadModules)
+ lustreDB.close()
else:
# ugly hack, only need to run lctl commands for --dump
sys_set_portals_upcall(portals_upcall)
for_each_profile(node_db, prof_list, doSetup)
+ lustreDB.close()
-def doRecovery(db, lctl, tgt_uuid, client_uuid, nid_uuid):
- tgt = db.lookup(tgt_uuid)
+def doRecovery(lustreDB, lctl, tgt_uuid, client_uuid, nid_uuid):
+ tgt = lustreDB.lookup(tgt_uuid)
if not tgt:
raise Lustre.LconfError("doRecovery: "+ tgt_uuid +" not found.")
new_uuid = get_active_target(tgt)
if not new_uuid:
raise Lustre.LconfError("doRecovery: no active target found for: " +
tgt_uuid)
- net = choose_local_server(get_ost_net(db, new_uuid))
+ net = choose_local_server(get_ost_net(lustreDB, new_uuid))
if not net:
raise Lustre.LconfError("Unable to find a connection to:" + new_uuid)
log("Reconnecting", tgt_uuid, " to ", net.nid_uuid);
try:
- oldnet = get_server_by_nid_uuid(db, nid_uuid)
+ oldnet = get_server_by_nid_uuid(lustreDB, nid_uuid)
+ lustreDB.close()
if oldnet:
lctl.disconnect(oldnet)
except CommandError, e:
]
def main():
- global lctl, config, toplevel, CONFIG_FILE
+ global lctl, config, toplustreDB, CONFIG_FILE
# in the upcall this is set to SIG_IGN
signal.signal(signal.SIGCHLD, signal.SIG_DFL)
except Exception:
panic("%s does not appear to be a config file." % (args[0]))
sys.exit(1) # make sure to die here, even in debug mode.
+ config_file.close()
CONFIG_FILE = args[0]
- db = Lustre.LustreDB_XML(dom.documentElement, dom.documentElement)
+ lustreDB = Lustre.LustreDB_XML(dom.documentElement, dom.documentElement)
if not config.config:
config.config = os.path.basename(args[0])# use full path?
if config.config[-4:] == '.xml':
if not config.config:
panic("--ldapurl requires --config name")
dn = "config=%s,fs=lustre" % (config.config)
- db = Lustre.LustreDB_LDAP('', {}, base=dn, url = config.ldapurl)
+ lustreDB = Lustre.LustreDB_LDAP('', {}, base=dn, url = config.ldapurl)
elif config.ptldebug or config.subsystem:
sys_set_ptldebug(None)
sys_set_subsystem(None)
print 'see lconf --help for command summary'
sys.exit(1)
- toplevel = db
+ toplustreDB = lustreDB
- ver = db.get_version()
+ ver = lustreDB.get_version()
if not ver:
panic("No version found in config data, please recreate.")
if ver != Lustre.CONFIG_VERSION:
lctl.clear_log(config.record_device, config.record_log)
lctl.record(config.record_device, config.record_log)
- doHost(db, node_list)
+ doHost(lustreDB, node_list)
if config.record:
lctl.end_record()
return CMD_HELP;
}
- result = op_create_file(argv[1], st_size, st_offset, st_count);
+ result = llapi_file_create(argv[1], st_size, st_offset, st_count, 0);
if (result)
fprintf(stderr, "error: %s: create stripe file failed\n",
argv[0]);
return CMD_HELP;
do {
- rc = op_find(argv[optind], obduuid, recursive, verbose, quiet);
+ rc = llapi_find(argv[optind], obduuid, recursive,verbose,quiet);
} while (++optind < argc && !rc);
if (rc)
optind = 1;
do {
- rc = op_find(argv[optind], obduuid, 0, 0, 0);
+ rc = llapi_find(argv[optind], obduuid, 0, 0, 0);
} while (++optind < argc && !rc);
if (rc)
mnt = getmntent(fp);
while (feof(fp) == 0 && ferror(fp) ==0) {
if (llapi_is_lustre_mnttype(mnt->mnt_type)) {
- rc = op_find(mnt->mnt_dir, obduuid, 0, 0, 0);
+ rc = llapi_find(mnt->mnt_dir, obduuid, 0, 0, 0);
if (rc)
- fprintf(stderr, "error: lfs osts failed for %s\n",
- mnt->mnt_dir);
+ fprintf(stderr,
+ "error: lfs osts failed on %s\n",
+ mnt->mnt_dir);
}
mnt = getmntent(fp);
}
int rc;
FILE *fp;
struct mntent *mnt = NULL;
- int type_num = 1;
- char *obd_type_p[2];
+ int num_types = 1;
+ char *obd_types[2];
char obd_type1[4];
char obd_type2[4];
if (argc != 2)
return CMD_HELP;
- obd_type_p[1]=obd_type1;
- obd_type_p[2]=obd_type2;
-
- if (strcmp(argv[1],"osts")==0) {
- strcpy(obd_type_p[0],"osc");
- } else if (strcmp(argv[1],"mds")==0) {
- strcpy(obd_type_p[0],"mdc");
- } else if (strcmp(argv[1],"servers")==0) {
- type_num=2;
- strcpy(obd_type_p[0],"osc");
- strcpy(obd_type_p[1],"mdc");
+ obd_types[1] = obd_type1;
+ obd_types[2] = obd_type2;
+
+ if (strcmp(argv[1], "osts") == 0) {
+ strcpy(obd_types[0], "osc");
+ } else if (strcmp(argv[1], "mds") == 0) {
+ strcpy(obd_types[0], "mdc");
+ } else if (strcmp(argv[1], "servers") == 0) {
+ num_types = 2;
+ strcpy(obd_types[0], "osc");
+ strcpy(obd_types[1], "mdc");
} else {
fprintf(stderr, "error: %s: option '%s' unrecognized\n",
argv[0], argv[1]);
endmntent(fp);
}
- rc = op_check(type_num,obd_type_p,mnt->mnt_dir);
+ rc = llapi_target_check(num_types, obd_types, mnt->mnt_dir);
if (rc)
fprintf(stderr, "error: %s: %s status failed\n",
if (mnt) {
if (argc == 3)
- rc = op_catinfo(mnt->mnt_dir, argv[1], argv[2]);
+ rc = llapi_catinfo(mnt->mnt_dir, argv[1], argv[2]);
else
- rc = op_catinfo(mnt->mnt_dir, argv[1], NULL);
+ rc = llapi_catinfo(mnt->mnt_dir, argv[1], NULL);
} else {
fprintf(stderr, "no lustre_lite mounted.\n");
rc = -1;
fprintf(stderr, ": %s (%d)\n", strerror(tmp_errno), tmp_errno);
}
-int op_create_file(char *name, long stripe_size, int stripe_offset,
- int stripe_count)
+int llapi_file_create(char *name, long stripe_size, int stripe_offset,
+ int stripe_count, int stripe_pattern)
{
struct lov_user_md lum = { 0 };
int fd, rc = 0;
/* Initialize IOCTL striping pattern structure */
lum.lmm_magic = LOV_USER_MAGIC;
+ lum.lmm_pattern = stripe_pattern;
lum.lmm_stripe_size = stripe_size;
- lum.lmm_stripe_offset = stripe_offset;
lum.lmm_stripe_count = stripe_count;
+ lum.lmm_stripe_offset = stripe_offset;
fd = open(name, O_CREAT | O_RDWR | O_LOV_DELAY_CREATE, 0644);
if (errno == EISDIR)
return rc;
}
+/* short term backwards compat only */
+int op_create_file(char *name, long stripe_size, int stripe_offset,
+ int stripe_count)
+{
+ return llapi_file_create(name, stripe_size, stripe_offset,
+ stripe_count, 0);
+}
+
struct find_param {
int recursive;
int verbose;
int quiet;
struct obd_uuid *obduuid;
- struct obd_ioctl_data data;
- struct lov_desc desc;
- int uuidslen;
- char *buf;
- int buflen;
- struct obd_uuid *uuids;
+ int lumlen;
struct lov_user_md *lum;
int got_uuids;
int obdindex;
- int max_ost_count;
};
/* XXX Max obds per lov currently hardcoded to 1000 in lov/lov_obd.c */
static int prepare_find(struct find_param *param)
{
- int datalen, desclen;
- int cfglen, lumlen;
- int max_ost_count = MAX_LOV_UUID_COUNT;
-
- datalen = size_round(sizeof(param->data));
- desclen = size_round(sizeof(param->desc));
- param->uuidslen = size_round(max_ost_count * sizeof(*param->uuids));
- cfglen = datalen + desclen + param->uuidslen;
- lumlen = lov_mds_md_size(max_ost_count);
- if (cfglen > lumlen)
- param->buflen = cfglen;
- else
- param->buflen = lumlen;
-
- /* XXX max ioctl buffer size currently hardcoded to 8192 */
- if (param->buflen > 8192) {
- int nuuids, remaining;
-
- param->buflen = 8192;
- nuuids = (param->buflen - datalen - desclen) /
- sizeof(*param->uuids);
- param->uuidslen = size_round(nuuids * sizeof(*param->uuids));
- remaining = nuuids * sizeof(*param->uuids);
- if (param->uuidslen > remaining)
- nuuids--;
- max_ost_count = nuuids;
- while ((lumlen=lov_mds_md_size(max_ost_count)) > param->buflen)
- --max_ost_count;
-
- cfglen = datalen + desclen + param->uuidslen;
- }
-
- if ((param->buf = malloc(param->buflen)) == NULL) {
- err_msg("unable to allocate %d bytes of memory for ioctl's",
- param->buflen);
+ param->lumlen = lov_mds_md_size(MAX_LOV_UUID_COUNT);
+ if ((param->lum = malloc(param->lumlen)) == NULL) {
+ err_msg("unable to allocate %d bytes of memory for ioctl",
+ param->lumlen);
return ENOMEM;
}
- param->lum = (struct lov_user_md *)param->buf;
- param->uuids = (struct obd_uuid *)param->buf;
param->got_uuids = 0;
param->obdindex = OBD_NOT_FOUND;
- param->max_ost_count = max_ost_count;
return 0;
}
{
if (param->obduuid)
free(param->obduuid);
- if (param->buf)
- free(param->buf);
+ if (param->lum)
+ free(param->lum);
}
-static int get_obd_uuids(DIR *dir, char *dname, struct find_param *param)
+int llapi_lov_get_uuids(int fd, struct obd_uuid *uuidp, int *ost_count)
{
- int obdcount;
- struct obd_uuid *uuidp;
- int rc, i;
-
- param->got_uuids = 1;
- memset(¶m->data, 0, sizeof(param->data));
- param->data.ioc_inllen1 = sizeof(struct lov_desc);
- param->data.ioc_inlbuf1 = (char *)¶m->desc;
- param->data.ioc_inllen2 = param->uuidslen;
- param->data.ioc_inlbuf2 = (char *)param->uuids;
-
- memset(¶m->desc, 0, sizeof(struct lov_desc));
- param->desc.ld_tgt_count = param->max_ost_count;
-
- if (obd_ioctl_pack(¶m->data, ¶m->buf, param->buflen)) {
- fprintf(stderr, "internal buffer error from %s\n", dname);
- return (param->obduuid ? EINVAL : 0);
+ struct obd_ioctl_data data = { 0, };
+ struct lov_desc desc = { 0, };
+ char *buf = NULL;
+ int max_ost_count, rc;
+
+ max_ost_count = (OBD_MAX_IOCTL_BUFFER - size_round(sizeof(data)) -
+ size_round(sizeof(desc))) / sizeof(*uuidp);
+ if (max_ost_count > *ost_count)
+ max_ost_count = *ost_count;
+
+ data.ioc_inllen1 = sizeof(desc);
+ data.ioc_inlbuf1 = (char *)&desc;
+ data.ioc_inllen2 = size_round(max_ost_count * sizeof(*uuidp));
+ data.ioc_inlbuf2 = (char *)uuidp;
+
+ desc.ld_tgt_count = max_ost_count;
+
+ if (obd_ioctl_pack(&data, &buf, OBD_MAX_IOCTL_BUFFER)) {
+ fprintf(stderr, "internal buffer error packing\n");
+ rc = EINVAL;
+ goto out;
}
- rc = ioctl(dirfd(dir), OBD_IOC_LOV_GET_CONFIG, param->buf);
+ rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf);
if (rc) {
- err_msg("error getting LOV config from %s", dname);
- return (param->obduuid ? errno : 0);
+ err_msg("error getting LOV config");
+ rc = errno;
+ goto out;
}
- if (obd_ioctl_unpack(¶m->data, param->buf, param->buflen)) {
- err_msg("invalid reply from ioctl from %s", dname);
- return (param->obduuid ? EINVAL : 0);
+ if (obd_ioctl_unpack(&data, buf, OBD_MAX_IOCTL_BUFFER)) {
+ fprintf(stderr, "invalid reply from ioctl");
+ rc = EINVAL;
+ goto out;
}
- obdcount = param->desc.ld_tgt_count;
+ *ost_count = desc.ld_tgt_count;
+out:
+ free(buf);
+
+ return 0;
+}
+
+static int setup_obd_uuids(DIR *dir, char *dname, struct find_param *param)
+{
+ struct obd_uuid uuids[1024], *uuidp;
+ int obdcount = 1024;
+ int rc, i;
+
+ param->got_uuids = 1;
+
+ rc = llapi_lov_get_uuids(dirfd(dir), uuids, &obdcount);
+ if (rc != 0)
+ return (param->obduuid ? rc : 0);
+
if (obdcount == 0)
return 0;
if (param->obduuid) {
- for (i = 0, uuidp = param->uuids; i < obdcount; i++, uuidp++) {
+ for (i = 0, uuidp = uuids; i < obdcount; i++, uuidp++) {
if (strncmp(param->obduuid->uuid, uuidp->uuid,
sizeof(*uuidp)) == 0) {
param->obdindex = i;
}
} else if (!param->quiet) {
printf("OBDS:\n");
- for (i = 0, uuidp = param->uuids; i < obdcount; i++, uuidp++)
+ for (i = 0, uuidp = uuids; i < obdcount; i++, uuidp++)
printf("%4d: %s\n", i, uuidp->uuid);
}
}
}
-void lov_dump_user_lmm(struct find_param *param, char *dname, char *fname)
+void llapi_lov_dump_user_lmm(struct find_param *param, char *dname, char *fname)
{
switch(*(__u32 *)param->lum) { /* lum->lmm_magic */
case LOV_USER_MAGIC_V1:
}
}
-int get_file_stripe(char *path, struct lov_user_md *lum)
+int llapi_file_get_stripe(char *path, struct lov_user_md *lum)
{
char *dname, *fname;
int fd, rc = 0;
return rc;
}
+/* short term backwards compat only */
+int op_get_file_stripe(char *path, struct lov_user_md *lum)
+{
+ return llapi_file_get_stripe(path, lum);
+}
+
static int process_file(DIR *dir, char *dname, char *fname,
struct find_param *param)
{
int rc;
- strncpy((char *)param->lum, fname, param->buflen);
+ strncpy((char *)param->lum, fname, param->lumlen);
rc = ioctl(dirfd(dir), IOC_MDC_GETSTRIPE, (void *)param->lum);
if (rc) {
return rc;
}
- lov_dump_user_lmm(param, dname, fname);
+ llapi_lov_dump_user_lmm(param, dname, fname);
return 0;
}
int rc;
if (!param->got_uuids) {
- rc = get_obd_uuids(dir, dname, param);
+ rc = setup_obd_uuids(dir, dname, param);
if (rc)
return rc;
}
/* retrieve dir's stripe info */
- strncpy((char *)param->lum, dname, param->buflen);
+ strncpy((char *)param->lum, dname, param->lumlen);
rc = ioctl(dirfd(dir), LL_IOC_LOV_GETSTRIPE, (void *)param->lum);
if (rc) {
if (errno == ENODATA) {
return errno;
}
} else {
- lov_dump_user_lmm(param, dname, "");
+ llapi_lov_dump_user_lmm(param, dname, "");
}
/* Handle the contents of the directory */
rc = errno;
} else {
if (!param->got_uuids)
- rc = get_obd_uuids(dir, dname, param);
+ rc = setup_obd_uuids(dir, dname, param);
if (rc == 0)
rc = process_file(dir, dname, fname, param);
closedir(dir);
return rc;
}
-
-int op_find(char *path, struct obd_uuid *obduuid, int recursive,
- int verbose, int quiet)
+int llapi_find(char *path, struct obd_uuid *obduuid, int recursive,
+ int verbose, int quiet)
{
struct find_param param;
int ret = 0;
#define MAX_STRING_SIZE 128
#define DEVICES_LIST "/proc/fs/lustre/devices"
-int op_check(int type_num, char **obd_type, char *dir)
+int llapi_target_check(int type_num, char **obd_type, char *dir)
{
char buf[MAX_STRING_SIZE];
FILE *fp = fopen(DEVICES_LIST, "r");
int i;
if (fp == NULL) {
- fprintf(stderr, "error: %s could not open file "
- DEVICES_LIST " .\n", strerror(rc = errno));
+ fprintf(stderr, "error: %s opening "DEVICES_LIST"\n",
+ strerror(rc = errno));
return rc;
}
#undef MAX_STRING_SIZE
-int op_catinfo(char *dir, char *keyword, char *node_name)
+int llapi_catinfo(char *dir, char *keyword, char *node_name)
{
char raw[OBD_MAX_IOCTL_BUFFER];
char out[LLOG_CHUNK_SIZE];
int rc;
char buf[MAX_STRING_SIZE];
FILE *fp = fopen(DEVICES_LIST, "r");
-
+
if (fp == NULL) {
- fprintf(stderr, "error: %s: %s could not open file "
- DEVICES_LIST " .\n",
+ fprintf(stderr, "error: %s: %s opening "DEVICES_LIST"\n",
jt_cmdname(argv[0]), strerror(rc = errno));
return rc;
}
-
+
if (argc != 1)
return CMD_HELP;
-
+
while (fgets(buf, sizeof(buf), fp) != NULL)
printf("%s", buf);
-
+
fclose(fp);
-
+
return 0;
}