Whamcloud - gitweb
Support delayed creation of objects, including a test program.
authoradilger <adilger>
Fri, 11 Oct 2002 00:47:39 +0000 (00:47 +0000)
committeradilger <adilger>
Fri, 11 Oct 2002 00:47:39 +0000 (00:47 +0000)
lustre/llite/file.c
lustre/osc/osc_request.c
lustre/tests/Makefile.am
lustre/tests/lovstripe.c [new file with mode: 0644]

index bcdaaa1..5861307 100644 (file)
 int ll_inode_setattr(struct inode *inode, struct iattr *attr, int do_trunc);
 extern int ll_setattr(struct dentry *de, struct iattr *attr);
 
+static int ll_create_objects(struct inode *inode, struct ll_inode_info *lli)
+{
+        struct obdo *oa;
+        int rc;
+        ENTRY;
+
+        oa = obdo_alloc();
+        if (!oa)
+                RETURN(-ENOMEM);
+
+        oa->o_mode = S_IFREG | 0600;
+        oa->o_easize = ll_mds_easize(inode->i_sb);
+        oa->o_id = inode->i_ino;
+        oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE |
+                OBD_MD_FLMODE | OBD_MD_FLEASIZE;
+        rc = obd_create(ll_i2obdconn(inode), oa, &lli->lli_smd);
+        obdo_free(oa);
+
+        if (!rc)
+                LASSERT(lli->lli_smd->lsm_object_id);
+        RETURN(rc);
+}
+
 static int ll_file_open(struct inode *inode, struct file *file)
 {
         struct ptlrpc_request *req = NULL;
         struct ll_file_data *fd;
-        struct obdo *oa = NULL;
+        struct obdo *oa;
         struct lov_stripe_md *lsm = NULL;
         struct ll_sb_info *sbi = ll_i2sbi(inode);
         struct ll_inode_info *lli = ll_i2info(inode);
@@ -53,32 +76,18 @@ static int ll_file_open(struct inode *inode, struct file *file)
         /*  XXX object needs to be cleaned up if mdc_open fails */
         /*  XXX error handling appropriate here? */
         if (lsm == NULL) {
-                struct inode *inode = file->f_dentry->d_inode;
-
+                if (file->f_flags & O_LOV_DELAY_CREATE) {
+                        CDEBUG(D_INODE, "delaying object creation\n");
+                        RETURN(0);
+                }
                 down(&lli->lli_open_sem);
                 /* Check to see if we lost the race */
-                if (lli->lli_smd == NULL) {
-                        oa = obdo_alloc();
-                        if (!oa) {
-                                up(&lli->lli_open_sem);
-                                RETURN(-ENOMEM);
-                        }
-                        oa->o_mode = S_IFREG | 0600;
-                        oa->o_easize = ll_mds_easize(inode->i_sb);
-                        oa->o_id = inode->i_ino;
-                        oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE |
-                                OBD_MD_FLMODE | OBD_MD_FLEASIZE;
-                        rc = obd_create(ll_i2obdconn(inode), oa, &lli->lli_smd);
-
-                        if (rc) {
-                                obdo_free(oa);
-                                up(&lli->lli_open_sem);
-                                RETURN(rc);
-                        }
-                }
-                if (lli->lli_smd->lsm_object_id == 0)
-                        LBUG();
+                if (!lli->lli_smd)
+                        rc = ll_create_objects(inode, lli);
                 up(&lli->lli_open_sem);
+                if (rc)
+                        RETURN(rc);
+
                 lsm = lli->lli_smd;
         }
 
@@ -102,8 +111,7 @@ static int ll_file_open(struct inode *inode, struct file *file)
                 /* XXX handle this how, abort or is it non-fatal? */
         }
 
-        if (!oa)
-                oa = obdo_alloc();
+        oa = obdo_alloc();
         if (!oa)
                 GOTO(out_mdc, rc = -EINVAL);
 
@@ -111,13 +119,13 @@ static int ll_file_open(struct inode *inode, struct file *file)
         oa->o_mode = S_IFREG;
         oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLSIZE;
         rc = obd_open(ll_i2obdconn(inode), oa, lsm);
+
         obd_oa2handle(&fd->fd_osthandle, oa);
+        obdo_free(oa);
 
         if (rc)
                 GOTO(out_mdc, rc = -abs(rc));
 
-        obdo_free(oa);
-
         file->private_data = fd;
 
         RETURN(0);
@@ -127,9 +135,7 @@ out_mdc:
 out_req:
         ptlrpc_free_req(req);
 //out_fd:
-        obdo_free(oa);
         kmem_cache_free(ll_file_data_slab, fd);
-        file->private_data = NULL;
 out:
         return rc;
 }
@@ -542,6 +548,47 @@ ll_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
         return retval;
 }
 
