linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sage Weil <sage@newdream.net>
To: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: Sage Weil <sage@newdream.net>
Subject: [PATCH 06/26] ceph: dynamic pagelist buffer
Date: Tue,  2 Mar 2010 16:46:37 -0800	[thread overview]
Message-ID: <1267577217-31923-7-git-send-email-sage@newdream.net> (raw)
In-Reply-To: <1267577217-31923-1-git-send-email-sage@newdream.net>

struct ceph_pagelist is a simple linked list of pages for encoding
data into.  Whole pages are allocated and added to the list as needed.
This is used for encoding large outgoing messages when the final
buffer size is known know ahead of time and we do not want to worry
about something like valloc failing due to fragmentation.

Signed-off-by: Sage Weil <sage@newdream.net>
---
 fs/ceph/pagelist.c |   54 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/ceph/pagelist.h |   54 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+), 0 deletions(-)
 create mode 100644 fs/ceph/pagelist.c
 create mode 100644 fs/ceph/pagelist.h

diff --git a/fs/ceph/pagelist.c b/fs/ceph/pagelist.c
new file mode 100644
index 0000000..370e936
--- /dev/null
+++ b/fs/ceph/pagelist.c
@@ -0,0 +1,54 @@
+
+#include <linux/pagemap.h>
+#include <linux/highmem.h>
+
+#include "pagelist.h"
+
+int ceph_pagelist_release(struct ceph_pagelist *pl)
+{
+	if (pl->mapped_tail)
+		kunmap(pl->mapped_tail);
+	while (!list_empty(&pl->head)) {
+		struct page *page = list_first_entry(&pl->head, struct page,
+						     lru);
+		list_del(&page->lru);
+		__free_page(page);
+	}
+	return 0;
+}
+
+static int ceph_pagelist_addpage(struct ceph_pagelist *pl)
+{
+	struct page *page = alloc_page(GFP_NOFS);
+	if (!page)
+		return -ENOMEM;
+	pl->room += PAGE_SIZE;
+	list_add_tail(&page->lru, &pl->head);
+	if (pl->mapped_tail)
+		kunmap(pl->mapped_tail);
+	pl->mapped_tail = kmap(page);
+	return 0;
+}
+
+int ceph_pagelist_append(struct ceph_pagelist *pl, void *buf, size_t len)
+{
+	while (pl->room < len) {
+		size_t bit = pl->room;
+		int ret;
+
+		memcpy(pl->mapped_tail + (pl->length & ~PAGE_CACHE_MASK),
+		       buf, bit);
+		pl->length += bit;
+		pl->room -= bit;
+		buf += bit;
+		len -= bit;
+		ret = ceph_pagelist_addpage(pl);
+		if (ret)
+			return ret;
+	}
+
+	memcpy(pl->mapped_tail + (pl->length & ~PAGE_CACHE_MASK), buf, len);
+	pl->length += len;
+	pl->room -= len;
+	return 0;
+}
diff --git a/fs/ceph/pagelist.h b/fs/ceph/pagelist.h
new file mode 100644
index 0000000..e8a4187
--- /dev/null
+++ b/fs/ceph/pagelist.h
@@ -0,0 +1,54 @@
+#ifndef __FS_CEPH_PAGELIST_H
+#define __FS_CEPH_PAGELIST_H
+
+#include <linux/list.h>
+
+struct ceph_pagelist {
+	struct list_head head;
+	void *mapped_tail;
+	size_t length;
+	size_t room;
+};
+
+static inline void ceph_pagelist_init(struct ceph_pagelist *pl)
+{
+	INIT_LIST_HEAD(&pl->head);
+	pl->mapped_tail = NULL;
+	pl->length = 0;
+	pl->room = 0;
+}
+extern int ceph_pagelist_release(struct ceph_pagelist *pl);
+
+extern int ceph_pagelist_append(struct ceph_pagelist *pl, void *d, size_t l);
+
+static inline int ceph_pagelist_encode_64(struct ceph_pagelist *pl, u64 v)
+{
+	__le64 ev = cpu_to_le64(v);
+	return ceph_pagelist_append(pl, &ev, sizeof(ev));
+}
+static inline int ceph_pagelist_encode_32(struct ceph_pagelist *pl, u32 v)
+{
+	__le32 ev = cpu_to_le32(v);
+	return ceph_pagelist_append(pl, &ev, sizeof(ev));
+}
+static inline int ceph_pagelist_encode_16(struct ceph_pagelist *pl, u16 v)
+{
+	__le16 ev = cpu_to_le16(v);
+	return ceph_pagelist_append(pl, &ev, sizeof(ev));
+}
+static inline int ceph_pagelist_encode_8(struct ceph_pagelist *pl, u8 v)
+{
+	return ceph_pagelist_append(pl, &v, 1);
+}
+static inline int ceph_pagelist_encode_string(struct ceph_pagelist *pl,
+					      char *s, size_t len)
+{
+	int ret = ceph_pagelist_encode_32(pl, len);
+	if (ret)
+		return ret;
+	if (len)
+		return ceph_pagelist_append(pl, s, len);
+	return 0;
+}
+
+#endif
-- 
1.7.0


  parent reply	other threads:[~2010-03-03  0:46 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-03-03  0:46 [PATCH 00/26] ceph distributed file system client Sage Weil
2010-03-03  0:46 ` [PATCH 01/26] ceph: documentation Sage Weil
2010-03-03  0:46 ` [PATCH 02/26] ceph: on-wire types Sage Weil
2010-03-03  0:46 ` [PATCH 03/26] ceph: client types Sage Weil
2010-03-03  0:46 ` [PATCH 04/26] ceph: hash function Sage Weil
2010-03-03  0:46 ` [PATCH 05/26] ceph: ref counted buffer Sage Weil
2010-03-03  0:46 ` Sage Weil [this message]
2010-03-03  0:46 ` [PATCH 07/26] ceph: super.c Sage Weil
2010-03-03  0:46 ` [PATCH 08/26] ceph: inode operations Sage Weil
2010-03-03  0:46 ` [PATCH 09/26] ceph: directory operations Sage Weil
2010-03-03  0:46 ` [PATCH 10/26] ceph: file operations Sage Weil
2010-03-03  0:46 ` [PATCH 11/26] ceph: address space operations Sage Weil
2010-03-03  0:46 ` [PATCH 12/26] ceph: MDS client Sage Weil
2010-03-03  0:46 ` [PATCH 13/26] ceph: OSD client Sage Weil
2010-03-03  0:46 ` [PATCH 14/26] ceph: CRUSH mapping algorithm Sage Weil
2010-03-03  0:46 ` [PATCH 15/26] ceph: monitor client Sage Weil
2010-03-03  0:46 ` [PATCH 16/26] ceph: authentication interface Sage Weil
2010-03-03  0:46 ` [PATCH 17/26] ceph: trivial 'auth_none' authentication scheme Sage Weil
2010-03-03  0:46 ` [PATCH 18/26] ceph: 'auth_x' " Sage Weil
2010-03-03  0:46 ` [PATCH 19/26] ceph: capability management Sage Weil
2010-03-03  0:46 ` [PATCH 20/26] ceph: snapshot management Sage Weil
2010-03-03  0:46 ` [PATCH 21/26] ceph: messenger library Sage Weil
2010-03-03  0:46 ` [PATCH 22/26] ceph: message pools Sage Weil
2010-03-03  0:46 ` [PATCH 23/26] ceph: nfs re-export support Sage Weil
2010-03-03  7:48   ` Christoph Hellwig
2010-03-03 21:37     ` Sage Weil
2010-03-04 11:50       ` Miklos Szeredi
2010-03-03  0:46 ` [PATCH 24/26] ceph: ioctls Sage Weil
2010-03-03  0:46 ` [PATCH 25/26] ceph: debugfs Sage Weil
2010-03-03  0:46 ` [PATCH 26/26] ceph: Kconfig, Makefile, MAINTAINERS entry Sage Weil

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1267577217-31923-7-git-send-email-sage@newdream.net \
    --to=sage@newdream.net \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).