+TBD
+ * version v0_5_20
+ * bug fixes
+ - Fix ldlm_lock_match on the MDS to avoid matching remote locks (592)
+ - Fix fsfilt_extN_readpage() to read a full page of directory
+ entries, or fake the remainder if PAGE_SIZE != blocksize (500)
+ - Avoid extra mdc_getattr() in ll_intent_lock when possible (534, 604)
+ - Fix imbalanced LOV object allocation and out-of-bound access (469)
+ - Most intent operations were removed, in favour of a new RPC mode
+ that does a single RPC to the server and bypasses most of the VFS
+ - All LDLM resource ID arrays were removed in favour of ldlm_res_id
+ - Aggressively cancel local locks on DLM servers
+ - mds_reint_unlink sends EA to the client if it's the last nlink.
+ client uses that EA to unlink OST objects.
+ - mds_reint_{rename,unlink,link} were rewritten to take ordered locks
+ - recursive symlinks were fixed (439)
+ - fixed NULL deref in DEBUG_REQ
+ - filter_update_lastobjid no longer calls sync, which annoyed extN
+ - fixed multi-client small-writes to a single file problem (445)
+ - fixed mtime updates during file writes (607)
+ - fixed vector writes on obdfilter causing problems when ENOSPC (670)
+ - fixed bug in obd_brw_read/write() (under guise of testing 367)
+ - fixed Linux OST size reporting problem (444, 656)
+ - OST now updates object mtime with writes or setattr (607, 619)
+ - client verifies file size before zeroing page past EOF (445)
+ - OST now writes last allocated objid to disk with allocation (108)
+ - LOV on echo now works (409)
+ * protocol changes
+ - mds_reint_unlink sends a new buffer, with the EA included. this
+ buffer is only valid if body->valid & OBD_MD_FLEASIZE, which is only
+ set if a regular file was being unlinked, and it was the last link
+ - use PtlGet from the target for bulk writes (315)
+ - OST now updates object mtime with writes or setattr (607, 619)
+ - LDLM now has a grant-time callback to revalidate locked items, if
+ necessary (604)
+ - Many MDS operations were reorganized to combat race conditions
+ * other changes
+ - Merge b_intel branch (updated lprocfs code) - now at /proc/fs/lustre
+ - configure check to avoid gcc version 2.96 20000731-2.96-98) (606)
+
2003-01-06 Andreas Dilger <adilger@clusterfs.com>
* version v0_5_19
* bug fixes
rm -f $(top_srcdir)/TAGS
rm -f $(top_srcdir)/tags
find $(top_srcdir)/../portals/ -name '*.[hc]' | xargs etags -a
- find $(top_srcdir) -name '*.[hc]' | xargs etags -a
+ find $(top_srcdir) -name '*.[hc]' | grep -v ".orig" | xargs etags -a
find $(top_srcdir)/../portals/ -name '*.[hc]' | xargs ctags -a
- find $(top_srcdir) -name '*.[hc]' | xargs ctags -a
+ find $(top_srcdir) -name '*.[hc]' | grep -v ".orig" | xargs ctags -a
AM_CPPFLAGS=-I$(top_builddir)/include
ia64 )
AC_MSG_RESULT($host_cpu)
- KCFLAGS='-g -O2 -Wall -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -pipe -ffixed-r13 -mfixed-range=f10-f15,f32-f127 -falign-functions=32 -mb-step'
+ KCFLAGS='-gstabs -O2 -Wall -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -pipe -ffixed-r13 -mfixed-range=f10-f15,f32-f127 -falign-functions=32 -mb-step'
KCPPFLAGS='-D__KERNEL__ -DMODULE'
MOD_LINK=elf64_ia64
;;
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
* vim:expandtab:shiftwidth=8:tabstop=8:
*
- * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
+ * Copyright (c) 2002 Cluster File Systems, Inc. <info@clusterfs.com>
*
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
+ * This file is part of Lustre, http://www.lustre.org.
+ *
+ * Lustre is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * Lustre is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Lustre; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define DEBUG_SUBSYSTEM S_COBD
#include <linux/obd_class.h>
#include <linux/obd_cache.h>
-extern struct lprocfs_vars status_var_nm_1[];
-extern struct lprocfs_vars status_class_var[];
-
-static int
-cobd_attach (struct obd_device *dev, obd_count len, void *data)
+static int cobd_attach(struct obd_device *dev, obd_count len, void *data)
{
- return (lprocfs_reg_obd (dev, status_var_nm_1, dev));
+ struct lprocfs_static_vars lvars;
+
+ lprocfs_init_vars(&lvars);
+ return lprocfs_obd_attach(dev, lvars.obd_vars);
}
-static int
-cobd_detach (struct obd_device *dev)
+static int cobd_detach(struct obd_device *dev)
{
- return (lprocfs_dereg_obd (dev));
+ return lprocfs_obd_detach(dev);
}
static int
struct cache_obd *cobd = &dev->u.cobd;
struct obd_device *target;
struct obd_device *cache;
+ struct obd_uuid target_uuid;
+ struct obd_uuid cache_uuid;
int rc;
-
+
if (data->ioc_inlbuf1 == NULL ||
data->ioc_inlbuf2 == NULL)
return (-EINVAL);
-
- target = class_uuid2obd (data->ioc_inlbuf1);
- cache = class_uuid2obd (data->ioc_inlbuf2);
+
+ obd_str2uuid(&target_uuid, data->ioc_inlbuf1);
+ target = class_uuid2obd (&target_uuid);
+
+ obd_str2uuid(&cache_uuid, data->ioc_inlbuf2);
+ cache = class_uuid2obd (&cache_uuid);
if (target == NULL ||
cache == NULL)
return (-EINVAL);
-
- /* don't bother checking attached/setup;
- * obd_connect() should, and it can change underneath us */
- rc = obd_connect (&cobd->cobd_target, target, NULL, NULL, NULL);
+ /* don't bother checking attached/setup;
+ * obd_connect() should, and it can change underneath us */
+ rc = obd_connect (&cobd->cobd_target, target, &target_uuid, NULL, NULL);
if (rc != 0)
return (rc);
- rc = obd_connect (&cobd->cobd_cache, cache, NULL, NULL, NULL);
+ rc = obd_connect (&cobd->cobd_cache, cache, &cache_uuid, NULL, NULL);
if (rc != 0)
goto fail_0;
{
struct cache_obd *cobd = &dev->u.cobd;
int rc;
-
+
if (!list_empty (&dev->obd_exports))
return (-EBUSY);
-
+
rc = obd_disconnect (&cobd->cobd_cache);
if (rc != 0)
CERROR ("error %d disconnecting cache\n", rc);
-
+
rc = obd_disconnect (&cobd->cobd_target);
if (rc != 0)
CERROR ("error %d disconnecting target\n", rc);
static int
cobd_connect (struct lustre_handle *conn, struct obd_device *obd,
- obd_uuid_t cluuid, struct recovd_obd *recovd,
+ struct obd_uuid *cluuid, struct recovd_obd *recovd,
ptlrpc_recovery_cb_t recover)
{
int rc = class_connect (conn, obd, cluuid);
cobd_disconnect (struct lustre_handle *conn)
{
int rc = class_disconnect (conn);
-
+
CERROR ("rc %d\n", rc);
return (rc);
}
-static int
+static int
cobd_get_info(struct lustre_handle *conn, obd_count keylen,
void *key, obd_count *vallen, void **val)
{
/* intercept cache utilisation info? */
- return (obd_get_info (&cobd->cobd_target,
+ return (obd_get_info (&cobd->cobd_target,
keylen, key, vallen, val));
}
-static int
+static int
cobd_statfs(struct lustre_handle *conn, struct obd_statfs *osfs)
{
struct obd_device *obd = class_conn2obd(conn);
return (obd_statfs (&cobd->cobd_target, osfs));
}
-static int
+static int
cobd_getattr(struct lustre_handle *conn, struct obdo *oa,
struct lov_stripe_md *lsm)
{
return (obd_getattr (&cobd->cobd_target, oa, lsm));
}
-static int
+static int
cobd_open(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *lsm)
+ struct lov_stripe_md *lsm, struct obd_trans_info *oti)
{
struct obd_device *obd = class_conn2obd(conn);
struct cache_obd *cobd;
}
cobd = &obd->u.cobd;
- return (obd_open (&cobd->cobd_target, oa, lsm));
+ return (obd_open (&cobd->cobd_target, oa, lsm, oti));
}
-static int
+static int
cobd_close(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *lsm)
+ struct lov_stripe_md *lsm, struct obd_trans_info *oti)
{
struct obd_device *obd = class_conn2obd(conn);
struct cache_obd *cobd;
}
cobd = &obd->u.cobd;
- return (obd_close (&cobd->cobd_target, oa, lsm));
+ return (obd_close (&cobd->cobd_target, oa, lsm, oti));
}
-static int
+static int
cobd_preprw(int cmd, struct lustre_handle *conn,
int objcount, struct obd_ioobj *obj,
int niocount, struct niobuf_remote *nb,
- struct niobuf_local *res, void **desc_private)
+ struct niobuf_local *res, void **desc_private,
+ struct obd_trans_info *oti)
{
struct obd_device *obd = class_conn2obd(conn);
struct cache_obd *cobd;
if ((cmd & OBD_BRW_WRITE) != 0)
return -EOPNOTSUPP;
-
+
cobd = &obd->u.cobd;
- return (obd_preprw (cmd, &cobd->cobd_target,
- objcount, obj,
- niocount, nb,
- res, desc_private));
+ return (obd_preprw (cmd, &cobd->cobd_target,
+ objcount, obj,
+ niocount, nb,
+ res, desc_private, oti));
}
-static int
+static int
cobd_commitrw(int cmd, struct lustre_handle *conn,
int objcount, struct obd_ioobj *obj,
int niocount, struct niobuf_local *local,
- void *desc_private)
+ void *desc_private, struct obd_trans_info *oti)
{
struct obd_device *obd = class_conn2obd(conn);
struct cache_obd *cobd;
if ((cmd & OBD_BRW_WRITE) != 0)
return -EOPNOTSUPP;
-
+
cobd = &obd->u.cobd;
return (obd_commitrw (cmd, &cobd->cobd_target,
objcount, obj,
niocount, local,
- desc_private));
+ desc_private, oti));
}
-static inline int
+static inline int
cobd_brw(int cmd, struct lustre_handle *conn,
struct lov_stripe_md *lsm, obd_count oa_bufs,
- struct brw_page *pga, struct obd_brw_set *set)
+ struct brw_page *pga, struct obd_brw_set *set,
+ struct obd_trans_info *oti)
{
struct obd_device *obd = class_conn2obd(conn);
struct cache_obd *cobd;
if ((cmd & OBD_BRW_WRITE) != 0)
return -EOPNOTSUPP;
-
+
cobd = &obd->u.cobd;
- return (obd_brw (cmd, &cobd->cobd_target,
- lsm, oa_bufs, pga, set));
+ return (obd_brw (cmd, &cobd->cobd_target,
+ lsm, oa_bufs, pga, set, oti));
}
-static int
+static int
cobd_iocontrol(unsigned int cmd, struct lustre_handle *conn, int len,
void *karg, void *uarg)
{
o_iocontrol: cobd_iocontrol,
};
-static int __init
-cobd_init (void)
+static int __init cobd_init(void)
{
- int rc;
-
- printk (KERN_INFO "Lustre Caching OBD driver\n");
-
- rc = class_register_type (&cobd_ops, status_class_var,
- OBD_CACHE_DEVICENAME);
- return (rc);
+ struct lprocfs_static_vars lvars;
+ ENTRY;
+
+ printk(KERN_INFO "Lustre Caching OBD driver; info@clusterfs.com\n");
+
+ lprocfs_init_vars(&lvars);
+ RETURN(class_register_type(&cobd_ops, lvars.module_vars,
+ OBD_CACHE_DEVICENAME));
}
-static void __exit
-cobd_exit (void)
+static void __exit cobd_exit(void)
{
- class_unregister_type (OBD_CACHE_DEVICENAME);
+ class_unregister_type(OBD_CACHE_DEVICENAME);
}
-MODULE_AUTHOR("Cluster Filesystems Inc. <info@clusterfs.com>");
+MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
MODULE_DESCRIPTION("Lustre Caching OBD driver");
MODULE_LICENSE("GPL");
module_init(cobd_init);
module_exit(cobd_exit);
-
-
#include <linux/lustre_lite.h>
#include <linux/lprocfs_status.h>
-/*
- * Common STATUS namespace
- */
-
-static int rd_uuid (char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- struct obd_device* dev = (struct obd_device*)data;
-
- return (snprintf(page, count, "%s\n", dev->obd_uuid));
-}
-
-static int rd_target (char *page, char **start, off_t off, int count,
- int *eof, void *data)
+#ifndef LPROCFS
+struct lprocfs_vars lprocfs_obd_vars[] = { {0} };
+struct lprocfs_vars lprocfs_module_vars[] = { {0} };
+#else
+/* Common STATUS namespace */
+static int rd_target(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
{
struct obd_device *dev = (struct obd_device*)data;
- struct cache_obd *cobd = &dev->u.cobd;
- struct lustre_handle *conn = &cobd->cobd_target;
+ struct lustre_handle *conn = &dev->u.cobd.cobd_target;
struct obd_export *exp;
int rc;
rc = snprintf (page, count, "not set up\n");
else {
exp = class_conn2export (conn);
- LASSERT (exp != NULL);
- rc = snprintf(page, count, "%s\n", exp->exp_obd->obd_uuid);
+ LASSERT(exp != NULL);
+ rc = snprintf(page, count, "%s\n", exp->exp_obd->obd_uuid.uuid);
}
return (rc);
}
int *eof, void *data)
{
struct obd_device *dev = (struct obd_device*)data;
- struct cache_obd *cobd = &dev->u.cobd;
- struct lustre_handle *conn = &cobd->cobd_cache;
+ struct lustre_handle *conn = &dev->u.cobd.cobd_cache;
struct obd_export *exp;
int rc;
else {
exp = class_conn2export (conn);
LASSERT (exp != NULL);
- rc = snprintf(page, count, "%s\n", exp->exp_obd->obd_uuid);
+ rc = snprintf(page, count, "%s\n", exp->exp_obd->obd_uuid.uuid);
}
return (rc);
}
-struct lprocfs_vars status_var_nm_1[] = {
- {"status/uuid", rd_uuid, 0, 0},
- {"status/target_uuid", rd_target, 0, 0},
- {"status/cache_uuid", rd_cache, 0, 0},
- {0}
+struct lprocfs_vars lprocfs_obd_vars[] = {
+ { "uuid", lprocfs_rd_uuid, 0, 0 },
+ { "target_uuid", rd_target, 0, 0 },
+ { "cache_uuid", rd_cache, 0, 0 },
+ { 0 }
};
-int rd_numrefs(char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- struct obd_type* class = (struct obd_type*)data;
-
- return (snprintf(page, count, "%d\n", class->typ_refcnt));
-}
-
-struct lprocfs_vars status_class_var[] = {
- {"status/num_refs", rd_numrefs, 0, 0},
- {0}
+struct lprocfs_vars lprocfs_module_vars[] = {
+ { "num_refs", lprocfs_rd_numrefs, 0, 0 },
+ { 0 }
};
+#endif /* LPROCFS */
+
+LPROCFS_INIT_VARS(lprocfs_module_vars, lprocfs_obd_vars)
# This code is issued under the GNU General Public License.
# See the file COPYING in this distribution
-EXTRA_DIST = lustre2ldif.xsl lustre.dtd lustre.schema slapd-lustre.conf
+EXTRA_DIST = lustre.dtd lustre.schema slapd-lustre.conf lustre2ldif.xsl top.ldif
ldapconfdir = $(sysconfdir)/openldap
ldapschemadir = $(sysconfdir)/openldap/schema
ldapconf_SCRIPTS = slapd-lustre.conf
ldapschema_SCRIPTS = lustre.schema
+pkglibdir = '${exec_prefix}/usr/lib/$(PACKAGE)'
+pkglib_DATA = top.ldif lustre2ldif.xsl
include $(top_srcdir)/Rules
mdsRef: <value-of select="@uuidref"/>
</template>
+<template match="mdsdev_ref">
+mdsdevRef: <value-of select="@uuidref"/>
+</template>
+
<template match="mountpoint_ref">
mountpointRef: <value-of select="@uuidref"/>
</template>
AC_INIT
AC_CANONICAL_SYSTEM
-# Copyright (C) 2001 Cluster File Systems, Inc.
+# Copyright (C) 2001-2003 Cluster File Systems, Inc.
#
# This code is issued under the GNU General Public License.
# See the file COPYING in this distribution
# Automake variables. Steal the version number from lustre.spec.in.
AM_INIT_AUTOMAKE(lustre, builtin([esyscmd], [sed -ne '/^%define version /{ s/.*version //; p; q; }' scripts/lustre.spec.in]))
#AM_MAINTAINER_MODE
+
AC_PROG_CC
+AC_MSG_CHECKING(for buggy compiler)
+CC_VERSION=`$CC -v 2>&1 | grep "^gcc version"`
+bad_cc() {
+ echo
+ echo " '$CC_VERSION'"
+ echo " has been known to generate bad code, "
+ echo " please get an updated compiler."
+ AC_MSG_ERROR(sorry)
+}
+case "$CC_VERSION" in
+ # ost_pack_niobuf putting 64bit NTOH temporaries on the stack
+ # without "sub $0xc,%esp" to protect the stack from being
+ # stomped on by interrupts (bug 606)
+ "gcc version 2.96 20000731 (Red Hat Linux 7.1 2.96-98)")
+ bad_cc
+ ;;
+ *)
+ AC_MSG_RESULT(no known problems)
+ ;;
+esac
+
AC_PROG_RANLIB
#
EXTNP = htree-ext3-2.4.18.diff linux-2.4.18ea-0.8.26.diff
EXTNP+= ext3-2.4.18-ino_sb_macro.diff extN-misc-fixup.diff extN-noread.diff
EXTNP+= extN-wantedi.diff
+#EXTNP+= extN-iget-debug.diff
EXTNC = balloc.c bitmap.c dir.c file.c fsync.c ialloc.c inode.c ioctl.c
EXTNC+= namei.c super.c symlink.c
EXTNI = extN_fs.h extN_fs_i.h extN_fs_sb.h extN_jbd.h quotaops.h
list='$(EXTN_EXTRA)'; for f in $$list; do $(RM) $(top_builddir)/$$f; done
if [ -f $(srcdir)/extN.patch-$(RELEASE) ]; then \
echo "applying patch $(srcdir)/extN.patch-$(RELEASE)"; \
- (cd $(top_builddir) && patch -p0) < $(srcdir)/extN.patch-$(RELEASE); \
+ (cd $(top_builddir) && patch -p0) < $(srcdir)/extN.patch-$(RELEASE);\
else \
- echo "If first patch fails, read NOTE in extN/Makefile.am"; \
list='$(EXTNP)'; \
- sed '/i_version/q' $(extN_orig)/namei.c | tail -2 | \
- grep extN_mark_inode_dirty >/dev/null && list="$(EXTN_FIXES) $$list"; \
+ grep -q "err = extN_mark_inode_dirty" $(extN_orig)/namei.c || \
+ list="ext3-use-after-free.diff $$list"; \
+ sed '/i_version/q' $(extN_orig)/namei.c | tail -2 | \
+ grep -q extN_mark_inode_dirty && list="$(EXTN_FIXES) $$list"; \
+ grep -q "if (do_sync_supers)" $(extN_orig)/super.c && \
+ list="ext3-unmount_sync.diff $$list"; \
for p in $$list; do \
echo "applying patch $$p"; \
sed $(SUB) $(srcdir)/$$p | \
- (cd $(top_builddir) && patch -p1) || exit $$?; \
+ (cd $(top_builddir) && patch -p1) || exit $$?; \
done; \
- echo "It is OK if the next patch says it is already applied"; \
+ echo "It is OK if the next patch says it is skipping this patch"; \
echo "applying patch $(srcdir)/extN-2.4.18-exports.diff"; \
(cd $(top_builddir) && \
patch -N -p1) < $(srcdir)/extN-2.4.18-exports.diff; \
--- /dev/null
+From adilger@clusterfs.com Mon Dec 2 10:26:44 2002
+Date: Mon, 2 Dec 2002 10:26:44 -0700
+From: Andreas Dilger <adilger@clusterfs.com>
+To: Lustre LLNL Mailing list <lc-lustre@llnl.gov>,
+ Lustre Development Mailing List <lustre-devel@lists.sourceforge.net>
+Subject: Re: data corrupting bug in 2.4.20 ext3, data=journal
+Message-ID: <20021202102644.H1422@schatzie.adilger.int>
+Mail-Followup-To: Lustre LLNL Mailing list <lc-lustre@llnl.gov>,
+ Lustre Development Mailing List <lustre-devel@lists.sourceforge.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: inline
+User-Agent: Mutt/1.2.5.1i
+X-GPG-Key: 1024D/0D35BED6
+X-GPG-Fingerprint: 7A37 5D79 BF1B CECA D44F 8A29 A488 39F5 0D35 BED6
+Status: RO
+Content-Length: 1160
+Lines: 39
+
+Here is the new-improved fix for the ext3 discarding data at umount bug
+discovered late last week. To be used instead of the previous ext3 fix.
+
+Sadly, this is completely unrelated to the problems Mike is having with
+ext3 under UML, since it is an unmount-time problem.
+
+----- Forwarded message from "Stephen C. Tweedie" <sct@redhat.com> -----
+The attached patch seems to fix things for me.
+
+Cheers,
+ Stephen
+
+
+--- linux-2.4-ext3merge/fs/ext3/super.c.=K0027=.orig 2002-12-02 15:35:13.000000000 +0000
++++ linux-2.4-ext3merge/fs/ext3/super.c 2002-12-02 15:35:14.000000000 +0000
+@@ -1640,7 +1640,12 @@
+ sb->s_dirt = 0;
+ target = log_start_commit(EXT3_SB(sb)->s_journal, NULL);
+
+- if (do_sync_supers) {
++ /*
++ * Tricky --- if we are unmounting, the write really does need
++ * to be synchronous. We can detect that by looking for NULL in
++ * sb->s_root.
++ */
++ if (do_sync_supers || !sb->s_root) {
+ unlock_super(sb);
+ log_wait_commit(EXT3_SB(sb)->s_journal, target);
+ lock_super(sb);
+
+
+----- End forwarded message -----
+
+Cheers, Andreas
+--
+Andreas Dilger
+http://sourceforge.net/projects/ext2resize/
+http://www-mddsp.enel.ucalgary.ca/People/adilger/
+
+
--- /dev/null
+
+
+If ext3_add_nondir() fails it will do an iput() of the inode. But we
+continue to run ext3_mark_inode_dirty() against the potentially-freed
+inode. This oopses when slab poisoning is enabled.
+
+Fix it so that we only run ext3_mark_inode_dirty() if the inode was
+successfully instantiated.
+
+This bug was added in 2.4.20-pre9.
+
+
+ fs/ext3/namei.c | 11 +++++------
+ 1 files changed, 5 insertions(+), 6 deletions(-)
+
+--- 24/fs/ext3/namei.c~ext3-use-after-free Sun Dec 15 11:27:50 2002
++++ 24-akpm/fs/ext3/namei.c Sun Dec 15 11:27:50 2002
+@@ -429,8 +429,11 @@ static int ext3_add_nondir(handle_t *han
+ {
+ int err = ext3_add_entry(handle, dentry, inode);
+ if (!err) {
+- d_instantiate(dentry, inode);
+- return 0;
++ err = ext3_mark_inode_dirty(handle, inode);
++ if (err == 0) {
++ d_instantiate(dentry, inode);
++ return 0;
++ }
+ }
+ ext3_dec_count(handle, inode);
+ iput(inode);
+@@ -465,7 +468,6 @@ static int ext3_create (struct inode * d
+ inode->i_fop = &ext3_file_operations;
+ inode->i_mapping->a_ops = &ext3_aops;
+ err = ext3_add_nondir(handle, dentry, inode);
+- ext3_mark_inode_dirty(handle, inode);
+ }
+ ext3_journal_stop(handle, dir);
+ return err;
+@@ -490,7 +492,6 @@ static int ext3_mknod (struct inode * di
+ if (!IS_ERR(inode)) {
+ init_special_inode(inode, mode, rdev);
+ err = ext3_add_nondir(handle, dentry, inode);
+- ext3_mark_inode_dirty(handle, inode);
+ }
+ ext3_journal_stop(handle, dir);
+ return err;
+@@ -934,7 +935,6 @@ static int ext3_symlink (struct inode *
+ }
+ inode->u.ext3_i.i_disksize = inode->i_size;
+ err = ext3_add_nondir(handle, dentry, inode);
+- ext3_mark_inode_dirty(handle, inode);
+ out_stop:
+ ext3_journal_stop(handle, dir);
+ return err;
+@@ -971,7 +971,6 @@ static int ext3_link (struct dentry * ol
+ atomic_inc(&inode->i_count);
+
+ err = ext3_add_nondir(handle, dentry, inode);
+- ext3_mark_inode_dirty(handle, inode);
+ ext3_journal_stop(handle, dir);
+ return err;
+ }
+
+_
--- /dev/null
+--- linux/fs/ext3/namei.c.orig Thu Jan 30 01:15:13 2003
++++ linux/fs/ext3/namei.c Sat Feb 1 00:33:46 2003
+@@ -710,6 +710,24 @@
+ return ret;
+ }
+
++static int extN_find_inode(struct inode *inode, unsigned long ino,
++ void *opaque)
++{
++ const char *name = NULL;
++ int len = 0;
++
++ if (opaque) {
++ struct dentry *dentry = opaque;
++ name = dentry->d_name.name;
++ len = dentry->d_name.len;
++ }
++ printk(KERN_INFO "finding inode %s:%lu (%p) count %d (%p = %*s)\n",
++ kdevname(inode->i_dev), ino, inode, atomic_read(&inode->i_count),
++ opaque, len, name ? name : "");
++
++ return 1;
++}
++
+ static struct dentry *extN_lookup(struct inode * dir, struct dentry *dentry)
+ {
+ struct inode * inode;
+@@ -724,7 +742,7 @@
+ if (bh) {
+ unsigned long ino = le32_to_cpu(de->inode);
+ brelse (bh);
+- inode = iget(dir->i_sb, ino);
++ inode = iget4(dir->i_sb, ino, extN_find_inode, dentry);
+
+ if (!inode)
+ return ERR_PTR(-EACCES);
+--- linux/fs/ext3/inode.c.orig Thu Jan 30 01:15:13 2003
++++ linux/fs/ext3/inode.c Sat Feb 1 00:34:45 2003
+@@ -166,6 +166,9 @@
+ */
+ void extN_put_inode (struct inode * inode)
+ {
++ printk(KERN_INFO "putting inode %s:%lu (%p) count %d\n",
++ kdevname(inode->i_dev), inode->i_ino, inode,
++ atomic_read(&inode->i_count));
+ extN_discard_prealloc (inode);
+ }
+
goto out_journal;
}
EXTN_SB(sb)->journal_bdev = bdev;
+@@ -1560,6 +1560,7 @@
+ unlock_kernel();
+ return ret;
+ }
++EXPORT_SYMBOL(extN_force_commit); /* here to avoid potential patch collisions */
+
+ /*
+ * Ext3 always journals updates to the superblock itself, so we don't
+ if (err) goto fail;
+
+ if (extN_set_bit(j, bh->b_data)) {
-+ printk(KERN_ERR "goal inode %lu unavailable", goal);
++ printk(KERN_ERR "goal inode %lu unavailable\n", goal);
+ /* Oh well, we tried. */
+ goto repeat;
+ }
static struct buffer_head * ext3_find_entry (struct dentry *dentry,
struct ext3_dir_entry_2 ** res_dir)
{
-@@ -119,10 +564,76 @@
+@@ -119,10 +564,70 @@
int num = 0;
int nblocks, i, err;
struct inode *dir = dentry->d_parent->d_inode;
-+ int namelen;
-+ const u8 *name;
-+ unsigned blocksize;
+ ext3_dirent *de, *top;
*res_dir = NULL;
sb = dir->i_sb;
-+ blocksize = sb->s_blocksize;
-+ namelen = dentry->d_name.len;
-+ name = dentry->d_name.name;
-+ if (namelen > EXT3_NAME_LEN)
++ if (dentry->d_name.len > EXT3_NAME_LEN)
+ return NULL;
+ if (ext3_dx && is_dx(dir)) {
-+ u32 hash = dx_hash (name, namelen);
++ u32 hash = dx_hash(dentry->d_name.name, dentry->d_name.len);
+ struct dx_frame frames[2], *frame;
+ if (!(frame = dx_probe (dir, hash, frames)))
+ return NULL;
+ if (!(bh = ext3_bread (NULL,dir, block, 0, &err)))
+ goto dxfail;
+ de = (ext3_dirent *) bh->b_data;
-+ top = (ext3_dirent *) ((char *) de + blocksize -
++ top = (ext3_dirent *) ((char *) de + sb->s_blocksize -
+ EXT3_DIR_REC_LEN(0));
+ for (; de < top; de = ext3_next_entry(de))
-+ if (ext3_match (namelen, name, de)) {
++ if (ext3_match(dentry->d_name.len, dentry->d_name.name, de)) {
+ if (!ext3_check_dir_entry("ext3_find_entry",
+ dir, de, bh,
+ (block<<EXT3_BLOCK_SIZE_BITS(sb))
nblocks = dir->i_size >> EXT3_BLOCK_SIZE_BITS(sb);
start = dir->u.ext3_i.i_dir_start_lookup;
if (start >= nblocks)
-@@ -237,6 +748,92 @@
+@@ -237,6 +748,90 @@
de->file_type = ext3_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
}
+ struct buffer_head **bh,struct dx_frame *frame,
+ u32 hash, int *error)
+{
-+ unsigned blocksize = dir->i_sb->s_blocksize;
-+ unsigned count, continued;
++ unsigned count;
+ struct buffer_head *bh2;
+ u32 newblock;
-+ unsigned MAX_DX_MAP = PAGE_CACHE_SIZE/EXT3_DIR_REC_LEN(1) + 1;
+ u32 hash2;
+ struct dx_map_entry *map;
+ char *data1 = (*bh)->b_data, *data2, *data3;
+
+ data2 = bh2->b_data;
+
-+ map = kmalloc(sizeof(*map) * MAX_DX_MAP, GFP_KERNEL);
++ map = kmalloc(sizeof(*map) * PAGE_CACHE_SIZE/EXT3_DIR_REC_LEN(1) + 1,
++ GFP_KERNEL);
+ if (!map)
+ panic("no memory for do_split\n");
-+ count = dx_make_map ((ext3_dirent *) data1, blocksize, map);
++ count = dx_make_map((ext3_dirent *)data1, dir->i_sb->s_blocksize, map);
+ split = count/2; // need to adjust to actual middle
+ dx_sort_map (map, count);
+ hash2 = map[split].hash;
-+ continued = hash2 == map[split - 1].hash;
+ dxtrace(printk("Split block %i at %x, %i/%i\n",
+ dx_get_block(frame->at), hash2, split, count-split));
+
+ de = dx_copy_dirents (data1, data3, map, split);
+ memcpy(data1, data3, (char *) de + de->rec_len - data3);
+ de = (ext3_dirent *) ((char *) de - data3 + data1); // relocate de
-+ de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
-+ de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2);
-+ dxtrace(dx_show_leaf ((ext3_dirent *) data1, blocksize, 1));
-+ dxtrace(dx_show_leaf ((ext3_dirent *) data2, blocksize, 1));
++ de->rec_len = cpu_to_le16(data1 + dir->i_sb->s_blocksize - (char *)de);
++ de2->rec_len = cpu_to_le16(data2 + dir->i_sb->s_blocksize-(char *)de2);
++ dxtrace(dx_show_leaf((ext3_dirent *)data1, dir->i_sb->s_blocksize, 1));
++ dxtrace(dx_show_leaf((ext3_dirent *)data2, dir->i_sb->s_blocksize, 1));
+
+ /* Which block gets the new entry? */
+ if (hash >= hash2)
+ swap(*bh, bh2);
+ de = de2;
+ }
-+ dx_insert_block (frame, hash2 + continued, newblock);
++ dx_insert_block(frame, hash2 + (hash2 == map[split-1].hash), newblock);
+ ext3_journal_dirty_metadata (handle, bh2);
+ brelse (bh2);
+ ext3_journal_dirty_metadata (handle, frame->bh);
/*
* ext3_add_entry()
*
-@@ -251,6 +844,7 @@
- /*
- * AKPM: the journalling code here looks wrong on the error paths
- */
-+
- static int ext3_add_entry (handle_t *handle, struct dentry *dentry,
+@@ -255,118 +849,278 @@
struct inode *inode)
{
-@@ -258,117 +852,281 @@
- const char *name = dentry->d_name.name;
- int namelen = dentry->d_name.len;
+ struct inode *dir = dentry->d_parent->d_inode;
+- const char *name = dentry->d_name.name;
+- int namelen = dentry->d_name.len;
unsigned long offset;
- unsigned short rec_len;
struct buffer_head * bh;
+ ext3_dirent *de;
+ struct super_block * sb = dir->i_sb;
int retval;
-+ unsigned short reclen = EXT3_DIR_REC_LEN(namelen);
++ unsigned short reclen = EXT3_DIR_REC_LEN(dentry->d_name.len);
- sb = dir->i_sb;
-+ unsigned blocksize = sb->s_blocksize;
+ unsigned nlen, rlen;
+ u32 block, blocks;
+ char *top;
- if (!namelen)
+- if (!namelen)
++ if (!dentry->d_name.len)
return -EINVAL;
- bh = ext3_bread (handle, dir, 0, 0, &retval);
- if (!bh)
+ u32 hash;
+ char *data1;
+
-+ hash = dx_hash(name, namelen);
++ hash = dx_hash(dentry->d_name.name, dentry->d_name.len);
+ /* FIXME: do something if dx_probe() fails here */
+ frame = dx_probe(dir, hash, frames);
+ entries = frame->entries;
+
+ data1 = bh->b_data;
+ de = (ext3_dirent *) data1;
-+ top = data1 + (0? 200: blocksize);
++ top = data1 + (0? 200: sb->s_blocksize);
+ while ((char *) de < top)
+ {
+ /* FIXME: check EEXIST and dir */
+ goto dxfail2;
+ node2 = (struct dx_node *)(bh2->b_data);
+ entries2 = node2->entries;
-+ node2->fake.rec_len = cpu_to_le16(blocksize);
++ node2->fake.rec_len = cpu_to_le16(sb->s_blocksize);
+ node2->fake.inode = 0;
+ BUFFER_TRACE(frame->bh, "get_write_access");
+ ext3_journal_get_write_access(handle, frame->bh);
+ if(!bh)
+ return retval;
+ de = (ext3_dirent *)bh->b_data;
-+ top = bh->b_data + blocksize - reclen;
++ top = bh->b_data + sb->s_blocksize - reclen;
+ while ((char *) de <= top) {
+ if (!ext3_check_dir_entry("ext3_add_entry", dir, de,
+ bh, offset)) {
+ brelse (bh);
+ return -EIO;
+ }
-+ if (ext3_match (namelen, name, de)) {
++ if (ext3_match(dentry->d_name.len,dentry->d_name.name,de)) {
brelse (bh);
return -EEXIST;
- }
- ext3_journal_dirty_metadata(handle, bh);
+ nlen = EXT3_DIR_REC_LEN(de->name_len);
+ rlen = le16_to_cpu(de->rec_len);
-+ if ((de->inode? rlen - nlen: rlen) >= reclen)
++ if ((de->inode ? rlen - nlen: rlen) >= reclen)
+ goto add;
+ de = (ext3_dirent *)((char *)de + rlen);
+ offset += rlen;
+ return retval;
+ de = (ext3_dirent *) bh->b_data;
+ de->inode = 0;
-+ de->rec_len = cpu_to_le16(rlen = blocksize);
++ de->rec_len = cpu_to_le16(rlen = sb->s_blocksize);
+ nlen = 0;
+ goto add;
+
+ ext3_set_de_type(dir->i_sb, de, inode->i_mode);
+ } else
+ de->inode = 0;
-+ de->name_len = namelen;
-+ memcpy (de->name, name, namelen);
++ de->name_len = dentry->d_name.len;
++ memcpy (de->name, dentry->d_name.name, dentry->d_name.len);
+ /*
+ * XXX shouldn't update any times until successful
+ * completion of syscall, but too many callers depend
+
+ /* The 0th block becomes the root, move the dirents out */
+ de = (ext3_dirent *) &root->info;
-+ len = ((char *) root) + blocksize - (char *) de;
++ len = ((char *) root) + sb->s_blocksize - (char *) de;
+ memcpy (data1, de, len);
+ de = (ext3_dirent *) data1;
+ top = data1 + len;
+ while (((char *) de2=(char*)de+le16_to_cpu(de->rec_len)) < top)
+ de = de2;
-+ de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
++ de->rec_len = cpu_to_le16(data1 + sb->s_blocksize - (char *)de);
+ /* Initialize the root; the dot dirents already exist */
+ de = (ext3_dirent *) (&root->dotdot);
-+ de->rec_len = cpu_to_le16(blocksize - EXT3_DIR_REC_LEN(2));
++ de->rec_len = cpu_to_le16(sb->s_blocksize-EXT3_DIR_REC_LEN(2));
+ memset (&root->info, 0, sizeof(root->info));
+ root->info.info_length = sizeof(root->info);
+ entries = root->entries;
+ dx_set_limit (entries, dx_root_limit(dir, sizeof(root->info)));
+
+ /* Initialize as for dx_probe */
-+ hash = dx_hash (name, namelen);
++ hash = dx_hash (dentry->d_name.name, dentry->d_name.len);
+ frame = frames;
+ frame->entries = entries;
+ frame->at = entries;
+ return -ENOENT;
}
-+
/*
- * ext3_delete_entry deletes a directory entry by merging it with the
- * previous entry
@@ -451,7 +1212,8 @@
struct inode * inode;
int err;
#include <linux/fcntl.h>
#include <linux/stat.h>
#include <linux/string.h>
-@@ -465,6 +466,8 @@
- inode->i_fop = &extN_file_operations;
- inode->i_mapping->a_ops = &ext3_aops;
- err = ext3_add_nondir(handle, dentry, inode);
-+ if (err)
-+ ext3_xattr_drop_inode(handle, inode);
- ext3_mark_inode_dirty(handle, inode);
- }
- ext3_journal_stop(handle, dir);
-@@ -490,6 +493,8 @@
- if (!IS_ERR(inode)) {
- init_special_inode(inode, mode, rdev);
- err = ext3_add_nondir(handle, dentry, inode);
-+ if (err)
-+ ext3_xattr_drop_inode(handle, inode);
- ext3_mark_inode_dirty(handle, inode);
+@@ -435,6 +435,7 @@ static int ext3_add_nondir(handle_t *han
+ return 0;
+ }
}
- ext3_journal_stop(handle, dir);
++ ext3_xattr_drop_inode(handle, inode);
+ ext3_dec_count(handle, inode);
+ iput(inode);
+ return err;
@@ -514,7 +519,7 @@
if (IS_SYNC(dir))
handle->h_sync = 1;
ext3_mark_inode_dirty(handle, inode);
err = ext3_add_entry (handle, dentry, inode);
if (err)
-@@ -565,6 +566,7 @@
- return err;
-
- out_no_entry:
-+ ext3_xattr_drop_inode(handle, inode);
- inode->i_nlink = 0;
- ext3_mark_inode_dirty(handle, inode);
- iput (inode);
@@ -917,5 +919,5 @@
goto out_stop;
#ifndef _LPROCFS_SNMP_H
#define _LPROCFS_SNMP_H
-
-#ifndef LPROC_SNMP
-#define LPROC_SNMP
-#endif
-
+#include <linux/autoconf.h>
#include <linux/proc_fs.h>
-typedef enum {
- E_LPROC_OK = 0
-} lproc_error_t;
-
-struct lprocfs_vars{
+#ifndef LPROCFS
+#ifdef CONFIG_PROC_FS /* Ensure that /proc is configured */
+#define LPROCFS
+#endif
+#endif
- char* name;
- read_proc_t* read_fptr;
- write_proc_t* write_fptr;
- void* data;
+struct lprocfs_vars {
+ char *name;
+ read_proc_t *read_fptr;
+ write_proc_t *write_fptr;
+ void *data;
};
-#ifdef LPROC_SNMP
-
-struct proc_dir_entry* lprocfs_mkdir(const char *dname,
- struct proc_dir_entry *parent);
-struct proc_dir_entry* lprocfs_srch(struct proc_dir_entry *head,
- const char *name);
-void lprocfs_remove_all(struct proc_dir_entry *root);
-struct proc_dir_entry* lprocfs_new_dir(struct proc_dir_entry *root,
- const char *string,
- const char *tok);
-int lprocfs_new_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
- const char *tok, void *data);
-
-int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *var,
- void *data);
-int lprocfs_reg_obd(struct obd_device *device, struct lprocfs_vars *list,
- void *data);
-int lprocfs_dereg_obd(struct obd_device *device);
-struct proc_dir_entry* lprocfs_reg_mnt(char *mnt_name);
-int lprocfs_dereg_mnt(struct proc_dir_entry *root);
-
-int lprocfs_reg_class(struct obd_type *type, struct lprocfs_vars *list,
- void *data);
-int lprocfs_dereg_class(struct obd_type *class);
-int lprocfs_reg_main(void);
-int lprocfs_dereg_main(void);
-int lprocfs_ll_rd(char *page, char **start, off_t off, int count, int *eof,
- void *data);
-#else
-
-
-static inline int lprocfs_add_vars(struct proc_dir_entry *root,
- struct lprocfs_vars *var, void *data)
-{
- return 0;
-}
-
-static inline int lprocfs_reg_obd(struct obd_device* device,
- struct lprocfs_vars* list, void* data)
-{
- return 0;
-}
-
-static inline int lprocfs_dereg_obd(struct obd_device* device)
-{
- return 0;
-}
-
-static inline struct proc_dir_entry* lprocfs_reg_mnt(char *name)
-{
- return NULL;
-}
-
-static inline int lprocfs_dereg_mnt(struct proc_dir_entry* root)
-{
- return 0;
-}
-
-static inline int lprocfs_reg_class(struct obd_type* type,
- struct lprocfs_vars* list, void* data)
-{
- return 0;
-}
-
-static inline int lprocfs_dereg_class(struct obd_type* class)
-{
- return 0;
-}
+struct lprocfs_static_vars {
+ struct lprocfs_vars *module_vars;
+ struct lprocfs_vars *obd_vars;
+};
-static inline int lprocfs_reg_main(void)
-{
- return 0;
+/* class_obd.c */
+extern struct proc_dir_entry *proc_lustre_root;
+
+extern void lprocfs_init_vars(struct lprocfs_static_vars *var);
+extern void lprocfs_init_multi_vars(unsigned int idx,
+ struct lprocfs_static_vars *var);
+
+#define LPROCFS_INIT_MULTI_VARS(array, size) \
+void lprocfs_init_multi_vars(unsigned int idx, \
+ struct lprocfs_static_vars *x) \
+{ \
+ struct lprocfs_static_vars *glob = (struct lprocfs_static_vars*)array; \
+ LASSERT(glob != 0); \
+ LASSERT(idx < (unsigned int)(size)); \
+ x->module_vars = glob[idx].module_vars; \
+ x->obd_vars = glob[idx].obd_vars; \
+} \
+
+#define LPROCFS_INIT_VARS(vclass, vinstance) \
+void lprocfs_init_vars(struct lprocfs_static_vars *x) \
+{ \
+ x->module_vars = vclass; \
+ x->obd_vars = vinstance; \
+} \
+
+#ifdef LPROCFS
+/* lprocfs_status.c */
+extern int lprocfs_add_vars(struct proc_dir_entry *root,
+ struct lprocfs_vars *var,
+ void *data);
+
+extern struct proc_dir_entry *lprocfs_register(const char *name,
+ struct proc_dir_entry *parent,
+ struct lprocfs_vars *list,
+ void *data);
+
+extern void lprocfs_remove(struct proc_dir_entry *root);
+
+struct obd_device;
+extern int lprocfs_obd_attach(struct obd_device *dev, struct lprocfs_vars *list);
+extern int lprocfs_obd_detach(struct obd_device *dev);
+
+/* Generic callbacks */
+
+extern int lprocfs_rd_u64(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+extern int lprocfs_rd_uuid(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+extern int lprocfs_rd_name(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+extern int lprocfs_rd_server_uuid(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+extern int lprocfs_rd_conn_uuid(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+extern int lprocfs_rd_numrefs(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+
+/* Statfs helpers */
+struct statfs;
+extern int lprocfs_rd_blksize(char *page, char **start, off_t off,
+ int count, int *eof, struct statfs *sfs);
+extern int lprocfs_rd_kbytestotal(char *page, char **start, off_t off,
+ int count, int *eof, struct statfs *sfs);
+extern int lprocfs_rd_kbytesfree(char *page, char **start, off_t off,
+ int count, int *eof, struct statfs *sfs);
+extern int lprocfs_rd_filestotal(char *page, char **start, off_t off,
+ int count, int *eof, struct statfs *sfs);
+extern int lprocfs_rd_filesfree(char *page, char **start, off_t off,
+ int count, int *eof, struct statfs *sfs);
+extern int lprocfs_rd_filegroups(char *page, char **start, off_t off,
+ int count, int *eof, struct statfs *sfs);
+
+#define DEFINE_LPROCFS_STATFS_FCT(fct_name, get_statfs_fct) \
+int fct_name(char *page, char **start, off_t off, \
+ int count, int *eof, void *data) \
+{ \
+ struct statfs sfs; \
+ int rc = get_statfs_fct((struct obd_device*)data, &sfs); \
+ return (rc==0 \
+ ? lprocfs_##fct_name (page, start, off, count, eof, &sfs) \
+ : rc); \
}
-static inline int lprocfs_dereg_main(void)
-{
- return 0;
-}
+#else
-static inline int lprocfs_ll_rd(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-#endif /* LPROC_SNMP */
+static inline struct proc_dir_entry *
+lprocfs_register(const char *name, struct proc_dir_entry *parent,
+ struct lprocfs_vars *list, void *data) { return NULL; }
+static inline int lprocfs_add_vars(struct proc_dir_entry *root,
+ struct lprocfs_vars *var,
+ void *data) { return 0; }
+static inline void lprocfs_remove(struct proc_dir_entry *root) {};
+struct obd_device;
+static inline int lprocfs_obd_attach(struct obd_device *dev,
+ struct lprocfs_vars *list) { return 0; }
+static inline int lprocfs_obd_detach(struct obd_device *dev) { return 0; }
+static inline int lprocfs_rd_u64(char *page, char **start, off_t off,
+ int count, int *eof, void *data) { return 0; }
+static inline int lprocfs_rd_uuid(char *page, char **start, off_t off,
+ int count, int *eof, void *data) { return 0; }
+static inline int lprocfs_rd_name(char *page, char **start, off_t off,
+ int count, int *eof, void *data) { return 0; }
+static inline int lprocfs_rd_server_uuid(char *page, char **start, off_t off,
+ int count, int *eof, void *data) { return 0; }
+static inline int lprocfs_rd_conn_uuid(char *page, char **start, off_t off,
+ int count, int *eof, void *data) { return 0; }
+static inline int lprocfs_rd_numrefs(char *page, char **start, off_t off,
+ int count, int *eof, void *data) { return 0; }
+
+/* Statfs helpers */
+struct statfs;
+static inline
+int lprocfs_rd_blksize(char *page, char **start, off_t off,
+ int count, int *eof, struct statfs *sfs) { return 0; }
+static inline
+int lprocfs_rd_kbytestotal(char *page, char **start, off_t off,
+ int count, int *eof, struct statfs *sfs) { return 0; }
+static inline
+int lprocfs_rd_kbytesfree(char *page, char **start, off_t off,
+ int count, int *eof, struct statfs *sfs) { return 0; }
+static inline
+int lprocfs_rd_filestotal(char *page, char **start, off_t off,
+ int count, int *eof, struct statfs *sfs) { return 0; }
+static inline
+int lprocfs_rd_filesfree(char *page, char **start, off_t off,
+ int count, int *eof, struct statfs *sfs) { return 0; }
+static inline
+int lprocfs_rd_filegroups(char *page, char **start, off_t off,
+ int count, int *eof, struct statfs *sfs) { return 0; }
+
+#define DEFINE_LPROCFS_STATFS_FCT(fct_name, get_statfs_fct) \
+int fct_name(char *page, char **start, off_t off, \
+ int count, int *eof, void *data) { *eof = 1; return 0; }
+
+#endif /* LPROCFS */
#endif /* LPROCFS_SNMP_H */
ELDLM_LOCK_CHANGED = 300,
ELDLM_LOCK_ABORTED = 301,
+ ELDLM_LOCK_REPLACED = 302,
ELDLM_NAMESPACE_EXISTS = 400,
ELDLM_BAD_NAMESPACE = 401
#define LDLM_FL_NO_CALLBACK (1 << 11) /* see ldlm_cli_cancel_unused */
#define LDLM_FL_HAS_INTENT (1 << 12) /* lock request has intent */
#define LDLM_FL_CANCELING (1 << 13) /* lock cancel has already been sent */
+#define LDLM_FL_LOCAL (1 << 14) // a local lock (ie, no srv/cli split)
/* The blocking callback is overloaded to perform two functions. These flags
* indicate which operation should be performed. */
typedef int (*ldlm_blocking_callback)(struct ldlm_lock *lock,
struct ldlm_lock_desc *new, void *data,
- __u32 data_len, int flag);
-
-typedef int (*ldlm_completion_callback)(struct ldlm_lock *lock, int flags);
+ int flag);
+typedef int (*ldlm_completion_callback)(struct ldlm_lock *lock, int flags, void *data);
+typedef int (*ldlm_granted_callback)(struct ldlm_lock *,
+ struct lustre_msg *, int offset);
struct ldlm_lock {
struct portals_handle l_handle; // must be first in the structure
ldlm_completion_callback l_completion_ast;
ldlm_blocking_callback l_blocking_ast;
+ ldlm_granted_callback l_granted_cb;
struct obd_export *l_export;
struct lustre_handle *l_connh;
__u32 l_flags;
struct lustre_handle l_remote_handle;
void *l_data;
- __u32 l_data_len;
+ void *l_cp_data;
struct ldlm_extent l_extent;
__u32 l_version[RES_VERSION_SIZE];
};
typedef int (*ldlm_res_compat)(struct ldlm_lock *child, struct ldlm_lock *new);
-typedef int (*ldlm_res_policy)(struct ldlm_namespace *, struct ldlm_lock *,
+typedef int (*ldlm_res_policy)(struct ldlm_namespace *, struct ldlm_lock **,
void *req_cookie, ldlm_mode_t mode, int flags,
void *data);
ldlm_mode_t lr_most_restr;
__u32 lr_type; /* LDLM_PLAIN or LDLM_EXTENT */
struct ldlm_resource *lr_root;
- __u64 lr_name[RES_NAME_SIZE];
+ struct ldlm_res_id lr_name;
__u32 lr_version[RES_VERSION_SIZE];
atomic_t lr_refcount;
+
+ /* lr_tmp holds a list head temporarily, during the building of a work
+ * queue. see ldlm_add_ast_work_item and ldlm_run_ast_work */
void *lr_tmp;
};
struct obd_import led_import;
};
-static inline struct ldlm_extent *ldlm_res2extent(struct ldlm_resource *res)
-{
- return (struct ldlm_extent *)(res->lr_name);
-}
-
extern struct obd_ops ldlm_obd_ops;
extern char *ldlm_lockname[];
extern char *ldlm_typename[];
extern char *ldlm_it2str(int it);
-#define LDLM_DEBUG(lock, format, a...) \
+#define __LDLM_DEBUG(level, lock, format, a...) \
do { \
if (lock->l_resource == NULL) { \
- CDEBUG(D_DLMTRACE, "### " format \
+ CDEBUG(level, "### " format \
" ns: \?\? lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s "\
"res: \?\? rrc=\?\? type: \?\?\? remote: "LPX64")\n" \
, ## a, lock, lock->l_handle.h_cookie, \
break; \
} \
if (lock->l_resource->lr_type == LDLM_EXTENT) { \
- CDEBUG(D_DLMTRACE, "### " format \
+ CDEBUG(level, "### " format \
" ns: %s lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s " \
"res: "LPU64"/"LPU64" rrc: %d type: %s ["LPU64"->"LPU64\
"] remote: "LPX64"\n" , ## a, \
lock->l_readers, lock->l_writers, \
ldlm_lockname[lock->l_granted_mode], \
ldlm_lockname[lock->l_req_mode], \
- lock->l_resource->lr_name[0], \
- lock->l_resource->lr_name[1], \
+ lock->l_resource->lr_name.name[0], \
+ lock->l_resource->lr_name.name[1], \
atomic_read(&lock->l_resource->lr_refcount), \
ldlm_typename[lock->l_resource->lr_type], \
lock->l_extent.start, lock->l_extent.end, \
break; \
} \
{ \
- CDEBUG(D_DLMTRACE, "### " format \
+ CDEBUG(level, "### " format \
" ns: %s lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s " \
"res: "LPU64"/"LPU64" rrc: %d type: %s remote: "LPX64 \
"\n" , ## a, lock->l_resource->lr_namespace->ns_name, \
lock->l_readers, lock->l_writers, \
ldlm_lockname[lock->l_granted_mode], \
ldlm_lockname[lock->l_req_mode], \
- lock->l_resource->lr_name[0], \
- lock->l_resource->lr_name[1], \
+ lock->l_resource->lr_name.name[0], \
+ lock->l_resource->lr_name.name[1], \
atomic_read(&lock->l_resource->lr_refcount), \
ldlm_typename[lock->l_resource->lr_type], \
lock->l_remote_handle.cookie); \
} \
} while (0)
+#define LDLM_DEBUG(lock, format, a...) __LDLM_DEBUG(D_DLMTRACE, lock, format, a)
+#define LDLM_ERROR(lock, format, a...) __LDLM_DEBUG(D_ERROR, lock, format, a)
+
#define LDLM_DEBUG_NOLOCK(format, a...) \
CDEBUG(D_DLMTRACE, "### " format "\n" , ## a)
/* ldlm_extent.c */
int ldlm_extent_compat(struct ldlm_lock *, struct ldlm_lock *);
-int ldlm_extent_policy(struct ldlm_namespace *, struct ldlm_lock *, void *,
+int ldlm_extent_policy(struct ldlm_namespace *, struct ldlm_lock **, void *,
ldlm_mode_t, int flags, void *);
/* ldlm_lockd.c */
-int ldlm_handle_enqueue(struct ptlrpc_request *req);
+int ldlm_server_blocking_ast(struct ldlm_lock *, struct ldlm_lock_desc *,
+ void *data, int flag);
+int ldlm_server_completion_ast(struct ldlm_lock *lock, int flags, void *data);
+int ldlm_handle_enqueue(struct ptlrpc_request *req, ldlm_completion_callback,
+ ldlm_blocking_callback);
int ldlm_handle_convert(struct ptlrpc_request *req);
int ldlm_handle_cancel(struct ptlrpc_request *req);
int ldlm_del_waiting_lock(struct ldlm_lock *lock);
void ldlm_lock2handle(struct ldlm_lock *lock, struct lustre_handle *lockh);
struct ldlm_lock *__ldlm_handle2lock(struct lustre_handle *, int flags);
void ldlm_cancel_callback(struct ldlm_lock *);
-int ldlm_lock_set_data(struct lustre_handle *, void *data, int datalen);
+int ldlm_lock_set_data(struct lustre_handle *, void *data, void *cp_data);
void ldlm_lock_remove_from_lru(struct ldlm_lock *);
static inline struct ldlm_lock *ldlm_handle2lock(struct lustre_handle *h)
#define LDLM_LOCK_PUT(lock) \
do { \
- /*LDLM_DEBUG(lock, "put");*/ \
+ /*LDLM_DEBUG((lock), "put");*/ \
ldlm_lock_put(lock); \
} while (0)
#define LDLM_LOCK_GET(lock) \
({ \
ldlm_lock_get(lock); \
- /*LDLM_DEBUG(lock, "get");*/ \
+ /*LDLM_DEBUG((lock), "get");*/ \
lock; \
})
void ldlm_lock_addref(struct lustre_handle *lockh, __u32 mode);
void ldlm_lock_addref_internal(struct ldlm_lock *, __u32 mode);
void ldlm_lock_decref(struct lustre_handle *lockh, __u32 mode);
-void ldlm_grant_lock(struct ldlm_lock *lock);
-int ldlm_lock_match(struct ldlm_namespace *ns, __u64 *res_id, __u32 type,
- void *cookie, int cookielen, ldlm_mode_t mode,
- struct lustre_handle *lockh);
+void ldlm_lock_decref_and_cancel(struct lustre_handle *lockh, __u32 mode);
+void ldlm_grant_lock(struct ldlm_lock *lock, void *data, int datalen);
+int ldlm_lock_match(struct ldlm_namespace *ns, int flags, struct ldlm_res_id *,
+ __u32 type, void *cookie, int cookielen, ldlm_mode_t mode,
+ struct lustre_handle *);
struct ldlm_lock *
ldlm_lock_create(struct ldlm_namespace *ns,
- struct lustre_handle *parent_lock_handle,
- __u64 *res_id, __u32 type, ldlm_mode_t mode, void *data,
- __u32 data_len);
-ldlm_error_t ldlm_lock_enqueue(struct ldlm_namespace *, struct ldlm_lock *,
+ struct lustre_handle *parent_lock_handle, struct ldlm_res_id,
+ __u32 type, ldlm_mode_t mode, void *data, void *cp_data);
+ldlm_error_t ldlm_lock_enqueue(struct ldlm_namespace *, struct ldlm_lock **,
void *cookie, int cookie_len, int *flags,
ldlm_completion_callback completion,
ldlm_blocking_callback blocking);
/* resource.c - internal */
struct ldlm_resource *ldlm_resource_get(struct ldlm_namespace *ns,
struct ldlm_resource *parent,
- __u64 *name, __u32 type, int create);
+ struct ldlm_res_id, __u32 type,
+ int create);
struct ldlm_resource *ldlm_resource_getref(struct ldlm_resource *res);
int ldlm_resource_putref(struct ldlm_resource *res);
void ldlm_resource_add_lock(struct ldlm_resource *res, struct list_head *head,
void ldlm_namespace_dump(struct ldlm_namespace *);
void ldlm_resource_dump(struct ldlm_resource *);
int ldlm_lock_change_resource(struct ldlm_namespace *, struct ldlm_lock *,
- __u64 new_resid[3]);
+ struct ldlm_res_id);
/* ldlm_request.c */
int ldlm_expired_completion_wait(void *data);
-int ldlm_completion_ast(struct ldlm_lock *lock, int flags);
+int ldlm_completion_ast(struct ldlm_lock *lock, int flags, void *data);
int ldlm_cli_enqueue(struct lustre_handle *conn,
struct ptlrpc_request *req,
struct ldlm_namespace *ns,
struct lustre_handle *parent_lock_handle,
- __u64 *res_id,
+ struct ldlm_res_id,
__u32 type,
void *cookie, int cookielen,
ldlm_mode_t mode,
ldlm_completion_callback completion,
ldlm_blocking_callback callback,
void *data,
- __u32 data_len,
+ void *cp_data,
struct lustre_handle *lockh);
int ldlm_match_or_enqueue(struct lustre_handle *connh,
struct ptlrpc_request *req,
struct ldlm_namespace *ns,
struct lustre_handle *parent_lock_handle,
- __u64 *res_id,
+ struct ldlm_res_id,
__u32 type,
void *cookie, int cookielen,
ldlm_mode_t mode,
ldlm_completion_callback completion,
ldlm_blocking_callback callback,
void *data,
- __u32 data_len,
+ void *cp_data,
struct lustre_handle *lockh);
int ldlm_server_ast(struct lustre_handle *lockh, struct ldlm_lock_desc *new,
void *data, __u32 data_len);
int ldlm_cli_convert(struct lustre_handle *, int new_mode, int *flags);
int ldlm_cli_cancel(struct lustre_handle *lockh);
-int ldlm_cli_cancel_unused(struct ldlm_namespace *, __u64 *, int flags);
+int ldlm_cli_cancel_unused(struct ldlm_namespace *, struct ldlm_res_id *,
+ int flags);
int ldlm_cancel_lru(struct ldlm_namespace *ns);
/* mds/handler.c */
/* This has to be here because recurisve inclusion sucks. */
int mds_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
- void *data, __u32 data_len, int flag);
+ void *data, int flag);
#endif /* __KERNEL__ */
};
struct ost_export_data {
- __u8 oed_uuid[37]; /* client UUID */
+ struct obd_uuid oed_uuid; /* client UUID */
+};
+
+struct ec_export_data { /* echo client */
+ struct list_head eced_open_head;
+ struct list_head eced_locks;
};
struct obd_export {
__u64 exp_cookie;
+ struct obd_uuid exp_client_uuid;
struct list_head exp_obd_chain;
struct list_head exp_conn_chain;
struct obd_device *exp_obd;
struct filter_export_data eu_filter_data;
struct lov_export_data eu_lov_data;
struct ost_export_data eu_ost_data;
+ struct ec_export_data eu_ec_data;
} u;
};
#define exp_lov_data u.eu_lov_data
#define exp_filter_data u.eu_filter_data
#define exp_ost_data u.eu_ost_data
+#define exp_ec_data u.eu_ec_data
extern struct obd_export *class_conn2export(struct lustre_handle *conn);
extern struct obd_device *class_conn2obd(struct lustre_handle *conn);
int (* fs_set_last_rcvd)(struct obd_device *obd, __u64 last_rcvd,
void *handle, fsfilt_cb_t cb_func);
int (* fs_statfs)(struct super_block *sb, struct obd_statfs *osfs);
+ int (* fs_sync)(struct super_block *sb);
};
extern int fsfilt_register_ops(struct fsfilt_operations *fs_ops);
return obd->obd_fsops->fs_statfs(fs, osfs);
}
+static inline int fsfilt_sync(struct obd_device *obd, struct super_block *fs)
+{
+ return obd->obd_fsops->fs_sync(fs);
+}
+
#endif /* __KERNEL__ */
#endif
/*
* GENERAL STUFF
*/
-typedef __u8 obd_uuid_t[37];
+struct obd_uuid {
+ __u8 uuid[37];
+};
+
+static inline void obd_str2uuid(struct obd_uuid *uuid, char *tmp)
+{
+ strncpy(uuid->uuid, tmp, sizeof(uuid->uuid));
+ uuid->uuid[sizeof(uuid->uuid) - 1] = '\0';
+}
/* FOO_REQUEST_PORTAL is for incoming requests on the FOO
* FOO_REPLY_PORTAL is for incoming replies on the FOO
#define PTLBD_REQUEST_PORTAL 19
#define PTLBD_REPLY_PORTAL 20
#define PTLBD_BULK_PORTAL 21
+#define MDS_GETATTR_PORTAL 22
#define SVC_KILLED 1
#define SVC_EVENT 2
#define MSG_LAST_REPLAY 1
#define MSG_RESENT 2
-/* XXX horrible interim hack -- see bug 578 */
-#define MSG_REPLAY_IN_PROGRESS 4
-
static inline int lustre_msg_get_flags(struct lustre_msg *msg)
{
return (msg->flags & MSG_GEN_FLAG_MASK);
return (msg->flags >> MSG_OP_FLAG_SHIFT);
}
+static inline void lustre_msg_add_op_flags(struct lustre_msg *msg, int flags)
+{
+ msg->flags |= ((flags & MSG_GEN_FLAG_MASK) << MSG_OP_FLAG_SHIFT);
+}
+
static inline void lustre_msg_set_op_flags(struct lustre_msg *msg, int flags)
{
msg->flags &= ~MSG_OP_FLAG_MASK;
- msg->flags |= ((flags & MSG_GEN_FLAG_MASK) << MSG_OP_FLAG_SHIFT);
+ lustre_msg_add_op_flags(msg, flags);
}
-#define CONNMGR_REPLY 0
-#define CONNMGR_CONNECT 1
+/*
+ * Flags for all connect opcodes (MDS_CONNECT, OST_CONNECT)
+ */
+
+#define MSG_CONNECT_RECOVERING 0x1
+#define MSG_CONNECT_RECONNECT 0x2
+#define MSG_CONNECT_REPLAYABLE 0x4
/*
* OST requests: OBDO & OBD request records
__u32 flags;
};
-#define CONNMGR_REPLY 0
-#define CONNMGR_CONNECT 1
-
-struct connmgr_body {
- __u64 conn;
- __u64 conn_token;
- __u32 generation;
- obd_uuid_t conn_uuid;
-};
-
/* request structure for OST's */
#define OST_REQ_HAS_OA1 0x1
*/
/* opcodes */
-#define MDS_GETATTR 1
-#define MDS_OPEN 2
-#define MDS_CLOSE 3
-#define MDS_REINT 4
-#define MDS_READPAGE 6
-#define MDS_CONNECT 7
-#define MDS_DISCONNECT 8
-#define MDS_GETSTATUS 9
-#define MDS_STATFS 10
-#define MDS_GETLOVINFO 11
-#define MDS_GETATTR_NAME 12
+#define MDS_GETATTR 1
+#define MDS_GETATTR_NAME 2
+#define MDS_CLOSE 3
+#define MDS_REINT 4
+#define MDS_READPAGE 6
+#define MDS_CONNECT 7
+#define MDS_DISCONNECT 8
+#define MDS_GETSTATUS 9
+#define MDS_STATFS 10
+#define MDS_GETLOVINFO 11
#define REINT_SETATTR 1
#define REINT_CREATE 2
#define REINT_LINK 3
#define REINT_UNLINK 4
#define REINT_RENAME 5
-#define REINT_MAX 5
+#define REINT_OPEN 6
+#define REINT_MAX 6
+
+#define IT_INTENT_EXEC 1
+#define IT_OPEN_LOOKUP (1 << 1)
+#define IT_OPEN_NEG (1 << 2)
+#define IT_OPEN_POS (1 << 3)
+#define IT_OPEN_CREATE (1 << 4)
+#define IT_OPEN_OPEN (1 << 5)
+
+#define IT_UNLINK (1<<8)
#define REINT_OPCODE_MASK 0xff /* opcodes must fit into this mask */
#define REINT_REPLAYING 0x1000 /* masked into the opcode to indicate replay */
struct ll_fid fid2;
struct lustre_handle handle;
__u64 size;
+ __u64 blocks; /* XID, in the case of MDS_READPAGE */
__u32 ino; /* make this a __u64 */
__u32 valid;
__u32 fsuid;
__u32 rdev;
__u32 nlink;
__u32 generation;
+ __u32 suppgid;
};
/* This is probably redundant with OBD_MD_FLEASIZE, but we need an audit */
__u64 sa_atime;
__u64 sa_mtime;
__u64 sa_ctime;
+ __u32 sa_suppgid;
};
struct mds_rec_create {
__u32 cr_fsuid;
__u32 cr_fsgid;
__u32 cr_cap;
- __u32 cr_reserved;
+ __u32 cr_flags; /* for use with open */
__u32 cr_mode;
struct ll_fid cr_fid;
struct ll_fid cr_replayfid;
__u32 cr_gid;
__u64 cr_time;
__u64 cr_rdev;
+ __u32 cr_suppgid;
};
struct mds_rec_link {
__u32 lk_fsuid;
__u32 lk_fsgid;
__u32 lk_cap;
+ __u32 lk_suppgid;
struct ll_fid lk_fid1;
struct ll_fid lk_fid2;
};
__u32 ul_cap;
__u32 ul_reserved;
__u32 ul_mode;
+ __u32 ul_suppgid;
struct ll_fid ul_fid1;
struct ll_fid ul_fid2;
};
__u64 ld_default_stripe_size; /* in bytes */
__u64 ld_default_stripe_offset; /* in bytes */
__u32 ld_pattern; /* RAID 0,1 etc */
- obd_uuid_t ld_uuid;
+ struct obd_uuid ld_uuid;
};
/*
#define RES_NAME_SIZE 3
#define RES_VERSION_SIZE 4
+struct ldlm_res_id {
+ __u64 name[RES_NAME_SIZE];
+};
+
/* lock types */
typedef enum {
LCK_EX = 1,
* below, we're probably fine. */
struct ldlm_resource_desc {
__u32 lr_type;
- __u64 lr_name[RES_NAME_SIZE];
+ struct ldlm_res_id lr_name;
__u32 lr_version[RES_VERSION_SIZE];
};
struct ldlm_reply {
__u32 lock_flags;
__u32 lock_mode;
- __u64 lock_resource_name[RES_NAME_SIZE];
+ struct ldlm_res_id lock_resource_name;
struct lustre_handle lock_handle;
struct ldlm_extent lock_extent; /* XXX make this policy 1 &2 */
__u64 lock_policy_res1;
typedef int (*import_recover_t)(struct obd_import *imp, int phase);
#include <linux/lustre_idl.h>
+
struct obd_import {
import_recover_t imp_recover;
struct ptlrpc_connection *imp_connection;
int imp_flags;
int imp_level;
__u64 imp_last_xid;
+ __u64 imp_last_bulk_xid;
__u64 imp_max_transno;
- __u64 imp_peer_last_xid;
__u64 imp_peer_committed_transno;
- /* Protects flags, level, *_xid, *_list */
+ /* Protects flags, level, last_xid, *_list */
spinlock_t imp_lock;
};
* along with Lustre; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Basic Lustre library routines.
+ * Basic Lustre library routines.
*
*/
int target_handle_connect(struct ptlrpc_request *req);
int target_handle_disconnect(struct ptlrpc_request *req);
int target_handle_reconnect(struct lustre_handle *conn, struct obd_export *exp,
- char *cluuid);
+ struct obd_uuid *cluuid);
int client_obd_connect(struct lustre_handle *conn, struct obd_device *obd,
- obd_uuid_t cluuid, struct recovd_obd *recovd,
+ struct obd_uuid *cluuid, struct recovd_obd *recovd,
ptlrpc_recovery_cb_t recover);
int client_obd_disconnect(struct lustre_handle *conn);
int client_obd_setup(struct obd_device *obddev, obd_count len, void *buf);
int client_obd_cleanup(struct obd_device * obddev);
-struct client_obd *client_conn2cli(struct lustre_handle *conn);
-struct obd_device *client_tgtuuid2obd(char *tgtuuid);
+struct client_obd *client_conn2cli(struct lustre_handle *conn);
+struct obd_device *client_tgtuuid2obd(struct obd_uuid *tgtuuid);
int target_revoke_connection(struct recovd_data *rd, int phase);
+int obd_self_statfs(struct obd_device *dev, struct statfs *sfs);
+
/* l_lock.c */
-struct lustre_lock {
+struct lustre_lock {
int l_depth;
struct task_struct *l_owner;
struct semaphore l_sem;
/* FIXME: This needs to validate pointers and cookies */
static inline void *lustre_handle2object(struct lustre_handle *handle)
{
- if (handle)
+ if (handle)
return (void *)(unsigned long)(handle->addr);
- return NULL;
+ return NULL;
}
static inline void ldlm_object2handle(void *object, struct lustre_handle *handle)
printk("OBD ioctl: inlbuf3 not 0 terminated\n");
return 1;
}
-#endif
+#endif
return 0;
}
#define OBD_IOC_RECOVD_FAILCONN _IOWR('f', 136, long)
#define OBD_IOC_DEC_FS_USE_COUNT _IO ('f', 139 )
+#define OBD_IOC_NO_TRANSNO _IOW ('f', 140, long)
+#define OBD_IOC_SET_READONLY _IOW ('f', 141, long)
#define OBD_GET_VERSION _IOWR ('f', 144, long)
+#define ECHO_IOC_GET_STRIPE _IOWR('f', 200, long)
+#define ECHO_IOC_SET_STRIPE _IOWR('f', 201, long)
+#define ECHO_IOC_ENQUEUE _IOWR('f', 202, long)
+#define ECHO_IOC_CANCEL _IOWR('f', 203, long)
+
+
/*
* l_wait_event is a flexible sleeping function, permitting simple caller
* configuration of interrupt and timeout sensitivity along with actions to
* be performed in the event of either exception.
*
* Common usage looks like this:
- *
+ *
* struct l_wait_info lwi = LWI_TIMEOUT_INTR(timeout, timeout_handler,
* intr_handler, callback_data);
* rc = l_wait_event(waitq, condition, &lwi);
#endif
};
-
+/* interpet return codes from intent lookup */
+#define LL_LOOKUP_POSITIVE 1
+#define LL_LOOKUP_NEGATIVE 2
#define LL_SUPER_MAGIC 0x0BD00BD0
#define LL_SBI_NOLCK 0x1
struct ll_sb_info {
- obd_uuid_t ll_sb_uuid;
+ struct obd_uuid ll_sb_uuid;
struct lustre_handle ll_mdc_conn;
struct lustre_handle ll_osc_conn;
struct proc_dir_entry* ll_proc_root;
return ll_s2sbi(inode->i_sb);
}
+static inline void d_unhash_aliases(struct inode *inode)
+{
+ struct dentry *dentry = NULL;
+ struct list_head *tmp;
+ struct ll_sb_info *sbi = ll_i2sbi(inode);
+ ENTRY;
+
+ CDEBUG(D_INODE, "marking dentries for ino %lx/%x invalid\n",
+ inode->i_ino, inode->i_generation);
+
+ spin_lock(&dcache_lock);
+ list_for_each(tmp, &inode->i_dentry) {
+ dentry = list_entry(tmp, struct dentry, d_alias);
+
+ list_del_init(&dentry->d_hash);
+ dentry->d_flags |= DCACHE_LUSTRE_INVALID;
+ list_add(&dentry->d_hash, &sbi->ll_orphan_dentry_list);
+ }
+
+ spin_unlock(&dcache_lock);
+ EXIT;
+}
// FIXME: replace the name of this with LL_I to conform to kernel stuff
// static inline struct ll_inode_info *LL_I(struct inode *inode)
/* dcache.c */
void ll_intent_release(struct dentry *, struct lookup_intent *);
-int ll_set_dd(struct dentry *de);
/****
/* file.c */
extern struct file_operations ll_file_operations;
extern struct inode_operations ll_file_inode_operations;
+extern struct inode_operations ll_special_inode_operations;
struct ldlm_lock;
-int ll_lock_callback(struct ldlm_lock *, struct ldlm_lock_desc *, void *data,
- __u32 data_len, int flag);
+int ll_lock_callback(struct ldlm_lock *, struct ldlm_lock_desc *, void *data, int flag);
int ll_size_lock(struct inode *, struct lov_stripe_md *, obd_off start,
int mode, struct lustre_handle *);
int ll_size_unlock(struct inode *, struct lov_stripe_md *, int mode,
struct lustre_handle *);
-int ll_file_size(struct inode *inode, struct lov_stripe_md *md);
+int ll_file_size(struct inode *inode, struct lov_stripe_md *md,
+ struct lustre_handle *);
int ll_create_objects(struct super_block *sb, obd_id id, uid_t uid,
gid_t gid, struct lov_stripe_md **lsmp);
void ll_truncate(struct inode *inode);
/* super.c */
-void ll_update_inode(struct inode *, struct mds_body *);
+void ll_update_inode(struct inode *, struct mds_body *, struct lov_mds_md *);
/* symlink.c */
extern struct inode_operations ll_fast_symlink_inode_operations;
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
* vim:expandtab:shiftwidth=8:tabstop=8:
*
- * Copyright (C) 2001 Cluster File Systems, Inc. <info@clusterfs.com>
+ * Copyright (C) 2001-2003 Cluster File Systems, Inc. <info@clusterfs.com>
*
* This file is part of Lustre, http://www.lustre.org.
*
#ifdef __KERNEL__
#include <linux/fs.h>
+#include <linux/kp30.h>
#include <linux/lustre_idl.h>
struct ldlm_lock_desc;
struct obd_export;
struct ptlrpc_request;
struct obd_device;
+struct ll_file_data;
#define LUSTRE_MDS_NAME "mds"
#define LUSTRE_MDT_NAME "mdt"
#define LUSTRE_MDC_NAME "mdc"
+struct mdc_rpc_lock {
+ struct semaphore rpcl_sem;
+ struct lookup_intent *rpcl_it;
+};
+extern struct mdc_rpc_lock mdc_rpc_lock;
+
+static inline void mdc_init_rpc_lock(struct mdc_rpc_lock *lck)
+{
+ sema_init(&lck->rpcl_sem, 1);
+ lck->rpcl_it = NULL;
+}
+
+static inline void mdc_get_rpc_lock(struct mdc_rpc_lock *lck,
+ struct lookup_intent *it)
+{
+ down(&lck->rpcl_sem);
+ if (it) {
+ lck->rpcl_it = it;
+ it->it_iattr = (void *)1;
+ }
+}
+
+static inline void mdc_put_rpc_lock(struct mdc_rpc_lock *lck,
+ struct lookup_intent *it)
+{
+ if (it == NULL) {
+ LASSERT(it == lck->rpcl_it);
+ up(&lck->rpcl_sem);
+ return;
+ }
+ if (it && it->it_iattr) {
+ it->it_iattr = NULL;
+ LASSERT(it == lck->rpcl_it);
+ lck->rpcl_it = NULL;
+ up(&lck->rpcl_sem);
+ }
+}
+struct mdc_unlink_data {
+ struct inode *unl_dir;
+ struct inode *unl_de;
+ int unl_mode;
+ const char *unl_name;
+ int unl_len;
+};
+
struct mds_update_record {
__u32 ur_fsuid;
__u32 ur_fsgid;
__u32 ur_uid;
__u32 ur_gid;
__u64 ur_time;
+ __u32 ur_flags;
+ __u32 ur_suppgid;
};
#define MDS_LR_CLIENT 8192
#define MDS_CLIENT_SLOTS 17
#define MDS_MOUNT_RECOV 2
+#define MDS_RECOVERY_TIMEOUT (obd_timeout * 5 * HZ / 2) /* *waves hands* */
/* Data stored per server at the head of the last_rcvd file. In le32 order. */
struct mds_server_data {
spinlock_t med_open_lock;
struct mds_client_data *med_mcd;
int med_off;
+ __u64 med_last_xid;
+ struct lustre_msg *med_last_reply;
+ int med_last_replen;
};
/* file data for open files on MDS */
struct mds_file_data {
struct list_head mfd_list;
- struct lustre_handle mfd_clienthandle;
__u64 mfd_servercookie;
struct file *mfd_file;
};
/* mds/mds_reint.c */
int mds_reint_rec(struct mds_update_record *r, int offset,
- struct ptlrpc_request *req);
+ struct ptlrpc_request *req, struct lustre_handle *);
+
+/* mds/mds_open.c */
+int mds_open(struct mds_update_record *rec, int offset,
+ struct ptlrpc_request *req, struct lustre_handle *);
/* lib/mds_updates.c */
void mds_unpack_body(struct mds_body *b);
int mds_update_unpack(struct ptlrpc_request *, int offset,
struct mds_update_record *);
-void mds_readdir_pack(struct ptlrpc_request *req, __u64 offset,
- obd_id ino, int type);
-void mds_getattr_pack(struct ptlrpc_request *req, int offset,
+void mds_readdir_pack(struct ptlrpc_request *req, __u64 offset, obd_id ino,
+ int type, __u64 xid);
+void mds_getattr_pack(struct ptlrpc_request *req, int valid, int offset, int fl,
struct inode *inode, const char *name, int namelen);
-void mds_setattr_pack(struct ptlrpc_request *, int offset, struct inode *,
- struct iattr *, const char *name, int namelen);
+void mds_setattr_pack(struct ptlrpc_request *, struct inode *,
+ struct iattr *, void *ea, int ealen);
void mds_create_pack(struct ptlrpc_request *, int offset, struct inode *dir,
__u32 mode, __u64 rdev, __u32 uid, __u32 gid, __u64 time,
const char *name, int namelen, const void *data,
int datalen);
+void mds_open_pack(struct ptlrpc_request *, int offset, struct inode *dir,
+ __u32 mode, __u64 rdev, __u32 uid, __u32 gid, __u64 time,
+ __u32 flags, const char *name, int namelen,
+ const void *data, int datalen);
void mds_unlink_pack(struct ptlrpc_request *, int offset, struct inode *inode,
struct inode *child, __u32 mode, const char *name,
int namelen);
struct lustre_handle *lockh);
struct dentry *mds_fid2dentry(struct mds_obd *mds, struct ll_fid *fid,
struct vfsmount **mnt);
-int mds_reint(struct ptlrpc_request *req, int offset);
-int mds_pack_md(struct mds_obd *mds, struct ptlrpc_request *req,
+int mds_reint(struct ptlrpc_request *req, int offset, struct lustre_handle *);
+int mds_pack_md(struct obd_device *mds, struct lustre_msg *msg,
int offset, struct mds_body *body, struct inode *inode);
/* mds/mds_fs.c */
char *filename, int namelen, unsigned long valid,
unsigned int ea_size, struct ptlrpc_request **request);
int mdc_setattr(struct lustre_handle *conn,
- struct inode *, struct iattr *iattr, struct ptlrpc_request **);
+ struct inode *, struct iattr *iattr,
+ void *ea, int ealen, struct ptlrpc_request **);
int mdc_open(struct lustre_handle *conn, obd_id ino, int type, int flags,
struct lov_mds_md *lmm, int lmm_size, struct lustre_handle *fh,
struct ptlrpc_request **);
+void mdc_set_open_replay_data(struct ll_file_data *fd);
int mdc_close(struct lustre_handle *conn, obd_id ino, int type,
struct lustre_handle *fh, struct ptlrpc_request **req);
int mdc_readpage(struct lustre_handle *conn, obd_id ino,
__u32 mode, const char *name, int namelen,
struct ptlrpc_request **);
int mdc_link(struct lustre_handle *conn,
- struct dentry *src, struct inode *dir, const char *name,
+ struct inode *src, struct inode *dir, const char *name,
int namelen, struct ptlrpc_request **);
int mdc_rename(struct lustre_handle *conn,
struct inode *src, struct inode *tgt, const char *old,
int oldlen, const char *new, int newlen,
struct ptlrpc_request **);
-int mdc_create_client(obd_uuid_t uuid, struct ptlrpc_client *cl);
+int mdc_create_client(struct obd_uuid uuid, struct ptlrpc_client *cl);
+void mdc_lock_set_inode(struct lustre_handle *lock, struct inode *inode);
/* Store the generation of a newly-created inode in |req| for replay. */
void mdc_store_inode_generation(struct ptlrpc_request *req, int reqoff,
*/
#define LDLM_NUM_THREADS 4
-#define LDLM_NEVENTS 1024
-#define LDLM_NBUFS 100
+#define LDLM_NEVENT_MAX 8192UL
+#define LDLM_NEVENTS min(num_physpages / 64, LDLM_NEVENT_MAX)
+#define LDLM_NBUF_MAX 256UL
+#define LDLM_NBUFS min(LDLM_NEVENTS / 16, LDLM_NBUF_MAX)
#define LDLM_BUFSIZE (8 * 1024)
#define LDLM_MAXREQSIZE 1024
#define MDT_NUM_THREADS 8
-#define MDS_NEVENTS 1024
-#define MDS_NBUFS 100
+#define MDS_NEVENT_MAX 8192UL
+#define MDS_NEVENTS min(num_physpages / 64, MDS_NEVENT_MAX)
+#define MDS_NBUF_MAX 512UL
+#define MDS_NBUFS min(MDS_NEVENTS / 16, MDS_NBUF_MAX)
#define MDS_BUFSIZE (8 * 1024)
-#define MDS_MAXREQSIZE 1024
+/* Assume file name length = FNAME_MAX = 256 (true for extN).
+ * path name length = PATH_MAX = 4096
+ * LOV MD size max = EA_MAX = 4000
+ * symlink: FNAME_MAX + PATH_MAX <- largest
+ * link: FNAME_MAX + PATH_MAX (mds_rec_link < mds_rec_create)
+ * rename: FNAME_MAX + FNAME_MAX
+ * open: FNAME_MAX + EA_MAX
+ *
+ * MDS_MAXREQSIZE ~= 4736 bytes =
+ * lustre_msg + ldlm_request + mds_body + mds_rec_create + FNAME_MAX + PATH_MAX
+ *
+ * Realistic size is about 512 bytes (20 character name + 128 char symlink),
+ * except in the open case where there are a large number of OSTs in a LOV.
+ */
+#define MDS_MAXREQSIZE (5 * 1024)
#define OST_NUM_THREADS 6
-#define OST_NEVENTS min(num_physpages / 16, 32768UL)
-#define OST_NBUFS min(OST_NEVENTS / 128, 1280UL)
-#define OST_BUFSIZE ((OST_NEVENTS > 4096UL ? 32 : 8) * 1024)
-#define OST_MAXREQSIZE (8 * 1024)
+#define OST_NEVENT_MAX 32768UL
+#define OST_NEVENTS min(num_physpages / 16, OST_NEVENT_MAX)
+#define OST_NBUF_MAX 1280UL
+#define OST_NBUFS min(OST_NEVENTS / 64, OST_NBUF_MAX)
+#define OST_BUFSIZE (8 * 1024)
+/* OST_MAXREQSIZE ~= 1896 bytes =
+ * lustre_msg + obdo + 16 * obd_ioobj + 64 * niobuf_remote
+ *
+ * single object with 16 pages is 576 bytes
+ */
+#define OST_MAXREQSIZE (2 * 1024)
#define PTLBD_NUM_THREADS 4
#define PTLBD_NEVENTS 1024
struct ptlrpc_connection {
struct list_head c_link;
struct lustre_peer c_peer;
- __u8 c_local_uuid[37]; /* XXX do we need this? */
- __u8 c_remote_uuid[37];
+ struct obd_uuid c_local_uuid; /* XXX do we need this? */
+ struct obd_uuid c_remote_uuid;
__u32 c_generation; /* changes upon new connection */
__u32 c_epoch; /* changes when peer changes */
struct ptlrpc_service *rq_svc;
void (*rq_replay_cb)(struct ptlrpc_request *);
+ void *rq_replay_data;
};
#define DEBUG_REQ(level, req, fmt, args...) \
do { \
CDEBUG(level, \
"@@@ " fmt " req@%p x"LPD64"/t"LPD64" o%d->%s:%d lens %d/%d ref %d fl " \
- "%x\n" , ## args, req, req->rq_xid, req->rq_reqmsg->transno, \
+ "%x/%x/%x rc %x\n" , ## args, req, req->rq_xid, \
+ req->rq_reqmsg ? req->rq_reqmsg->transno : -1, \
req->rq_reqmsg ? req->rq_reqmsg->opc : -1, \
- req->rq_connection ? (char *)req->rq_connection->c_remote_uuid : "<?>", \
+ req->rq_connection ? \
+ (char *)req->rq_connection->c_remote_uuid.uuid : "<?>", \
(req->rq_import && req->rq_import->imp_client) ? \
req->rq_import->imp_client->cli_request_portal : -1, \
req->rq_reqlen, req->rq_replen, \
- atomic_read (&req->rq_refcount), req->rq_flags); \
+ atomic_read (&req->rq_refcount), req->rq_flags, \
+ req->rq_reqmsg ? req->rq_reqmsg->flags : 0, \
+ req->rq_repmsg ? req->rq_repmsg->flags : 0, \
+ req->rq_status); \
} while (0)
struct ptlrpc_bulk_page {
typedef int (*svc_handler_t)(struct ptlrpc_request *req);
/* rpc/connection.c */
-void ptlrpc_readdress_connection(struct ptlrpc_connection *, obd_uuid_t uuid);
+void ptlrpc_readdress_connection(struct ptlrpc_connection *, struct obd_uuid *uuid);
struct ptlrpc_connection *ptlrpc_get_connection(struct lustre_peer *peer,
- obd_uuid_t uuid);
+ struct obd_uuid *uuid);
int ptlrpc_put_connection(struct ptlrpc_connection *c);
struct ptlrpc_connection *ptlrpc_connection_addref(struct ptlrpc_connection *);
void ptlrpc_init_connection(void);
/* rpc/niobuf.c */
int ptlrpc_check_bulk_sent(struct ptlrpc_bulk_desc *bulk);
int ptlrpc_check_bulk_received(struct ptlrpc_bulk_desc *bulk);
-int ptlrpc_send_bulk(struct ptlrpc_bulk_desc *);
-int ptlrpc_register_bulk(struct ptlrpc_bulk_desc *);
+int ptlrpc_bulk_put(struct ptlrpc_bulk_desc *);
+int ptlrpc_bulk_get(struct ptlrpc_bulk_desc *);
+int ptlrpc_register_bulk_put(struct ptlrpc_bulk_desc *);
+int ptlrpc_register_bulk_get(struct ptlrpc_bulk_desc *);
int ptlrpc_abort_bulk(struct ptlrpc_bulk_desc *bulk);
struct obd_brw_set *obd_brw_set_new(void);
void obd_brw_set_add(struct obd_brw_set *, struct ptlrpc_bulk_desc *);
void ptlrpc_init_client(int req_portal, int rep_portal, char *name,
struct ptlrpc_client *);
void ptlrpc_cleanup_client(struct obd_import *imp);
-__u8 *ptlrpc_req_to_uuid(struct ptlrpc_request *req);
-struct ptlrpc_connection *ptlrpc_uuid_to_connection(obd_uuid_t uuid);
+struct obd_uuid *ptlrpc_req_to_uuid(struct ptlrpc_request *req);
+struct ptlrpc_connection *ptlrpc_uuid_to_connection(struct obd_uuid *uuid);
int ll_brw_sync_wait(struct obd_brw_set *, int phase);
void ptlrpc_continue_req(struct ptlrpc_request *req);
int ptlrpc_replay_req(struct ptlrpc_request *req);
void ptlrpc_restart_req(struct ptlrpc_request *req);
-void ptlrpc_abort_inflight(struct obd_import *imp);
+void ptlrpc_abort_inflight(struct obd_import *imp, int dying_import);
struct ptlrpc_request *ptlrpc_prep_req(struct obd_import *imp, int opcode,
int count, int *lengths, char **bufs);
void ptlrpc_free_req(struct ptlrpc_request *request);
void ptlrpc_req_finished(struct ptlrpc_request *request);
+struct ptlrpc_request *ptlrpc_request_addref(struct ptlrpc_request *req);
struct ptlrpc_bulk_desc *ptlrpc_prep_bulk(struct ptlrpc_connection *);
void ptlrpc_free_bulk(struct ptlrpc_bulk_desc *bulk);
struct ptlrpc_bulk_page *ptlrpc_prep_bulk_page(struct ptlrpc_bulk_desc *desc);
void ptlrpc_free_bulk_page(struct ptlrpc_bulk_page *page);
+void ptlrpc_retain_replayable_request(struct ptlrpc_request *req,
+ struct obd_import *imp);
/* rpc/service.c */
struct ptlrpc_service *
ptlrpc_init_svc(__u32 nevents, __u32 nbufs, __u32 bufsize, __u32 max_req_size,
int req_portal, int rep_portal,
- obd_uuid_t uuid, svc_handler_t, char *name);
+ struct obd_uuid *uuid, svc_handler_t, char *name);
void ptlrpc_stop_all_threads(struct ptlrpc_service *svc);
int ptlrpc_start_thread(struct obd_device *dev, struct ptlrpc_service *svc,
char *name);
};
struct lov_stripe_md {
- __u64 lsm_object_id; /* lov object id */
+ __u64 lsm_object_id; /* lov object id */
__u32 lsm_magic;
- __u32 lsm_stripe_size; /* size of the stripe */
- int lsm_stripe_offset; /* offset of first stripe in lmd_objects */
- int lsm_stripe_count; /* how many objects are being striped on */
+ __u32 lsm_stripe_size; /* size of the stripe */
+ unsigned lsm_stripe_offset; /* offset of first stripe in lmd_objects */
+ unsigned lsm_stripe_count; /* how many objects are being striped on */
struct lov_oinfo lsm_oinfo[0];
};
__u32 ouc_fsuid;
__u32 ouc_fsgid;
__u32 ouc_cap;
+ __u32 ouc_suppgid;
};
#define OBD_RUN_CTXT_MAGIC 0xC0FFEEAA
#define OBD_SET_CTXT_MAGIC(ctxt) do {} while(0)
#endif
+struct ost_server_data;
+
struct filter_obd {
char *fo_fstype;
struct super_block *fo_sb;
struct dentry *fo_dentry_O;
struct dentry *fo_dentry_O_mode[16];
spinlock_t fo_objidlock; /* protects fo_lastobjid increment */
- __u64 fo_lastobjid;
- __u64 fo_last_committed;
+ struct semaphore fo_transno_sem;
+ struct file *fo_rcvd_filp;
+ struct filter_server_data *fo_fsd;
+
+ __u64 fo_next_recovery_transno;
+ int fo_recoverable_clients;
struct file_operations *fo_fop;
struct inode_operations *fo_iop;
struct address_space_operations *fo_aops;
struct obd_import cl_import;
struct semaphore cl_sem;
int cl_conn_count;
- obd_uuid_t cl_target_uuid; /* XXX -> lustre_name */
+ struct obd_uuid cl_target_uuid; /* XXX -> lustre_name */
/* max_mds_easize is purely a performance thing so we don't have to
* call obd_size_wiremd() all the time. */
int cl_max_mds_easize;
struct mds_obd {
struct ptlrpc_service *mds_service;
+ struct ptlrpc_service *mds_getattr_service;
struct super_block *mds_sb;
struct vfsmount *mds_vfsmnt;
int mds_max_mdsize;
struct file *mds_rcvd_filp;
struct semaphore mds_transno_sem;
- __u64 mds_last_committed;
__u64 mds_last_rcvd;
__u64 mds_mount_count;
struct ll_fid mds_rootfid;
struct list_head mds_delayed_reply_queue;
spinlock_t mds_processing_task_lock;
pid_t mds_processing_task;
-
+ struct timer_list mds_recovery_timer;
+
int mds_has_lov_desc;
struct lov_desc mds_lov_desc;
};
struct ptlbd_obd {
/* server's */
struct ptlrpc_service *ptlbd_service;
+ struct file *filp;
/* client's */
struct ptlrpc_client bd_client;
struct obd_import bd_import;
struct ost_obd {
struct ptlrpc_service *ost_service;
- struct lustre_handle ost_conn; /* the local connection to the OBD */
};
struct echo_client_obd {
- struct lustre_handle conn; /* the local connection to osc/lov */
+ struct lustre_handle ec_conn; /* the local connection to osc/lov */
+ spinlock_t ec_lock;
+ struct list_head ec_objects;
+ int ec_lsmsize;
+ int ec_nstripes;
+ __u64 ec_unique;
};
struct cache_obd {
};
struct lov_tgt_desc {
- obd_uuid_t uuid;
+ struct obd_uuid uuid;
struct lustre_handle conn;
int active; /* is this target available for requests, etc */
};
struct dentry *dentry;
};
+struct obd_trans_info {
+ __u64 oti_transno;
+};
+
#define N_LOCAL_TEMP_PAGE 0x00000001
/* corresponds to one of the obd's */
/* common and UUID name of this device */
char *obd_name;
- obd_uuid_t obd_uuid;
+ struct obd_uuid obd_uuid;
int obd_minor;
int obd_flags;
struct ptlrpc_client obd_ldlm_client; /* XXX OST/MDS only */
/* a spinlock is OK for what we do now, may need a semaphore later */
spinlock_t obd_dev_lock;
+ __u64 obd_last_committed;
struct fsfilt_operations *obd_fsops;
union {
struct ext2_obd ext2;
int (*o_setup) (struct obd_device *dev, obd_count len, void *data);
int (*o_cleanup)(struct obd_device *dev);
int (*o_connect)(struct lustre_handle *conn, struct obd_device *src,
- obd_uuid_t cluuid, struct recovd_obd *recovd,
+ struct obd_uuid *cluuid, struct recovd_obd *recovd,
ptlrpc_recovery_cb_t recover);
int (*o_disconnect)(struct lustre_handle *conn);
int (*o_preallocate)(struct lustre_handle *, obd_count *req,
obd_id *ids);
int (*o_create)(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md **ea);
+ struct lov_stripe_md **ea, struct obd_trans_info *oti);
int (*o_destroy)(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *ea);
+ struct lov_stripe_md *ea, struct obd_trans_info *oti);
int (*o_setattr)(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *ea);
+ struct lov_stripe_md *ea, struct obd_trans_info *oti);
int (*o_getattr)(struct lustre_handle *conn, struct obdo *oa,
struct lov_stripe_md *ea);
int (*o_open)(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *ea);
+ struct lov_stripe_md *ea, struct obd_trans_info *oti);
int (*o_close)(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *ea);
+ struct lov_stripe_md *ea, struct obd_trans_info *oti);
int (*o_brw)(int rw, struct lustre_handle *conn,
struct lov_stripe_md *ea, obd_count oa_bufs,
- struct brw_page *pgarr, struct obd_brw_set *);
+ struct brw_page *pgarr, struct obd_brw_set *,
+ struct obd_trans_info *oti);
int (*o_punch)(struct lustre_handle *conn, struct obdo *tgt,
struct lov_stripe_md *ea, obd_size count,
- obd_off offset);
+ obd_off offset, struct obd_trans_info *oti);
int (*o_sync)(struct lustre_handle *conn, struct obdo *tgt,
obd_size count, obd_off offset);
int (*o_migrate)(struct lustre_handle *conn, struct obdo *dst,
struct obdo *src, obd_size count, obd_off offset);
int (*o_copy)(struct lustre_handle *dstconn, struct obdo *dst,
struct lustre_handle *srconn, struct obdo *src,
- obd_size count, obd_off offset);
+ obd_size count, obd_off offset, struct obd_trans_info *);
int (*o_iterate)(struct lustre_handle *conn,
int (*)(obd_id, obd_gr, void *),
obd_id *startid, obd_gr group, void *data);
int (*o_preprw)(int cmd, struct lustre_handle *conn,
int objcount, struct obd_ioobj *obj,
int niocount, struct niobuf_remote *remote,
- struct niobuf_local *local, void **desc_private);
+ struct niobuf_local *local, void **desc_private,
+ struct obd_trans_info *oti);
int (*o_commitrw)(int cmd, struct lustre_handle *conn,
int objcount, struct obd_ioobj *obj,
int niocount, struct niobuf_local *local,
- void *desc_private);
+ void *desc_private, struct obd_trans_info *oti);
int (*o_enqueue)(struct lustre_handle *conn, struct lov_stripe_md *md,
struct lustre_handle *parent_lock,
__u32 type, void *cookie, int cookielen, __u32 mode,
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
* vim:expandtab:shiftwidth=8:tabstop=8:
*
- * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
+ * Copyright (C) 2001-2003 Cluster File Systems, Inc.
*
* This file is part of Lustre, http://www.lustre.org.
*
#include <linux/lprocfs_status.h>
#endif
-
/* OBD Device Declarations */
#define MAX_OBD_DEVICES 128
extern struct obd_device obd_dev[MAX_OBD_DEVICES];
-#define OBD_ATTACHED 0x1
-#define OBD_SET_UP 0x2
+#define OBD_ATTACHED 0x01
+#define OBD_SET_UP 0x02
+#define OBD_RECOVERING 0x04
+#define OBD_ABORT_RECOVERY 0x08
+#define OBD_REPLAYABLE 0x10
+#define OBD_NO_TRANSNO 0x20 /* XXX needs better name */
/* OBD Operations Declarations */
\
exp = class_conn2export(conn); \
if (!(exp)) { \
- CERROR("No export\n"); \
+ CERROR("No export for conn "LPX64":"LPX64"\n", \
+ conn->addr, conn->cookie); \
RETURN(-EINVAL); \
} \
\
}
static inline int obd_create(struct lustre_handle *conn, struct obdo *obdo,
- struct lov_stripe_md **ea)
+ struct lov_stripe_md **ea,
+ struct obd_trans_info *oti)
{
struct obd_export *exp;
int rc;
OBD_CHECK_SETUP(conn, exp);
OBD_CHECK_OP(exp->exp_obd, create);
- rc = OBP(exp->exp_obd, create)(conn, obdo, ea);
+ rc = OBP(exp->exp_obd, create)(conn, obdo, ea, oti);
RETURN(rc);
}
static inline int obd_destroy(struct lustre_handle *conn, struct obdo *obdo,
- struct lov_stripe_md *ea)
+ struct lov_stripe_md *ea,
+ struct obd_trans_info *oti)
{
struct obd_export *exp;
int rc;
OBD_CHECK_SETUP(conn, exp);
OBD_CHECK_OP(exp->exp_obd, destroy);
- rc = OBP(exp->exp_obd, destroy)(conn, obdo, ea);
+ rc = OBP(exp->exp_obd, destroy)(conn, obdo, ea, oti);
RETURN(rc);
}
}
static inline int obd_close(struct lustre_handle *conn, struct obdo *obdo,
- struct lov_stripe_md *ea)
+ struct lov_stripe_md *ea,
+ struct obd_trans_info *oti)
{
struct obd_export *exp;
int rc;
OBD_CHECK_SETUP(conn, exp);
OBD_CHECK_OP(exp->exp_obd, close);
- rc = OBP(exp->exp_obd, close)(conn, obdo, ea);
+ rc = OBP(exp->exp_obd, close)(conn, obdo, ea, oti);
RETURN(rc);
}
static inline int obd_open(struct lustre_handle *conn, struct obdo *obdo,
- struct lov_stripe_md *ea)
+ struct lov_stripe_md *ea, struct obd_trans_info *oti)
{
struct obd_export *exp;
int rc;
OBD_CHECK_SETUP(conn, exp);
OBD_CHECK_OP(exp->exp_obd, open);
- rc = OBP(exp->exp_obd, open)(conn, obdo, ea);
+ rc = OBP(exp->exp_obd, open)(conn, obdo, ea, oti);
RETURN(rc);
}
static inline int obd_setattr(struct lustre_handle *conn, struct obdo *obdo,
- struct lov_stripe_md *ea)
+ struct lov_stripe_md *ea,
+ struct obd_trans_info *oti)
{
struct obd_export *exp;
int rc;
OBD_CHECK_SETUP(conn, exp);
OBD_CHECK_OP(exp->exp_obd, setattr);
- rc = OBP(exp->exp_obd, setattr)(conn, obdo, ea);
+ rc = OBP(exp->exp_obd, setattr)(conn, obdo, ea, oti);
RETURN(rc);
}
static inline int obd_connect(struct lustre_handle *conn,
- struct obd_device *obd, obd_uuid_t cluuid,
+ struct obd_device *obd, struct obd_uuid *cluuid,
struct recovd_obd *recovd,
ptlrpc_recovery_cb_t recover)
{
}
static inline int obd_punch(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *ea,
- obd_size start, obd_size end)
+ struct lov_stripe_md *ea, obd_size start,
+ obd_size end, struct obd_trans_info *oti)
{
struct obd_export *exp;
int rc;
OBD_CHECK_SETUP(conn, exp);
OBD_CHECK_OP(exp->exp_obd, punch);
- rc = OBP(exp->exp_obd, punch)(conn, oa, ea, start, end);
+ rc = OBP(exp->exp_obd, punch)(conn, oa, ea, start, end, oti);
RETURN(rc);
}
static inline int obd_brw(int cmd, struct lustre_handle *conn,
struct lov_stripe_md *ea, obd_count oa_bufs,
- struct brw_page *pg, struct obd_brw_set *set)
+ struct brw_page *pg, struct obd_brw_set *set,
+ struct obd_trans_info *oti)
{
struct obd_export *exp;
int rc;
LBUG();
}
- rc = OBP(exp->exp_obd, brw)(cmd, conn, ea, oa_bufs, pg, set);
+ rc = OBP(exp->exp_obd, brw)(cmd, conn, ea, oa_bufs, pg, set, oti);
RETURN(rc);
}
static inline int obd_preprw(int cmd, struct lustre_handle *conn,
int objcount, struct obd_ioobj *obj,
int niocount, struct niobuf_remote *remote,
- struct niobuf_local *local, void **desc_private)
+ struct niobuf_local *local, void **desc_private,
+ struct obd_trans_info *oti)
{
struct obd_export *exp;
int rc;
OBD_CHECK_OP(exp->exp_obd, preprw);
rc = OBP(exp->exp_obd, preprw)(cmd, conn, objcount, obj, niocount,
- remote, local, desc_private);
+ remote, local, desc_private, oti);
RETURN(rc);
}
static inline int obd_commitrw(int cmd, struct lustre_handle *conn,
int objcount, struct obd_ioobj *obj,
int niocount, struct niobuf_local *local,
- void *desc_private)
+ void *desc_private, struct obd_trans_info *oti)
{
struct obd_export *exp;
int rc;
OBD_CHECK_OP(exp->exp_obd, commitrw);
rc = OBP(exp->exp_obd, commitrw)(cmd, conn, objcount, obj, niocount,
- local, desc_private);
+ local, desc_private, oti);
RETURN(rc);
}
static inline void obd_handle2oa(struct obdo *oa, struct lustre_handle *handle)
{
- if (handle->addr) {
+ if (handle && handle->addr) {
struct lustre_handle *oa_handle = obdo_handle(oa);
memcpy(oa_handle, handle, sizeof(*handle));
oa->o_valid |= OBD_MD_FLHANDLE;
dst->i_atime = src->o_atime;
if (valid & OBD_MD_FLMTIME)
dst->i_mtime = src->o_mtime;
- if (valid & OBD_MD_FLCTIME)
+ if (valid & OBD_MD_FLCTIME && src->o_ctime > dst->i_ctime)
dst->i_ctime = src->o_ctime;
if (valid & OBD_MD_FLSIZE)
dst->i_size = src->o_size;
/* I'm as embarrassed about this as you are.
*
* <shaver> // XXX do not look into _superhack with remaining eye
- * <shaver> // XXX if this were any uglier, I'd get my own show on MTV */
+ * <shaver> // XXX if this were any uglier, I'd get my own show on MTV */
extern int (*ptlrpc_put_connection_superhack)(struct ptlrpc_connection *c);
+extern void (*ptlrpc_abort_inflight_superhack)(struct obd_import *imp,
+ int dying_import);
-int class_register_type(struct obd_ops *ops, struct lprocfs_vars* vars,
+int class_register_type(struct obd_ops *ops, struct lprocfs_vars* vars,
char *nm);
int class_unregister_type(char *nm);
int class_name2dev(char *name);
-int class_uuid2dev(char *uuid);
-struct obd_device *class_uuid2obd(char *uuid);
+int class_uuid2dev(struct obd_uuid *uuid);
+struct obd_device *class_uuid2obd(struct obd_uuid *uuid);
struct obd_export *class_new_export(struct obd_device *obddev);
struct obd_type *class_get_type(char *name);
void class_put_type(struct obd_type *type);
void class_destroy_export(struct obd_export *exp);
int class_connect(struct lustre_handle *conn, struct obd_device *obd,
- obd_uuid_t cluuid);
+ struct obd_uuid *cluuid);
int class_disconnect(struct lustre_handle *conn);
void class_disconnect_all(struct obd_device *obddev);
void obd_statfs_pack(struct obd_statfs *tgt, struct obd_statfs *src);
void obd_statfs_unpack(struct obd_statfs *tgt, struct obd_statfs *src);
+
+struct obd_class_user_state {
+ struct obd_device *ocus_current_obd;
+ struct list_head ocus_conns;
+};
+
+struct obd_class_user_conn {
+ struct list_head ocuc_chain;
+ struct lustre_handle ocuc_conn;
+};
+
#endif
/* sysctl.c */
/* uuid.c */
typedef __u8 class_uuid_t[16];
-//int class_uuid_parse(obd_uuid_t in, class_uuid_t out);
-void class_uuid_unparse(class_uuid_t in, obd_uuid_t out);
-#endif /* __LINUX_CLASS_OBD_H */
+//int class_uuid_parse(struct obd_uuid in, class_uuid_t out);
+void class_uuid_unparse(class_uuid_t in, struct obd_uuid *out);
+#endif /* __LINUX_OBD_CLASS_H */
#define OBD_ECHO_DEVICENAME "obdecho"
#define OBD_ECHO_CLIENT_DEVICENAME "echo_client"
+struct ec_object
+{
+ struct list_head eco_obj_chain;
+ struct obd_device *eco_device;
+ int eco_refcount;
+ int eco_deleted;
+ obd_id eco_id;
+ struct lov_stripe_md *eco_lsm;
+};
+
+struct ec_open_object
+{
+ struct list_head ecoo_exp_chain;
+ struct ec_object *ecoo_object;
+ struct obdo ecoo_oa;
+ __u64 ecoo_cookie;
+};
+
+struct ec_lock
+{
+ struct list_head ecl_exp_chain;
+ struct lustre_handle ecl_handle;
+ struct ldlm_extent ecl_extent;
+ __u32 ecl_mode;
+ struct ec_object *ecl_object;
+ __u64 ecl_cookie;
+};
+
#endif
#define OBD_FILTER_DEVICENAME "obdfilter"
#endif
+#define FILTER_LR_SERVER_SIZE 512
+
+#define FILTER_LR_CLIENT_START 8192
+#define FILTER_LR_CLIENT_SIZE 128
+
+#define FILTER_MOUNT_RECOV 2
+#define FILTER_RECOVERY_TIMEOUT (obd_timeout * 5 * HZ / 2) /* *waves hands* */
+
+/* Data stored per server at the head of the last_rcvd file. In le32 order. */
+struct filter_server_data {
+ __u8 fsd_uuid[37]; /* server UUID */
+ __u8 fsd_uuid_padding[3]; /* unused */
+ __u64 fsd_last_objid; /* last completed transaction ID */
+ __u64 fsd_last_rcvd; /* last completed transaction ID */
+ __u64 fsd_mount_count; /* FILTER incarnation number */
+ __u8 fsd_padding[FILTER_LR_SERVER_SIZE - 64]; /* */
+};
+
+/* Data stored per client in the last_rcvd file. In le32 order. */
+struct filter_client_data {
+ __u8 fcd_uuid[37]; /* client UUID */
+ __u8 fcd_uuid_padding[3]; /* unused */
+ __u64 fcd_last_rcvd; /* last completed transaction ID */
+ __u64 fcd_mount_count; /* FILTER incarnation number */
+ __u64 fcd_last_xid; /* client RPC xid for the last transaction */
+ __u8 fcd_padding[FILTER_LR_CLIENT_SIZE - 64];
+};
+
/* In-memory access to client data from OST struct */
struct filter_export_data {
struct list_head fed_open_head; /* files to close on disconnect */
spinlock_t fed_lock; /* protects fed_open_head */
+ struct filter_client_data *fed_fcd;
+ int fed_lr_off;
};
/* file data for open files on OST */
#define FILTER_FLAG_DESTROY 0x0001 /* destroy dentry on last file close */
+
#endif
extern unsigned long obd_fail_loc;
extern unsigned long obd_timeout;
extern char obd_recovery_upcall[128];
+extern unsigned long obd_sync_filter;
#define OBD_FAIL_MDS 0x100
#define OBD_FAIL_MDS_HANDLE_UNPACK 0x101
#define OBD_FAIL_MDS_STATFS_PACK 0x11d
#define OBD_FAIL_MDS_STATFS_NET 0x11e
#define OBD_FAIL_MDS_GETATTR_NAME_NET 0x11f
+#define OBD_FAIL_MDS_ALL_REPLY_NET 0x120
+#define OBD_FAIL_MDS_ALL_REQUEST_NET 0x121
#define OBD_FAIL_OST 0x200
#define OBD_FAIL_OST_CONNECT_NET 0x201
#define OBD_FAIL_MDS_ALL_NET 0x01000000
#define OBD_FAIL_OST_ALL_NET 0x02000000
-#define OBD_FAIL_CHECK(id) ((obd_fail_loc & OBD_FAIL_MASK_LOC) == (id) && \
- ((obd_fail_loc & (OBD_FAILED | OBD_FAIL_ONCE))!=\
+#define OBD_FAIL_CHECK(id) (((obd_fail_loc & OBD_FAIL_MASK_LOC) == \
+ ((id) & OBD_FAIL_MASK_LOC)) && \
+ ((obd_fail_loc & (OBD_FAILED | OBD_FAIL_ONCE))!= \
(OBD_FAILED | OBD_FAIL_ONCE)))
#define OBD_FAIL_RETURN(id, ret) \
+EXPORT_SYMBOL(dev_clear_rdonly);
--- linux-2.4.18-17.8.0/drivers/block/loop.c~dev_read_only 2002-12-06 14:52:29.000000000 -0800
+++ linux-2.4.18-17.8.0-zab/drivers/block/loop.c 2002-12-06 14:52:29.000000000 -0800
-@@ -491,6 +491,11 @@ static int loop_make_request(request_que
+@@ -491,6 +491,9 @@ static int loop_make_request(request_que
spin_unlock_irq(&lo->lo_lock);
if (rw == WRITE) {
-+#ifdef CONFIG_DEV_RDONLY
+ if (dev_check_rdonly(rbh->b_rdev))
+ goto err;
-+#endif
+
if (lo->lo_flags & LO_FLAGS_READ_ONLY)
goto err;
} else if (rw == READA) {
--- linux-2.4.18-17.8.0/drivers/ide/ide-disk.c~dev_read_only 2002-12-06 14:52:29.000000000 -0800
+++ linux-2.4.18-17.8.0-zab/drivers/ide/ide-disk.c 2002-12-06 14:52:29.000000000 -0800
-@@ -557,6 +557,12 @@ static ide_startstop_t lba_48_rw_disk (i
+@@ -557,6 +557,10 @@ static ide_startstop_t lba_48_rw_disk (i
*/
static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
{
-+#ifdef CONFIG_DEV_RDONLY
+ if (rq->cmd == WRITE && dev_check_rdonly(rq->rq_dev)) {
+ ide_end_request(1, HWGROUP(drive));
+ return ide_stopped;
+ }
-+#endif
if (IDE_CONTROL_REG)
OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
--- /dev/null
+ drivers/block/blkpg.c | 38 ++++++++++++++++++++++++++++++++++++++
+ drivers/block/loop.c | 5 +++++
+ drivers/ide/ide-disk.c | 6 ++++++
+ 3 files changed, 49 insertions(+)
+
+--- linux-2.4.19-hp2_pnnl2/drivers/block/blkpg.c~dev_read_only_hp Sun Jan 19 18:51:12 2003
++++ linux-2.4.19-hp2_pnnl2-root/drivers/block/blkpg.c Sun Jan 19 18:52:28 2003
+@@ -310,6 +310,42 @@ int blk_ioctl(kdev_t dev, unsigned int c
+
+ EXPORT_SYMBOL(blk_ioctl);
+
++
++#define NUM_DEV_NO_WRITE 16
++static int dev_no_write[NUM_DEV_NO_WRITE];
++
++/*
++ * Debug code for turning block devices "read-only" (will discard writes
++ * silently). This is for filesystem crash/recovery testing.
++ */
++void dev_set_rdonly(kdev_t dev, int no_write)
++{
++ if (dev) {
++ printk(KERN_WARNING "Turning device %s read-only\n",
++ bdevname(dev));
++ dev_no_write[no_write] = 0xdead0000 + dev;
++ }
++}
++
++int dev_check_rdonly(kdev_t dev) {
++ int i;
++
++ for (i = 0; i < NUM_DEV_NO_WRITE; i++) {
++ if ((dev_no_write[i] & 0xffff0000) == 0xdead0000 &&
++ dev == (dev_no_write[i] & 0xffff))
++ return 1;
++ }
++ return 0;
++}
++
++void dev_clear_rdonly(int no_write) {
++ dev_no_write[no_write] = 0;
++}
++
++EXPORT_SYMBOL(dev_set_rdonly);
++EXPORT_SYMBOL(dev_check_rdonly);
++EXPORT_SYMBOL(dev_clear_rdonly);
++
+ /**
+ * get_last_sector()
+ *
+--- linux-2.4.19-hp2_pnnl2/drivers/block/loop.c~dev_read_only_hp Sun Jan 19 18:51:12 2003
++++ linux-2.4.19-hp2_pnnl2-root/drivers/block/loop.c Sun Jan 19 18:51:12 2003
+@@ -474,6 +474,9 @@ static int loop_make_request(request_que
+ spin_unlock_irq(&lo->lo_lock);
+
+ if (rw == WRITE) {
++ if (dev_check_rdonly(rbh->b_rdev))
++ goto err;
++
+ if (lo->lo_flags & LO_FLAGS_READ_ONLY)
+ goto err;
+ } else if (rw == READA) {
+--- linux-2.4.19-hp2_pnnl2/drivers/ide/ide-disk.c~dev_read_only_hp Sun Jan 19 18:51:12 2003
++++ linux-2.4.19-hp2_pnnl2-root/drivers/ide/ide-disk.c Sun Jan 19 18:51:12 2003
+@@ -551,6 +551,10 @@ static ide_startstop_t lba_48_rw_disk (i
+ */
+ static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
+ {
++ if (rq->cmd == WRITE && dev_check_rdonly(rq->rq_dev)) {
++ ide_end_request(1, HWGROUP(drive));
++ return ide_stopped;
++ }
+ if (IDE_CONTROL_REG)
+ OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
+
+
+_
- 0 files changed
+ fs/ext3/Makefile | 2 ++
+ fs/ext3/super.c | 2 +-
+ include/linux/fs.h | 1 +
+ kernel/ksyms.c | 5 +++++
+ 4 files changed, 9 insertions(+), 1 deletion(-)
---- linux-2.4.18-17.8.0/fs/ext3/Makefile~exports 2002-12-06 14:52:29.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/fs/ext3/Makefile 2002-12-06 14:52:29.000000000 -0800
+--- linux-2.4.19-hp2_pnnl2/fs/ext3/Makefile~exports Sun Jan 19 18:52:38 2003
++++ linux-2.4.19-hp2_pnnl2-root/fs/ext3/Makefile Sun Jan 19 18:52:38 2003
@@ -9,6 +9,8 @@
O_TARGET := ext3.o
obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
ioctl.o namei.o super.o symlink.o
obj-m := $(O_TARGET)
---- linux-2.4.18-17.8.0/fs/ext3/super.c~exports 2002-12-06 14:52:29.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/fs/ext3/super.c 2002-12-06 14:52:29.000000000 -0800
-@@ -1746,7 +1746,7 @@ static void __exit exit_ext3_fs(void)
+--- linux-2.4.19-hp2_pnnl2/fs/ext3/super.c~exports Sun Jan 19 18:52:38 2003
++++ linux-2.4.19-hp2_pnnl2-root/fs/ext3/super.c Sun Jan 19 18:52:38 2003
+@@ -1744,7 +1744,7 @@ static void __exit exit_ext3_fs(void)
unregister_filesystem(&ext3_fs_type);
}
MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
---- linux-2.4.18-17.8.0/include/linux/fs.h~exports 2002-12-06 14:52:29.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/include/linux/fs.h 2002-12-06 14:52:29.000000000 -0800
-@@ -1046,6 +1046,7 @@ extern int unregister_filesystem(struct
+--- linux-2.4.19-hp2_pnnl2/include/linux/fs.h~exports Sun Jan 19 18:52:38 2003
++++ linux-2.4.19-hp2_pnnl2-root/include/linux/fs.h Sun Jan 19 18:52:38 2003
+@@ -1020,6 +1020,7 @@ extern int unregister_filesystem(struct
extern struct vfsmount *kern_mount(struct file_system_type *);
extern int may_umount(struct vfsmount *);
extern long do_mount(char *, char *, char *, unsigned long, void *);
extern void umount_tree(struct vfsmount *);
#define kern_umount mntput
---- linux-2.4.18-17.8.0/kernel/ksyms.c~exports 2002-12-06 14:52:29.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/kernel/ksyms.c 2002-12-06 14:52:29.000000000 -0800
-@@ -306,6 +306,11 @@ EXPORT_SYMBOL_GPL(buffermem_pages);
- EXPORT_SYMBOL_GPL(nr_free_pages);
- EXPORT_SYMBOL_GPL(page_cache_size);
+--- linux-2.4.19-hp2_pnnl2/kernel/ksyms.c~exports Sun Jan 19 18:52:38 2003
++++ linux-2.4.19-hp2_pnnl2-root/kernel/ksyms.c Sun Jan 19 18:52:38 2003
+@@ -308,6 +308,11 @@ EXPORT_SYMBOL(dcache_dir_fsync);
+ EXPORT_SYMBOL(dcache_readdir);
+ EXPORT_SYMBOL(dcache_dir_ops);
+/* lustre */
+EXPORT_SYMBOL(panic_notifier_list);
--- /dev/null
+
+
+
+ fs/ext3/Makefile | 2 ++
+ fs/ext3/super.c | 2 +-
+ include/linux/fs.h | 1 +
+ kernel/ksyms.c | 4 ++++
+ 4 files changed, 9 insertions(+), 1 deletion(-)
+
+--- linux-2.4.19-hp2_pnnl2/fs/ext3/Makefile~exports Sun Jan 19 18:52:38 2003
++++ linux-2.4.19-hp2_pnnl2-root/fs/ext3/Makefile Sun Jan 19 18:52:38 2003
+@@ -9,6 +9,8 @@
+
+ O_TARGET := ext3.o
+
++export-objs := super.o
++
+ obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
+ ioctl.o namei.o super.o symlink.o
+ obj-m := $(O_TARGET)
+--- linux-2.4.19-hp2_pnnl2/fs/ext3/super.c~exports Sun Jan 19 18:52:38 2003
++++ linux-2.4.19-hp2_pnnl2-root/fs/ext3/super.c Sun Jan 19 18:52:38 2003
+@@ -1744,7 +1744,7 @@ static void __exit exit_ext3_fs(void)
+ unregister_filesystem(&ext3_fs_type);
+ }
+
+-EXPORT_NO_SYMBOLS;
++EXPORT_SYMBOL(ext3_bread);
+
+ MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
+ MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
+--- linux-2.4.19-hp2_pnnl2/include/linux/fs.h~exports Sun Jan 19 18:52:38 2003
++++ linux-2.4.19-hp2_pnnl2-root/include/linux/fs.h Sun Jan 19 18:52:38 2003
+@@ -1020,6 +1020,7 @@ extern int unregister_filesystem(struct
+ extern struct vfsmount *kern_mount(struct file_system_type *);
+ extern int may_umount(struct vfsmount *);
+ extern long do_mount(char *, char *, char *, unsigned long, void *);
++struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
+ extern void umount_tree(struct vfsmount *);
+
+ #define kern_umount mntput
+--- linux-2.4.19-hp2_pnnl2/kernel/ksyms.c~exports Sun Jan 19 18:52:38 2003
++++ linux-2.4.19-hp2_pnnl2-root/kernel/ksyms.c Sun Jan 19 18:52:38 2003
+@@ -308,6 +308,10 @@ EXPORT_SYMBOL(dcache_dir_fsync);
+ EXPORT_SYMBOL(dcache_readdir);
+ EXPORT_SYMBOL(dcache_dir_ops);
+
++/* lustre */
++EXPORT_SYMBOL(pagecache_lock_cacheline);
++EXPORT_SYMBOL(do_kern_mount);
++
+ /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */
+ EXPORT_SYMBOL(default_llseek);
+ EXPORT_SYMBOL(dentry_open);
+
+_
--- /dev/null
+--- lum/fs/inode.c Sat Oct 19 11:42:42 2002
++++ linux-2.4.18-uml35-ext3online/fs/inode.c Mon Oct 14 00:41:20 2002
+@@ -606,7 +553,8 @@ static void dispose_list(struct list_hea
+ /*
+ * Invalidate all inodes for a device.
+ */
+-static int invalidate_list(struct list_head *head, struct super_block * sb, struct list_head * dispose)
++static int invalidate_list(struct list_head *head, struct super_block * sb,
++ struct list_head * dispose, int show)
+ {
+ struct list_head *next;
+ int busy = 0, count = 0;
+@@ -631,6 +579,11 @@ static int invalidate_list(struct list_h
+ count++;
+ continue;
+ }
++ if (show)
++ printk(KERN_ERR
++ "inode busy: dev %s:%lu (%p) mode %o count %u\n",
++ kdevname(sb->s_dev), inode->i_ino, inode,
++ inode->i_mode, atomic_read(&inode->i_count));
+ busy = 1;
+ }
+ /* only unused inodes may be cached with i_count zero */
+@@ -649,22 +601,23 @@ static int invalidate_list(struct list_h
+ /**
+ * invalidate_inodes - discard the inodes on a device
+ * @sb: superblock
++ * @show: whether we should display any busy inodes found
+ *
+ * Discard all of the inodes for a given superblock. If the discard
+ * fails because there are busy inodes then a non zero value is returned.
+ * If the discard is successful all the inodes have been discarded.
+ */
+
+-int invalidate_inodes(struct super_block * sb)
++int invalidate_inodes(struct super_block * sb, int show)
+ {
+ int busy;
+ LIST_HEAD(throw_away);
+
+ spin_lock(&inode_lock);
+- busy = invalidate_list(&inode_in_use, sb, &throw_away);
+- busy |= invalidate_list(&inode_unused, sb, &throw_away);
+- busy |= invalidate_list(&sb->s_dirty, sb, &throw_away);
+- busy |= invalidate_list(&sb->s_locked_inodes, sb, &throw_away);
++ busy = invalidate_list(&inode_in_use, sb, &throw_away, show);
++ busy |= invalidate_list(&inode_unused, sb, &throw_away, show);
++ busy |= invalidate_list(&sb->s_dirty, sb, &throw_away, show);
++ busy |= invalidate_list(&sb->s_locked_inodes, sb, &throw_away, show);
+ spin_unlock(&inode_lock);
+
+ dispose_list(&throw_away);
+@@ -690,7 +643,7 @@ int invalidate_device(kdev_t dev, int do
+ * hold).
+ */
+ shrink_dcache_sb(sb);
+- res = invalidate_inodes(sb);
++ res = invalidate_inodes(sb, 0);
+ drop_super(sb);
+ }
+ invalidate_buffers(dev);
+--- lum/fs/super.c.orig Sat Oct 19 11:42:42 2002
++++ lum/fs/super.c Wed Oct 30 17:16:55 2002
+@@ -936,7 +936,7 @@
+ lock_super(sb);
+ lock_kernel();
+ sb->s_flags &= ~MS_ACTIVE;
+- invalidate_inodes(sb); /* bad name - it should be evict_inodes() */
++ invalidate_inodes(sb, 0); /* bad name - it should be evict_inodes() */
+ if (sop) {
+ if (sop->write_super && sb->s_dirt)
+ sop->write_super(sb);
+@@ -945,7 +945,7 @@
+ }
+
+ /* Forget any remaining inodes */
+- if (invalidate_inodes(sb)) {
++ if (invalidate_inodes(sb, 1)) {
+ printk(KERN_ERR "VFS: Busy inodes after unmount. "
+ "Self-destruct in 5 seconds. Have a nice day...\n");
+ }
+--- lum/include/linux/fs.h Wed Oct 30 17:10:42 2002
++++ lum/include/linux/fs.h.orig Tue Oct 22 23:15:00 2002
+@@ -1261,7 +1261,7 @@
+ extern void set_buffer_flushtime(struct buffer_head *);
+ extern void balance_dirty(void);
+ extern int check_disk_change(kdev_t);
+-extern int invalidate_inodes(struct super_block *);
++extern int invalidate_inodes(struct super_block *, int);
+ extern int invalidate_device(kdev_t, int);
+ extern void invalidate_inode_pages(struct inode *);
+ extern void invalidate_inode_pages2(struct address_space *);
+--- lum/fs/smbfs/inode.c.orig Mon Feb 25 12:38:09 2002
++++ lum/fs/smbfs/inode.c Thu Feb 6 21:34:26 2003
+@@ -166,7 +166,7 @@
+ {
+ VERBOSE("\n");
+ shrink_dcache_sb(SB_of(server));
+- invalidate_inodes(SB_of(server));
++ invalidate_inodes(SB_of(server), 0);
+ }
+
+ /*
--- /dev/null
+--- linux-chaos/fs/inode.c.b_io_export Wed Jan 29 16:56:15 2003
++++ linux-chaos/fs/inode.c Wed Jan 29 16:56:27 2003
+@@ -66,7 +66,8 @@
+ * NOTE! You also have to own the lock if you change
+ * the i_state of an inode while it is in use..
+ */
+-static spinlock_t inode_lock = SPIN_LOCK_UNLOCKED;
++spinlock_t inode_lock = SPIN_LOCK_UNLOCKED;
++EXPORT_SYMBOL(inode_lock);
+
+ /*
+ * Statistics gathering..
+--- linux-chaos/fs/Makefile.b_io_export Wed Jan 29 16:56:45 2003
++++ linux-chaos/fs/Makefile Wed Jan 29 16:56:53 2003
+@@ -7,7 +7,7 @@
+
+ O_TARGET := fs.o
+
+-export-objs := filesystems.o open.o dcache.o buffer.o
++export-objs := filesystems.o open.o dcache.o buffer.o inode.o
+ mod-subdirs := nls
+
+ obj-y := open.o read_write.o devices.o file_table.o buffer.o \
+--- linux-chaos/mm/filemap.c.b_io_export Wed Jan 29 16:50:39 2003
++++ linux-chaos/mm/filemap.c Wed Jan 29 16:51:11 2003
+@@ -65,6 +65,7 @@
+ * pagecache_lock
+ */
+ spinlock_cacheline_t pagemap_lru_lock_cacheline = {SPIN_LOCK_UNLOCKED};
++EXPORT_SYMBOL(pagemap_lru_lock_cacheline);
+
+ #define CLUSTER_PAGES (1 << page_cluster)
+ #define CLUSTER_OFFSET(x) (((x) >> page_cluster) << page_cluster)
+--- linux-chaos/mm/vmscan.c.b_io_export Wed Jan 29 16:51:58 2003
++++ linux-chaos/mm/vmscan.c Wed Jan 29 16:55:16 2003
+@@ -839,6 +839,7 @@
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&kswapd_done, &wait);
+ }
++EXPORT_SYMBOL(wakeup_kswapd);
+
+ static void wakeup_memwaiters(void)
+ {
+--- linux-chaos/mm/Makefile.b_io_export Wed Jan 29 16:52:46 2003
++++ linux-chaos/mm/Makefile Wed Jan 29 16:54:23 2003
+@@ -9,7 +9,7 @@
+
+ O_TARGET := mm.o
+
+-export-objs := shmem.o filemap.o memory.o page_alloc.o mempool.o
++export-objs := shmem.o filemap.o memory.o page_alloc.o mempool.o vmscan.c
+
+ obj-y := memory.o mmap.o filemap.o mprotect.o mlock.o mremap.o \
+ vmalloc.o slab.o bootmem.o swap.o vmscan.o page_io.o \
+--- linux-chaos/mm/page_alloc.c.b_io_export Wed Jan 29 17:00:32 2003
++++ linux-chaos/mm/page_alloc.c Wed Jan 29 17:01:31 2003
+@@ -31,6 +31,7 @@
+ int nr_inactive_dirty_pages;
+ int nr_inactive_clean_pages;
+ pg_data_t *pgdat_list;
++EXPORT_SYMBOL(pgdat_list);
+
+ /*
+ * The zone_table array is used to look up the address of the
--- /dev/null
+
+
+
+ fs/jbd/commit.c | 27 +++++++++++++++++++++---
+ fs/jbd/journal.c | 1
+ fs/jbd/transaction.c | 56 ++++++++++++++++++++++++++++++++++++++++-----------
+ include/linux/jbd.h | 20 ++++++++++++++++++
+ 4 files changed, 90 insertions(+), 14 deletions(-)
+
+--- linux-2.4.19/fs/jbd/commit.c~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
++++ linux-2.4.19-root/fs/jbd/commit.c Sun Jan 19 19:46:42 2003
+@@ -475,7 +475,7 @@ start_journal_io:
+ transaction's t_log_list queue, and metadata buffers are on
+ the t_iobuf_list queue.
+
+- Wait for the transactions in reverse order. That way we are
++ Wait for the buffers in reverse order. That way we are
+ less likely to be woken up until all IOs have completed, and
+ so we incur less scheduling load.
+ */
+@@ -566,8 +566,10 @@ start_journal_io:
+
+ jbd_debug(3, "JBD: commit phase 6\n");
+
+- if (is_journal_aborted(journal))
++ if (is_journal_aborted(journal)) {
++ unlock_journal(journal);
+ goto skip_commit;
++ }
+
+ /* Done it all: now write the commit record. We should have
+ * cleaned up our previous buffers by now, so if we are in abort
+@@ -577,6 +579,7 @@ start_journal_io:
+ descriptor = journal_get_descriptor_buffer(journal);
+ if (!descriptor) {
+ __journal_abort_hard(journal);
++ unlock_journal(journal);
+ goto skip_commit;
+ }
+
+@@ -600,7 +603,6 @@ start_journal_io:
+ put_bh(bh); /* One for getblk() */
+ journal_unlock_journal_head(descriptor);
+ }
+- lock_journal(journal);
+
+ /* End of a transaction! Finally, we can do checkpoint
+ processing: any buffers committed as a result of this
+@@ -609,6 +611,25 @@ start_journal_io:
+
+ skip_commit:
+
++ /* Call any callbacks that had been registered for handles in this
++ * transaction. It is up to the callback to free any allocated
++ * memory.
++ */
++ if (!list_empty(&commit_transaction->t_jcb)) {
++ struct list_head *p, *n;
++ int error = is_journal_aborted(journal);
++
++ list_for_each_safe(p, n, &commit_transaction->t_jcb) {
++ struct journal_callback *jcb;
++
++ jcb = list_entry(p, struct journal_callback, jcb_list);
++ list_del(p);
++ jcb->jcb_func(jcb, error);
++ }
++ }
++
++ lock_journal(journal);
++
+ jbd_debug(3, "JBD: commit phase 7\n");
+
+ J_ASSERT(commit_transaction->t_sync_datalist == NULL);
+--- linux-2.4.19/fs/jbd/journal.c~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
++++ linux-2.4.19-root/fs/jbd/journal.c Sun Jan 19 19:46:42 2003
+@@ -58,6 +58,7 @@ EXPORT_SYMBOL(journal_sync_buffer);
+ #endif
+ EXPORT_SYMBOL(journal_flush);
+ EXPORT_SYMBOL(journal_revoke);
++EXPORT_SYMBOL(journal_callback_set);
+
+ EXPORT_SYMBOL(journal_init_dev);
+ EXPORT_SYMBOL(journal_init_inode);
+--- linux-2.4.19/fs/jbd/transaction.c~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
++++ linux-2.4.19-root/fs/jbd/transaction.c Sun Jan 19 19:46:42 2003
+@@ -57,6 +57,7 @@ static transaction_t * get_transaction (
+ transaction->t_state = T_RUNNING;
+ transaction->t_tid = journal->j_transaction_sequence++;
+ transaction->t_expires = jiffies + journal->j_commit_interval;
++ INIT_LIST_HEAD(&transaction->t_jcb);
+
+ /* Set up the commit timer for the new transaction. */
+ J_ASSERT (!journal->j_commit_timer_active);
+@@ -201,6 +202,20 @@ repeat_locked:
+ return 0;
+ }
+
++/* Allocate a new handle. This should probably be in a slab... */
++static handle_t *new_handle(int nblocks)
++{
++ handle_t *handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
++ if (!handle)
++ return NULL;
++ memset(handle, 0, sizeof (handle_t));
++ handle->h_buffer_credits = nblocks;
++ handle->h_ref = 1;
++ INIT_LIST_HEAD(&handle->h_jcb);
++
++ return handle;
++}
++
+ /*
+ * Obtain a new handle.
+ *
+@@ -227,14 +242,11 @@ handle_t *journal_start(journal_t *journ
+ handle->h_ref++;
+ return handle;
+ }
+-
+- handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
++
++ handle = new_handle(nblocks);
+ if (!handle)
+ return ERR_PTR(-ENOMEM);
+- memset (handle, 0, sizeof (handle_t));
+
+- handle->h_buffer_credits = nblocks;
+- handle->h_ref = 1;
+ current->journal_info = handle;
+
+ err = start_this_handle(journal, handle);
+@@ -333,14 +345,11 @@ handle_t *journal_try_start(journal_t *j
+
+ if (is_journal_aborted(journal))
+ return ERR_PTR(-EIO);
+-
+- handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
++
++ handle = new_handle(nblocks);
+ if (!handle)
+ return ERR_PTR(-ENOMEM);
+- memset (handle, 0, sizeof (handle_t));
+
+- handle->h_buffer_credits = nblocks;
+- handle->h_ref = 1;
+ current->journal_info = handle;
+
+ err = try_start_this_handle(journal, handle);
+@@ -1328,6 +1337,28 @@ out:
+ #endif
+
+ /*
++ * Register a callback function for this handle. The function will be
++ * called when the transaction that this handle is part of has been
++ * committed to disk with the original callback data struct and the
++ * error status of the journal as parameters. There is no guarantee of
++ * ordering between handles within a single transaction, nor between
++ * callbacks registered on the same handle.
++ *
++ * The caller is responsible for allocating the journal_callback struct.
++ * This is to allow the caller to add as much extra data to the callback
++ * as needed, but reduce the overhead of multiple allocations. The caller
++ * allocated struct must start with a struct journal_callback at offset 0,
++ * and has the caller-specific data afterwards.
++ */
++void journal_callback_set(handle_t *handle,
++ void (*func)(struct journal_callback *jcb, int error),
++ struct journal_callback *jcb)
++{
++ list_add(&jcb->jcb_list, &handle->h_jcb);
++ jcb->jcb_func = func;
++}
++
++/*
+ * All done for a particular handle.
+ *
+ * There is not much action needed here. We just return any remaining
+@@ -1393,7 +1424,10 @@ int journal_stop(handle_t *handle)
+ wake_up(&journal->j_wait_transaction_locked);
+ }
+
+- /*
++ /* Move callbacks from the handle to the transaction. */
++ list_splice(&handle->h_jcb, &transaction->t_jcb);
++
++ /*
+ * If the handle is marked SYNC, we need to set another commit
+ * going! We also want to force a commit if the current
+ * transaction is occupying too much of the log, or if the
+--- linux-2.4.19/include/linux/jbd.h~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
++++ linux-2.4.19-root/include/linux/jbd.h Sun Jan 19 19:46:42 2003
+@@ -249,6 +249,13 @@ static inline struct journal_head *bh2jh
+ return bh->b_private;
+ }
+
++#define HAVE_JOURNAL_CALLBACK_STATUS
++struct journal_callback {
++ struct list_head jcb_list;
++ void (*jcb_func)(struct journal_callback *jcb, int error);
++ /* user data goes here */
++};
++
+ struct jbd_revoke_table_s;
+
+ /* The handle_t type represents a single atomic update being performed
+@@ -279,6 +286,12 @@ struct handle_s
+ operations */
+ int h_err;
+
++ /* List of application registered callbacks for this handle.
++ * The function(s) will be called after the transaction that
++ * this handle is part of has been committed to disk.
++ */
++ struct list_head h_jcb;
++
+ /* Flags */
+ unsigned int h_sync: 1; /* sync-on-close */
+ unsigned int h_jdata: 1; /* force data journaling */
+@@ -398,6 +411,10 @@ struct transaction_s
+
+ /* How many handles used this transaction? */
+ int t_handle_count;
++
++ /* List of registered callback functions for this transaction.
++ * Called when the transaction is committed. */
++ struct list_head t_jcb;
+ };
+
+
+@@ -646,6 +663,9 @@ extern int journal_flushpage(journal_t
+ extern int journal_try_to_free_buffers(journal_t *, struct page *, int);
+ extern int journal_stop(handle_t *);
+ extern int journal_flush (journal_t *);
++extern void journal_callback_set(handle_t *handle,
++ void (*fn)(struct journal_callback *,int),
++ struct journal_callback *jcb);
+
+ extern void journal_lock_updates (journal_t *);
+ extern void journal_unlock_updates (journal_t *);
--- /dev/null
+ arch/ia64/mm/init.c | 6 +++++
+ include/linux/slab.h | 1
+ kernel/ksyms.c | 1
+ mm/slab.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 61 insertions(+)
+
+--- linux-2.4.19-hp2_pnnl2/arch/ia64/mm/init.c~kmem_cache_validate_hp Sun Jan 19 18:59:23 2003
++++ linux-2.4.19-hp2_pnnl2-root/arch/ia64/mm/init.c Sun Jan 19 18:59:24 2003
+@@ -44,6 +44,12 @@ unsigned long vmalloc_end = VMALLOC_END_
+ static struct page *vmem_map;
+ static unsigned long num_dma_physpages;
+
++struct page *check_get_page(unsigned long kaddr)
++{
++#warning FIXME: Lustre team, is this solid?
++ return virt_to_page(kaddr);
++}
++
+ int
+ do_check_pgt_cache (int low, int high)
+ {
+--- linux-2.4.19-hp2_pnnl2/include/linux/slab.h~kmem_cache_validate_hp Sun Jan 19 18:59:23 2003
++++ linux-2.4.19-hp2_pnnl2-root/include/linux/slab.h Sun Jan 19 19:01:07 2003
+@@ -56,6 +56,7 @@ extern kmem_cache_t *kmem_cache_create(c
+ extern int kmem_cache_destroy(kmem_cache_t *);
+ extern int kmem_cache_shrink(kmem_cache_t *);
+ extern void *kmem_cache_alloc(kmem_cache_t *, int);
++extern int kmem_cache_validate(kmem_cache_t *cachep, void *objp);
+ extern void kmem_cache_free(kmem_cache_t *, void *);
+ extern unsigned int kmem_cache_size(kmem_cache_t *);
+
+--- linux-2.4.19-hp2_pnnl2/kernel/ksyms.c~kmem_cache_validate_hp Sun Jan 19 18:59:23 2003
++++ linux-2.4.19-hp2_pnnl2-root/kernel/ksyms.c Sun Jan 19 19:00:32 2003
+@@ -118,6 +118,7 @@ EXPORT_SYMBOL(kmem_find_general_cachep);
+ EXPORT_SYMBOL(kmem_cache_create);
+ EXPORT_SYMBOL(kmem_cache_destroy);
+ EXPORT_SYMBOL(kmem_cache_shrink);
++EXPORT_SYMBOL(kmem_cache_validate);
+ EXPORT_SYMBOL(kmem_cache_alloc);
+ EXPORT_SYMBOL(kmem_cache_free);
+ EXPORT_SYMBOL(kmem_cache_size);
+--- linux-2.4.19-hp2_pnnl2/mm/slab.c~kmem_cache_validate_hp Sun Jan 19 18:59:23 2003
++++ linux-2.4.19-hp2_pnnl2-root/mm/slab.c Sun Jan 19 18:59:24 2003
+@@ -1207,6 +1207,59 @@ failed:
+ * Called with the cache-lock held.
+ */
+
++extern struct page *check_get_page(unsigned long kaddr);
++struct page *page_mem_map(struct page *page);
++static int kmem_check_cache_obj (kmem_cache_t * cachep,
++ slab_t *slabp, void * objp)
++{
++ int i;
++ unsigned int objnr;
++
++#if DEBUG
++ if (cachep->flags & SLAB_RED_ZONE) {
++ objp -= BYTES_PER_WORD;
++ if ( *(unsigned long *)objp != RED_MAGIC2)
++ /* Either write before start, or a double free. */
++ return 0;
++ if (*(unsigned long *)(objp+cachep->objsize -
++ BYTES_PER_WORD) != RED_MAGIC2)
++ /* Either write past end, or a double free. */
++ return 0;
++ }
++#endif
++
++ objnr = (objp-slabp->s_mem)/cachep->objsize;
++ if (objnr >= cachep->num)
++ return 0;
++ if (objp != slabp->s_mem + objnr*cachep->objsize)
++ return 0;
++
++ /* Check slab's freelist to see if this obj is there. */
++ for (i = slabp->free; i != BUFCTL_END; i = slab_bufctl(slabp)[i]) {
++ if (i == objnr)
++ return 0;
++ }
++ return 1;
++}
++
++
++int kmem_cache_validate(kmem_cache_t *cachep, void *objp)
++{
++ struct page *page = check_get_page((unsigned long)objp);
++
++ if (!VALID_PAGE(page))
++ return 0;
++
++ if (!PageSlab(page))
++ return 0;
++
++ /* XXX check for freed slab objects ? */
++ if (!kmem_check_cache_obj(cachep, GET_PAGE_SLAB(page), objp))
++ return 0;
++
++ return (cachep == GET_PAGE_CACHE(page));
++}
++
+ #if DEBUG
+ static int kmem_extra_free_checks (kmem_cache_t * cachep,
+ slab_t *slabp, void * objp)
+
+_
- 0 files changed
+ include/linux/lustre_version.h | 1 +
+ 1 files changed, 1 insertion(+)
---- /dev/null 2002-08-30 16:31:37.000000000 -0700
-+++ linux-2.4.18-17.8.0-zab/include/linux/lustre_version.h 2002-12-06 14:52:30.000000000 -0800
+--- /dev/null Fri Aug 30 17:31:37 2002
++++ linux-2.4.18-18.8.0-l7-root/include/linux/lustre_version.h Mon Jan 20 12:24:45 2003
@@ -0,0 +1 @@
-+#define LUSTRE_KERNEL_VERSION 5
++#define LUSTRE_KERNEL_VERSION 10
_
- arch/i386/mm/init.c | 6 +
- arch/ia64/mm/init.c | 6 +
- drivers/block/blkpg.c | 35 ++++++
+
+
+
+ arch/i386/mm/init.c | 6
+ arch/ia64/mm/init.c | 6
+ drivers/block/blkpg.c | 35 ++++
drivers/block/loop.c | 5
- drivers/ide/ide-disk.c | 6 +
+ drivers/ide/ide-disk.c | 6
fs/dcache.c | 1
fs/ext3/Makefile | 2
fs/ext3/super.c | 2
- fs/jbd/commit.c | 27 ++++-
- fs/jbd/journal.c | 1
- fs/jbd/transaction.c | 56 ++++++++--
- fs/namei.c | 215 ++++++++++++++++++++++++++++++++---------
+ fs/namei.c | 296 ++++++++++++++++++++++++++++++++++-------
fs/nfsd/vfs.c | 2
- fs/open.c | 63 +++++++++---
- fs/stat.c | 30 ++++-
+ fs/open.c | 63 ++++++--
+ fs/stat.c | 30 +++-
include/linux/blkdev.h | 4
- include/linux/dcache.h | 31 +++++
- include/linux/fs.h | 14 ++
- include/linux/jbd.h | 20 +++
+ include/linux/dcache.h | 31 ++++
+ include/linux/fs.h | 23 +++
include/linux/lustre_version.h | 1
include/linux/slab.h | 1
- kernel/ksyms.c | 7 +
- mm/slab.c | 53 ++++++++++
- 23 files changed, 502 insertions(+), 86 deletions(-)
+ kernel/ksyms.c | 7
+ mm/slab.c | 53 +++++++
+ 19 files changed, 501 insertions(+), 73 deletions(-)
--- /dev/null Fri Aug 30 17:31:37 2002
-+++ linux-2.4.19-root/include/linux/lustre_version.h Sun Dec 15 16:58:43 2002
++++ linux-2.4.19-root/include/linux/lustre_version.h Sun Jan 19 19:54:00 2003
@@ -0,0 +1 @@
-+#define LUSTRE_KERNEL_VERSION 5
---- linux-2.4.19/arch/ia64/mm/init.c~vanilla-2.4.19 Sun Dec 15 16:58:43 2002
-+++ linux-2.4.19-root/arch/ia64/mm/init.c Sun Dec 15 16:58:43 2002
++#define LUSTRE_KERNEL_VERSION 7
+--- linux-2.4.19/arch/ia64/mm/init.c~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
++++ linux-2.4.19-root/arch/ia64/mm/init.c Sun Jan 19 19:46:42 2003
@@ -37,6 +37,12 @@ unsigned long MAX_DMA_ADDRESS = PAGE_OFF
static unsigned long totalram_pages;
int
do_check_pgt_cache (int low, int high)
{
---- linux-2.4.19/arch/i386/mm/init.c~vanilla-2.4.19 Sun Dec 15 16:58:43 2002
-+++ linux-2.4.19-root/arch/i386/mm/init.c Sun Dec 15 16:58:43 2002
+--- linux-2.4.19/arch/i386/mm/init.c~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
++++ linux-2.4.19-root/arch/i386/mm/init.c Sun Jan 19 19:46:42 2003
@@ -43,6 +43,12 @@ unsigned long highstart_pfn, highend_pfn
static unsigned long totalram_pages;
static unsigned long totalhigh_pages;
int do_check_pgt_cache(int low, int high)
{
int freed = 0;
---- linux-2.4.19/drivers/block/blkpg.c~vanilla-2.4.19 Sun Dec 15 16:58:43 2002
-+++ linux-2.4.19-root/drivers/block/blkpg.c Sun Dec 15 16:58:43 2002
+--- linux-2.4.19/drivers/block/blkpg.c~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
++++ linux-2.4.19-root/drivers/block/blkpg.c Sun Jan 19 19:46:42 2003
@@ -296,3 +296,38 @@ int blk_ioctl(kdev_t dev, unsigned int c
}
+EXPORT_SYMBOL(dev_set_rdonly);
+EXPORT_SYMBOL(dev_check_rdonly);
+EXPORT_SYMBOL(dev_clear_rdonly);
---- linux-2.4.19/drivers/block/loop.c~vanilla-2.4.19 Sun Dec 15 16:58:43 2002
-+++ linux-2.4.19-root/drivers/block/loop.c Sun Dec 15 16:58:43 2002
+--- linux-2.4.19/drivers/block/loop.c~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
++++ linux-2.4.19-root/drivers/block/loop.c Sun Jan 19 19:46:42 2003
@@ -474,6 +474,11 @@ static int loop_make_request(request_que
spin_unlock_irq(&lo->lo_lock);
if (lo->lo_flags & LO_FLAGS_READ_ONLY)
goto err;
} else if (rw == READA) {
---- linux-2.4.19/drivers/ide/ide-disk.c~vanilla-2.4.19 Sun Dec 15 16:58:43 2002
-+++ linux-2.4.19-root/drivers/ide/ide-disk.c Sun Dec 15 16:58:43 2002
+--- linux-2.4.19/drivers/ide/ide-disk.c~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
++++ linux-2.4.19-root/drivers/ide/ide-disk.c Sun Jan 19 19:46:42 2003
@@ -551,6 +551,12 @@ static ide_startstop_t lba_48_rw_disk (i
*/
static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
if (IDE_CONTROL_REG)
OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
---- linux-2.4.19/fs/ext3/Makefile~vanilla-2.4.19 Sun Dec 15 16:58:43 2002
-+++ linux-2.4.19-root/fs/ext3/Makefile Sun Dec 15 16:58:43 2002
+--- linux-2.4.19/fs/ext3/Makefile~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
++++ linux-2.4.19-root/fs/ext3/Makefile Sun Jan 19 19:46:42 2003
@@ -9,6 +9,8 @@
O_TARGET := ext3.o
obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
ioctl.o namei.o super.o symlink.o
obj-m := $(O_TARGET)
---- linux-2.4.19/fs/ext3/super.c~vanilla-2.4.19 Sun Dec 15 16:58:43 2002
-+++ linux-2.4.19-root/fs/ext3/super.c Sun Dec 15 16:58:43 2002
+--- linux-2.4.19/fs/ext3/super.c~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
++++ linux-2.4.19-root/fs/ext3/super.c Sun Jan 19 19:46:42 2003
@@ -1744,7 +1744,7 @@ static void __exit exit_ext3_fs(void)
unregister_filesystem(&ext3_fs_type);
}
MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
---- linux-2.4.19/fs/jbd/commit.c~vanilla-2.4.19 Sun Dec 15 16:58:43 2002
-+++ linux-2.4.19-root/fs/jbd/commit.c Sun Dec 15 16:58:43 2002
-@@ -475,7 +475,7 @@ start_journal_io:
- transaction's t_log_list queue, and metadata buffers are on
- the t_iobuf_list queue.
-
-- Wait for the transactions in reverse order. That way we are
-+ Wait for the buffers in reverse order. That way we are
- less likely to be woken up until all IOs have completed, and
- so we incur less scheduling load.
- */
-@@ -566,8 +566,10 @@ start_journal_io:
-
- jbd_debug(3, "JBD: commit phase 6\n");
-
-- if (is_journal_aborted(journal))
-+ if (is_journal_aborted(journal)) {
-+ unlock_journal(journal);
- goto skip_commit;
-+ }
-
- /* Done it all: now write the commit record. We should have
- * cleaned up our previous buffers by now, so if we are in abort
-@@ -577,6 +579,7 @@ start_journal_io:
- descriptor = journal_get_descriptor_buffer(journal);
- if (!descriptor) {
- __journal_abort_hard(journal);
-+ unlock_journal(journal);
- goto skip_commit;
- }
-
-@@ -600,7 +603,6 @@ start_journal_io:
- put_bh(bh); /* One for getblk() */
- journal_unlock_journal_head(descriptor);
- }
-- lock_journal(journal);
-
- /* End of a transaction! Finally, we can do checkpoint
- processing: any buffers committed as a result of this
-@@ -609,6 +611,25 @@ start_journal_io:
-
- skip_commit:
-
-+ /* Call any callbacks that had been registered for handles in this
-+ * transaction. It is up to the callback to free any allocated
-+ * memory.
-+ */
-+ if (!list_empty(&commit_transaction->t_jcb)) {
-+ struct list_head *p, *n;
-+ int error = is_journal_aborted(journal);
-+
-+ list_for_each_safe(p, n, &commit_transaction->t_jcb) {
-+ struct journal_callback *jcb;
-+
-+ jcb = list_entry(p, struct journal_callback, jcb_list);
-+ list_del(p);
-+ jcb->jcb_func(jcb, error);
-+ }
-+ }
-+
-+ lock_journal(journal);
-+
- jbd_debug(3, "JBD: commit phase 7\n");
-
- J_ASSERT(commit_transaction->t_sync_datalist == NULL);
---- linux-2.4.19/fs/jbd/journal.c~vanilla-2.4.19 Sun Dec 15 16:58:43 2002
-+++ linux-2.4.19-root/fs/jbd/journal.c Sun Dec 15 16:58:43 2002
-@@ -58,6 +58,7 @@ EXPORT_SYMBOL(journal_sync_buffer);
- #endif
- EXPORT_SYMBOL(journal_flush);
- EXPORT_SYMBOL(journal_revoke);
-+EXPORT_SYMBOL(journal_callback_set);
-
- EXPORT_SYMBOL(journal_init_dev);
- EXPORT_SYMBOL(journal_init_inode);
---- linux-2.4.19/fs/jbd/transaction.c~vanilla-2.4.19 Sun Dec 15 16:58:43 2002
-+++ linux-2.4.19-root/fs/jbd/transaction.c Sun Dec 15 16:58:43 2002
-@@ -57,6 +57,7 @@ static transaction_t * get_transaction (
- transaction->t_state = T_RUNNING;
- transaction->t_tid = journal->j_transaction_sequence++;
- transaction->t_expires = jiffies + journal->j_commit_interval;
-+ INIT_LIST_HEAD(&transaction->t_jcb);
-
- /* Set up the commit timer for the new transaction. */
- J_ASSERT (!journal->j_commit_timer_active);
-@@ -201,6 +202,20 @@ repeat_locked:
- return 0;
- }
-
-+/* Allocate a new handle. This should probably be in a slab... */
-+static handle_t *new_handle(int nblocks)
-+{
-+ handle_t *handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+ if (!handle)
-+ return NULL;
-+ memset(handle, 0, sizeof (handle_t));
-+ handle->h_buffer_credits = nblocks;
-+ handle->h_ref = 1;
-+ INIT_LIST_HEAD(&handle->h_jcb);
-+
-+ return handle;
-+}
-+
- /*
- * Obtain a new handle.
- *
-@@ -227,14 +242,11 @@ handle_t *journal_start(journal_t *journ
- handle->h_ref++;
- return handle;
- }
--
-- handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+
-+ handle = new_handle(nblocks);
- if (!handle)
- return ERR_PTR(-ENOMEM);
-- memset (handle, 0, sizeof (handle_t));
-
-- handle->h_buffer_credits = nblocks;
-- handle->h_ref = 1;
- current->journal_info = handle;
-
- err = start_this_handle(journal, handle);
-@@ -333,14 +345,11 @@ handle_t *journal_try_start(journal_t *j
-
- if (is_journal_aborted(journal))
- return ERR_PTR(-EIO);
--
-- handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+
-+ handle = new_handle(nblocks);
- if (!handle)
- return ERR_PTR(-ENOMEM);
-- memset (handle, 0, sizeof (handle_t));
-
-- handle->h_buffer_credits = nblocks;
-- handle->h_ref = 1;
- current->journal_info = handle;
-
- err = try_start_this_handle(journal, handle);
-@@ -1328,6 +1337,28 @@ out:
- #endif
-
- /*
-+ * Register a callback function for this handle. The function will be
-+ * called when the transaction that this handle is part of has been
-+ * committed to disk with the original callback data struct and the
-+ * error status of the journal as parameters. There is no guarantee of
-+ * ordering between handles within a single transaction, nor between
-+ * callbacks registered on the same handle.
-+ *
-+ * The caller is responsible for allocating the journal_callback struct.
-+ * This is to allow the caller to add as much extra data to the callback
-+ * as needed, but reduce the overhead of multiple allocations. The caller
-+ * allocated struct must start with a struct journal_callback at offset 0,
-+ * and has the caller-specific data afterwards.
-+ */
-+void journal_callback_set(handle_t *handle,
-+ void (*func)(struct journal_callback *jcb, int error),
-+ struct journal_callback *jcb)
-+{
-+ list_add(&jcb->jcb_list, &handle->h_jcb);
-+ jcb->jcb_func = func;
-+}
-+
-+/*
- * All done for a particular handle.
- *
- * There is not much action needed here. We just return any remaining
-@@ -1393,7 +1424,10 @@ int journal_stop(handle_t *handle)
- wake_up(&journal->j_wait_transaction_locked);
- }
-
-- /*
-+ /* Move callbacks from the handle to the transaction. */
-+ list_splice(&handle->h_jcb, &transaction->t_jcb);
-+
-+ /*
- * If the handle is marked SYNC, we need to set another commit
- * going! We also want to force a commit if the current
- * transaction is occupying too much of the log, or if the
---- linux-2.4.19/include/linux/blkdev.h~vanilla-2.4.19 Sun Dec 15 16:58:43 2002
-+++ linux-2.4.19-root/include/linux/blkdev.h Sun Dec 15 17:02:24 2002
+--- linux-2.4.19/include/linux/blkdev.h~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
++++ linux-2.4.19-root/include/linux/blkdev.h Sun Jan 19 21:05:55 2003
@@ -240,4 +240,8 @@ static inline unsigned int block_size(kd
return retval;
}
+int dev_check_rdonly(kdev_t);
+void dev_clear_rdonly(int);
#endif
---- linux-2.4.19/include/linux/slab.h~vanilla-2.4.19 Sun Dec 15 16:58:43 2002
-+++ linux-2.4.19-root/include/linux/slab.h Sun Dec 15 17:02:12 2002
+--- linux-2.4.19/include/linux/slab.h~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
++++ linux-2.4.19-root/include/linux/slab.h Sun Jan 19 21:05:52 2003
@@ -57,6 +57,7 @@ extern int kmem_cache_destroy(kmem_cache
extern int kmem_cache_shrink(kmem_cache_t *);
extern void *kmem_cache_alloc(kmem_cache_t *, int);
extern void *kmalloc(size_t, int);
extern void kfree(const void *);
---- linux-2.4.19/include/linux/jbd.h~vanilla-2.4.19 Sun Dec 15 16:58:43 2002
-+++ linux-2.4.19-root/include/linux/jbd.h Sun Dec 15 16:58:43 2002
-@@ -249,6 +249,13 @@ static inline struct journal_head *bh2jh
- return bh->b_private;
- }
-
-+#define HAVE_JOURNAL_CALLBACK_STATUS
-+struct journal_callback {
-+ struct list_head jcb_list;
-+ void (*jcb_func)(struct journal_callback *jcb, int error);
-+ /* user data goes here */
-+};
-+
- struct jbd_revoke_table_s;
-
- /* The handle_t type represents a single atomic update being performed
-@@ -279,6 +286,12 @@ struct handle_s
- operations */
- int h_err;
-
-+ /* List of application registered callbacks for this handle.
-+ * The function(s) will be called after the transaction that
-+ * this handle is part of has been committed to disk.
-+ */
-+ struct list_head h_jcb;
-+
- /* Flags */
- unsigned int h_sync: 1; /* sync-on-close */
- unsigned int h_jdata: 1; /* force data journaling */
-@@ -398,6 +411,10 @@ struct transaction_s
-
- /* How many handles used this transaction? */
- int t_handle_count;
-+
-+ /* List of registered callback functions for this transaction.
-+ * Called when the transaction is committed. */
-+ struct list_head t_jcb;
- };
-
-
-@@ -646,6 +663,9 @@ extern int journal_flushpage(journal_t
- extern int journal_try_to_free_buffers(journal_t *, struct page *, int);
- extern int journal_stop(handle_t *);
- extern int journal_flush (journal_t *);
-+extern void journal_callback_set(handle_t *handle,
-+ void (*fn)(struct journal_callback *,int),
-+ struct journal_callback *jcb);
-
- extern void journal_lock_updates (journal_t *);
- extern void journal_unlock_updates (journal_t *);
---- linux-2.4.19/kernel/ksyms.c~vanilla-2.4.19 Sun Dec 15 16:58:43 2002
-+++ linux-2.4.19-root/kernel/ksyms.c Sun Dec 15 17:03:55 2002
+--- linux-2.4.19/kernel/ksyms.c~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
++++ linux-2.4.19-root/kernel/ksyms.c Sun Jan 19 19:46:42 2003
@@ -264,6 +264,7 @@ EXPORT_SYMBOL(read_cache_page);
EXPORT_SYMBOL(set_page_dirty);
EXPORT_SYMBOL(vfs_readlink);
/* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */
EXPORT_SYMBOL(default_llseek);
EXPORT_SYMBOL(dentry_open);
---- linux-2.4.19/include/linux/dcache.h~vanilla-2.4.19 Sun Dec 15 16:58:43 2002
-+++ linux-2.4.19-root/include/linux/dcache.h Sun Dec 15 17:02:11 2002
+--- linux-2.4.19/include/linux/dcache.h~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
++++ linux-2.4.19-root/include/linux/dcache.h Sun Jan 19 19:46:42 2003
@@ -6,6 +6,34 @@
#include <asm/atomic.h>
#include <linux/mount.h>
};
/* the dentry parameter passed to d_hash and d_compare is the parent
---- linux-2.4.19/include/linux/fs.h~vanilla-2.4.19 Sun Dec 15 16:58:43 2002
-+++ linux-2.4.19-root/include/linux/fs.h Sun Dec 15 17:02:11 2002
+--- linux-2.4.19/include/linux/fs.h~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
++++ linux-2.4.19-root/include/linux/fs.h Sun Jan 19 21:05:40 2003
@@ -541,6 +541,7 @@ struct file {
/* needed for tty driver, and maybe others */
/*
* File types
-@@ -853,6 +856,7 @@ struct file_operations {
+@@ -853,16 +856,28 @@ struct file_operations {
struct inode_operations {
int (*create) (struct inode *,struct dentry *,int);
struct dentry * (*lookup) (struct inode *,struct dentry *);
+ struct dentry * (*lookup2) (struct inode *,struct dentry *, struct lookup_intent *);
int (*link) (struct dentry *,struct inode *,struct dentry *);
++ int (*link2) (struct inode *,struct inode *, const char *, int);
int (*unlink) (struct inode *,struct dentry *);
++ int (*unlink2) (struct inode *, char *, int);
int (*symlink) (struct inode *,struct dentry *,const char *);
-@@ -863,6 +867,8 @@ struct inode_operations {
++ int (*symlink2) (struct inode *,const char *, int, const char *);
+ int (*mkdir) (struct inode *,struct dentry *,int);
++ int (*mkdir2) (struct inode *,char *, int,int);
+ int (*rmdir) (struct inode *,struct dentry *);
++ int (*rmdir2) (struct inode *, char *, int);
+ int (*mknod) (struct inode *,struct dentry *,int,int);
++ int (*mknod2) (struct inode *,char *, int,int,int);
+ int (*rename) (struct inode *, struct dentry *,
struct inode *, struct dentry *);
++ int (*rename2) (struct inode *, struct inode *,
++ char *oldname, int oldlen,
++ char *newname, int newlen);
int (*readlink) (struct dentry *, char *,int);
int (*follow_link) (struct dentry *, struct nameidata *);
+ int (*follow_link2) (struct dentry *, struct nameidata *,
void (*truncate) (struct inode *);
int (*permission) (struct inode *, int);
int (*revalidate) (struct dentry *);
-@@ -999,6 +1005,7 @@ extern int unregister_filesystem(struct
+@@ -999,6 +1014,7 @@ extern int unregister_filesystem(struct
extern struct vfsmount *kern_mount(struct file_system_type *);
extern int may_umount(struct vfsmount *);
extern long do_mount(char *, char *, char *, unsigned long, void *);
-+struct vfsmount *do_kern_mount(char *type, int flags, char *name, void *data);
++struct vfsmount *do_kern_mount(const char *fstype, int flags, char *name, void *data);
extern void umount_tree(struct vfsmount *);
#define kern_umount mntput
-@@ -1329,6 +1336,7 @@ typedef int (*read_actor_t)(read_descrip
+@@ -1329,6 +1345,7 @@ typedef int (*read_actor_t)(read_descrip
extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *));
extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *));
extern int FASTCALL(path_walk(const char *, struct nameidata *));
extern int FASTCALL(link_path_walk(const char *, struct nameidata *));
-@@ -1339,6 +1347,8 @@ extern struct dentry * lookup_one_len(co
+@@ -1339,6 +1356,8 @@ extern struct dentry * lookup_one_len(co
extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
#define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
#define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
extern void iput(struct inode *);
extern void force_delete(struct inode *);
-@@ -1448,6 +1458,8 @@ extern struct file_operations generic_ro
+@@ -1448,6 +1467,8 @@ extern struct file_operations generic_ro
extern int vfs_readlink(struct dentry *, char *, int, const char *);
extern int vfs_follow_link(struct nameidata *, const char *);
extern int page_readlink(struct dentry *, char *, int);
extern int page_follow_link(struct dentry *, struct nameidata *);
extern struct inode_operations page_symlink_inode_operations;
---- linux-2.4.19/fs/dcache.c~vanilla-2.4.19 Sun Dec 15 16:58:43 2002
-+++ linux-2.4.19-root/fs/dcache.c Sun Dec 15 16:58:43 2002
+--- linux-2.4.19/fs/dcache.c~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
++++ linux-2.4.19-root/fs/dcache.c Sun Jan 19 19:46:42 2003
@@ -616,6 +616,7 @@ struct dentry * d_alloc(struct dentry *
dentry->d_op = NULL;
dentry->d_fsdata = NULL;
INIT_LIST_HEAD(&dentry->d_hash);
INIT_LIST_HEAD(&dentry->d_lru);
INIT_LIST_HEAD(&dentry->d_subdirs);
---- linux-2.4.19/fs/nfsd/vfs.c~vanilla-2.4.19 Sun Dec 15 16:58:43 2002
-+++ linux-2.4.19-root/fs/nfsd/vfs.c Sun Dec 15 16:58:43 2002
+--- linux-2.4.19/fs/nfsd/vfs.c~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
++++ linux-2.4.19-root/fs/nfsd/vfs.c Sun Jan 19 19:46:42 2003
@@ -1295,7 +1295,7 @@ nfsd_rename(struct svc_rqst *rqstp, stru
err = nfserr_perm;
} else
if (!err && EX_ISSYNC(tfhp->fh_export)) {
nfsd_sync_dir(tdentry);
nfsd_sync_dir(fdentry);
---- linux-2.4.19/fs/namei.c~vanilla-2.4.19 Sun Dec 15 16:58:43 2002
-+++ linux-2.4.19-root/fs/namei.c Sun Dec 15 16:58:43 2002
+--- linux-2.4.19/fs/namei.c~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
++++ linux-2.4.19-root/fs/namei.c Sun Jan 19 19:46:42 2003
@@ -94,6 +94,12 @@
* XEmacs seems to be relying on it...
*/
break;
}
goto return_base;
-@@ -651,10 +683,21 @@ return_err:
+@@ -646,15 +678,28 @@ out_dput:
+ dput(dentry);
+ break;
+ }
++ if (err)
++ intent_release(nd->dentry, it);
+ path_release(nd);
+ return_err:
return err;
}
}
/* SMP-safe */
-@@ -757,7 +800,8 @@ int path_init(const char *name, unsigned
+@@ -757,7 +802,8 @@ int path_init(const char *name, unsigned
* needs parent already locked. Doesn't follow mounts.
* SMP-safe.
*/
{
struct dentry * dentry;
struct inode *inode;
-@@ -780,13 +824,16 @@ struct dentry * lookup_hash(struct qstr
+@@ -780,13 +826,16 @@ struct dentry * lookup_hash(struct qstr
goto out;
}
dentry = inode->i_op->lookup(inode, new);
unlock_kernel();
if (!dentry)
-@@ -798,6 +845,12 @@ out:
+@@ -798,6 +847,12 @@ out:
return dentry;
}
/* SMP-safe */
struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
{
-@@ -819,7 +872,7 @@ struct dentry * lookup_one_len(const cha
+@@ -819,7 +874,7 @@ struct dentry * lookup_one_len(const cha
}
this.hash = end_name_hash(hash);
access:
return ERR_PTR(-EACCES);
}
-@@ -851,6 +904,23 @@ int __user_walk(const char *name, unsign
+@@ -851,6 +906,23 @@ int __user_walk(const char *name, unsign
return err;
}
/*
* It's inline, so penalty for filesystems that don't use sticky bit is
* minimal.
-@@ -987,7 +1057,8 @@ exit_lock:
+@@ -987,7 +1059,8 @@ exit_lock:
* for symlinks (where the permissions are checked later).
* SMP-safe
*/
{
int acc_mode, error = 0;
struct inode *inode;
-@@ -1002,7 +1073,7 @@ int open_namei(const char * pathname, in
+@@ -1002,7 +1075,7 @@ int open_namei(const char * pathname, in
*/
if (!(flag & O_CREAT)) {
if (path_init(pathname, lookup_flags(flag), nd))
if (error)
return error;
dentry = nd->dentry;
-@@ -1012,6 +1083,10 @@ int open_namei(const char * pathname, in
+@@ -1012,6 +1085,10 @@ int open_namei(const char * pathname, in
/*
* Create - we need to know the parent.
*/
if (path_init(pathname, LOOKUP_PARENT, nd))
error = path_walk(pathname, nd);
if (error)
-@@ -1028,7 +1103,7 @@ int open_namei(const char * pathname, in
+@@ -1028,7 +1105,7 @@ int open_namei(const char * pathname, in
dir = nd->dentry;
down(&dir->d_inode->i_sem);
do_last:
error = PTR_ERR(dentry);
-@@ -1037,6 +1112,7 @@ do_last:
+@@ -1037,6 +1114,7 @@ do_last:
goto exit;
}
/* Negative dentry, just create the file */
if (!dentry->d_inode) {
error = vfs_create(dir->d_inode, dentry,
-@@ -1070,7 +1146,8 @@ do_last:
+@@ -1070,7 +1148,8 @@ do_last:
error = -ENOENT;
if (!dentry->d_inode)
goto exit_dput;
goto do_link;
dput(nd->dentry);
-@@ -1156,8 +1233,10 @@ ok:
+@@ -1156,8 +1235,10 @@ ok:
return 0;
exit_dput:
path_release(nd);
return error;
-@@ -1176,7 +1255,12 @@ do_link:
+@@ -1176,7 +1257,12 @@ do_link:
* are done. Procfs-like symlinks just set LAST_BIND.
*/
UPDATE_ATIME(dentry->d_inode);
dput(dentry);
if (error)
return error;
-@@ -1198,13 +1282,20 @@ do_link:
+@@ -1198,13 +1284,20 @@ do_link:
}
dir = nd->dentry;
down(&dir->d_inode->i_sem);
{
struct dentry *dentry;
-@@ -1212,7 +1303,7 @@ static struct dentry *lookup_create(stru
+@@ -1212,7 +1305,7 @@ static struct dentry *lookup_create(stru
dentry = ERR_PTR(-EEXIST);
if (nd->last_type != LAST_NORM)
goto fail;
if (IS_ERR(dentry))
goto fail;
if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
-@@ -1258,6 +1349,7 @@ asmlinkage long sys_mknod(const char * f
+@@ -1258,6 +1351,7 @@ asmlinkage long sys_mknod(const char * f
char * tmp;
struct dentry * dentry;
struct nameidata nd;
if (S_ISDIR(mode))
return -EPERM;
-@@ -1269,7 +1361,7 @@ asmlinkage long sys_mknod(const char * f
+@@ -1269,7 +1363,19 @@ asmlinkage long sys_mknod(const char * f
error = path_walk(tmp, &nd);
if (error)
goto out;
- dentry = lookup_create(&nd, 0);
++
++ if (nd.dentry->d_inode->i_op->mknod2) {
++ struct inode_operations *op = nd.dentry->d_inode->i_op;
++ error = op->mknod2(nd.dentry->d_inode,
++ nd.last.name,
++ nd.last.len,
++ mode, dev);
++ /* the file system want to use normal vfs path now */
++ if (error != -EOPNOTSUPP)
++ goto out2;
++ }
++
+ dentry = lookup_create(&nd, 0, &it);
error = PTR_ERR(dentry);
mode &= ~current->fs->umask;
-@@ -1287,6 +1379,7 @@ asmlinkage long sys_mknod(const char * f
+@@ -1287,9 +1393,11 @@ asmlinkage long sys_mknod(const char * f
default:
error = -EINVAL;
}
dput(dentry);
}
up(&nd.dentry->d_inode->i_sem);
-@@ -1327,6 +1420,7 @@ asmlinkage long sys_mkdir(const char * p
++ out2:
+ path_release(&nd);
+ out:
+ putname(tmp);
+@@ -1327,6 +1435,7 @@ asmlinkage long sys_mkdir(const char * p
{
int error = 0;
char * tmp;
tmp = getname(pathname);
error = PTR_ERR(tmp);
-@@ -1338,11 +1432,12 @@ asmlinkage long sys_mkdir(const char * p
+@@ -1338,14 +1447,26 @@ asmlinkage long sys_mkdir(const char * p
error = path_walk(tmp, &nd);
if (error)
goto out;
- dentry = lookup_create(&nd, 1);
++ if (nd.dentry->d_inode->i_op->mkdir2) {
++ struct inode_operations *op = nd.dentry->d_inode->i_op;
++ error = op->mkdir2(nd.dentry->d_inode,
++ nd.last.name,
++ nd.last.len,
++ mode);
++ /* the file system want to use normal vfs path now */
++ if (error != -EOPNOTSUPP)
++ goto out2;
++ }
+ dentry = lookup_create(&nd, 1, &it);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
dput(dentry);
}
up(&nd.dentry->d_inode->i_sem);
-@@ -1426,6 +1521,7 @@ asmlinkage long sys_rmdir(const char * p
++out2:
+ path_release(&nd);
+ out:
+ putname(tmp);
+@@ -1426,6 +1547,7 @@ asmlinkage long sys_rmdir(const char * p
char * name;
struct dentry *dentry;
struct nameidata nd;
name = getname(pathname);
if(IS_ERR(name))
-@@ -1448,10 +1544,11 @@ asmlinkage long sys_rmdir(const char * p
+@@ -1447,11 +1569,21 @@ asmlinkage long sys_rmdir(const char * p
+ error = -EBUSY;
goto exit1;
}
++ if (nd.dentry->d_inode->i_op->rmdir2) {
++ struct inode_operations *op = nd.dentry->d_inode->i_op;
++ error = op->rmdir2(nd.dentry->d_inode,
++ nd.last.name,
++ nd.last.len);
++ /* the file system want to use normal vfs path now */
++ if (error != -EOPNOTSUPP)
++ goto exit1;
++ }
down(&nd.dentry->d_inode->i_sem);
- dentry = lookup_hash(&nd.last, nd.dentry);
+ dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
dput(dentry);
}
up(&nd.dentry->d_inode->i_sem);
-@@ -1495,6 +1592,7 @@ asmlinkage long sys_unlink(const char *
+@@ -1495,6 +1627,7 @@ asmlinkage long sys_unlink(const char *
char * name;
struct dentry *dentry;
struct nameidata nd;
name = getname(pathname);
if(IS_ERR(name))
-@@ -1508,7 +1606,7 @@ asmlinkage long sys_unlink(const char *
+@@ -1507,8 +1640,17 @@ asmlinkage long sys_unlink(const char *
+ error = -EISDIR;
if (nd.last_type != LAST_NORM)
goto exit1;
++ if (nd.dentry->d_inode->i_op->unlink2) {
++ struct inode_operations *op = nd.dentry->d_inode->i_op;
++ error = op->unlink2(nd.dentry->d_inode,
++ nd.last.name,
++ nd.last.len);
++ /* the file system want to use normal vfs path now */
++ if (error != -EOPNOTSUPP)
++ goto exit1;
++ }
down(&nd.dentry->d_inode->i_sem);
- dentry = lookup_hash(&nd.last, nd.dentry);
+ dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
/* Why not before? Because we want correct error value */
-@@ -1516,6 +1614,7 @@ asmlinkage long sys_unlink(const char *
+@@ -1516,6 +1658,7 @@ asmlinkage long sys_unlink(const char *
goto slashes;
error = vfs_unlink(nd.dentry->d_inode, dentry);
exit2:
dput(dentry);
}
up(&nd.dentry->d_inode->i_sem);
-@@ -1562,6 +1661,7 @@ asmlinkage long sys_symlink(const char *
+@@ -1562,6 +1705,7 @@ asmlinkage long sys_symlink(const char *
int error = 0;
char * from;
char * to;
from = getname(oldname);
if(IS_ERR(from))
-@@ -1576,10 +1676,12 @@ asmlinkage long sys_symlink(const char *
+@@ -1576,15 +1720,28 @@ asmlinkage long sys_symlink(const char *
error = path_walk(to, &nd);
if (error)
goto out;
- dentry = lookup_create(&nd, 0);
++ if (nd.dentry->d_inode->i_op->symlink2) {
++ struct inode_operations *op = nd.dentry->d_inode->i_op;
++ error = op->symlink2(nd.dentry->d_inode,
++ nd.last.name,
++ nd.last.len,
++ from);
++ /* the file system want to use normal vfs path now */
++ if (error != -EOPNOTSUPP)
++ goto out2;
++ }
+ it.it_data = from;
+ dentry = lookup_create(&nd, 0, &it);
error = PTR_ERR(dentry);
dput(dentry);
}
up(&nd.dentry->d_inode->i_sem);
-@@ -1645,6 +1747,7 @@ asmlinkage long sys_link(const char * ol
++ out2:
+ path_release(&nd);
+-out:
++ out:
+ putname(to);
+ }
+ putname(from);
+@@ -1645,6 +1802,7 @@ asmlinkage long sys_link(const char * ol
int error;
char * from;
char * to;
from = getname(oldname);
if(IS_ERR(from))
-@@ -1657,7 +1760,7 @@ asmlinkage long sys_link(const char * ol
+@@ -1657,7 +1815,7 @@ asmlinkage long sys_link(const char * ol
error = 0;
if (path_init(from, LOOKUP_POSITIVE, &old_nd))
if (error)
goto exit;
if (path_init(to, LOOKUP_PARENT, &nd))
-@@ -1667,10 +1770,12 @@ asmlinkage long sys_link(const char * ol
+@@ -1667,10 +1825,22 @@ asmlinkage long sys_link(const char * ol
error = -EXDEV;
if (old_nd.mnt != nd.mnt)
goto out_release;
- new_dentry = lookup_create(&nd, 0);
++ if (nd.dentry->d_inode->i_op->link2) {
++ struct inode_operations *op = nd.dentry->d_inode->i_op;
++ error = op->link2(old_nd.dentry->d_inode,
++ nd.dentry->d_inode,
++ nd.last.name,
++ nd.last.len);
++ /* the file system want to use normal vfs path now */
++ if (error != -EOPNOTSUPP)
++ goto out_release;
++ }
+ it.it_op = IT_LINK2;
+ new_dentry = lookup_create(&nd, 0, &it);
error = PTR_ERR(new_dentry);
dput(new_dentry);
}
up(&nd.dentry->d_inode->i_sem);
-@@ -1713,7 +1818,8 @@ exit:
+@@ -1713,7 +1883,8 @@ exit:
* locking].
*/
int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
{
int error;
struct inode *target;
-@@ -1771,6 +1877,7 @@ int vfs_rename_dir(struct inode *old_dir
+@@ -1771,6 +1942,7 @@ int vfs_rename_dir(struct inode *old_dir
error = -EBUSY;
else
error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
if (target) {
if (!error)
target->i_flags |= S_DEAD;
-@@ -1792,7 +1899,8 @@ out_unlock:
+@@ -1792,7 +1964,8 @@ out_unlock:
}
int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
{
int error;
-@@ -1823,6 +1931,7 @@ int vfs_rename_other(struct inode *old_d
+@@ -1823,6 +1996,7 @@ int vfs_rename_other(struct inode *old_d
error = -EBUSY;
else
error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
double_up(&old_dir->i_zombie, &new_dir->i_zombie);
if (error)
return error;
-@@ -1834,13 +1943,14 @@ int vfs_rename_other(struct inode *old_d
+@@ -1834,13 +2008,14 @@ int vfs_rename_other(struct inode *old_d
}
int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (!error) {
if (old_dir == new_dir)
inode_dir_notify(old_dir, DN_RENAME);
-@@ -1857,6 +1967,7 @@ static inline int do_rename(const char *
+@@ -1857,6 +2032,7 @@ static inline int do_rename(const char *
int error = 0;
struct dentry * old_dir, * new_dir;
struct dentry * old_dentry, *new_dentry;
struct nameidata oldnd, newnd;
if (path_init(oldname, LOOKUP_PARENT, &oldnd))
-@@ -1885,7 +1996,7 @@ static inline int do_rename(const char *
-
+@@ -1883,9 +2059,23 @@ static inline int do_rename(const char *
+ if (newnd.last_type != LAST_NORM)
+ goto exit2;
+
++ if (old_dir->d_inode->i_op->rename2) {
++ lock_kernel();
++ error = old_dir->d_inode->i_op->rename2(old_dir->d_inode,
++ new_dir->d_inode,
++ oldnd.last.name,
++ oldnd.last.len,
++ newnd.last.name,
++ newnd.last.len);
++ unlock_kernel();
++ /* the file system want to use normal vfs path now */
++ if (error != -EOPNOTSUPP)
++ goto exit2;
++ }
++
double_lock(new_dir, old_dir);
- old_dentry = lookup_hash(&oldnd.last, old_dir);
error = PTR_ERR(old_dentry);
if (IS_ERR(old_dentry))
goto exit3;
-@@ -1901,18 +2012,21 @@ static inline int do_rename(const char *
+@@ -1901,18 +2091,21 @@ static inline int do_rename(const char *
if (newnd.last.name[newnd.last.len])
goto exit4;
}
dput(old_dentry);
exit3:
double_up(&new_dir->d_inode->i_sem, &old_dir->d_inode->i_sem);
-@@ -1961,7 +2075,8 @@ out:
+@@ -1961,7 +2154,8 @@ out:
}
static inline int
{
int res = 0;
char *name;
-@@ -1974,7 +2089,7 @@ __vfs_follow_link(struct nameidata *nd,
+@@ -1974,7 +2168,7 @@ __vfs_follow_link(struct nameidata *nd,
/* weird __emul_prefix() stuff did it */
goto out;
}
out:
if (current->link_count || res || nd->last_type!=LAST_NORM)
return res;
-@@ -1996,7 +2111,13 @@ fail:
+@@ -1996,7 +2190,13 @@ fail:
int vfs_follow_link(struct nameidata *nd, const char *link)
{
}
/* get the link contents into pagecache */
-@@ -2038,7 +2159,7 @@ int page_follow_link(struct dentry *dent
+@@ -2038,7 +2238,7 @@ int page_follow_link(struct dentry *dent
{
struct page *page = NULL;
char *s = page_getlink(dentry, &page);
if (page) {
kunmap(page);
page_cache_release(page);
---- linux-2.4.19/fs/open.c~vanilla-2.4.19 Sun Dec 15 16:58:43 2002
-+++ linux-2.4.19-root/fs/open.c Sun Dec 15 16:58:43 2002
+--- linux-2.4.19/fs/open.c~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
++++ linux-2.4.19-root/fs/open.c Sun Jan 19 19:46:42 2003
@@ -19,6 +19,9 @@
#include <asm/uaccess.h>
/*
* Find an empty file descriptor entry, and mark it busy.
*/
---- linux-2.4.19/fs/stat.c~vanilla-2.4.19 Sun Dec 15 16:58:43 2002
-+++ linux-2.4.19-root/fs/stat.c Sun Dec 15 16:58:43 2002
+--- linux-2.4.19/fs/stat.c~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
++++ linux-2.4.19-root/fs/stat.c Sun Jan 19 19:46:42 2003
@@ -13,6 +13,7 @@
#include <asm/uaccess.h>
path_release(&nd);
}
return error;
---- linux-2.4.19/mm/slab.c~vanilla-2.4.19 Sun Dec 15 16:58:43 2002
-+++ linux-2.4.19-root/mm/slab.c Sun Dec 15 16:58:43 2002
+--- linux-2.4.19/mm/slab.c~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
++++ linux-2.4.19-root/mm/slab.c Sun Jan 19 19:46:42 2003
@@ -1207,6 +1207,59 @@ failed:
* Called with the cache-lock held.
*/
- fs/dcache.c | 3
- fs/namei.c | 228 ++++++++++++++++++++++++++++++++++++++-----------
+ fs/dcache.c | 8 +
+ fs/namei.c | 288 ++++++++++++++++++++++++++++++++++++++++---------
fs/nfsd/vfs.c | 2
- fs/open.c | 53 +++++++++--
+ fs/open.c | 53 +++++++--
fs/stat.c | 9 +
- include/linux/dcache.h | 31 ++++++
- include/linux/fs.h | 13 ++
+ include/linux/dcache.h | 25 ++++
+ include/linux/fs.h | 22 +++
kernel/ksyms.c | 1
- 8 files changed, 278 insertions(+), 62 deletions(-)
+ 8 files changed, 345 insertions(+), 63 deletions(-)
---- linux-2.4.18-18.8.0-l4/fs/dcache.c~vfs_intent-2.4.18-18 Sat Dec 14 06:31:22 2002
-+++ linux-2.4.18-18.8.0-l4-root/fs/dcache.c Sat Dec 14 06:31:22 2002
-@@ -150,6 +150,8 @@ repeat:
- unhash_it:
- list_del_init(&dentry->d_hash);
-
+--- linux-2.4.18-49chaos-lustre9/fs/dcache.c~vfs_intent-2.4.18-18 Wed Jan 29 12:43:32 2003
++++ linux-2.4.18-49chaos-lustre9-root/fs/dcache.c Wed Jan 29 12:43:32 2003
+@@ -186,6 +186,13 @@ int d_invalidate(struct dentry * dentry)
+ spin_unlock(&dcache_lock);
+ return 0;
+ }
+
++ /* network invalidation by Lustre */
++ if (dentry->d_flags & DCACHE_LUSTRE_INVALID) {
++ spin_unlock(&dcache_lock);
++ return 0;
++ }
+
- kill_it: {
- struct dentry *parent;
- list_del(&dentry->d_child);
-@@ -645,6 +647,7 @@ struct dentry * d_alloc(struct dentry *
+ /*
+ * Check whether to do a partial shrink_dcache
+ * to get rid of unused child entries.
+@@ -645,6 +652,7 @@ struct dentry * d_alloc(struct dentry *
dentry->d_fsdata = NULL;
dentry->d_extra_attributes = NULL;
dentry->d_mounted = 0;
INIT_LIST_HEAD(&dentry->d_hash);
INIT_LIST_HEAD(&dentry->d_lru);
INIT_LIST_HEAD(&dentry->d_subdirs);
---- linux-2.4.18-18.8.0-l4/fs/namei.c~vfs_intent-2.4.18-18 Sat Dec 14 06:31:22 2002
-+++ linux-2.4.18-18.8.0-l4-root/fs/namei.c Sat Dec 14 06:37:21 2002
-@@ -1,3 +1,6 @@
-+
-+
-+
- /*
- * linux/fs/namei.c
- *
-@@ -94,6 +97,14 @@
+--- linux-2.4.18-49chaos-lustre9/fs/namei.c~vfs_intent-2.4.18-18 Wed Jan 29 12:43:32 2003
++++ linux-2.4.18-49chaos-lustre9-root/fs/namei.c Wed Feb 5 16:23:06 2003
+@@ -94,6 +94,13 @@
* XEmacs seems to be relying on it...
*/
+
+}
+
-+
/* In order to reduce some races, while at the same time doing additional
* checking and hopefully speeding things up, we copy filenames to the
* kernel data space before using them..
-@@ -260,10 +271,19 @@ void path_release(struct nameidata *nd)
+@@ -260,10 +267,19 @@ void path_release(struct nameidata *nd)
* Internal lookup() using the new generic dcache.
* SMP-safe
*/
if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
dput(dentry);
-@@ -281,7 +301,8 @@ static struct dentry * cached_lookup(str
+@@ -281,11 +297,14 @@ static struct dentry * cached_lookup(str
* make sure that nobody added the entry to the dcache in the meantime..
* SMP-safe
*/
{
struct dentry * result;
struct inode *dir = parent->d_inode;
-@@ -300,6 +321,9 @@ static struct dentry * real_lookup(struc
+
++again:
++
+ down(&dir->i_sem);
+ /*
+ * First re-do the cached lookup just in case it was created
+@@ -300,6 +319,9 @@ static struct dentry * real_lookup(struc
result = ERR_PTR(-ENOMEM);
if (dentry) {
lock_kernel();
result = dir->i_op->lookup(dir, dentry);
unlock_kernel();
if (result)
-@@ -321,6 +345,12 @@ static struct dentry * real_lookup(struc
+@@ -321,6 +343,12 @@ static struct dentry * real_lookup(struc
dput(result);
result = ERR_PTR(-ENOENT);
}
+ if (!result->d_op->d_revalidate2(result, flags, it) &&
+ !d_invalidate(result)) {
+ dput(result);
-+ result = ERR_PTR(-ENOENT);
++ goto again;
+ }
}
return result;
}
-@@ -334,7 +364,8 @@ int max_recursive_link = 5;
+@@ -334,7 +362,8 @@ int max_recursive_link = 5;
* Without that kind of total limit, nasty chains of consecutive
* symlinks can cause almost arbitrarily long lookups.
*/
-static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd)
-+static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd,
-+ struct lookup_intent *it)
++static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd,
++ struct lookup_intent *it)
{
int err;
if (current->link_count >= max_recursive_link)
-@@ -348,10 +379,14 @@ static inline int do_follow_link(struct
+@@ -348,10 +377,14 @@ static inline int do_follow_link(struct
current->link_count++;
current->total_link_count++;
UPDATE_ATIME(dentry->d_inode);
- err = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (dentry->d_inode->i_op->follow_link2)
-+ err = dentry->d_inode->i_op->follow_link2(dentry, nd, it);
-+ else
-+ err = dentry->d_inode->i_op->follow_link(dentry, nd);
++ if (dentry->d_inode->i_op->follow_link2)
++ err = dentry->d_inode->i_op->follow_link2(dentry, nd, it);
++ else
++ err = dentry->d_inode->i_op->follow_link(dentry, nd);
current->link_count--;
return err;
loop:
-+ intent_release(dentry, it);
++ intent_release(dentry, it);
path_release(nd);
return -ELOOP;
}
-@@ -449,7 +484,8 @@ static inline void follow_dotdot(struct
+@@ -449,7 +482,8 @@ static inline void follow_dotdot(struct
*
* We expect 'base' to be positive and a directory.
*/
{
struct dentry *dentry;
struct inode *inode;
-@@ -526,12 +562,12 @@ int link_path_walk(const char * name, st
+@@ -526,12 +560,12 @@ int link_path_walk(const char * name, st
break;
}
/* This does the actual lookups.. */
err = PTR_ERR(dentry);
if (IS_ERR(dentry))
break;
-@@ -548,8 +584,8 @@ int link_path_walk(const char * name, st
+@@ -548,8 +582,8 @@ int link_path_walk(const char * name, st
if (!inode->i_op)
goto out_dput;
dput(dentry);
if (err)
goto return_err;
-@@ -565,7 +601,7 @@ int link_path_walk(const char * name, st
+@@ -565,7 +599,7 @@ int link_path_walk(const char * name, st
nd->dentry = dentry;
}
err = -ENOTDIR;
break;
continue;
/* here ends the main loop */
-@@ -592,12 +628,12 @@ last_component:
+@@ -592,12 +626,12 @@ last_component:
if (err < 0)
break;
}
err = PTR_ERR(dentry);
if (IS_ERR(dentry))
break;
-@@ -606,8 +642,10 @@ last_component:
+@@ -606,8 +640,9 @@ last_component:
;
inode = dentry->d_inode;
if ((lookup_flags & LOOKUP_FOLLOW)
- && inode && inode->i_op && inode->i_op->follow_link) {
- err = do_follow_link(dentry, nd);
-+ && inode && inode->i_op &&
-+ (inode->i_op->follow_link ||
-+ inode->i_op->follow_link2)) {
++ && inode && inode->i_op &&
++ (inode->i_op->follow_link || inode->i_op->follow_link2)) {
+ err = do_follow_link(dentry, nd, it);
dput(dentry);
if (err)
goto return_err;
-@@ -621,7 +659,8 @@ last_component:
+@@ -621,7 +656,8 @@ last_component:
goto no_inode;
if (lookup_flags & LOOKUP_DIRECTORY) {
err = -ENOTDIR;
- if (!inode->i_op || !inode->i_op->lookup)
-+ if (!inode->i_op || (!inode->i_op->lookup &&
-+ !inode->i_op->lookup2))
++ if (!inode->i_op ||
++ (!inode->i_op->lookup && !inode->i_op->lookup2))
break;
}
goto return_base;
-@@ -663,10 +702,21 @@ return_err:
+@@ -658,15 +694,28 @@ out_dput:
+ dput(dentry);
+ break;
+ }
++ if (err)
++ intent_release(nd->dentry, it);
+ path_release(nd);
+ return_err:
return err;
}
}
/* SMP-safe */
-@@ -751,6 +801,17 @@ walk_init_root(const char *name, struct
+@@ -751,6 +800,17 @@ walk_init_root(const char *name, struct
}
/* SMP-safe */
int path_lookup(const char *path, unsigned flags, struct nameidata *nd)
{
int error = 0;
-@@ -779,7 +840,8 @@ int path_init(const char *name, unsigned
+@@ -779,7 +839,8 @@ int path_init(const char *name, unsigned
* needs parent already locked. Doesn't follow mounts.
* SMP-safe.
*/
{
struct dentry * dentry;
struct inode *inode;
-@@ -802,13 +864,16 @@ struct dentry * lookup_hash(struct qstr
+@@ -802,13 +863,16 @@ struct dentry * lookup_hash(struct qstr
goto out;
}
dentry = inode->i_op->lookup(inode, new);
unlock_kernel();
if (!dentry)
-@@ -820,6 +885,12 @@ out:
+@@ -820,6 +884,12 @@ out:
return dentry;
}
/* SMP-safe */
struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
{
-@@ -841,7 +912,7 @@ struct dentry * lookup_one_len(const cha
+@@ -841,7 +911,7 @@ struct dentry * lookup_one_len(const cha
}
this.hash = end_name_hash(hash);
access:
return ERR_PTR(-EACCES);
}
-@@ -872,6 +943,23 @@ int __user_walk(const char *name, unsign
+@@ -872,6 +942,23 @@ int __user_walk(const char *name, unsign
return err;
}
/*
* It's inline, so penalty for filesystems that don't use sticky bit is
* minimal.
-@@ -1045,14 +1133,17 @@ int may_open(struct nameidata *nd, int a
+@@ -1045,14 +1132,17 @@ int may_open(struct nameidata *nd, int a
return get_lease(inode, flag);
}
+extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
-+ int flags, struct lookup_intent *it);
++ int flags, struct lookup_intent *it);
+
struct file *filp_open(const char * pathname, int open_flags, int mode)
{
struct dentry *dir;
int flag = open_flags;
struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_OPEN };
++ struct lookup_intent it = { .it_op = IT_OPEN, .it_flags = open_flags };
int count = 0;
if ((flag+1) & O_ACCMODE)
-@@ -1066,7 +1157,7 @@ struct file *filp_open(const char * path
+@@ -1066,7 +1156,7 @@ struct file *filp_open(const char * path
* The simplest case - just a plain lookup.
*/
if (!(flag & O_CREAT)) {
if (error)
return ERR_PTR(error);
dentry = nd.dentry;
-@@ -1076,6 +1167,8 @@ struct file *filp_open(const char * path
+@@ -1076,6 +1166,8 @@ struct file *filp_open(const char * path
/*
* Create - we need to know the parent.
*/
-+ it.it_mode = mode;
-+ it.it_op |= IT_CREAT;
++ it.it_mode = mode;
++ it.it_op |= IT_CREAT;
error = path_lookup(pathname, LOOKUP_PARENT, &nd);
if (error)
return ERR_PTR(error);
-@@ -1091,7 +1184,7 @@ struct file *filp_open(const char * path
+@@ -1091,7 +1183,7 @@ struct file *filp_open(const char * path
dir = nd.dentry;
down(&dir->d_inode->i_sem);
do_last:
error = PTR_ERR(dentry);
-@@ -1100,6 +1193,7 @@ do_last:
+@@ -1100,6 +1192,7 @@ do_last:
goto exit;
}
/* Negative dentry, just create the file */
if (!dentry->d_inode) {
error = vfs_create(dir->d_inode, dentry,
-@@ -1134,7 +1228,8 @@ do_last:
+@@ -1134,7 +1227,8 @@ do_last:
error = -ENOENT;
if (!dentry->d_inode)
goto exit_dput;
- if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link)
-+ if (dentry->d_inode->i_op && (dentry->d_inode->i_op->follow_link ||
-+ dentry->d_inode->i_op->follow_link2))
++ if (dentry->d_inode->i_op && (dentry->d_inode->i_op->follow_link ||
++ dentry->d_inode->i_op->follow_link2))
goto do_link;
dput(nd.dentry);
-@@ -1149,11 +1244,13 @@ ok:
+@@ -1149,11 +1243,13 @@ ok:
if (!S_ISREG(nd.dentry->d_inode->i_mode))
open_flags &= ~O_TRUNC;
- return dentry_open(nd.dentry, nd.mnt, open_flags);
-+ return dentry_open_it(nd.dentry, nd.mnt, open_flags, &it);
++ return dentry_open_it(nd.dentry, nd.mnt, open_flags, &it);
exit_dput:
-+ intent_release(dentry, &it);
++ intent_release(dentry, &it);
dput(dentry);
exit:
-+ intent_release(nd.dentry, &it);
++ intent_release(nd.dentry, &it);
path_release(&nd);
return ERR_PTR(error);
-@@ -1172,7 +1269,12 @@ do_link:
+@@ -1172,7 +1268,12 @@ do_link:
* are done. Procfs-like symlinks just set LAST_BIND.
*/
UPDATE_ATIME(dentry->d_inode);
- error = dentry->d_inode->i_op->follow_link(dentry, &nd);
-+ if (dentry->d_inode->i_op->follow_link2)
-+ error = dentry->d_inode->i_op->follow_link2(dentry, &nd, &it);
-+ else
-+ error = dentry->d_inode->i_op->follow_link(dentry, &nd);
++ if (dentry->d_inode->i_op->follow_link2)
++ error = dentry->d_inode->i_op->follow_link2(dentry, &nd, &it);
++ else
++ error = dentry->d_inode->i_op->follow_link(dentry, &nd);
+ if (error)
+ intent_release(dentry, &it);
dput(dentry);
if (error)
return error;
-@@ -1194,13 +1296,15 @@ do_link:
+@@ -1194,13 +1295,15 @@ do_link:
}
dir = nd.dentry;
down(&dir->d_inode->i_sem);
{
struct dentry *dentry;
-@@ -1208,7 +1312,7 @@ static struct dentry *lookup_create(stru
+@@ -1208,7 +1311,7 @@ static struct dentry *lookup_create(stru
dentry = ERR_PTR(-EEXIST);
if (nd->last_type != LAST_NORM)
goto fail;
if (IS_ERR(dentry))
goto fail;
if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
-@@ -1254,6 +1358,7 @@ asmlinkage long sys_mknod(const char * f
- char * tmp;
- struct dentry * dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_MKNOD, .it_mode = mode };
-
- if (S_ISDIR(mode))
- return -EPERM;
-@@ -1264,7 +1369,7 @@ asmlinkage long sys_mknod(const char * f
+@@ -1264,7 +1367,19 @@ asmlinkage long sys_mknod(const char * f
error = path_lookup(tmp, LOOKUP_PARENT, &nd);
if (error)
goto out;
- dentry = lookup_create(&nd, 0);
-+ dentry = lookup_create(&nd, 0, &it);
++
++ if (nd.dentry->d_inode->i_op->mknod2) {
++ struct inode_operations *op = nd.dentry->d_inode->i_op;
++ error = op->mknod2(nd.dentry->d_inode,
++ nd.last.name,
++ nd.last.len,
++ mode, dev);
++ /* the file system want to use normal vfs path now */
++ if (error != -EOPNOTSUPP)
++ goto out2;
++ }
++
++ dentry = lookup_create(&nd, 0, NULL);
error = PTR_ERR(dentry);
mode &= ~current->fs->umask;
-@@ -1282,6 +1387,7 @@ asmlinkage long sys_mknod(const char * f
- default:
- error = -EINVAL;
- }
-+ intent_release(dentry, &it);
+@@ -1285,6 +1400,7 @@ asmlinkage long sys_mknod(const char * f
dput(dentry);
}
up(&nd.dentry->d_inode->i_sem);
-@@ -1322,6 +1428,7 @@ asmlinkage long sys_mkdir(const char * p
- {
- int error = 0;
- char * tmp;
-+ struct lookup_intent it = { .it_op = IT_MKDIR, .it_mode = mode };
-
- tmp = getname(pathname);
- error = PTR_ERR(tmp);
-@@ -1332,11 +1439,12 @@ asmlinkage long sys_mkdir(const char * p
++out2:
+ path_release(&nd);
+ out:
+ putname(tmp);
+@@ -1332,7 +1448,17 @@ asmlinkage long sys_mkdir(const char * p
error = path_lookup(tmp, LOOKUP_PARENT, &nd);
if (error)
goto out;
- dentry = lookup_create(&nd, 1);
-+ dentry = lookup_create(&nd, 1, &it);
++ if (nd.dentry->d_inode->i_op->mkdir2) {
++ struct inode_operations *op = nd.dentry->d_inode->i_op;
++ error = op->mkdir2(nd.dentry->d_inode,
++ nd.last.name,
++ nd.last.len,
++ mode);
++ /* the file system want to use normal vfs path now */
++ if (error != -EOPNOTSUPP)
++ goto out2;
++ }
++ dentry = lookup_create(&nd, 1, NULL);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
error = vfs_mkdir(nd.dentry->d_inode, dentry,
- mode & ~current->fs->umask);
-+ intent_release(dentry, &it);
+@@ -1340,6 +1466,7 @@ asmlinkage long sys_mkdir(const char * p
dput(dentry);
}
up(&nd.dentry->d_inode->i_sem);
-@@ -1420,6 +1528,7 @@ asmlinkage long sys_rmdir(const char * p
- char * name;
- struct dentry *dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_RMDIR };
-
- name = getname(pathname);
- if(IS_ERR(name))
-@@ -1441,10 +1550,11 @@ asmlinkage long sys_rmdir(const char * p
++out2:
+ path_release(&nd);
+ out:
+ putname(tmp);
+@@ -1440,8 +1567,17 @@ asmlinkage long sys_rmdir(const char * p
+ error = -EBUSY;
goto exit1;
}
++ if (nd.dentry->d_inode->i_op->rmdir2) {
++ struct inode_operations *op = nd.dentry->d_inode->i_op;
++ error = op->rmdir2(nd.dentry->d_inode,
++ nd.last.name,
++ nd.last.len);
++ /* the file system want to use normal vfs path now */
++ if (error != -EOPNOTSUPP)
++ goto exit1;
++ }
down(&nd.dentry->d_inode->i_sem);
- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
++ dentry = lookup_hash_it(&nd.last, nd.dentry, NULL);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
error = vfs_rmdir(nd.dentry->d_inode, dentry);
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1488,6 +1598,7 @@ asmlinkage long sys_unlink(const char *
- char * name;
- struct dentry *dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_UNLINK };
-
- name = getname(pathname);
- if(IS_ERR(name))
-@@ -1500,7 +1611,7 @@ asmlinkage long sys_unlink(const char *
+@@ -1499,8 +1635,17 @@ asmlinkage long sys_unlink(const char *
+ error = -EISDIR;
if (nd.last_type != LAST_NORM)
goto exit1;
++ if (nd.dentry->d_inode->i_op->unlink2) {
++ struct inode_operations *op = nd.dentry->d_inode->i_op;
++ error = op->unlink2(nd.dentry->d_inode,
++ nd.last.name,
++ nd.last.len);
++ /* the file system want to use normal vfs path now */
++ if (error != -EOPNOTSUPP)
++ goto exit1;
++ }
down(&nd.dentry->d_inode->i_sem);
- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
++ dentry = lookup_hash_it(&nd.last, nd.dentry, NULL);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
/* Why not before? Because we want correct error value */
-@@ -1508,6 +1619,7 @@ asmlinkage long sys_unlink(const char *
- goto slashes;
- error = vfs_unlink(nd.dentry->d_inode, dentry);
- exit2:
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1554,6 +1666,7 @@ asmlinkage long sys_symlink(const char *
- int error = 0;
- char * from;
- char * to;
-+ struct lookup_intent it = { .it_op = IT_SYMLINK };
-
- from = getname(oldname);
- if(IS_ERR(from))
-@@ -1567,10 +1680,12 @@ asmlinkage long sys_symlink(const char *
+@@ -1567,15 +1712,26 @@ asmlinkage long sys_symlink(const char *
error = path_lookup(to, LOOKUP_PARENT, &nd);
if (error)
goto out;
- dentry = lookup_create(&nd, 0);
-+ it.it_data = from;
-+ dentry = lookup_create(&nd, 0, &it);
++ if (nd.dentry->d_inode->i_op->symlink2) {
++ struct inode_operations *op = nd.dentry->d_inode->i_op;
++ error = op->symlink2(nd.dentry->d_inode,
++ nd.last.name,
++ nd.last.len,
++ from);
++ /* the file system want to use normal vfs path now */
++ if (error != -EOPNOTSUPP)
++ goto out2;
++ }
++ dentry = lookup_create(&nd, 0, NULL);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
error = vfs_symlink(nd.dentry->d_inode, dentry, from);
-+ intent_release(dentry, &it);
dput(dentry);
}
up(&nd.dentry->d_inode->i_sem);
-@@ -1635,6 +1750,7 @@ asmlinkage long sys_link(const char * ol
- {
- int error;
- char * to;
-+ struct lookup_intent it = { .it_op = IT_LINK };
-
- to = getname(newname);
- error = PTR_ERR(to);
-@@ -1642,7 +1758,7 @@ asmlinkage long sys_link(const char * ol
++ out2:
+ path_release(&nd);
+-out:
++ out:
+ putname(to);
+ }
+ putname(from);
+@@ -1642,7 +1798,7 @@ asmlinkage long sys_link(const char * ol
struct dentry *new_dentry;
struct nameidata nd, old_nd;
- error = __user_walk(oldname, LOOKUP_POSITIVE, &old_nd);
-+ error = __user_walk_it(oldname, LOOKUP_POSITIVE, &old_nd, &it);
++ error = __user_walk_it(oldname, LOOKUP_POSITIVE, &old_nd, NULL);
if (error)
goto exit;
error = path_lookup(to, LOOKUP_PARENT, &nd);
-@@ -1651,10 +1767,12 @@ asmlinkage long sys_link(const char * ol
+@@ -1651,7 +1807,17 @@ asmlinkage long sys_link(const char * ol
error = -EXDEV;
if (old_nd.mnt != nd.mnt)
goto out_release;
- new_dentry = lookup_create(&nd, 0);
-+ it.it_op = IT_LINK2;
-+ new_dentry = lookup_create(&nd, 0, &it);
++ if (nd.dentry->d_inode->i_op->link2) {
++ struct inode_operations *op = nd.dentry->d_inode->i_op;
++ error = op->link2(old_nd.dentry->d_inode,
++ nd.dentry->d_inode,
++ nd.last.name,
++ nd.last.len);
++ /* the file system want to use normal vfs path now */
++ if (error != -EOPNOTSUPP)
++ goto out_release;
++ }
++ new_dentry = lookup_create(&nd, 0, NULL);
error = PTR_ERR(new_dentry);
if (!IS_ERR(new_dentry)) {
error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
-+ intent_release(new_dentry, &it);
- dput(new_dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1695,7 +1813,8 @@ exit:
+@@ -1695,7 +1861,8 @@ exit:
* locking].
*/
int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
{
int error;
struct inode *target;
-@@ -1753,6 +1872,7 @@ int vfs_rename_dir(struct inode *old_dir
+@@ -1753,6 +1920,7 @@ int vfs_rename_dir(struct inode *old_dir
error = -EBUSY;
else
error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
if (target) {
if (!error)
target->i_flags |= S_DEAD;
-@@ -1774,7 +1894,8 @@ out_unlock:
+@@ -1774,7 +1942,8 @@ out_unlock:
}
int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
{
int error;
-@@ -1805,6 +1926,7 @@ int vfs_rename_other(struct inode *old_d
+@@ -1805,6 +1974,7 @@ int vfs_rename_other(struct inode *old_d
error = -EBUSY;
else
error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
double_up(&old_dir->i_zombie, &new_dir->i_zombie);
if (error)
return error;
-@@ -1816,13 +1938,14 @@ int vfs_rename_other(struct inode *old_d
+@@ -1816,13 +1986,14 @@ int vfs_rename_other(struct inode *old_d
}
int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (!error) {
if (old_dir == new_dir)
inode_dir_notify(old_dir, DN_RENAME);
-@@ -1839,6 +1962,7 @@ static inline int do_rename(const char *
- int error = 0;
- struct dentry * old_dir, * new_dir;
- struct dentry * old_dentry, *new_dentry;
-+ struct lookup_intent it = { .it_op = IT_RENAME };
- struct nameidata oldnd, newnd;
-
- error = path_lookup(oldname, LOOKUP_PARENT, &oldnd);
-@@ -1864,7 +1988,7 @@ static inline int do_rename(const char *
-
+@@ -1862,9 +2033,23 @@ static inline int do_rename(const char *
+ if (newnd.last_type != LAST_NORM)
+ goto exit2;
+
++ if (old_dir->d_inode->i_op->rename2) {
++ lock_kernel();
++ error = old_dir->d_inode->i_op->rename2(old_dir->d_inode,
++ new_dir->d_inode,
++ oldnd.last.name,
++ oldnd.last.len,
++ newnd.last.name,
++ newnd.last.len);
++ unlock_kernel();
++ /* the file system want to use normal vfs path now */
++ if (error != -EOPNOTSUPP)
++ goto exit2;
++ }
++
double_lock(new_dir, old_dir);
- old_dentry = lookup_hash(&oldnd.last, old_dir);
-+ old_dentry = lookup_hash_it(&oldnd.last, old_dir, &it);
++ old_dentry = lookup_hash_it(&oldnd.last, old_dir, NULL);
error = PTR_ERR(old_dentry);
if (IS_ERR(old_dentry))
goto exit3;
-@@ -1880,18 +2004,21 @@ static inline int do_rename(const char *
+@@ -1880,14 +2065,14 @@ static inline int do_rename(const char *
if (newnd.last.name[newnd.last.len])
goto exit4;
}
- new_dentry = lookup_hash(&newnd.last, new_dir);
-+ it.it_op = IT_RENAME2;
-+ new_dentry = lookup_hash_it(&newnd.last, new_dir, &it);
++ new_dentry = lookup_hash_it(&newnd.last, new_dir, NULL);
error = PTR_ERR(new_dentry);
if (IS_ERR(new_dentry))
goto exit4;
lock_kernel();
error = vfs_rename(old_dir->d_inode, old_dentry,
- new_dir->d_inode, new_dentry);
-+ new_dir->d_inode, new_dentry, &it);
++ new_dir->d_inode, new_dentry, NULL);
unlock_kernel();
-+ intent_release(new_dentry, &it);
dput(new_dentry);
- exit4:
-+ intent_release(old_dentry, &it);
- dput(old_dentry);
- exit3:
- double_up(&new_dir->d_inode->i_sem, &old_dir->d_inode->i_sem);
-@@ -1940,7 +2067,8 @@ out:
+@@ -1940,7 +2125,8 @@ out:
}
static inline int
-__vfs_follow_link(struct nameidata *nd, const char *link)
-+__vfs_follow_link(struct nameidata *nd, const char *link,
-+ struct lookup_intent *it)
++__vfs_follow_link(struct nameidata *nd, const char *link,
++ struct lookup_intent *it)
{
int res = 0;
char *name;
-@@ -1953,7 +2081,7 @@ __vfs_follow_link(struct nameidata *nd,
+@@ -1953,7 +2139,7 @@ __vfs_follow_link(struct nameidata *nd,
/* weird __emul_prefix() stuff did it */
goto out;
}
out:
if (current->link_count || res || nd->last_type!=LAST_NORM)
return res;
-@@ -1975,7 +2103,13 @@ fail:
+@@ -1975,7 +2161,13 @@ fail:
int vfs_follow_link(struct nameidata *nd, const char *link)
{
+ return __vfs_follow_link(nd, link, NULL);
+}
+
-+int vfs_follow_link_it(struct nameidata *nd, const char *link,
-+ struct lookup_intent *it)
++int vfs_follow_link_it(struct nameidata *nd, const char *link,
++ struct lookup_intent *it)
+{
+ return __vfs_follow_link(nd, link, it);
}
/* get the link contents into pagecache */
-@@ -2017,7 +2151,7 @@ int page_follow_link(struct dentry *dent
+@@ -2017,7 +2209,7 @@ int page_follow_link(struct dentry *dent
{
struct page *page = NULL;
char *s = page_getlink(dentry, &page);
if (page) {
kunmap(page);
page_cache_release(page);
---- linux-2.4.18-18.8.0-l4/fs/nfsd/vfs.c~vfs_intent-2.4.18-18 Sat Dec 14 06:31:22 2002
-+++ linux-2.4.18-18.8.0-l4-root/fs/nfsd/vfs.c Sat Dec 14 06:31:22 2002
+--- linux-2.4.18-49chaos-lustre9/fs/nfsd/vfs.c~vfs_intent-2.4.18-18 Wed Jan 29 12:43:32 2003
++++ linux-2.4.18-49chaos-lustre9-root/fs/nfsd/vfs.c Wed Jan 29 12:43:32 2003
@@ -1298,7 +1298,7 @@ nfsd_rename(struct svc_rqst *rqstp, stru
err = nfserr_perm;
} else
unlock_kernel();
if (!err && EX_ISSYNC(tfhp->fh_export)) {
nfsd_sync_dir(tdentry);
---- linux-2.4.18-18.8.0-l4/fs/open.c~vfs_intent-2.4.18-18 Sat Dec 14 06:31:22 2002
-+++ linux-2.4.18-18.8.0-l4-root/fs/open.c Sat Dec 14 06:31:22 2002
+--- linux-2.4.18-49chaos-lustre9/fs/open.c~vfs_intent-2.4.18-18 Wed Jan 29 12:43:32 2003
++++ linux-2.4.18-49chaos-lustre9-root/fs/open.c Wed Jan 29 12:43:32 2003
@@ -19,6 +19,9 @@
#include <asm/uaccess.h>
struct nameidata nd;
struct inode * inode;
int error;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
++ struct lookup_intent it = { .it_op = IT_TRUNC };
error = -EINVAL;
if (length < 0) /* sorry, but loff_t says... */
/*
* Find an empty file descriptor entry, and mark it busy.
*/
---- linux-2.4.18-18.8.0-l4/fs/stat.c~vfs_intent-2.4.18-18 Sat Dec 14 06:31:22 2002
-+++ linux-2.4.18-18.8.0-l4-root/fs/stat.c Sat Dec 14 06:31:22 2002
+--- linux-2.4.18-49chaos-lustre9/fs/stat.c~vfs_intent-2.4.18-18 Wed Jan 29 12:43:32 2003
++++ linux-2.4.18-49chaos-lustre9-root/fs/stat.c Wed Jan 29 12:43:32 2003
@@ -13,6 +13,7 @@
#include <asm/uaccess.h>
path_release(&nd);
}
return error;
---- linux-2.4.18-18.8.0-l4/include/linux/dcache.h~vfs_intent-2.4.18-18 Sat Dec 14 06:31:22 2002
-+++ linux-2.4.18-18.8.0-l4-root/include/linux/dcache.h Sat Dec 14 06:31:22 2002
-@@ -6,6 +6,34 @@
+--- linux-2.4.18-49chaos-lustre9/include/linux/dcache.h~vfs_intent-2.4.18-18 Wed Jan 29 12:43:32 2003
++++ linux-2.4.18-49chaos-lustre9-root/include/linux/dcache.h Wed Jan 29 12:43:32 2003
+@@ -6,6 +6,27 @@
#include <asm/atomic.h>
#include <linux/mount.h>
-+#define IT_OPEN (1)
-+#define IT_CREAT (1<<1)
-+#define IT_MKDIR (1<<2)
-+#define IT_LINK (1<<3)
-+#define IT_LINK2 (1<<4)
-+#define IT_SYMLINK (1<<5)
-+#define IT_UNLINK (1<<6)
-+#define IT_RMDIR (1<<7)
-+#define IT_RENAME (1<<8)
-+#define IT_RENAME2 (1<<9)
-+#define IT_READDIR (1<<10)
-+#define IT_GETATTR (1<<11)
-+#define IT_SETATTR (1<<12)
-+#define IT_READLINK (1<<13)
-+#define IT_MKNOD (1<<14)
-+#define IT_LOOKUP (1<<15)
++#define IT_OPEN (1)
++#define IT_CREAT (1<<1)
++#define IT_READDIR (1<<2)
++#define IT_GETATTR (1<<3)
++#define IT_SETATTR (1<<4)
++#define IT_TRUNC (1<<5)
++#define IT_READLINK (1<<6)
++#define IT_LOOKUP (1<<7)
+
+struct lookup_intent {
+ int it_op;
+ int it_mode;
++ int it_flags;
+ int it_disposition;
+ int it_status;
+ struct iattr *it_iattr;
/*
* linux/include/linux/dcache.h
*
-@@ -78,6 +106,7 @@ struct dentry {
+@@ -78,6 +99,7 @@ struct dentry {
unsigned long d_time; /* used by d_revalidate */
struct dentry_operations *d_op;
struct super_block * d_sb; /* The root of the dentry tree */
unsigned long d_vfs_flags;
void * d_fsdata; /* fs-specific data */
void * d_extra_attributes; /* TUX-specific data */
-@@ -91,6 +120,8 @@ struct dentry_operations {
+@@ -91,6 +113,8 @@ struct dentry_operations {
int (*d_delete)(struct dentry *);
void (*d_release)(struct dentry *);
void (*d_iput)(struct dentry *, struct inode *);
};
/* the dentry parameter passed to d_hash and d_compare is the parent
---- linux-2.4.18-18.8.0-l4/include/linux/fs.h~vfs_intent-2.4.18-18 Sat Dec 14 06:31:22 2002
-+++ linux-2.4.18-18.8.0-l4-root/include/linux/fs.h Sat Dec 14 06:33:11 2002
+@@ -124,6 +148,7 @@ d_iput: no no yes
+ * s_nfsd_free_path semaphore will be down
+ */
+ #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */
++#define DCACHE_LUSTRE_INVALID 0x0010 /* Lustre invalidated */
+
+ extern spinlock_t dcache_lock;
+
+--- linux-2.4.18-49chaos-lustre9/include/linux/fs.h~vfs_intent-2.4.18-18 Wed Jan 29 12:43:32 2003
++++ linux-2.4.18-49chaos-lustre9-root/include/linux/fs.h Wed Jan 29 12:43:32 2003
@@ -576,6 +576,7 @@ struct file {
/* needed for tty driver, and maybe others */
/*
* File types
-@@ -897,6 +900,7 @@ struct file_operations {
+@@ -897,16 +900,28 @@ struct file_operations {
struct inode_operations {
int (*create) (struct inode *,struct dentry *,int);
struct dentry * (*lookup) (struct inode *,struct dentry *);
+ struct dentry * (*lookup2) (struct inode *,struct dentry *, struct lookup_intent *);
int (*link) (struct dentry *,struct inode *,struct dentry *);
++ int (*link2) (struct inode *,struct inode *, const char *, int);
int (*unlink) (struct inode *,struct dentry *);
++ int (*unlink2) (struct inode *, const char *, int);
int (*symlink) (struct inode *,struct dentry *,const char *);
-@@ -907,6 +911,8 @@ struct inode_operations {
++ int (*symlink2) (struct inode *, const char *, int, const char *);
+ int (*mkdir) (struct inode *,struct dentry *,int);
++ int (*mkdir2) (struct inode *, const char *, int,int);
+ int (*rmdir) (struct inode *,struct dentry *);
++ int (*rmdir2) (struct inode *, const char *, int);
+ int (*mknod) (struct inode *,struct dentry *,int,int);
++ int (*mknod2) (struct inode *, const char *, int,int,int);
+ int (*rename) (struct inode *, struct dentry *,
struct inode *, struct dentry *);
++ int (*rename2) (struct inode *, struct inode *,
++ const char *oldname, int oldlen,
++ const char *newname, int newlen);
int (*readlink) (struct dentry *, char *,int);
int (*follow_link) (struct dentry *, struct nameidata *);
-+ int (*follow_link2) (struct dentry *, struct nameidata *,
-+ struct lookup_intent *it);
++ int (*follow_link2) (struct dentry *, struct nameidata *,
++ struct lookup_intent *it);
void (*truncate) (struct inode *);
int (*permission) (struct inode *, int);
int (*revalidate) (struct dentry *);
-@@ -1381,6 +1387,7 @@ typedef int (*read_actor_t)(read_descrip
+@@ -1383,6 +1398,7 @@ typedef int (*read_actor_t)(read_descrip
extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *));
extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *));
extern int FASTCALL(path_walk(const char *, struct nameidata *));
extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
-@@ -1392,6 +1399,8 @@ extern struct dentry * lookup_one_len(co
+@@ -1394,6 +1410,8 @@ extern struct dentry * lookup_one_len(co
extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
#define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
#define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
extern void inode_init_once(struct inode *);
extern void iput(struct inode *);
-@@ -1492,6 +1501,8 @@ extern struct file_operations generic_ro
+@@ -1494,6 +1512,8 @@ extern struct file_operations generic_ro
extern int vfs_readlink(struct dentry *, char *, int, const char *);
extern int vfs_follow_link(struct nameidata *, const char *);
-+extern int vfs_follow_link_it(struct nameidata *, const char *,
-+ struct lookup_intent *it);
++extern int vfs_follow_link_it(struct nameidata *, const char *,
++ struct lookup_intent *it);
extern int page_readlink(struct dentry *, char *, int);
extern int page_follow_link(struct dentry *, struct nameidata *);
extern struct inode_operations page_symlink_inode_operations;
---- linux-2.4.18-18.8.0-l4/kernel/ksyms.c~vfs_intent-2.4.18-18 Sat Dec 14 06:31:22 2002
-+++ linux-2.4.18-18.8.0-l4-root/kernel/ksyms.c Sat Dec 14 06:31:22 2002
-@@ -293,6 +293,7 @@ EXPORT_SYMBOL(read_cache_page);
+--- linux-2.4.18-49chaos-lustre9/kernel/ksyms.c~vfs_intent-2.4.18-18 Wed Jan 29 12:43:32 2003
++++ linux-2.4.18-49chaos-lustre9-root/kernel/ksyms.c Wed Jan 29 12:43:32 2003
+@@ -294,6 +294,7 @@ EXPORT_SYMBOL(read_cache_page);
EXPORT_SYMBOL(set_page_dirty);
EXPORT_SYMBOL(vfs_readlink);
EXPORT_SYMBOL(vfs_follow_link);
+ fs/dcache.c | 8 +
+ fs/namei.c | 287 ++++++++++++++++++++++++++++++++++++++++---------
+ fs/nfsd/vfs.c | 2
+ fs/open.c | 53 +++++++--
+ fs/stat.c | 9 +
+ include/linux/dcache.h | 25 ++++
+ include/linux/fs.h | 22 +++
+ kernel/ksyms.c | 1
+ 8 files changed, 344 insertions(+), 63 deletions(-)
-
-
- 0 files changed
-
---- linux-2.4.18-17.8.0/fs/dcache.c~vfs_intent 2002-12-06 14:52:31.000000000 -0800
-+++ linux-2.4.18-17.8.0-zab/fs/dcache.c 2002-12-06 14:52:31.000000000 -0800
-@@ -150,6 +150,8 @@ repeat:
- unhash_it:
- list_del_init(&dentry->d_hash);
-
+--- linux-2.4.18-18.8.0-l7/fs/dcache.c~vfs_intent-2.4.18-18 Mon Jan 20 08:28:00 2003
++++ linux-2.4.18-18.8.0-l7-root/fs/dcache.c Mon Jan 20 08:54:54 2003
+@@ -186,6 +188,13 @@ int d_invalidate(struct dentry * dentry)
+ spin_unlock(&dcache_lock);
+ &nbs