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);
/* 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;
}
/* 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);
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);
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;
}
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)
{
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
{
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));
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;
}
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
test_brw_SOURCES = test_brw.c
openclose_SOURCES = openclose.c
createdestroy_SOURCES = createdestroy.c
+lovstripe_SOURCES = lovstripe.c
include $(top_srcdir)/Rules
--- /dev/null
+#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;
+}