Commit 2f9fd182607e7b3bdca35f6ed7f2fae539f7c46b

Authored by Fred Isaman
Committed by Trond Myklebust
1 parent 03341d2cc9

pnfsblock: call and parse getdevicelist

Call GETDEVICELIST during mount, then call and parse GETDEVICEINFO
for each device returned.

[pnfsblock: get rid of deprecated xdr macros]
Signed-off-by: Jim Rees <rees@umich.edu>
[pnfsblock: fix pnfs_deviceid references]
Signed-off-by: Fred Isaman <iisaman@citi.umich.edu>
[pnfsblock: fix print format warnings for sector_t and size_t]
[pnfs-block: #include <linux/vmalloc.h>]
[pnfsblock: no PNFS_NFS_SERVER]
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
[pnfsblock: fix bug determining size of striped volume]
[pnfsblock: fix oops when using multiple devices]
Signed-off-by: Fred Isaman <iisaman@citi.umich.edu>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
Signed-off-by: Benny Halevy <bhalevy@tonian.com>
[pnfsblock: get rid of vmap and deviceid->area structure]
Signed-off-by: Peng Tao <peng_tao@emc.com>
Signed-off-by: Jim Rees <rees@umich.edu>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

Showing 5 changed files with 158 additions and 8 deletions Side-by-side Diff

fs/nfs/blocklayout/blocklayout.c
... ... @@ -157,17 +157,153 @@
157 157 {
158 158 }
159 159  
  160 +static void free_blk_mountid(struct block_mount_id *mid)
  161 +{
  162 + if (mid) {
  163 + struct pnfs_block_dev *dev;
  164 + spin_lock(&mid->bm_lock);
  165 + while (!list_empty(&mid->bm_devlist)) {
  166 + dev = list_first_entry(&mid->bm_devlist,
  167 + struct pnfs_block_dev,
  168 + bm_node);
  169 + list_del(&dev->bm_node);
  170 + bl_free_block_dev(dev);
  171 + }
  172 + spin_unlock(&mid->bm_lock);
  173 + kfree(mid);
  174 + }
  175 +}
  176 +
  177 +/* This is mostly copied from the filelayout's get_device_info function.
  178 + * It seems much of this should be at the generic pnfs level.
  179 + */
  180 +static struct pnfs_block_dev *
  181 +nfs4_blk_get_deviceinfo(struct nfs_server *server, const struct nfs_fh *fh,
  182 + struct nfs4_deviceid *d_id)
  183 +{
  184 + struct pnfs_device *dev;
  185 + struct pnfs_block_dev *rv = NULL;
  186 + u32 max_resp_sz;
  187 + int max_pages;
  188 + struct page **pages = NULL;
  189 + int i, rc;
  190 +
  191 + /*
  192 + * Use the session max response size as the basis for setting
  193 + * GETDEVICEINFO's maxcount
  194 + */
  195 + max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
  196 + max_pages = max_resp_sz >> PAGE_SHIFT;
  197 + dprintk("%s max_resp_sz %u max_pages %d\n",
  198 + __func__, max_resp_sz, max_pages);
  199 +
  200 + dev = kmalloc(sizeof(*dev), GFP_NOFS);
  201 + if (!dev) {
  202 + dprintk("%s kmalloc failed\n", __func__);
  203 + return NULL;
  204 + }
  205 +
  206 + pages = kzalloc(max_pages * sizeof(struct page *), GFP_NOFS);
  207 + if (pages == NULL) {
  208 + kfree(dev);
  209 + return NULL;
  210 + }
  211 + for (i = 0; i < max_pages; i++) {
  212 + pages[i] = alloc_page(GFP_NOFS);
  213 + if (!pages[i])
  214 + goto out_free;
  215 + }
  216 +
  217 + memcpy(&dev->dev_id, d_id, sizeof(*d_id));
  218 + dev->layout_type = LAYOUT_BLOCK_VOLUME;
  219 + dev->pages = pages;
  220 + dev->pgbase = 0;
  221 + dev->pglen = PAGE_SIZE * max_pages;
  222 + dev->mincount = 0;
  223 +
  224 + dprintk("%s: dev_id: %s\n", __func__, dev->dev_id.data);
  225 + rc = nfs4_proc_getdeviceinfo(server, dev);
  226 + dprintk("%s getdevice info returns %d\n", __func__, rc);
  227 + if (rc)
  228 + goto out_free;
  229 +
  230 + rv = nfs4_blk_decode_device(server, dev);
  231 + out_free:
  232 + for (i = 0; i < max_pages; i++)
  233 + __free_page(pages[i]);
  234 + kfree(pages);
  235 + kfree(dev);
  236 + return rv;
  237 +}
  238 +
160 239 static int
161 240 bl_set_layoutdriver(struct nfs_server *server, const struct nfs_fh *fh)
162 241 {
  242 + struct block_mount_id *b_mt_id = NULL;
  243 + struct pnfs_devicelist *dlist = NULL;
  244 + struct pnfs_block_dev *bdev;
  245 + LIST_HEAD(block_disklist);
  246 + int status = 0, i;
  247 +
163 248 dprintk("%s enter\n", __func__);
164   - return 0;
  249 +
  250 + if (server->pnfs_blksize == 0) {
  251 + dprintk("%s Server did not return blksize\n", __func__);
  252 + return -EINVAL;
  253 + }
  254 + b_mt_id = kzalloc(sizeof(struct block_mount_id), GFP_NOFS);
  255 + if (!b_mt_id) {
  256 + status = -ENOMEM;
  257 + goto out_error;
  258 + }
  259 + /* Initialize nfs4 block layout mount id */
  260 + spin_lock_init(&b_mt_id->bm_lock);
  261 + INIT_LIST_HEAD(&b_mt_id->bm_devlist);
  262 +
  263 + dlist = kmalloc(sizeof(struct pnfs_devicelist), GFP_NOFS);
  264 + if (!dlist) {
  265 + status = -ENOMEM;
  266 + goto out_error;
  267 + }
  268 + dlist->eof = 0;
  269 + while (!dlist->eof) {
  270 + status = nfs4_proc_getdevicelist(server, fh, dlist);
  271 + if (status)
  272 + goto out_error;
  273 + dprintk("%s GETDEVICELIST numdevs=%i, eof=%i\n",
  274 + __func__, dlist->num_devs, dlist->eof);
  275 + for (i = 0; i < dlist->num_devs; i++) {
  276 + bdev = nfs4_blk_get_deviceinfo(server, fh,
  277 + &dlist->dev_id[i]);
  278 + if (!bdev) {
  279 + status = -ENODEV;
  280 + goto out_error;
  281 + }
  282 + spin_lock(&b_mt_id->bm_lock);
  283 + list_add(&bdev->bm_node, &b_mt_id->bm_devlist);
  284 + spin_unlock(&b_mt_id->bm_lock);
  285 + }
  286 + }
  287 + dprintk("%s SUCCESS\n", __func__);
  288 + server->pnfs_ld_data = b_mt_id;
  289 +
  290 + out_return:
  291 + kfree(dlist);
  292 + return status;
  293 +
  294 + out_error:
  295 + free_blk_mountid(b_mt_id);
  296 + goto out_return;
165 297 }
166 298  
167 299 static int
168 300 bl_clear_layoutdriver(struct nfs_server *server)
169 301 {
  302 + struct block_mount_id *b_mt_id = server->pnfs_ld_data;
  303 +
170 304 dprintk("%s enter\n", __func__);
  305 + free_blk_mountid(b_mt_id);
  306 + dprintk("%s RETURNS\n", __func__);
171 307 return 0;
172 308 }
173 309  
fs/nfs/blocklayout/blocklayout.h
... ... @@ -38,6 +38,11 @@
38 38  
39 39 #include "../pnfs.h"
40 40  
  41 +struct block_mount_id {
  42 + spinlock_t bm_lock; /* protects list */
  43 + struct list_head bm_devlist; /* holds pnfs_block_dev */
  44 +};
  45 +
41 46 struct pnfs_block_dev {
42 47 struct list_head bm_node;
43 48 struct nfs4_deviceid bm_mdevid; /* associated devid */
... ... @@ -99,7 +104,10 @@
99 104 sector_t bl_blocksize; /* Server blocksize in sectors */
100 105 };
101 106  
102   -static inline struct pnfs_block_layout *BLK_LO2EXT(struct pnfs_layout_hdr *lo)
  107 +#define BLK_ID(lo) ((struct block_mount_id *)(NFS_SERVER(lo->plh_inode)->pnfs_ld_data))
  108 +
  109 +static inline struct pnfs_block_layout *
  110 +BLK_LO2EXT(struct pnfs_layout_hdr *lo)
103 111 {
104 112 return container_of(lo, struct pnfs_block_layout, bl_layout);
105 113 }
... ... @@ -137,8 +145,7 @@
137 145 struct block_device *nfs4_blkdev_get(dev_t dev);
138 146 int nfs4_blkdev_put(struct block_device *bdev);
139 147 struct pnfs_block_dev *nfs4_blk_decode_device(struct nfs_server *server,
140   - struct pnfs_device *dev,
141   - struct list_head *sdlist);
  148 + struct pnfs_device *dev);
