objio_osd.c 18.0 KB
Newer Older
1 2 3 4 5 6 7
/*
 *  pNFS Objects layout implementation over open-osd initiator library
 *
 *  Copyright (C) 2009 Panasas Inc. [year of first publication]
 *  All rights reserved.
 *
 *  Benny Halevy <bhalevy@panasas.com>
8
 *  Boaz Harrosh <ooo@electrozaur.com>
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2
 *  See the file COPYING included with this distribution for more details.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of the Panasas company nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <linux/module.h>
41
#include <scsi/osd_ore.h>
42 43

#include "objlayout.h"
44
#include "../internal.h"
45 46 47

#define NFSDBG_FACILITY         NFSDBG_PNFS_LD

48 49
struct objio_dev_ent {
	struct nfs4_deviceid_node id_node;
50
	struct ore_dev od;
51 52 53 54 55 56 57
};

static void
objio_free_deviceid_node(struct nfs4_deviceid_node *d)
{
	struct objio_dev_ent *de = container_of(d, struct objio_dev_ent, id_node);

58 59
	dprintk("%s: free od=%p\n", __func__, de->od.od);
	osduld_put_device(de->od.od);
60 61 62
	kfree(de);
}

63 64 65
struct objio_segment {
	struct pnfs_layout_segment lseg;

66 67
	struct ore_layout layout;
	struct ore_components oc;
68 69 70 71 72 73 74 75
};

static inline struct objio_segment *
OBJIO_LSEG(struct pnfs_layout_segment *lseg)
{
	return container_of(lseg, struct objio_segment, lseg);
}

76 77
struct objio_state {
	/* Generic layer */
78
	struct objlayout_io_res oir;
79

80
	bool sync;
81 82
	/*FIXME: Support for extra_bytes at ore_get_rw_state() */
	struct ore_io_state *ios;
83 84
};

85 86
/* Send and wait for a get_device_info of devices in the layout,
   then look them up with the osd_initiator library */
87 88 89
struct nfs4_deviceid_node *
objio_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
			gfp_t gfp_flags)
90 91
{
	struct pnfs_osd_deviceaddr *deviceaddr;
92
	struct objio_dev_ent *ode = NULL;
93 94
	struct osd_dev *od;
	struct osd_dev_info odi;
95
	bool retry_flag = true;
96
	__be32 *p;
97 98
	int err;

99 100 101
	deviceaddr = kzalloc(sizeof(*deviceaddr), gfp_flags);
	if (!deviceaddr)
		return NULL;
102

103 104
	p = page_address(pdev->pages[0]);
	pnfs_osd_xdr_decode_deviceaddr(deviceaddr, p);
105 106 107

	odi.systemid_len = deviceaddr->oda_systemid.len;
	if (odi.systemid_len > sizeof(odi.systemid)) {
108 109
		dprintk("%s: odi.systemid_len > sizeof(systemid=%zd)\n",
			__func__, sizeof(odi.systemid));
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
		err = -EINVAL;
		goto out;
	} else if (odi.systemid_len)
		memcpy(odi.systemid, deviceaddr->oda_systemid.data,
		       odi.systemid_len);
	odi.osdname_len	 = deviceaddr->oda_osdname.len;
	odi.osdname	 = (u8 *)deviceaddr->oda_osdname.data;

	if (!odi.osdname_len && !odi.systemid_len) {
		dprintk("%s: !odi.osdname_len && !odi.systemid_len\n",
			__func__);
		err = -ENODEV;
		goto out;
	}

125
retry_lookup:
126 127 128 129
	od = osduld_info_lookup(&odi);
	if (unlikely(IS_ERR(od))) {
		err = PTR_ERR(od);
		dprintk("%s: osduld_info_lookup => %d\n", __func__, err);
130 131 132 133 134 135 136
		if (err == -ENODEV && retry_flag) {
			err = objlayout_autologin(deviceaddr);
			if (likely(!err)) {
				retry_flag = false;
				goto retry_lookup;
			}
		}
137 138 139
		goto out;
	}

140
	dprintk("Adding new dev_id(%llx:%llx)\n",
141 142 143 144 145 146 147 148 149 150 151 152 153 154
		_DEVID_LO(&pdev->dev_id), _DEVID_HI(&pdev->dev_id));

	ode = kzalloc(sizeof(*ode), gfp_flags);
	if (!ode) {
		dprintk("%s: -ENOMEM od=%p\n", __func__, od);
		goto out;
	}

	nfs4_init_deviceid_node(&ode->id_node, server, &pdev->dev_id);
	kfree(deviceaddr);

	ode->od.od = od;
	return &ode->id_node;

155
out:
156 157
	kfree(deviceaddr);
	return NULL;
158 159
}

