Whamcloud - gitweb
Widesweeping change to support different-sized LOV MD data (b=307,345, and
authoradilger <adilger>
Tue, 12 Nov 2002 18:50:44 +0000 (18:50 +0000)
committeradilger <adilger>
Tue, 12 Nov 2002 18:50:44 +0000 (18:50 +0000)
partially 314).  The goal is to remove all knowledge of MD data from llite
and the MDS, and keep it solely inside OSC and LOV.  The change is not
entirely complete (for enh 314) in that we still pass "struct lov_stripe_md"
and "struct lov_mds_md" structs around, but that was mostly for sanity to
avoid getting the two screwed up during this large amount of change.

OSC passes runtests, and LOV has a _huge_ bug in it that dies after a
single file copy+cleanup, so that's why it's on a branch.

This adds two new OBD API methods (I'm not totally stuck on the names yet):
- o_packmd to alloc/pack/free data for wire transport and storage on disk
- o_unpackmd to alloc/pack/free data for in-memory and storage on disk

There are helper functions obd_{alloc,size,free}_{mem,wire}md() which call
the above two OBD API methods with the correct parameters to just allocate
or size or free an MD.  This totally isolates anything outside LOV/OSC from
knowing anything of the internals of the MD data struct, and lays the
groundwork for LOV stacking in the future.

The user-space LOV striping setup has also changed slightly to use the
"MDS/wire/disk" MD format for communication instead of the in-memory
MD format, and the lovstripe.c test, utils/lfind.c and new utils/lstripe.c
program (formerly makestripe.c from Kevin Harlan) have been updated to use
this new interface.  The lstripe.c utility allows easy creation of files
with a specific striping pattern.

lustre/lov/lov_pack.c [new file with mode: 0644]
lustre/utils/lstripe.c [new file with mode: 0644]

diff --git a/lustre/lov/lov_pack.c b/lustre/lov/lov_pack.c
new file mode 100644 (file)
index 0000000..a35a3a2
--- /dev/null
@@ -0,0 +1,178 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *  Copyright (C) 2002 Cluster File Systems, Inc. <adilger@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.
+ *
+ * (Un)packing of OST/MDS requests
+ *
+ */
+
+#define DEBUG_SUBSYSTEM S_LLITE
+
+#include <linux/lustre_net.h>
+#include <linux/obd.h>
+#include <linux/obd_lov.h>
+#include <linux/obd_support.h>
+
+void lov_packdesc(struct lov_desc *ld)
+{
+        ld->ld_tgt_count = HTON__u32(ld->ld_tgt_count);
+        ld->ld_default_stripe_count = HTON__u32(ld->ld_default_stripe_count);
+        ld->ld_default_stripe_size = HTON__u32(ld->ld_default_stripe_size);
+        ld->ld_pattern = HTON__u32(ld->ld_pattern);
+}
+
+void lov_unpackdesc(struct lov_desc *ld)
+{
+        ld->ld_tgt_count = NTOH__u32(ld->ld_tgt_count);
+        ld->ld_default_stripe_count = HTON__u32(ld->ld_default_stripe_count);
+        ld->ld_default_stripe_size = HTON__u32(ld->ld_default_stripe_size);
+        ld->ld_pattern = HTON__u32(ld->ld_pattern);
+}
+
+/* Pack LOV object metadata for shipment to the MDS.
+ *
+ * XXX In the future, this will be enhanced to get the EA size from the
+ *     underlying OSC device(s) to get their EA sizes so we can stack
+ *     LOVs properly.  For now lov_mds_md_size() just assumes one obd_id
+ *     per stripe.
+ */
+int lov_packmd(struct lustre_handle *conn, struct lov_mds_md **lmmp,
+               struct lov_stripe_md *lsm)
+{
+        struct obd_device *obd = class_conn2obd(conn);
+        struct lov_obd *lov = &obd->u.lov;
+        struct lov_oinfo *loi;
+        struct lov_mds_md *lmm;
+        int ost_count = lov->desc.ld_tgt_count;
+        int stripe_count = ost_count;
+        int lmm_size;
+        int i;
+
+        if (lsm)
+                stripe_count = lsm->lsm_stripe_count;
+
+        /* XXX LOV STACKING call into osc for sizes */
+        lmm_size = lov_mds_md_size(stripe_count);
+
+        if (!lmmp)
+                RETURN(lmm_size);
+
+        if (*lmmp && !lsm) {
+                /* endianness */
+                stripe_count = ((*lmmp)->lmm_stripe_count);
+                OBD_FREE(*lmmp, lov_stripe_md_size(stripe_count));
+                *lmmp = NULL;
+                RETURN(0);
+        }
+
+        if (!*lmmp) {
+                OBD_ALLOC(*lmmp, lmm_size);
+                if (!*lmmp)
+                        RETURN(-ENOMEM);
+        }
+        lmm->lmm_stripe_count = (stripe_count);
+        if (!lsm)
+                RETURN(lmm_size);
+        lmm = *lmmp;
+
+        /* XXX endianness */
+        lmm->lmm_magic = (lsm->lsm_magic);
+        lmm->lmm_object_id = (lsm->lsm_object_id);
+        lmm->lmm_stripe_size = (lsm->lsm_stripe_size);
+        lmm->lmm_stripe_pattern = (lsm->lsm_stripe_pattern);
+        lmm->lmm_stripe_offset = (lsm->lsm_stripe_offset);
+
+        /* Only fill in the object ids which we are actually using.
+         * Assumes lmm_objects is otherwise zero-filled. */
+        for (i = 0, loi = lsm->lsm_oinfo; i < stripe_count; i++, loi++)
+                /* XXX call down to osc_packmd() to do the packing */
+                lmm->lmm_objects[loi->loi_ost_idx].l_object_id = (loi->loi_id);
+
+        return lmm_size;
+}
+
+int lov_unpackmd(struct lustre_handle *conn, struct lov_stripe_md **lsmp,
+                 struct lov_mds_md *lmm)
+{
+        struct obd_device *obd = class_conn2obd(conn);
+        struct lov_obd *lov = &obd->u.lov;
+        struct lov_stripe_md *lsm;
+        struct lov_oinfo *loi;
+        int ost_count = lov->desc.ld_active_tgt_count;
+        int ost_offset = 0;
+        int stripe_count = 0;
+        int lsm_size;
+        int i;
+
+        if (lmm)
+                /* endianness */
+                stripe_count = (lmm->lmm_stripe_count);
+
+        if (!stripe_count)
+                stripe_count = lov->desc.ld_default_stripe_count;
+        if (!stripe_count || stripe_count > ost_count)
+                stripe_count = ost_count;
+
+        /* XXX LOV STACKING call into osc for sizes */
+        lsm_size = lov_stripe_md_size(stripe_count);
+
+        if (!lsmp)
+                RETURN(lsm_size);
+
+        if (*lsmp && !lmm) {
+                stripe_count = (*lsmp)->lsm_stripe_count;
+                OBD_FREE(*lsmp, lov_stripe_md_size(stripe_count));
+                *lsmp = NULL;
+                RETURN(0);
+        }
+
+        if (!*lsmp) {
+                OBD_ALLOC(*lsmp, lsm_size);
+                if (!*lsmp)
+                        RETURN(-ENOMEM);
+        }
+
+        lsm->lsm_stripe_count = stripe_count;
+        if (!lmm)
+                RETURN(lsm_size);
+
+        lsm = *lsmp;
+
+        /* XXX endianness */
+        ost_offset = lsm->lsm_stripe_offset = (lmm->lmm_stripe_offset);
+        lsm->lsm_magic = (lmm->lmm_magic);
+        lsm->lsm_object_id = (lmm->lmm_object_id);
+        lsm->lsm_stripe_size = (lmm->lmm_stripe_size);
+        lsm->lsm_stripe_pattern = (lmm->lmm_stripe_pattern);
+
+        for (i = 0, loi = lsm->lsm_oinfo; i < ost_count; i++, ost_offset++) {
+                ost_offset %= ost_count;
+
+                if (!lmm->lmm_objects[ost_offset].l_object_id)
+                        continue;
+
+                LASSERT(loi - lsm->lsm_oinfo < stripe_count);
+                /* XXX LOV STACKING call down to osc_unpackmd() */
+                loi->loi_id = (lmm->lmm_objects[ost_offset].l_object_id);
+                loi->loi_ost_idx = ost_offset;
+                loi++;
+        }
+
+        return lsm_size;
+}
diff --git a/lustre/utils/lstripe.c b/lustre/utils/lstripe.c
new file mode 100644 (file)
index 0000000..65055a5
--- /dev/null
@@ -0,0 +1,101 @@
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+
+/****************** Custom includes ********************/
+#include <linux/lustre_lite.h>
+#include <linux/lustre_idl.h>
+
+
+/******************  Functions ******************/
+
+void usage(char *pgm)
+{
+       fprintf(stderr, "\nIncorrect parameters!  Correct usage:\n\n" );
+       fprintf(stderr, "%s <output filename> <stripe size> <OST #> <stripe #>\n", pgm);
+
+       fprintf(stderr, "\n\nArgument explanations:\n---------------------\n\n");
+       fprintf(stderr, "<output filename> = the full name and path of the output file to create\n");
+       fprintf(stderr, "<stripe size> = the number of bytes to have in each stripe.\n");
+       fprintf(stderr, "<OST #> = the OST number to start the striping on.\n");
+       fprintf(stderr, "<stripe #> = the number of stripes to use.\n");
+
+       fprintf(stderr, "\n\nExamples:\n---------\n\n");
+
+       fprintf(stderr, "%s /mnt/lustre/ost1 131072 0 1\n", pgm);
+       fprintf(stderr, "\t\tcreates a file only on ost1.\n\n");
+
+       fprintf(stderr, "%s /mnt/lustre/ost2 131072 1 1\n", pgm);
+       fprintf(stderr, "\t\tcreates a file only on ost2.\n\n");
+
+       fprintf(stderr, "%s /mnt/lustre/ost1and2 131072 0 2\n", pgm);
+       fprintf(stderr, "\t\tcreates a 128k file with 2 stripes, on ost1 and ost2.\n");
+
+       fprintf(stderr, "%s /mnt/lustre/ost1and2 131072 1 2\n", pgm);
+       fprintf(stderr, "\t\tcreates a 128k file with 2 stripes, on ost2 and ost1.\n");
+}
+
+int create_file(char *name, long stripe_size, int stripe_offset,
+               int stripe_count)
+{
+       struct lov_mds_md a_striping;
+       int fd, result = 0;
+
+       /*  Initialize IOCTL striping pattern structure  */
+       a_striping.lmm_magic = LOV_MAGIC;
+       a_striping.lmm_stripe_pattern = 0;
+       a_striping.lmm_stripe_size = stripe_size;
+       a_striping.lmm_stripe_offset = stripe_offset;
+       a_striping.lmm_stripe_count = stripe_count;
+
+       fd = open(name, O_CREAT | O_RDWR | O_LOV_DELAY_CREATE, 0644);
+       if (fd < 0) {
+               fprintf(stderr, "\nUnable to open '%s': %s\n",
+                       name, strerror(errno));
+               result = -errno;
+       } else if (ioctl(fd, LL_IOC_LOV_SETSTRIPE, &a_striping)) {
+               fprintf(stderr, "\nError on ioctl for '%s' (%d): %s\n",
+                       name, fd, strerror(errno));
+               result = -errno;
+       } else if (close(fd) < 0) {
+               fprintf(stderr, "\nError on close for '%s' (%d): %s\n",
+                       name, fd, strerror(errno));
+               result = -errno;
+       }
+
+       return result;
+}
+
+int main(int argc, char *argv[])
+{
+       int result;
+       long st_size;
+       int  st_offset,
+            st_count;
+
+       /*  Check to make sure we have enough parameters  */
+       if (argc != 5) {
+               usage(argv[0]);
+               return(-1);
+       }
+
+       /* Get the stripe size */
+       st_size = atol(argv[2]);
+
+       /* Get the stripe offset*/
+       st_offset = atoi(argv[3]);
+
+       /* Get the stripe count */
+       st_count = atoi(argv[4]);
+
+       /*  Create the file, as specified.  Return and display any errors.  */
+       result = create_file(argv[1], st_size, st_offset, st_count);
+
+       return result;
+}