Merge tag 'for-linus-20130509' of git://git.infradead.org/linux-mtd
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / include / linux / ceph / messenger.h
index 60903e0f665cb62ea9bf2db0cba04c984255e493..7c1420bb1dcef40e6f8e4cc571ef5ea2c25df913 100644 (file)
@@ -64,6 +64,77 @@ struct ceph_messenger {
        u32 required_features;
 };
 
+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 {
+       struct list_head                links;  /* ceph_msg->data */
+       enum ceph_msg_data_type         type;
+       union {
+#ifdef CONFIG_BLOCK
+               struct {
+                       struct bio      *bio;
+                       size_t          bio_length;
+               };
+#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 {
+       size_t                  total_resid;    /* across all data items */
+       struct list_head        *data_head;     /* = &ceph_msg->data */
+
+       struct ceph_msg_data    *data;          /* current data item */
+       size_t                  resid;          /* bytes not yet consumed */
+       bool                    last_piece;     /* current is last piece */
+       bool                    need_crc;       /* crc update needed */
+       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 */
+               };
+       };
+};
+
 /*
  * 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 +145,15 @@ 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 */
+
+       size_t                          data_length;
+       struct list_head                data;
+       struct ceph_msg_data_cursor     cursor;
 
        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;
@@ -98,12 +163,6 @@ struct ceph_msg {
        struct ceph_msgpool *pool;
 };
 
-struct ceph_msg_pos {
-       int page, page_pos;  /* which page; offset in page */
-       int data_pos;        /* offset in data payload */
-       bool did_page_crc;   /* true if we've calculated crc for current page */
-};
-
 /* ceph connection fault delay defaults, for exponential backoff */
 #define BASE_DELAY_INTERVAL    (HZ/2)
 #define MAX_DELAY_INTERVAL     (5 * 60 * HZ)
@@ -161,7 +220,6 @@ struct ceph_connection {
        struct ceph_msg *out_msg;        /* sending message (== tail of
                                            out_sent) */
        bool out_msg_done;
-       struct ceph_msg_pos out_msg_pos;
 
        struct kvec out_kvec[8],         /* sending header/footer data */
                *out_kvec_cur;
@@ -175,7 +233,6 @@ struct ceph_connection {
        /* message in temps */
        struct ceph_msg_header in_hdr;
        struct ceph_msg *in_msg;
-       struct ceph_msg_pos in_msg_pos;
        u32 in_front_crc, in_middle_crc, in_data_crc;  /* calculated crc */
 
        char in_tag;         /* protocol control byte */
@@ -218,6 +275,15 @@ extern void ceph_msg_revoke_incoming(struct ceph_msg *msg);
 
 extern void ceph_con_keepalive(struct ceph_connection *con);
 
+extern void ceph_msg_data_add_pages(struct ceph_msg *msg, struct page **pages,
+                               size_t length, size_t alignment);
+extern void ceph_msg_data_add_pagelist(struct ceph_msg *msg,
+                               struct ceph_pagelist *pagelist);
+#ifdef CONFIG_BLOCK
+extern void ceph_msg_data_add_bio(struct ceph_msg *msg, struct bio *bio,
+                               size_t length);
+#endif /* CONFIG_BLOCK */
+
 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);