160 161
static void copy_single_comp(struct ore_components *oc, unsigned c,
			     struct pnfs_osd_object_cred *src_comp)
162
{
163
	struct ore_comp *ocomp = &oc->comps[c];
164

165 166
	WARN_ON(src_comp->oc_cap_key.cred_len > 0); /* libosd is NO_SEC only */
	WARN_ON(src_comp->oc_cap.cred_len > sizeof(ocomp->cred));
167

168 169
	ocomp->obj.partition = src_comp->oc_object_id.oid_partition_id;
	ocomp->obj.id = src_comp->oc_object_id.oid_object_id;
170

171 172 173
	memcpy(ocomp->cred, src_comp->oc_cap.cred, sizeof(ocomp->cred));
}

T
Trond Myklebust 已提交
174
static int __alloc_objio_seg(unsigned numdevs, gfp_t gfp_flags,
175 176
		       struct objio_segment **pseg)
{
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
/*	This is the in memory structure of the objio_segment
 *
 *	struct __alloc_objio_segment {
 *		struct objio_segment olseg;
 *		struct ore_dev *ods[numdevs];
 *		struct ore_comp	comps[numdevs];
 *	} *aolseg;
 *	NOTE: The code as above compiles and runs perfectly. It is elegant,
 *	type safe and compact. At some Past time Linus has decided he does not
 *	like variable length arrays, For the sake of this principal we uglify
 *	the code as below.
 */
	struct objio_segment *lseg;
	size_t lseg_size = sizeof(*lseg) +
			numdevs * sizeof(lseg->oc.ods[0]) +
			numdevs * sizeof(*lseg->oc.comps);

	lseg = kzalloc(lseg_size, gfp_flags);
	if (unlikely(!lseg)) {
M
Masanari Iida 已提交
196
		dprintk("%s: Failed allocation numdevs=%d size=%zd\n", __func__,
197
			numdevs, lseg_size);
198 199 200
		return -ENOMEM;
	}

201 202 203 204
	lseg->oc.numdevs = numdevs;
	lseg->oc.single_comp = EC_MULTPLE_COMPS;
	lseg->oc.ods = (void *)(lseg + 1);
	lseg->oc.comps = (void *)(lseg->oc.ods + numdevs);
205

206
	*pseg = lseg;
207
	return 0;
208 209 210 211 212 213 214 215
}

