libceph: collapse all data items into one
[cascardo/linux.git] / include / linux / ceph / messenger.h
index 60903e0..af786b2 100644 (file)
@@ -64,6 +64,71 @@ struct ceph_messenger {
        u32 required_features;
 };
 
+#define ceph_msg_has_data(m)           ((m)->data.type != CEPH_MSG_DATA_NONE)
+
+enum ceph_msg_data_type {
+       CEPH_MSG_DATA_NONE,     /* message contains no data payload */
+       CEPH_MSG_DATA_PAGES,    /* data source/destination is a page array */
+       CEPH_MSG_DATA_PAGELIST, /* data source/destination is a pagelist */
+#ifdef CONFIG_BLOCK
+       CEPH_MSG_DATA_BIO,      /* data source/destination is a bio list */
+#endif /* CONFIG_BLOCK */
+};
+
+static __inline__ bool ceph_msg_data_type_valid(enum ceph_msg_data_type type)
+{
+       switch (type) {
+       case CEPH_MSG_DATA_NONE:
+       case CEPH_MSG_DATA_PAGES:
+       case CEPH_MSG_DATA_PAGELIST:
+#ifdef CONFIG_BLOCK
+       case CEPH_MSG_DATA_BIO:
+#endif /* CONFIG_BLOCK */
+               return true;
+       default:
+               return false;
+       }
+}
+
+struct ceph_msg_data_cursor {
+       size_t          resid;          /* bytes not yet consumed */
+       bool            last_piece;     /* now at last piece of data item */
+       union {
+#ifdef CONFIG_BLOCK
+               struct {                                /* bio */
+                       struct bio      *bio;           /* bio from list */
+                       unsigned int    vector_index;   /* vector from bio */
+                       unsigned int    vector_offset;  /* bytes from vector */
+               };
+#endif /* CONFIG_BLOCK */
+               struct {                                /* pages */
+                       unsigned int    page_offset;    /* offset in page */
+                       unsigned short  page_index;     /* index in array */
+                       unsigned short  page_count;     /* pages in array */
+               };
+               struct {                                /* pagelist */
+                       struct page     *page;          /* page from list */
+                       size_t          offset;         /* bytes from list */
+               };
+       };
+};
+
+struct ceph_msg_data {
+       enum ceph_msg_data_type         type;
+       union {
+#ifdef CONFIG_BLOCK
+               struct bio              *bio;
+#endif /* CONFIG_BLOCK */
+               struct {
+                       struct page     **pages;        /* NOT OWNER. */
+                       size_t          length;         /* total # bytes */
+                       unsigned int    alignment;      /* first page */
+               };
+               struct ceph_pagelist    *pagelist;
+       };
+       struct ceph_msg_data_cursor     cursor;         /* pagelist only */
+};
+
 /*
  * a single message.  it contains a header (src, dest, message type, etc.),
  * footer (crc values, mainly), a "front" message body, and possibly a
@@ -74,21 +139,14 @@ struct ceph_msg {
        struct ceph_msg_footer footer;  /* footer */
        struct kvec front;              /* unaligned blobs of message */
        struct ceph_buffer *middle;
-       struct page **pages;            /* data payload.  NOT OWNER. */
-       unsigned nr_pages;              /* size of page array */
-       unsigned page_alignment;        /* io offset in first page */
-       struct ceph_pagelist *pagelist; /* instead of pages */
+
+       /* data payload */
+       struct ceph_msg_data    data;
 
        struct ceph_connection *con;
-       struct list_head list_head;
+       struct list_head list_head;     /* links for connection lists */
 
        struct kref kref;
-#ifdef CONFIG_BLOCK
-       struct bio  *bio;               /* instead of pages/pagelist */
-       struct bio  *bio_iter;          /* bio iterator */
-       int bio_seg;                    /* current bio segment */
-#endif /* CONFIG_BLOCK */
-       struct ceph_pagelist *trail;    /* the trailing part of the data */
        bool front_is_vmalloc;
        bool more_to_follow;
        bool needs_out_seq;
@@ -218,6 +276,12 @@ extern void ceph_msg_revoke_incoming(struct ceph_msg *msg);
 
 extern void ceph_con_keepalive(struct ceph_connection *con);
 
+extern void ceph_msg_data_set_pages(struct ceph_msg *msg, struct page **pages,
+                               size_t length, size_t alignment);
+extern void ceph_msg_data_set_pagelist(struct ceph_msg *msg,
+                               struct ceph_pagelist *pagelist);
+extern void ceph_msg_data_set_bio(struct ceph_msg *msg, struct bio *bio);
+
 extern struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags,
                                     bool can_fail);
 extern void ceph_msg_kfree(struct ceph_msg *m);