* OST requests: OBDO & OBD request records
*/
-
/* opcodes */
-#define OST_GET_INFO 6
-#define OST_CONNECT 7
+#define OST_GETATTR 1
+#define OST_SETATTR 2
+#define OST_BRW 3
+#define OST_CREATE 4
+#define OST_DESTROY 5
+#define OST_GET_INFO 6
+#define OST_CONNECT 7
#define OST_DISCONNECT 8
-#define OST_GETATTR 1
-#define OST_SETATTR 2
-#define OST_PREPW 3
-#define OST_CREATE 4
-#define OST_DESTROY 5
/* packet types */
#define OST_TYPE_REQ 1
__u64 offset;
__u32 len;
__u32 flags;
+ void *page;
};
struct mds_req {
# include <string.h>
#endif
+#ifdef __KERNEL__
+/* page.c */
+inline void lustre_put_page(struct page *page);
+struct page * lustre_get_page(struct inode *dir, unsigned long n);
+void lustre_prepare_page(unsigned from, unsigned to, struct page *page);
+int lustre_commit_page(struct page *page, unsigned from, unsigned to);
+#endif
+
+
+/* macros */
#undef MIN
#define MIN(a,b) (((a)<(b)) ? (a): (b))
#undef MAX
#include <portals/p30.h>
#include <linux/lustre_idl.h>
+/* FOO_REQUEST_PORTAL receives requests for the FOO subsystem.
+ * FOO_REPLY_PORTAL receives replies _from_ the FOO subsystem. */
#define OSC_REQUEST_PORTAL 1
#define OSC_REPLY_PORTAL 2
#define MDS_REQUEST_PORTAL 3
* ======== OBD Operations Declarations ===========
*/
-#define OBD_BRW_READ (READ)
-#define OBD_BRW_WRITE (WRITE)
-#define OBD_BRW_RWMASK (READ | WRITE)
-#define OBD_BRW_CREATE (0x00000010UL)
+#define OBD_BRW_READ 1
+#define OBD_BRW_WRITE 2
+#define OBD_BRW_RWMASK OBD_BRW_READ | OBD_BRW_WRITE
+#define OBD_BRW_CREATE 4
struct obd_ops {
int (*o_iocontrol)(int cmd, struct obd_conn *, int len, void *karg,
obd_size count, obd_off offset);
int (*o_iterate)(struct obd_conn *conn, int (*)(obd_id, obd_gr, void *),
obd_id *startid, obd_gr group, void *data);
-#if 0
- int (*o_dmaread)(struct obd_conn *conn, int count, struct obd_buf **dest,
- struct obd_bufref **source);
- int (*o_pre_dmawrite)(struct obd_conn *conn, int count, struct obd_buf **dstbufs,
- struct obd_bufref **dest);
- int (*o_dmawrite)(struct obd_conn *conn, int count, struct obd_buf **dstbufs,
- struct obd_buf **dest);
-#endif
+ int (*o_preprw)(int cmd, struct obd_conn *conn,
+ int objcount, struct obd_ioobj *obj,
+ int niocount, struct niobuf *nb,
+ struct niobuf *res);
+ int (*o_commitrw)(int cmd, struct obd_conn *conn,
+ int objcount, struct obd_ioobj *obj,
+ int niocount, struct niobuf *res);
};
struct obd_request {
#define OBT(dev) dev->obd_type->typ_ops
#define OBP(dev,op) dev->obd_type->typ_ops->o_ ## op
-#define OBD_CHECK_OP(conn,op) \
-do { \
- int rc = obd_check_conn(conn); \
- if (rc) { \
- printk("obd: error in operation: " #op "\n"); \
- return rc; \
- } \
- if (!OBP(conn->oc_dev,op)) { \
- printk("obd_" #op ": dev %d no operation\n", \
- conn->oc_dev->obd_minor); \
- return -EOPNOTSUPP; \
- } \
+#define OBD_CHECK_OP(conn,op) \
+do { \
+ int rc = obd_check_conn(conn); \
+ if (rc) { \
+ printk("obd: error in operation: " #op "\n"); \
+ return rc; \
+ } \
+ if (!OBP(conn->oc_dev,op)) { \
+ printk("obd_" #op ": dev %d no operation\n", \
+ conn->oc_dev->obd_minor); \
+ return -EOPNOTSUPP; \
+ } \
} while (0)
static inline int obd_get_info(struct obd_conn *conn, obd_count keylen, void *key,
return rc;
}
-
#endif
-/* This value is not arbitrarily chosen. KIO_STATIC_PAGES from linux/iobuf.h */
-#define MAX_IOVEC (KIO_STATIC_PAGES - 1)
-
-
/*
* ======== OBD Metadata Support ===========
*/
__u32 flags);
void ost_unpack_niobuf(void **tmp, struct niobuf **nbp);
void ost_pack_ioo(void **tmp, struct obdo *oa, int bufcnt);
+void ost_unpack_ioo(void **tmp, struct obd_ioobj **ioop);
void *ost_req_buf2(struct ost_req *req);
void *ost_req_buf1(struct ost_req *req);
void *ost_rep_buf2(struct ost_rep *rep);
*nbp = *tmp;
- nb->addr = NTOH__u64((__u64)(unsigned long)nb->addr);
+ nb->addr = NTOH__u64(nb->addr);
nb->offset = NTOH__u64(nb->offset);
nb->len = NTOH__u32(nb->len);
nb->flags = NTOH__u32(nb->flags);
modulefs_DATA = llight.o
EXTRA_PROGRAMS = llight
+page.c:
+ ln -s ../lib/page.c
-llight_SOURCES = super.c rw.c file.c dir.c sysctl.c namei.c symlink.c
+
+llight_SOURCES = page.c super.c rw.c file.c dir.c sysctl.c namei.c symlink.c
include $(top_srcdir)/Rules
* Lustre Light I/O Page Cache
*
* Copyright (C) 2002, Cluster File Systems, Inc.
-*/
-
+ */
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/lustre_mds.h>
#include <linux/lustre_light.h>
+int ll_inode_setattr(struct inode *inode, struct iattr *attr);
+
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10))
/*
* Add a page to the dirty page list.
-
/*
* Remove page from dirty list
*/
EXIT;
}
-inline void set_page_clean(struct page *page)
-{
- if (PageDirty(page)) {
- ClearPageDirty(page);
- __set_page_clean(page);
- }
-}
-
/* SYNCHRONOUS I/O to object storage for an inode -- object attr will be updated too */
static int ll_brw(int rw, struct inode *inode, struct page *page, int create)
{
obd_off offset = (((obd_off)page->index) << PAGE_SHIFT);
obd_flag flags = create ? OBD_BRW_CREATE : 0;
int err;
+ struct iattr iattr;
+ loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
ENTRY;
oa = obdo_alloc();
CDEBUG(D_INODE, "commit_page writing (at %d) to %d, count %Ld\n",
from, to, count);
- err = obd_brw(WRITE, IID(inode), num_obdo, &oa, &bufs_per_obdo,
- &page, &count, &offset, &flags);
+ err = obd_brw(OBD_BRW_WRITE, IID(inode), num_obdo, &oa, &bufs_per_obdo,
+ &page, &count, &offset, &flags);
if ( !err ) {
SetPageUptodate(page);
set_page_clean(page);
}
+ if (pos > inode->i_size) {
+ iattr.ia_valid = ATTR_SIZE;
+ iattr.ia_size = inode->i_size;
+ err = ll_inode_setattr(inode, &iattr);
+ if (err) {
+ printk("mds_inode_setattr failed; do something dramatic.\n");
+ obdo_free(oa);
+ EXIT;
+ return -EIO;
+ }
+ }
+
//if ( !err )
// ll_to_inode(inode, oa); /* copy o_blocks to i_blocks */
ENTRY;
/* PDEBUG(page, "WRITEPAGE"); */
/* XXX everything is synchronous now */
- err = ll_brw(WRITE, inode, page, 1);
+ err = ll_brw(OBD_BRW_WRITE, inode, page, 1);
if ( !err ) {
SetPageUptodate(page);
struct inode *inode = page->mapping->host;
ENTRY;
printk("---> writepage called ino %ld!\n", inode->i_ino);
- BUG();
rc = ll_do_writepage(page, 1);
if ( !rc ) {
set_page_clean(page);
return error;
}
-int ll_setattr(struct dentry *de, struct iattr *attr)
+int ll_inode_setattr(struct inode *inode, struct iattr *attr)
{
- struct inode *inode = de->d_inode;
struct ptlrep_hdr *hdr = NULL;
struct ll_sb_info *sbi =
(struct ll_sb_info *)(&inode->i_sb->u.generic_sbp);
EXIT;
return err;
-} /* ll_setattr */
-
+}
+int ll_setattr(struct dentry *de, struct iattr *attr)
+{
+ return ll_inode_setattr(de->d_inode, attr);
+}
static int ll_statfs(struct super_block *sb, struct statfs *buf)
{
struct list_head *lp;
struct dentry *result;
- if (mnt) {
- *mnt = mntget(mds->mds_vfsmnt);
- }
-
if (ino == 0)
return ERR_PTR(-ESTALE);
int mds_getattr(struct ptlrpc_request *req)
{
- struct dentry *de = mds_fid2dentry(req->rq_obd, &req->rq_req.mds->fid1,
- NULL);
+ struct dentry *de;
struct inode *inode;
struct mds_rep *rep;
int rc;
req->rq_rephdr->seqno = req->rq_reqhdr->seqno;
rep = req->rq_rep.mds;
- if (!de) {
+ de = mds_fid2dentry(req->rq_obd, &req->rq_req.mds->fid1, NULL);
+ if (IS_ERR(de)) {
EXIT;
req->rq_rephdr->status = -ENOENT;
return 0;
int mds_readpage(struct ptlrpc_request *req)
{
struct vfsmount *mnt;
- struct dentry *de = mds_fid2dentry(req->rq_obd, &req->rq_req.mds->fid1,
- &mnt);
+ struct dentry *de;
struct file *file;
struct niobuf *niobuf;
struct mds_rep *rep;
int rc;
- printk("mds_readpage: ino %ld\n", de->d_inode->i_ino);
rc = mds_pack_rep(NULL, 0, NULL, 0, &req->rq_rephdr, &req->rq_rep.mds,
&req->rq_replen, &req->rq_repbuf);
if (rc) {
req->rq_rephdr->seqno = req->rq_reqhdr->seqno;
rep = req->rq_rep.mds;
+ de = mds_fid2dentry(req->rq_obd, &req->rq_req.mds->fid1, &mnt);
if (IS_ERR(de)) {
EXIT;
req->rq_rephdr->status = PTR_ERR(de);
return 0;
}
+ printk("mds_readpage: ino %ld\n", de->d_inode->i_ino);
+
file = dentry_open(de, mnt, O_RDONLY | O_LARGEFILE);
/* note: in case of an error, dentry_open puts dentry */
if (IS_ERR(file)) {
}
printk("mds_setattr: ino %ld\n", de->d_inode->i_ino);
- req->rq_rephdr->status = notify_change(de, &rec->ur_iattr);
+ if ( de->d_inode->i_op->setattr ) {
+ req->rq_rephdr->status =
+ de->d_inode->i_op->setattr(de, &rec->ur_iattr);
+ } else {
+ req->rq_rephdr->status =
+ inode_setattr(de->d_inode, &rec->ur_iattr);
+ }
dput(de);
EXIT;
EXIT;
}
+/* This value is not arbitrarily chosen. KIO_STATIC_PAGES from linux/iobuf.h */
+#define MAX_IOVEC (KIO_STATIC_PAGES - 1)
+
/* Remove writeback requests for the superblock */
int obdfs_flush_reqs(struct list_head *inode_list, unsigned long check_time)
{
ENTRY;
printk("---> writepage called ino %ld!\n", inode->i_ino);
BUG();
- rc = obdfs_brw(WRITE, inode, page, 1);
+ rc = obdfs_brw(OBD_BRW_WRITE, inode, page, 1);
if ( !rc ) {
set_page_clean(page);
} else {
printk("\n");
}
- err = obd_brw(WRITE, IID(inodes[0]), num_obdos, obdos,
- oa_bufs, pages, counts, offsets, flags);
+ err = obd_brw(OBD_BRW_WRITE, IID(inodes[0]), num_obdos, obdos,
+ oa_bufs, pages, counts, offsets, flags);
CDEBUG(D_INFO, "BRW done\n");
/* release the pages from the page cache */
ENTRY;
/* PDEBUG(page, "WRITEPAGE"); */
if ( sync )
- err = obdfs_brw(WRITE, inode, page, 1);
+ err = obdfs_brw(OBD_BRW_WRITE, inode, page, 1);
else {
err = obdfs_add_page_to_cache(inode, page);
CDEBUG(D_INFO, "DO_WR ino: %ld, page %p, err %d, uptodate %d\n",
-/*
+/*
* Copryright (C) 2001 Cluster File Systems, Inc.
*
+ * This code is issued under the GNU General Public License.
+ * See the file COPYING in this distribution
+ *
+ * Author Peter Braam <braam@clusterfs.com>
+ *
+ * This server is single threaded at present (but can easily be multi
+ * threaded). For testing and management it is treated as an
+ * obd_device, although it does not export a full OBD method table
+ * (the requests are coming in over the wire, so object target
+ * modules do not have a full method table.)
+ *
*/
#define EXPORT_SYMTAB
size2 += oa_bufs[i] * sizeof(src);
}
- request = ost_prep_req(OST_PREPW, size1, NULL, size2, NULL);
+ request = ost_prep_req(OST_BRW, size1, NULL, size2, NULL);
if (!request) {
printk("osc_connect: cannot pack req!\n");
return -ENOMEM;
}
n = 0;
+ request->rq_req.ost->cmd = rw;
ptr1 = ost_req_buf1(request->rq_req.ost);
ptr2 = ost_req_buf2(request->rq_req.ost);
for (i=0; i < num_oa; i++) {
}
}
+ request->rq_replen =
+ sizeof(struct ptlrep_hdr) + sizeof(struct ost_rep) + size2;
+
rc = osc_queue_wait(conn, request);
if (rc) {
EXIT;
goto out;
}
+#if 0
ptr2 = ost_rep_buf2(request->rq_rep.ost);
if (request->rq_rep.ost->buflen2 != n * sizeof(struct niobuf)) {
printk(__FUNCTION__ ": buffer length wrong\n");
goto out;
}
+ if (rw == OBD_BRW_READ)
+ goto out;
+
for (i=0; i < num_oa; i++) {
for (j = 0 ; j < oa_bufs[i] ; j++) {
struct niobuf *dst;
n++;
}
}
- //ost_complete_brw(rep);
+#endif
out:
if (request->rq_rephdr)
o_getattr: osc_getattr,
o_setattr: osc_setattr,
o_connect: osc_connect,
- o_disconnect: osc_disconnect
+ o_disconnect: osc_disconnect,
+ o_brw: osc_brw
};
static int __init osc_init(void)
obd_pack.c:
ln -s ../lib/obd_pack.c .
+page.c:
+ ln -s ../lib/page.c
-ost_SOURCES = obd_pack.c ost_handler.c
+ost_SOURCES = page.c obd_pack.c ost_handler.c
include $(top_srcdir)/Rules
return 0;
}
-
static int ost_disconnect(struct ost_obd *ost, struct ptlrpc_request *req)
{
struct obd_conn conn;
return 0;
}
-
-#if 0
-static struct page * ext2_get_page(struct inode *dir, unsigned long n)
-{
- struct address_space *mapping = dir->i_mapping;
- struct page *page = read_cache_page(mapping, n,
- (filler_t*)mapping->a_ops->readpage, NULL);
- if (!IS_ERR(page)) {
- wait_on_page(page);
- kmap(page);
- if (!Page_Uptodate(page))
- goto fail;
- if (!PageChecked(page))
- ext2_check_page(page);
- if (PageError(page))
- goto fail;
- }
- return page;
-
-fail:
- ext2_put_page(page);
- return ERR_PTR(-EIO);
-}
-
-static inline void ext2_put_page(struct page *page)
-{
- kunmap(page);
- page_cache_release(page);
-}
-
-/* Releases the page */
-void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de,
- struct page *page, struct inode *inode)
-{
- unsigned from = (char *) de - (char *) page_address(page);
- unsigned to = from + le16_to_cpu(de->rec_len);
- int err;
-
- lock_page(page);
- err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
- if (err)
- BUG();
- de->inode = cpu_to_le32(inode->i_ino);
- ext2_set_de_type (de, inode);
- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
- err = ext2_commit_chunk(page, from, to);
- UnlockPage(page);
- ext2_put_page(page);
-}
-
-static int ext2_commit_chunk(struct page *page, unsigned from, unsigned to)
-{
- struct inode *dir = page->mapping->host;
- int err = 0;
- dir->i_version = ++event;
- SetPageUptodate(page);
- set_page_clean(page);
-
- //page->mapping->a_ops->commit_write(NULL, page, from, to);
- //if (IS_SYNC(dir))
- // err = waitfor_one_page(page);
- return err;
-}
-
-#endif
-
-int ost_prepw(struct ost_obd *obddev, struct ptlrpc_request *req)
+int ost_brw(struct ost_obd *obddev, struct ptlrpc_request *req)
{
-#if 0
struct obd_conn conn;
int rc;
- int i, j, n;
- int objcount;
- void *tmp;
- struct niobuf **nb;
- struct obd_ioo **ioo;
+ int i, j;
+ int objcount, niocount;
+ char *tmp1, *tmp2, *end2;
+ char *res;
+ int cmd;
+ struct niobuf *nb, *src, *dst;
+ struct obd_ioobj *ioo;
+ struct ost_req *r = req->rq_req.ost;
ENTRY;
- tmp1 = ost_req_buf1(req);
- tmp2 = ost_req_buf2(req);
- objcount = req->buflen1 / sizeof(**ioo);
-
- n = 0;
- for (i=0 ; i<objcount ; i++) {
- obd_unpack_ioo
+ tmp1 = ost_req_buf1(r);
+ tmp2 = ost_req_buf2(r);
+ end2 = tmp2 + req->rq_req.ost->buflen2;
+ objcount = r->buflen1 / sizeof(*ioo);
+ niocount = r->buflen2 / sizeof(*nb);
+ cmd = r->cmd;
conn.oc_id = req->rq_req.ost->connid;
- conn.oc_dev = ost->ost_tgt;
+ conn.oc_dev = req->rq_ost->ost_tgt;
- rc = ost_pack_rep(NULL, 0, NULL, 0, &req->rq_rephdr, &req->rq_rep,
+ rc = ost_pack_rep(NULL, niocount, NULL, 0,
+ &req->rq_rephdr, &req->rq_rep.ost,
&req->rq_replen, &req->rq_repbuf);
if (rc) {
printk("ost_create: cannot pack reply\n");
return rc;
}
+ res = ost_rep_buf1(req->rq_rep.ost);
- memcpy(&req->rq_rep.ost->oa, &req->rq_req.ost->oa, sizeof(req->rq_req.ost->oa));
+ for (i=0; i < objcount; i++) {
+ ost_unpack_ioo((void *)&tmp1, &ioo);
+ if (tmp2 + ioo->ioo_bufcnt > end2) {
+ rc = -EFAULT;
+ break;
+ }
+ for (j = 0 ; j < ioo->ioo_bufcnt ; j++) {
+ ost_unpack_niobuf((void *)&tmp2, &nb);
+ }
+ }
- req->rq_rep.ost->result =ost->ost_tgt->obd_type->typ_ops->o_create
- (&conn, &req->rq_rep.ost->oa);
+ /* The unpackers move tmp1 and tmp2, so reset them before using */
+ tmp1 = ost_req_buf1(r);
+ tmp2 = ost_req_buf2(r);
+ req->rq_rep.ost->result =
+ req->rq_ost->ost_tgt->obd_type->typ_ops->o_preprw
+ (cmd, &conn, objcount, (struct obd_ioobj *)tmp1,
+ niocount, (struct niobuf *)tmp2, (struct niobuf *)res);
+
+ if (cmd == OBD_BRW_WRITE) {
+ for (i=0; i<niocount; i++) {
+ src = &((struct niobuf *)tmp2)[i];
+ dst = &((struct niobuf *)res)[i];
+ memcpy((void *)(unsigned long)dst->addr,
+ (void *)(unsigned long)src->addr,
+ src->len);
+ }
+ } else {
+ for (i=0; i<niocount; i++) {
+ dst = &((struct niobuf *)tmp2)[i];
+ src = &((struct niobuf *)res)[i];
+ memcpy((void *)(unsigned long)dst->addr,
+ (void *)(unsigned long)src->addr,
+ PAGE_SIZE);
+ }
+ }
+
+ req->rq_rep.ost->result =
+ req->rq_ost->ost_tgt->obd_type->typ_ops->o_commitrw
+ (cmd, &conn, objcount, (struct obd_ioobj *)tmp1,
+ niocount, (struct niobuf *)res);
EXIT;
return 0;
-#endif
- return -ENOTSUPP;
-
}
-
int ost_handle(struct obd_device *obddev, struct ptlrpc_request *req)
{
int rc;
CDEBUG(D_INODE, "setattr\n");
rc = ost_setattr(ost, req);
break;
- case OST_PREPW:
- CDEBUG(D_INODE, "prepw\n");
- rc = ost_prepw(ost, req);
+ case OST_BRW:
+ CDEBUG(D_INODE, "brw\n");
+ rc = ost_brw(ost, req);
break;
default:
req->rq_status = -ENOTSUPP;
ENTRY;
+ if (request->rq_replen == 0) {
+ printk(__FUNCTION__ ": request->rq_replen is 0!\n");
+ EXIT;
+ return -EINVAL;
+ }
+
request->rq_repbuf = kmalloc(request->rq_replen, GFP_KERNEL);
if (!request->rq_repbuf) {
EXIT;
printk(__FUNCTION__ ": PtlMEUnlink failed: %d\n", rc);
kfree(service->srv_buf);
+ return 0;
}
static int req_init_portals(void)
$R/usr/src/portals/linux/utils/acceptor 1234 &
-$R/usr/src/portals/linux/utils/ptlctl <<EOF
-mynid
-setup tcp
-connect localhost 1234
-add_uuid self
-add_uuid mds
-EOF
-
insmod $R/usr/src/obd/rpc/ptlrpc.o
insmod $R/usr/src/obd/class/obdclass.o
insmod $R/usr/src/obd/ext2obd/obdext2.o
insmod $R/usr/src/obd/mdc/mdc.o
insmod $R/usr/src/obd/llight/llight.o
+$R/usr/src/portals/linux/utils/ptlctl <<EOF
+mynid
+setup tcp
+connect localhost 1234
+add_uuid self
+add_uuid mds
+add_uuid ost
+quit
+EOF
+
dd if=/dev/zero of=/tmp/ost bs=1024 count=10000
mke2fs -b 4096 -F /tmp/ost
losetup ${LOOP}0 /tmp/ost
setup 1
device 3
attach osc
-setup 2
+setup
quit
EOF
mkdir /mnt/obd
-# mount -t lustre_light -o device=3 none /mnt/obd
+mount -t lustre_light -o device=3 none /mnt/obd
del_uuid self
del_uuid mds
del_uuid ost
+quit
EOF
rmmod ksocknal