int objio_alloc_lseg(struct pnfs_layout_segment **outp,
	struct pnfs_layout_hdr *pnfslay,
	struct pnfs_layout_range *range,
	struct xdr_stream *xdr,
	gfp_t gfp_flags)
{
216
	struct nfs_server *server = NFS_SERVER(pnfslay->plh_inode);
217 218 219
	struct objio_segment *objio_seg;
	struct pnfs_osd_xdr_decode_layout_iter iter;
	struct pnfs_osd_layout layout;
220 221
	struct pnfs_osd_object_cred src_comp;
	unsigned cur_comp;
222 223 224 225 226 227
	int err;

	err = pnfs_osd_xdr_decode_layout_map(&layout, &iter, xdr);
	if (unlikely(err))
		return err;

228
	err = __alloc_objio_seg(layout.olo_num_comps, gfp_flags, &objio_seg);
229 230 231
	if (unlikely(err))
		return err;

232 233 234 235 236
	objio_seg->layout.stripe_unit = layout.olo_map.odm_stripe_unit;
	objio_seg->layout.group_width = layout.olo_map.odm_group_width;
	objio_seg->layout.group_depth = layout.olo_map.odm_group_depth;
	objio_seg->layout.mirrors_p1 = layout.olo_map.odm_mirror_cnt + 1;
	objio_seg->layout.raid_algorithm = layout.olo_map.odm_raid_algorithm;
237

238 239
	err = ore_verify_layout(layout.olo_map.odm_num_comps,
					  &objio_seg->layout);
240 241 242
	if (unlikely(err))
		goto err;

243 244 245
	objio_seg->oc.first_dev = layout.olo_comps_index;
	cur_comp = 0;
	while (pnfs_osd_xdr_decode_layout_comp(&src_comp, &iter, xdr, &err)) {
246 247 248
		struct nfs4_deviceid_node *d;
		struct objio_dev_ent *ode;

249
		copy_single_comp(&objio_seg->oc, cur_comp, &src_comp);
250 251 252 253 254 255

		d = nfs4_find_get_deviceid(server,
				&src_comp.oc_object_id.oid_device_id,
				pnfslay->plh_lc_cred, gfp_flags);
		if (!d) {
			err = -ENXIO;
256
			goto err;
257 258 259 260
		}

		ode = container_of(d, struct objio_dev_ent, id_node);
		objio_seg->oc.ods[cur_comp++] = &ode->od;
261
	}
262 263 264
	/* pnfs_osd_xdr_decode_layout_comp returns false on error */
	if (unlikely(err))
		goto err;
265

266 267 268 269 270 271 272 273 274 275 276 277
	*outp = &objio_seg->lseg;
	return 0;

err:
	kfree(objio_seg);
	dprintk("%s: Error: return %d\n", __func__, err);
	*outp = NULL;
	return err;
}

void objio_free_lseg(struct pnfs_layout_segment *lseg)
{
278
	int i;
279 280
	struct objio_segment *objio_seg = OBJIO_LSEG(lseg);

281 282 283 284 285
	for (i = 0; i < objio_seg->oc.numdevs; i++) {
		struct ore_dev *od = objio_seg->oc.ods[i];
		struct objio_dev_ent *ode;

		if (!od)
286
			break;
287 288
		ode = container_of(od, typeof(*ode), od);
		nfs4_put_deviceid_node(&ode->id_node);
289
	}
290 291 292
	kfree(objio_seg);
}

293
static int
294
objio_alloc_io_state(struct pnfs_layout_hdr *pnfs_layout_type, bool is_reading,
295 296 297
	struct pnfs_layout_segment *lseg, struct page **pages, unsigned pgbase,
	loff_t offset, size_t count, void *rpcdata, gfp_t gfp_flags,
	struct objio_state **outp)
298 299
{
	struct objio_segment *objio_seg = OBJIO_LSEG(lseg);
300 301
	struct ore_io_state *ios;
	int ret;
302 303
	struct __alloc_objio_state {
		struct objio_state objios;
304
		struct pnfs_osd_ioerr ioerrs[objio_seg->oc.numdevs];
305 306 307 308
	} *aos;

	aos = kzalloc(sizeof(*aos), gfp_flags);
	if (unlikely(!aos))
309 310
		return -ENOMEM;

311
	objlayout_init_ioerrs(&aos->objios.oir, objio_seg->oc.numdevs,
312 313
			aos->ioerrs, rpcdata, pnfs_layout_type);

314 315 316 317 318 319 320
	ret = ore_get_rw_state(&objio_seg->layout, &objio_seg->oc, is_reading,
			       offset, count, &ios);
	if (unlikely(ret)) {
		kfree(aos);
		return ret;
	}

321 322
	ios->pages = pages;
	ios->pgbase = pgbase;
323
	ios->private = aos;
324 325
	BUG_ON(ios->nr_pages > (pgbase + count + PAGE_SIZE - 1) >> PAGE_SHIFT);

326 327 328
	aos->objios.sync = 0;
	aos->objios.ios = ios;
	*outp = &aos->objios;
329 330 331
	return 0;
}

332
void objio_free_result(struct objlayout_io_res *oir)
333
{
334
	struct objio_state *objios = container_of(oir, struct objio_state, oir);
335

336 337
	ore_put_io_state(objios->ios);
	kfree(objios);
338 339
}

