at v3.17 704 lines 19 kB view raw
1/* 2 * pNFS Objects layout implementation over open-osd initiator library 3 * 4 * Copyright (C) 2009 Panasas Inc. [year of first publication] 5 * All rights reserved. 6 * 7 * Benny Halevy <bhalevy@panasas.com> 8 * Boaz Harrosh <bharrosh@panasas.com> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 12 * See the file COPYING included with this distribution for more details. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 18 * 1. Redistributions of source code must retain the above copyright 19 * notice, this list of conditions and the following disclaimer. 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in the 22 * documentation and/or other materials provided with the distribution. 23 * 3. Neither the name of the Panasas company nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 28 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 29 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 30 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 34 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 35 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 36 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 37 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40#include <linux/module.h> 41#include <scsi/osd_ore.h> 42 43#include "objlayout.h" 44#include "../internal.h" 45 46#define NFSDBG_FACILITY NFSDBG_PNFS_LD 47 48struct objio_dev_ent { 49 struct nfs4_deviceid_node id_node; 50 struct ore_dev od; 51}; 52 53static void 54objio_free_deviceid_node(struct nfs4_deviceid_node *d) 55{ 56 struct objio_dev_ent *de = container_of(d, struct objio_dev_ent, id_node); 57 58 dprintk("%s: free od=%p\n", __func__, de->od.od); 59 osduld_put_device(de->od.od); 60 kfree(de); 61} 62 63static struct objio_dev_ent *_dev_list_find(const struct nfs_server *nfss, 64 const struct nfs4_deviceid *d_id) 65{ 66 struct nfs4_deviceid_node *d; 67 struct objio_dev_ent *de; 68 69 d = nfs4_find_get_deviceid(nfss->pnfs_curr_ld, nfss->nfs_client, d_id); 70 if (!d) 71 return NULL; 72 73 de = container_of(d, struct objio_dev_ent, id_node); 74 return de; 75} 76 77static struct objio_dev_ent * 78_dev_list_add(const struct nfs_server *nfss, 79 const struct nfs4_deviceid *d_id, struct osd_dev *od, 80 gfp_t gfp_flags) 81{ 82 struct nfs4_deviceid_node *d; 83 struct objio_dev_ent *de = kzalloc(sizeof(*de), gfp_flags); 84 struct objio_dev_ent *n; 85 86 if (!de) { 87 dprintk("%s: -ENOMEM od=%p\n", __func__, od); 88 return NULL; 89 } 90 91 dprintk("%s: Adding od=%p\n", __func__, od); 92 nfs4_init_deviceid_node(&de->id_node, 93 nfss->pnfs_curr_ld, 94 nfss->nfs_client, 95 d_id); 96 de->od.od = od; 97 98 d = nfs4_insert_deviceid_node(&de->id_node); 99 n = container_of(d, struct objio_dev_ent, id_node); 100 if (n != de) { 101 dprintk("%s: Race with other n->od=%p\n", __func__, n->od.od); 102 objio_free_deviceid_node(&de->id_node); 103 de = n; 104 } 105 106 return de; 107} 108 109struct objio_segment { 110 struct pnfs_layout_segment lseg; 111 112 struct ore_layout layout; 113 struct ore_components oc; 114}; 115 116static inline struct objio_segment * 117OBJIO_LSEG(struct pnfs_layout_segment *lseg) 118{ 119 return container_of(lseg, struct objio_segment, lseg); 120} 121 122struct objio_state { 123 /* Generic layer */ 124 struct objlayout_io_res oir; 125 126 bool sync; 127 /*FIXME: Support for extra_bytes at ore_get_rw_state() */ 128 struct ore_io_state *ios; 129}; 130 131/* Send and wait for a get_device_info of devices in the layout, 132 then look them up with the osd_initiator library */ 133static int objio_devices_lookup(struct pnfs_layout_hdr *pnfslay, 134 struct objio_segment *objio_seg, unsigned c, struct nfs4_deviceid *d_id, 135 gfp_t gfp_flags) 136{ 137 struct pnfs_osd_deviceaddr *deviceaddr; 138 struct objio_dev_ent *ode; 139 struct osd_dev *od; 140 struct osd_dev_info odi; 141 bool retry_flag = true; 142 int err; 143 144 ode = _dev_list_find(NFS_SERVER(pnfslay->plh_inode), d_id); 145 if (ode) { 146 objio_seg->oc.ods[c] = &ode->od; /* must use container_of */ 147 return 0; 148 } 149 150 err = objlayout_get_deviceinfo(pnfslay, d_id, &deviceaddr, gfp_flags); 151 if (unlikely(err)) { 152 dprintk("%s: objlayout_get_deviceinfo dev(%llx:%llx) =>%d\n", 153 __func__, _DEVID_LO(d_id), _DEVID_HI(d_id), err); 154 return err; 155 } 156 157 odi.systemid_len = deviceaddr->oda_systemid.len; 158 if (odi.systemid_len > sizeof(odi.systemid)) { 159 dprintk("%s: odi.systemid_len > sizeof(systemid=%zd)\n", 160 __func__, sizeof(odi.systemid)); 161 err = -EINVAL; 162 goto out; 163 } else if (odi.systemid_len) 164 memcpy(odi.systemid, deviceaddr->oda_systemid.data, 165 odi.systemid_len); 166 odi.osdname_len = deviceaddr->oda_osdname.len; 167 odi.osdname = (u8 *)deviceaddr->oda_osdname.data; 168 169 if (!odi.osdname_len && !odi.systemid_len) { 170 dprintk("%s: !odi.osdname_len && !odi.systemid_len\n", 171 __func__); 172 err = -ENODEV; 173 goto out; 174 } 175 176retry_lookup: 177 od = osduld_info_lookup(&odi); 178 if (unlikely(IS_ERR(od))) { 179 err = PTR_ERR(od); 180 dprintk("%s: osduld_info_lookup => %d\n", __func__, err); 181 if (err == -ENODEV && retry_flag) { 182 err = objlayout_autologin(deviceaddr); 183 if (likely(!err)) { 184 retry_flag = false; 185 goto retry_lookup; 186 } 187 } 188 goto out; 189 } 190 191 ode = _dev_list_add(NFS_SERVER(pnfslay->plh_inode), d_id, od, 192 gfp_flags); 193 objio_seg->oc.ods[c] = &ode->od; /* must use container_of */ 194 dprintk("Adding new dev_id(%llx:%llx)\n", 195 _DEVID_LO(d_id), _DEVID_HI(d_id)); 196out: 197 objlayout_put_deviceinfo(deviceaddr); 198 return err; 199} 200 201static void copy_single_comp(struct ore_components *oc, unsigned c, 202 struct pnfs_osd_object_cred *src_comp) 203{ 204 struct ore_comp *ocomp = &oc->comps[c]; 205 206 WARN_ON(src_comp->oc_cap_key.cred_len > 0); /* libosd is NO_SEC only */ 207 WARN_ON(src_comp->oc_cap.cred_len > sizeof(ocomp->cred)); 208 209 ocomp->obj.partition = src_comp->oc_object_id.oid_partition_id; 210 ocomp->obj.id = src_comp->oc_object_id.oid_object_id; 211 212 memcpy(ocomp->cred, src_comp->oc_cap.cred, sizeof(ocomp->cred)); 213} 214 215static int __alloc_objio_seg(unsigned numdevs, gfp_t gfp_flags, 216 struct objio_segment **pseg) 217{ 218/* This is the in memory structure of the objio_segment 219 * 220 * struct __alloc_objio_segment { 221 * struct objio_segment olseg; 222 * struct ore_dev *ods[numdevs]; 223 * struct ore_comp comps[numdevs]; 224 * } *aolseg; 225 * NOTE: The code as above compiles and runs perfectly. It is elegant, 226 * type safe and compact. At some Past time Linus has decided he does not 227 * like variable length arrays, For the sake of this principal we uglify 228 * the code as below. 229 */ 230 struct objio_segment *lseg; 231 size_t lseg_size = sizeof(*lseg) + 232 numdevs * sizeof(lseg->oc.ods[0]) + 233 numdevs * sizeof(*lseg->oc.comps); 234 235 lseg = kzalloc(lseg_size, gfp_flags); 236 if (unlikely(!lseg)) { 237 dprintk("%s: Failed allocation numdevs=%d size=%zd\n", __func__, 238 numdevs, lseg_size); 239 return -ENOMEM; 240 } 241 242 lseg->oc.numdevs = numdevs; 243 lseg->oc.single_comp = EC_MULTPLE_COMPS; 244 lseg->oc.ods = (void *)(lseg + 1); 245 lseg->oc.comps = (void *)(lseg->oc.ods + numdevs); 246 247 *pseg = lseg; 248 return 0; 249} 250 251int objio_alloc_lseg(struct pnfs_layout_segment **outp, 252 struct pnfs_layout_hdr *pnfslay, 253 struct pnfs_layout_range *range, 254 struct xdr_stream *xdr, 255 gfp_t gfp_flags) 256{ 257 struct objio_segment *objio_seg; 258 struct pnfs_osd_xdr_decode_layout_iter iter; 259 struct pnfs_osd_layout layout; 260 struct pnfs_osd_object_cred src_comp; 261 unsigned cur_comp; 262 int err; 263 264 err = pnfs_osd_xdr_decode_layout_map(&layout, &iter, xdr); 265 if (unlikely(err)) 266 return err; 267 268 err = __alloc_objio_seg(layout.olo_num_comps, gfp_flags, &objio_seg); 269 if (unlikely(err)) 270 return err; 271 272 objio_seg->layout.stripe_unit = layout.olo_map.odm_stripe_unit; 273 objio_seg->layout.group_width = layout.olo_map.odm_group_width; 274 objio_seg->layout.group_depth = layout.olo_map.odm_group_depth; 275 objio_seg->layout.mirrors_p1 = layout.olo_map.odm_mirror_cnt + 1; 276 objio_seg->layout.raid_algorithm = layout.olo_map.odm_raid_algorithm; 277 278 err = ore_verify_layout(layout.olo_map.odm_num_comps, 279 &objio_seg->layout); 280 if (unlikely(err)) 281 goto err; 282 283 objio_seg->oc.first_dev = layout.olo_comps_index; 284 cur_comp = 0; 285 while (pnfs_osd_xdr_decode_layout_comp(&src_comp, &iter, xdr, &err)) { 286 copy_single_comp(&objio_seg->oc, cur_comp, &src_comp); 287 err = objio_devices_lookup(pnfslay, objio_seg, cur_comp, 288 &src_comp.oc_object_id.oid_device_id, 289 gfp_flags); 290 if (err) 291 goto err; 292 ++cur_comp; 293 } 294 /* pnfs_osd_xdr_decode_layout_comp returns false on error */ 295 if (unlikely(err)) 296 goto err; 297 298 *outp = &objio_seg->lseg; 299 return 0; 300 301err: 302 kfree(objio_seg); 303 dprintk("%s: Error: return %d\n", __func__, err); 304 *outp = NULL; 305 return err; 306} 307 308void objio_free_lseg(struct pnfs_layout_segment *lseg) 309{ 310 int i; 311 struct objio_segment *objio_seg = OBJIO_LSEG(lseg); 312 313 for (i = 0; i < objio_seg->oc.numdevs; i++) { 314 struct ore_dev *od = objio_seg->oc.ods[i]; 315 struct objio_dev_ent *ode; 316 317 if (!od) 318 break; 319 ode = container_of(od, typeof(*ode), od); 320 nfs4_put_deviceid_node(&ode->id_node); 321 } 322 kfree(objio_seg); 323} 324 325static int 326objio_alloc_io_state(struct pnfs_layout_hdr *pnfs_layout_type, bool is_reading, 327 struct pnfs_layout_segment *lseg, struct page **pages, unsigned pgbase, 328 loff_t offset, size_t count, void *rpcdata, gfp_t gfp_flags, 329 struct objio_state **outp) 330{ 331 struct objio_segment *objio_seg = OBJIO_LSEG(lseg); 332 struct ore_io_state *ios; 333 int ret; 334 struct __alloc_objio_state { 335 struct objio_state objios; 336 struct pnfs_osd_ioerr ioerrs[objio_seg->oc.numdevs]; 337 } *aos; 338 339 aos = kzalloc(sizeof(*aos), gfp_flags); 340 if (unlikely(!aos)) 341 return -ENOMEM; 342 343 objlayout_init_ioerrs(&aos->objios.oir, objio_seg->oc.numdevs, 344 aos->ioerrs, rpcdata, pnfs_layout_type); 345 346 ret = ore_get_rw_state(&objio_seg->layout, &objio_seg->oc, is_reading, 347 offset, count, &ios); 348 if (unlikely(ret)) { 349 kfree(aos); 350 return ret; 351 } 352 353 ios->pages = pages; 354 ios->pgbase = pgbase; 355 ios->private = aos; 356 BUG_ON(ios->nr_pages > (pgbase + count + PAGE_SIZE - 1) >> PAGE_SHIFT); 357 358 aos->objios.sync = 0; 359 aos->objios.ios = ios; 360 *outp = &aos->objios; 361 return 0; 362} 363 364void objio_free_result(struct objlayout_io_res *oir) 365{ 366 struct objio_state *objios = container_of(oir, struct objio_state, oir); 367 368 ore_put_io_state(objios->ios); 369 kfree(objios); 370} 371 372static enum pnfs_osd_errno osd_pri_2_pnfs_err(enum osd_err_priority oep) 373{ 374 switch (oep) { 375 case OSD_ERR_PRI_NO_ERROR: 376 return (enum pnfs_osd_errno)0; 377 378 case OSD_ERR_PRI_CLEAR_PAGES: 379 BUG_ON(1); 380 return 0; 381 382 case OSD_ERR_PRI_RESOURCE: 383 return PNFS_OSD_ERR_RESOURCE; 384 case OSD_ERR_PRI_BAD_CRED: 385 return PNFS_OSD_ERR_BAD_CRED; 386 case OSD_ERR_PRI_NO_ACCESS: 387 return PNFS_OSD_ERR_NO_ACCESS; 388 case OSD_ERR_PRI_UNREACHABLE: 389 return PNFS_OSD_ERR_UNREACHABLE; 390 case OSD_ERR_PRI_NOT_FOUND: 391 return PNFS_OSD_ERR_NOT_FOUND; 392 case OSD_ERR_PRI_NO_SPACE: 393 return PNFS_OSD_ERR_NO_SPACE; 394 default: 395 WARN_ON(1); 396 /* fallthrough */ 397 case OSD_ERR_PRI_EIO: 398 return PNFS_OSD_ERR_EIO; 399 } 400} 401 402static void __on_dev_error(struct ore_io_state *ios, 403 struct ore_dev *od, unsigned dev_index, enum osd_err_priority oep, 404 u64 dev_offset, u64 dev_len) 405{ 406 struct objio_state *objios = ios->private; 407 struct pnfs_osd_objid pooid; 408 struct objio_dev_ent *ode = container_of(od, typeof(*ode), od); 409 /* FIXME: what to do with more-then-one-group layouts. We need to 410 * translate from ore_io_state index to oc->comps index 411 */ 412 unsigned comp = dev_index; 413 414 pooid.oid_device_id = ode->id_node.deviceid; 415 pooid.oid_partition_id = ios->oc->comps[comp].obj.partition; 416 pooid.oid_object_id = ios->oc->comps[comp].obj.id; 417 418 objlayout_io_set_result(&objios->oir, comp, 419 &pooid, osd_pri_2_pnfs_err(oep), 420 dev_offset, dev_len, !ios->reading); 421} 422 423/* 424 * read 425 */ 426static void _read_done(struct ore_io_state *ios, void *private) 427{ 428 struct objio_state *objios = private; 429 ssize_t status; 430 int ret = ore_check_io(ios, &__on_dev_error); 431 432 /* FIXME: _io_free(ios) can we dealocate the libosd resources; */ 433 434 if (likely(!ret)) 435 status = ios->length; 436 else 437 status = ret; 438 439 objlayout_read_done(&objios->oir, status, objios->sync); 440} 441 442int objio_read_pagelist(struct nfs_pgio_header *hdr) 443{ 444 struct objio_state *objios; 445 int ret; 446 447 ret = objio_alloc_io_state(NFS_I(hdr->inode)->layout, true, 448 hdr->lseg, hdr->args.pages, hdr->args.pgbase, 449 hdr->args.offset, hdr->args.count, hdr, 450 GFP_KERNEL, &objios); 451 if (unlikely(ret)) 452 return ret; 453 454 objios->ios->done = _read_done; 455 dprintk("%s: offset=0x%llx length=0x%x\n", __func__, 456 hdr->args.offset, hdr->args.count); 457 ret = ore_read(objios->ios); 458 if (unlikely(ret)) 459 objio_free_result(&objios->oir); 460 return ret; 461} 462 463/* 464 * write 465 */ 466static void _write_done(struct ore_io_state *ios, void *private) 467{ 468 struct objio_state *objios = private; 469 ssize_t status; 470 int ret = ore_check_io(ios, &__on_dev_error); 471 472 /* FIXME: _io_free(ios) can we dealocate the libosd resources; */ 473 474 if (likely(!ret)) { 475 /* FIXME: should be based on the OSD's persistence model 476 * See OSD2r05 Section 4.13 Data persistence model */ 477 objios->oir.committed = NFS_FILE_SYNC; 478 status = ios->length; 479 } else { 480 status = ret; 481 } 482 483 objlayout_write_done(&objios->oir, status, objios->sync); 484} 485 486static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate) 487{ 488 struct objio_state *objios = priv; 489 struct nfs_pgio_header *hdr = objios->oir.rpcdata; 490 struct address_space *mapping = hdr->inode->i_mapping; 491 pgoff_t index = offset / PAGE_SIZE; 492 struct page *page; 493 loff_t i_size = i_size_read(hdr->inode); 494 495 if (offset >= i_size) { 496 *uptodate = true; 497 dprintk("%s: g_zero_page index=0x%lx\n", __func__, index); 498 return ZERO_PAGE(0); 499 } 500 501 page = find_get_page(mapping, index); 502 if (!page) { 503 page = find_or_create_page(mapping, index, GFP_NOFS); 504 if (unlikely(!page)) { 505 dprintk("%s: grab_cache_page Failed index=0x%lx\n", 506 __func__, index); 507 return NULL; 508 } 509 unlock_page(page); 510 } 511 if (PageDirty(page) || PageWriteback(page)) 512 *uptodate = true; 513 else 514 *uptodate = PageUptodate(page); 515 dprintk("%s: index=0x%lx uptodate=%d\n", __func__, index, *uptodate); 516 return page; 517} 518 519static void __r4w_put_page(void *priv, struct page *page) 520{ 521 dprintk("%s: index=0x%lx\n", __func__, 522 (page == ZERO_PAGE(0)) ? -1UL : page->index); 523 if (ZERO_PAGE(0) != page) 524 page_cache_release(page); 525 return; 526} 527 528static const struct _ore_r4w_op _r4w_op = { 529 .get_page = &__r4w_get_page, 530 .put_page = &__r4w_put_page, 531}; 532 533int objio_write_pagelist(struct nfs_pgio_header *hdr, int how) 534{ 535 struct objio_state *objios; 536 int ret; 537 538 ret = objio_alloc_io_state(NFS_I(hdr->inode)->layout, false, 539 hdr->lseg, hdr->args.pages, hdr->args.pgbase, 540 hdr->args.offset, hdr->args.count, hdr, GFP_NOFS, 541 &objios); 542 if (unlikely(ret)) 543 return ret; 544 545 objios->sync = 0 != (how & FLUSH_SYNC); 546 objios->ios->r4w = &_r4w_op; 547 548 if (!objios->sync) 549 objios->ios->done = _write_done; 550 551 dprintk("%s: offset=0x%llx length=0x%x\n", __func__, 552 hdr->args.offset, hdr->args.count); 553 ret = ore_write(objios->ios); 554 if (unlikely(ret)) { 555 objio_free_result(&objios->oir); 556 return ret; 557 } 558 559 if (objios->sync) 560 _write_done(objios->ios, objios); 561 562 return 0; 563} 564 565/* 566 * Return 0 if @req cannot be coalesced into @pgio, otherwise return the number 567 * of bytes (maximum @req->wb_bytes) that can be coalesced. 568 */ 569static size_t objio_pg_test(struct nfs_pageio_descriptor *pgio, 570 struct nfs_page *prev, struct nfs_page *req) 571{ 572 unsigned int size; 573 574 size = pnfs_generic_pg_test(pgio, prev, req); 575 576 if (!size || pgio->pg_count + req->wb_bytes > 577 (unsigned long)pgio->pg_layout_private) 578 return 0; 579 580 return min(size, req->wb_bytes); 581} 582 583static void objio_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) 584{ 585 pnfs_generic_pg_init_read(pgio, req); 586 if (unlikely(pgio->pg_lseg == NULL)) 587 return; /* Not pNFS */ 588 589 pgio->pg_layout_private = (void *) 590 OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length; 591} 592 593static bool aligned_on_raid_stripe(u64 offset, struct ore_layout *layout, 594 unsigned long *stripe_end) 595{ 596 u32 stripe_off; 597 unsigned stripe_size; 598 599 if (layout->raid_algorithm == PNFS_OSD_RAID_0) 600 return true; 601 602 stripe_size = layout->stripe_unit * 603 (layout->group_width - layout->parity); 604 605 div_u64_rem(offset, stripe_size, &stripe_off); 606 if (!stripe_off) 607 return true; 608 609 *stripe_end = stripe_size - stripe_off; 610 return false; 611} 612 613static void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) 614{ 615 unsigned long stripe_end = 0; 616 u64 wb_size; 617 618 if (pgio->pg_dreq == NULL) 619 wb_size = i_size_read(pgio->pg_inode) - req_offset(req); 620 else 621 wb_size = nfs_dreq_bytes_left(pgio->pg_dreq); 622 623 pnfs_generic_pg_init_write(pgio, req, wb_size); 624 if (unlikely(pgio->pg_lseg == NULL)) 625 return; /* Not pNFS */ 626 627 if (req->wb_offset || 628 !aligned_on_raid_stripe(req->wb_index * PAGE_SIZE, 629 &OBJIO_LSEG(pgio->pg_lseg)->layout, 630 &stripe_end)) { 631 pgio->pg_layout_private = (void *)stripe_end; 632 } else { 633 pgio->pg_layout_private = (void *) 634 OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length; 635 } 636} 637 638static const struct nfs_pageio_ops objio_pg_read_ops = { 639 .pg_init = objio_init_read, 640 .pg_test = objio_pg_test, 641 .pg_doio = pnfs_generic_pg_readpages, 642}; 643 644static const struct nfs_pageio_ops objio_pg_write_ops = { 645 .pg_init = objio_init_write, 646 .pg_test = objio_pg_test, 647 .pg_doio = pnfs_generic_pg_writepages, 648}; 649 650static struct pnfs_layoutdriver_type objlayout_type = { 651 .id = LAYOUT_OSD2_OBJECTS, 652 .name = "LAYOUT_OSD2_OBJECTS", 653 .flags = PNFS_LAYOUTRET_ON_SETATTR | 654 PNFS_LAYOUTRET_ON_ERROR, 655 656 .owner = THIS_MODULE, 657 .alloc_layout_hdr = objlayout_alloc_layout_hdr, 658 .free_layout_hdr = objlayout_free_layout_hdr, 659 660 .alloc_lseg = objlayout_alloc_lseg, 661 .free_lseg = objlayout_free_lseg, 662 663 .read_pagelist = objlayout_read_pagelist, 664 .write_pagelist = objlayout_write_pagelist, 665 .pg_read_ops = &objio_pg_read_ops, 666 .pg_write_ops = &objio_pg_write_ops, 667 668 .free_deviceid_node = objio_free_deviceid_node, 669 670 .encode_layoutcommit = objlayout_encode_layoutcommit, 671 .encode_layoutreturn = objlayout_encode_layoutreturn, 672}; 673 674MODULE_DESCRIPTION("pNFS Layout Driver for OSD2 objects"); 675MODULE_AUTHOR("Benny Halevy <bhalevy@panasas.com>"); 676MODULE_LICENSE("GPL"); 677 678static int __init 679objlayout_init(void) 680{ 681 int ret = pnfs_register_layoutdriver(&objlayout_type); 682 683 if (ret) 684 printk(KERN_INFO 685 "NFS: %s: Registering OSD pNFS Layout Driver failed: error=%d\n", 686 __func__, ret); 687 else 688 printk(KERN_INFO "NFS: %s: Registered OSD pNFS Layout Driver\n", 689 __func__); 690 return ret; 691} 692 693static void __exit 694objlayout_exit(void) 695{ 696 pnfs_unregister_layoutdriver(&objlayout_type); 697 printk(KERN_INFO "NFS: %s: Unregistered OSD pNFS Layout Driver\n", 698 __func__); 699} 700 701MODULE_ALIAS("nfs-layouttype4-2"); 702 703module_init(objlayout_init); 704module_exit(objlayout_exit);