diff options
Diffstat (limited to 'fs/nfs/objlayout/objlayout.c')
| -rw-r--r-- | fs/nfs/objlayout/objlayout.c | 706 | 
1 files changed, 0 insertions, 706 deletions
| diff --git a/fs/nfs/objlayout/objlayout.c b/fs/nfs/objlayout/objlayout.c deleted file mode 100644 index 8f3d2acb81c3..000000000000 --- a/fs/nfs/objlayout/objlayout.c +++ /dev/null @@ -1,706 +0,0 @@ -/* - *  pNFS Objects layout driver high level definitions - * - *  Copyright (C) 2007 Panasas Inc. [year of first publication] - *  All rights reserved. - * - *  Benny Halevy <bhalevy@panasas.com> - *  Boaz Harrosh <ooo@electrozaur.com> - * - *  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/kmod.h> -#include <linux/moduleparam.h> -#include <linux/ratelimit.h> -#include <scsi/osd_initiator.h> -#include "objlayout.h" - -#define NFSDBG_FACILITY         NFSDBG_PNFS_LD -/* - * Create a objlayout layout structure for the given inode and return it. - */ -struct pnfs_layout_hdr * -objlayout_alloc_layout_hdr(struct inode *inode, gfp_t gfp_flags) -{ -	struct objlayout *objlay; - -	objlay = kzalloc(sizeof(struct objlayout), gfp_flags); -	if (!objlay) -		return NULL; -	spin_lock_init(&objlay->lock); -	INIT_LIST_HEAD(&objlay->err_list); -	dprintk("%s: Return %p\n", __func__, objlay); -	return &objlay->pnfs_layout; -} - -/* - * Free an objlayout layout structure - */ -void -objlayout_free_layout_hdr(struct pnfs_layout_hdr *lo) -{ -	struct objlayout *objlay = OBJLAYOUT(lo); - -	dprintk("%s: objlay %p\n", __func__, objlay); - -	WARN_ON(!list_empty(&objlay->err_list)); -	kfree(objlay); -} - -/* - * Unmarshall layout and store it in pnfslay. - */ -struct pnfs_layout_segment * -objlayout_alloc_lseg(struct pnfs_layout_hdr *pnfslay, -		     struct nfs4_layoutget_res *lgr, -		     gfp_t gfp_flags) -{ -	int status = -ENOMEM; -	struct xdr_stream stream; -	struct xdr_buf buf = { -		.pages =  lgr->layoutp->pages, -		.page_len =  lgr->layoutp->len, -		.buflen =  lgr->layoutp->len, -		.len = lgr->layoutp->len, -	}; -	struct page *scratch; -	struct pnfs_layout_segment *lseg; - -	dprintk("%s: Begin pnfslay %p\n", __func__, pnfslay); - -	scratch = alloc_page(gfp_flags); -	if (!scratch) -		goto err_nofree; - -	xdr_init_decode(&stream, &buf, NULL); -	xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE); - -	status = objio_alloc_lseg(&lseg, pnfslay, &lgr->range, &stream, gfp_flags); -	if (unlikely(status)) { -		dprintk("%s: objio_alloc_lseg Return err %d\n", __func__, -			status); -		goto err; -	} - -	__free_page(scratch); - -	dprintk("%s: Return %p\n", __func__, lseg); -	return lseg; - -err: -	__free_page(scratch); -err_nofree: -	dprintk("%s: Err Return=>%d\n", __func__, status); -	return ERR_PTR(status); -} - -/* - * Free a layout segement - */ -void -objlayout_free_lseg(struct pnfs_layout_segment *lseg) -{ -	dprintk("%s: freeing layout segment %p\n", __func__, lseg); - -	if (unlikely(!lseg)) -		return; - -	objio_free_lseg(lseg); -} - -/* - * I/O Operations - */ -static inline u64 -end_offset(u64 start, u64 len) -{ -	u64 end; - -	end = start + len; -	return end >= start ? end : NFS4_MAX_UINT64; -} - -static void _fix_verify_io_params(struct pnfs_layout_segment *lseg, -			   struct page ***p_pages, unsigned *p_pgbase, -			   u64 offset, unsigned long count) -{ -	u64 lseg_end_offset; - -	BUG_ON(offset < lseg->pls_range.offset); -	lseg_end_offset = end_offset(lseg->pls_range.offset, -				     lseg->pls_range.length); -	BUG_ON(offset >= lseg_end_offset); -	WARN_ON(offset + count > lseg_end_offset); - -	if (*p_pgbase > PAGE_SIZE) { -		dprintk("%s: pgbase(0x%x) > PAGE_SIZE\n", __func__, *p_pgbase); -		*p_pages += *p_pgbase >> PAGE_SHIFT; -		*p_pgbase &= ~PAGE_MASK; -	} -} - -/* - * I/O done common code - */ -static void -objlayout_iodone(struct objlayout_io_res *oir) -{ -	if (likely(oir->status >= 0)) { -		objio_free_result(oir); -	} else { -		struct objlayout *objlay = oir->objlay; - -		spin_lock(&objlay->lock); -		objlay->delta_space_valid = OBJ_DSU_INVALID; -		list_add(&objlay->err_list, &oir->err_list); -		spin_unlock(&objlay->lock); -	} -} - -/* - * objlayout_io_set_result - Set an osd_error code on a specific osd comp. - * - * The @index component IO failed (error returned from target). Register - * the error for later reporting at layout-return. - */ -void -objlayout_io_set_result(struct objlayout_io_res *oir, unsigned index, -			struct pnfs_osd_objid *pooid, int osd_error, -			u64 offset, u64 length, bool is_write) -{ -	struct pnfs_osd_ioerr *ioerr = &oir->ioerrs[index]; - -	BUG_ON(index >= oir->num_comps); -	if (osd_error) { -		ioerr->oer_component = *pooid; -		ioerr->oer_comp_offset = offset; -		ioerr->oer_comp_length = length; -		ioerr->oer_iswrite = is_write; -		ioerr->oer_errno = osd_error; - -		dprintk("%s: err[%d]: errno=%d is_write=%d dev(%llx:%llx) " -			"par=0x%llx obj=0x%llx offset=0x%llx length=0x%llx\n", -			__func__, index, ioerr->oer_errno, -			ioerr->oer_iswrite, -			_DEVID_LO(&ioerr->oer_component.oid_device_id), -			_DEVID_HI(&ioerr->oer_component.oid_device_id), -			ioerr->oer_component.oid_partition_id, -			ioerr->oer_component.oid_object_id, -			ioerr->oer_comp_offset, -			ioerr->oer_comp_length); -	} else { -		/* User need not call if no error is reported */ -		ioerr->oer_errno = 0; -	} -} - -/* Function scheduled on rpc workqueue to call ->nfs_readlist_complete(). - * This is because the osd completion is called with ints-off from - * the block layer - */ -static void _rpc_read_complete(struct work_struct *work) -{ -	struct rpc_task *task; -	struct nfs_pgio_header *hdr; - -	dprintk("%s enter\n", __func__); -	task = container_of(work, struct rpc_task, u.tk_work); -	hdr = container_of(task, struct nfs_pgio_header, task); - -	pnfs_ld_read_done(hdr); -} - -void -objlayout_read_done(struct objlayout_io_res *oir, ssize_t status, bool sync) -{ -	struct nfs_pgio_header *hdr = oir->rpcdata; - -	oir->status = hdr->task.tk_status = status; -	if (status >= 0) -		hdr->res.count = status; -	else -		hdr->pnfs_error = status; -	objlayout_iodone(oir); -	/* must not use oir after this point */ - -	dprintk("%s: Return status=%zd eof=%d sync=%d\n", __func__, -		status, hdr->res.eof, sync); - -	if (sync) -		pnfs_ld_read_done(hdr); -	else { -		INIT_WORK(&hdr->task.u.tk_work, _rpc_read_complete); -		schedule_work(&hdr->task.u.tk_work); -	} -} - -/* - * Perform sync or async reads. - */ -enum pnfs_try_status -objlayout_read_pagelist(struct nfs_pgio_header *hdr) -{ -	struct inode *inode = hdr->inode; -	loff_t offset = hdr->args.offset; -	size_t count = hdr->args.count; -	int err; -	loff_t eof; - -	eof = i_size_read(inode); -	if (unlikely(offset + count > eof)) { -		if (offset >= eof) { -			err = 0; -			hdr->res.count = 0; -			hdr->res.eof = 1; -			/*FIXME: do we need to call pnfs_ld_read_done() */ -			goto out; -		} -		count = eof - offset; -	} - -	hdr->res.eof = (offset + count) >= eof; -	_fix_verify_io_params(hdr->lseg, &hdr->args.pages, -			      &hdr->args.pgbase, -			      hdr->args.offset, hdr->args.count); - -	dprintk("%s: inode(%lx) offset 0x%llx count 0x%zx eof=%d\n", -		__func__, inode->i_ino, offset, count, hdr->res.eof); - -	err = objio_read_pagelist(hdr); - out: -	if (unlikely(err)) { -		hdr->pnfs_error = err; -		dprintk("%s: Returned Error %d\n", __func__, err); -		return PNFS_NOT_ATTEMPTED; -	} -	return PNFS_ATTEMPTED; -} - -/* Function scheduled on rpc workqueue to call ->nfs_writelist_complete(). - * This is because the osd completion is called with ints-off from - * the block layer - */ -static void _rpc_write_complete(struct work_struct *work) -{ -	struct rpc_task *task; -	struct nfs_pgio_header *hdr; - -	dprintk("%s enter\n", __func__); -	task = container_of(work, struct rpc_task, u.tk_work); -	hdr = container_of(task, struct nfs_pgio_header, task); - -	pnfs_ld_write_done(hdr); -} - -void -objlayout_write_done(struct objlayout_io_res *oir, ssize_t status, bool sync) -{ -	struct nfs_pgio_header *hdr = oir->rpcdata; - -	oir->status = hdr->task.tk_status = status; -	if (status >= 0) { -		hdr->res.count = status; -		hdr->verf.committed = oir->committed; -	} else { -		hdr->pnfs_error = status; -	} -	objlayout_iodone(oir); -	/* must not use oir after this point */ - -	dprintk("%s: Return status %zd committed %d sync=%d\n", __func__, -		status, hdr->verf.committed, sync); - -	if (sync) -		pnfs_ld_write_done(hdr); -	else { -		INIT_WORK(&hdr->task.u.tk_work, _rpc_write_complete); -		schedule_work(&hdr->task.u.tk_work); -	} -} - -/* - * Perform sync or async writes. - */ -enum pnfs_try_status -objlayout_write_pagelist(struct nfs_pgio_header *hdr, int how) -{ -	int err; - -	_fix_verify_io_params(hdr->lseg, &hdr->args.pages, -			      &hdr->args.pgbase, -			      hdr->args.offset, hdr->args.count); - -	err = objio_write_pagelist(hdr, how); -	if (unlikely(err)) { -		hdr->pnfs_error = err; -		dprintk("%s: Returned Error %d\n", __func__, err); -		return PNFS_NOT_ATTEMPTED; -	} -	return PNFS_ATTEMPTED; -} - -void -objlayout_encode_layoutcommit(struct pnfs_layout_hdr *pnfslay, -			      struct xdr_stream *xdr, -			      const struct nfs4_layoutcommit_args *args) -{ -	struct objlayout *objlay = OBJLAYOUT(pnfslay); -	struct pnfs_osd_layoutupdate lou; -	__be32 *start; - -	dprintk("%s: Begin\n", __func__); - -	spin_lock(&objlay->lock); -	lou.dsu_valid = (objlay->delta_space_valid == OBJ_DSU_VALID); -	lou.dsu_delta = objlay->delta_space_used; -	objlay->delta_space_used = 0; -	objlay->delta_space_valid = OBJ_DSU_INIT; -	lou.olu_ioerr_flag = !list_empty(&objlay->err_list); -	spin_unlock(&objlay->lock); - -	start = xdr_reserve_space(xdr, 4); - -	BUG_ON(pnfs_osd_xdr_encode_layoutupdate(xdr, &lou)); - -	*start = cpu_to_be32((xdr->p - start - 1) * 4); - -	dprintk("%s: Return delta_space_used %lld err %d\n", __func__, -		lou.dsu_delta, lou.olu_ioerr_flag); -} - -static int -err_prio(u32 oer_errno) -{ -	switch (oer_errno) { -	case 0: -		return 0; - -	case PNFS_OSD_ERR_RESOURCE: -		return OSD_ERR_PRI_RESOURCE; -	case PNFS_OSD_ERR_BAD_CRED: -		return OSD_ERR_PRI_BAD_CRED; -	case PNFS_OSD_ERR_NO_ACCESS: -		return OSD_ERR_PRI_NO_ACCESS; -	case PNFS_OSD_ERR_UNREACHABLE: -		return OSD_ERR_PRI_UNREACHABLE; -	case PNFS_OSD_ERR_NOT_FOUND: -		return OSD_ERR_PRI_NOT_FOUND; -	case PNFS_OSD_ERR_NO_SPACE: -		return OSD_ERR_PRI_NO_SPACE; -	default: -		WARN_ON(1); -		/* fallthrough */ -	case PNFS_OSD_ERR_EIO: -		return OSD_ERR_PRI_EIO; -	} -} - -static void -merge_ioerr(struct pnfs_osd_ioerr *dest_err, -	    const struct pnfs_osd_ioerr *src_err) -{ -	u64 dest_end, src_end; - -	if (!dest_err->oer_errno) { -		*dest_err = *src_err; -		/* accumulated device must be blank */ -		memset(&dest_err->oer_component.oid_device_id, 0, -			sizeof(dest_err->oer_component.oid_device_id)); - -		return; -	} - -	if (dest_err->oer_component.oid_partition_id != -				src_err->oer_component.oid_partition_id) -		dest_err->oer_component.oid_partition_id = 0; - -	if (dest_err->oer_component.oid_object_id != -				src_err->oer_component.oid_object_id) -		dest_err->oer_component.oid_object_id = 0; - -	if (dest_err->oer_comp_offset > src_err->oer_comp_offset) -		dest_err->oer_comp_offset = src_err->oer_comp_offset; - -	dest_end = end_offset(dest_err->oer_comp_offset, -			      dest_err->oer_comp_length); -	src_end =  end_offset(src_err->oer_comp_offset, -			      src_err->oer_comp_length); -	if (dest_end < src_end) -		dest_end = src_end; - -	dest_err->oer_comp_length = dest_end - dest_err->oer_comp_offset; - -	if ((src_err->oer_iswrite == dest_err->oer_iswrite) && -	    (err_prio(src_err->oer_errno) > err_prio(dest_err->oer_errno))) { -			dest_err->oer_errno = src_err->oer_errno; -	} else if (src_err->oer_iswrite) { -		dest_err->oer_iswrite = true; -		dest_err->oer_errno = src_err->oer_errno; -	} -} - -static void -encode_accumulated_error(struct objlayout *objlay, __be32 *p) -{ -	struct objlayout_io_res *oir, *tmp; -	struct pnfs_osd_ioerr accumulated_err = {.oer_errno = 0}; - -	list_for_each_entry_safe(oir, tmp, &objlay->err_list, err_list) { -		unsigned i; - -		for (i = 0; i < oir->num_comps; i++) { -			struct pnfs_osd_ioerr *ioerr = &oir->ioerrs[i]; - -			if (!ioerr->oer_errno) -				continue; - -			printk(KERN_ERR "NFS: %s: err[%d]: errno=%d " -				"is_write=%d dev(%llx:%llx) par=0x%llx " -				"obj=0x%llx offset=0x%llx length=0x%llx\n", -				__func__, i, ioerr->oer_errno, -				ioerr->oer_iswrite, -				_DEVID_LO(&ioerr->oer_component.oid_device_id), -				_DEVID_HI(&ioerr->oer_component.oid_device_id), -				ioerr->oer_component.oid_partition_id, -				ioerr->oer_component.oid_object_id, -				ioerr->oer_comp_offset, -				ioerr->oer_comp_length); - -			merge_ioerr(&accumulated_err, ioerr); -		} -		list_del(&oir->err_list); -		objio_free_result(oir); -	} - -	pnfs_osd_xdr_encode_ioerr(p, &accumulated_err); -} - -void -objlayout_encode_layoutreturn(struct xdr_stream *xdr, -			      const struct nfs4_layoutreturn_args *args) -{ -	struct pnfs_layout_hdr *pnfslay = args->layout; -	struct objlayout *objlay = OBJLAYOUT(pnfslay); -	struct objlayout_io_res *oir, *tmp; -	__be32 *start; - -	dprintk("%s: Begin\n", __func__); -	start = xdr_reserve_space(xdr, 4); -	BUG_ON(!start); - -	spin_lock(&objlay->lock); - -	list_for_each_entry_safe(oir, tmp, &objlay->err_list, err_list) { -		__be32 *last_xdr = NULL, *p; -		unsigned i; -		int res = 0; - -		for (i = 0; i < oir->num_comps; i++) { -			struct pnfs_osd_ioerr *ioerr = &oir->ioerrs[i]; - -			if (!ioerr->oer_errno) -				continue; - -			dprintk("%s: err[%d]: errno=%d is_write=%d " -				"dev(%llx:%llx) par=0x%llx obj=0x%llx " -				"offset=0x%llx length=0x%llx\n", -				__func__, i, ioerr->oer_errno, -				ioerr->oer_iswrite, -				_DEVID_LO(&ioerr->oer_component.oid_device_id), -				_DEVID_HI(&ioerr->oer_component.oid_device_id), -				ioerr->oer_component.oid_partition_id, -				ioerr->oer_component.oid_object_id, -				ioerr->oer_comp_offset, -				ioerr->oer_comp_length); - -			p = pnfs_osd_xdr_ioerr_reserve_space(xdr); -			if (unlikely(!p)) { -				res = -E2BIG; -				break; /* accumulated_error */ -			} - -			last_xdr = p; -			pnfs_osd_xdr_encode_ioerr(p, &oir->ioerrs[i]); -		} - -		/* TODO: use xdr_write_pages */ -		if (unlikely(res)) { -			/* no space for even one error descriptor */ -			BUG_ON(!last_xdr); - -			/* we've encountered a situation with lots and lots of -			 * errors and no space to encode them all. Use the last -			 * available slot to report the union of all the -			 * remaining errors. -			 */ -			encode_accumulated_error(objlay, last_xdr); -			goto loop_done; -		} -		list_del(&oir->err_list); -		objio_free_result(oir); -	} -loop_done: -	spin_unlock(&objlay->lock); - -	*start = cpu_to_be32((xdr->p - start - 1) * 4); -	dprintk("%s: Return\n", __func__); -} - -enum { -	OBJLAYOUT_MAX_URI_LEN = 256, OBJLAYOUT_MAX_OSDNAME_LEN = 64, -	OBJLAYOUT_MAX_SYSID_HEX_LEN = OSD_SYSTEMID_LEN * 2 + 1, -	OSD_LOGIN_UPCALL_PATHLEN  = 256 -}; - -static char osd_login_prog[OSD_LOGIN_UPCALL_PATHLEN] = "/sbin/osd_login"; - -module_param_string(osd_login_prog, osd_login_prog, sizeof(osd_login_prog), -		    0600); -MODULE_PARM_DESC(osd_login_prog, "Path to the osd_login upcall program"); - -struct __auto_login { -	char uri[OBJLAYOUT_MAX_URI_LEN]; -	char osdname[OBJLAYOUT_MAX_OSDNAME_LEN]; -	char systemid_hex[OBJLAYOUT_MAX_SYSID_HEX_LEN]; -}; - -static int __objlayout_upcall(struct __auto_login *login) -{ -	static char *envp[] = { "HOME=/", -		"TERM=linux", -		"PATH=/sbin:/usr/sbin:/bin:/usr/bin", -		NULL -	}; -	char *argv[8]; -	int ret; - -	if (unlikely(!osd_login_prog[0])) { -		dprintk("%s: osd_login_prog is disabled\n", __func__); -		return -EACCES; -	} - -	dprintk("%s uri: %s\n", __func__, login->uri); -	dprintk("%s osdname %s\n", __func__, login->osdname); -	dprintk("%s systemid_hex %s\n", __func__, login->systemid_hex); - -	argv[0] = (char *)osd_login_prog; -	argv[1] = "-u"; -	argv[2] = login->uri; -	argv[3] = "-o"; -	argv[4] = login->osdname; -	argv[5] = "-s"; -	argv[6] = login->systemid_hex; -	argv[7] = NULL; - -	ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC); -	/* -	 * Disable the upcall mechanism if we're getting an ENOENT or -	 * EACCES error. The admin can re-enable it on the fly by using -	 * sysfs to set the objlayoutdriver.osd_login_prog module parameter once -	 * the problem has been fixed. -	 */ -	if (ret == -ENOENT || ret == -EACCES) { -		printk(KERN_ERR "PNFS-OBJ: %s was not found please set " -			"objlayoutdriver.osd_login_prog kernel parameter!\n", -			osd_login_prog); -		osd_login_prog[0] = '\0'; -	} -	dprintk("%s %s return value: %d\n", __func__, osd_login_prog, ret); - -	return ret; -} - -/* Assume dest is all zeros */ -static void __copy_nfsS_and_zero_terminate(struct nfs4_string s, -					   char *dest, int max_len, -					   const char *var_name) -{ -	if (!s.len) -		return; - -	if (s.len >= max_len) { -		pr_warn_ratelimited( -			"objlayout_autologin: %s: s.len(%d) >= max_len(%d)", -			var_name, s.len, max_len); -		s.len = max_len - 1; /* space for null terminator */ -	} - -	memcpy(dest, s.data, s.len); -} - -/* Assume sysid is all zeros */ -static void _sysid_2_hex(struct nfs4_string s, -		  char sysid[OBJLAYOUT_MAX_SYSID_HEX_LEN]) -{ -	int i; -	char *cur; - -	if (!s.len) -		return; - -	if (s.len != OSD_SYSTEMID_LEN) { -		pr_warn_ratelimited( -		    "objlayout_autologin: systemid_len(%d) != OSD_SYSTEMID_LEN", -		    s.len); -		if (s.len > OSD_SYSTEMID_LEN) -			s.len = OSD_SYSTEMID_LEN; -	} - -	cur = sysid; -	for (i = 0; i < s.len; i++) -		cur = hex_byte_pack(cur, s.data[i]); -} - -int objlayout_autologin(struct pnfs_osd_deviceaddr *deviceaddr) -{ -	int rc; -	struct __auto_login login; - -	if (!deviceaddr->oda_targetaddr.ota_netaddr.r_addr.len) -		return -ENODEV; - -	memset(&login, 0, sizeof(login)); -	__copy_nfsS_and_zero_terminate( -		deviceaddr->oda_targetaddr.ota_netaddr.r_addr, -		login.uri, sizeof(login.uri), "URI"); - -	__copy_nfsS_and_zero_terminate( -		deviceaddr->oda_osdname, -		login.osdname, sizeof(login.osdname), "OSDNAME"); - -	_sysid_2_hex(deviceaddr->oda_systemid, login.systemid_hex); - -	rc = __objlayout_upcall(&login); -	if (rc > 0) /* script returns positive values */ -		rc = -ENODEV; - -	return rc; -} | 
