-/*
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
* linux/fs/ext2_obd/ext2_obd.c
*
* Copyright (C) 2001 Cluster File Systems, Inc.
};
-
-/* push / pop to root of obd store */
-void push_ctxt(struct obd_run_ctxt *save, struct obd_run_ctxt *new)
-{
- save->fs = get_fs();
- save->pwd = dget(current->fs->pwd);
- save->pwdmnt = mntget(current->fs->pwdmnt);
-
- set_fs(new->fs);
- set_fs_pwd(current->fs, new->pwdmnt, new->pwd);
-}
-
-void pop_ctxt(struct obd_run_ctxt *saved)
-{
- set_fs(saved->fs);
- set_fs_pwd(current->fs, saved->pwdmnt, saved->pwd);
-
- dput(saved->pwd);
- mntput(saved->pwdmnt);
-}
-
-/* utility to make a directory */
-static int simple_mkdir(struct dentry *dir, char *name, int mode)
-{
- struct dentry *dchild;
- int err;
- ENTRY;
-
- dchild = lookup_one_len(name, dir, strlen(name));
- if (IS_ERR(dchild)) {
- EXIT;
- return PTR_ERR(dchild);
- }
-
- if (dchild->d_inode) {
- dput(dchild);
- EXIT;
- return -EEXIST;
- }
-
- err = vfs_mkdir(dir->d_inode, dchild, mode);
- dput(dchild);
-
- EXIT;
- return err;
-}
-
/* write the pathname into the string */
static void filter_id(char *buf, obd_id id, obd_mode mode)
{
}
/* setup the object store with correct subdirectories */
-static void filter_prep(struct obd_device *obddev)
+static int filter_prep(struct obd_device *obddev)
{
struct obd_run_ctxt saved;
struct file *file;
struct inode *inode;
loff_t off;
- long rc;
+ int rc = 0;
char rootid[128];
__u64 lastino = 2;
rc = simple_mkdir(current->fs->pwd, "O", 0700);
rc = simple_mkdir(current->fs->pwd, "P", 0700);
rc = simple_mkdir(current->fs->pwd, "D", 0700);
- file = filp_open("O", O_RDONLY, 0);
- if (!file || IS_ERR(file)) {
- CERROR("cannot open O\n");
- goto out;
+ file = filp_open("O", O_RDONLY, 0);
+ if (IS_ERR(file)) {
+ CERROR("cannot open O\n");
+ GOTO(out, rc = PTR_ERR(file));
}
rc = simple_mkdir(file->f_dentry, "R", 0700); /* regular */
rc = simple_mkdir(file->f_dentry, "D", 0700); /* directory */
rc = simple_mkdir(file->f_dentry, "B", 0700); /* block devices */
rc = simple_mkdir(file->f_dentry, "F", 0700); /* fifo's */
rc = simple_mkdir(file->f_dentry, "S", 0700); /* sockets */
- filp_close(file, NULL);
+ filp_close(file, NULL);
filter_id(rootid, FILTER_ROOTINO, S_IFDIR);
file = filp_open(rootid, O_RDWR | O_CREAT, 00755);
if (IS_ERR(file)) {
CERROR("OBD filter: cannot make root directory");
- goto out;
+ GOTO(out, rc = PTR_ERR(file));
}
filp_close(file, 0);
+ /* FIXME: this is the same as the _file_ we just created? */
rc = simple_mkdir(current->fs->pwd, rootid, 0755);
file = filp_open("D/status", O_RDWR | O_CREAT, 0700);
if ( !file || IS_ERR(file) ) {
CERROR("OBD filter: cannot open/create status file\n");
- goto out;
+ GOTO(out, rc = PTR_ERR(file));
}
/* steal operations */
obddev->u.filter.fo_aops = inode->i_mapping->a_ops;
off = 0;
- if (inode->i_size == 0) {
- rc = file->f_op->write(file, (char *)&lastino,
- sizeof(lastino), &off);
- if (rc != sizeof(lastino)) {
+ if (inode->i_size == 0) {
+ ssize_t retval = file->f_op->write(file, (char *)&lastino,
+ sizeof(lastino), &off);
+ if (retval != sizeof(lastino)) {
CERROR("OBD filter: error writing lastino\n");
- goto out;
+ GOTO(out, rc = -EIO);
}
- } else {
- rc = file->f_op->read(file, (char *)&lastino, sizeof(lastino),
- &off);
- if (rc != sizeof(lastino)) {
+ } else {
+ ssize_t retval = file->f_op->read(file, (char *)&lastino,
+ sizeof(lastino), &off);
+ if (retval != sizeof(lastino)) {
CERROR("OBD filter: error reading lastino\n");
- goto out;
+ GOTO(out, rc = -EIO);
}
}
obddev->u.filter.fo_lastino = lastino;
filp_close(file, 0);
+ rc = 0;
out:
pop_ctxt(&saved);
+
+ return(rc);
}
/* cleanup the filter: write last used object id to status file */
}
/* mount the file system (secretly) */
-static int filter_setup(struct obd_device *obddev, obd_count len,
- void *buf)
-
+static int filter_setup(struct obd_device *obddev, obd_count len, void *buf)
{
struct obd_ioctl_data* data = buf;
struct vfsmount *mnt;
- int err;
+ int err = 0;
ENTRY;
-
-
- mnt = do_kern_mount(data->ioc_inlbuf2, 0,
- data->ioc_inlbuf1, NULL);
+
+ MOD_INC_USE_COUNT;
+ mnt = do_kern_mount(data->ioc_inlbuf2, 0, data->ioc_inlbuf1, NULL);
err = PTR_ERR(mnt);
- if (IS_ERR(mnt)) {
- EXIT;
- return err;
- }
+ if (IS_ERR(mnt))
+ GOTO(err_dec, err);
+ /* XXX is this even possible if do_kern_mount succeeded? */
obddev->u.filter.fo_sb = mnt->mnt_root->d_inode->i_sb;
- if (!obddev->u.filter.fo_sb) {
- EXIT;
- return -ENODEV;
- }
+ if (!obddev->u.filter.fo_sb)
+ GOTO(err_put, err = -ENODEV);
obddev->u.filter.fo_vfsmnt = mnt;
obddev->u.filter.fo_fstype = strdup(data->ioc_inlbuf2);
obddev->u.filter.fo_ctxt.pwd = mnt->mnt_root;
obddev->u.filter.fo_ctxt.fs = KERNEL_DS;
- filter_prep(obddev);
+ err = filter_prep(obddev);
+ if (err)
+ GOTO(err_kfree, err);
spin_lock_init(&obddev->u.filter.fo_lock);
- MOD_INC_USE_COUNT;
- EXIT;
- return 0;
-}
+ RETURN(0);
+
+err_kfree:
+ kfree(obddev->u.filter.fo_fstype);
+err_put:
+ unlock_kernel();
+ mntput(obddev->u.filter.fo_vfsmnt);
+ obddev->u.filter.fo_sb = 0;
+ lock_kernel();
+
+err_dec:
+ MOD_DEC_USE_COUNT;
+ return err;
+}
static int filter_cleanup(struct obd_device * obddev)
ENTRY;
- if ( !(obddev->obd_flags & OBD_SET_UP) ) {
- EXIT;
- return 0;
- }
+ if ( !(obddev->obd_flags & OBD_SET_UP) )
+ RETURN(0);
if ( !list_empty(&obddev->obd_gen_clients) ) {
CERROR("still has clients!\n");
- EXIT;
- return -EBUSY;
+ RETURN(-EBUSY);
}
sb = obddev->u.filter.fo_sb;
- if (!obddev->u.filter.fo_sb){
- EXIT;
- return 0;
- }
+ if (!obddev->u.filter.fo_sb)
+ RETURN(0);
+
filter_post(obddev);
unlock_kernel();
lock_kernel();
MOD_DEC_USE_COUNT;
- EXIT;
- return 0;
+ RETURN(0);
}
}
#if 0
- else if (ext2obd_has_inline(inode)) {
+ else if (filter_has_inline(inode)) {
CDEBUG(D_INFO, "copying inline from inode to obdo\n");
memcpy(oa->o_inline, inode->u.ext2_i.i_data,
MIN(sizeof(inode->u.ext2_i.i_data),OBD_INLINESZ));
oa->o_valid |= OBD_MD_FLINLINE;
}
- if (ext2obd_has_obdmd(inode)) {
+ if (filter_has_obdmd(inode)) {
/* XXX this will change when we don't store the obdmd in data */
CDEBUG(D_INFO, "copying obdmd from inode to obdo\n");
memcpy(oa->o_obdmd, inode->u.ext2_i.i_data,
return rc;
}
+static int filter_open(struct obd_conn *conn, struct obdo *oa)
+{
+ struct inode *inode;
+ /* ENTRY; */
+
+ if (!gen_client(conn))
+ RETURN(-EINVAL);
+
+ if ( !(inode = filter_inode_from_obj(conn->oc_dev,
+ oa->o_id, oa->o_mode)) )
+ RETURN(-ENOENT);
+
+ return 0;
+} /* filter_open */
+
+static int filter_close(struct obd_conn *conn, struct obdo *oa)
+{
+ struct inode *inode;
+ /* ENTRY; */
+
+ if (!gen_client(conn))
+ RETURN(-EINVAL);
+
+ if ( !(inode = filter_inode_from_obj(conn->oc_dev,
+ oa->o_id, oa->o_mode)) )
+ RETURN(-ENOENT);
+
+ iput(inode); /* for the close */
+ iput(inode); /* for this call */
+ return 0;
+} /* filter_close */
+
static int filter_create (struct obd_conn* conn, struct obdo *oa)
{
char name[64];
}
return err;
-} /* ext2obd_write */
+} /* filter_write */
static int filter_pgcache_brw(int rw, struct obd_conn *conn,
obd_count num_oa,
return inode;
}
-int filter_preprw(int cmd, struct obd_conn *conn,
- int objcount, struct obd_ioobj *obj,
- int niocount, struct niobuf *nb,
- struct niobuf *res)
+static int filter_preprw(int cmd, struct obd_conn *conn,
+ int objcount, struct obd_ioobj *obj,
+ int niocount, struct niobuf *nb,
+ struct niobuf *res)
{
- int i, j;
- struct obd_ioobj *o;
- struct niobuf *b;
- struct niobuf *r;
- struct inode *inode;
- struct page *page;
- int rc = 0;
+ struct obd_ioobj *o = obj;
+ struct niobuf *b = nb;
+ struct niobuf *r = res;
+ int i;
ENTRY;
memset(res, 0, sizeof(*res) * niocount);
- for (i=0; i < objcount; i++) {
- o = obj;
- obj++;
- for (j = 0 ; j < o->ioo_bufcnt ; j++) {
- b = nb;
- r = res;
- nb++;
- res++;
-
- inode = ioobj_to_inode(conn, o);
- if (!inode) {
- EXIT;
- /* FIXME: we need to iput all of previous inodes */
- return -EINVAL;
- }
+ for (i = 0; i < objcount; i++, o++) {
+ int j;
+ for (j = 0; j < o->ioo_bufcnt; j++, b++, r++) {
+ struct inode *inode = ioobj_to_inode(conn, o);
+ struct page *page;
+
+ /* FIXME: we need to iput all inodes on error */
+ if (!inode)
+ RETURN(-EINVAL);
page = lustre_get_page(inode, b->offset >> PAGE_SHIFT);
- if (IS_ERR(page)) {
- EXIT;
- return PTR_ERR(page);
- }
+ if (IS_ERR(page))
+ RETURN(PTR_ERR(page));
+
if (cmd == OBD_BRW_WRITE) {
- rc = lustre_prepare_page(0, PAGE_SIZE, page);
- }
- if (rc) {
- CERROR("i %d j %d objcount %d bufcnt %d , rc %d, offset %Ld\n", i, j, objcount, o->ioo_bufcnt, rc, b->offset);
+ int rc = lustre_prepare_page(0, PAGE_SIZE,page);
+ if (rc)
+ CERROR("i %d j %d objcount %d bufcnt %d , rc %d, offset %Ld\n", i, j, objcount, o->ioo_bufcnt, rc, b->offset);
}
-
- r->addr = (__u64)(unsigned long)page_address(page);
+
+ r->addr = (__u64)(unsigned long)page_address(page);
r->offset = b->offset;
r->page = page;
r->len = PAGE_SIZE;
- /* r->flags */
}
}
return 0;
}
-int filter_commitrw(int cmd, struct obd_conn *conn,
- int objcount, struct obd_ioobj *obj,
- int niocount, struct niobuf *res)
+static int filter_commitrw(int cmd, struct obd_conn *conn,
+ int objcount, struct obd_ioobj *obj,
+ int niocount, struct niobuf *res)
{
- int i, j;
- int rc;
- struct inode *inode;
- struct obd_ioobj *o;
- struct niobuf *r = NULL;
+ struct obd_ioobj *o = obj;
+ struct niobuf *r = res;
+ int i;
ENTRY;
- for (i=0; i < objcount; i++) {
- o = obj;
- obj++;
+ for (i = 0; i < objcount; i++, obj++) {
+ int j;
+ for (j = 0 ; j < o->ioo_bufcnt ; j++, r++) {
+ struct page *page = r->page;
- for (j = 0 ; j < o->ioo_bufcnt ; j++) {
- r = res;
- if (!r)
+ if (!r->page)
LBUG();
- res++;
- if (!r)
- LBUG();
+ if (cmd == OBD_BRW_WRITE) {
+ int rc = lustre_commit_page(page, 0, PAGE_SIZE);
- if (cmd == OBD_BRW_WRITE)
- rc = lustre_commit_page(r->page, 0, PAGE_SIZE);
- else {
- lustre_put_page(r->page);
- rc = 0;
- }
+ /* FIXME: still need to iput the other inodes */
+ if (rc)
+ RETURN(rc);
+ } else
+ lustre_put_page(page);
- if (rc) {
- EXIT;
- return rc;
- }
- inode = ((struct page *)r->page)->mapping->host;
- iput(inode);
+ iput(page->mapping->host);
}
}
- return 0;
+ RETURN(0);
}
static int filter_statfs (struct obd_conn *conn, struct statfs * statfs)
err = sb->s_op->statfs(sb, statfs);
EXIT;
return err;
-} /* ext2obd_statfs */
+} /* filter_statfs */
static int filter_get_info(struct obd_conn *conn, obd_count keylen,
o_create: filter_create,
o_setattr: filter_setattr,
o_destroy: filter_destroy,
+ o_open: filter_open,
+ o_close: filter_close,
o_read: filter_read,
o_write: filter_write,
o_brw: filter_pgcache_brw,
o_preprw: filter_preprw,
o_commitrw: filter_commitrw
#if 0
- o_preallocate: ext2obd_preallocate_inodes,
- o_migrate: ext2obd_migrate,
+ o_preallocate: filter_preallocate_inodes,
+ o_migrate: filter_migrate,
o_copy: gen_copy_data,
- o_iterate: ext2obd_iterate
+ o_iterate: filter_iterate
#endif
};