}
        kfree(req->r_path1);
        kfree(req->r_path2);
+       if (req->r_pagelist)
+               ceph_pagelist_release(req->r_pagelist);
        put_request_session(req);
        ceph_unreserve_caps(req->r_mdsc, &req->r_caps_reservation);
        kfree(req);
        msg->front.iov_len = p - msg->front.iov_base;
        msg->hdr.front_len = cpu_to_le32(msg->front.iov_len);
 
-       if (req->r_data_len) {
-               /* outbound data set only by ceph_sync_setxattr() */
-               BUG_ON(!req->r_pages);
-               ceph_msg_data_add_pages(msg, req->r_pages, req->r_data_len, 0);
+       if (req->r_pagelist) {
+               struct ceph_pagelist *pagelist = req->r_pagelist;
+               atomic_inc(&pagelist->refcnt);
+               ceph_msg_data_add_pagelist(msg, pagelist);
+               msg->hdr.data_len = cpu_to_le32(pagelist->length);
+       } else {
+               msg->hdr.data_len = 0;
        }
 
-       msg->hdr.data_len = cpu_to_le32(req->r_data_len);
        msg->hdr.data_off = cpu_to_le16(0);
 
 out_free2:
 
 #include <linux/ceph/ceph_debug.h>
+#include <linux/ceph/pagelist.h>
 
 #include "super.h"
 #include "mds_client.h"
        struct ceph_inode_info *ci = ceph_inode(inode);
        struct ceph_mds_request *req;
        struct ceph_mds_client *mdsc = fsc->mdsc;
+       struct ceph_pagelist *pagelist = NULL;
        int err;
-       int i, nr_pages;
-       struct page **pages = NULL;
-       void *kaddr;
-
-       /* copy value into some pages */
-       nr_pages = calc_pages_for(0, size);
-       if (nr_pages) {
-               pages = kmalloc(sizeof(pages[0])*nr_pages, GFP_NOFS);
-               if (!pages)
+
+       if (value) {
+               /* copy value into pagelist */
+               pagelist = kmalloc(sizeof(*pagelist), GFP_NOFS);
+               if (!pagelist)
                        return -ENOMEM;
-               err = -ENOMEM;
-               for (i = 0; i < nr_pages; i++) {
-                       pages[i] = __page_cache_alloc(GFP_NOFS);
-                       if (!pages[i]) {
-                               nr_pages = i;
-                               goto out;
-                       }
-                       kaddr = kmap(pages[i]);
-                       memcpy(kaddr, value + i*PAGE_CACHE_SIZE,
-                              min(PAGE_CACHE_SIZE, size-i*PAGE_CACHE_SIZE));
-               }
+
+               ceph_pagelist_init(pagelist);
+               err = ceph_pagelist_append(pagelist, value, size);
+               if (err)
+                       goto out;
+       } else {
+               flags |= CEPH_XATTR_REMOVE;
        }
 
        dout("setxattr value=%.*s\n", (int)size, value);
 
-       if (!value)
-               flags |= CEPH_XATTR_REMOVE;
-
        /* do request */
        req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETXATTR,
                                       USE_AUTH_MDS);
        req->r_args.setxattr.flags = cpu_to_le32(flags);
        req->r_path2 = kstrdup(name, GFP_NOFS);
 
-       req->r_pages = pages;
-       req->r_num_pages = nr_pages;
-       req->r_data_len = size;
+       req->r_pagelist = pagelist;
+       pagelist = NULL;
 
        dout("xattr.ver (before): %lld\n", ci->i_xattrs.version);
        err = ceph_mdsc_do_request(mdsc, NULL, req);
        dout("xattr.ver (after): %lld\n", ci->i_xattrs.version);
 
 out:
-       if (pages) {
-               for (i = 0; i < nr_pages; i++)
-                       __free_page(pages[i]);
-               kfree(pages);
-       }
+       if (pagelist)
+               ceph_pagelist_release(pagelist);
        return err;
 }