pnfs-obj: autologin: Add support for protocol autologin
The pnfs-objects protocol mandates that we autologin into devices not present in the system, according to information specified in the get_device_info returned from the server. The Protocol specifies two login hints. 1. An IP address:port combination 2. A string URI which is constructed as a URL with a protocol prefix followed by :// and a string as address. For each protocol prefix the string-address format might be different. We only support the second option. The first option is just redundant to the second one. NOTE: The Kernel part of autologin does not parse the URI string. It just channels it to a user-mode script. So any new login protocols should only update the user-mode script which is a part of the nfs-utils package, but the Kernel need not change. We implement the autologin by using the call_usermodehelper() API. (Thanks to Steve Dickson <steved@redhat.com> for pointing it out) So there is no running daemon needed, and/or special setup. We Add the osd_login_prog Kernel module parameters which defaults to: /sbin/osd_login Kernel try's to upcall the program specified in osd_login_prog. If the file is not found or the execution fails Kernel will disable any farther upcalls, by zeroing out osd_login_prog, Until Admin re-enables it by setting the osd_login_prog parameter to a proper program. Also add text about the osd_login program command line API to: Documentation/filesystems/nfs/pnfs.txt and documentation of the new osd_login_prog module parameter to: Documentation/kernel-parameters.txt TODO: Add timeout option in the case osd_login program gets stuck Signed-off-by: Sachin Bhamare <sbhamare@panasas.com> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
committed by
Trond Myklebust
parent
c6bfa1a163
commit
18d98f6c04
@@ -37,6 +37,9 @@
|
||||
* 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"
|
||||
|
||||
@@ -651,3 +654,134 @@ void objlayout_put_deviceinfo(struct pnfs_osd_deviceaddr *deviceaddr)
|
||||
__free_page(odi->page);
|
||||
kfree(odi);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user