340
static enum pnfs_osd_errno osd_pri_2_pnfs_err(enum osd_err_priority oep)
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369
{
	switch (oep) {
	case OSD_ERR_PRI_NO_ERROR:
		return (enum pnfs_osd_errno)0;

	case OSD_ERR_PRI_CLEAR_PAGES:
		BUG_ON(1);
		return 0;

	case OSD_ERR_PRI_RESOURCE:
		return PNFS_OSD_ERR_RESOURCE;
	case OSD_ERR_PRI_BAD_CRED:
		return PNFS_OSD_ERR_BAD_CRED;
	case OSD_ERR_PRI_NO_ACCESS:
		return PNFS_OSD_ERR_NO_ACCESS;
	case OSD_ERR_PRI_UNREACHABLE:
		return PNFS_OSD_ERR_UNREACHABLE;
	case OSD_ERR_PRI_NOT_FOUND:
		return PNFS_OSD_ERR_NOT_FOUND;
	case OSD_ERR_PRI_NO_SPACE:
		return PNFS_OSD_ERR_NO_SPACE;
	default:
		WARN_ON(1);
		/* fallthrough */
	case OSD_ERR_PRI_EIO:
		return PNFS_OSD_ERR_EIO;
	}
}

370
static void __on_dev_error(struct ore_io_state *ios,
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387
	struct ore_dev *od, unsigned dev_index, enum osd_err_priority oep,
	u64 dev_offset, u64  dev_len)
{
	struct objio_state *objios = ios->private;
	struct pnfs_osd_objid pooid;
	struct objio_dev_ent *ode = container_of(od, typeof(*ode), od);
	/* FIXME: what to do with more-then-one-group layouts. We need to
	 * translate from ore_io_state index to oc->comps index
	 */
	unsigned comp = dev_index;

	pooid.oid_device_id = ode->id_node.deviceid;
	pooid.oid_partition_id = ios->oc->comps[comp].obj.partition;
	pooid.oid_object_id = ios->oc->comps[comp].obj.id;

	objlayout_io_set_result(&objios->oir, comp,
				&pooid, osd_pri_2_pnfs_err(oep),
388
				dev_offset, dev_len, !ios->reading);
389 390
}

391 392 393
/*
 * read
 */
394
static void _read_done(struct ore_io_state *ios, void *private)
395
{
396
	struct objio_state *objios = private;
397
	ssize_t status;
398
	int ret = ore_check_io(ios, &__on_dev_error);
399

400
	/* FIXME: _io_free(ios) can we dealocate the libosd resources; */
401 402 403 404 405 406

	if (likely(!ret))
		status = ios->length;
	else
		status = ret;

407
	objlayout_read_done(&objios->oir, status, objios->sync);
408 409
}

410
int objio_read_pagelist(struct nfs_pgio_header *hdr)
411
{
412
	struct objio_state *objios;
413 414
	int ret;

415
	ret = objio_alloc_io_state(NFS_I(hdr->inode)->layout, true,
416 417
			hdr->lseg, hdr->args.pages, hdr->args.pgbase,
			hdr->args.offset, hdr->args.count, hdr,
418
			GFP_KERNEL, &objios);
419 420 421
	if (unlikely(ret))
		return ret;

422 423
	objios->ios->done = _read_done;
	dprintk("%s: offset=0x%llx length=0x%x\n", __func__,
424
		hdr->args.offset, hdr->args.count);
425 426 427 428
	ret = ore_read(objios->ios);
	if (unlikely(ret))
		objio_free_result(&objios->oir);
	return ret;
429 430 431 432 433
}

/*
 * write
 */
434
static void _write_done(struct ore_io_state *ios, void *private)
435
{
436
	struct objio_state *objios = private;
437
	ssize_t status;
438
	int ret = ore_check_io(ios, &__on_dev_error);
439

440
	/* FIXME: _io_free(ios) can we dealocate the libosd resources; */
441 442 443 444

	if (likely(!ret)) {
		/* FIXME: should be based on the OSD's persistence model
		 * See OSD2r05 Section 4.13 Data persistence model */
445
		objios->oir.committed = NFS_FILE_SYNC;
446 447 448 449 450
		status = ios->length;
	} else {
		status = ret;
	}

451
	objlayout_write_done(&objios->oir, status, objios->sync);
452 453
}

