diff options
Diffstat (limited to 'fs/nfs/objlayout/objlayout.c')
-rw-r--r-- | fs/nfs/objlayout/objlayout.c | 142 |
1 files changed, 138 insertions, 4 deletions
diff --git a/fs/nfs/objlayout/objlayout.c b/fs/nfs/objlayout/objlayout.c index b3c29039f5b8..8d45f1c318ce 100644 --- a/fs/nfs/objlayout/objlayout.c +++ b/fs/nfs/objlayout/objlayout.c | |||
@@ -37,6 +37,9 @@ | |||
37 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 37 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
38 | */ | 38 | */ |
39 | 39 | ||
40 | #include <linux/kmod.h> | ||
41 | #include <linux/moduleparam.h> | ||
42 | #include <linux/ratelimit.h> | ||
40 | #include <scsi/osd_initiator.h> | 43 | #include <scsi/osd_initiator.h> |
41 | #include "objlayout.h" | 44 | #include "objlayout.h" |
42 | 45 | ||
@@ -156,7 +159,7 @@ last_byte_offset(u64 start, u64 len) | |||
156 | return end > start ? end - 1 : NFS4_MAX_UINT64; | 159 | return end > start ? end - 1 : NFS4_MAX_UINT64; |
157 | } | 160 | } |
158 | 161 | ||
159 | void _fix_verify_io_params(struct pnfs_layout_segment *lseg, | 162 | static void _fix_verify_io_params(struct pnfs_layout_segment *lseg, |
160 | struct page ***p_pages, unsigned *p_pgbase, | 163 | struct page ***p_pages, unsigned *p_pgbase, |
161 | u64 offset, unsigned long count) | 164 | u64 offset, unsigned long count) |
162 | { | 165 | { |
@@ -490,9 +493,9 @@ encode_accumulated_error(struct objlayout *objlay, __be32 *p) | |||
490 | if (!ioerr->oer_errno) | 493 | if (!ioerr->oer_errno) |
491 | continue; | 494 | continue; |
492 | 495 | ||
493 | printk(KERN_ERR "%s: err[%d]: errno=%d is_write=%d " | 496 | printk(KERN_ERR "NFS: %s: err[%d]: errno=%d " |
494 | "dev(%llx:%llx) par=0x%llx obj=0x%llx " | 497 | "is_write=%d dev(%llx:%llx) par=0x%llx " |
495 | "offset=0x%llx length=0x%llx\n", | 498 | "obj=0x%llx offset=0x%llx length=0x%llx\n", |
496 | __func__, i, ioerr->oer_errno, | 499 | __func__, i, ioerr->oer_errno, |
497 | ioerr->oer_iswrite, | 500 | ioerr->oer_iswrite, |
498 | _DEVID_LO(&ioerr->oer_component.oid_device_id), | 501 | _DEVID_LO(&ioerr->oer_component.oid_device_id), |
@@ -651,3 +654,134 @@ void objlayout_put_deviceinfo(struct pnfs_osd_deviceaddr *deviceaddr) | |||
651 | __free_page(odi->page); | 654 | __free_page(odi->page); |
652 | kfree(odi); | 655 | kfree(odi); |
653 | } | 656 | } |
657 | |||
658 | enum { | ||
659 | OBJLAYOUT_MAX_URI_LEN = 256, OBJLAYOUT_MAX_OSDNAME_LEN = 64, | ||
660 | OBJLAYOUT_MAX_SYSID_HEX_LEN = OSD_SYSTEMID_LEN * 2 + 1, | ||
661 | OSD_LOGIN_UPCALL_PATHLEN = 256 | ||
662 | }; | ||
663 | |||
664 | static char osd_login_prog[OSD_LOGIN_UPCALL_PATHLEN] = "/sbin/osd_login"; | ||
665 | |||
666 | module_param_string(osd_login_prog, osd_login_prog, sizeof(osd_login_prog), | ||
667 | 0600); | ||
668 | MODULE_PARM_DESC(osd_login_prog, "Path to the osd_login upcall program"); | ||
669 | |||
670 | struct __auto_login { | ||
671 | char uri[OBJLAYOUT_MAX_URI_LEN]; | ||
672 | char osdname[OBJLAYOUT_MAX_OSDNAME_LEN]; | ||
673 | char systemid_hex[OBJLAYOUT_MAX_SYSID_HEX_LEN]; | ||
674 | }; | ||
675 | |||
676 | static int __objlayout_upcall(struct __auto_login *login) | ||
677 | { | ||
678 | static char *envp[] = { "HOME=/", | ||
679 | "TERM=linux", | ||
680 | "PATH=/sbin:/usr/sbin:/bin:/usr/bin", | ||
681 | NULL | ||
682 | }; | ||
683 | char *argv[8]; | ||
684 | int ret; | ||
685 | |||
686 | if (unlikely(!osd_login_prog[0])) { | ||
687 | dprintk("%s: osd_login_prog is disabled\n", __func__); | ||
688 | return -EACCES; | ||
689 | } | ||
690 | |||
691 | dprintk("%s uri: %s\n", __func__, login->uri); | ||
692 | dprintk("%s osdname %s\n", __func__, login->osdname); | ||
693 | dprintk("%s systemid_hex %s\n", __func__, login->systemid_hex); | ||
694 | |||
695 | argv[0] = (char *)osd_login_prog; | ||
696 | argv[1] = "-u"; | ||
697 | argv[2] = login->uri; | ||
698 | argv[3] = "-o"; | ||
699 | argv[4] = login->osdname; | ||
700 | argv[5] = "-s"; | ||
701 | argv[6] = login->systemid_hex; | ||
702 | argv[7] = NULL; | ||
703 | |||
704 | ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC); | ||
705 | /* | ||
706 | * Disable the upcall mechanism if we're getting an ENOENT or | ||
707 | * EACCES error. The admin can re-enable it on the fly by using | ||
708 | * sysfs to set the objlayoutdriver.osd_login_prog module parameter once | ||
709 | * the problem has been fixed. | ||
710 | */ | ||
711 | if (ret == -ENOENT || ret == -EACCES) { | ||
712 | printk(KERN_ERR "PNFS-OBJ: %s was not found please set " | ||
713 | "objlayoutdriver.osd_login_prog kernel parameter!\n", | ||
714 | osd_login_prog); | ||
715 | osd_login_prog[0] = '\0'; | ||
716 | } | ||
717 | dprintk("%s %s return value: %d\n", __func__, osd_login_prog, ret); | ||
718 | |||
719 | return ret; | ||
720 | } | ||
721 | |||
722 | /* Assume dest is all zeros */ | ||
723 | static void __copy_nfsS_and_zero_terminate(struct nfs4_string s, | ||
724 | char *dest, int max_len, | ||
725 | const char *var_name) | ||
726 | { | ||
727 | if (!s.len) | ||
728 | return; | ||
729 | |||
730 | if (s.len >= max_len) { | ||
731 | pr_warn_ratelimited( | ||
732 | "objlayout_autologin: %s: s.len(%d) >= max_len(%d)", | ||
733 | var_name, s.len, max_len); | ||
734 | s.len = max_len - 1; /* space for null terminator */ | ||
735 | } | ||
736 | |||
737 | memcpy(dest, s.data, s.len); | ||
738 | } | ||
739 | |||
740 | /* Assume sysid is all zeros */ | ||
741 | static void _sysid_2_hex(struct nfs4_string s, | ||
742 | char sysid[OBJLAYOUT_MAX_SYSID_HEX_LEN]) | ||
743 | { | ||
744 | int i; | ||
745 | char *cur; | ||
746 | |||
747 | if (!s.len) | ||
748 | return; | ||
749 | |||
750 | if (s.len != OSD_SYSTEMID_LEN) { | ||
751 | pr_warn_ratelimited( | ||
752 | "objlayout_autologin: systemid_len(%d) != OSD_SYSTEMID_LEN", | ||
753 | s.len); | ||
754 | if (s.len > OSD_SYSTEMID_LEN) | ||
755 | s.len = OSD_SYSTEMID_LEN; | ||
756 | } | ||
757 | |||
758 | cur = sysid; | ||
759 | for (i = 0; i < s.len; i++) | ||
760 | cur = hex_byte_pack(cur, s.data[i]); | ||
761 | } | ||
762 | |||
763 | int objlayout_autologin(struct pnfs_osd_deviceaddr *deviceaddr) | ||
764 | { | ||
765 | int rc; | ||
766 | struct __auto_login login; | ||
767 | |||
768 | if (!deviceaddr->oda_targetaddr.ota_netaddr.r_addr.len) | ||
769 | return -ENODEV; | ||
770 | |||
771 | memset(&login, 0, sizeof(login)); | ||
772 | __copy_nfsS_and_zero_terminate( | ||
773 | deviceaddr->oda_targetaddr.ota_netaddr.r_addr, | ||
774 | login.uri, sizeof(login.uri), "URI"); | ||
775 | |||
776 | __copy_nfsS_and_zero_terminate( | ||
777 | deviceaddr->oda_osdname, | ||
778 | login.osdname, sizeof(login.osdname), "OSDNAME"); | ||
779 | |||
780 | _sysid_2_hex(deviceaddr->oda_systemid, login.systemid_hex); | ||
781 | |||
782 | rc = __objlayout_upcall(&login); | ||
783 | if (rc > 0) /* script returns positive values */ | ||
784 | rc = -ENODEV; | ||
785 | |||
786 | return rc; | ||
787 | } | ||