* Curtail some excessive include cycles.
* Create "phantom" exports from last_rcvd data, suitable for later (soon!)
hooking up in mds_connect.
* Add class_new_export utility function for use by class_connect and
mds_read_last_rcvd.
* Fix last_mount/last_rcvd recovery-eligibility test in mds_read_last_rcvd.
* Force common.sh's DEBUG_WAIT read to use /dev/tty, so it works from scripts
like runtests. (lconf, take me away!)
#else
+#include <linux/obd_support.h>
+
/* buffer MUST be at least the size of obd_ioctl_hdr */
static inline int obd_ioctl_getdata(char **buf, int *len, void *arg)
{
#include <linux/fs.h>
#include <linux/ext2_fs.h>
+#include <linux/obd_class.h>
#include <linux/lustre_net.h>
#include <linux/lustre_mds.h>
#include <linux/lustre_ha.h>
#ifdef __KERNEL__
-#include <linux/obd_class.h>
#include <linux/lustre_idl.h>
#include <linux/lustre_net.h>
-#include <linux/lustre_dlm.h>
-#include <linux/obd_lov.h> /* for lov_md */
+
+struct ldlm_lock_desc;
+struct lov_stripe_md;
#define LUSTRE_MDS_NAME "mds"
#define LUSTRE_MDC_NAME "mdc"
};
/* In-memory access to client data from MDS struct */
-struct mds_client_info {
- struct list_head mci_list;
- struct list_head mci_open_head;
- struct mds_client_data *mci_mcd;
- int mci_off;
+struct mds_export_data {
+ struct list_head med_open_head;
+ struct mds_client_data *med_mcd;
+ int med_off;
};
/* file data for open files on MDS */
/* mds/mds_reint.c */
int mds_reint_rec(struct mds_update_record *r, int offset,
struct ptlrpc_request *req);
-struct mds_client_info *mds_uuid_to_mci(struct mds_obd *mds, __u8 *uuid);
/* lib/mds_updates.c */
void mds_unpack_body(struct mds_body *b);
struct ptlrpc_request **);
int mdc_create_client(char *uuid, struct ptlrpc_client *cl);
-extern int mds_client_add(struct mds_obd *mds, struct mds_client_data *mcd,
+extern int mds_client_add(struct mds_obd *mds, struct mds_export_data *med,
int cl_off);
/* mds/mds_fs.c */
extern int mds_register_fs_type(struct mds_fs_operations *op, const char *name);
extern void mds_unregister_fs_type(const char *name);
-extern int mds_fs_setup(struct mds_obd *mds, struct vfsmount *mnt);
-extern void mds_fs_cleanup(struct mds_obd *mds);
+extern int mds_fs_setup(struct obd_device *obddev, struct vfsmount *mnt);
+extern void mds_fs_cleanup(struct obd_device *obddev);
static inline void *mds_fs_start(struct mds_obd *mds, struct inode *inode,
int op)
struct address_space_operations *fo_aops;
};
-struct mds_client_info;
struct mds_server_data;
struct client_obd {
__u64 mds_mount_count;
struct ll_fid mds_rootfid;
int mds_client_count;
- struct list_head mds_client_info;
struct mds_server_data *mds_server_data;
};
#include <linux/obd.h>
#include <linux/lustre_lib.h>
#include <linux/lustre_idl.h>
+#include <linux/lustre_mds.h>
#endif
struct list_head exp_chain;
struct obd_device *exp_obd;
struct ptlrpc_connection *exp_connection;
+ struct mds_export_data exp_mds_data;
+#if NOTYET && 0
+ struct ldlm_export_data exp_ldlm_data;
+ struct ost_export_data exp_ost_data;
+#endif
void *exp_data; /* device specific data */
int exp_desclen;
char *exp_desc;
int class_name2dev(char *name);
int class_uuid2dev(char *name);
struct obd_device *class_uuid2obd(char *name);
+struct obd_export *class_new_export(struct obd_device *obddev);
int class_connect (struct lustre_handle *conn, struct obd_device *obd);
int class_disconnect(struct lustre_handle *conn);
struct obd_export *class_conn2export(struct lustre_handle *);
#include <linux/obd_support.h>
#include <linux/lustre_lite.h>
+#include <linux/lustre_dlm.h>
extern struct address_space_operations ll_aops;
#include <linux/lustre_lite.h>
#include <linux/lustre_dlm.h>
#include <linux/init.h>
+#include <linux/obd_lov.h>
#define REQUEST_MINOR 244
{
int rc;
+#warning shaver: find existing export if there is one.
MOD_INC_USE_COUNT;
rc = class_connect(conn, obd);
{
struct mds_obd *mds = mds_req2mds(req);
struct mds_body *body;
- struct mds_client_info *mci;
struct mds_client_data *mcd;
+ struct mds_export_data *med = &req->rq_export->exp_mds_data;
int rc, size = sizeof(*body);
ENTRY;
body = lustre_msg_buf(req->rq_repmsg, 0);
memcpy(&body->fid1, &mds->mds_rootfid, sizeof(body->fid1));
- mci = mds_uuid_to_mci(mds, ptlrpc_req_to_uuid(req));
- if (!mci) {
- /* We don't have any old connection data for this client */
+ mcd = med->med_mcd;
+ if (!mcd) {
int rc;
-
- CDEBUG(D_INFO, "allocating new client data for UUID '%s'",
- ptlrpc_req_to_uuid(req));
-
+
+ CDEBUG(D_INFO, "allocating new client data for UUID '%s'\n",
+ ptlrpc_req_to_uuid(req));
OBD_ALLOC(mcd, sizeof(*mcd));
if (!mcd) {
CERROR("mds: out of memory for client data\n");
}
memcpy(mcd->mcd_uuid, ptlrpc_req_to_uuid(req),
sizeof(mcd->mcd_uuid));
- rc = mds_client_add(mds, mcd, -1);
+ rc = mds_client_add(mds, med, -1);
if (rc) {
req->rq_status = rc;
+ OBD_FREE(mcd, sizeof(*mcd));
RETURN(0);
}
+ med->med_mcd = mcd;
} else {
- /* We have old connection data for this client... */
- mcd = mci->mci_mcd;
CDEBUG(D_INFO, "found existing data for UUID '%s' at #%d\n",
- mcd->mcd_uuid, mci->mci_off);
+ mcd->mcd_uuid, med->med_off);
}
/* mcd_last_xid is is stored in little endian on the disk and
mds_pack_rep_body converts it to network order */
struct file *file;
struct vfsmount *mnt;
struct mds_obd *mds = mds_req2mds(req);
- struct mds_client_info *mci;
+ struct mds_export_data *med;
__u32 flags;
struct list_head *tmp;
struct mds_file_data *mfd;
RETURN(0);
}
- mci = mds_uuid_to_mci(mds, ptlrpc_req_to_uuid(req));
- if (!mci) {
- CERROR("mds: no mci!\n");
- req->rq_status = -ENOTCONN;
- RETURN(0);
- }
-
body = lustre_msg_buf(req->rq_reqmsg, 0);
/* was this animal open already? */
/* XXX we should only check on re-open, or do a refcount... */
- list_for_each(tmp, &mci->mci_open_head) {
+ med = &req->rq_export->exp_mds_data;
+ list_for_each(tmp, &med->med_open_head) {
struct mds_file_data *fd;
fd = list_entry(tmp, struct mds_file_data, mfd_list);
if (body->extra == fd->mfd_clientfd &&
file->private_data = mfd;
mfd->mfd_file = file;
mfd->mfd_clientfd = body->extra;
- list_add(&mfd->mfd_list, &mci->mci_open_head);
+ list_add(&mfd->mfd_list, &med->med_open_head);
body = lustre_msg_buf(req->rq_repmsg, 0);
body->extra = (__u64) (unsigned long)file;
GOTO(err_put, rc = -ENODEV);
mds->mds_max_mdsize = sizeof(struct lov_stripe_md);
- rc = mds_fs_setup(mds, mnt);
+ rc = mds_fs_setup(obddev, mnt);
if (rc) {
CERROR("MDS filesystem method init failed: rc = %d\n", rc);
GOTO(err_put, rc);
err_svc:
ptlrpc_unregister_service(mds->mds_service);
err_fs:
- mds_fs_cleanup(mds);
+ mds_fs_cleanup(obddev);
err_put:
unlock_kernel();
mntput(mds->mds_vfsmnt);
#ifdef CONFIG_DEV_RDONLY
dev_clear_rdonly(2);
#endif
- mds_fs_cleanup(mds);
+ mds_fs_cleanup(obddev);
MOD_DEC_USE_COUNT;
RETURN(0);
#include <linux/module.h>
#include <linux/kmod.h>
#include <linux/lustre_mds.h>
+#include <linux/obd_class.h>
+#include <linux/obd_support.h>
+#include <linux/lustre_lib.h>
LIST_HEAD(mds_fs_types);
char *mft_name;
};
-/* This will be a hash table at some point. */
-static int mds_init_client_data(struct mds_obd *mds)
-{
- INIT_LIST_HEAD(&mds->mds_client_info);
- return 0;
-}
-
#define MDS_MAX_CLIENTS 1024
#define MDS_MAX_CLIENT_WORDS (MDS_MAX_CLIENTS / sizeof(unsigned long))
static unsigned long last_rcvd_slots[MDS_MAX_CLIENT_WORDS];
-/* Add client data to the MDS. The in-memory storage will be a hash at some
- * point. We use a bitmap to locate a free space in the last_rcvd file if
- * cl_off is -1 (i.e. a new client). Otherwise, we have just read the data
- * from the last_rcvd file and we know its offset.
+/* Add client data to the MDS. We use a bitmap to locate a free space
+ * in the last_rcvd file if cl_off is -1 (i.e. a new client).
+ * Otherwise, we have just read the data from the last_rcvd file and
+ * we know its offset.
*/
-int mds_client_add(struct mds_obd *mds, struct mds_client_data *mcd, int cl_off)
+int mds_client_add(struct mds_obd *mds, struct mds_export_data *med, int cl_off)
{
- struct mds_client_info *mci;
-
- OBD_ALLOC(mci, sizeof(*mci));
- if (!mci) {
- CERROR("no memory for MDS client info\n");
- RETURN(-ENOMEM);
- }
- INIT_LIST_HEAD(&mci->mci_open_head);
-
CDEBUG(D_INFO, "client at offset %d with UUID '%s' added\n",
- cl_off, mcd->mcd_uuid);
+ cl_off, med->med_mcd->mcd_uuid);
if (cl_off == -1) {
unsigned long *word;
}
}
- mci->mci_mcd = mcd;
- mci->mci_off = cl_off;
-
- /* For now we just put the clients in a list, not a hashed list */
- list_add_tail(&mci->mci_list, &mds->mds_client_info);
-
+ med->med_off = cl_off;
mds->mds_client_count++;
return 0;
}
-void mds_client_del(struct mds_obd *mds, struct mds_client_info *mci)
+static int mds_client_free_all(struct obd_device *obddev)
{
- unsigned long *word;
- int bit;
-
- word = last_rcvd_slots + mci->mci_off / sizeof(unsigned long);
- bit = mci->mci_off % sizeof(unsigned long);
-
- if (!test_and_clear_bit(bit, word)) {
- CERROR("bit %d already clear in word %d - bad bad\n",
- bit, word - last_rcvd_slots);
- LBUG();
- }
+ struct mds_obd *mds = &obddev->u.mds;
+ struct list_head *p, *n;
- --mds->mds_client_count;
- list_del(&mci->mci_list);
- OBD_FREE(mci->mci_mcd, sizeof(*mci->mci_mcd));
- OBD_FREE(mci, sizeof (*mci));
-}
+ list_for_each_safe(p, n, &obddev->obd_exports) {
+ struct obd_export *exp;
+ struct mds_export_data *med;
+ unsigned long *word;
+ int bit;
-static int mds_client_free_all(struct mds_obd *mds)
-{
- struct list_head *p, *n;
+ exp = list_entry(p, struct obd_export, exp_chain);
+ med = &exp->exp_mds_data;
+
+ word = last_rcvd_slots + med->med_off / sizeof(unsigned long);
+ bit = med->med_off % sizeof(unsigned long);
- list_for_each_safe(p, n, &mds->mds_client_info) {
- struct mds_client_info *mci;
+ if (!test_and_clear_bit(bit, word)) {
+ CERROR("bit %d already clear in word %d - bad bad\n",
+ bit, word - last_rcvd_slots);
+ LBUG();
+ }
- mci = list_entry(p, struct mds_client_info, mci_list);
- mds_client_del(mds, mci);
+ OBD_FREE(med->med_mcd, sizeof(*med->med_mcd));
+ --mds->mds_client_count;
}
+ if (mds->mds_client_count) {
+ CERROR("%d mds clients remaining after cleanup\n",
+ mds->mds_client_count);
+ /* LBUG()? */
+ }
+
return 0;
}
#define LAST_RCVD "last_rcvd"
-static int mds_read_last_rcvd(struct mds_obd *mds, struct file *f)
+static int mds_read_last_rcvd(struct obd_device *obddev, struct file *f)
{
+ struct mds_obd *mds = &obddev->u.mds;
struct mds_server_data *msd;
struct mds_client_data *mcd = NULL;
loff_t fsize = f->f_dentry->d_inode->i_size;
if (rc == 0) {
CERROR("empty MDS %s, new MDS?\n", LAST_RCVD);
RETURN(0);
- } else if (rc != sizeof(*msd)) {
+ }
+
+ if (rc != sizeof(*msd)) {
CERROR("error reading MDS %s: rc = %d\n", LAST_RCVD, rc);
if (rc > 0) {
rc = -EIO;
}
last_rcvd = le64_to_cpu(mcd->mcd_last_rcvd);
- last_mount = le64_to_cpu(mcd->mcd_mount_count);
- if (last_rcvd &&
- last_mount - mcd->mcd_mount_count < MDS_MOUNT_RECOV) {
- rc = mds_client_add(mds, mcd, cl_off);
- if (rc) {
- rc = 0;
+ if (last_rcvd && (last_mount - le64_to_cpu(mcd->mcd_mount_count)
+ < MDS_MOUNT_RECOV)) {
+ struct obd_export *export = class_new_export(obddev);
+ if (!export) {
+ rc = -ENOMEM;
break;
}
+ export->exp_mds_data.med_mcd = mcd;
mcd = NULL;
} else {
CDEBUG(D_INFO,
CDEBUG(D_INODE, "got %Lu for highest last_rcvd value, %d clients\n",
(unsigned long long)mds->mds_last_rcvd, mds->mds_client_count);
+ if (mcd)
+ OBD_FREE(mcd, sizeof(*mcd));
+
/* After recovery, there can be no local uncommitted transactions */
mds->mds_last_committed = mds->mds_last_rcvd;
return rc;
}
-static int mds_fs_prep(struct mds_obd *mds)
+static int mds_fs_prep(struct obd_device *obddev)
{
+ struct mds_obd *mds = &obddev->u.mds;
struct obd_run_ctxt saved;
struct dentry *dentry;
struct file *f;
/* XXX probably want to hold on to this later... */
dput(dentry);
- rc = mds_init_client_data(mds);
- if (rc)
- GOTO(err_pop, rc);
-
f = filp_open(LAST_RCVD, O_RDWR | O_CREAT, 0644);
if (IS_ERR(f)) {
rc = PTR_ERR(f);
GOTO(err_filp, rc);
}
- rc = mds_read_last_rcvd(mds, f);
+ rc = mds_read_last_rcvd(obddev, f);
if (rc) {
CERROR("cannot read %s: rc = %d\n", LAST_RCVD, rc);
GOTO(err_client, rc);
RETURN(0);
err_client:
- mds_client_free_all(mds);
+ mds_client_free_all(obddev);
err_filp:
if (filp_close(f, 0))
CERROR("can't close %s after error\n", LAST_RCVD);
__MOD_DEC_USE_COUNT(fs_ops->fs_owner);
}
-int mds_fs_setup(struct mds_obd *mds, struct vfsmount *mnt)
+int mds_fs_setup(struct obd_device *obddev, struct vfsmount *mnt)
{
+ struct mds_obd *mds = &obddev->u.mds;
int rc;
mds->mds_fsops = mds_fs_get_ops(mds->mds_fstype);
mds->mds_sop->delete_inode = mds->mds_fsops->fs_delete_inode;
mds->mds_sb->s_op = mds->mds_sop;
- rc = mds_fs_prep(mds);
+ rc = mds_fs_prep(obddev);
if (rc)
GOTO(out_free, rc);
return rc;
}
-void mds_fs_cleanup(struct mds_obd *mds)
+void mds_fs_cleanup(struct obd_device *obddev)
{
- mds_client_free_all(mds);
+ struct mds_obd *mds = &obddev->u.mds;
+ mds_client_free_all(obddev);
mds_server_free_data(mds);
OBD_FREE(mds->mds_sop, sizeof(*mds->mds_sop));
#include <linux/lustre_mds.h>
#include <linux/lustre_idl.h>
#include <linux/obd_lov.h>
+#include <linux/obd_class.h>
+#include <linux/lustre_lib.h>
int mds_configure_lov(struct obd_device *obd, struct lov_desc *desc,
uuid_t *uuidarray)
extern inline struct mds_obd *mds_req2mds(struct ptlrpc_request *req);
-struct mds_client_info *mds_uuid_to_mci(struct mds_obd *mds, __u8 *uuid)
-{
- struct list_head *p;
-
- if (!uuid)
- return NULL;
-
- list_for_each(p, &mds->mds_client_info) {
- struct mds_client_info *mci;
-
- mci = list_entry(p, struct mds_client_info, mci_list);
- CDEBUG(D_INFO, "checking client UUID '%s'\n",
- mci->mci_mcd->mcd_uuid);
- if (!strncmp(mci->mci_mcd->mcd_uuid, uuid,
- sizeof(mci->mci_mcd->mcd_uuid)))
- return mci;
- }
- CDEBUG(D_INFO, "no mds client info found for UUID '%s'\n", uuid);
- return NULL;
-}
-
/* Assumes caller has already pushed us into the kernel context. */
int mds_update_last_rcvd(struct mds_obd *mds, void *handle,
struct ptlrpc_request *req)
{
- /* get from req->rq_connection-> or req->rq_client */
- struct mds_client_info *mci;
+ struct mds_export_data *med = &req->rq_export->exp_mds_data;
+ struct mds_client_data *mcd = med->med_mcd;
loff_t off;
int rc;
- mci = mds_uuid_to_mci(mds, req->rq_connection->c_remote_uuid);
- if (!mci) {
- CERROR("unable to locate MDS client data for UUID '%s'\n",
- ptlrpc_req_to_uuid(req));
- /* This will be a real error once everything is working */
- //LBUG();
- RETURN(0);
- }
-
- off = MDS_LR_CLIENT + mci->mci_off * MDS_LR_SIZE;
+ off = MDS_LR_CLIENT + med->med_off * MDS_LR_SIZE;
++mds->mds_last_rcvd; /* lock this, or make it an LDLM function? */
req->rq_repmsg->transno = HTON__u64(mds->mds_last_rcvd);
- mci->mci_mcd->mcd_last_rcvd = cpu_to_le64(mds->mds_last_rcvd);
- mci->mci_mcd->mcd_mount_count = cpu_to_le64(mds->mds_mount_count);
- mci->mci_mcd->mcd_last_xid = cpu_to_le64(req->rq_xid);
+ mcd->mcd_last_rcvd = cpu_to_le64(mds->mds_last_rcvd);
+ mcd->mcd_mount_count = cpu_to_le64(mds->mds_mount_count);
+ mcd->mcd_last_xid = cpu_to_le64(req->rq_xid);
mds_fs_set_last_rcvd(mds, handle);
- rc = lustre_fwrite(mds->mds_rcvd_filp, (char *)mci->mci_mcd,
- sizeof(*mci->mci_mcd), &off);
+ rc = lustre_fwrite(mds->mds_rcvd_filp, (char *)mcd, sizeof(*mcd), &off);
CDEBUG(D_INODE, "wrote trans #%Ld for client '%s' at #%d: rc = %d\n",
- mds->mds_last_rcvd, mci->mci_mcd->mcd_uuid, mci->mci_off, rc);
+ mds->mds_last_rcvd, mcd->mcd_uuid, med->med_off, rc);
// store new value and last committed value in req struct
- if (rc == sizeof(*mci->mci_mcd))
+ if (rc == sizeof(*mcd))
rc = 0;
else {
CERROR("error writing to last_rcvd file: rc = %d\n", rc);
EXPORT_SYMBOL(class_name2dev);
EXPORT_SYMBOL(class_uuid2dev);
EXPORT_SYMBOL(class_uuid2obd);
+EXPORT_SYMBOL(class_new_export);
EXPORT_SYMBOL(class_connect);
EXPORT_SYMBOL(class_conn2export);
EXPORT_SYMBOL(class_rconn2export);
return NULL;
}
+struct obd_export *class_new_export(struct obd_device *obddev)
+{
+ struct obd_export * export;
+
+ export = kmem_cache_alloc(export_cachep, GFP_KERNEL);
+ if ( !export ) {
+ CERROR("no memory! (minor %d)\n", obddev->obd_minor);
+ return NULL;
+ }
+
+ memset(export, 0, sizeof(*export));
+ get_random_bytes(&export->exp_cookie, sizeof(__u64));
+ export->exp_obd = obddev;
+ INIT_LIST_HEAD(&export->exp_mds_data.med_open_head);
+ list_add(&(export->exp_chain), export->exp_obd->obd_exports.prev);
+ return export;
+}
+
/* a connection defines an export context in which preallocation can
be managed. */
int class_connect (struct lustre_handle *conn, struct obd_device *obd)
{
struct obd_export * export;
-
if (conn == NULL) {
LBUG();
return -EINVAL;
return -EINVAL;
}
- export = kmem_cache_alloc(export_cachep, GFP_KERNEL);
- if ( !export ) {
- CERROR("no memory! (minor %d)\n", obd->obd_minor);
+ export = class_new_export(obd);
+ if (!export)
return -ENOMEM;
- }
- memset(export, 0, sizeof(*export));
- get_random_bytes(&export->exp_cookie, sizeof(export->exp_cookie));
- export->exp_obd = obd;
export->exp_rconnh.addr = conn->addr;
export->exp_rconnh.cookie = conn->cookie;
- list_add(&(export->exp_chain), export->exp_obd->obd_exports.prev);
conn->addr = (__u64) (unsigned long)export;
conn->cookie = export->exp_cookie;
CDEBUG(D_IOCTL, "connect: addr %Lx cookie %Lx\n",
list_mods() {
$DBGCTL modules > $R/tmp/ogdb
echo "The GDB module script is in $R/tmp/ogdb"
- [ "$DEBUG_WAIT" = "yes" ] && echo -n "Press ENTER to continue" && read
+ [ "$DEBUG_WAIT" = "yes" ] && echo -n "Press ENTER to continue" && read < /dev/tty
return 0
}