454 455 456
static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate)
{
	struct objio_state *objios = priv;
457 458
	struct nfs_pgio_header *hdr = objios->oir.rpcdata;
	struct address_space *mapping = hdr->inode->i_mapping;
459
	pgoff_t index = offset / PAGE_SIZE;
460
	struct page *page;
461
	loff_t i_size = i_size_read(hdr->inode);
462

463 464 465 466 467 468 469
	if (offset >= i_size) {
		*uptodate = true;
		dprintk("%s: g_zero_page index=0x%lx\n", __func__, index);
		return ZERO_PAGE(0);
	}

	page = find_get_page(mapping, index);
470
	if (!page) {
471
		page = find_or_create_page(mapping, index, GFP_NOFS);
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
		if (unlikely(!page)) {
			dprintk("%s: grab_cache_page Failed index=0x%lx\n",
				__func__, index);
			return NULL;
		}
		unlock_page(page);
	}
	if (PageDirty(page) || PageWriteback(page))
		*uptodate = true;
	else
		*uptodate = PageUptodate(page);
	dprintk("%s: index=0x%lx uptodate=%d\n", __func__, index, *uptodate);
	return page;
}

static void __r4w_put_page(void *priv, struct page *page)
{
489 490 491 492
	dprintk("%s: index=0x%lx\n", __func__,
		(page == ZERO_PAGE(0)) ? -1UL : page->index);
	if (ZERO_PAGE(0) != page)
		page_cache_release(page);
493 494 495 496 497 498 499 500
	return;
}

static const struct _ore_r4w_op _r4w_op = {
	.get_page = &__r4w_get_page,
	.put_page = &__r4w_put_page,
};

501
int objio_write_pagelist(struct nfs_pgio_header *hdr, int how)
502
{
503
	struct objio_state *objios;
504 505
	int ret;

506
	ret = objio_alloc_io_state(NFS_I(hdr->inode)->layout, false,
507 508
			hdr->lseg, hdr->args.pages, hdr->args.pgbase,
			hdr->args.offset, hdr->args.count, hdr, GFP_NOFS,
509
			&objios);
510 511 512
	if (unlikely(ret))
		return ret;

513
	objios->sync = 0 != (how & FLUSH_SYNC);
514
	objios->ios->r4w = &_r4w_op;
515

516 517 518 519
	if (!objios->sync)
		objios->ios->done = _write_done;

	dprintk("%s: offset=0x%llx length=0x%x\n", __func__,
520
		hdr->args.offset, hdr->args.count);
521
	ret = ore_write(objios->ios);
522 523
	if (unlikely(ret)) {
		objio_free_result(&objios->oir);
524
		return ret;
525
	}
526

527 528 529 530
	if (objios->sync)
		_write_done(objios->ios, objios);

	return 0;
531 532
}

533 534 535 536 537
/*
 * Return 0 if @req cannot be coalesced into @pgio, otherwise return the number
 * of bytes (maximum @req->wb_bytes) that can be coalesced.
 */
static size_t objio_pg_test(struct nfs_pageio_descriptor *pgio,
538 539
			  struct nfs_page *prev, struct nfs_page *req)
{
540 541 542 543 544
	unsigned int size;

	size = pnfs_generic_pg_test(pgio, prev, req);

	if (!size || pgio->pg_count + req->wb_bytes >
545 546
	    (unsigned long)pgio->pg_layout_private)
		return 0;
547

548
	return min(size, req->wb_bytes);
549 550
}

551
static void objio_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580
{
	pnfs_generic_pg_init_read(pgio, req);
	if (unlikely(pgio->pg_lseg == NULL))
		return; /* Not pNFS */

	pgio->pg_layout_private = (void *)
				OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length;
}

static bool aligned_on_raid_stripe(u64 offset, struct ore_layout *layout,
				   unsigned long *stripe_end)
{
	u32 stripe_off;
	unsigned stripe_size;

	if (layout->raid_algorithm == PNFS_OSD_RAID_0)
		return true;

	stripe_size = layout->stripe_unit *
				(layout->group_width - layout->parity);

	div_u64_rem(offset, stripe_size, &stripe_off);
	if (!stripe_off)
		return true;

	*stripe_end = stripe_size - stripe_off;
	return false;
}