+static int ll_lov_setstripe(struct inode *inode, struct file *file,
+                            struct lov_user_md *lum)
+{
+        struct ll_inode_info *lli = ll_i2info(inode);
+        struct lov_stripe_md *lsm;
+        int size = ll_mds_easize(inode->i_sb);
+        int rc;
+
+        rc = verify_area(VERIFY_READ, lum, sizeof(*lum));
+        if (rc)
+                RETURN(rc);
+
+        down(&lli->lli_open_sem);
+        if (lli->lli_smd) {
+                CERROR("striping data already set for %d\n", inode->i_ino);
+                GOTO(out_lov_up, rc = -EPERM);
+        }
+
+        OBD_ALLOC(lli->lli_smd, size);
+        if (!lli->lli_smd)
+                GOTO(out_lov_up, rc = -ENOMEM);
+
+        lsm = lli->lli_smd;
+        lsm->lsm_magic = LOV_MAGIC;
+        lsm->lsm_stripe_size = lum->lum_stripe_size;
+        lsm->lsm_stripe_pattern = lum->lum_stripe_pattern;
+        lsm->lsm_stripe_offset = lum->lum_stripe_offset;
+        lsm->lsm_stripe_count = lum->lum_stripe_count;
+        lsm->lsm_mds_easize = size;
+
+        file->f_flags &= ~O_LOV_DELAY_CREATE;
+        rc = ll_create_objects(inode, lli);
+        if (rc)
+                OBD_FREE(lli->lli_smd, size);
+        else
+                rc = ll_file_open(inode, file);
+out_lov_up:
+        up(&lli->lli_open_sem);
+        return rc;
+}
+
 int ll_file_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                   unsigned long arg)
 {
@@ -566,6 +613,8 @@ int ll_file_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                 else
                         fd->fd_flags &= ~flags;
                 return 0;
+        case LL_IOC_LOV_SETSTRIPE:
+                return ll_lov_setstripe(inode, file, (struct lov_user_md *)arg);
 
         /* We need to special case any other ioctls we want to handle,
          * to send them to the MDS/OST as appropriate and to properly
index 0ede4f0..61adb9e 100644 (file)
@@ -169,30 +169,26 @@ static int osc_create(struct lustre_handle *conn, struct obdo *oa,
 {
         struct ptlrpc_request *request;
         struct ost_body *body;
+        struct lov_stripe_md *lsm;
         int rc, size = sizeof(*body);
         ENTRY;
 
-        if (!oa) {
-                CERROR("oa NULL\n");
-                RETURN(-EINVAL);
-        }
-
-        if (!ea) {
-                LBUG();
-        }
+        LASSERT(oa);
+        LASSERT(ea);
 
-        if (!*ea) {
+        lsm = *ea;
+        if (!lsm) {
                 // XXX check oa->o_valid & OBD_MD_FLEASIZE first...
-                OBD_ALLOC(*ea, oa->o_easize);
-                if (!*ea)
+                OBD_ALLOC(lsm, oa->o_easize);
+                if (!lsm)
                         RETURN(-ENOMEM);
-                (*ea)->lsm_mds_easize = oa->o_easize;
+                lsm->lsm_mds_easize = oa->o_easize;
         }
 
         request = ptlrpc_prep_req(class_conn2cliimp(conn), OST_CREATE, 1, &size,
                                   NULL);
         if (!request)
-                RETURN(-ENOMEM);
+                GOTO(out, rc = -ENOMEM);
 
         body = lustre_msg_buf(request->rq_reqmsg, 0);
         memcpy(&body->oa, oa, sizeof(*oa));
@@ -202,16 +198,20 @@ static int osc_create(struct lustre_handle *conn, struct obdo *oa,
         rc = ptlrpc_queue_wait(request);
         rc = ptlrpc_check_status(request, rc);
         if (rc)
-                GOTO(out, rc);
+                GOTO(out_req, rc);
 
         body = lustre_msg_buf(request->rq_repmsg, 0);
         memcpy(oa, &body->oa, sizeof(*oa));
 
-        (*ea)->lsm_object_id = oa->o_id;
-        (*ea)->lsm_stripe_count = 0;
+        lsm->lsm_object_id = oa->o_id;
+        lsm->lsm_stripe_count = 0;
+        *ea = lsm;
         EXIT;
- out:
+out_req:
         ptlrpc_free_req(request);
+out:
+        if (rc && !*ea)
+                OBD_FREE(lsm, oa->o_easize);
         return rc;
 }
 
index 9646b90..58aee95 100644 (file)
@@ -25,7 +25,7 @@ pkglib_SCRIPTS = common.sh
 pkgcfg_DATA = lustre.cfg
 noinst_PROGRAMS = openunlink testreq truncate directio openme writeme mcreate
 noinst_PROGRAMS += munlink tchmod toexcl fsx test_brw openclose createdestroy
-# noinst_PROGRAMS += ldaptest 
+noinst_PROGRAMS += lovstripe # ldaptest 
 
 # ldaptest_SOURCES = ldaptest.c
 tchmod_SOURCES = tchmod.c
@@ -42,5 +42,6 @@ fsx_SOURCES = fsx.c
 test_brw_SOURCES = test_brw.c
 openclose_SOURCES = openclose.c
 createdestroy_SOURCES = createdestroy.c
+lovstripe_SOURCES = lovstripe.c
 
 include $(top_srcdir)/Rules
diff --git a/lustre/tests/lovstripe.c b/lustre/tests/lovstripe.c
new file mode 100644 (file)
index 0000000..01d487c
--- /dev/null
@@ -0,0 +1,143 @@
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <errno.h>
+
+
+/****************** Custom includes ********************/
+#include <linux/lustre_lite.h>
+
+
+/******************  Functions ******************/
+int write_file( char *name, struct lov_user_md *striping );
+
+
+/************************  Main **********************/
+
+int main( void )
+{
+       int result;
+       struct lov_user_md a_striping;
+
+       /*  Init defaults on striping info  */
+       a_striping.lum_stripe_size = 128 * 1024;
+       a_striping.lum_stripe_pattern = 0;
+
+       /*  Write file for OST1 only  */
+       /*       Start at OST 0, and use only 1 OST  */
+       a_striping.lum_stripe_offset = 0;
+       a_striping.lum_stripe_count = 1;
+
+       result = write_file("/mnt/lustre/ost1", &a_striping);
+
+       if (result < 0) {
+               fprintf(stderr, "\nProblem writing to /mnt/lustre/ost1: %s\n",
+                       strerror(errno));
+               exit(-1);
+       }
+
+       /*  Write file for OST2 only  */
+       /*       Start at OST 1, and use only 1 OST  */
+       a_striping.lum_stripe_offset = 1;
+       a_striping.lum_stripe_count = 1;
+
+       result = write_file("/mnt/lustre/ost2", &a_striping);
+
+       if (result < 0) {
+               fprintf(stderr, "Problem writing to /mnt/lustre/ost2: %s\n",
+                       strerror(errno));
+               exit(-1);
+       }
+
+       /*  Write file across both OST1 and OST2  */
+       /*       Start at OST 0, and use only 2 OSTs  */
+       a_striping.lum_stripe_offset = 0;
+       a_striping.lum_stripe_count = 2;
+
+       result = write_file("/mnt/lustre/ost1and2", &a_striping);
+
+       if (result < 0) {
+               fprintf(stderr, "Problem writing to /mnt/lustre/ost1and2: %s\n",
+                       strerror(errno));
+               exit(-1);
+       }
+
+       return 0;
+}
+
+
+int write_file(char *name, struct lov_user_md *striping)
+{
+       char buf[262144], buf2[262144];
+       int fd, result;
+
+       fd = open(name, O_CREAT | O_RDWR | O_LOV_DELAY_CREATE);
+       if (fd < 0) {
+               fprintf(stderr, "\nUnable to open '%s': %s\n",
+                        name, strerror(errno));
+               return -1;
+       }
+
+       result = ioctl(fd, LL_IOC_LOV_SETSTRIPE, striping);
+       if (result < 0) {
+               fprintf(stderr, "\nError on ioctl for '%s' (%d): %s\n",
+                       name, fd, strerror(errno));
+               close(fd);
+               return -1;
+       }
+
+       /*  Write bogus data  */
+       result = write(fd, buf, sizeof(buf));
+       if (result < 0 || result != sizeof(buf)) {
+               fprintf(stderr, "\nError in writing data to '%s' (%d): %s\n",
+                       name, fd, strerror(errno));
+               close(fd);
+               return -1;
+       }
+
+       if (result != sizeof(buf)) {
+               fprintf(stderr, "\nShort write to '%s' (%d): %d != %d\n",
+                       name, fd, result, sizeof(buf));
+               close(fd);
+               return -1;
+       }
+
+       /*  Seek to beginning again */
+       result = lseek(fd, 0, SEEK_SET);
+       if (result < 0) {
+               fprintf(stderr, "\nError seeking to beginning '%s' (%d): %s\n",
+                       name, fd, strerror(errno));
+               close(fd);
+               return -1;
+       }
+
+       /*  Read bogus data back  */
+       result = read(fd, buf2, sizeof(buf));
+       if (result < 0) {
+               fprintf(stderr, "\nError in reading data from '%s' (%d): %s\n",
+                       name, fd, strerror(errno));
+               close(fd);
+               return -1;
+       }
+
+       if (result != sizeof(buf)) {
+               fprintf(stderr, "\nShort read from '%s' (%d): %d != %d\n",
+                       name, fd, result, sizeof(buf));
+               close(fd);
+               return -1;
+       }
+
+       if (memcmp(buf, buf2, sizeof(buf))) {
+               fprintf(stderr, "\nError comparing data in '%s' (%d): %s\n",
+                       name, fd, strerror(errno));
+               close(fd);
+               return -1;
+       }
+
+       close(fd);
+
+       return 0;
+}