at v3.11 698 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_read_data *rdata) 443{ 444 struct nfs_pgio_header *hdr = rdata->header; 445 struct objio_state *objios; 446 int ret; 447 448 ret = objio_alloc_io_state(NFS_I(hdr->inode)->layout, true, 449 hdr->lseg, rdata->args.pages, rdata->args.pgbase, 450 rdata->args.offset, rdata->args.count, rdata, 451 GFP_KERNEL, &objios); 452 if (unlikely(ret)) 453 return ret; 454 455 objios->ios->done = _read_done; 456 dprintk("%s: offset=0x%llx length=0x%x\n", __func__, 457 rdata->args.offset, rdata->args.count); 458 ret = ore_read(objios->ios); 459 if (unlikely(ret)) 460 objio_free_result(&objios->oir); 461 return ret; 462} 463 464/* 465 * write 466 */ 467static void _write_done(struct ore_io_state *ios, void *private) 468{ 469 struct objio_state *objios = private; 470 ssize_t status; 471 int ret = ore_check_io(ios, &__on_dev_error); 472 473 /* FIXME: _io_free(ios) can we dealocate the libosd resources; */ 474 475 if (likely(!ret)) { 476 /* FIXME: should be based on the OSD's persistence model 477 * See OSD2r05 Section 4.13 Data persistence model */ 478 objios->oir.committed = NFS_FILE_SYNC; 479 status = ios->length; 480 } else { 481 status = ret; 482 } 483 484 objlayout_write_done(&objios->oir, status, objios->sync); 485} 486 487static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate) 488{ 489 struct objio_state *objios = priv; 490 struct nfs_write_data *wdata = objios->oir.rpcdata; 491 struct address_space *mapping = wdata->header->inode->i_mapping; 492 pgoff_t index = offset / PAGE_SIZE; 493 struct page *page; 494 loff_t i_size = i_size_read(wdata->header->inode); 495 496 if (offset >= i_size) { 497 *uptodate = true; 498 dprintk("%s: g_zero_page index=0x%lx\n", __func__, index); 499 return ZERO_PAGE(0); 500 } 501 502 page = find_get_page(mapping, index); 503 if (!page) { 504 page = find_or_create_page(mapping, index, GFP_NOFS); 505 if (unlikely(!page)) { 506 dprintk("%s: grab_cache_page Failed index=0x%lx\n", 507 __func__, index); 508 return NULL; 509 } 510 unlock_page(page); 511 } 512 if (PageDirty(page) || PageWriteback(page)) 513 *uptodate = true; 514 else 515 *uptodate = PageUptodate(page); 516 dprintk("%s: index=0x%lx uptodate=%d\n", __func__, index, *uptodate); 517 return page; 518} 519 520static void __r4w_put_page(void *priv, struct page *page) 521{ 522 dprintk("%s: index=0x%lx\n", __func__, 523 (page == ZERO_PAGE(0)) ? -1UL : page->index); 524 if (ZERO_PAGE(0) != page) 525 page_cache_release(page); 526 return; 527} 528 529static const struct _ore_r4w_op _r4w_op = { 530 .get_page = &__r4w_get_page, 531 .put_page = &__r4w_put_page, 532}; 533 534int objio_write_pagelist(struct nfs_write_data *wdata, int how) 535{ 536 struct nfs_pgio_header *hdr = wdata->header; 537 struct objio_state *objios; 538 int ret; 539 540 ret = objio_alloc_io_state(NFS_I(hdr->inode)->layout, false, 541 hdr->lseg, wdata->args.pages, wdata->args.pgbase, 542 wdata->args.offset, wdata->args.count, wdata, GFP_NOFS, 543 &objios); 544 if (unlikely(ret)) 545 return ret; 546 547 objios->sync = 0 != (how & FLUSH_SYNC); 548 objios->ios->r4w = &_r4w_op; 549 550 if (!objios->sync) 551 objios->ios->done = _write_done; 552 553 dprintk("%s: offset=0x%llx length=0x%x\n", __func__, 554 wdata->args.offset, wdata->args.count); 555 ret = ore_write(objios->ios); 556 if (unlikely(ret)) { 557 objio_free_result(&objios->oir); 558 return ret; 559 } 560 561 if (objios->sync) 562 _write_done(objios->ios, objios); 563 564 return 0; 565} 566 567static bool objio_pg_test(struct nfs_pageio_descriptor *pgio, 568 struct nfs_page *prev, struct nfs_page *req) 569{ 570 if (!pnfs_generic_pg_test(pgio, prev, req)) 571 return false; 572 573 return pgio->pg_count + req->wb_bytes <= 574 (unsigned long)pgio->pg_layout_private; 575} 576 577static void objio_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) 578{ 579 pnfs_generic_pg_init_read(pgio, req); 580 if (unlikely(pgio->pg_lseg == NULL)) 581 return; /* Not pNFS */ 582 583 pgio->pg_layout_private = (void *) 584 OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length; 585} 586 587static bool aligned_on_raid_stripe(u64 offset, struct ore_layout *layout, 588 unsigned long *stripe_end) 589{ 590 u32 stripe_off; 591 unsigned stripe_size; 592 593 if (layout->raid_algorithm == PNFS_OSD_RAID_0) 594 return true; 595 596 stripe_size = layout->stripe_unit * 597 (layout->group_width - layout->parity); 598 599 div_u64_rem(offset, stripe_size, &stripe_off); 600 if (!stripe_off) 601 return true; 602 603 *stripe_end = stripe_size - stripe_off; 604 return false; 605} 606 607static void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) 608{ 609 unsigned long stripe_end = 0; 610 u64 wb_size; 611 612 if (pgio->pg_dreq == NULL) 613 wb_size = i_size_read(pgio->pg_inode) - req_offset(req); 614 else 615 wb_size = nfs_dreq_bytes_left(pgio->pg_dreq); 616 617 pnfs_generic_pg_init_write(pgio, req, wb_size); 618 if (unlikely(pgio->pg_lseg == NULL)) 619 return; /* Not pNFS */ 620 621 if (req->wb_offset || 622 !aligned_on_raid_stripe(req->wb_index * PAGE_SIZE, 623 &OBJIO_LSEG(pgio->pg_lseg)->layout, 624 &stripe_end)) { 625 pgio->pg_layout_private = (void *)stripe_end; 626 } else { 627 pgio->pg_layout_private = (void *) 628 OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length; 629 } 630} 631 632static const struct nfs_pageio_ops objio_pg_read_ops = { 633 .pg_init = objio_init_read, 634 .pg_test = objio_pg_test, 635 .pg_doio = pnfs_generic_pg_readpages, 636}; 637 638static const struct nfs_pageio_ops objio_pg_write_ops = { 639 .pg_init = objio_init_write, 640 .pg_test = objio_pg_test, 641 .pg_doio = pnfs_generic_pg_writepages, 642}; 643 644static struct pnfs_layoutdriver_type objlayout_type = { 645 .id = LAYOUT_OSD2_OBJECTS, 646 .name = "LAYOUT_OSD2_OBJECTS", 647 .flags = PNFS_LAYOUTRET_ON_SETATTR | 648 PNFS_LAYOUTRET_ON_ERROR, 649 650 .owner = THIS_MODULE, 651 .alloc_layout_hdr = objlayout_alloc_layout_hdr, 652 .free_layout_hdr = objlayout_free_layout_hdr, 653 654 .alloc_lseg = objlayout_alloc_lseg, 655 .free_lseg = objlayout_free_lseg, 656 657 .read_pagelist = objlayout_read_pagelist, 658 .write_pagelist = objlayout_write_pagelist, 659 .pg_read_ops = &objio_pg_read_ops, 660 .pg_write_ops = &objio_pg_write_ops, 661 662 .free_deviceid_node = objio_free_deviceid_node, 663 664 .encode_layoutcommit = objlayout_encode_layoutcommit, 665 .encode_layoutreturn = objlayout_encode_layoutreturn, 666}; 667 668MODULE_DESCRIPTION("pNFS Layout Driver for OSD2 objects"); 669MODULE_AUTHOR("Benny Halevy <bhalevy@panasas.com>"); 670MODULE_LICENSE("GPL"); 671 672static int __init 673objlayout_init(void) 674{ 675 int ret = pnfs_register_layoutdriver(&objlayout_type); 676 677 if (ret) 678 printk(KERN_INFO 679 "NFS: %s: Registering OSD pNFS Layout Driver failed: error=%d\n", 680 __func__, ret); 681 else 682 printk(KERN_INFO "NFS: %s: Registered OSD pNFS Layout Driver\n", 683 __func__); 684 return ret; 685} 686 687static void __exit 688objlayout_exit(void) 689{ 690 pnfs_unregister_layoutdriver(&objlayout_type); 691 printk(KERN_INFO "NFS: %s: Unregistered OSD pNFS Layout Driver\n", 692 __func__); 693} 694 695MODULE_ALIAS("nfs-layouttype4-2"); 696 697module_init(objlayout_init); 698module_exit(objlayout_exit);