581
static void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
582 583
{
	unsigned long stripe_end = 0;
584
	u64 wb_size;
585

586 587 588 589 590 591
	if (pgio->pg_dreq == NULL)
		wb_size = i_size_read(pgio->pg_inode) - req_offset(req);
	else
		wb_size = nfs_dreq_bytes_left(pgio->pg_dreq);

	pnfs_generic_pg_init_write(pgio, req, wb_size);
592 593 594 595 596 597 598 599 600 601 602 603
	if (unlikely(pgio->pg_lseg == NULL))
		return; /* Not pNFS */

	if (req->wb_offset ||
	    !aligned_on_raid_stripe(req->wb_index * PAGE_SIZE,
			       &OBJIO_LSEG(pgio->pg_lseg)->layout,
			       &stripe_end)) {
		pgio->pg_layout_private = (void *)stripe_end;
	} else {
		pgio->pg_layout_private = (void *)
				OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length;
	}
604 605
}

606
static const struct nfs_pageio_ops objio_pg_read_ops = {
607
	.pg_init = objio_init_read,
608
	.pg_test = objio_pg_test,
609
	.pg_doio = pnfs_generic_pg_readpages,
610
	.pg_cleanup = pnfs_generic_pg_cleanup,
611 612 613
};

static const struct nfs_pageio_ops objio_pg_write_ops = {
614
	.pg_init = objio_init_write,
615
	.pg_test = objio_pg_test,
616
	.pg_doio = pnfs_generic_pg_writepages,
617
	.pg_cleanup = pnfs_generic_pg_cleanup,
618 619
};

620 621 622
static struct pnfs_layoutdriver_type objlayout_type = {
	.id = LAYOUT_OSD2_OBJECTS,
	.name = "LAYOUT_OSD2_OBJECTS",
623 624
	.flags                   = PNFS_LAYOUTRET_ON_SETATTR |
				   PNFS_LAYOUTRET_ON_ERROR,
625

626
	.max_deviceinfo_size	 = PAGE_SIZE,
627
	.owner		       	 = THIS_MODULE,
628 629 630
	.alloc_layout_hdr        = objlayout_alloc_layout_hdr,
	.free_layout_hdr         = objlayout_free_layout_hdr,

631 632
	.alloc_lseg              = objlayout_alloc_lseg,
	.free_lseg               = objlayout_free_lseg,
633

634 635
	.read_pagelist           = objlayout_read_pagelist,
	.write_pagelist          = objlayout_write_pagelist,
636 637
	.pg_read_ops             = &objio_pg_read_ops,
	.pg_write_ops            = &objio_pg_write_ops,
638

639
	.free_deviceid_node	 = objio_free_deviceid_node,
640

641
	.encode_layoutcommit	 = objlayout_encode_layoutcommit,
642
	.encode_layoutreturn     = objlayout_encode_layoutreturn,
643 644 645 646 647 648 649 650 651 652 653 654 655
};

MODULE_DESCRIPTION("pNFS Layout Driver for OSD2 objects");
MODULE_AUTHOR("Benny Halevy <bhalevy@panasas.com>");
MODULE_LICENSE("GPL");

static int __init
objlayout_init(void)
{
	int ret = pnfs_register_layoutdriver(&objlayout_type);

	if (ret)
		printk(KERN_INFO
656
			"NFS: %s: Registering OSD pNFS Layout Driver failed: error=%d\n",
657 658
			__func__, ret);
	else
659
		printk(KERN_INFO "NFS: %s: Registered OSD pNFS Layout Driver\n",
660 661 662 663 664 665 666 667
			__func__);
	return ret;
}

static void __exit
objlayout_exit(void)
{
	pnfs_unregister_layoutdriver(&objlayout_type);
668
	printk(KERN_INFO "NFS: %s: Unregistered OSD pNFS Layout Driver\n",
669 670 671
	       __func__);
}

672 673
MODULE_ALIAS("nfs-layouttype4-2");

674 675
module_init(objlayout_init);
module_exit(objlayout_exit);