142 149 int nfs4_blk_process_layoutget(struct pnfs_layout_hdr *lo,
143 150 struct nfs4_layoutget_res *lgr, gfp_t gfp_flags);
144 151  
fs/nfs/blocklayout/blocklayoutdev.c
... ... @@ -116,8 +116,7 @@
116 116 */
117 117 struct pnfs_block_dev *
118 118 nfs4_blk_decode_device(struct nfs_server *server,
119   - struct pnfs_device *dev,
120   - struct list_head *sdlist)
  119 + struct pnfs_device *dev)
121 120 {
122 121 struct pnfs_block_dev *rv = NULL;
123 122 struct block_device *bd = NULL;
... ... @@ -129,6 +128,7 @@
129 128 uint8_t *dataptr;
130 129 DECLARE_WAITQUEUE(wq, current);
131 130 struct bl_dev_msg *reply = &bl_mount_reply;
  131 + int offset, len, i;
132 132  
133 133 dprintk("%s CREATING PIPEFS MESSAGE\n", __func__);
134 134 dprintk("%s: deviceid: %s, mincount: %d\n", __func__, dev->dev_id.data,
... ... @@ -143,7 +143,14 @@
143 143  
144 144 memcpy(msg.data, &bl_msg, sizeof(bl_msg));
145 145 dataptr = (uint8_t *) msg.data;
146   - memcpy(&dataptr[sizeof(bl_msg)], dev->area, dev->mincount);
  146 + len = dev->mincount;
  147 + offset = sizeof(bl_msg);
  148 + for (i = 0; len > 0; i++) {
  149 + memcpy(&dataptr[offset], page_address(dev->pages[i]),
  150 + len < PAGE_CACHE_SIZE ? len : PAGE_CACHE_SIZE);
  151 + len -= PAGE_CACHE_SIZE;
  152 + offset += PAGE_CACHE_SIZE;
  153 + }
147 154 msg.len = sizeof(bl_msg) + dev->mincount;
148 155  
149 156 dprintk("%s CALLING USERSPACE DAEMON\n", __func__);
... ... @@ -140,7 +140,6 @@
140 140 unsigned int layout_type;
141 141 unsigned int mincount;
142 142 struct page **pages;
143   - void *area;
144 143 unsigned int pgbase;
145 144 unsigned int pglen;
146 145 };
include/linux/nfs_fs_sb.h
... ... @@ -146,6 +146,7 @@
146 146 struct pnfs_layoutdriver_type *pnfs_curr_ld; /* Active layout driver */
147 147 struct rpc_wait_queue roc_rpcwaitq;
148 148 u32 pnfs_blksize; /* layout_blksize attr */
  149 + void *pnfs_ld_data; /* per mount point data */
149 150  
150 151 /* the following fields are protected by nfs_client->cl_lock */
151 152 struct rb_root state_owners;