for inode poisoning during failed recovery.
- Chain superblocks off the associated connections, because they were the only
things we weren't yet keeping in a list or three. (Also, so we can find the
right superblocks to poison during recovery.)
- Split l_net.c into client.c and target.c to avoid OST/MDS dependencies on
llite, and soothe my soul.
- Build client.c and target.c as sources from other directories as needed,
instead of symlinking them. (Someone could do this with the rest of the
symlinked stuff, or I'll get to it later.)
char *lli_symlink_name;
struct lustre_handle lli_intent_lock_handle;
struct semaphore lli_open_sem;
+ __u32 lli_mount_epoch;
};
#define LL_SUPER_MAGIC 0x0BD00BD0
time_t ll_commitcbd_waketime;
time_t ll_commitcbd_timeout;
spinlock_t ll_commitcbd_lock;
+ struct list_head ll_conn_chain; /* per-conn chain of SBs */
+ __u32 ll_mount_epoch;
};
+#define CHECK_MOUNT_EPOCH(i) \
+do { \
+ if (ll_i2info(i)->lli_mount_epoch != ll_i2sbi(i)->ll_mount_epoch) \
+ RETURN(-EIO); \
+} while(0)
static inline struct ll_sb_info *ll_s2sbi(struct super_block *sb)
{
struct list_head c_imports;
struct list_head c_exports;
+ struct list_head c_sb_chain;
};
struct ptlrpc_client {
modulefs_DATA = ldlm.o
EXTRA_PROGRAMS = ldlm
-l_net.c:
- test -e l_net.c || ln -sf $(top_srcdir)/lib/l_net.c
-
-LINX=l_net.c
-
ldlm_SOURCES = l_lock.c ldlm_lock.c ldlm_resource.c ldlm_test.c ldlm_lockd.c \
-ldlm_extent.c ldlm_request.c l_net.c
+ldlm_extent.c ldlm_request.c
include $(top_srcdir)/Rules
* Copyright (C) 2001, 2002 Cluster File Systems, Inc.
* Author: Peter J. Braam <braam@clusterfs.com>
* Author: Phil Schwan <phil@clusterfs.com>
+ * Author: Mike Shaver <shaver@clusterfs.com>
*
* This file is part of Lustre, http://www.lustre.org.
*
* along with Lustre; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Storage Target Handling functions
- * Lustre Object Server Module (OST)
- *
- * This server is single threaded at present (but can easily be multi
- * threaded). For testing and management it is treated as an
- * obd_device, although it does not export a full OBD method table
- * (the requests are coming in over the wire, so object target
- * modules do not have a full method table.)
+ * Client-common OBD method implementations and utility functions.
*/
#define EXPORT_SYMTAB
-#define DEBUG_SUBSYSTEM S_OST
+#define DEBUG_SUBSYSTEM S_OST /* XXX WRONG */
#include <linux/module.h>
#include <linux/obd_ost.h>
cli->cl_import.imp_handle.addr = request->rq_repmsg->addr;
cli->cl_import.imp_handle.cookie = request->rq_repmsg->cookie;
-
recovd_conn_manage(c, ptlrpc_recovd, ll_recover);
EXIT;
up(&cli->cl_sem);
RETURN(rc);
}
-
-int target_handle_connect(struct ptlrpc_request *req)
-{
- struct obd_device *target;
- struct obd_export *export;
- struct obd_import *dlmimp;
- struct lustre_handle conn;
- char *tgtuuid, *cluuid;
- int rc, i;
- ENTRY;
-
- tgtuuid = lustre_msg_buf(req->rq_reqmsg, 0);
- if (req->rq_reqmsg->buflens[0] > 37) {
- CERROR("bad target UUID for connect\n");
- GOTO(out, rc = -EINVAL);
- }
-
- cluuid = lustre_msg_buf(req->rq_reqmsg, 1);
- if (req->rq_reqmsg->buflens[1] > 37) {
- CERROR("bad client UUID for connect\n");
- GOTO(out, rc = -EINVAL);
- }
-
- i = class_uuid2dev(tgtuuid);
- if (i == -1) {
- CERROR("UUID '%s' not found for connect\n", tgtuuid);
- GOTO(out, rc = -ENODEV);
- }
-
- target = &obd_dev[i];
- if (!target)
- GOTO(out, rc = -ENODEV);
-
- conn.addr = req->rq_reqmsg->addr;
- conn.cookie = req->rq_reqmsg->cookie;
-
- rc = obd_connect(&conn, target, cluuid);
- if (rc)
- GOTO(out, rc);
-
- rc = lustre_pack_msg(0, NULL, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc)
- GOTO(out, rc);
- req->rq_repmsg->addr = conn.addr;
- req->rq_repmsg->cookie = conn.cookie;
-
- export = class_conn2export(&conn);
- LASSERT(export);
-
- req->rq_export = export;
- export->exp_connection = ptlrpc_get_connection(&req->rq_peer, cluuid);
- if (req->rq_connection != NULL)
- ptlrpc_put_connection(req->rq_connection);
- req->rq_connection = ptlrpc_connection_addref(export->exp_connection);
-
- spin_lock(&export->exp_connection->c_lock);
- list_add(&export->exp_conn_chain, &export->exp_connection->c_exports);
- spin_unlock(&export->exp_connection->c_lock);
-
- recovd_conn_manage(export->exp_connection, ptlrpc_recovd,
- target_revoke_connection);
- dlmimp = &export->exp_ldlm_data.led_import;
- dlmimp->imp_connection = req->rq_connection;
- dlmimp->imp_client = &export->exp_obd->obd_ldlm_client;
- dlmimp->imp_handle.addr = req->rq_reqmsg->addr;
- dlmimp->imp_handle.cookie = req->rq_reqmsg->cookie;
- dlmimp->imp_obd = /* LDLM! */ NULL;
-
-#warning Peter: is this the right place to upgrade the server connection level?
- req->rq_connection->c_level = LUSTRE_CONN_FULL;
-out:
- req->rq_status = rc;
- RETURN(rc);
-}
-
-int target_handle_disconnect(struct ptlrpc_request *req)
-{
- struct lustre_handle *conn = (struct lustre_handle *)req->rq_reqmsg;
- int rc;
- ENTRY;
-
- rc = lustre_pack_msg(0, NULL, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc)
- RETURN(rc);
-
- req->rq_status = obd_disconnect(conn);
-
- RETURN(0);
-}
-
-static int target_disconnect_client(struct ptlrpc_connection *conn)
-{
- struct list_head *expiter, *n;
- struct lustre_handle hdl;
- struct obd_export *exp;
- int rc;
- ENTRY;
-
- list_for_each_safe(expiter, n, &conn->c_exports) {
- exp = list_entry(expiter, struct obd_export, exp_conn_chain);
-
- hdl.addr = (__u64)(unsigned long)exp;
- hdl.cookie = exp->exp_cookie;
- rc = obd_disconnect(&hdl);
- if (rc)
- CERROR("disconnecting export %p failed: %d\n", exp, rc);
- }
- RETURN(0);
-}
-
-static int target_fence_failed_connection(struct ptlrpc_connection *conn)
-{
- ENTRY;
-
- conn->c_level = LUSTRE_CONN_RECOVD;
- conn->c_recovd_data.rd_phase = RD_PREPARED;
-
- RETURN(0);
-}
-
-int target_revoke_connection(struct recovd_data *rd, int phase)
-{
- struct ptlrpc_connection *conn = class_rd2conn(rd);
-
- LASSERT(conn);
- ENTRY;
-
- switch (phase) {
- case PTLRPC_RECOVD_PHASE_PREPARE:
- RETURN(target_fence_failed_connection(conn));
- case PTLRPC_RECOVD_PHASE_RECOVER:
- RETURN(target_disconnect_client(conn));
- case PTLRPC_RECOVD_PHASE_FAILURE:
- LBUG();
- RETURN(0);
- }
-
- LBUG();
- RETURN(-ENOSYS);
-}
--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
+ * Author: Peter J. Braam <braam@clusterfs.com>
+ * Author: Phil Schwan <phil@clusterfs.com>
+ * Author: Mike Shaver <shaver@clusterfs.com>
+ *
+ * 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.
+ *
+ * Target-common OBD method implementations and utility functions.
+ */
+
+#define EXPORT_SYMTAB
+#define DEBUG_SUBSYSTEM S_OST /* XXX WRONG */
+
+#include <linux/module.h>
+#include <linux/obd_ost.h>
+#include <linux/lustre_net.h>
+#include <linux/lustre_dlm.h>
+
+int target_handle_connect(struct ptlrpc_request *req)
+{
+ struct obd_device *target;
+ struct obd_export *export;
+ struct obd_import *dlmimp;
+ struct lustre_handle conn;
+ char *tgtuuid, *cluuid;
+ int rc, i;
+ ENTRY;
+
+ tgtuuid = lustre_msg_buf(req->rq_reqmsg, 0);
+ if (req->rq_reqmsg->buflens[0] > 37) {
+ CERROR("bad target UUID for connect\n");
+ GOTO(out, rc = -EINVAL);
+ }
+
+ cluuid = lustre_msg_buf(req->rq_reqmsg, 1);
+ if (req->rq_reqmsg->buflens[1] > 37) {
+ CERROR("bad client UUID for connect\n");
+ GOTO(out, rc = -EINVAL);
+ }
+
+ i = class_uuid2dev(tgtuuid);
+ if (i == -1) {
+ CERROR("UUID '%s' not found for connect\n", tgtuuid);
+ GOTO(out, rc = -ENODEV);
+ }
+
+ target = &obd_dev[i];
+ if (!target)
+ GOTO(out, rc = -ENODEV);
+
+ conn.addr = req->rq_reqmsg->addr;
+ conn.cookie = req->rq_reqmsg->cookie;
+
+ rc = obd_connect(&conn, target, cluuid);
+ if (rc)
+ GOTO(out, rc);
+
+ rc = lustre_pack_msg(0, NULL, NULL, &req->rq_replen, &req->rq_repmsg);
+ if (rc)
+ GOTO(out, rc);
+ req->rq_repmsg->addr = conn.addr;
+ req->rq_repmsg->cookie = conn.cookie;
+
+ export = class_conn2export(&conn);
+ LASSERT(export);
+
+ req->rq_export = export;
+ export->exp_connection = ptlrpc_get_connection(&req->rq_peer, cluuid);
+ if (req->rq_connection != NULL)
+ ptlrpc_put_connection(req->rq_connection);
+ req->rq_connection = ptlrpc_connection_addref(export->exp_connection);
+
+ spin_lock(&export->exp_connection->c_lock);
+ list_add(&export->exp_conn_chain, &export->exp_connection->c_exports);
+ spin_unlock(&export->exp_connection->c_lock);
+
+ recovd_conn_manage(export->exp_connection, ptlrpc_recovd,
+ target_revoke_connection);
+ dlmimp = &export->exp_ldlm_data.led_import;
+ dlmimp->imp_connection = req->rq_connection;
+ dlmimp->imp_client = &export->exp_obd->obd_ldlm_client;
+ dlmimp->imp_handle.addr = req->rq_reqmsg->addr;
+ dlmimp->imp_handle.cookie = req->rq_reqmsg->cookie;
+ dlmimp->imp_obd = /* LDLM! */ NULL;
+
+#warning Peter: is this the right place to upgrade the server connection level?
+ req->rq_connection->c_level = LUSTRE_CONN_FULL;
+out:
+ req->rq_status = rc;
+ RETURN(rc);
+}
+
+int target_handle_disconnect(struct ptlrpc_request *req)
+{
+ struct lustre_handle *conn = (struct lustre_handle *)req->rq_reqmsg;
+ int rc;
+ ENTRY;
+
+ rc = lustre_pack_msg(0, NULL, NULL, &req->rq_replen, &req->rq_repmsg);
+ if (rc)
+ RETURN(rc);
+
+ req->rq_status = obd_disconnect(conn);
+
+ RETURN(0);
+}
+
+static int target_disconnect_client(struct ptlrpc_connection *conn)
+{
+ struct list_head *expiter, *n;
+ struct lustre_handle hdl;
+ struct obd_export *exp;
+ int rc;
+ ENTRY;
+
+ list_for_each_safe(expiter, n, &conn->c_exports) {
+ exp = list_entry(expiter, struct obd_export, exp_conn_chain);
+
+ hdl.addr = (__u64)(unsigned long)exp;
+ hdl.cookie = exp->exp_cookie;
+ rc = obd_disconnect(&hdl);
+ if (rc)
+ CERROR("disconnecting export %p failed: %d\n", exp, rc);
+ }
+ RETURN(0);
+}
+
+static int target_fence_failed_connection(struct ptlrpc_connection *conn)
+{
+ ENTRY;
+
+ conn->c_level = LUSTRE_CONN_RECOVD;
+ conn->c_recovd_data.rd_phase = RD_PREPARED;
+
+ RETURN(0);
+}
+
+int target_revoke_connection(struct recovd_data *rd, int phase)
+{
+ struct ptlrpc_connection *conn = class_rd2conn(rd);
+
+ LASSERT(conn);
+ ENTRY;
+
+ switch (phase) {
+ case PTLRPC_RECOVD_PHASE_PREPARE:
+ RETURN(target_fence_failed_connection(conn));
+ case PTLRPC_RECOVD_PHASE_RECOVER:
+ RETURN(target_disconnect_client(conn));
+ case PTLRPC_RECOVD_PHASE_FAILURE:
+ LBUG();
+ RETURN(0);
+ }
+
+ LBUG();
+ RETURN(-ENOSYS);
+}
if (file->private_data)
LBUG();
+ CHECK_MOUNT_EPOCH(inode);
+
lsm = lli->lli_smd;
/* delayed create of object (intent created inode) */
struct ll_inode_info *lli = ll_i2info(inode);
ENTRY;
+
+ CHECK_MOUNT_EPOCH(inode);
fd = (struct ll_file_data *)file->private_data;
if (!fd || !fd->fd_mdshandle) {
long long retval;
ENTRY;
+ CHECK_MOUNT_EPOCH(inode);
+
switch (origin) {
case 2: {
struct ll_inode_info *lli = ll_i2info(inode);
ENTRY;
+ CHECK_MOUNT_EPOCH(dir);
+
if (it == NULL) {
it = &lookup_it;
dentry->d_it = it;
struct ll_inode_info *lli = NULL;
ENTRY;
+ CHECK_MOUNT_EPOCH(dir);
+
if (dentry->d_it->it_disposition == 0) {
memset(&oa, 0, sizeof(oa));
oa.o_mode = S_IFREG | 0600;
int err = 0;
ENTRY;
+ CHECK_MOUNT_EPOCH(dir);
+
inode = ll_create_node(dir, dentry->d_name.name, dentry->d_name.len,
symname, l, S_IFLNK | S_IRWXUGO, 0,
dentry->d_it, NULL);
int err;
ENTRY;
+ CHECK_MOUNT_EPOCH(inode);
+
if (!cbd)
RETURN(-ENOMEM);
struct io_cb_data *cbd = ll_init_cb();
ENTRY;
+ CHECK_MOUNT_EPOCH(inode);
+
pg.pg = page;
pg.count = to;
pg.off = (((obd_off)page->index) << PAGE_SHIFT);
int i, rc = 0;
struct io_cb_data *cbd;
+ CHECK_MOUNT_EPOCH(inode);
+
ENTRY;
if (!lsm || !lsm->lsm_object_id)
RETURN(-ENOMEM);
#include <linux/obd_lov.h>
#include <linux/lustre_dlm.h>
#include <linux/init.h>
+#include <linux/fs.h>
kmem_cache_t *ll_file_data_slab;
extern struct address_space_operations ll_aops;
__u64 last_committed;
__u64 last_xid;
struct ptlrpc_request *request = NULL;
+ struct ptlrpc_connection *mdc_conn;
struct ll_read_inode2_cookie lic;
class_uuid_t uuid;
RETURN(NULL);
}
+ INIT_LIST_HEAD(&sbi->ll_conn_chain);
+ sbi->ll_mount_epoch = 0;
generate_random_uuid(uuid);
class_uuid_unparse(uuid, sbi->ll_sb_uuid);
}
#warning Peter: is this the right place to raise the connection level?
- sbi2mdc(sbi)->cl_import.imp_connection->c_level = LUSTRE_CONN_FULL;
+ mdc_conn = sbi2mdc(sbi)->cl_import.imp_connection;
+ mdc_conn->c_level = LUSTRE_CONN_FULL;
+ list_add(&mdc_conn->c_sb_chain, &sbi->ll_conn_chain);
obd = class_uuid2obd(osc);
if (!obd) {
static void ll_put_super(struct super_block *sb)
{
struct ll_sb_info *sbi = ll_s2sbi(sb);
+
ENTRY;
+ list_del(&sbi->ll_conn_chain);
ll_commitcbd_cleanup(sbi);
obd_disconnect(&sbi->ll_osc_conn);
obd_disconnect(&sbi->ll_mdc_conn);
static void ll_clear_inode(struct inode *inode)
{
+ /* XXX EPOCH */
+
if (atomic_read(&inode->i_count) == 0) {
struct ll_inode_info *lli = ll_i2info(inode);
struct lov_stripe_md *lsm = lli->lli_smd;
struct mds_body *body = lic->lic_body;
struct ll_inode_info *lli = ll_i2info(inode);
ENTRY;
-
+
sema_init(&lli->lli_open_sem, 1);
-
+ lli->lli_mount_epoch = ll_i2sbi(inode)->ll_mount_epoch;
+
/* core attributes first */
ll_update_inode(inode, body);
static int __init init_lustre_lite(void)
{
- printk(KERN_INFO "Lustre Lite 0.0.1, info@clusterfs.com\n");
+ printk(KERN_INFO "Lustre Lite 0.5.14, info@clusterfs.com\n");
ll_file_data_slab = kmem_cache_create("ll_file_data",
sizeof(struct ll_file_data), 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
+ SLAB_HWCACHE_ALIGN, NULL, NULL);
if (ll_file_data_slab == NULL)
return -ENOMEM;
return register_filesystem(&lustre_lite_fs_type);
*request = NULL;
+ CHECK_MOUNT_EPOCH(inode);
+
if (lli->lli_symlink_name) {
*symname = lli->lli_symlink_name;
CDEBUG(D_INODE, "using cached symlink %s\n", *symname);
int rc;
ENTRY;
+ CHECK_MOUNT_EPOCH(inode);
+
/* on symlinks lli_open_sem protects lli_symlink_name allocation/data */
down(&lli->lli_open_sem);
rc = ll_readlink_internal(inode, &request, &symname);
int rc;
ENTRY;
+ CHECK_MOUNT_EPOCH(inode);
+
down(&lli->lli_open_sem);
rc = ll_readlink_internal(inode, &request, &symname);
if (rc)
modulefs_DATA = mdc.o
EXTRA_PROGRAMS = mdc
-LINX=l_net.c mds_updates.c ll_pack.c lov_pack.c
-mdc_SOURCES = mdc_request.c mdc_reint.c $(LINX)
+LINX= mds_updates.c ll_pack.c lov_pack.c
+mdc_SOURCES = mdc_request.c mdc_reint.c ../lib/client.c $(LINX)
+
lov_pack.c:
test -e lov_pack.c || ln -sf $(top_srcdir)/lib/lov_pack.c .
ll_pack.c:
test -e ll_pack.c || ln -sf $(top_srcdir)/lib/ll_pack.c .
-l_net.c:
- test -e l_net.c || ln -sf $(top_srcdir)/lib/l_net.c .
-
mds_updates.c:
test -e mds_updates.c || ln -sf $(top_srcdir)/lib/mds_updates.c .
modulefs_DATA = mds.o mds_extN.o # mds_ext2.o mds_ext3.o
EXTRA_PROGRAMS = mds mds_extN # mds_ext2 mds_ext3
-LINX= mds_updates.c simple.c ll_pack.c l_net.c lov_pack.c
+LINX= mds_updates.c simple.c ll_pack.c lov_pack.c
ll_pack.c:
test -e ll_pack.c || ln -sf $(top_srcdir)/lib/ll_pack.c
test -e mds_updates.c || ln -sf $(top_srcdir)/lib/mds_updates.c
simple.c:
test -e simple.c || ln -sf $(top_srcdir)/lib/simple.c
-l_net.c:
- test -e l_net.c || ln -sf $(top_srcdir)/lib/l_net.c
lov_pack.c:
test -e lov_pack.c || ln -sf $(top_srcdir)/lib/lov_pack.c
-mds_SOURCES = mds_lov.c handler.c mds_reint.c mds_fs.c $(LINX)
-
+mds_SOURCES = mds_lov.c handler.c mds_reint.c mds_fs.c $(LINX) ../lib/target.c
include $(top_srcdir)/Rules
ENTRY;
+ CHECK_MOUNT_EPOCH(inode);
+ CHECK_MOUNT_EPOCH(inode2);
+
err = obd_brw(rw == WRITE ? OBD_BRW_WRITE : OBD_BRW_READ, IID(inode),
md, 1, &page, &count, &offset,
&flags, NULL);
modulefs_DATA = osc.o
EXTRA_PROGRAMS = osc
-LINX= obd_pack.c ll_pack.c l_net.c
-osc_SOURCES = osc_request.c $(LINX)
+LINX= obd_pack.c ll_pack.c
+osc_SOURCES = osc_request.c ../lib/client.c $(LINX)
obd_pack.c:
test -e obd_pack.c || ln -sf $(top_srcdir)/lib/obd_pack.c
ll_pack.c:
test -e ll_pack.c || ln -sf $(top_srcdir)/lib/ll_pack.c
-l_net.c:
- test -e l_net.c || ln -sf $(top_srcdir)/lib/l_net.c .
-
dist-hook:
list='$(LINX)'; for f in $$list; do rm -f $(distdir)/$$f; done
modulefs_DATA = ost.o
EXTRA_PROGRAMS = ost
-LINX=obd_pack.c l_net.c ll_pack.c
+LINX=obd_pack.c ll_pack.c
ll_pack.c:
test -e ll_pack.c || ln -sf $(top_srcdir)/lib/ll_pack.c
obd_pack.c:
test -e obd_pack.c || ln -sf $(top_srcdir)/lib/obd_pack.c
-l_net.c:
- test -e l_net.c || ln -sf $(top_srcdir)/lib/l_net.c
-
-ost_SOURCES = $(LINX) ost_handler.c
+ost_SOURCES = $(LINX) ost_handler.c ../lib/target.c
dist-hook:
list='$(LINX)'; for f in $$list; do rm -f $(distdir)/$$f; done
INIT_LIST_HEAD(&c->c_dying_head);
INIT_LIST_HEAD(&c->c_imports);
INIT_LIST_HEAD(&c->c_exports);
+ INIT_LIST_HEAD(&c->c_sb_chain);
atomic_set(&c->c_refcount, 0);
ptlrpc_connection_addref(c);
spin_lock_init(&c->c_lock);