Whamcloud - gitweb
land b_colibri_devel on HEAD:
authorericm <ericm>
Tue, 29 Jan 2008 21:24:51 +0000 (21:24 +0000)
committerericm <ericm>
Tue, 29 Jan 2008 21:24:51 +0000 (21:24 +0000)
- redesigned remote acl support, by FanYong
  b=11842
  r=pravin.shelar, eric.mei
- new sptlrpc configure interface
  b=13642
  r=yong.fan, rahul.deshmukh
- split kerberos keytab for lustre_root
  b=13873
  r=yong.fan, h.huang
- fix setuid for gss with linux keyring
  b=13899
  r=yong.fan, h.huang

130 files changed:
lustre/ChangeLog
lustre/autoconf/kerberos5.m4
lustre/include/Makefile.am
lustre/include/linux/lustre_acl.h
lustre/include/linux/lustre_mds.h
lustre/include/linux/lvfs.h
lustre/include/lustre/liblustreapi.h
lustre/include/lustre/lustre_idl.h
lustre/include/lustre/lustre_user.h
lustre/include/lustre_cfg.h
lustre/include/lustre_disk.h
lustre/include/lustre_eacl.h [new file with mode: 0644]
lustre/include/lustre_export.h
lustre/include/lustre_idmap.h [new file with mode: 0644]
lustre/include/lustre_import.h
lustre/include/lustre_mdc.h
lustre/include/lustre_mdt.h
lustre/include/lustre_net.h
lustre/include/lustre_param.h
lustre/include/lustre_sec.h
lustre/include/lustre_ucache.h
lustre/include/md_object.h
lustre/include/obd.h
lustre/include/obd_class.h
lustre/kernel_patches/kernel_configs/kernel-2.6.16-2.6-sles10-i686-bigsmp.config
lustre/kernel_patches/kernel_configs/kernel-2.6.16-2.6-sles10-i686.config
lustre/kernel_patches/kernel_configs/kernel-2.6.16-2.6-sles10-x86_64-smp.config
lustre/kernel_patches/kernel_configs/kernel-2.6.16-2.6-sles10-x86_64.config
lustre/ldlm/ldlm_lib.c
lustre/ldlm/ldlm_lockd.c
lustre/llite/Makefile.in
lustre/llite/dir.c
lustre/llite/file.c
lustre/llite/llite_internal.h
lustre/llite/llite_lib.c
lustre/llite/llite_nfs.c
lustre/llite/llite_rmtacl.c [new file with mode: 0644]
lustre/llite/namei.c
lustre/llite/remote_perm.c
lustre/llite/xattr.c
lustre/lmv/lmv_obd.c
lustre/mdc/lproc_mdc.c
lustre/mdc/mdc_internal.h
lustre/mdc/mdc_lib.c
lustre/mdc/mdc_request.c
lustre/mdd/mdd_internal.h
lustre/mdd/mdd_object.c
lustre/mdd/mdd_permission.c
lustre/mds/handler.c
lustre/mdt/Makefile.in
lustre/mdt/mdt_handler.c
lustre/mdt/mdt_identity.c
lustre/mdt/mdt_idmap.c
lustre/mdt/mdt_internal.h
lustre/mdt/mdt_lib.c
lustre/mdt/mdt_lproc.c
lustre/mdt/mdt_rmtacl.c [deleted file]
lustre/mdt/mdt_xattr.c
lustre/mgc/mgc_request.c
lustre/mgs/lproc_mgs.c
lustre/mgs/mgs_handler.c
lustre/mgs/mgs_internal.h
lustre/mgs/mgs_llog.c
lustre/obdclass/Makefile.in
lustre/obdclass/acl.c [new file with mode: 0644]
lustre/obdclass/genops.c
lustre/obdclass/idmap.c [new file with mode: 0644]
lustre/obdclass/obd_config.c
lustre/obdclass/obd_mount.c
lustre/obdfilter/filter.c
lustre/osc/lproc_osc.c
lustre/osc/osc_request.c
lustre/ost/ost_handler.c
lustre/ptlrpc/Makefile.in
lustre/ptlrpc/autoMakefile.am
lustre/ptlrpc/gss/autoMakefile.am
lustre/ptlrpc/gss/gss_api.h
lustre/ptlrpc/gss/gss_bulk.c
lustre/ptlrpc/gss/gss_cli_upcall.c
lustre/ptlrpc/gss/gss_internal.h
lustre/ptlrpc/gss/gss_keyring.c
lustre/ptlrpc/gss/gss_krb5_mech.c
lustre/ptlrpc/gss/gss_mech_switch.c
lustre/ptlrpc/gss/gss_pipefs.c
lustre/ptlrpc/gss/gss_rawobj.c
lustre/ptlrpc/gss/gss_svc_upcall.c
lustre/ptlrpc/gss/sec_gss.c
lustre/ptlrpc/import.c
lustre/ptlrpc/layout.c
lustre/ptlrpc/niobuf.c
lustre/ptlrpc/pack_generic.c
lustre/ptlrpc/ptlrpc_internal.h
lustre/ptlrpc/sec.c
lustre/ptlrpc/sec_bulk.c
lustre/ptlrpc/sec_config.c [new file with mode: 0644]
lustre/ptlrpc/sec_gc.c
lustre/ptlrpc/sec_lproc.c
lustre/ptlrpc/sec_null.c
lustre/ptlrpc/sec_plain.c
lustre/ptlrpc/service.c
lustre/tests/Makefile.am
lustre/tests/acceptance-small.sh
lustre/tests/conf-sanity.sh
lustre/tests/krb5_login.sh
lustre/tests/replay-dual.sh
lustre/tests/rmtacl/README [new file with mode: 0644]
lustre/tests/rmtacl/cp.test [new file with mode: 0644]
lustre/tests/rmtacl/getfacl-noacl.test [new file with mode: 0644]
lustre/tests/rmtacl/inheritance.test [new file with mode: 0644]
lustre/tests/rmtacl/make-tree [new file with mode: 0755]
lustre/tests/rmtacl/misc.test [new file with mode: 0644]
lustre/tests/rmtacl/permissions.test [new file with mode: 0644]
lustre/tests/rmtacl/run [new file with mode: 0755]
lustre/tests/rmtacl/setfacl.test [new file with mode: 0644]
lustre/tests/sanity-gss.sh
lustre/tests/sanity-sec.sh
lustre/tests/sanity.sh
lustre/tests/test-framework.sh
lustre/utils/Makefile.am
lustre/utils/gss/lgss_keyring.c
lustre/utils/gss/lgss_krb5_utils.c
lustre/utils/gss/lsupport.c
lustre/utils/gss/lsupport.h
lustre/utils/gss/nfs-utils-1.0.11-lustre.diff
lustre/utils/gss/svcgssd_proc.c
lustre/utils/l_facl.c [deleted file]
lustre/utils/l_getidentity.c
lustre/utils/lfs.c
lustre/utils/liblustreapi.c
lustre/utils/module_setup.sh

index 3422dfb..b0b0823 100644 (file)
@@ -61,6 +61,14 @@ Details    : If an OST is down the MDS will hang indefinitely in
             MDS QOS usage of statfs, it should not stuck in waiting.
 
 Severity   : enhancement
             MDS QOS usage of statfs, it should not stuck in waiting.
 
 Severity   : enhancement
+Bugzilla   : 11842
+Description: remote_acl support
+Details    : Support ACL-based permission check for remote user.
+             Support setfacl/getfacl for remote user with the utils
+             "lfs {l,r}{s,g}etfacl" which follow the same parameter format as
+             the system "{s,g}etfacl" utils.
+
+Severity   : enhancement
 Bugzilla   : 14288
 Description: Update to RHEL4 U6 kernel-2.6.9-67.EL.
 
 Bugzilla   : 14288
 Description: Update to RHEL4 U6 kernel-2.6.9-67.EL.
 
index 1dac9f0..dfa5738 100644 (file)
@@ -36,6 +36,8 @@ AC_DEFUN([AC_KERBEROS_V5],[
       AC_DEFINE_UNQUOTED(KRB5_VERSION, $K5VERS, [Define this as the Kerberos version number])
       if test -f $dir/include/gssapi/gssapi_krb5.h -a \
                 \( -f $dir/lib/libgssapi_krb5.a -o \
       AC_DEFINE_UNQUOTED(KRB5_VERSION, $K5VERS, [Define this as the Kerberos version number])
       if test -f $dir/include/gssapi/gssapi_krb5.h -a \
                 \( -f $dir/lib/libgssapi_krb5.a -o \
+                   -f $dir/lib64/libgssapi_krb5.a -o \
+                   -f $dir/lib64/libgssapi_krb5.so -o \
                    -f $dir/lib/libgssapi_krb5.so \) ; then
          AC_DEFINE(HAVE_KRB5, 1, [Define this if you have MIT Kerberos libraries])
          KRBDIR="$dir"
                    -f $dir/lib/libgssapi_krb5.so \) ; then
          AC_DEFINE(HAVE_KRB5, 1, [Define this if you have MIT Kerberos libraries])
          KRBDIR="$dir"
@@ -91,6 +93,14 @@ AC_DEFUN([AC_KERBEROS_V5],[
   AC_CHECK_LIB($gssapi_lib, gss_krb5_ccache_name,
     AC_DEFINE(HAVE_GSS_KRB5_CCACHE_NAME, 1, [Define this if the Kerberos GSS library supports gss_krb5_ccache_name]), ,$KRBLIBS)
 
   AC_CHECK_LIB($gssapi_lib, gss_krb5_ccache_name,
     AC_DEFINE(HAVE_GSS_KRB5_CCACHE_NAME, 1, [Define this if the Kerberos GSS library supports gss_krb5_ccache_name]), ,$KRBLIBS)
 
+  dnl Check for newer error message facility
+  AC_CHECK_LIB($gssapi_lib, krb5_get_error_message,
+    AC_DEFINE(HAVE_KRB5_GET_ERROR_MESSAGE, 1, [Define this if the function krb5_get_error_message is available]), ,$KRBLIBS)
+
+  dnl Check for function to specify addressless tickets
+  AC_CHECK_LIB($gssapi_lib, krb5_get_init_creds_opt_set_addressless,
+    AC_DEFINE(HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS, 1, [Define this if the function krb5_get_init_creds_opt_set_addressless is available]), ,$KRBLIBS)
+
   dnl If they specified a directory and it didn't work, give them a warning
   if test "x$krb5_with" != "x" -a "$krb5_with" != "$KRBDIR"; then
     AC_MSG_WARN(Using $KRBDIR instead of requested value of $krb5_with for Kerberos!)
   dnl If they specified a directory and it didn't work, give them a warning
   if test "x$krb5_with" != "x" -a "$krb5_with" != "$KRBDIR"; then
     AC_MSG_WARN(Using $KRBDIR instead of requested value of $krb5_with for Kerberos!)
index adf7c6e..27e62fc 100644 (file)
@@ -15,5 +15,5 @@ EXTRA_DIST = ioctl.h liblustre.h lprocfs_status.h lustre_cfg.h        \
             obd_cache.h obd_class.h obd_echo.h obd.h obd_lov.h \
             obd_ost.h obd_support.h lustre_ver.h lu_object.h lu_time.h  \
              md_object.h dt_object.h lustre_param.h lustre_mdt.h \
             obd_cache.h obd_class.h obd_echo.h obd.h obd_lov.h \
             obd_ost.h obd_support.h lustre_ver.h lu_object.h lu_time.h  \
              md_object.h dt_object.h lustre_param.h lustre_mdt.h \
-             lustre_fid.h lustre_fld.h lustre_req_layout.h lustre_capa.h
-
+             lustre_fid.h lustre_fld.h lustre_req_layout.h lustre_capa.h \
+             lustre_idmap.h lustre_eacl.h
index 0583ea4..153ac74 100644 (file)
 # ifdef CONFIG_FS_POSIX_ACL
 #  ifdef HAVE_XATTR_ACL
 #   include <linux/xattr_acl.h>
 # ifdef CONFIG_FS_POSIX_ACL
 #  ifdef HAVE_XATTR_ACL
 #   include <linux/xattr_acl.h>
-#  endif
+#  endif /* HAVE_XATTR_ACL */
 #  ifdef HAVE_LINUX_POSIX_ACL_XATTR_H
 #   include <linux/posix_acl_xattr.h>
 #  ifdef HAVE_LINUX_POSIX_ACL_XATTR_H
 #   include <linux/posix_acl_xattr.h>
-#  endif
-# endif
+#  endif /* HAVE_LINUX_POSIX_ACL_XATTR_H */
+# endif /* CONFIG_FS_POSIX_ACL */
 # ifndef HAVE_VFS_INTENT_PATCHES
 #  include <linux/lustre_intent.h>
 # endif
 # ifndef HAVE_VFS_INTENT_PATCHES
 #  include <linux/lustre_intent.h>
 # endif
-#endif
+#endif /* __KERNEL__ */
 
 /* ACL */
 #ifdef CONFIG_FS_POSIX_ACL
 
 /* ACL */
 #ifdef CONFIG_FS_POSIX_ACL
@@ -42,8 +42,8 @@
 
 # define LUSTRE_POSIX_ACL_MAX_SIZE   XATTR_ACL_SIZE
 
 
 # define LUSTRE_POSIX_ACL_MAX_SIZE   XATTR_ACL_SIZE
 
-#else /* CONFIG_FS_POSIX_ACL */
+# else /* CONFIG_FS_POSIX_ACL */
 # define LUSTRE_POSIX_ACL_MAX_SIZE      0
 # define LUSTRE_POSIX_ACL_MAX_SIZE      0
-#endif /* CONFIG_FS_POSIX_ACL */
+# endif /* CONFIG_FS_POSIX_ACL */
 
 #endif /* _LUSTRE_ACL_H */
 
 #endif /* _LUSTRE_ACL_H */
index 8e7c372..ce48c0d 100644 (file)
 # ifdef CONFIG_FS_POSIX_ACL
 #  ifdef HAVE_XATTR_ACL
 #   include <linux/xattr_acl.h>
 # ifdef CONFIG_FS_POSIX_ACL
 #  ifdef HAVE_XATTR_ACL
 #   include <linux/xattr_acl.h>
-#  endif 
+#  endif /* HAVE_XATTR_ACL */ 
 #  ifdef HAVE_LINUX_POSIX_ACL_XATTR_H
 #   include <linux/posix_acl_xattr.h>
 #  ifdef HAVE_LINUX_POSIX_ACL_XATTR_H
 #   include <linux/posix_acl_xattr.h>
-#  endif
-# endif
+#  endif /* HAVE_LINUX_POSIX_ACL_XATTR_H */
+# endif /* CONFIG_FS_POSIX_ACL */
 # ifndef HAVE_VFS_INTENT_PATCHES
 #  include <linux/lustre_intent.h>
 # endif
 # ifndef HAVE_VFS_INTENT_PATCHES
 #  include <linux/lustre_intent.h>
 # endif
-#endif
+#endif /* __KERNEL__ */
 
 struct mds_obd;
 struct ptlrpc_request;
 
 struct mds_obd;
 struct ptlrpc_request;
index 1cc27c4..e66a3a2 100644 (file)
@@ -52,7 +52,7 @@ struct lvfs_ucred {
         __u32                   luc_cap;
         __u32                   luc_umask;
        struct group_info      *luc_ginfo;
         __u32                   luc_cap;
         __u32                   luc_umask;
        struct group_info      *luc_ginfo;
-       struct mdt_identity    *luc_identity;
+       struct md_identity     *luc_identity;
 };
 
 struct lvfs_callback_ops {
 };
 
 struct lvfs_callback_ops {
index cf63180..0e5b2bf 100644 (file)
@@ -110,6 +110,10 @@ extern int llapi_quotacheck(char *mnt, int check_type);
 extern int llapi_poll_quotacheck(char *mnt, struct if_quotacheck *qchk);
 extern int llapi_quotactl(char *mnt, struct if_quotactl *qctl);
 extern int llapi_target_iterate(int type_num, char **obd_type, void *args, llapi_cb_t cb);
 extern int llapi_poll_quotacheck(char *mnt, struct if_quotacheck *qchk);
 extern int llapi_quotactl(char *mnt, struct if_quotactl *qctl);
 extern int llapi_target_iterate(int type_num, char **obd_type, void *args, llapi_cb_t cb);
-extern int llapi_getfacl(char *fname, char *cmd);
-extern int llapi_setfacl(char *fname, char *cmd);
+extern int llapi_lsetfacl(int argc, char *argv[]);
+extern int llapi_lgetfacl(int argc, char *argv[]);
+extern int llapi_rsetfacl(int argc, char *argv[]);
+extern int llapi_rgetfacl(int argc, char *argv[]);
+extern int llapi_cp(int argc, char *argv[]);
+extern int llapi_ls(int argc, char *argv[]);
 #endif
 #endif
index d308bbc..c877670 100644 (file)
@@ -753,9 +753,6 @@ extern void lustre_swab_lov_mds_md(struct lov_mds_md *llm);
 #define XATTR_NAME_ACL_DEFAULT  "system.posix_acl_default"
 #define XATTR_NAME_LOV          "trusted.lov"
 
 #define XATTR_NAME_ACL_DEFAULT  "system.posix_acl_default"
 #define XATTR_NAME_LOV          "trusted.lov"
 
-/* remote ACL */
-#define XATTR_NAME_LUSTRE_ACL   "system.lustre_acl"
-
 #define OBD_MD_FLID        (0x00000001ULL) /* object ID */
 #define OBD_MD_FLATIME     (0x00000002ULL) /* access time */
 #define OBD_MD_FLMTIME     (0x00000004ULL) /* data modification time */
 #define OBD_MD_FLID        (0x00000001ULL) /* object ID */
 #define OBD_MD_FLATIME     (0x00000002ULL) /* access time */
 #define OBD_MD_FLMTIME     (0x00000004ULL) /* data modification time */
@@ -803,6 +800,11 @@ extern void lustre_swab_lov_mds_md(struct lov_mds_md *llm);
 #define OBD_MD_FLCKSPLIT   (0x0000080000000000ULL) /* Check split on server */
 #define OBD_MD_FLCROSSREF  (0x0000100000000000ULL) /* Cross-ref case */
 
 #define OBD_MD_FLCKSPLIT   (0x0000080000000000ULL) /* Check split on server */
 #define OBD_MD_FLCROSSREF  (0x0000100000000000ULL) /* Cross-ref case */
 
+#define OBD_MD_FLRMTLSETFACL    (0x0001000000000000ULL) /* lfs lsetfacl case */
+#define OBD_MD_FLRMTLGETFACL    (0x0002000000000000ULL) /* lfs lgetfacl case */
+#define OBD_MD_FLRMTRSETFACL    (0x0004000000000000ULL) /* lfs rsetfacl case */
+#define OBD_MD_FLRMTRGETFACL    (0x0008000000000000ULL) /* lfs rgetfacl case */
+
 #define OBD_MD_FLGETATTR (OBD_MD_FLID    | OBD_MD_FLATIME | OBD_MD_FLMTIME | \
                           OBD_MD_FLCTIME | OBD_MD_FLSIZE  | OBD_MD_FLBLKSZ | \
                           OBD_MD_FLMODE  | OBD_MD_FLTYPE  | OBD_MD_FLUID   | \
 #define OBD_MD_FLGETATTR (OBD_MD_FLID    | OBD_MD_FLATIME | OBD_MD_FLMTIME | \
                           OBD_MD_FLCTIME | OBD_MD_FLSIZE  | OBD_MD_FLBLKSZ | \
                           OBD_MD_FLMODE  | OBD_MD_FLTYPE  | OBD_MD_FLUID   | \
@@ -1164,10 +1166,13 @@ struct mds_remote_perm {
         __u32           rp_access_perm; /* MAY_READ/WRITE/EXEC */
 };
 
         __u32           rp_access_perm; /* MAY_READ/WRITE/EXEC */
 };
 
-/* setxid permissions for mds_setxid_perm.mp_perm */
-#define LUSTRE_SETUID_PERM 0x01
-#define LUSTRE_SETGID_PERM 0x02
-#define LUSTRE_SETGRP_PERM 0x04
+/* permissions for md_perm.mp_perm */
+enum {
+        CFS_SETUID_PERM = 0x01,
+        CFS_SETGID_PERM = 0x02,
+        CFS_SETGRP_PERM = 0x04,
+        CFS_RMTACL_PERM = 0x08
+};
 
 extern void lustre_swab_mds_remote_perm(struct mds_remote_perm *p);
 
 
 extern void lustre_swab_mds_remote_perm(struct mds_remote_perm *p);
 
@@ -1294,6 +1299,8 @@ extern void lustre_swab_mdt_rec_setattr (struct mdt_rec_setattr *sa);
 #define MAY_VTX_PART    (1 << 12)
 /* full VTX permission check */
 #define MAY_VTX_FULL    (1 << 13)
 #define MAY_VTX_PART    (1 << 12)
 /* full VTX permission check */
 #define MAY_VTX_FULL    (1 << 13)
+/* lfs rgetfacl permission check */
+#define MAY_RGETFACL    (1 << 14)
 
 enum {
         MDS_CHECK_SPLIT  = 1 << 0,
 
 enum {
         MDS_CHECK_SPLIT  = 1 << 0,
index 8c17bc5..0dc8b87 100644 (file)
@@ -59,8 +59,7 @@ struct obd_statfs;
 #define IOC_OBD_STATFS                  _IOWR('f', 164, struct obd_statfs *)
 #define IOC_LOV_GETINFO                 _IOWR('f', 165, struct lov_user_mds_data *)
 #define LL_IOC_FLUSHCTX                 _IOW ('f', 166, long)
 #define IOC_OBD_STATFS                  _IOWR('f', 164, struct obd_statfs *)
 #define IOC_LOV_GETINFO                 _IOWR('f', 165, struct lov_user_mds_data *)
 #define LL_IOC_FLUSHCTX                 _IOW ('f', 166, long)
-#define LL_IOC_GETFACL                  _IOWR('f', 167, struct rmtacl_ioctl_data *)
-#define LL_IOC_SETFACL                  _IOWR('f', 168, struct rmtacl_ioctl_data *)
+#define LL_IOC_RMTACL                   _IOW ('f', 167, long)
 
 #define LL_IOC_LLOOP_ATTACH             _IOWR('f', 169, long)
 #define LL_IOC_LLOOP_DETACH             _IOWR('f', 170, long)
 
 #define LL_IOC_LLOOP_ATTACH             _IOWR('f', 169, long)
 #define LL_IOC_LLOOP_DETACH             _IOWR('f', 170, long)
@@ -89,6 +88,7 @@ struct obd_statfs;
 #define LL_FILE_IGNORE_LOCK             0x00000001
 #define LL_FILE_GROUP_LOCKED            0x00000002
 #define LL_FILE_READAHEAD               0x00000004
 #define LL_FILE_IGNORE_LOCK             0x00000001
 #define LL_FILE_GROUP_LOCKED            0x00000002
 #define LL_FILE_READAHEAD               0x00000004
+#define LL_FILE_RMTACL                  0x00000008
 
 #define LOV_USER_MAGIC_V1 0x0BD10BD0
 #define LOV_USER_MAGIC    LOV_USER_MAGIC_V1
 
 #define LOV_USER_MAGIC_V1 0x0BD10BD0
 #define LOV_USER_MAGIC    LOV_USER_MAGIC_V1
@@ -188,10 +188,10 @@ struct if_quotacheck {
 
 #define IDENTITY_DOWNCALL_MAGIC 0x6d6dd620
 
 
 #define IDENTITY_DOWNCALL_MAGIC 0x6d6dd620
 
-/* setxid permission */
-#define N_SETXID_PERMS_MAX      64
+/* permission */
+#define N_PERMS_MAX      64
 
 
-struct setxid_perm_downcall_data {
+struct perm_downcall_data {
         __u64 pdd_nid;
         __u32 pdd_perm;
 };
         __u64 pdd_nid;
         __u32 pdd_perm;
 };
@@ -202,21 +202,22 @@ struct identity_downcall_data {
         __u32                            idd_uid;
         __u32                            idd_gid;
         __u32                            idd_nperms;
         __u32                            idd_uid;
         __u32                            idd_gid;
         __u32                            idd_nperms;
-        struct setxid_perm_downcall_data idd_perms[N_SETXID_PERMS_MAX];
+        struct perm_downcall_data idd_perms[N_PERMS_MAX];
         __u32                            idd_ngroups;
         __u32                            idd_groups[0];
 };
 
         __u32                            idd_ngroups;
         __u32                            idd_groups[0];
 };
 
-#define RMTACL_DOWNCALL_MAGIC 0x6d6dd620
-#define RMTACL_SIZE_MAX     (4096)
+/* for non-mapped uid/gid */
+#define NOBODY_UID      99
+#define NOBODY_GID      99
 
 
-struct rmtacl_downcall_data {
-        __u32           add_magic;
-        __u32           add_handle;
-        __u64           add_key;
-        __u32           add_buflen;
-        __u32           add_padding;
-        __u8            add_buf[0];
+#define INVALID_ID      (-1)
+
+enum {
+        RMT_LSETFACL    = 1,
+        RMT_LGETFACL    = 2,
+        RMT_RSETFACL    = 3,
+        RMT_RGETFACL    = 4
 };
 
 #ifdef NEED_QUOTA_DEFS
 };
 
 #ifdef NEED_QUOTA_DEFS
@@ -284,12 +285,4 @@ struct if_quotactl {
 # define offsetof(typ,memb)     ((unsigned long)((char *)&(((typ *)0)->memb)))
 #endif
 
 # define offsetof(typ,memb)     ((unsigned long)((char *)&(((typ *)0)->memb)))
 #endif
 
-/* remote acl ioctl */
-struct rmtacl_ioctl_data {
-        char           *cmd;            /* IN */
-        unsigned long   cmd_len;
-        char           *res;            /* OUT */
-        unsigned long   res_len;
-};
-
 #endif /* _LUSTRE_USER_H */
 #endif /* _LUSTRE_USER_H */
index 89c5447..5432519 100644 (file)
@@ -58,7 +58,7 @@ enum lcfg_command_type {
         LCFG_LOV_ADD_INA    = 0x00ce013,
         LCFG_ADD_MDC        = 0x00cf014,
         LCFG_DEL_MDC        = 0x00cf015,
         LCFG_LOV_ADD_INA    = 0x00ce013,
         LCFG_ADD_MDC        = 0x00cf014,
         LCFG_DEL_MDC        = 0x00cf015,
-        LCFG_SEC_FLAVOR     = 0x00ce016,
+        LCFG_SPTLRPC_CONF   = 0x00cf016,
 };
 
 struct lustre_cfg_bufs {
 };
 
 struct lustre_cfg_bufs {
@@ -256,9 +256,8 @@ static inline int lustre_cfg_sanity_check(void *buf, int len)
         RETURN(0);
 }
 
         RETURN(0);
 }
 
-/* default value for nllu/nllg for llite */
-#define NOBODY_UID      99
-#define NOBODY_GID      99
+#include <lustre/lustre_user.h>
+
 #define INVALID_UID     (-1)
 
 #endif // _LUSTRE_CFG_H
 #define INVALID_UID     (-1)
 
 #endif // _LUSTRE_CFG_H
index fd8c664..98ede40 100644 (file)
@@ -141,10 +141,6 @@ struct lustre_mount_data {
         int        lmd_exclude_count;
         char      *lmd_dev;           /* device name */
         char      *lmd_profile;       /* client only */
         int        lmd_exclude_count;
         char      *lmd_dev;           /* device name */
         char      *lmd_profile;       /* client only */
-        char      *lmd_sec_mdt;       /* sec from mdt (to ost/mdt) */
-        char      *lmd_sec_cli;       /* sec from client (to ost/mdt) */
-        uid_t      lmd_nllu;          /* non-lustre-local-user id */
-        gid_t      lmd_nllg;          /* non-lustre-local-group id */
         char      *lmd_opts;          /* lustre mount options (as opposed to 
                                          _device_ mount options) */
         __u32     *lmd_exclude;       /* array of OSTs to ignore */
         char      *lmd_opts;          /* lustre mount options (as opposed to 
                                          _device_ mount options) */
         __u32     *lmd_exclude;       /* array of OSTs to ignore */
diff --git a/lustre/include/lustre_eacl.h b/lustre/include/lustre_eacl.h
new file mode 100644 (file)
index 0000000..dddfde5
--- /dev/null
@@ -0,0 +1,80 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *   This file is part of Lustre, http://www.lustre.org
+ *
+ * MDS data structures.
+ * See also lustre_idl.h for wire formats of requests.
+ */
+
+#ifndef _LUSTRE_EACL_H
+#define _LUSTRE_EACL_H
+
+#ifdef CONFIG_FS_POSIX_ACL
+
+# ifdef HAVE_XATTR_ACL
+#  include <linux/xattr_acl.h>
+# endif /* HAVE_XATTR_ACL */
+# ifdef HAVE_LINUX_POSIX_ACL_XATTR_H
+#  include <linux/posix_acl_xattr.h>
+# endif /* HAVE_LINUX_POSIX_ACL_XATTR_H */
+
+#include <lustre_idmap.h>
+#include <md_object.h>
+#include <lu_object.h>
+
+typedef struct {
+        __u16                   e_tag;
+        __u16                   e_perm;
+        __u32                   e_id;
+        __u32                   e_stat;
+} ext_acl_xattr_entry;
+
+typedef struct {
+        __u32                   a_count;
+        ext_acl_xattr_entry     a_entries[0];
+} ext_acl_xattr_header;
+
+#define CFS_ACL_XATTR_SIZE(count, prefix) \
+        (sizeof(prefix ## _header) + (count) * sizeof(prefix ## _entry))
+
+#define CFS_ACL_XATTR_COUNT(size, prefix) \
+        (((size) - sizeof(prefix ## _header)) / sizeof(prefix ## _entry))
+
+extern int lustre_posix_acl_permission(struct md_ucred *mu, struct lu_attr *la,
+                                       int want, posix_acl_xattr_entry *entry,
+                                       int count);
+extern int lustre_posix_acl_chmod_masq(posix_acl_xattr_entry *entry,
+                                       __u32 mode, int count);
+extern int lustre_posix_acl_create_masq(posix_acl_xattr_entry *entry,
+                                        __u32 *pmode, int count);
+
+extern ext_acl_xattr_header *
+lustre_posix_acl_xattr_2ext(posix_acl_xattr_header *header, int size);
+extern int
+lustre_posix_acl_xattr_filter(posix_acl_xattr_header *header, int size,
+                              posix_acl_xattr_header **out);
+extern int
+lustre_posix_acl_xattr_id2client(struct md_ucred *mu,
+                                 struct lustre_idmap_table *t,
+                                 posix_acl_xattr_header *header,
+                                 int size, int flags);
+extern void
+lustre_posix_acl_xattr_free(posix_acl_xattr_header *header, int size);
+extern int
+lustre_ext_acl_xattr_id2server(struct md_ucred *mu,
+                               struct lustre_idmap_table *t,
+                               ext_acl_xattr_header *header);
+extern void
+lustre_ext_acl_xattr_free(ext_acl_xattr_header *header);
+extern int
+lustre_acl_xattr_merge2posix(posix_acl_xattr_header *posix_header, int size,
+                             ext_acl_xattr_header *ext_header,
+                             posix_acl_xattr_header **out);
+extern ext_acl_xattr_header *
+lustre_acl_xattr_merge2ext(posix_acl_xattr_header *posix_header, int size,
+                           ext_acl_xattr_header *ext_header);
+
+#endif /* CONFIG_FS_POSIX_ACL */
+
+#endif
index 047c98c..c87468b 100644 (file)
@@ -23,9 +23,8 @@ struct mds_export_data {
         loff_t                  med_lr_off;
         int                     med_lr_idx;
         unsigned int            med_rmtclient:1; /* remote client? */
         loff_t                  med_lr_off;
         int                     med_lr_idx;
         unsigned int            med_rmtclient:1; /* remote client? */
-        __u32                   med_nllu;
-        __u32                   med_nllg;
-        struct mds_idmap_table *med_idmap;
+        struct semaphore           med_idmap_sem;
+        struct lustre_idmap_table *med_idmap;
 };
 
 struct mdt_export_data {
 };
 
 struct mdt_export_data {
@@ -37,9 +36,8 @@ struct mdt_export_data {
         loff_t                  med_lr_off;
         int                     med_lr_idx;
         unsigned int            med_rmtclient:1; /* remote client? */
         loff_t                  med_lr_off;
         int                     med_lr_idx;
         unsigned int            med_rmtclient:1; /* remote client? */
-        __u32                   med_nllu;
-        __u32                   med_nllg;
-        struct mdt_idmap_table *med_idmap;
+        struct semaphore           med_idmap_sem;
+        struct lustre_idmap_table *med_idmap;
 };
 
 struct osc_creator {
 };
 
 struct osc_creator {
@@ -111,7 +109,15 @@ struct obd_export {
                                   exp_req_replay_needed:1,
                                   exp_lock_replay_needed:1,
                                   exp_need_sync:1,
                                   exp_req_replay_needed:1,
                                   exp_lock_replay_needed:1,
                                   exp_need_sync:1,
+                                  exp_flvr_changed:1,
+                                  exp_flvr_adapt:1,
                                   exp_libclient:1; /* liblustre client? */
                                   exp_libclient:1; /* liblustre client? */
+        /* also protected by exp_lock */
+        enum lustre_sec_part      exp_sp_peer;
+        struct sptlrpc_flavor     exp_flvr;             /* current */
+        struct sptlrpc_flavor     exp_flvr_old[2];      /* about-to-expire */
+        cfs_time_t                exp_flvr_expire[2];   /* seconds */
+
         union {
                 struct mds_export_data    eu_mds_data;
                 struct mdt_export_data    eu_mdt_data;
         union {
                 struct mds_export_data    eu_mds_data;
                 struct mdt_export_data    eu_mdt_data;
diff --git a/lustre/include/lustre_idmap.h b/lustre/include/lustre_idmap.h
new file mode 100644 (file)
index 0000000..fa1a6cc
--- /dev/null
@@ -0,0 +1,63 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *   This file is part of Lustre, http://www.lustre.org
+ *
+ * MDS data structures.
+ * See also lustre_idl.h for wire formats of requests.
+ */
+
+#ifndef _LUSTRE_IDMAP_H
+#define _LUSTRE_IDMAP_H
+
+#include <md_object.h>
+
+#define CFS_NGROUPS_PER_BLOCK   ((int)(CFS_PAGE_SIZE / sizeof(gid_t)))
+
+#define CFS_GROUP_AT(gi, i) \
+        ((gi)->blocks[(i) / CFS_NGROUPS_PER_BLOCK][(i) % CFS_NGROUPS_PER_BLOCK])
+
+enum {
+        CFS_IC_NOTHING     = 0,    /* convert nothing */
+        CFS_IC_ALL         = 1,    /* convert all items */
+        CFS_IC_MAPPED      = 2,    /* convert mapped uid/gid */
+        CFS_IC_UNMAPPED    = 3     /* convert unmapped uid/gid */
+};
+
+#define  CFS_IDMAP_NOTFOUND     (-1)
+
+#define CFS_IDMAP_HASHSIZE      32
+
+enum lustre_idmap_idx {
+        RMT_UIDMAP_IDX,
+        LCL_UIDMAP_IDX,
+        RMT_GIDMAP_IDX,
+        LCL_GIDMAP_IDX,
+        CFS_IDMAP_N_HASHES
+};
+
+struct lustre_idmap_table {
+        spinlock_t       lit_lock;
+        struct list_head lit_idmaps[CFS_IDMAP_N_HASHES][CFS_IDMAP_HASHSIZE];
+};
+
+extern void lustre_groups_from_list(struct group_info *ginfo, gid_t *glist);
+extern void lustre_groups_sort(struct group_info *group_info);
+extern int lustre_in_group_p(struct md_ucred *mu, gid_t grp);
+
+extern int lustre_idmap_add(struct lustre_idmap_table *t,
+                            uid_t ruid, uid_t luid,
+                            gid_t rgid, gid_t lgid);
+extern int lustre_idmap_del(struct lustre_idmap_table *t,
+                            uid_t ruid, uid_t luid,
+                            gid_t rgid, gid_t lgid);
+extern int lustre_idmap_lookup_uid(struct md_ucred *mu,
+                                   struct lustre_idmap_table *t,
+                                   int reverse, uid_t uid);
+extern int lustre_idmap_lookup_gid(struct md_ucred *mu,
+                                   struct lustre_idmap_table *t,
+                                   int reverse, gid_t gid);
+extern struct lustre_idmap_table *lustre_idmap_init(void);
+extern void lustre_idmap_fini(struct lustre_idmap_table *t);
+
+#endif
index 5dee54a..7a5c761 100644 (file)
@@ -66,6 +66,8 @@ struct obd_import {
 
         struct obd_device        *imp_obd;
         struct ptlrpc_sec        *imp_sec;
 
         struct obd_device        *imp_obd;
         struct ptlrpc_sec        *imp_sec;
+        struct semaphore          imp_sec_mutex;
+        cfs_time_t                imp_sec_expire;
         cfs_waitq_t               imp_recovery_waitq;
 
         atomic_t                  imp_inflight;
         cfs_waitq_t               imp_recovery_waitq;
 
         atomic_t                  imp_inflight;
index f025ead..598754b 100644 (file)
 # ifdef CONFIG_FS_POSIX_ACL
 #  ifdef HAVE_XATTR_ACL
 #   include <linux/xattr_acl.h>
 # ifdef CONFIG_FS_POSIX_ACL
 #  ifdef HAVE_XATTR_ACL
 #   include <linux/xattr_acl.h>
-#  endif
+#  endif /*HAVE_XATTR_ACL */
 #  ifdef HAVE_LINUX_POSIX_ACL_XATTR_H
 #   include <linux/posix_acl_xattr.h>
 #  ifdef HAVE_LINUX_POSIX_ACL_XATTR_H
 #   include <linux/posix_acl_xattr.h>
-#  endif
-# endif
+#  endif /* HAVE_LINUX_POSIX_ACL_XATTR_H */
+# endif /* CONFIG_FS_POSIX_ACL */
 # ifndef HAVE_VFS_INTENT_PATCHES
 # include <linux/lustre_intent.h>
 # ifndef HAVE_VFS_INTENT_PATCHES
 # include <linux/lustre_intent.h>
-# endif
-#endif
+# endif /* HAVE_VFS_INTENT_PATCHES */
+#endif /* __KERNEL__ */
 #include <lustre_handles.h>
 #include <libcfs/kp30.h>
 #include <lustre/lustre_idl.h>
 #include <lustre_handles.h>
 #include <libcfs/kp30.h>
 #include <lustre/lustre_idl.h>
index 861a077..06ed6b1 100644 (file)
@@ -40,24 +40,6 @@ struct com_thread_info {
         struct req_capsule cti_pill;
 };
 
         struct req_capsule cti_pill;
 };
 
-/* id map */
-#define MDT_IDMAP_HASHSIZE      (32)
-#define MDT_IDMAP_HASHFUNC(id)  ((id) & (MDT_IDMAP_HASHSIZE - 1))
-
-enum mdt_idmap_idx {
-        RMT_UIDMAP_IDX,
-        LCL_UIDMAP_IDX,
-        RMT_GIDMAP_IDX,
-        LCL_GIDMAP_IDX,
-        MDT_IDMAP_N_HASHES
-};
-
-struct mdt_idmap_table {
-        spinlock_t       mit_lock;
-        struct list_head mit_idmaps[MDT_IDMAP_N_HASHES]
-                                   [MDT_IDMAP_HASHSIZE];
-};
-
 enum {
         ESERIOUS = 0x0001000
 };
 enum {
         ESERIOUS = 0x0001000
 };
index 0635010..ca69a55 100644 (file)
@@ -337,9 +337,12 @@ struct ptlrpc_request {
         struct ptlrpc_cli_ctx   *rq_cli_ctx;     /* client's half ctx */
         struct ptlrpc_svc_ctx   *rq_svc_ctx;     /* server's half ctx */
         struct list_head         rq_ctx_chain;   /* link to waited ctx */
         struct ptlrpc_cli_ctx   *rq_cli_ctx;     /* client's half ctx */
         struct ptlrpc_svc_ctx   *rq_svc_ctx;     /* server's half ctx */
         struct list_head         rq_ctx_chain;   /* link to waited ctx */
-        ptlrpc_sec_flavor_t      rq_sec_flavor;  /* client & server */
-                                 /* client security flags */
-        unsigned long            rq_ctx_init:1,      /* context initiation */
+
+        struct sptlrpc_flavor    rq_flvr;        /* client & server */
+        enum lustre_sec_part     rq_sp_from;
+
+        unsigned long            /* client/server security flags */
+                                 rq_ctx_init:1,      /* context initiation */
                                  rq_ctx_fini:1,      /* context destroy */
                                  rq_bulk_read:1,     /* request bulk read */
                                  rq_bulk_write:1,    /* request bulk write */
                                  rq_ctx_fini:1,      /* context destroy */
                                  rq_bulk_read:1,     /* request bulk read */
                                  rq_bulk_write:1,    /* request bulk write */
@@ -348,6 +351,9 @@ struct ptlrpc_request {
                                  rq_auth_remote:1,   /* authed as remote user */
                                  rq_auth_usr_root:1, /* authed as root */
                                  rq_auth_usr_mdt:1,  /* authed as mdt */
                                  rq_auth_remote:1,   /* authed as remote user */
                                  rq_auth_usr_root:1, /* authed as root */
                                  rq_auth_usr_mdt:1,  /* authed as mdt */
+                                 /* security tfm flags */
+                                 rq_pack_udesc:1,
+                                 rq_pack_bulk:1,
                                  /* doesn't expect reply FIXME */
                                  rq_no_reply:1;
 
                                  /* doesn't expect reply FIXME */
                                  rq_no_reply:1;
 
index 8acf23e..afcc851 100644 (file)
@@ -60,9 +60,9 @@ int do_lcfg(char *cfgname, lnet_nid_t nid, int cmd,
 #define PARAM_MDC                  "mdc."
 #define PARAM_LLITE                "llite."
 #define PARAM_LOV                  "lov."
 #define PARAM_MDC                  "mdc."
 #define PARAM_LLITE                "llite."
 #define PARAM_LOV                  "lov."
+#define PARAM_SRPC                 "srpc."
+#define PARAM_SRPC_FLVR            "srpc.flavor."
+#define PARAM_SRPC_UDESC           "srpc.udesc.cli2mdt"
 #define PARAM_SEC                  "security."
 #define PARAM_SEC                  "security."
-#define PARAM_SEC_RPC              PARAM_SEC"rpc."
-#define PARAM_SEC_RPC_MDT          PARAM_SEC_RPC"mdt="
-#define PARAM_SEC_RPC_CLI          PARAM_SEC_RPC"cli="
 
 #endif /* _LUSTRE_PARAM_H */
 
 #endif /* _LUSTRE_PARAM_H */
index e9fe854..6455858 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  * vim:expandtab:shiftwidth=8:tabstop=8:
  *
 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  * vim:expandtab:shiftwidth=8:tabstop=8:
  *
- * Copyright (C) 2004-2006 Cluster File Systems, Inc.
+ * Copyright (C) 2004-2007 Cluster File Systems, Inc.
  *
  *   This file is part of Lustre, http://www.lustre.org.
  *
  *
  *   This file is part of Lustre, http://www.lustre.org.
  *
@@ -32,6 +32,7 @@ struct ptlrpc_request;
 struct ptlrpc_reply_state;
 struct ptlrpc_bulk_desc;
 struct brw_page;
 struct ptlrpc_reply_state;
 struct ptlrpc_bulk_desc;
 struct brw_page;
+struct seq_file;
 
 /*
  * forward declaration
 
 /*
  * forward declaration
@@ -51,7 +52,6 @@ enum sptlrpc_policy {
         SPTLRPC_POLICY_NULL             = 0,
         SPTLRPC_POLICY_PLAIN            = 1,
         SPTLRPC_POLICY_GSS              = 2,
         SPTLRPC_POLICY_NULL             = 0,
         SPTLRPC_POLICY_PLAIN            = 1,
         SPTLRPC_POLICY_GSS              = 2,
-        SPTLRPC_POLICY_GSS_PIPEFS       = 3,
         SPTLRPC_POLICY_MAX,
 };
 
         SPTLRPC_POLICY_MAX,
 };
 
@@ -80,119 +80,169 @@ enum sptlrpc_service_type {
 };
 
 /*
 };
 
 /*
- * flavor compose/extract
+ * rpc flavor compose/extract, represented as 16 bits
+ *
+ * 4b (reserved) | 4b (svc) | 4b (mech)  | 4b (policy)
  */
  */
+#define RPC_FLVR_POLICY_OFFSET        (0)
+#define RPC_FLVR_MECH_OFFSET          (4)
+#define RPC_FLVR_SVC_OFFSET           (8)
 
 
-typedef __u32 ptlrpc_sec_flavor_t;
+#define MAKE_RPC_FLVR(policy, mech, svc)                                \
+        (((__u16)(policy) << RPC_FLVR_POLICY_OFFSET) |                  \
+         ((__u16)(mech) << RPC_FLVR_MECH_OFFSET) |                      \
+         ((__u16)(svc) << RPC_FLVR_SVC_OFFSET))
 
 
-/*
- *  8b (reserved)            | 8b (flags)
- *  4b (reserved) | 4b (svc) | 4b (mech)  | 4b (policy)
- */
-#define SEC_FLAVOR_POLICY_OFFSET        (0)
-#define SEC_FLAVOR_MECH_OFFSET          (4)
-#define SEC_FLAVOR_SVC_OFFSET           (8)
-#define SEC_FLAVOR_RESERVE1_OFFSET      (12)
-#define SEC_FLAVOR_FLAGS_OFFSET         (16)
-
-#define SEC_MAKE_RPC_FLAVOR(policy, mech, svc)                          \
-        (((__u32)(policy) << SEC_FLAVOR_POLICY_OFFSET) |                \
-         ((__u32)(mech) << SEC_FLAVOR_MECH_OFFSET) |                    \
-         ((__u32)(svc) << SEC_FLAVOR_SVC_OFFSET))
-
-#define SEC_MAKE_RPC_SUBFLAVOR(mech, svc)                               \
-        ((__u32)(mech) |                                                \
-         ((__u32)(svc) <<                                               \
-                (SEC_FLAVOR_SVC_OFFSET - SEC_FLAVOR_MECH_OFFSET)))
-
-#define SEC_FLAVOR_SUB(flavor)                                          \
-        ((((__u32)(flavor)) >> SEC_FLAVOR_MECH_OFFSET) & 0xFF)
-
-#define SEC_FLAVOR_POLICY(flavor)                                       \
-        ((((__u32)(flavor)) >> SEC_FLAVOR_POLICY_OFFSET) & 0xF)
-#define SEC_FLAVOR_MECH(flavor)                                         \
-        ((((__u32)(flavor)) >> SEC_FLAVOR_MECH_OFFSET) & 0xF)
-#define SEC_FLAVOR_SVC(flavor)                                          \
-        ((((__u32)(flavor)) >> SEC_FLAVOR_SVC_OFFSET) & 0xF)
-
-#define SEC_FLAVOR_RPC(f)                                               \
-        (((__u32) (f)) & ((1 << SEC_FLAVOR_RESERVE1_OFFSET) - 1))
+#define MAKE_RPC_SUBFLVR(mech, svc)                                     \
+        ((__u16)(mech) |                                                \
+         ((__u16)(svc) << (RPC_FLVR_SVC_OFFSET - RPC_FLVR_MECH_OFFSET)))
+
+#define RPC_FLVR_SUB(flavor)                                            \
+        ((((__u16)(flavor)) >> RPC_FLVR_MECH_OFFSET) & 0xFF)
+
+#define RPC_FLVR_POLICY(flavor)                                         \
+        ((((__u16)(flavor)) >> RPC_FLVR_POLICY_OFFSET) & 0xF)
+#define RPC_FLVR_MECH(flavor)                                           \
+        ((((__u16)(flavor)) >> RPC_FLVR_MECH_OFFSET) & 0xF)
+#define RPC_FLVR_SVC(flavor)                                            \
+        ((((__u16)(flavor)) >> RPC_FLVR_SVC_OFFSET) & 0xF)
 
 /*
  * gss subflavors
  */
 
 /*
  * gss subflavors
  */
-#define SPTLRPC_SUBFLVR_KRB5N                                   \
-        SEC_MAKE_RPC_SUBFLAVOR(SPTLRPC_MECH_GSS_KRB5,           \
-                               SPTLRPC_SVC_NULL)
-#define SPTLRPC_SUBFLVR_KRB5A                                   \
-        SEC_MAKE_RPC_SUBFLAVOR(SPTLRPC_MECH_GSS_KRB5,           \
-                               SPTLRPC_SVC_AUTH)
-#define SPTLRPC_SUBFLVR_KRB5I                                   \
-        SEC_MAKE_RPC_SUBFLAVOR(SPTLRPC_MECH_GSS_KRB5,           \
-                               SPTLRPC_SVC_INTG)
-#define SPTLRPC_SUBFLVR_KRB5P                                   \
-        SEC_MAKE_RPC_SUBFLAVOR(SPTLRPC_MECH_GSS_KRB5,           \
-                               SPTLRPC_SVC_PRIV)
+#define SPTLRPC_SUBFLVR_KRB5N                                           \
+        MAKE_RPC_SUBFLVR(SPTLRPC_MECH_GSS_KRB5, SPTLRPC_SVC_NULL)
+#define SPTLRPC_SUBFLVR_KRB5A                                           \
+        MAKE_RPC_SUBFLVR(SPTLRPC_MECH_GSS_KRB5, SPTLRPC_SVC_AUTH)
+#define SPTLRPC_SUBFLVR_KRB5I                                           \
+        MAKE_RPC_SUBFLVR(SPTLRPC_MECH_GSS_KRB5, SPTLRPC_SVC_INTG)
+#define SPTLRPC_SUBFLVR_KRB5P                                           \
+        MAKE_RPC_SUBFLVR(SPTLRPC_MECH_GSS_KRB5, SPTLRPC_SVC_PRIV)
 
 /*
  * "end user" flavors
  */
 
 /*
  * "end user" flavors
  */
-#define SPTLRPC_FLVR_NULL                                       \
-        SEC_MAKE_RPC_FLAVOR(SPTLRPC_POLICY_NULL,                \
-                            SPTLRPC_MECH_NULL,                  \
-                            SPTLRPC_SVC_NULL)
-#define SPTLRPC_FLVR_PLAIN                                      \
-        SEC_MAKE_RPC_FLAVOR(SPTLRPC_POLICY_PLAIN,               \
-                            SPTLRPC_MECH_PLAIN,                 \
-                            SPTLRPC_SVC_NULL)
-#define SPTLRPC_FLVR_KRB5N                                      \
-        SEC_MAKE_RPC_FLAVOR(SPTLRPC_POLICY_GSS,                 \
-                            SPTLRPC_MECH_GSS_KRB5,              \
-                            SPTLRPC_SVC_NULL)
-#define SPTLRPC_FLVR_KRB5A                                      \
-        SEC_MAKE_RPC_FLAVOR(SPTLRPC_POLICY_GSS,                 \
-                            SPTLRPC_MECH_GSS_KRB5,              \
-                            SPTLRPC_SVC_AUTH)
-#define SPTLRPC_FLVR_KRB5I                                      \
-        SEC_MAKE_RPC_FLAVOR(SPTLRPC_POLICY_GSS,                 \
-                            SPTLRPC_MECH_GSS_KRB5,              \
-                            SPTLRPC_SVC_INTG)
-#define SPTLRPC_FLVR_KRB5P                                      \
-        SEC_MAKE_RPC_FLAVOR(SPTLRPC_POLICY_GSS,                 \
-                            SPTLRPC_MECH_GSS_KRB5,              \
-                            SPTLRPC_SVC_PRIV)
-
-#define SPTLRPC_FLVR_INVALID            (-1)
+#define SPTLRPC_FLVR_NULL                               \
+        MAKE_RPC_FLVR(SPTLRPC_POLICY_NULL,              \
+                      SPTLRPC_MECH_NULL,                \
+                      SPTLRPC_SVC_NULL)
+#define SPTLRPC_FLVR_PLAIN                              \
+        MAKE_RPC_FLVR(SPTLRPC_POLICY_PLAIN,             \
+                      SPTLRPC_MECH_PLAIN,               \
+                      SPTLRPC_SVC_NULL)
+#define SPTLRPC_FLVR_KRB5N                              \
+        MAKE_RPC_FLVR(SPTLRPC_POLICY_GSS,               \
+                      SPTLRPC_MECH_GSS_KRB5,            \
+                      SPTLRPC_SVC_NULL)
+#define SPTLRPC_FLVR_KRB5A                              \
+        MAKE_RPC_FLVR(SPTLRPC_POLICY_GSS,               \
+                      SPTLRPC_MECH_GSS_KRB5,            \
+                      SPTLRPC_SVC_AUTH)
+#define SPTLRPC_FLVR_KRB5I                              \
+        MAKE_RPC_FLVR(SPTLRPC_POLICY_GSS,               \
+                      SPTLRPC_MECH_GSS_KRB5,            \
+                      SPTLRPC_SVC_INTG)
+#define SPTLRPC_FLVR_KRB5P                              \
+        MAKE_RPC_FLVR(SPTLRPC_POLICY_GSS,               \
+                      SPTLRPC_MECH_GSS_KRB5,            \
+                      SPTLRPC_SVC_PRIV)
+
+#define SPTLRPC_FLVR_INVALID            ((__u16) -1)
 
 #define SPTLRPC_FLVR_DEFAULT            SPTLRPC_FLVR_NULL
 
 /*
 
 #define SPTLRPC_FLVR_DEFAULT            SPTLRPC_FLVR_NULL
 
 /*
- * flavor flags (maximum 8 flags)
+ * 32 bits wire flavor (msg->lm_secflvr), lower 12 bits is the rpc flavor,
+ * higher 20 bits is not defined right now.
  */
  */
-#define SEC_FLAVOR_FL_BULK              (1 << (0 + SEC_FLAVOR_FLAGS_OFFSET))
-#define SEC_FLAVOR_FL_USER              (1 << (1 + SEC_FLAVOR_FLAGS_OFFSET))
+#define WIRE_FLVR_RPC(wflvr)            (((__u16) (wflvr)) & 0x0FFF)
+
+static inline void rpc_flvr_set_svc(__u16 *flvr, __u16 svc)
+{
+        LASSERT(svc < SPTLRPC_SVC_MAX);
+        *flvr = MAKE_RPC_FLVR(RPC_FLVR_POLICY(*flvr),
+                              RPC_FLVR_MECH(*flvr),
+                              svc);
+}
+
 
 
-#define SEC_FLAVOR_HAS_BULK(flavor)             \
-        (((flavor) & SEC_FLAVOR_FL_BULK) != 0)
-#define SEC_FLAVOR_HAS_USER(flavor)             \
-        (((flavor) & SEC_FLAVOR_FL_USER) != 0)
+struct sptlrpc_flavor {
+        __u16   sf_rpc;         /* rpc flavor */
+        __u8    sf_bulk_priv;   /* bulk encrypt alg */
+        __u8    sf_bulk_csum;   /* bulk checksum alg */
+        __u32   sf_flags;       /* general flags */
+};
 
 
+enum lustre_sec_part {
+        LUSTRE_SP_CLI           = 0,
+        LUSTRE_SP_MDT,
+        LUSTRE_SP_OST,
+        LUSTRE_SP_MGS,
+        LUSTRE_SP_ANY           = 0xFF
+};
 
 
-struct sec_flavor_config {
-        __u32   sfc_rpc_flavor; /* main rpc flavor */
-        __u32   sfc_bulk_priv;  /* bulk encryption algorithm */
-        __u32   sfc_bulk_csum;  /* bulk checksum algorithm */
-        __u32   sfc_flags;      /* extra flags */
+struct sptlrpc_rule {
+        __u32                   sr_netid;   /* LNET network ID */
+        __u8                    sr_from;    /* sec_part */
+        __u8                    sr_to;      /* sec_part */
+        __u16                   sr_padding;
+        struct sptlrpc_flavor   sr_flvr;
 };
 
 };
 
-enum lustre_part {
-        LUSTRE_CLI      = 0,
-        LUSTRE_MDT,
-        LUSTRE_OST,
-        LUSTRE_MGC,
-        LUSTRE_MGS,
+struct sptlrpc_rule_set {
+        int                     srs_nslot;
+        int                     srs_nrule;
+        struct sptlrpc_rule    *srs_rules;
+};
+
+#define SPTLRPC_CONF_LOG_MAX    (64)
+
+struct sptlrpc_conf_log {
+        __u32               scl_max;            /* maximum rules # */
+        __u32               scl_nrule;          /* rules # */
+        __u8                scl_part;           /* which part am i */
+        __u8                scl_pad0;
+        __u16               scl_pad1;
+        __u32               scl_pad2;
+        struct sptlrpc_rule scl_rules[SPTLRPC_CONF_LOG_MAX];
 };
 
 };
 
+static inline void sptlrpc_rule_set_init(struct sptlrpc_rule_set *set)
+{
+        memset(set, 0, sizeof(*set));
+}
+
+void sptlrpc_rule_set_free(struct sptlrpc_rule_set *set);
+int  sptlrpc_rule_set_expand(struct sptlrpc_rule_set *set, int expand);
+int  sptlrpc_rule_set_merge(struct sptlrpc_rule_set *set,
+                            struct sptlrpc_rule *rule,
+                            int expand);
+int sptlrpc_rule_set_from_log(struct sptlrpc_rule_set *rset,
+                              struct sptlrpc_conf_log *log);
+void sptlrpc_rule_set_choose(struct sptlrpc_rule_set *rset,
+                             enum lustre_sec_part from,
+                             lnet_nid_t nid,
+                             struct sptlrpc_flavor *flavor);
+void sptlrpc_rule_set_dump(struct sptlrpc_rule_set *set);
+
+struct sptlrpc_conf_log *sptlrpc_conf_log_alloc(void);
+void sptlrpc_conf_log_free(struct sptlrpc_conf_log *log);
+int sptlrpc_conf_log_populate(struct sptlrpc_rule_set *gen,
+                              struct sptlrpc_rule_set *tgt,
+                              enum lustre_sec_part from,
+                              enum lustre_sec_part to,
+                              unsigned int fl_udesc,
+                              struct sptlrpc_conf_log *log);
+struct sptlrpc_conf_log *sptlrpc_conf_log_extract(struct lustre_cfg *lcfg);
+void sptlrpc_conf_log_cleanup(struct sptlrpc_conf_log *log);
+void sptlrpc_conf_log_dump(struct sptlrpc_conf_log *log);
+
+const char *sptlrpc_part2name(enum lustre_sec_part part);
+enum lustre_sec_part sptlrpc_target_sec_part(struct obd_device *obd);
+
+int sptlrpc_cliobd_process_config(struct obd_device *obd,
+                                  struct lustre_cfg *lcfg);
+
 /* The maximum length of security payload. 1024 is enough for Kerberos 5,
  * and should be enough for other future mechanisms but not sure.
  * Only used by pre-allocated request/reply pool.
 /* The maximum length of security payload. 1024 is enough for Kerberos 5,
  * and should be enough for other future mechanisms but not sure.
  * Only used by pre-allocated request/reply pool.
@@ -275,11 +325,15 @@ struct ptlrpc_sec_cops {
          */
         struct ptlrpc_sec *     (*create_sec)  (struct obd_import *imp,
                                                 struct ptlrpc_svc_ctx *ctx,
          */
         struct ptlrpc_sec *     (*create_sec)  (struct obd_import *imp,
                                                 struct ptlrpc_svc_ctx *ctx,
-                                                __u32 flavor,
-                                                unsigned long flags);
+                                                struct sptlrpc_flavor *flavor);
         void                    (*destroy_sec) (struct ptlrpc_sec *sec);
 
         /*
         void                    (*destroy_sec) (struct ptlrpc_sec *sec);
 
         /*
+         * notify to-be-dead
+         */
+        void                    (*kill_sec)    (struct ptlrpc_sec *sec);
+
+        /*
          * context
          */
         struct ptlrpc_cli_ctx * (*lookup_ctx)  (struct ptlrpc_sec *sec,
          * context
          */
         struct ptlrpc_cli_ctx * (*lookup_ctx)  (struct ptlrpc_sec *sec,
@@ -324,7 +378,7 @@ struct ptlrpc_sec_cops {
          * misc
          */
         int                     (*display)     (struct ptlrpc_sec *sec,
          * misc
          */
         int                     (*display)     (struct ptlrpc_sec *sec,
-                                                char *buf, int buflen);
+                                                struct seq_file *seq);
 };
 
 struct ptlrpc_sec_sops {
 };
 
 struct ptlrpc_sec_sops {
@@ -350,24 +404,27 @@ struct ptlrpc_sec_sops {
 struct ptlrpc_sec_policy {
         struct module                  *sp_owner;
         char                           *sp_name;
 struct ptlrpc_sec_policy {
         struct module                  *sp_owner;
         char                           *sp_name;
-        __u32                           sp_policy; /* policy number */
+        __u16                           sp_policy; /* policy number */
         struct ptlrpc_sec_cops         *sp_cops;   /* client ops */
         struct ptlrpc_sec_sops         *sp_sops;   /* server ops */
 };
 
 #define PTLRPC_SEC_FL_REVERSE           0x0001 /* reverse sec */
 #define PTLRPC_SEC_FL_ROOTONLY          0x0002 /* treat everyone as root */
         struct ptlrpc_sec_cops         *sp_cops;   /* client ops */
         struct ptlrpc_sec_sops         *sp_sops;   /* server ops */
 };
 
 #define PTLRPC_SEC_FL_REVERSE           0x0001 /* reverse sec */
 #define PTLRPC_SEC_FL_ROOTONLY          0x0002 /* treat everyone as root */
-#define PTLRPC_SEC_FL_PAG               0x0004 /* PAG mode */
+#define PTLRPC_SEC_FL_UDESC             0x0004 /* ship udesc */
 #define PTLRPC_SEC_FL_BULK              0x0008 /* intensive bulk i/o expected */
 #define PTLRPC_SEC_FL_BULK              0x0008 /* intensive bulk i/o expected */
+#define PTLRPC_SEC_FL_PAG               0x0010 /* PAG mode */
 
 struct ptlrpc_sec {
         struct ptlrpc_sec_policy       *ps_policy;
         atomic_t                        ps_refcount;
 
 struct ptlrpc_sec {
         struct ptlrpc_sec_policy       *ps_policy;
         atomic_t                        ps_refcount;
-        __u32                           ps_flavor;      /* rpc flavor */
-        unsigned long                   ps_flags;       /* PTLRPC_SEC_FL_XX */
+        atomic_t                        ps_nctx;        /* statistic only */
+        int                             ps_id;          /* unique identifier */
+        struct sptlrpc_flavor           ps_flvr;        /* flavor */
+        enum lustre_sec_part            ps_part;
+        unsigned int                    ps_dying:1;
         struct obd_import              *ps_import;      /* owning import */
         spinlock_t                      ps_lock;        /* protect ccache */
         struct obd_import              *ps_import;      /* owning import */
         spinlock_t                      ps_lock;        /* protect ccache */
-        atomic_t                        ps_busy;        /* busy count */
         /*
          * garbage collection
          */
         /*
          * garbage collection
          */
@@ -378,12 +435,12 @@ struct ptlrpc_sec {
 
 static inline int sec_is_reverse(struct ptlrpc_sec *sec)
 {
 
 static inline int sec_is_reverse(struct ptlrpc_sec *sec)
 {
-        return (sec->ps_flags & PTLRPC_SEC_FL_REVERSE);
+        return (sec->ps_flvr.sf_flags & PTLRPC_SEC_FL_REVERSE);
 }
 
 static inline int sec_is_rootonly(struct ptlrpc_sec *sec)
 {
 }
 
 static inline int sec_is_rootonly(struct ptlrpc_sec *sec)
 {
-        return (sec->ps_flags & PTLRPC_SEC_FL_ROOTONLY);
+        return (sec->ps_flvr.sf_flags & PTLRPC_SEC_FL_ROOTONLY);
 }
 
 
 }
 
 
@@ -429,16 +486,16 @@ enum bulk_encrypt_alg {
 
 struct ptlrpc_bulk_sec_desc {
         __u32           bsd_version;
 
 struct ptlrpc_bulk_sec_desc {
         __u32           bsd_version;
-        __u32           bsd_pad;
-        __u32           bsd_csum_alg;   /* checksum algorithm */
-        __u32           bsd_priv_alg;   /* encrypt algorithm */
+        __u8            bsd_csum_alg;   /* checksum algorithm */
+        __u8            bsd_priv_alg;   /* encrypt algorithm */
+        __u16           bsd_pad;
         __u8            bsd_iv[16];     /* encrypt iv */
         __u8            bsd_csum[0];
 };
 
         __u8            bsd_iv[16];     /* encrypt iv */
         __u8            bsd_csum[0];
 };
 
-const char * sptlrpc_bulk_csum_alg2name(__u32 csum_alg);
-const char * sptlrpc_bulk_priv_alg2name(__u32 priv_alg);
-__u32 sptlrpc_bulk_priv_alg2flags(__u32 priv_alg);
+const char * sptlrpc_bulk_csum_alg2name(__u8 csum_alg);
+const char * sptlrpc_bulk_priv_alg2name(__u8 priv_alg);
+__u32 sptlrpc_bulk_priv_alg2flags(__u8 priv_alg);
 
 /*
  * lprocfs
 
 /*
  * lprocfs
@@ -474,8 +531,9 @@ void _sptlrpc_enlarge_msg_inplace(struct lustre_msg *msg,
 int sptlrpc_register_policy(struct ptlrpc_sec_policy *policy);
 int sptlrpc_unregister_policy(struct ptlrpc_sec_policy *policy);
 
 int sptlrpc_register_policy(struct ptlrpc_sec_policy *policy);
 int sptlrpc_unregister_policy(struct ptlrpc_sec_policy *policy);
 
-__u32 sptlrpc_name2flavor(const char *name);
-char *sptlrpc_flavor2name(__u32 flavor);
+__u16 sptlrpc_name2rpcflavor(const char *name);
+const char *sptlrpc_rpcflavor2name(__u16 flavor);
+int sptlrpc_flavor2name(struct sptlrpc_flavor *sf, char *buf, int bufsize);
 
 static inline
 struct ptlrpc_sec_policy *sptlrpc_policy_get(struct ptlrpc_sec_policy *policy)
 
 static inline
 struct ptlrpc_sec_policy *sptlrpc_policy_get(struct ptlrpc_sec_policy *policy)
@@ -536,8 +594,15 @@ int cli_ctx_is_eternal(struct ptlrpc_cli_ctx *ctx)
 }
 
 /*
 }
 
 /*
+ * sec get/put
+ */
+struct ptlrpc_sec *sptlrpc_sec_get(struct ptlrpc_sec *sec);
+void sptlrpc_sec_put(struct ptlrpc_sec *sec);
+
+/*
  * internal apis which only used by policy impelentation
  */
  * internal apis which only used by policy impelentation
  */
+int  sptlrpc_get_next_secid(void);
 void sptlrpc_sec_destroy(struct ptlrpc_sec *sec);
 
 /*
 void sptlrpc_sec_destroy(struct ptlrpc_sec *sec);
 
 /*
@@ -565,10 +630,14 @@ void sptlrpc_request_out_callback(struct ptlrpc_request *req);
 /*
  * exported higher interface of import & request
  */
 /*
  * exported higher interface of import & request
  */
-int sptlrpc_import_get_sec(struct obd_import *imp, struct ptlrpc_svc_ctx *svc_ctx,
-                           __u32 flavor, unsigned long flags);
-void sptlrpc_import_put_sec(struct obd_import *imp);
+int sptlrpc_import_sec_adapt(struct obd_import *imp,
+                             struct ptlrpc_svc_ctx *ctx,
+                             __u16 rpc_flavor);
+struct ptlrpc_sec *sptlrpc_import_sec_ref(struct obd_import *imp);
+void sptlrpc_import_sec_put(struct obd_import *imp);
+
 int  sptlrpc_import_check_ctx(struct obd_import *imp);
 int  sptlrpc_import_check_ctx(struct obd_import *imp);
+void sptlrpc_import_inval_all_ctx(struct obd_import *imp);
 void sptlrpc_import_flush_root_ctx(struct obd_import *imp);
 void sptlrpc_import_flush_my_ctx(struct obd_import *imp);
 void sptlrpc_import_flush_all_ctx(struct obd_import *imp);
 void sptlrpc_import_flush_root_ctx(struct obd_import *imp);
 void sptlrpc_import_flush_my_ctx(struct obd_import *imp);
 void sptlrpc_import_flush_all_ctx(struct obd_import *imp);
@@ -578,8 +647,7 @@ int  sptlrpc_req_refresh_ctx(struct ptlrpc_request *req, long timeout);
 int  sptlrpc_req_replace_dead_ctx(struct ptlrpc_request *req);
 void sptlrpc_req_set_flavor(struct ptlrpc_request *req, int opcode);
 
 int  sptlrpc_req_replace_dead_ctx(struct ptlrpc_request *req);
 void sptlrpc_req_set_flavor(struct ptlrpc_request *req, int opcode);
 
-int sptlrpc_parse_flavor(enum lustre_part from, enum lustre_part to,
-                         char *str, struct sec_flavor_config *conf);
+int sptlrpc_parse_rule(char *param, struct sptlrpc_rule *rule);
 
 /* gc */
 void sptlrpc_gc_add_sec(struct ptlrpc_sec *sec);
 
 /* gc */
 void sptlrpc_gc_add_sec(struct ptlrpc_sec *sec);
@@ -588,8 +656,7 @@ void sptlrpc_gc_add_ctx(struct ptlrpc_cli_ctx *ctx);
 
 /* misc */
 const char * sec2target_str(struct ptlrpc_sec *sec);
 
 /* misc */
 const char * sec2target_str(struct ptlrpc_sec *sec);
-int sptlrpc_lprocfs_rd(char *page, char **start, off_t off, int count,
-                       int *eof, void *data);
+int sptlrpc_lprocfs_cliobd_attach(struct obd_device *dev);
 
 /*
  * server side
 
 /*
  * server side
@@ -600,8 +667,6 @@ enum secsvc_accept_res {
         SECSVC_DROP,
 };
 
         SECSVC_DROP,
 };
 
-int sptlrpc_target_export_check(struct obd_export *exp,
-                                struct ptlrpc_request *req);
 int  sptlrpc_svc_unwrap_request(struct ptlrpc_request *req);
 int  sptlrpc_svc_alloc_rs(struct ptlrpc_request *req, int msglen);
 int  sptlrpc_svc_wrap_reply(struct ptlrpc_request *req);
 int  sptlrpc_svc_unwrap_request(struct ptlrpc_request *req);
 int  sptlrpc_svc_alloc_rs(struct ptlrpc_request *req, int msglen);
 int  sptlrpc_svc_wrap_reply(struct ptlrpc_request *req);
@@ -610,6 +675,11 @@ void sptlrpc_svc_ctx_addref(struct ptlrpc_request *req);
 void sptlrpc_svc_ctx_decref(struct ptlrpc_request *req);
 void sptlrpc_svc_ctx_invalidate(struct ptlrpc_request *req);
 
 void sptlrpc_svc_ctx_decref(struct ptlrpc_request *req);
 void sptlrpc_svc_ctx_invalidate(struct ptlrpc_request *req);
 
+int  sptlrpc_target_export_check(struct obd_export *exp,
+                                 struct ptlrpc_request *req);
+void sptlrpc_target_update_exp_flavor(struct obd_device *obd,
+                                      struct sptlrpc_rule_set *rset);
+
 /*
  * reverse context
  */
 /*
  * reverse context
  */
@@ -647,7 +717,7 @@ int sptlrpc_pack_user_desc(struct lustre_msg *msg, int offset);
 int sptlrpc_unpack_user_desc(struct lustre_msg *msg, int offset);
 
 /* bulk helpers (internal use only by policies) */
 int sptlrpc_unpack_user_desc(struct lustre_msg *msg, int offset);
 
 /* bulk helpers (internal use only by policies) */
-int bulk_sec_desc_size(__u32 csum_alg, int request, int read);
+int bulk_sec_desc_size(__u8 csum_alg, int request, int read);
 int bulk_sec_desc_unpack(struct lustre_msg *msg, int offset);
 
 int bulk_csum_cli_request(struct ptlrpc_bulk_desc *desc, int read,
 int bulk_sec_desc_unpack(struct lustre_msg *msg, int offset);
 
 int bulk_csum_cli_request(struct ptlrpc_bulk_desc *desc, int read,
index 0cba634..ecfdab8 100644 (file)
 
 struct upcall_cache_entry;
 
 
 struct upcall_cache_entry;
 
-struct mdt_setxid_perm {
+struct md_perm {
         lnet_nid_t      mp_nid;
         __u32           mp_perm;
 };
 
         lnet_nid_t      mp_nid;
         __u32           mp_perm;
 };
 
-struct mdt_identity {
+struct md_identity {
         struct upcall_cache_entry *mi_uc_entry;
         uid_t                      mi_uid;
         gid_t                      mi_gid;
         struct group_info         *mi_ginfo;
         int                        mi_nperms;
         struct upcall_cache_entry *mi_uc_entry;
         uid_t                      mi_uid;
         gid_t                      mi_gid;
         struct group_info         *mi_ginfo;
         int                        mi_nperms;
-        struct mdt_setxid_perm    *mi_perms;
-};
-
-struct rmtacl_upcall_data {
-        uid_t                      aud_uid;
-        gid_t                      aud_gid;
-        char                      *aud_cmd;
-};
-
-struct mdt_rmtacl {
-        uid_t                      ra_uid;
-        gid_t                      ra_gid;
-        __u32                      ra_handle;
-        char                      *ra_cmd;
-        char                      *ra_buf;
+        struct md_perm            *mi_perms;
 };
 
 struct upcall_cache_entry {
         struct list_head        ue_hash;
         __u64                   ue_key;
 };
 
 struct upcall_cache_entry {
         struct list_head        ue_hash;
         __u64                   ue_key;
-//        __u64                   ue_primary;
-//        struct group_info      *ue_group_info;
         atomic_t                ue_refcount;
         int                     ue_flags;
         cfs_waitq_t             ue_waitq;
         cfs_time_t              ue_acquire_expire;
         cfs_time_t              ue_expire;
         union {
         atomic_t                ue_refcount;
         int                     ue_flags;
         cfs_waitq_t             ue_waitq;
         cfs_time_t              ue_acquire_expire;
         cfs_time_t              ue_expire;
         union {
-                struct mdt_identity     identity;
-                struct mdt_rmtacl       acl;
+                struct md_identity     identity;
         } u;
 };
 
         } u;
 };
 
index 42fbe90..432cf0d 100644 (file)
@@ -47,20 +47,15 @@ struct md_device_operations;
 struct md_object;
 
 
 struct md_object;
 
 
-typedef enum {
+enum {
         UCRED_INVALID   = -1,
         UCRED_INIT      = 0,
         UCRED_OLD       = 1,
         UCRED_INVALID   = -1,
         UCRED_INIT      = 0,
         UCRED_OLD       = 1,
-        UCRED_NEW       = 2,
-} ucred_t;
-
-#define SQUASH_NONE     0x00
-#define SQUASH_UID      0x01
-#define SQUASH_GID      0x02
+        UCRED_NEW       = 2
+};
 
 struct md_ucred {
 
 struct md_ucred {
-        ucred_t                 mu_valid;
-        __u32                   mu_squash;
+        __u32               mu_valid;
         __u32                   mu_o_uid;
         __u32                   mu_o_gid;
         __u32                   mu_o_fsuid;
         __u32                   mu_o_uid;
         __u32                   mu_o_gid;
         __u32                   mu_o_fsuid;
@@ -73,7 +68,7 @@ struct md_ucred {
         __u32                   mu_cap;
         __u32                   mu_umask;
        struct group_info      *mu_ginfo;
         __u32                   mu_cap;
         __u32                   mu_umask;
        struct group_info      *mu_ginfo;
-       struct mdt_identity    *mu_identity;
+       struct md_identity *mu_identity;
 };
 
 #define MD_CAPAINFO_MAX 5
 };
 
 #define MD_CAPAINFO_MAX 5
index 8d6e9f1..1515bab 100644 (file)
@@ -370,6 +370,10 @@ struct filter_obd {
         int                      fo_fmd_max_num; /* per exp filter_mod_data */
         int                      fo_fmd_max_age; /* jiffies to fmd expiry */
 
         int                      fo_fmd_max_num; /* per exp filter_mod_data */
         int                      fo_fmd_max_age; /* jiffies to fmd expiry */
 
+        /* sptlrpc stuff */
+        rwlock_t                 fo_sptlrpc_lock;
+        struct sptlrpc_rule_set  fo_sptlrpc_rset;
+
         /* capability related */
         unsigned int             fo_fl_oss_capa;
         struct list_head         fo_capa_keys;
         /* capability related */
         unsigned int             fo_fl_oss_capa;
         struct list_head         fo_capa_keys;
@@ -399,7 +403,8 @@ struct client_obd {
         int                      cl_max_mds_cookiesize;
 
         /* security configuration */
         int                      cl_max_mds_cookiesize;
 
         /* security configuration */
-        struct sec_flavor_config cl_sec_conf;
+        struct sptlrpc_rule_set  cl_sptlrpc_rset;
+        enum lustre_sec_part     cl_sec_part;
 
         //struct llog_canceld_ctxt *cl_llcd; /* it's included by obd_llog_ctxt */
         void                    *cl_llcd_offset;
 
         //struct llog_canceld_ctxt *cl_llcd; /* it's included by obd_llog_ctxt */
         void                    *cl_llcd_offset;
@@ -492,15 +497,6 @@ struct mgs_obd {
         cfs_proc_dir_entry_t            *mgs_proc_live;
 };
 
         cfs_proc_dir_entry_t            *mgs_proc_live;
 };
 
-/* hah, upper limit 64 should be enough */
-#define N_NOSQUASH_NIDS 64
-struct rootsquash_info {
-        uid_t           rsi_uid;
-        gid_t           rsi_gid;
-        int             rsi_n_nosquash_nids;
-        lnet_nid_t      rsi_nosquash_nids[N_NOSQUASH_NIDS];
-};
-
 struct mds_obd {
         /* NB this field MUST be first */
         struct obd_device_target         mds_obt;
 struct mds_obd {
         /* NB this field MUST be first */
         struct obd_device_target         mds_obt;
@@ -556,10 +552,6 @@ struct mds_obd {
                                          mds_fl_synced:1;
 
         struct upcall_cache             *mds_identity_cache;
                                          mds_fl_synced:1;
 
         struct upcall_cache             *mds_identity_cache;
-        struct upcall_cache             *mds_rmtacl_cache;
-
-        /* root squash */
-        struct rootsquash_info          *mds_rootsquash_info;
 
         /* for capability keys update */
         struct lustre_capa_key          *mds_capa_keys;
 
         /* for capability keys update */
         struct lustre_capa_key          *mds_capa_keys;
@@ -1070,7 +1062,8 @@ struct obd_ops {
         int (*o_connect)(const struct lu_env *env,
                          struct lustre_handle *conn, struct obd_device *src,
                          struct obd_uuid *cluuid, struct obd_connect_data *ocd);
         int (*o_connect)(const struct lu_env *env,
                          struct lustre_handle *conn, struct obd_device *src,
                          struct obd_uuid *cluuid, struct obd_connect_data *ocd);
-        int (*o_reconnect)(struct obd_export *exp, struct obd_device *src,
+        int (*o_reconnect)(const struct lu_env *env,
+                           struct obd_export *exp, struct obd_device *src,
                            struct obd_uuid *cluuid,
                            struct obd_connect_data *ocd);
         int (*o_disconnect)(struct obd_export *exp);
                            struct obd_uuid *cluuid,
                            struct obd_connect_data *ocd);
         int (*o_disconnect)(struct obd_export *exp);
@@ -1293,7 +1286,7 @@ struct md_ops {
                          struct ptlrpc_request **);
         int (*m_getattr_name)(struct obd_export *, const struct lu_fid *,
                               struct obd_capa *, const char *, int, obd_valid,
                          struct ptlrpc_request **);
         int (*m_getattr_name)(struct obd_export *, const struct lu_fid *,
                               struct obd_capa *, const char *, int, obd_valid,
-                              int, struct ptlrpc_request **);
+                              int, __u32, struct ptlrpc_request **);
         int (*m_intent_lock)(struct obd_export *, struct md_op_data *,
                              void *, int, struct lookup_intent *, int,
                              struct ptlrpc_request **,
         int (*m_intent_lock)(struct obd_export *, struct md_op_data *,
                              void *, int, struct lookup_intent *, int,
                              struct ptlrpc_request **,
@@ -1320,7 +1313,7 @@ struct md_ops {
 
         int (*m_setxattr)(struct obd_export *, const struct lu_fid *,
                           struct obd_capa *, obd_valid, const char *,
 
         int (*m_setxattr)(struct obd_export *, const struct lu_fid *,
                           struct obd_capa *, obd_valid, const char *,
-                          const char *, int, int, int,
+                          const char *, int, int, int, __u32,
                           struct ptlrpc_request **);
 
         int (*m_getxattr)(struct obd_export *, const struct lu_fid *,
                           struct ptlrpc_request **);
 
         int (*m_getxattr)(struct obd_export *, const struct lu_fid *,
@@ -1355,7 +1348,8 @@ struct md_ops {
                             renew_capa_cb_t cb);
 
         int (*m_get_remote_perm)(struct obd_export *, const struct lu_fid *,
                             renew_capa_cb_t cb);
 
         int (*m_get_remote_perm)(struct obd_export *, const struct lu_fid *,
-                                 struct obd_capa *, struct ptlrpc_request **);
+                                 struct obd_capa *, __u32,
+                                 struct ptlrpc_request **);
 
         /*
          * NOTE: If adding ops, add another LPROCFS_MD_OP_INIT() line to
 
         /*
          * NOTE: If adding ops, add another LPROCFS_MD_OP_INIT() line to
index 3f111f9..94cd618 100644 (file)
@@ -814,7 +814,8 @@ static inline int obd_connect(const struct lu_env *env,
         RETURN(rc);
 }
 
         RETURN(rc);
 }
 
-static inline int obd_reconnect(struct obd_export *exp,
+static inline int obd_reconnect(const struct lu_env *env,
+                                struct obd_export *exp,
                                 struct obd_device *obd,
                                 struct obd_uuid *cluuid,
                                 struct obd_connect_data *d)
                                 struct obd_device *obd,
                                 struct obd_uuid *cluuid,
                                 struct obd_connect_data *d)
@@ -831,7 +832,7 @@ static inline int obd_reconnect(struct obd_export *exp,
         OBD_CHECK_DT_OP(obd, reconnect, 0);
         OBD_COUNTER_INCREMENT(obd, reconnect);
 
         OBD_CHECK_DT_OP(obd, reconnect, 0);
         OBD_COUNTER_INCREMENT(obd, reconnect);
 
-        rc = OBP(obd, reconnect)(exp, obd, cluuid, d);
+        rc = OBP(obd, reconnect)(env, exp, obd, cluuid, d);
         /* check that only subset is granted */
         LASSERT(ergo(d != NULL,
                      (d->ocd_connect_flags & ocf) == d->ocd_connect_flags));
         /* check that only subset is granted */
         LASSERT(ergo(d != NULL,
                      (d->ocd_connect_flags & ocf) == d->ocd_connect_flags));
@@ -1751,7 +1752,7 @@ static inline int md_enqueue(struct obd_export *exp,
 static inline int md_getattr_name(struct obd_export *exp,
                                   const struct lu_fid *fid, struct obd_capa *oc,
                                   const char *name, int namelen,
 static inline int md_getattr_name(struct obd_export *exp,
                                   const struct lu_fid *fid, struct obd_capa *oc,
                                   const char *name, int namelen,
-                                  obd_valid valid, int ea_size,
+                                  obd_valid valid, int ea_size, __u32 suppgid,
                                   struct ptlrpc_request **request)
 {
         int rc;
                                   struct ptlrpc_request **request)
 {
         int rc;
@@ -1759,7 +1760,7 @@ static inline int md_getattr_name(struct obd_export *exp,
         EXP_CHECK_MD_OP(exp, getattr_name);
         EXP_MD_COUNTER_INCREMENT(exp, getattr_name);
         rc = MDP(exp->exp_obd, getattr_name)(exp, fid, oc, name, namelen,
         EXP_CHECK_MD_OP(exp, getattr_name);
         EXP_MD_COUNTER_INCREMENT(exp, getattr_name);
         rc = MDP(exp->exp_obd, getattr_name)(exp, fid, oc, name, namelen,
-                                             valid, ea_size, request);
+                                             valid, ea_size, suppgid, request);
         RETURN(rc);
 }
 
         RETURN(rc);
 }
 
@@ -1892,7 +1893,7 @@ static inline int md_setxattr(struct obd_export *exp,
                               const struct lu_fid *fid, struct obd_capa *oc,
                               obd_valid valid, const char *name,
                               const char *input, int input_size,
                               const struct lu_fid *fid, struct obd_capa *oc,
                               obd_valid valid, const char *name,
                               const char *input, int input_size,
-                              int output_size, int flags,
+                              int output_size, int flags, __u32 suppgid,
                               struct ptlrpc_request **request)
 {
         ENTRY;
                               struct ptlrpc_request **request)
 {
         ENTRY;
@@ -1900,7 +1901,7 @@ static inline int md_setxattr(struct obd_export *exp,
         EXP_MD_COUNTER_INCREMENT(exp, setxattr);
         RETURN(MDP(exp->exp_obd, setxattr)(exp, fid, oc, valid, name, input,
                                            input_size, output_size, flags,
         EXP_MD_COUNTER_INCREMENT(exp, setxattr);
         RETURN(MDP(exp->exp_obd, setxattr)(exp, fid, oc, valid, name, input,
                                            input_size, output_size, flags,
-                                           request));
+                                           suppgid, request));
 }
 
 static inline int md_getxattr(struct obd_export *exp,
 }
 
 static inline int md_getxattr(struct obd_export *exp,
@@ -1988,13 +1989,14 @@ static inline int md_init_ea_size(struct obd_export *exp, int easize,
 
 static inline int md_get_remote_perm(struct obd_export *exp,
                                      const struct lu_fid *fid,
 
 static inline int md_get_remote_perm(struct obd_export *exp,
                                      const struct lu_fid *fid,
-                                     struct obd_capa *oc,
+                                     struct obd_capa *oc, __u32 suppgid,
                                      struct ptlrpc_request **request)
 {
         ENTRY;
         EXP_CHECK_MD_OP(exp, get_remote_perm);
         EXP_MD_COUNTER_INCREMENT(exp, get_remote_perm);
                                      struct ptlrpc_request **request)
 {
         ENTRY;
         EXP_CHECK_MD_OP(exp, get_remote_perm);
         EXP_MD_COUNTER_INCREMENT(exp, get_remote_perm);
-        RETURN(MDP(exp->exp_obd, get_remote_perm)(exp, fid, oc, request));
+        RETURN(MDP(exp->exp_obd, get_remote_perm)(exp, fid, oc, suppgid,
+                                                  request));
 }
 
 static inline int md_renew_capa(struct obd_export *exp, struct obd_capa *ocapa,
 }
 
 static inline int md_renew_capa(struct obd_export *exp, struct obd_capa *ocapa,
index 013ad43..77bc38f 100644 (file)
@@ -3424,7 +3424,8 @@ CONFIG_X86_MPPARSE=y
 #
 # Security options
 #
 #
 # Security options
 #
-# CONFIG_KEYS is not set
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
 CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
 # CONFIG_SECURITY_NETWORK_XFRM is not set
 CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
 # CONFIG_SECURITY_NETWORK_XFRM is not set
index 3d04f51..2c071b6 100644 (file)
@@ -3424,7 +3424,8 @@ CONFIG_X86_MPPARSE=y
 #
 # Security options
 #
 #
 # Security options
 #
-# CONFIG_KEYS is not set
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
 CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
 # CONFIG_SECURITY_NETWORK_XFRM is not set
 CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
 # CONFIG_SECURITY_NETWORK_XFRM is not set
index 7391827..ab3b905 100644 (file)
@@ -2997,7 +2997,8 @@ CONFIG_RCU_TORTURE_TEST=m
 #
 # Security options
 #
 #
 # Security options
 #
-# CONFIG_KEYS is not set
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
 CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
 # CONFIG_SECURITY_NETWORK_XFRM is not set
 CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
 # CONFIG_SECURITY_NETWORK_XFRM is not set
index d5e00e7..d9a018d 100644 (file)
@@ -2985,7 +2985,8 @@ CONFIG_RCU_TORTURE_TEST=m
 #
 # Security options
 #
 #
 # Security options
 #
-# CONFIG_KEYS is not set
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
 CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
 # CONFIG_SECURITY_NETWORK_XFRM is not set
 CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
 # CONFIG_SECURITY_NETWORK_XFRM is not set
index 12ab289..197791e 100644 (file)
@@ -180,11 +180,10 @@ out:
 static void destroy_import(struct obd_import *imp)
 {
         /* drop security policy instance after all rpc finished/aborted
 static void destroy_import(struct obd_import *imp)
 {
         /* drop security policy instance after all rpc finished/aborted
-         * to let all busy credentials be released.
-         */
+         * to let all busy contexts be released. */
         class_import_get(imp);
         class_destroy_import(imp);
         class_import_get(imp);
         class_destroy_import(imp);
-        sptlrpc_import_put_sec(imp);
+        sptlrpc_import_sec_put(imp);
         class_import_put(imp);
 }
 
         class_import_put(imp);
 }
 
@@ -247,10 +246,8 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg)
 
         sema_init(&cli->cl_sem, 1);
         sema_init(&cli->cl_mgc_sem, 1);
 
         sema_init(&cli->cl_sem, 1);
         sema_init(&cli->cl_mgc_sem, 1);
-        cli->cl_sec_conf.sfc_rpc_flavor = SPTLRPC_FLVR_NULL;
-        cli->cl_sec_conf.sfc_bulk_csum = BULK_CSUM_ALG_NULL;
-        cli->cl_sec_conf.sfc_bulk_priv = BULK_PRIV_ALG_NULL;
-        cli->cl_sec_conf.sfc_flags = 0;
+        sptlrpc_rule_set_init(&cli->cl_sptlrpc_rset);
+        cli->cl_sec_part = LUSTRE_SP_ANY;
         cli->cl_conn_count = 0;
         memcpy(server_uuid.uuid, lustre_cfg_buf(lcfg, 2),
                min_t(unsigned int, LUSTRE_CFG_BUFLEN(lcfg, 2),
         cli->cl_conn_count = 0;
         memcpy(server_uuid.uuid, lustre_cfg_buf(lcfg, 2),
                min_t(unsigned int, LUSTRE_CFG_BUFLEN(lcfg, 2),
@@ -359,6 +356,7 @@ err:
 int client_obd_cleanup(struct obd_device *obddev)
 {
         ENTRY;
 int client_obd_cleanup(struct obd_device *obddev)
 {
         ENTRY;
+        sptlrpc_rule_set_free(&obddev->u.cli.cl_sptlrpc_rset);
         ldlm_put_ref(obddev->obd_force);
         RETURN(0);
 }
         ldlm_put_ref(obddev->obd_force);
         RETURN(0);
 }
@@ -400,11 +398,6 @@ int client_connect_import(const struct lu_env *env,
         if (rc != 0)
                 GOTO(out_ldlm, rc);
 
         if (rc != 0)
                 GOTO(out_ldlm, rc);
 
-        rc = sptlrpc_import_get_sec(imp, NULL, cli->cl_sec_conf.sfc_rpc_flavor,
-                                    cli->cl_sec_conf.sfc_flags);
-        if (rc)
-                GOTO(out_ldlm, rc);
-
         ocd = &imp->imp_connect_data;
         if (data) {
                 *ocd = *data;
         ocd = &imp->imp_connect_data;
         if (data) {
                 *ocd = *data;
@@ -810,7 +803,8 @@ dont_check_exports:
                                          &conn, target, &cluuid, data);
                 }
         } else {
                                          &conn, target, &cluuid, data);
                 }
         } else {
-                rc = obd_reconnect(export, target, &cluuid, data);
+                rc = obd_reconnect(req->rq_svc_thread->t_env,
+                                   export, target, &cluuid, data);
         }
         if (rc)
                 GOTO(out, rc);
         }
         if (rc)
                 GOTO(out, rc);
@@ -915,6 +909,20 @@ dont_check_exports:
                 /* destroyed import can be still referenced in ctxt */
                 obd_set_info_async(export, strlen(KEY_REVIMP_UPD), 
                                    KEY_REVIMP_UPD, 0, NULL, NULL);
                 /* destroyed import can be still referenced in ctxt */
                 obd_set_info_async(export, strlen(KEY_REVIMP_UPD), 
                                    KEY_REVIMP_UPD, 0, NULL, NULL);
+
+                /* in some recovery senarios, previous ctx init rpc handled
+                 * in sptlrpc_target_export_check() might be used to install
+                 * a reverse ctx in this reverse import, and later OBD_CONNECT
+                 * using the same gss ctx could reach here and following new
+                 * reverse import. note all reverse ctx in new/old import are
+                 * actually based on the same gss ctx. so we invalidate ctx
+                 * here before destroy import, otherwise flush old import will
+                 * lead to remote reverse ctx be destroied, thus the reverse
+                 * ctx of new import will lost its peer.
+                 * there might be a better way to deal with this???
+                 */
+                sptlrpc_import_inval_all_ctx(export->exp_imp_reverse);
+
                 destroy_import(export->exp_imp_reverse);
         }
 
                 destroy_import(export->exp_imp_reverse);
         }
 
@@ -938,8 +946,8 @@ dont_check_exports:
                 lustre_msg_add_op_flags(req->rq_repmsg, MSG_CONNECT_NEXT_VER);
         }
 
                 lustre_msg_add_op_flags(req->rq_repmsg, MSG_CONNECT_NEXT_VER);
         }
 
-        rc = sptlrpc_import_get_sec(revimp, req->rq_svc_ctx,
-                                    req->rq_sec_flavor, 0);
+        rc = sptlrpc_import_sec_adapt(revimp, req->rq_svc_ctx,
+                                      req->rq_flvr.sf_rpc);
         if (rc) {
                 CERROR("Failed to get sec for reverse import: %d\n", rc);
                 export->exp_imp_reverse = NULL;
         if (rc) {
                 CERROR("Failed to get sec for reverse import: %d\n", rc);
                 export->exp_imp_reverse = NULL;
index 32a8d69..9e2e644 100644 (file)
@@ -1412,6 +1412,9 @@ static void ldlm_handle_gl_callback(struct ptlrpc_request *req,
 
 static int ldlm_callback_reply(struct ptlrpc_request *req, int rc)
 {
 
 static int ldlm_callback_reply(struct ptlrpc_request *req, int rc)
 {
+        if (req->rq_no_reply)
+                return 0;
+
         req->rq_status = rc;
         if (req->rq_reply_state == NULL) {
                 rc = lustre_pack_reply(req, 1, NULL, NULL);
         req->rq_status = rc;
         if (req->rq_reply_state == NULL) {
                 rc = lustre_pack_reply(req, 1, NULL, NULL);
index 97bba78..5cfb431 100644 (file)
@@ -1,7 +1,7 @@
 MODULES := lustre llite_lloop
 lustre-objs := dcache.o dir.o file.o llite_close.o llite_lib.o llite_nfs.o
 lustre-objs += llite_fid.o rw.o lproc_llite.o namei.o symlink.o llite_mmap.o
 MODULES := lustre llite_lloop
 lustre-objs := dcache.o dir.o file.o llite_close.o llite_lib.o llite_nfs.o
 lustre-objs += llite_fid.o rw.o lproc_llite.o namei.o symlink.o llite_mmap.o
-lustre-objs += xattr.o remote_perm.o llite_capa.o
+lustre-objs += xattr.o remote_perm.o llite_rmtacl.o llite_capa.o
 lustre-objs += rw26.o super25.o
 
 llite_lloop-objs := lloop.o
 lustre-objs += rw26.o super25.o
 
 llite_lloop-objs := lloop.o
index 2afec74..9f5f22a 100644 (file)
@@ -723,7 +723,7 @@ static int ll_dir_ioctl(struct inode *inode, struct file *file,
                 oc = ll_mdscapa_get(inode);
                 rc = md_getattr_name(sbi->ll_md_exp, ll_inode2fid(inode), oc,
                                      filename, namelen, OBD_MD_FLID, 0,
                 oc = ll_mdscapa_get(inode);
                 rc = md_getattr_name(sbi->ll_md_exp, ll_inode2fid(inode), oc,
                                      filename, namelen, OBD_MD_FLID, 0,
-                                     &request);
+                                     ll_i2suppgid(inode), &request);
                 capa_put(oc);
                 if (rc < 0) {
                         CDEBUG(D_INFO, "md_getattr_name: %d\n", rc);
                 capa_put(oc);
                 if (rc < 0) {
                         CDEBUG(D_INFO, "md_getattr_name: %d\n", rc);
@@ -1119,22 +1119,22 @@ static int ll_dir_ioctl(struct inode *inode, struct file *file,
         }
         case LL_IOC_FLUSHCTX:
                 RETURN(ll_flush_ctx(inode));
         }
         case LL_IOC_FLUSHCTX:
                 RETURN(ll_flush_ctx(inode));
-        case LL_IOC_GETFACL: {
-                struct rmtacl_ioctl_data ioc;
-
-                if (copy_from_user(&ioc, (void *)arg, sizeof(ioc)))
-                        RETURN(-EFAULT);
-
-                RETURN(ll_ioctl_getfacl(inode, &ioc));
-        }
-        case LL_IOC_SETFACL: {
-                struct rmtacl_ioctl_data ioc;
-
-                if (copy_from_user(&ioc, (void *)arg, sizeof(ioc)))
-                        RETURN(-EFAULT);
+#ifdef CONFIG_FS_POSIX_ACL
+        case LL_IOC_RMTACL: {
+            if (sbi->ll_flags & LL_SBI_RMT_CLIENT &&
+                inode == inode->i_sb->s_root->d_inode) {
+                struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
+                int rc;
 
 
-                RETURN(ll_ioctl_setfacl(inode, &ioc));
+                LASSERT(fd != NULL);
+                rc = rct_add(&sbi->ll_rct, cfs_curproc_pid(), arg);
+                if (!rc)
+                        fd->fd_flags |= LL_FILE_RMTACL;
+                RETURN(rc);
+            } else
+                RETURN(0);
         }
         }
+#endif
         default:
                 RETURN(obd_iocontrol(cmd, sbi->ll_dt_exp,0,NULL,(void *)arg));
         }
         default:
                 RETURN(obd_iocontrol(cmd, sbi->ll_dt_exp,0,NULL,(void *)arg));
         }
index 7a83bce..4ce948e 100644 (file)
@@ -286,9 +286,19 @@ int ll_file_release(struct inode *inode, struct file *file)
         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n", inode->i_ino,
                inode->i_generation, inode);
 
         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n", inode->i_ino,
                inode->i_generation, inode);
 
-        /* don't do anything for / */
-        if (inode->i_sb->s_root == file->f_dentry)
-                RETURN(0);
+#ifdef CONFIG_FS_POSIX_ACL
+        if (sbi->ll_flags & LL_SBI_RMT_CLIENT &&
+            inode == inode->i_sb->s_root->d_inode) {
+                struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
+
+                LASSERT(fd != NULL);
+                if (unlikely(fd->fd_flags & LL_FILE_RMTACL)) {
+                        fd->fd_flags &= ~LL_FILE_RMTACL;
+                        rct_del(&sbi->ll_rct, cfs_curproc_pid());
+                        et_search_free(&sbi->ll_et, cfs_curproc_pid());
+                }
+        }
+#endif
 
         ll_stats_ops_tally(sbi, LPROC_LL_RELEASE, 1);
         fd = LUSTRE_FPRIVATE(file);
 
         ll_stats_ops_tally(sbi, LPROC_LL_RELEASE, 1);
         fd = LUSTRE_FPRIVATE(file);
@@ -469,10 +479,6 @@ int ll_file_open(struct inode *inode, struct file *file)
         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), flags %o\n", inode->i_ino,
                inode->i_generation, inode, file->f_flags);
 
         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), flags %o\n", inode->i_ino,
                inode->i_generation, inode, file->f_flags);
 
-        /* don't do anything for / */
-        if (inode->i_sb->s_root == file->f_dentry)
-                RETURN(0);
-
 #ifdef HAVE_VFS_INTENT_PATCHES
         it = file->f_it;
 #else
 #ifdef HAVE_VFS_INTENT_PATCHES
         it = file->f_it;
 #else
@@ -1799,7 +1805,8 @@ int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename,
         oc = ll_mdscapa_get(inode);
         rc = md_getattr_name(sbi->ll_md_exp, ll_inode2fid(inode),
                              oc, filename, strlen(filename) + 1,
         oc = ll_mdscapa_get(inode);
         rc = md_getattr_name(sbi->ll_md_exp, ll_inode2fid(inode),
                              oc, filename, strlen(filename) + 1,
-                             OBD_MD_FLEASIZE | OBD_MD_FLDIREA, lmmsize, &req);
+                             OBD_MD_FLEASIZE | OBD_MD_FLDIREA, lmmsize,
+                             ll_i2suppgid(inode), &req);
         capa_put(oc);
         if (rc < 0) {
                 CDEBUG(D_INFO, "md_getattr_name failed "
         capa_put(oc);
         if (rc < 0) {
                 CDEBUG(D_INFO, "md_getattr_name failed "
@@ -2302,22 +2309,6 @@ int ll_file_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
         */
         case LL_IOC_FLUSHCTX:
                 RETURN(ll_flush_ctx(inode));
         */
         case LL_IOC_FLUSHCTX:
                 RETURN(ll_flush_ctx(inode));
-        case LL_IOC_GETFACL: {
-                struct rmtacl_ioctl_data ioc;
-
-                if (copy_from_user(&ioc, (void *)arg, sizeof(ioc)))
-                        RETURN(-EFAULT);
-
-                RETURN(ll_ioctl_getfacl(inode, &ioc));
-        }
-        case LL_IOC_SETFACL: {
-                struct rmtacl_ioctl_data ioc;
-
-                if (copy_from_user(&ioc, (void *)arg, sizeof(ioc)))
-                        RETURN(-EFAULT);
-
-                RETURN(ll_ioctl_setfacl(inode, &ioc));
-        }
         default: {
                 int err;
 
         default: {
                 int err;
 
index 6273f68..64022e5 100644 (file)
 # include <linux/fs.h>
 #ifdef HAVE_XATTR_ACL
 # include <linux/xattr_acl.h>
 # include <linux/fs.h>
 #ifdef HAVE_XATTR_ACL
 # include <linux/xattr_acl.h>
-#endif
+#endif /* HAVE_XATTR_ACL */
 #ifdef HAVE_LINUX_POSIX_ACL_XATTR_H
 # include <linux/posix_acl_xattr.h>
 #ifdef HAVE_LINUX_POSIX_ACL_XATTR_H
 # include <linux/posix_acl_xattr.h>
-#endif
-#endif
+#endif /* HAVE_LINUX_POSIX_ACL_XATTR_H */
+#endif /* CONFIG_FS_POSIX_ACL */
 
 #include <lustre_debug.h>
 #include <lustre_ver.h>
 #include <lustre_disk.h>  /* for s2sbi */
 
 #include <lustre_debug.h>
 #include <lustre_ver.h>
 #include <lustre_disk.h>  /* for s2sbi */
+#include <lustre_eacl.h>
 
 #ifndef FMODE_EXEC
 #define FMODE_EXEC 0
 
 #ifndef FMODE_EXEC
 #define FMODE_EXEC 0
@@ -233,6 +234,34 @@ enum stats_track_type {
 #define LL_SBI_LOCALFLOCK       0x200 /* Local flocks support by kernel */
 #define LL_SBI_LRU_RESIZE       0x400 /* lru resize support */
 
 #define LL_SBI_LOCALFLOCK       0x200 /* Local flocks support by kernel */
 #define LL_SBI_LRU_RESIZE       0x400 /* lru resize support */
 
+#define RCE_HASHES      32
+
+struct rmtacl_ctl_entry {
+        struct list_head rce_list;
+        pid_t            rce_key; /* hash key */
+        int              rce_ops; /* acl operation type */
+};
+
+struct rmtacl_ctl_table {
+        spinlock_t       rct_lock;
+        struct list_head rct_entries[RCE_HASHES];
+};
+
+#define EE_HASHES       32
+
+struct eacl_entry {
+        struct list_head      ee_list;
+        pid_t                 ee_key; /* hash key */
+        struct lu_fid         ee_fid;
+        int                   ee_type; /* ACL type for ACCESS or DEFAULT */
+        ext_acl_xattr_header *ee_acl;
+};
+
+struct eacl_table {
+        spinlock_t       et_lock;
+        struct list_head et_entries[EE_HASHES];
+};
+
 struct ll_sb_info {
         struct list_head          ll_list;
         /* this protects pglist and ra_info.  It isn't safe to
 struct ll_sb_info {
         struct list_head          ll_list;
         /* this protects pglist and ra_info.  It isn't safe to
@@ -285,6 +314,8 @@ struct ll_sb_info {
 
         dev_t                     ll_sdev_orig; /* save s_dev before assign for
                                                  * clustred nfs */
 
         dev_t                     ll_sdev_orig; /* save s_dev before assign for
                                                  * clustred nfs */
+        struct rmtacl_ctl_table   ll_rct;
+        struct eacl_table         ll_et;
 };
 
 #define LL_DEFAULT_MAX_RW_CHUNK         (32 * 1024 * 1024)
 };
 
 #define LL_DEFAULT_MAX_RW_CHUNK         (32 * 1024 * 1024)
@@ -392,6 +423,7 @@ struct it_cb_data {
         obd_id hash;
 };
 
         obd_id hash;
 };
 
+__u32 ll_i2suppgid(struct inode *i);
 void ll_i2gids(__u32 *suppgids, struct inode *i1,struct inode *i2);
 
 #define LLAP_MAGIC 98764321
 void ll_i2gids(__u32 *suppgids, struct inode *i1,struct inode *i2);
 
 #define LLAP_MAGIC 98764321
@@ -601,8 +633,6 @@ struct ll_async_page *llite_pglist_next_llap(struct ll_sb_info *sbi,
 int ll_obd_statfs(struct inode *inode, void *arg);
 int ll_get_max_mdsize(struct ll_sb_info *sbi, int *max_mdsize);
 int ll_process_config(struct lustre_cfg *lcfg);
 int ll_obd_statfs(struct inode *inode, void *arg);
 int ll_get_max_mdsize(struct ll_sb_info *sbi, int *max_mdsize);
 int ll_process_config(struct lustre_cfg *lcfg);
-int ll_ioctl_getfacl(struct inode *inode, struct rmtacl_ioctl_data *ioc);
-int ll_ioctl_setfacl(struct inode *inode, struct rmtacl_ioctl_data *ioc);
 struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data,
                                       struct inode *i1, struct inode *i2,
                                       const char *name, int namelen,
 struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data,
                                       struct inode *i1, struct inode *i2,
                                       const char *name, int namelen,
@@ -768,6 +798,25 @@ void ll_truncate_free_capa(struct obd_capa *ocapa);
 void ll_clear_inode_capas(struct inode *inode);
 void ll_print_capa_stat(struct ll_sb_info *sbi);
 
 void ll_clear_inode_capas(struct inode *inode);
 void ll_print_capa_stat(struct ll_sb_info *sbi);
 
+/* llite/llite_rmtacl.c */
+#ifdef CONFIG_FS_POSIX_ACL
+obd_valid rce_ops2valid(int ops);
+struct rmtacl_ctl_entry *rct_search(struct rmtacl_ctl_table *rct, pid_t key);
+int rct_add(struct rmtacl_ctl_table *rct, pid_t key, int ops);
+int rct_del(struct rmtacl_ctl_table *rct, pid_t key);
+void rct_init(struct rmtacl_ctl_table *rct);
+void rct_fini(struct rmtacl_ctl_table *rct);
+
+void ee_free(struct eacl_entry *ee);
+int ee_add(struct eacl_table *et, pid_t key, struct lu_fid *fid, int type,
+           ext_acl_xattr_header *header);
+struct eacl_entry *et_search_del(struct eacl_table *et, pid_t key,
+                                 struct lu_fid *fid, int type);
+void et_search_free(struct eacl_table *et, pid_t key);
+void et_init(struct eacl_table *et);
+void et_fini(struct eacl_table *et);
+#endif
+
 /* llite ioctl register support rountine */
 #ifdef __KERNEL__
 enum llioc_iter {
 /* llite ioctl register support rountine */
 #ifdef __KERNEL__
 enum llioc_iter {
index ed8ae79..0f91ebc 100644 (file)
@@ -161,8 +161,7 @@ static int ll_init_ea_size(struct obd_export *md_exp, struct obd_export *dt_exp)
         RETURN(rc);
 }
 
         RETURN(rc);
 }
 
-static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
-                                    uid_t nllu, gid_t nllg)
+static int client_common_fill_super(struct super_block *sb, char *md, char *dt)
 {
         struct inode *root = 0;
         struct ll_sb_info *sbi = ll_s2sbi(sb);
 {
         struct inode *root = 0;
         struct ll_sb_info *sbi = ll_s2sbi(sb);
@@ -238,8 +237,6 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
                 data->ocd_connect_flags &= ~OBD_CONNECT_RMT_CLIENT;
                 data->ocd_connect_flags |= OBD_CONNECT_LCL_CLIENT;
         }
                 data->ocd_connect_flags &= ~OBD_CONNECT_RMT_CLIENT;
                 data->ocd_connect_flags |= OBD_CONNECT_LCL_CLIENT;
         }
-        data->ocd_nllu = nllu;
-        data->ocd_nllg = nllg;
 
         err = obd_connect(NULL, &md_conn, obd, &sbi->ll_sb_uuid, data);
         if (err == -EBUSY) {
 
         err = obd_connect(NULL, &md_conn, obd, &sbi->ll_sb_uuid, data);
         if (err == -EBUSY) {
@@ -487,6 +484,13 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
                 GOTO(out_root, err);
         }
 
                 GOTO(out_root, err);
         }
 
+#ifdef CONFIG_FS_POSIX_ACL
+        if (sbi->ll_flags & LL_SBI_RMT_CLIENT) {
+                rct_init(&sbi->ll_rct);
+                et_init(&sbi->ll_et);
+        }
+#endif
+
         checksum = sbi->ll_flags & LL_SBI_CHECKSUM;
         err = obd_set_info_async(sbi->ll_dt_exp, strlen("checksum"),"checksum",
                                  sizeof(checksum), &checksum, NULL);
         checksum = sbi->ll_flags & LL_SBI_CHECKSUM;
         err = obd_set_info_async(sbi->ll_dt_exp, strlen("checksum"),"checksum",
                                  sizeof(checksum), &checksum, NULL);
@@ -675,6 +679,13 @@ void client_common_put_super(struct super_block *sb)
         struct ll_sb_info *sbi = ll_s2sbi(sb);
         ENTRY;
 
         struct ll_sb_info *sbi = ll_s2sbi(sb);
         ENTRY;
 
+#ifdef CONFIG_FS_POSIX_ACL
+        if (sbi->ll_flags & LL_SBI_RMT_CLIENT) {
+                et_fini(&sbi->ll_et);
+                rct_fini(&sbi->ll_rct);
+        }
+#endif
+
         obd_cancel_unused(sbi->ll_dt_exp, NULL, 0, NULL);
 
         ll_close_thread_shutdown(sbi->ll_lcq);
         obd_cancel_unused(sbi->ll_dt_exp, NULL, 0, NULL);
 
         ll_close_thread_shutdown(sbi->ll_lcq);
@@ -932,9 +943,7 @@ int ll_fill_super(struct super_block *sb)
         sprintf(md, "%s-%s", lprof->lp_md, ll_instance);
 
         /* connections, registrations, sb setup */
         sprintf(md, "%s-%s", lprof->lp_md, ll_instance);
 
         /* connections, registrations, sb setup */
-        err = client_common_fill_super(sb, md, dt,
-                                       lsi->lsi_lmd->lmd_nllu,
-                                       lsi->lsi_lmd->lmd_nllg);
+        err = client_common_fill_super(sb, md, dt);
 
 out_free:
         if (md)
 
 out_free:
         if (md)
@@ -2208,100 +2217,3 @@ void ll_finish_md_op_data(struct md_op_data *op_data)
         capa_put(op_data->op_capa2);
         OBD_FREE_PTR(op_data);
 }
         capa_put(op_data->op_capa2);
         OBD_FREE_PTR(op_data);
 }
-
-int ll_ioctl_getfacl(struct inode *inode, struct rmtacl_ioctl_data *ioc)
-{
-        struct ll_sb_info *sbi = ll_i2sbi(inode);
-        struct ptlrpc_request *req = NULL;
-        struct mdt_body *body;
-        char *cmd, *buf;
-        struct obd_capa *oc;
-        int rc, buflen;
-        ENTRY;
-
-        if (!(sbi->ll_flags & LL_SBI_RMT_CLIENT))
-                RETURN(-EBADE);
-
-        LASSERT(ioc->cmd && ioc->cmd_len && ioc->res && ioc->res_len);
-
-        OBD_ALLOC(cmd, ioc->cmd_len);
-        if (!cmd)
-                RETURN(-ENOMEM);
-        if (copy_from_user(cmd, ioc->cmd, ioc->cmd_len))
-                GOTO(out, rc = -EFAULT);
-
-        oc = ll_mdscapa_get(inode);
-        rc = md_getxattr(ll_i2sbi(inode)->ll_md_exp, ll_inode2fid(inode), oc,
-                         OBD_MD_FLXATTR, XATTR_NAME_LUSTRE_ACL, cmd,
-                         ioc->cmd_len, ioc->res_len, 0, &req);
-        capa_put(oc);
-        if (rc < 0) {
-                CERROR("mdc_getxattr %s [%s] failed: %d\n",
-                       XATTR_NAME_LUSTRE_ACL, cmd, rc);
-                GOTO(out, rc);
-        }
-
-        body = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof(*body));
-        LASSERT(body);
-
-        buflen = lustre_msg_buflen(req->rq_repmsg, REPLY_REC_OFF);
-        LASSERT(buflen <= ioc->res_len);
-        buf = lustre_msg_string(req->rq_repmsg, REPLY_REC_OFF + 1, ioc->res_len);
-        LASSERT(buf);
-        if (copy_to_user(ioc->res, buf, buflen))
-                GOTO(out, rc = -EFAULT);
-        EXIT;
-out:
-        if (req)
-                ptlrpc_req_finished(req);
-        OBD_FREE(cmd, ioc->cmd_len);
-        return rc;
-}
-
-int ll_ioctl_setfacl(struct inode *inode, struct rmtacl_ioctl_data *ioc)
-{
-        struct ll_sb_info *sbi = ll_i2sbi(inode);
-        struct ptlrpc_request *req = NULL;
-        char *cmd, *buf;
-        struct obd_capa *oc;
-        int buflen, rc;
-        ENTRY;
-
-        if (!(sbi->ll_flags & LL_SBI_RMT_CLIENT))
-                RETURN(-EBADE);
-
-        if (!(sbi->ll_flags & LL_SBI_ACL)) 
-                RETURN(-EOPNOTSUPP);
-
-        LASSERT(ioc->cmd && ioc->cmd_len && ioc->res && ioc->res_len);
-
-        OBD_ALLOC(cmd, ioc->cmd_len);
-        if (!cmd)
-                RETURN(-ENOMEM);
-        if (copy_from_user(cmd, ioc->cmd, ioc->cmd_len))
-                GOTO(out, rc = -EFAULT);
-
-        oc = ll_mdscapa_get(inode);
-        rc = md_setxattr(ll_i2sbi(inode)->ll_md_exp, ll_inode2fid(inode), oc,
-                         OBD_MD_FLXATTR, XATTR_NAME_LUSTRE_ACL, cmd,
-                         ioc->cmd_len, ioc->res_len, 0, &req);
-        capa_put(oc);
-        if (rc) {
-                CERROR("mdc_setxattr %s [%s] failed: %d\n",
-                       XATTR_NAME_LUSTRE_ACL, cmd, rc);
-                GOTO(out, rc);
-        }
-
-        buflen = lustre_msg_buflen(req->rq_repmsg, REPLY_REC_OFF);
-        LASSERT(buflen <= ioc->res_len);
-        buf = lustre_msg_string(req->rq_repmsg, REPLY_REC_OFF, ioc->res_len);
-        LASSERT(buf);
-        if (copy_to_user(ioc->res, buf, buflen))
-                GOTO(out, rc = -EFAULT);
-        EXIT;
-out:
-        if (req)
-                ptlrpc_req_finished(req);
-        OBD_FREE(cmd, ioc->cmd_len);
-        return rc;
-}
index 754e49d..afd0c9b 100644 (file)
@@ -213,7 +213,8 @@ static struct dentry *ll_get_parent(struct dentry *dchild)
                         dir->i_ino, PFID(ll_inode2fid(dir)));
 
         rc = md_getattr_name(sbi->ll_md_exp, ll_inode2fid(dir), NULL,
                         dir->i_ino, PFID(ll_inode2fid(dir)));
 
         rc = md_getattr_name(sbi->ll_md_exp, ll_inode2fid(dir), NULL,
-                             dotdot, strlen(dotdot) + 1, 0, 0, &req);
+                             dotdot, strlen(dotdot) + 1, 0, 0,
+                             ll_i2suppgid(dir), &req);
         if (rc) {
                 CERROR("failure %d inode %lu get parent\n", rc, dir->i_ino);
                 RETURN(ERR_PTR(rc));
         if (rc) {
                 CERROR("failure %d inode %lu get parent\n", rc, dir->i_ino);
                 RETURN(ERR_PTR(rc));
diff --git a/lustre/llite/llite_rmtacl.c b/lustre/llite/llite_rmtacl.c
new file mode 100644 (file)
index 0000000..924092d
--- /dev/null
@@ -0,0 +1,283 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *   lustre/llite/llite_rmtacl.c
+ *   Lustre Remote User Access Control List.
+ *   Author: Fan Yong <fanyong@clusterfs.com>
+ *
+ * Copyright (c) 2004-2007 Cluster File Systems, Inc.
+ *
+ *   This file is part of Lustre, http://www.lustre.org.
+ *
+ *   Lustre is free software; you can redistribute it and/or
+ *   modify it under the terms of version 2 of the GNU General Public
+ *   License as published by the Free Software Foundation.
+ *
+ *   Lustre is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Lustre; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define DEBUG_SUBSYSTEM S_LLITE
+
+#ifdef CONFIG_FS_POSIX_ACL
+
+#include <lustre_lite.h>
+#include "llite_internal.h"
+
+static inline __u32 rce_hashfunc(uid_t id)
+{
+        return id & (RCE_HASHES - 1);
+}
+
+static inline __u32 ee_hashfunc(uid_t id)
+{
+        return id & (EE_HASHES - 1);
+}
+
+obd_valid rce_ops2valid(int ops)
+{
+        switch (ops) {
+        case RMT_LSETFACL:
+                return OBD_MD_FLRMTLSETFACL;
+        case RMT_LGETFACL:
+                return OBD_MD_FLRMTLGETFACL;
+        case RMT_RSETFACL:
+                return OBD_MD_FLRMTRSETFACL;
+        case RMT_RGETFACL:
+                return OBD_MD_FLRMTRGETFACL;
+        default:
+                return 0;
+        }
+}
+
+static struct rmtacl_ctl_entry *rce_alloc(pid_t key, int ops)
+{
+        struct rmtacl_ctl_entry *rce;
+
+        OBD_ALLOC_PTR(rce);
+        if (!rce)
+                return NULL;
+
+        CFS_INIT_LIST_HEAD(&rce->rce_list);
+        rce->rce_key = key;
+        rce->rce_ops = ops;
+
+        return rce;
+}
+
+static void rce_free(struct rmtacl_ctl_entry *rce)
+{
+        if (!list_empty(&rce->rce_list))
+                list_del(&rce->rce_list);
+
+        OBD_FREE_PTR(rce);
+}
+
+static struct rmtacl_ctl_entry *__rct_search(struct rmtacl_ctl_table *rct,
+                                           pid_t key)
+{
+        struct rmtacl_ctl_entry *rce;
+        struct list_head *head = &rct->rct_entries[rce_hashfunc(key)];
+
+        list_for_each_entry(rce, head, rce_list)
+                if (rce->rce_key == key)
+                        return rce;
+
+        return NULL;
+}
+
+struct rmtacl_ctl_entry *rct_search(struct rmtacl_ctl_table *rct, pid_t key)
+{
+        struct rmtacl_ctl_entry *rce;
+
+        spin_lock(&rct->rct_lock);
+        rce = __rct_search(rct, key);
+        spin_unlock(&rct->rct_lock);
+        return rce;
+}
+
+int rct_add(struct rmtacl_ctl_table *rct, pid_t key, int ops)
+{
+        struct rmtacl_ctl_entry *rce, *e;
+
+        rce = rce_alloc(key, ops);
+        if (rce == NULL)
+                return -ENOMEM;
+
+        spin_lock(&rct->rct_lock);
+        e = __rct_search(rct, key);
+        if (unlikely(e != NULL)) {
+                CWARN("Unexpected stale rmtacl_entry found: "
+                      "[key: %d] [ops: %d]\n", (int)key, ops);
+                rce_free(e);
+        }
+        list_add_tail(&rce->rce_list, &rct->rct_entries[rce_hashfunc(key)]);
+        spin_unlock(&rct->rct_lock);
+
+        return 0;
+}
+
+int rct_del(struct rmtacl_ctl_table *rct, pid_t key)
+{
+        struct rmtacl_ctl_entry *rce;
+
+        spin_lock(&rct->rct_lock);
+        rce = __rct_search(rct, key);
+        if (rce)
+                rce_free(rce);
+        spin_unlock(&rct->rct_lock);
+
+        return rce ? 0 : -ENOENT;
+}
+
+void rct_init(struct rmtacl_ctl_table *rct)
+{
+        int i;
+
+        spin_lock_init(&rct->rct_lock);
+        for (i = 0; i < RCE_HASHES; i++)
+                CFS_INIT_LIST_HEAD(&rct->rct_entries[i]);
+}
+
+void rct_fini(struct rmtacl_ctl_table *rct)
+{
+        struct rmtacl_ctl_entry *rce;
+        int i;
+
+        spin_lock(&rct->rct_lock);
+        for (i = 0; i < RCE_HASHES; i++)
+                while (!list_empty(&rct->rct_entries[i])) {
+                        rce = list_entry(rct->rct_entries[i].next,
+                                         struct rmtacl_ctl_entry, rce_list);
+                        rce_free(rce);
+                }
+        spin_unlock(&rct->rct_lock);
+}
+
+
+static struct eacl_entry *ee_alloc(pid_t key, struct lu_fid *fid, int type,
+                                   ext_acl_xattr_header *header)
+{
+        struct eacl_entry *ee;
+
+        OBD_ALLOC_PTR(ee);
+        if (!ee)
+                return NULL;
+
+        CFS_INIT_LIST_HEAD(&ee->ee_list);
+        ee->ee_key = key;
+        ee->ee_fid = *fid;
+        ee->ee_type = type;
+        ee->ee_acl = header;
+
+        return ee;
+}
+
+void ee_free(struct eacl_entry *ee)
+{
+        if (!list_empty(&ee->ee_list))
+                list_del(&ee->ee_list);
+
+        if (ee->ee_acl)
+                lustre_ext_acl_xattr_free(ee->ee_acl);
+
+        OBD_FREE_PTR(ee);
+}
+
+static struct eacl_entry *__et_search_del(struct eacl_table *et, pid_t key,
+                                        struct lu_fid *fid, int type)
+{
+        struct eacl_entry *ee;
+        struct list_head *head = &et->et_entries[ee_hashfunc(key)];
+
+        LASSERT(fid != NULL);
+        list_for_each_entry(ee, head, ee_list)
+                if (ee->ee_key == key) {
+                        if (lu_fid_eq(&ee->ee_fid, fid) &&
+                            ee->ee_type == type) {
+                                list_del_init(&ee->ee_list);
+                                return ee;
+                        }
+                }
+
+        return NULL;
+}
+
+struct eacl_entry *et_search_del(struct eacl_table *et, pid_t key,
+                                 struct lu_fid *fid, int type)
+{
+        struct eacl_entry *ee;
+
+        spin_lock(&et->et_lock);
+        ee = __et_search_del(et, key, fid, type);
+        spin_unlock(&et->et_lock);
+        return ee;
+}
+
+void et_search_free(struct eacl_table *et, pid_t key)
+{
+        struct eacl_entry *ee, *next;
+        struct list_head *head = &et->et_entries[ee_hashfunc(key)];
+
+        spin_lock(&et->et_lock);
+        list_for_each_entry_safe(ee, next, head, ee_list)
+                if (ee->ee_key == key)
+                        ee_free(ee);
+
+        spin_unlock(&et->et_lock);
+}
+
+int ee_add(struct eacl_table *et, pid_t key, struct lu_fid *fid, int type,
+           ext_acl_xattr_header *header)
+{
+        struct eacl_entry *ee, *e;
+
+        ee = ee_alloc(key, fid, type, header);
+        if (ee == NULL)
+                return -ENOMEM;
+
+        spin_lock(&et->et_lock);
+        e = __et_search_del(et, key, fid, type);
+        if (unlikely(e != NULL)) {
+                CWARN("Unexpected stale eacl_entry found: "
+                      "[key: %d] [fid: "DFID"] [type: %d]\n",
+                      (int)key, PFID(fid), type);
+                ee_free(e);
+        }
+        list_add_tail(&ee->ee_list, &et->et_entries[ee_hashfunc(key)]);
+        spin_unlock(&et->et_lock);
+
+        return 0;
+}
+
+void et_init(struct eacl_table *et)
+{
+        int i;
+
+        spin_lock_init(&et->et_lock);
+        for (i = 0; i < EE_HASHES; i++)
+                CFS_INIT_LIST_HEAD(&et->et_entries[i]);
+}
+
+void et_fini(struct eacl_table *et)
+{
+        struct eacl_entry *ee;
+        int i;
+
+        spin_lock(&et->et_lock);
+        for (i = 0; i < EE_HASHES; i++)
+                while (!list_empty(&et->et_entries[i])) {
+                        ee = list_entry(et->et_entries[i].next,
+                                        struct eacl_entry, ee_list);
+                        ee_free(ee);
+                }
+        spin_unlock(&et->et_lock);
+}
+
+#endif
index e6e204a..c4cc5ed 100644 (file)
@@ -214,31 +214,35 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
         RETURN(0);
 }
 
         RETURN(0);
 }
 
+__u32 ll_i2suppgid(struct inode *i)
+{
+        if (in_group_p(i->i_gid))
+                return (__u32)i->i_gid;
+        else
+                return (__u32)(-1);
+}
+
 /* Pack the required supplementary groups into the supplied groups array.
  * If we don't need to use the groups from the target inode(s) then we
  * instead pack one or more groups from the user's supplementary group
  * array in case it might be useful.  Not needed if doing an MDS-side upcall. */
 void ll_i2gids(__u32 *suppgids, struct inode *i1, struct inode *i2)
 {
 /* Pack the required supplementary groups into the supplied groups array.
  * If we don't need to use the groups from the target inode(s) then we
  * instead pack one or more groups from the user's supplementary group
  * array in case it might be useful.  Not needed if doing an MDS-side upcall. */
 void ll_i2gids(__u32 *suppgids, struct inode *i1, struct inode *i2)
 {
+#if 0
         int i;
         int i;
+#endif
 
         LASSERT(i1 != NULL);
         LASSERT(suppgids != NULL);
 
 
         LASSERT(i1 != NULL);
         LASSERT(suppgids != NULL);
 
-        if (in_group_p(i1->i_gid))
-                suppgids[0] = i1->i_gid;
-        else
-                suppgids[0] = -1;
+        suppgids[0] = ll_i2suppgid(i1);
 
 
-        if (i2) {
-                if (in_group_p(i2->i_gid))
-                        suppgids[1] = i2->i_gid;
+        if (i2)
+                suppgids[1] = ll_i2suppgid(i2);
                 else
                         suppgids[1] = -1;
                 else
                         suppgids[1] = -1;
-        } else {
-                suppgids[1] = -1;
-        }
 
 
+#if 0
         for (i = 0; i < current_ngroups; i++) {
                 if (suppgids[0] == -1) {
                         if (current_groups[i] != suppgids[1])
         for (i = 0; i < current_ngroups; i++) {
                 if (suppgids[0] == -1) {
                         if (current_groups[i] != suppgids[1])
@@ -252,6 +256,7 @@ void ll_i2gids(__u32 *suppgids, struct inode *i1, struct inode *i2)
                 }
                 break;
         }
                 }
                 break;
         }
+#endif
 }
 
 static void ll_d_add(struct dentry *de, struct inode *inode)
 }
 
 static void ll_d_add(struct dentry *de, struct inode *inode)
index ac0aec0..e87239d 100644 (file)
@@ -263,7 +263,8 @@ check:
         }
 
         oc = ll_mdscapa_get(inode);
         }
 
         oc = ll_mdscapa_get(inode);
-        rc = md_get_remote_perm(sbi->ll_md_exp, ll_inode2fid(inode), oc, &req);
+        rc = md_get_remote_perm(sbi->ll_md_exp, ll_inode2fid(inode), oc,
+                                ll_i2suppgid(inode), &req);
         capa_put(oc);
         if (rc) {
                 up(&lli->lli_rmtperm_sem);
         capa_put(oc);
         if (rc) {
                 up(&lli->lli_rmtperm_sem);
index c040923..db1bd85 100644 (file)
@@ -79,10 +79,9 @@ int get_xattr_type(const char *name)
 static
 int xattr_type_filter(struct ll_sb_info *sbi, int xattr_type)
 {
 static
 int xattr_type_filter(struct ll_sb_info *sbi, int xattr_type)
 {
-        if (((xattr_type == XATTR_ACL_ACCESS_T) ||
-            (xattr_type == XATTR_ACL_DEFAULT_T)) &&
-            (!(sbi->ll_flags & LL_SBI_ACL) ||
-            (sbi->ll_flags & LL_SBI_RMT_CLIENT)))
+        if ((xattr_type == XATTR_ACL_ACCESS_T ||
+             xattr_type == XATTR_ACL_DEFAULT_T) &&
+           !(sbi->ll_flags & LL_SBI_ACL))
                 return -EOPNOTSUPP;
 
         if (xattr_type == XATTR_USER_T && !(sbi->ll_flags & LL_SBI_USER_XATTR))
                 return -EOPNOTSUPP;
 
         if (xattr_type == XATTR_USER_T && !(sbi->ll_flags & LL_SBI_USER_XATTR))
@@ -104,6 +103,10 @@ int ll_setxattr_common(struct inode *inode, const char *name,
         struct ptlrpc_request *req;
         int xattr_type, rc;
         struct obd_capa *oc;
         struct ptlrpc_request *req;
         int xattr_type, rc;
         struct obd_capa *oc;
+        posix_acl_xattr_header *new_value = NULL;
+        struct rmtacl_ctl_entry *rce = NULL;
+        ext_acl_xattr_header *acl = NULL;
+        const char *pv = value;
         ENTRY;
 
         xattr_type = get_xattr_type(name);
         ENTRY;
 
         xattr_type = get_xattr_type(name);
@@ -116,10 +119,61 @@ int ll_setxattr_common(struct inode *inode, const char *name,
             (xattr_type == XATTR_LUSTRE_T && strcmp(name, "lustre.lov") == 0))
                 RETURN(0);
 
             (xattr_type == XATTR_LUSTRE_T && strcmp(name, "lustre.lov") == 0))
                 RETURN(0);
 
+#ifdef CONFIG_FS_POSIX_ACL
+        if (sbi->ll_flags & LL_SBI_RMT_CLIENT &&
+            (xattr_type == XATTR_ACL_ACCESS_T ||
+            xattr_type == XATTR_ACL_DEFAULT_T)) {
+                rce = rct_search(&sbi->ll_rct, cfs_curproc_pid());
+                if (rce == NULL ||
+                    (rce->rce_ops != RMT_LSETFACL &&
+                    rce->rce_ops != RMT_RSETFACL))
+                        RETURN(-EOPNOTSUPP);
+
+                if (rce->rce_ops == RMT_LSETFACL) {
+                        struct eacl_entry *ee;
+
+                        ee = et_search_del(&sbi->ll_et, cfs_curproc_pid(),
+                                           ll_inode2fid(inode), xattr_type);
+                        LASSERT(ee != NULL);
+                        if (valid & OBD_MD_FLXATTR) {
+                                acl = lustre_acl_xattr_merge2ext(
+                                                (posix_acl_xattr_header *)value,
+                                                size, ee->ee_acl);
+                                if (IS_ERR(acl)) {
+                                        ee_free(ee);
+                                        RETURN(PTR_ERR(acl));
+                                }
+                                size =  CFS_ACL_XATTR_SIZE(\
+                                                le32_to_cpu(acl->a_count), \
+                                                ext_acl_xattr);
+                                pv = (const char *)acl;
+                        }
+                        ee_free(ee);
+                } else if (rce->rce_ops == RMT_RSETFACL) {
+                        size = lustre_posix_acl_xattr_filter(
+                                                (posix_acl_xattr_header *)value,
+                                                size, &new_value);
+                        if (unlikely(size < 0))
+                                RETURN(size);
+
+                        pv = (const char *)new_value;
+                } else
+                        RETURN(-EOPNOTSUPP);
+
+                valid |= rce_ops2valid(rce->rce_ops);
+        }
+#endif
         oc = ll_mdscapa_get(inode);
         oc = ll_mdscapa_get(inode);
-        rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc, valid, name,
-                         value, size, 0, flags, &req);
+        rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc,
+                         valid, name, pv, size, 0, flags, ll_i2suppgid(inode),
+                         &req);
         capa_put(oc);
         capa_put(oc);
+#ifdef CONFIG_FS_POSIX_ACL
+        if (new_value != NULL)
+                lustre_posix_acl_xattr_free(new_value, size);
+        if (acl != NULL)
+                lustre_ext_acl_xattr_free(acl);
+#endif
         if (rc) {
                 if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) {
                         LCONSOLE_INFO("Disabling user_xattr feature because "
         if (rc) {
                 if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) {
                         LCONSOLE_INFO("Disabling user_xattr feature because "
@@ -200,6 +254,7 @@ int ll_getxattr_common(struct inode *inode, const char *name,
         int xattr_type, rc;
         void *xdata;
         struct obd_capa *oc;
         int xattr_type, rc;
         void *xdata;
         struct obd_capa *oc;
+        struct rmtacl_ctl_entry *rce = NULL;
         ENTRY;
 
         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n",
         ENTRY;
 
         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n",
@@ -219,12 +274,27 @@ int ll_getxattr_common(struct inode *inode, const char *name,
         if (rc)
                 RETURN(rc);
 
         if (rc)
                 RETURN(rc);
 
+#ifdef CONFIG_FS_POSIX_ACL
+        if (sbi->ll_flags & LL_SBI_RMT_CLIENT &&
+            (xattr_type == XATTR_ACL_ACCESS_T ||
+            xattr_type == XATTR_ACL_DEFAULT_T)) {
+                rce = rct_search(&sbi->ll_rct, cfs_curproc_pid());
+                if (rce == NULL ||
+                    (rce->rce_ops != RMT_LSETFACL &&
+                    rce->rce_ops != RMT_LGETFACL &&
+                    rce->rce_ops != RMT_RSETFACL &&
+                    rce->rce_ops != RMT_RGETFACL))
+                        RETURN(-EOPNOTSUPP);
+        }
+#endif
+
         /* posix acl is under protection of LOOKUP lock. when calling to this,
          * we just have path resolution to the target inode, so we have great
          * chance that cached ACL is uptodate.
          */
 #ifdef CONFIG_FS_POSIX_ACL
         /* posix acl is under protection of LOOKUP lock. when calling to this,
          * we just have path resolution to the target inode, so we have great
          * chance that cached ACL is uptodate.
          */
 #ifdef CONFIG_FS_POSIX_ACL
-        if (xattr_type == XATTR_ACL_ACCESS_T) {
+        if (xattr_type == XATTR_ACL_ACCESS_T &&
+            !(sbi->ll_flags & LL_SBI_RMT_CLIENT)) {
                 struct ll_inode_info *lli = ll_i2info(inode);
                 struct posix_acl *acl;
 
                 struct ll_inode_info *lli = ll_i2info(inode);
                 struct posix_acl *acl;
 
@@ -243,8 +313,9 @@ int ll_getxattr_common(struct inode *inode, const char *name,
 
 do_getxattr:
         oc = ll_mdscapa_get(inode);
 
 do_getxattr:
         oc = ll_mdscapa_get(inode);
-        rc = md_getxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc, valid, name,
-                         NULL, 0, size, 0, &req);
+        rc = md_getxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc,
+                         valid | (rce ? rce_ops2valid(rce->rce_ops) : 0),
+                         name, NULL, 0, size, 0, &req);
         capa_put(oc);
         if (rc) {
                 if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) {
         capa_put(oc);
         if (rc) {
                 if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) {
@@ -285,12 +356,33 @@ do_getxattr:
                 GOTO(out, rc = -EFAULT);
         }
 
                 GOTO(out, rc = -EFAULT);
         }
 
+#ifdef CONFIG_FS_POSIX_ACL
+        if (body->eadatasize >= 0 && rce && rce->rce_ops == RMT_LSETFACL) {
+                ext_acl_xattr_header *acl;
+
+                acl = lustre_posix_acl_xattr_2ext((posix_acl_xattr_header *)xdata,
+                                                  body->eadatasize);
+                if (IS_ERR(acl))
+                        GOTO(out, rc = PTR_ERR(acl));
+
+                rc = ee_add(&sbi->ll_et, cfs_curproc_pid(), ll_inode2fid(inode),
+                            xattr_type, acl);
+                if (unlikely(rc < 0)) {
+                        lustre_ext_acl_xattr_free(acl);
+                        GOTO(out, rc);
+                }
+        }
+
+        if (xattr_type == XATTR_ACL_ACCESS_T && !body->eadatasize)
+                GOTO(out, rc = -ENODATA);
+#endif
         LASSERT(buffer);
         memcpy(buffer, xdata, body->eadatasize);
         rc = body->eadatasize;
         LASSERT(buffer);
         memcpy(buffer, xdata, body->eadatasize);
         rc = body->eadatasize;
+        EXIT;
 out:
         ptlrpc_req_finished(req);
 out:
         ptlrpc_req_finished(req);
-        RETURN(rc);
+        return rc;
 }
 
 ssize_t ll_getxattr(struct dentry *dentry, const char *name,
 }
 
 ssize_t ll_getxattr(struct dentry *dentry, const char *name,
index 9c6a4db..783f4b6 100644 (file)
@@ -1128,7 +1128,8 @@ static int lmv_getxattr(struct obd_export *exp, const struct lu_fid *fid,
 static int lmv_setxattr(struct obd_export *exp, const struct lu_fid *fid,
                         struct obd_capa *oc, obd_valid valid, const char *name,
                         const char *input, int input_size, int output_size,
 static int lmv_setxattr(struct obd_export *exp, const struct lu_fid *fid,
                         struct obd_capa *oc, obd_valid valid, const char *name,
                         const char *input, int input_size, int output_size,
-                        int flags, struct ptlrpc_request **request)
+                        int flags, __u32 suppgid,
+                        struct ptlrpc_request **request)
 {
         struct obd_device *obd = exp->exp_obd;
         struct lmv_obd *lmv = &obd->u.lmv;
 {
         struct obd_device *obd = exp->exp_obd;
         struct lmv_obd *lmv = &obd->u.lmv;
@@ -1145,7 +1146,8 @@ static int lmv_setxattr(struct obd_export *exp, const struct lu_fid *fid,
                 RETURN(PTR_ERR(tgt_exp));
 
         rc = md_setxattr(tgt_exp, fid, oc, valid, name,
                 RETURN(PTR_ERR(tgt_exp));
 
         rc = md_setxattr(tgt_exp, fid, oc, valid, name,
-                         input, input_size, output_size, flags, request);
+                         input, input_size, output_size, flags, suppgid,
+                         request);
 
         RETURN(rc);
 }
 
         RETURN(rc);
 }
@@ -1614,7 +1616,8 @@ lmv_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo,
 static int
 lmv_getattr_name(struct obd_export *exp, const struct lu_fid *fid,
                  struct obd_capa *oc, const char *filename, int namelen,
 static int
 lmv_getattr_name(struct obd_export *exp, const struct lu_fid *fid,
                  struct obd_capa *oc, const char *filename, int namelen,
-                 obd_valid valid, int ea_size, struct ptlrpc_request **request)
+                 obd_valid valid, int ea_size, __u32 suppgid,
+                 struct ptlrpc_request **request)
 {
         struct obd_device *obd = exp->exp_obd;
         struct lmv_obd *lmv = &obd->u.lmv;
 {
         struct obd_device *obd = exp->exp_obd;
         struct lmv_obd *lmv = &obd->u.lmv;
@@ -1654,7 +1657,7 @@ repeat:
                namelen, filename, PFID(fid), PFID(&rid));
 
         rc = md_getattr_name(tgt_exp, &rid, oc, filename, namelen, valid,
                namelen, filename, PFID(fid), PFID(&rid));
 
         rc = md_getattr_name(tgt_exp, &rid, oc, filename, namelen, valid,
-                             ea_size, request);
+                             ea_size, suppgid, request);
         if (rc == 0) {
                 body = lustre_msg_buf((*request)->rq_repmsg,
                                       REQ_REC_OFF, sizeof(*body));
         if (rc == 0) {
                 body = lustre_msg_buf((*request)->rq_repmsg,
                                       REQ_REC_OFF, sizeof(*body));
@@ -1676,7 +1679,7 @@ repeat:
 
                         rc = md_getattr_name(tgt_exp, &rid, NULL, NULL, 1,
                                              valid | OBD_MD_FLCROSSREF,
 
                         rc = md_getattr_name(tgt_exp, &rid, NULL, NULL, 1,
                                              valid | OBD_MD_FLCROSSREF,
-                                             ea_size, &req);
+                                             ea_size, suppgid, &req);
                         ptlrpc_req_finished(*request);
                         *request = req;
                 }
                         ptlrpc_req_finished(*request);
                         *request = req;
                 }
@@ -2796,7 +2799,7 @@ int lmv_clear_open_replay_data(struct obd_export *exp,
 
 static int lmv_get_remote_perm(struct obd_export *exp,
                                const struct lu_fid *fid,
 
 static int lmv_get_remote_perm(struct obd_export *exp,
                                const struct lu_fid *fid,
-                               struct obd_capa *oc,
+                               struct obd_capa *oc, __u32 suppgid,
                                struct ptlrpc_request **request)
 {
         struct obd_device *obd = exp->exp_obd;
                                struct ptlrpc_request **request)
 {
         struct obd_device *obd = exp->exp_obd;
@@ -2814,7 +2817,7 @@ static int lmv_get_remote_perm(struct obd_export *exp,
         if (IS_ERR(tgt_exp))
                 RETURN(PTR_ERR(tgt_exp));
 
         if (IS_ERR(tgt_exp))
                 RETURN(PTR_ERR(tgt_exp));
 
-        rc = md_get_remote_perm(tgt_exp, fid, oc, request);
+        rc = md_get_remote_perm(tgt_exp, fid, oc, suppgid, request);
 
         RETURN(rc);
 }
 
         RETURN(rc);
 }
index 8ed8c92..bea58ac 100644 (file)
@@ -79,7 +79,6 @@ static struct lprocfs_vars lprocfs_mdc_obd_vars[] = {
         { "mds_conn_uuid",   lprocfs_rd_conn_uuid,   0, 0 },
         { "max_rpcs_in_flight", mdc_rd_max_rpcs_in_flight,
                                 mdc_wr_max_rpcs_in_flight, 0 },
         { "mds_conn_uuid",   lprocfs_rd_conn_uuid,   0, 0 },
         { "max_rpcs_in_flight", mdc_rd_max_rpcs_in_flight,
                                 mdc_wr_max_rpcs_in_flight, 0 },
-        { "sptlrpc",         sptlrpc_lprocfs_rd, 0, 0 },
         { 0 }
 };
 
         { 0 }
 };
 
index 595dfd4..dda6f11 100644 (file)
@@ -37,7 +37,8 @@ static inline void lprocfs_mdc_init_vars(struct lprocfs_static_vars *lvars)
 #endif
 void mdc_pack_req_body(struct ptlrpc_request *req, int offset,
                        __u64 valid, const struct lu_fid *fid,
 #endif
 void mdc_pack_req_body(struct ptlrpc_request *req, int offset,
                        __u64 valid, const struct lu_fid *fid,
-                       struct obd_capa *oc, int ea_size, int flags);
+                       struct obd_capa *oc, int ea_size,
+                       __u32 suppgid, int flags);
 void mdc_pack_capa(struct ptlrpc_request *req, int offset, struct obd_capa *oc);
 void mdc_pack_rep_body(struct ptlrpc_request *);
 void mdc_is_subdir_pack(struct ptlrpc_request *req, int offset,
 void mdc_pack_capa(struct ptlrpc_request *req, int offset, struct obd_capa *oc);
 void mdc_pack_rep_body(struct ptlrpc_request *);
 void mdc_is_subdir_pack(struct ptlrpc_request *req, int offset,
index 8f4cd9e..66e5ad3 100644 (file)
 #endif
 #endif
 
 #endif
 #endif
 
-static void mdc_pack_body(struct mdt_body *b)
+static void mdc_pack_body(struct mdt_body *b, __u32 suppgid)
 {
         LASSERT (b != NULL);
 
 {
         LASSERT (b != NULL);
 
+        b->suppgid = suppgid;
+        b->uid = current->uid;
+        b->gid = current->gid;
         b->fsuid = current->fsuid;
         b->fsgid = current->fsgid;
         b->capability = current->cap_effective;
         b->fsuid = current->fsuid;
         b->fsgid = current->fsgid;
         b->capability = current->cap_effective;
@@ -78,14 +81,15 @@ void mdc_is_subdir_pack(struct ptlrpc_request *req, int offset,
 
 void mdc_pack_req_body(struct ptlrpc_request *req, int offset,
                        __u64 valid, const struct lu_fid *fid,
 
 void mdc_pack_req_body(struct ptlrpc_request *req, int offset,
                        __u64 valid, const struct lu_fid *fid,
-                       struct obd_capa *oc, int ea_size, int flags)
+                       struct obd_capa *oc, int ea_size, __u32 suppgid,
+                       int flags)
 {
         struct mdt_body *b = lustre_msg_buf(req->rq_reqmsg, offset, sizeof(*b));
 
         b->valid = valid;
         b->eadatasize = ea_size;
         b->flags = flags;
 {
         struct mdt_body *b = lustre_msg_buf(req->rq_reqmsg, offset, sizeof(*b));
 
         b->valid = valid;
         b->eadatasize = ea_size;
         b->flags = flags;
-        mdc_pack_body(b);
+        mdc_pack_body(b, suppgid);
         if (fid) {
                 b->fid1 = *fid;
                 mdc_pack_capa(req, offset + 1, oc);
         if (fid) {
                 b->fid1 = *fid;
                 mdc_pack_capa(req, offset + 1, oc);
@@ -100,9 +104,8 @@ void mdc_readdir_pack(struct ptlrpc_request *req, int offset, __u64 pgoff,
         b = lustre_msg_buf(req->rq_reqmsg, offset, sizeof(*b));
         b->fid1 = *fid;
         b->size = pgoff;                       /* !! */
         b = lustre_msg_buf(req->rq_reqmsg, offset, sizeof(*b));
         b->fid1 = *fid;
         b->size = pgoff;                       /* !! */
-        b->suppgid = -1;
         b->nlink = size;                        /* !! */
         b->nlink = size;                        /* !! */
-        mdc_pack_body(b);
+        mdc_pack_body(b, -1);
         mdc_pack_capa(req, offset + 1, oc);
 }
 
         mdc_pack_capa(req, offset + 1, oc);
 }
 
index e9334f9..b72e700 100644 (file)
@@ -97,7 +97,7 @@ static int send_getstatus(struct obd_import *imp, struct lu_fid *rootfid,
         req->rq_send_state = level;
         ptlrpc_req_set_repsize(req, 3, size);
 
         req->rq_send_state = level;
         ptlrpc_req_set_repsize(req, 3, size);
 
-        mdc_pack_req_body(req, REQ_REC_OFF, 0, NULL, NULL, 0, 0);
+        mdc_pack_req_body(req, REQ_REC_OFF, 0, NULL, NULL, 0, -1, 0);
         lustre_msg_add_flags(req->rq_reqmsg, msg_flags);
         rc = ptlrpc_queue_wait(req);
 
         lustre_msg_add_flags(req->rq_reqmsg, msg_flags);
         rc = ptlrpc_queue_wait(req);
 
@@ -244,7 +244,7 @@ int mdc_getattr(struct obd_export *exp, const struct lu_fid *fid,
         if (!req)
                 GOTO(out, rc = -ENOMEM);
 
         if (!req)
                 GOTO(out, rc = -ENOMEM);
 
-        mdc_pack_req_body(req, REQ_REC_OFF, valid, fid, oc, ea_size,
+        mdc_pack_req_body(req, REQ_REC_OFF, valid, fid, oc, ea_size, -1,
                           MDS_BFLAG_EXT_FLAGS/*request "new" flags(bug 9486)*/);
 
         if (valid & OBD_MD_FLRMTPERM)
                           MDS_BFLAG_EXT_FLAGS/*request "new" flags(bug 9486)*/);
 
         if (valid & OBD_MD_FLRMTPERM)
@@ -267,7 +267,7 @@ int mdc_getattr(struct obd_export *exp, const struct lu_fid *fid,
 
 int mdc_getattr_name(struct obd_export *exp, const struct lu_fid *fid,
                      struct obd_capa *oc, const char *filename, int namelen,
 
 int mdc_getattr_name(struct obd_export *exp, const struct lu_fid *fid,
                      struct obd_capa *oc, const char *filename, int namelen,
-                     obd_valid valid, int ea_size,
+                     obd_valid valid, int ea_size, __u32 suppgid,
                      struct ptlrpc_request **request)
 {
         struct ptlrpc_request *req;
                      struct ptlrpc_request **request)
 {
         struct ptlrpc_request *req;
@@ -283,7 +283,7 @@ int mdc_getattr_name(struct obd_export *exp, const struct lu_fid *fid,
         if (!req)
                 GOTO(out, rc = -ENOMEM);
 
         if (!req)
                 GOTO(out, rc = -ENOMEM);
 
-        mdc_pack_req_body(req, REQ_REC_OFF, valid, fid, oc, ea_size,
+        mdc_pack_req_body(req, REQ_REC_OFF, valid, fid, oc, ea_size, suppgid,
                           MDS_BFLAG_EXT_FLAGS/*request "new" flags(bug 9486)*/);
 
         if (filename) {
                           MDS_BFLAG_EXT_FLAGS/*request "new" flags(bug 9486)*/);
 
         if (filename) {
@@ -342,12 +342,12 @@ int mdc_xattr_common(struct obd_export *exp, const struct lu_fid *fid,
                      struct obd_capa *oc,
                      int opcode, obd_valid valid, const char *xattr_name,
                      const char *input, int input_size, int output_size,
                      struct obd_capa *oc,
                      int opcode, obd_valid valid, const char *xattr_name,
                      const char *input, int input_size, int output_size,
-                     int flags, struct ptlrpc_request **request)
+                     int flags, __u32 suppgid, struct ptlrpc_request **request)
 {
         struct ptlrpc_request *req;
         int size[5] = { sizeof(struct ptlrpc_body), sizeof(struct mdt_body) };
         int bufcnt = 3, offset = REQ_REC_OFF + 2;
 {
         struct ptlrpc_request *req;
         int size[5] = { sizeof(struct ptlrpc_body), sizeof(struct mdt_body) };
         int bufcnt = 3, offset = REQ_REC_OFF + 2;
-        int rc, xattr_namelen = 0, remote_acl = 0;
+        int rc, xattr_namelen = 0;
         void *tmp;
         ENTRY;
 
         void *tmp;
         ENTRY;
 
@@ -367,14 +367,13 @@ int mdc_xattr_common(struct obd_export *exp, const struct lu_fid *fid,
                 GOTO(out, rc = -ENOMEM);
 
         /* request data */
                 GOTO(out, rc = -ENOMEM);
 
         /* request data */
-        mdc_pack_req_body(req, REQ_REC_OFF, valid, fid, oc, output_size, flags);
+        mdc_pack_req_body(req, REQ_REC_OFF, valid, fid, oc, output_size,
+                          suppgid, flags);
 
 
         if (xattr_name) {
                 tmp = lustre_msg_buf(req->rq_reqmsg, offset++, xattr_namelen);
                 memcpy(tmp, xattr_name, xattr_namelen);
 
 
         if (xattr_name) {
                 tmp = lustre_msg_buf(req->rq_reqmsg, offset++, xattr_namelen);
                 memcpy(tmp, xattr_name, xattr_namelen);
-                if (!strcmp(xattr_name, XATTR_NAME_LUSTRE_ACL))
-                        remote_acl = 1;
         }
         if (input_size) {
                 tmp = lustre_msg_buf(req->rq_reqmsg, offset++, input_size);
         }
         if (input_size) {
                 tmp = lustre_msg_buf(req->rq_reqmsg, offset++, input_size);
@@ -394,15 +393,12 @@ int mdc_xattr_common(struct obd_export *exp, const struct lu_fid *fid,
         ptlrpc_req_set_repsize(req, bufcnt, size);
 
         /* make rpc */
         ptlrpc_req_set_repsize(req, bufcnt, size);
 
         /* make rpc */
-        /* NB: set remote acl doesn't need hold rpc lock, because it just
-         * send command to MDS, and when it's executed on mountpoint on MDS,
-         * another mdc_xattr_common() will be invoked there. */
-        if (opcode == MDS_SETXATTR && !remote_acl)
+        if (opcode == MDS_SETXATTR)
                 mdc_get_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL);
 
         rc = ptlrpc_queue_wait(req);
 
                 mdc_get_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL);
 
         rc = ptlrpc_queue_wait(req);
 
-        if (opcode == MDS_SETXATTR && !remote_acl)
+        if (opcode == MDS_SETXATTR)
                 mdc_put_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL);
 
         if (rc != 0)
                 mdc_put_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL);
 
         if (rc != 0)
@@ -428,10 +424,11 @@ err_out:
 int mdc_setxattr(struct obd_export *exp, const struct lu_fid *fid,
                  struct obd_capa *oc, obd_valid valid, const char *xattr_name,
                  const char *input, int input_size, int output_size, int flags,
 int mdc_setxattr(struct obd_export *exp, const struct lu_fid *fid,
                  struct obd_capa *oc, obd_valid valid, const char *xattr_name,
                  const char *input, int input_size, int output_size, int flags,
-                 struct ptlrpc_request **request)
+                 __u32 suppgid, struct ptlrpc_request **request)
 {
         return mdc_xattr_common(exp, fid, oc, MDS_SETXATTR, valid, xattr_name,
 {
         return mdc_xattr_common(exp, fid, oc, MDS_SETXATTR, valid, xattr_name,
-                                input, input_size, output_size, flags, request);
+                                input, input_size, output_size, flags, suppgid,
+                                request);
 }
 
 int mdc_getxattr(struct obd_export *exp, const struct lu_fid *fid,
 }
 
 int mdc_getxattr(struct obd_export *exp, const struct lu_fid *fid,
@@ -440,7 +437,8 @@ int mdc_getxattr(struct obd_export *exp, const struct lu_fid *fid,
                  struct ptlrpc_request **request)
 {
         return mdc_xattr_common(exp, fid, oc, MDS_GETXATTR, valid, xattr_name,
                  struct ptlrpc_request **request)
 {
         return mdc_xattr_common(exp, fid, oc, MDS_GETXATTR, valid, xattr_name,
-                                input, input_size, output_size, flags, request);
+                                input, input_size, output_size, flags, -1,
+                                request);
 }
 
 #ifdef CONFIG_FS_POSIX_ACL
 }
 
 #ifdef CONFIG_FS_POSIX_ACL
@@ -1367,7 +1365,7 @@ int mdc_sync(struct obd_export *exp, const struct lu_fid *fid,
         if (!req)
                 RETURN(rc = -ENOMEM);
 
         if (!req)
                 RETURN(rc = -ENOMEM);
 
-        mdc_pack_req_body(req, REQ_REC_OFF, 0, fid, oc, 0, 0);
+        mdc_pack_req_body(req, REQ_REC_OFF, 0, fid, oc, 0, -1, 0);
 
         ptlrpc_req_set_repsize(req, 2, size);
 
 
         ptlrpc_req_set_repsize(req, 2, size);
 
@@ -1527,6 +1525,7 @@ static int mdc_setup(struct obd_device *obd, struct lustre_cfg *cfg)
                 GOTO(err_close_lock, rc);
         lprocfs_mdc_init_vars(&lvars);
         lprocfs_obd_setup(obd, lvars.obd_vars);
                 GOTO(err_close_lock, rc);
         lprocfs_mdc_init_vars(&lvars);
         lprocfs_obd_setup(obd, lvars.obd_vars);
+        sptlrpc_lprocfs_cliobd_attach(obd);
         ptlrpc_lprocfs_register_obd(obd);
 
         rc = obd_llog_init(obd, NULL, obd, 0, NULL, NULL);
         ptlrpc_lprocfs_register_obd(obd);
 
         rc = obd_llog_init(obd, NULL, obd, 0, NULL, NULL);
@@ -1662,14 +1661,23 @@ static int mdc_process_config(struct obd_device *obd, obd_count len, void *buf)
         int rc = 0;
 
         lprocfs_mdc_init_vars(&lvars);
         int rc = 0;
 
         lprocfs_mdc_init_vars(&lvars);
-        
-        rc = class_process_proc_param(PARAM_MDC, lvars.obd_vars, lcfg, obd);
+
+        switch (lcfg->lcfg_command) {
+        case LCFG_SPTLRPC_CONF:
+                rc = sptlrpc_cliobd_process_config(obd, lcfg);
+                break;
+        default:
+                rc = class_process_proc_param(PARAM_MDC, lvars.obd_vars,
+                                              lcfg, obd);
+                break;
+        }
         return(rc);
 }
 
 /* get remote permission for current user on fid */
 int mdc_get_remote_perm(struct obd_export *exp, const struct lu_fid *fid,
         return(rc);
 }
 
 /* get remote permission for current user on fid */
 int mdc_get_remote_perm(struct obd_export *exp, const struct lu_fid *fid,
-                        struct obd_capa *oc, struct ptlrpc_request **request)
+                        struct obd_capa *oc, __u32 suppgid,
+                        struct ptlrpc_request **request)
 {
         struct ptlrpc_request *req;
         struct mdt_body *body;
 {
         struct ptlrpc_request *req;
         struct mdt_body *body;
@@ -1686,7 +1694,8 @@ int mdc_get_remote_perm(struct obd_export *exp, const struct lu_fid *fid,
         if (!req)
                 RETURN(-ENOMEM);
 
         if (!req)
                 RETURN(-ENOMEM);
 
-        mdc_pack_req_body(req, REQ_REC_OFF, OBD_MD_FLRMTPERM, fid, oc, 0, 0);
+        mdc_pack_req_body(req, REQ_REC_OFF, OBD_MD_FLRMTPERM, fid, oc, 0,
+                          suppgid, 0);
 
         size[REPLY_REC_OFF + 1] = sizeof(*perm);
         ptlrpc_req_set_repsize(req, 5, size);
 
         size[REPLY_REC_OFF + 1] = sizeof(*perm);
         ptlrpc_req_set_repsize(req, 5, size);
@@ -1753,7 +1762,7 @@ static int mdc_renew_capa(struct obd_export *exp, struct obd_capa *oc,
                 RETURN(-ENOMEM);
 
         mdc_pack_req_body(req, REQ_REC_OFF, OBD_MD_FLOSSCAPA,
                 RETURN(-ENOMEM);
 
         mdc_pack_req_body(req, REQ_REC_OFF, OBD_MD_FLOSSCAPA,
-                          &oc->c_capa.lc_fid, oc, 0, 0);
+                          &oc->c_capa.lc_fid, oc, 0, -1, 0);
 
         ptlrpc_req_set_repsize(req, 5, size);
         req->rq_async_args.pointer_arg[0] = oc;
 
         ptlrpc_req_set_repsize(req, 5, size);
         req->rq_async_args.pointer_arg[0] = oc;
index 82efb15..a887733 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/semaphore.h>
 
 #include <linux/lustre_acl.h>
 #include <asm/semaphore.h>
 
 #include <linux/lustre_acl.h>
+#include <lustre_eacl.h>
 #include <obd.h>
 #include <md_object.h>
 #include <dt_object.h>
 #include <obd.h>
 #include <md_object.h>
 #include <dt_object.h>
@@ -301,7 +302,6 @@ static inline int mdd_capable(struct md_ucred *uc, int cap)
         return 0;
 }
 
         return 0;
 }
 
-int mdd_in_group_p(struct md_ucred *uc, gid_t grp);
 int mdd_acl_def_get(const struct lu_env *env, struct mdd_object *mdd_obj,
                     struct md_attr *ma);
 int mdd_acl_chmod(const struct lu_env *env, struct mdd_object *o, __u32 mode,
 int mdd_acl_def_get(const struct lu_env *env, struct mdd_object *mdd_obj,
                     struct md_attr *ma);
 int mdd_acl_chmod(const struct lu_env *env, struct mdd_object *o, __u32 mode,
index c10d4bc..758a1fc 100644 (file)
@@ -664,7 +664,7 @@ static int mdd_fix_attr(const struct lu_env *env, struct mdd_object *obj,
                                       (tmp_la->la_mode & ~S_IALLUGO);
 
                 /* Also check the setgid bit! */
                                       (tmp_la->la_mode & ~S_IALLUGO);
 
                 /* Also check the setgid bit! */
-                if (!mdd_in_group_p(uc, (la->la_valid & LA_GID) ? la->la_gid :
+                if (!lustre_in_group_p(uc, (la->la_valid & LA_GID) ? la->la_gid :
                                 tmp_la->la_gid) && !mdd_capable(uc, CAP_FSETID))
                         la->la_mode &= ~S_ISGID;
         } else {
                                 tmp_la->la_gid) && !mdd_capable(uc, CAP_FSETID))
                         la->la_mode &= ~S_ISGID;
         } else {
@@ -704,7 +704,7 @@ static int mdd_fix_attr(const struct lu_env *env, struct mdd_object *obj,
                         la->la_gid = tmp_la->la_gid;
                 if (((uc->mu_fsuid != tmp_la->la_uid) ||
                     ((la->la_gid != tmp_la->la_gid) &&
                         la->la_gid = tmp_la->la_gid;
                 if (((uc->mu_fsuid != tmp_la->la_uid) ||
                     ((la->la_gid != tmp_la->la_gid) &&
-                    !mdd_in_group_p(uc, la->la_gid))) &&
+                    !lustre_in_group_p(uc, la->la_gid))) &&
                     !mdd_capable(uc, CAP_CHOWN))
                         RETURN(-EPERM);
 
                     !mdd_capable(uc, CAP_CHOWN))
                         RETURN(-EPERM);
 
index a6357f0..1dad3eb 100644 (file)
 #include <lustre_mds.h>
 #include <lustre/lustre_idl.h>
 
 #include <lustre_mds.h>
 #include <lustre/lustre_idl.h>
 
-#ifdef CONFIG_FS_POSIX_ACL
-# include <linux/posix_acl_xattr.h>
-# include <linux/posix_acl.h>
-#endif
-
 #include "mdd_internal.h"
 
 #include "mdd_internal.h"
 
-#define mdd_get_group_info(group_info) do {             \
-        atomic_inc(&(group_info)->usage);               \
-} while (0)
-
-#define mdd_put_group_info(group_info) do {             \
-        if (atomic_dec_and_test(&(group_info)->usage))  \
-                groups_free(group_info);                \
-} while (0)
-
-#define MDD_NGROUPS_PER_BLOCK       ((int)(CFS_PAGE_SIZE / sizeof(gid_t)))
-
-#define MDD_GROUP_AT(gi, i) \
-    ((gi)->blocks[(i) / MDD_NGROUPS_PER_BLOCK][(i) % MDD_NGROUPS_PER_BLOCK])
-
-/*
- * groups_search() is copied from linux kernel!
- * A simple bsearch.
- */
-static int mdd_groups_search(struct group_info *group_info, gid_t grp)
-{
-        int left, right;
-
-        if (!group_info)
-                return 0;
-
-        left = 0;
-        right = group_info->ngroups;
-        while (left < right) {
-                int mid = (left + right) / 2;
-                int cmp = grp - MDD_GROUP_AT(group_info, mid);
-
-                if (cmp > 0)
-                        left = mid + 1;
-                else if (cmp < 0)
-                        right = mid;
-                else
-                        return 1;
-        }
-        return 0;
-}
-
-int mdd_in_group_p(struct md_ucred *uc, gid_t grp)
-{
-        int rc = 1;
-
-        if (grp != uc->mu_fsgid) {
-                struct group_info *group_info = NULL;
-
-                if (uc->mu_ginfo || !uc->mu_identity ||
-                    uc->mu_valid == UCRED_OLD)
-                        if (grp == uc->mu_suppgids[0] ||
-                            grp == uc->mu_suppgids[1])
-                                return 1;
-
-                if (uc->mu_ginfo)
-                        group_info = uc->mu_ginfo;
-                else if (uc->mu_identity)
-                        group_info = uc->mu_identity->mi_ginfo;
-
-                if (!group_info)
-                        return 0;
-
-                mdd_get_group_info(group_info);
-                rc = mdd_groups_search(group_info, grp);
-                mdd_put_group_info(group_info);
-        }
-        return rc;
-}
-
 #ifdef CONFIG_FS_POSIX_ACL
 #ifdef CONFIG_FS_POSIX_ACL
-static inline void mdd_acl_le_to_cpu(posix_acl_xattr_entry *p)
-{
-        p->e_tag = le16_to_cpu(p->e_tag);
-        p->e_perm = le16_to_cpu(p->e_perm);
-        p->e_id = le32_to_cpu(p->e_id);
-}
-
-static inline void mdd_acl_cpu_to_le(posix_acl_xattr_entry *p)
-{
-        p->e_tag = cpu_to_le16(p->e_tag);
-        p->e_perm = cpu_to_le16(p->e_perm);
-        p->e_id = cpu_to_le32(p->e_id);
-}
-
-/*
- * Check permission based on POSIX ACL.
- */
-static int mdd_posix_acl_permission(struct md_ucred *uc, struct lu_attr *la,
-                                    int want, posix_acl_xattr_entry *entry,
-                                    int count)
-{
-        posix_acl_xattr_entry *pa, *pe, *mask_obj;
-        int found = 0;
-        ENTRY;
-
-        if (count <= 0)
-                RETURN(-EACCES);
-
-        for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
-                mdd_acl_le_to_cpu(pa);
-                switch(pa->e_tag) {
-                        case ACL_USER_OBJ:
-                                /* (May have been checked already) */
-                                if (la->la_uid == uc->mu_fsuid)
-                                        goto check_perm;
-                                break;
-                        case ACL_USER:
-                                if (pa->e_id == uc->mu_fsuid)
-                                        goto mask;
-                                break;
-                        case ACL_GROUP_OBJ:
-                                if (mdd_in_group_p(uc, la->la_gid)) {
-                                        found = 1;
-                                        if ((pa->e_perm & want) == want)
-                                                goto mask;
-                                }
-                                break;
-                        case ACL_GROUP:
-                                if (mdd_in_group_p(uc, pa->e_id)) {
-                                        found = 1;
-                                        if ((pa->e_perm & want) == want)
-                                                goto mask;
-                                }
-                                break;
-                        case ACL_MASK:
-                                break;
-                        case ACL_OTHER:
-                                if (found)
-                                        RETURN(-EACCES);
-                                else
-                                        goto check_perm;
-                        default:
-                                RETURN(-EIO);
-                }
-        }
-        RETURN(-EIO);
-
-mask:
-        for (mask_obj = pa + 1; mask_obj <= pe; mask_obj++) {
-                mdd_acl_le_to_cpu(mask_obj);
-                if (mask_obj->e_tag == ACL_MASK) {
-                        if ((pa->e_perm & mask_obj->e_perm & want) == want)
-                                RETURN(0);
-
-                        RETURN(-EACCES);
-                }
-        }
-
-check_perm:
-        if ((pa->e_perm & want) == want)
-                RETURN(0);
-
-        RETURN(-EACCES);
-}
 
 /*
  * Get default acl EA only.
 
 /*
  * Get default acl EA only.
@@ -232,54 +74,6 @@ int mdd_acl_def_get(const struct lu_env *env, struct mdd_object *mdd_obj,
 }
 
 /*
 }
 
 /*
- * Modify the ACL for the chmod.
- */
-static int mdd_posix_acl_chmod_masq(posix_acl_xattr_entry *entry,
-                                    __u32 mode, int count)
-{
-       posix_acl_xattr_entry *group_obj = NULL, *mask_obj = NULL, *pa, *pe;
-
-        for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
-                mdd_acl_le_to_cpu(pa);
-               switch(pa->e_tag) {
-                       case ACL_USER_OBJ:
-                               pa->e_perm = (mode & S_IRWXU) >> 6;
-                               break;
-
-                       case ACL_USER:
-                       case ACL_GROUP:
-                               break;
-
-                       case ACL_GROUP_OBJ:
-                               group_obj = pa;
-                               break;
-
-                       case ACL_MASK:
-                               mask_obj = pa;
-                               break;
-
-                       case ACL_OTHER:
-                               pa->e_perm = (mode & S_IRWXO);
-                               break;
-
-                       default:
-                               return -EIO;
-               }
-                mdd_acl_cpu_to_le(pa);
-       }
-
-       if (mask_obj) {
-               mask_obj->e_perm = cpu_to_le16((mode & S_IRWXG) >> 3);
-       } else {
-               if (!group_obj)
-                       return -EIO;
-               group_obj->e_perm = cpu_to_le16((mode & S_IRWXG) >> 3);
-       }
-
-       return 0;
-}
-
-/*
  * Hold write_lock for o.
  */
 int mdd_acl_chmod(const struct lu_env *env, struct mdd_object *o, __u32 mode, 
  * Hold write_lock for o.
  */
 int mdd_acl_chmod(const struct lu_env *env, struct mdd_object *o, __u32 mode, 
@@ -310,7 +104,7 @@ int mdd_acl_chmod(const struct lu_env *env, struct mdd_object *o, __u32 mode,
         if (entry_count <= 0)
                 RETURN(0);
        
         if (entry_count <= 0)
                 RETURN(0);
        
-        rc = mdd_posix_acl_chmod_masq(entry, mode, entry_count);
+        rc = lustre_posix_acl_chmod_masq(entry, mode, entry_count);
         if (rc)
                 RETURN(rc);
 
         if (rc)
                 RETURN(rc);
 
@@ -320,67 +114,6 @@ int mdd_acl_chmod(const struct lu_env *env, struct mdd_object *o, __u32 mode,
 }
 
 /*
 }
 
 /*
- * Modify acl when creating a new obj.
- */
-static int mdd_posix_acl_create_masq(posix_acl_xattr_entry *entry,
-                                     __u32 *mode_p, int count)
-{
-        posix_acl_xattr_entry *group_obj = NULL, *mask_obj = NULL, *pa, *pe;
-       __u32 mode = *mode_p;
-       int not_equiv = 0;
-
-        for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
-                mdd_acl_le_to_cpu(pa);
-                switch(pa->e_tag) {
-                        case ACL_USER_OBJ:
-                               pa->e_perm &= (mode >> 6) | ~S_IRWXO;
-                               mode &= (pa->e_perm << 6) | ~S_IRWXU;
-                               break;
-
-                       case ACL_USER:
-                       case ACL_GROUP:
-                               not_equiv = 1;
-                               break;
-
-                        case ACL_GROUP_OBJ:
-                               group_obj = pa;
-                                break;
-
-                        case ACL_OTHER:
-                               pa->e_perm &= mode | ~S_IRWXO;
-                               mode &= pa->e_perm | ~S_IRWXO;
-                                break;
-
-                        case ACL_MASK:
-                               mask_obj = pa;
-                               not_equiv = 1;
-                                break;
-
-                       default:
-                               return -EIO;
-                }
-                mdd_acl_cpu_to_le(pa);
-        }
-
-       if (mask_obj) {
-               mask_obj->e_perm = le16_to_cpu(mask_obj->e_perm) &
-                                   ((mode >> 3) | ~S_IRWXO);
-               mode &= (mask_obj->e_perm << 3) | ~S_IRWXG;
-                mask_obj->e_perm = cpu_to_le16(mask_obj->e_perm);
-       } else {
-               if (!group_obj)
-                       return -EIO;
-               group_obj->e_perm = le16_to_cpu(group_obj->e_perm) &
-                                    ((mode >> 3) | ~S_IRWXO);
-               mode &= (group_obj->e_perm << 3) | ~S_IRWXG;
-                group_obj->e_perm = cpu_to_le16(group_obj->e_perm);
-       }
-
-       *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
-        return not_equiv;
-}
-
-/*
  * Hold write_lock for obj.
  */
 int __mdd_acl_init(const struct lu_env *env, struct mdd_object *obj,
  * Hold write_lock for obj.
  */
 int __mdd_acl_init(const struct lu_env *env, struct mdd_object *obj,
@@ -407,7 +140,7 @@ int __mdd_acl_init(const struct lu_env *env, struct mdd_object *obj,
                         RETURN(rc);
        }
 
                         RETURN(rc);
        }
 
-        rc = mdd_posix_acl_create_masq(entry, mode, entry_count);
+        rc = lustre_posix_acl_create_masq(entry, mode, entry_count);
         if (rc <= 0)
                 RETURN(rc);
 
         if (rc <= 0)
                 RETURN(rc);
 
@@ -472,7 +205,7 @@ static int mdd_check_acl(const struct lu_env *env, struct mdd_object *obj,
         entry_count = (buf->lb_len - sizeof(head->a_version)) /
                       sizeof(posix_acl_xattr_entry);
 
         entry_count = (buf->lb_len - sizeof(head->a_version)) /
                       sizeof(posix_acl_xattr_entry);
 
-        rc = mdd_posix_acl_permission(uc, la, mask, entry, entry_count);
+        rc = lustre_posix_acl_permission(uc, la, mask, entry, entry_count);
         RETURN(rc);
 #else
         ENTRY;
         RETURN(rc);
 #else
         ENTRY;
@@ -528,7 +261,7 @@ int __mdd_permission_internal(const struct lu_env *env, struct mdd_object *obj,
                                  (rc != -ENODATA))
                                 RETURN(rc);
                 }
                                  (rc != -ENODATA))
                                 RETURN(rc);
                 }
-                if (mdd_in_group_p(uc, la->la_gid))
+                if (lustre_in_group_p(uc, la->la_gid))
                         mode >>= 3;
         }
 
                         mode >>= 3;
         }
 
@@ -554,11 +287,13 @@ int mdd_permission(const struct lu_env *env,
                    struct md_attr *ma, int mask)
 {
         struct mdd_object *mdd_pobj, *mdd_cobj;
                    struct md_attr *ma, int mask)
 {
         struct mdd_object *mdd_pobj, *mdd_cobj;
+        struct md_ucred *uc = NULL;
         struct lu_attr *la = NULL;
         int check_create, check_link;
         int check_unlink;
         int check_rename_src, check_rename_tar;
         int check_vtx_part, check_vtx_full;
         struct lu_attr *la = NULL;
         int check_create, check_link;
         int check_unlink;
         int check_rename_src, check_rename_tar;
         int check_vtx_part, check_vtx_full;
+        int check_rgetfacl;
         int rc = 0;
         ENTRY;
 
         int rc = 0;
         ENTRY;
 
@@ -584,11 +319,13 @@ int mdd_permission(const struct lu_env *env,
         check_rename_tar = mask & MAY_RENAME_TAR;
         check_vtx_part = mask & MAY_VTX_PART;
         check_vtx_full = mask & MAY_VTX_FULL;
         check_rename_tar = mask & MAY_RENAME_TAR;
         check_vtx_part = mask & MAY_VTX_PART;
         check_vtx_full = mask & MAY_VTX_FULL;
+        check_rgetfacl = mask & MAY_RGETFACL;
 
         mask &= ~(MAY_CREATE | MAY_LINK |
                 MAY_UNLINK |
                 MAY_RENAME_SRC | MAY_RENAME_TAR |
 
         mask &= ~(MAY_CREATE | MAY_LINK |
                 MAY_UNLINK |
                 MAY_RENAME_SRC | MAY_RENAME_TAR |
-                MAY_VTX_PART | MAY_VTX_FULL);
+                MAY_VTX_PART | MAY_VTX_FULL |
+                MAY_RGETFACL);
 
         rc = mdd_permission_internal_locked(env, mdd_cobj, NULL, mask);
 
 
         rc = mdd_permission_internal_locked(env, mdd_cobj, NULL, mask);
 
@@ -609,8 +346,7 @@ int mdd_permission(const struct lu_env *env,
         }
 
         if (!rc && (check_vtx_part || check_vtx_full)) {
         }
 
         if (!rc && (check_vtx_part || check_vtx_full)) {
-                struct md_ucred *uc = md_ucred(env);
-
+                uc = md_ucred(env);
                 LASSERT(ma);
                 if (likely(!la)) {
                         la = &mdd_env_info(env)->mti_la;
                 LASSERT(ma);
                 if (likely(!la)) {
                         la = &mdd_env_info(env)->mti_la;
@@ -630,6 +366,21 @@ int mdd_permission(const struct lu_env *env,
                 }
         }
 
                 }
         }
 
+        if (unlikely(!rc && check_rgetfacl)) {
+                if (likely(!uc))
+                        uc = md_ucred(env);
+
+                if (likely(!la)) {
+                        la = &mdd_env_info(env)->mti_la;
+                        rc = mdd_la_get(env, mdd_cobj, la, BYPASS_CAPA);
+                        if (rc)
+                                RETURN(rc);
+                }
+
+                if (la->la_uid != uc->mu_fsuid && !mdd_capable(uc, CAP_FOWNER))
+                        rc = -EPERM;
+        }
+
         RETURN(rc);
 }
 
         RETURN(rc);
 }
 
index 4e16577..d5f60de 100644 (file)
@@ -289,7 +289,8 @@ static int mds_connect_internal(struct obd_export *exp,
         return 0;
 }
 
         return 0;
 }
 
-static int mds_reconnect(struct obd_export *exp, struct obd_device *obd,
+static int mds_reconnect(const struct lu_env *env,
+                         struct obd_export *exp, struct obd_device *obd,
                          struct obd_uuid *cluuid,
                          struct obd_connect_data *data)
 {
                          struct obd_uuid *cluuid,
                          struct obd_connect_data *data)
 {
@@ -340,6 +341,8 @@ static int mds_connect(const struct lu_env *env,
         LASSERT(exp);
         med = &exp->exp_mds_data;
 
         LASSERT(exp);
         med = &exp->exp_mds_data;
 
+        exp->exp_flvr.sf_rpc = SPTLRPC_FLVR_NULL;
+
         rc = mds_connect_internal(exp, data);
         if (rc)
                 GOTO(out, rc);
         rc = mds_connect_internal(exp, data);
         if (rc)
                 GOTO(out, rc);
index cc854bb..e06fd34 100644 (file)
@@ -1,5 +1,5 @@
 MODULES := mdt
 mdt-objs := mdt_handler.o mdt_lib.o mdt_reint.o mdt_xattr.o mdt_recovery.o
 MODULES := mdt
 mdt-objs := mdt_handler.o mdt_lib.o mdt_reint.o mdt_xattr.o mdt_recovery.o
-mdt-objs += mdt_open.o mdt_idmap.o mdt_identity.o mdt_rmtacl.o mdt_capa.o mdt_lproc.o
+mdt-objs += mdt_open.o mdt_idmap.o mdt_identity.o mdt_capa.o mdt_lproc.o
 
 @INCLUDE_RULES@
 
 @INCLUDE_RULES@
index 206b5bd..001583f 100644 (file)
@@ -1347,10 +1347,6 @@ static int mdt_readpage(struct mdt_thread_info *info)
         if (reqbody == NULL || repbody == NULL)
                 RETURN(err_serious(-EFAULT));
 
         if (reqbody == NULL || repbody == NULL)
                 RETURN(err_serious(-EFAULT));
 
-        rc = mdt_check_ucred(info);
-        if (rc)
-                RETURN(err_serious(rc));
-
         /*
          * prepare @rdpg before calling lower layers and transfer itself. Here
          * reqbody->size contains offset of where to start to read and
         /*
          * prepare @rdpg before calling lower layers and transfer itself. Here
          * reqbody->size contains offset of where to start to read and
@@ -3676,9 +3672,6 @@ static void mdt_fini(const struct lu_env *env, struct mdt_device *m)
 
         mdt_fs_cleanup(env, m);
 
 
         mdt_fs_cleanup(env, m);
 
-        upcall_cache_cleanup(m->mdt_rmtacl_cache);
-        m->mdt_rmtacl_cache = NULL;
-
         upcall_cache_cleanup(m->mdt_identity_cache);
         m->mdt_identity_cache = NULL;
 
         upcall_cache_cleanup(m->mdt_identity_cache);
         m->mdt_identity_cache = NULL;
 
@@ -3694,10 +3687,7 @@ static void mdt_fini(const struct lu_env *env, struct mdt_device *m)
         ptlrpc_lprocfs_unregister_obd(d->ld_obd);
         lprocfs_obd_cleanup(d->ld_obd);
 
         ptlrpc_lprocfs_unregister_obd(d->ld_obd);
         lprocfs_obd_cleanup(d->ld_obd);
 
-        if (m->mdt_rootsquash_info) {
-                OBD_FREE_PTR(m->mdt_rootsquash_info);
-                m->mdt_rootsquash_info = NULL;
-        }
+        sptlrpc_rule_set_free(&m->mdt_sptlrpc_rset);
 
         next->md_ops->mdo_init_capa_ctxt(env, next, 0, 0, 0, NULL);
         del_timer(&m->mdt_ck_timer);
 
         next->md_ops->mdo_init_capa_ctxt(env, next, 0, 0, 0, NULL);
         del_timer(&m->mdt_ck_timer);
@@ -3781,6 +3771,7 @@ static int mdt_init0(const struct lu_env *env, struct mdt_device *m,
         struct lustre_mount_info  *lmi;
         struct lustre_sb_info     *lsi;
         struct lu_site            *s;
         struct lustre_mount_info  *lmi;
         struct lustre_sb_info     *lsi;
         struct lu_site            *s;
+        const char                *identity_upcall = "NONE";
         int                        rc;
         ENTRY;
 
         int                        rc;
         ENTRY;
 
@@ -3807,6 +3798,9 @@ static int mdt_init0(const struct lu_env *env, struct mdt_device *m,
                 server_put_mount_2(dev, lmi->lmi_mnt);
         }
 
                 server_put_mount_2(dev, lmi->lmi_mnt);
         }
 
+        m->mdt_sptlrpc_lock = RW_LOCK_UNLOCKED;
+        sptlrpc_rule_set_init(&m->mdt_sptlrpc_rset);
+
         spin_lock_init(&m->mdt_ioepoch_lock);
         m->mdt_opts.mo_compat_resname = 0;
         m->mdt_capa_timeout = CAPA_TIMEOUT;
         spin_lock_init(&m->mdt_ioepoch_lock);
         m->mdt_opts.mo_compat_resname = 0;
         m->mdt_capa_timeout = CAPA_TIMEOUT;
@@ -3892,8 +3886,12 @@ static int mdt_init0(const struct lu_env *env, struct mdt_device *m,
         /* set obd_namespace for compatibility with old code */
         obd->obd_namespace = m->mdt_namespace;
 
         /* set obd_namespace for compatibility with old code */
         obd->obd_namespace = m->mdt_namespace;
 
-        m->mdt_identity_cache = upcall_cache_init(obd->obd_name,
-                                                  "NONE",
+        /* XXX: to support suppgid for ACL, we enable identity_upcall
+         * by default, otherwise, maybe got unexpected -EACCESS. */
+        if (m->mdt_opts.mo_acl)
+                identity_upcall = MDT_IDENTITY_UPCALL_PATH;
+
+        m->mdt_identity_cache = upcall_cache_init(obd->obd_name, identity_upcall,
                                                   &mdt_identity_upcall_cache_ops);
         if (IS_ERR(m->mdt_identity_cache)) {
                 rc = PTR_ERR(m->mdt_identity_cache);
                                                   &mdt_identity_upcall_cache_ops);
         if (IS_ERR(m->mdt_identity_cache)) {
                 rc = PTR_ERR(m->mdt_identity_cache);
@@ -3901,15 +3899,6 @@ static int mdt_init0(const struct lu_env *env, struct mdt_device *m,
                 GOTO(err_free_ns, rc);
         }
 
                 GOTO(err_free_ns, rc);
         }
 
-        m->mdt_rmtacl_cache = upcall_cache_init(obd->obd_name,
-                                                MDT_RMTACL_UPCALL_PATH,
-                                                &mdt_rmtacl_upcall_cache_ops);
-        if (IS_ERR(m->mdt_rmtacl_cache)) {
-                rc = PTR_ERR(m->mdt_rmtacl_cache);
-                m->mdt_rmtacl_cache = NULL;
-                GOTO(err_free_ns, rc);
-        }
-
         m->mdt_ck_timer.function = mdt_ck_timer_callback;
         m->mdt_ck_timer.data = (unsigned long)m;
         init_timer(&m->mdt_ck_timer);
         m->mdt_ck_timer.function = mdt_ck_timer_callback;
         m->mdt_ck_timer.data = (unsigned long)m;
         init_timer(&m->mdt_ck_timer);
@@ -3953,8 +3942,6 @@ err_capa:
         del_timer(&m->mdt_ck_timer);
         mdt_ck_thread_stop(m);
 err_free_ns:
         del_timer(&m->mdt_ck_timer);
         mdt_ck_thread_stop(m);
 err_free_ns:
-        upcall_cache_cleanup(m->mdt_rmtacl_cache);
-        m->mdt_rmtacl_cache = NULL;
         upcall_cache_cleanup(m->mdt_identity_cache);
         m->mdt_identity_cache = NULL;
         ldlm_namespace_free(m->mdt_namespace, 0);
         upcall_cache_cleanup(m->mdt_identity_cache);
         m->mdt_identity_cache = NULL;
         ldlm_namespace_free(m->mdt_namespace, 0);
@@ -3988,6 +3975,34 @@ static int mdt_process_config(const struct lu_env *env,
         ENTRY;
 
         switch (cfg->lcfg_command) {
         ENTRY;
 
         switch (cfg->lcfg_command) {
+        case LCFG_SPTLRPC_CONF: {
+                struct sptlrpc_conf_log *log;
+                struct sptlrpc_rule_set  tmp_rset;
+
+                log = sptlrpc_conf_log_extract(cfg);
+                if (IS_ERR(log)) {
+                        rc = PTR_ERR(log);
+                        break;
+                }
+
+                sptlrpc_rule_set_init(&tmp_rset);
+
+                rc = sptlrpc_rule_set_from_log(&tmp_rset, log);
+                if (rc) {
+                        CERROR("mdt %p: failed get sptlrpc rules: %d\n", m, rc);
+                        break;
+                }
+
+                write_lock(&m->mdt_sptlrpc_lock);
+                sptlrpc_rule_set_free(&m->mdt_sptlrpc_rset);
+                m->mdt_sptlrpc_rset = tmp_rset;
+                write_unlock(&m->mdt_sptlrpc_lock);
+
+                sptlrpc_target_update_exp_flavor(
+                                md2lu_dev(&m->mdt_md_dev)->ld_obd, &tmp_rset);
+
+                break;
+        }
         case LCFG_PARAM: {
                 struct lprocfs_static_vars lvars;
                 struct obd_device *obd = d->ld_obd;
         case LCFG_PARAM: {
                 struct lprocfs_static_vars lvars;
                 struct obd_device *obd = d->ld_obd;
@@ -4173,9 +4188,11 @@ static int mdt_obd_connect(const struct lu_env *env,
                            struct obd_uuid *cluuid,
                            struct obd_connect_data *data)
 {
                            struct obd_uuid *cluuid,
                            struct obd_connect_data *data)
 {
+        struct mdt_thread_info *info;
         struct mdt_client_data *mcd;
         struct obd_export      *exp;
         struct mdt_device      *mdt;
         struct mdt_client_data *mcd;
         struct obd_export      *exp;
         struct mdt_device      *mdt;
+        struct ptlrpc_request  *req;
         int                     rc;
         ENTRY;
 
         int                     rc;
         ENTRY;
 
@@ -4183,6 +4200,8 @@ static int mdt_obd_connect(const struct lu_env *env,
         if (!conn || !obd || !cluuid)
                 RETURN(-EINVAL);
 
         if (!conn || !obd || !cluuid)
                 RETURN(-EINVAL);
 
+        info = lu_context_key_get(&env->le_ctx, &mdt_thread_key);
+        req = info->mti_pill.rc_req;
         mdt = mdt_dev(obd->obd_lu_dev);
 
         rc = class_connect(conn, obd, cluuid);
         mdt = mdt_dev(obd->obd_lu_dev);
 
         rc = class_connect(conn, obd, cluuid);
@@ -4192,6 +4211,26 @@ static int mdt_obd_connect(const struct lu_env *env,
         exp = class_conn2export(conn);
         LASSERT(exp != NULL);
 
         exp = class_conn2export(conn);
         LASSERT(exp != NULL);
 
+        CDEBUG(D_SEC, "from %s\n", sptlrpc_part2name(req->rq_sp_from));
+
+        spin_lock(&exp->exp_lock);
+        exp->exp_sp_peer = req->rq_sp_from;
+
+        read_lock(&mdt->mdt_sptlrpc_lock);
+        sptlrpc_rule_set_choose(&mdt->mdt_sptlrpc_rset, exp->exp_sp_peer,
+                                req->rq_peer.nid, &exp->exp_flvr);
+        read_unlock(&mdt->mdt_sptlrpc_lock);
+
+        if (exp->exp_flvr.sf_rpc != req->rq_flvr.sf_rpc) {
+                CERROR("invalid rpc flavor %x, expect %x, from %s\n",
+                       req->rq_flvr.sf_rpc, exp->exp_flvr.sf_rpc,
+                       libcfs_nid2str(req->rq_peer.nid));
+                exp->exp_flvr.sf_rpc = SPTLRPC_FLVR_INVALID;
+                spin_unlock(&exp->exp_lock);
+                RETURN(-EACCES);
+        }
+        spin_unlock(&exp->exp_lock);
+
         rc = mdt_connect_internal(exp, mdt, data);
         if (rc == 0) {
                 OBD_ALLOC_PTR(mcd);
         rc = mdt_connect_internal(exp, mdt, data);
         if (rc == 0) {
                 OBD_ALLOC_PTR(mcd);
@@ -4220,16 +4259,47 @@ static int mdt_obd_connect(const struct lu_env *env,
         RETURN(rc);
 }
 
         RETURN(rc);
 }
 
-static int mdt_obd_reconnect(struct obd_export *exp, struct obd_device *obd,
+static int mdt_obd_reconnect(const struct lu_env *env,
+                             struct obd_export *exp, struct obd_device *obd,
                              struct obd_uuid *cluuid,
                              struct obd_connect_data *data)
 {
                              struct obd_uuid *cluuid,
                              struct obd_connect_data *data)
 {
-        int rc;
+        struct mdt_thread_info *info;
+        struct mdt_device      *mdt;
+        struct ptlrpc_request  *req;
+        int                     rc;
         ENTRY;
 
         if (exp == NULL || obd == NULL || cluuid == NULL)
                 RETURN(-EINVAL);
 
         ENTRY;
 
         if (exp == NULL || obd == NULL || cluuid == NULL)
                 RETURN(-EINVAL);
 
+        info = lu_context_key_get(&env->le_ctx, &mdt_thread_key);
+        req = info->mti_pill.rc_req;
+        mdt = mdt_dev(obd->obd_lu_dev);
+
+        CDEBUG(D_SEC, "from %s\n", sptlrpc_part2name(req->rq_sp_from));
+
+        spin_lock(&exp->exp_lock);
+        if (exp->exp_flvr.sf_rpc == SPTLRPC_FLVR_INVALID) {
+                exp->exp_sp_peer = req->rq_sp_from;
+
+                read_lock(&mdt->mdt_sptlrpc_lock);
+                sptlrpc_rule_set_choose(&mdt->mdt_sptlrpc_rset,
+                                        exp->exp_sp_peer,
+                                        req->rq_peer.nid, &exp->exp_flvr);
+                read_unlock(&mdt->mdt_sptlrpc_lock);
+
+                if (exp->exp_flvr.sf_rpc != req->rq_flvr.sf_rpc) {
+                        CERROR("invalid rpc flavor %x, expect %x, from %s\n",
+                               req->rq_flvr.sf_rpc, exp->exp_flvr.sf_rpc,
+                               libcfs_nid2str(req->rq_peer.nid));
+                        exp->exp_flvr.sf_rpc = SPTLRPC_FLVR_INVALID;
+                        spin_unlock(&exp->exp_lock);
+                        RETURN(-EACCES);
+                }
+        }
+        spin_unlock(&exp->exp_lock);
+
         rc = mdt_connect_internal(exp, mdt_dev(obd->obd_lu_dev), data);
 
         RETURN(rc);
         rc = mdt_connect_internal(exp, mdt_dev(obd->obd_lu_dev), data);
 
         RETURN(rc);
@@ -4276,6 +4346,8 @@ static int mdt_init_export(struct obd_export *exp)
 
         INIT_LIST_HEAD(&med->med_open_head);
         spin_lock_init(&med->med_open_lock);
 
         INIT_LIST_HEAD(&med->med_open_head);
         spin_lock_init(&med->med_open_lock);
+        sema_init(&med->med_idmap_sem, 1);
+        med->med_idmap = NULL;
         spin_lock(&exp->exp_lock);
         exp->exp_connecting = 1;
         spin_unlock(&exp->exp_lock);
         spin_lock(&exp->exp_lock);
         exp->exp_connecting = 1;
         spin_unlock(&exp->exp_lock);
@@ -4775,6 +4847,11 @@ static struct mdt_opc_slice mdt_xmds_handlers[] = {
                 .mos_hs        = mdt_obd_ops
         },
         {
                 .mos_hs        = mdt_obd_ops
         },
         {
+                .mos_opc_start = SEC_CTX_INIT,
+                .mos_opc_end   = SEC_LAST_OPC,
+                .mos_hs        = mdt_sec_ctx_ops
+        },
+        {
                 .mos_hs        = NULL
         }
 };
                 .mos_hs        = NULL
         }
 };
index f196570..12ed4a8 100644 (file)
@@ -67,15 +67,18 @@ static void mdt_identity_entry_init(struct upcall_cache_entry *entry,
 static void mdt_identity_entry_free(struct upcall_cache *cache,
                                     struct upcall_cache_entry *entry)
 {
 static void mdt_identity_entry_free(struct upcall_cache *cache,
                                     struct upcall_cache_entry *entry)
 {
-        struct mdt_identity *identity = &entry->u.identity;
+        struct md_identity *identity = &entry->u.identity;
 
 
-        if (identity->mi_ginfo)
+        if (identity->mi_ginfo) {
                 groups_free(identity->mi_ginfo);
                 groups_free(identity->mi_ginfo);
+                identity->mi_ginfo = NULL;
+        }
 
         if (identity->mi_nperms) {
                 LASSERT(identity->mi_perms);
                 OBD_FREE(identity->mi_perms,
 
         if (identity->mi_nperms) {
                 LASSERT(identity->mi_perms);
                 OBD_FREE(identity->mi_perms,
-                         identity->mi_nperms * sizeof(struct mdt_setxid_perm));
+                         identity->mi_nperms * sizeof(struct md_perm));
+                identity->mi_nperms = 0;
         }
 }
 
         }
 }
 
@@ -120,10 +123,10 @@ static int mdt_identity_parse_downcall(struct upcall_cache *cache,
                                        struct upcall_cache_entry *entry,
                                        void *args)
 {
                                        struct upcall_cache_entry *entry,
                                        void *args)
 {
-        struct mdt_identity *identity = &entry->u.identity;
+        struct md_identity *identity = &entry->u.identity;
         struct identity_downcall_data *data = args;
         struct group_info *ginfo;
         struct identity_downcall_data *data = args;
         struct group_info *ginfo;
-        struct mdt_setxid_perm *perms = NULL;
+        struct md_perm *perms = NULL;
         int size, i;
         ENTRY;
 
         int size, i;
         ENTRY;
 
@@ -137,9 +140,8 @@ static int mdt_identity_parse_downcall(struct upcall_cache *cache,
                 RETURN(-ENOMEM);
         }
 
                 RETURN(-ENOMEM);
         }
 
-        groups_from_list(ginfo, data->idd_groups);
-        groups_sort(ginfo);
-        identity->mi_ginfo = ginfo;
+        lustre_groups_from_list(ginfo, data->idd_groups);
+        lustre_groups_sort(ginfo);
 
         if (data->idd_nperms) {
                 size = data->idd_nperms * sizeof(*perms);
 
         if (data->idd_nperms) {
                 size = data->idd_nperms * sizeof(*perms);
@@ -147,9 +149,10 @@ static int mdt_identity_parse_downcall(struct upcall_cache *cache,
                 if (!perms) {
                         CERROR("failed to alloc %d permissions\n",
                                data->idd_nperms);
                 if (!perms) {
                         CERROR("failed to alloc %d permissions\n",
                                data->idd_nperms);
-                        put_group_info(ginfo);
+                        groups_free(ginfo);
                         RETURN(-ENOMEM);
                 }
                         RETURN(-ENOMEM);
                 }
+
                 for (i = 0; i < data->idd_nperms; i++) {
                         perms[i].mp_nid = data->idd_perms[i].pdd_nid;
                         perms[i].mp_perm = data->idd_perms[i].pdd_perm;
                 for (i = 0; i < data->idd_nperms; i++) {
                         perms[i].mp_nid = data->idd_perms[i].pdd_nid;
                         perms[i].mp_perm = data->idd_perms[i].pdd_perm;
@@ -169,7 +172,7 @@ static int mdt_identity_parse_downcall(struct upcall_cache *cache,
         RETURN(0);
 }
 
         RETURN(0);
 }
 
-struct mdt_identity *mdt_identity_get(struct upcall_cache *cache, __u32 uid)
+struct md_identity *mdt_identity_get(struct upcall_cache *cache, __u32 uid)
 {
         struct upcall_cache_entry *entry;
 
 {
         struct upcall_cache_entry *entry;
 
@@ -185,7 +188,7 @@ struct mdt_identity *mdt_identity_get(struct upcall_cache *cache, __u32 uid)
         return &entry->u.identity;
 }
 
         return &entry->u.identity;
 }
 
-void mdt_identity_put(struct upcall_cache *cache, struct mdt_identity *identity)
+void mdt_identity_put(struct upcall_cache *cache, struct md_identity *identity)
 {
         if (!cache)
                 return;
 {
         if (!cache)
                 return;
@@ -213,12 +216,18 @@ void mdt_flush_identity(struct upcall_cache *cache, int uid)
  * If there is LNET_NID_ANY in perm[i].mp_nid,
  * it must be perm[0].mp_nid, and act as default perm.
  */
  * If there is LNET_NID_ANY in perm[i].mp_nid,
  * it must be perm[0].mp_nid, and act as default perm.
  */
-__u32 mdt_identity_get_setxid_perm(struct mdt_identity *identity,
+__u32 mdt_identity_get_perm(struct md_identity *identity,
                                    __u32 is_rmtclient, lnet_nid_t nid)
 {
                                    __u32 is_rmtclient, lnet_nid_t nid)
 {
-        struct mdt_setxid_perm *perm = identity->mi_perms;
+        struct md_perm *perm;
         int i;
 
         int i;
 
+        if (!identity) {
+                LASSERT(is_rmtclient == 0);
+                return CFS_SETGRP_PERM;
+        }
+
+        perm = identity->mi_perms;
         /* check exactly matched nid first */
         for (i = identity->mi_nperms - 1; i > 0; i--) {
                 if (perm[i].mp_nid != nid)
         /* check exactly matched nid first */
         for (i = identity->mi_nperms - 1; i > 0; i--) {
                 if (perm[i].mp_nid != nid)
@@ -232,7 +241,7 @@ __u32 mdt_identity_get_setxid_perm(struct mdt_identity *identity,
                 return perm[0].mp_perm;
 
         /* return default last */
                 return perm[0].mp_perm;
 
         /* return default last */
-        return is_rmtclient ? 0 : LUSTRE_SETGRP_PERM;
+        return is_rmtclient ? 0 : CFS_SETGRP_PERM;
 }
 
 int mdt_pack_remote_perm(struct mdt_thread_info *info, struct mdt_object *o,
 }
 
 int mdt_pack_remote_perm(struct mdt_thread_info *info, struct mdt_object *o,
index 567c884..d7d602c 100644 (file)
@@ -27,9 +27,7 @@
 #endif
 #define DEBUG_SUBSYSTEM S_MDS
 
 #endif
 #define DEBUG_SUBSYSTEM S_MDS
 
-#ifndef AUTOCONF_INCLUDED
 #include <linux/config.h>
 #include <linux/config.h>
-#endif
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 
 #include "mdt_internal.h"
 
 
 #include "mdt_internal.h"
 
-enum {
-        MDT_IDMAP_NOTFOUND      = -1,
-};
-
-struct mdt_idmap_entry {
-        struct list_head mie_rmt_hash; /* hashed as mie_rmt_id; */
-        struct list_head mie_lcl_hash; /* hashed as mie_lcl_id; */
-        int              mie_refcount;
-        uid_t            mie_rmt_id;   /* remote uid/gid */
-        uid_t            mie_lcl_id;   /* local uid/gid */
-};
-
-/* uid/gid mapping */
-static struct mdt_idmap_table *mdt_idmap_alloc(void)
-{
-        struct mdt_idmap_table *tbl;
-        int i, j;
-
-        OBD_ALLOC_PTR(tbl);
-        if (!tbl)
-                return NULL;
-
-        spin_lock_init(&tbl->mit_lock);
-        for (i = 0; i < ARRAY_SIZE(tbl->mit_idmaps); i++)
-                for (j = 0; j < ARRAY_SIZE(tbl->mit_idmaps[i]); j++)
-                        INIT_LIST_HEAD(&tbl->mit_idmaps[i][j]);
-
-        return tbl;
-}
-
-static struct mdt_idmap_entry *idmap_entry_alloc(__u32 mie_rmt_id,
-                                                 __u32 mie_lcl_id)
-{
-        struct mdt_idmap_entry *e;
-
-        OBD_ALLOC_PTR(e);
-        if (!e)
-                return NULL;
-
-        INIT_LIST_HEAD(&e->mie_rmt_hash);
-        INIT_LIST_HEAD(&e->mie_lcl_hash);
-        e->mie_refcount = 1;
-        e->mie_rmt_id = mie_rmt_id;
-        e->mie_lcl_id = mie_lcl_id;
-
-        return e;
-}
-
-static void idmap_entry_free(struct mdt_idmap_entry *e)
-{
-        if (!list_empty(&e->mie_rmt_hash))
-                list_del(&e->mie_rmt_hash);
-        if (!list_empty(&e->mie_lcl_hash))
-                list_del(&e->mie_lcl_hash);
-        OBD_FREE_PTR(e);
-}
-
 int mdt_init_idmap(struct mdt_thread_info *info)
 {
         struct ptlrpc_request *req = mdt_info_req(info);
 int mdt_init_idmap(struct mdt_thread_info *info)
 {
         struct ptlrpc_request *req = mdt_info_req(info);
@@ -135,7 +76,6 @@ int mdt_init_idmap(struct mdt_thread_info *info)
         if (!req->rq_auth_gss || req->rq_auth_usr_mdt) {
                 med->med_rmtclient = 0;
                 reply->ocd_connect_flags &= ~OBD_CONNECT_RMT_CLIENT;
         if (!req->rq_auth_gss || req->rq_auth_usr_mdt) {
                 med->med_rmtclient = 0;
                 reply->ocd_connect_flags &= ~OBD_CONNECT_RMT_CLIENT;
-                //reply->ocd_connect_flags |= OBD_CONNECT_LCL_CLIENT;
                 RETURN(0);
         }
 
                 RETURN(0);
         }
 
@@ -153,22 +93,31 @@ int mdt_init_idmap(struct mdt_thread_info *info)
         }
 
         if (med->med_rmtclient) {
         }
 
         if (med->med_rmtclient) {
-                med->med_nllu = data->ocd_nllu;
-                med->med_nllg = data->ocd_nllg;
+                down(&med->med_idmap_sem);
                 if (!med->med_idmap)
                 if (!med->med_idmap)
-                        med->med_idmap = mdt_idmap_alloc();
-                if (!med->med_idmap) {
-                        CERROR("client %s -> target %s failed to alloc idmap!\n"
-                               , client, obd->obd_name);
+                        med->med_idmap = lustre_idmap_init();
+                up(&med->med_idmap_sem);
+
+                if (IS_ERR(med->med_idmap)) {
+                        long err = PTR_ERR(med->med_idmap);
+
+                        med->med_idmap = NULL;
+                        CERROR("client %s -> target %s "
+                               "failed to init idmap [%ld]!\n",
+                               client, obd->obd_name, err);
+                        RETURN(err);
+                } else if (!med->med_idmap) {
+                        CERROR("client %s -> target %s "
+                               "failed to init(2) idmap!\n",
+                               client, obd->obd_name);
                         RETURN(-ENOMEM);
                 }
 
                 reply->ocd_connect_flags &= ~OBD_CONNECT_LCL_CLIENT;
                         RETURN(-ENOMEM);
                 }
 
                 reply->ocd_connect_flags &= ~OBD_CONNECT_LCL_CLIENT;
-                //reply->ocd_connect_flags |= OBD_CONNECT_RMT_CLIENT;
                 CDEBUG(D_SEC, "client %s -> target %s is remote.\n",
                        client, obd->obd_name);
 
                 CDEBUG(D_SEC, "client %s -> target %s is remote.\n",
                        client, obd->obd_name);
 
-                /* NB, MDT_CONNECT establish root idmap too! */
+                /* NB, MDS_CONNECT establish root idmap too! */
                 rc = mdt_handle_idmap(info);
         } else {
                 if (req->rq_auth_uid == INVALID_UID) {
                 rc = mdt_handle_idmap(info);
         } else {
                 if (req->rq_auth_uid == INVALID_UID) {
@@ -177,47 +126,21 @@ int mdt_init_idmap(struct mdt_thread_info *info)
                         RETURN(-EACCES);
                 }
                 reply->ocd_connect_flags &= ~OBD_CONNECT_RMT_CLIENT;
                         RETURN(-EACCES);
                 }
                 reply->ocd_connect_flags &= ~OBD_CONNECT_RMT_CLIENT;
-                //reply->ocd_connect_flags |= OBD_CONNECT_LCL_CLIENT;
         }
 
         RETURN(rc);
 }
 
         }
 
         RETURN(rc);
 }
 
-static void idmap_clear_mie_rmt_hash(struct list_head *list)
-{
-        struct mdt_idmap_entry *e;
-        int i;
-
-        for (i = 0; i < MDT_IDMAP_HASHSIZE; i++) {
-                while (!list_empty(&list[i])) {
-                        e = list_entry(list[i].next, struct mdt_idmap_entry,
-                                       mie_rmt_hash);
-                        idmap_entry_free(e);
-                }
-        }
-}
-
 void mdt_cleanup_idmap(struct mdt_export_data *med)
 {
 void mdt_cleanup_idmap(struct mdt_export_data *med)
 {
-        struct mdt_idmap_table *tbl = med->med_idmap;
-        int i;
-
         LASSERT(med->med_rmtclient);
         LASSERT(med->med_rmtclient);
-        LASSERT(tbl);
-
-        spin_lock(&tbl->mit_lock);
-        idmap_clear_mie_rmt_hash(tbl->mit_idmaps[RMT_UIDMAP_IDX]);
-        idmap_clear_mie_rmt_hash(tbl->mit_idmaps[RMT_GIDMAP_IDX]);
-
-        /* paranoid checking */
-        for (i = 0; i < MDT_IDMAP_HASHSIZE; i++) {
-                LASSERT(list_empty(&tbl->mit_idmaps[LCL_UIDMAP_IDX][i]));
-                LASSERT(list_empty(&tbl->mit_idmaps[LCL_GIDMAP_IDX][i]));
-        }
-        spin_unlock(&tbl->mit_lock);
 
 
-        OBD_FREE_PTR(tbl);
+        down(&med->med_idmap_sem);
+        if (med->med_idmap != NULL) {
+                lustre_idmap_fini(med->med_idmap);
         med->med_idmap = NULL;
         med->med_idmap = NULL;
+        }
+        up(&med->med_idmap_sem);
 }
 
 static inline void mdt_revoke_export_locks(struct obd_export *exp)
 }
 
 static inline void mdt_revoke_export_locks(struct obd_export *exp)
@@ -229,217 +152,15 @@ static inline void mdt_revoke_export_locks(struct obd_export *exp)
         ldlm_revoke_export_locks(exp);
 }
 
         ldlm_revoke_export_locks(exp);
 }
 
-static
-struct mdt_idmap_entry *idmap_lookup_entry(struct list_head *mie_rmt_hash,
-                                           uid_t mie_rmt_id, uid_t mie_lcl_id)
-{
-        struct list_head *rmt_head =
-                         &mie_rmt_hash[MDT_IDMAP_HASHFUNC(mie_rmt_id)];
-        struct mdt_idmap_entry *e;
-
-        list_for_each_entry(e, rmt_head, mie_rmt_hash) {
-                if ((e->mie_rmt_id == mie_rmt_id) &&
-                    (e->mie_lcl_id == mie_lcl_id))
-                        return e;
-        }
-        return NULL;
-}
-
-/*
- * return value
- * NULL: not found entry
- * ERR_PTR(-EACCES): found multi->single mapped entry
- * others: found normal entry
- */
-static
-struct mdt_idmap_entry *idmap_search_entry(struct list_head *mie_rmt_hash,
-                                           uid_t mie_rmt_id,
-                                           struct list_head *mie_lcl_hash,
-                                           uid_t mie_lcl_id,
-                                           const char *warn_msg)
-{
-        struct list_head *rmt_head =
-                         &mie_rmt_hash[MDT_IDMAP_HASHFUNC(mie_rmt_id)];
-        struct list_head *lcl_head =
-                         &mie_lcl_hash[MDT_IDMAP_HASHFUNC(mie_lcl_id)];
-        struct mdt_idmap_entry *e;
-
-        list_for_each_entry(e, rmt_head, mie_rmt_hash) {
-                if (e->mie_rmt_id == mie_rmt_id) {
-                        if (e->mie_lcl_id == mie_lcl_id) {
-                                e->mie_refcount++;
-                                return e;
-                        } else {
-                                CERROR("%s: rmt id %u already be mapped to %u"
-                                       " (new %u)\n", warn_msg, e->mie_rmt_id,
-                                       e->mie_lcl_id, mie_lcl_id);
-                                return ERR_PTR(-EACCES);
-                        }
-                }
-        }
-
-        list_for_each_entry(e, lcl_head, mie_lcl_hash) {
-                if (e->mie_lcl_id == mie_lcl_id) {
-                        if (e->mie_rmt_id == mie_rmt_id) {
-                                e->mie_refcount++;
-                                return e;
-                        } else {
-                                CERROR("%s: lcl id %u already be mapped from %u"
-                                       " (new %u)\n", warn_msg, e->mie_lcl_id,
-                                       e->mie_rmt_id, mie_rmt_id);
-                                return ERR_PTR(-EACCES);
-                        }
-                }
-        }
-
-        return NULL;
-}
-
-static
-struct mdt_idmap_entry *idmap_insert_entry(struct list_head *mie_rmt_hash,
-                                           struct list_head *mie_lcl_hash,
-                                           struct mdt_idmap_entry *new,
-                                           const char *warn_msg)
-{
-        struct list_head *rmt_head =
-                         &mie_rmt_hash[MDT_IDMAP_HASHFUNC(new->mie_rmt_id)];
-        struct list_head *lcl_head =
-                         &mie_lcl_hash[MDT_IDMAP_HASHFUNC(new->mie_lcl_id)];
-        struct mdt_idmap_entry *e;
-
-        e = idmap_search_entry(mie_rmt_hash, new->mie_rmt_id,
-                               mie_lcl_hash, new->mie_lcl_id,
-                               warn_msg);
-        if (e == NULL) {
-                list_add_tail(&new->mie_rmt_hash, rmt_head);
-                list_add_tail(&new->mie_lcl_hash, lcl_head);
-        }
-        return e;
-}
-
-static int idmap_remove_entry(struct list_head *mie_rmt_hash,
-                              struct list_head *mie_lcl_hash,
-                              __u32 mie_rmt_id, __u32 mie_lcl_id)
-{
-        struct mdt_idmap_entry *e;
-        int rc = -ENOENT;
-
-        e = idmap_lookup_entry(mie_rmt_hash, mie_rmt_id, mie_lcl_id);
-        if (e != NULL) {
-                        e->mie_refcount--;
-                        if ((rc = e->mie_refcount) <= 0)
-                                idmap_entry_free(e);
-        }
-        return rc;
-}
-
-static int mdt_idmap_add(struct mdt_idmap_table *tbl,
-                         uid_t ruid, uid_t luid,
-                         gid_t rgid, gid_t lgid)
-{
-        struct mdt_idmap_entry *ue0, *ue1, *ge0, *ge1;
-        ENTRY;
-
-        LASSERT(tbl);
-
-        spin_lock(&tbl->mit_lock);
-        ue0 = idmap_search_entry(tbl->mit_idmaps[RMT_UIDMAP_IDX], ruid,
-                                 tbl->mit_idmaps[LCL_UIDMAP_IDX], luid,
-                                 "UID mapping");
-        spin_unlock(&tbl->mit_lock);
-        if (!ue0) {
-                ue0 = idmap_entry_alloc(ruid, luid);
-                if (!ue0)
-                        RETURN(-ENOMEM);
-
-                spin_lock(&tbl->mit_lock);
-                ue1 = idmap_insert_entry(tbl->mit_idmaps[RMT_UIDMAP_IDX],
-                                         tbl->mit_idmaps[LCL_UIDMAP_IDX],
-                                         ue0, "UID mapping");
-                if (ue1 != NULL) {
-                        idmap_entry_free(ue0);
-                        ue0 = ue1;
-                }
-                spin_unlock(&tbl->mit_lock);
-
-                if (IS_ERR(ue1))
-                        RETURN(PTR_ERR(ue1));
-        } else if (IS_ERR(ue0)) {
-                RETURN(PTR_ERR(ue0));
-        }
-
-        spin_lock(&tbl->mit_lock);
-        ge0 = idmap_search_entry(tbl->mit_idmaps[RMT_GIDMAP_IDX], rgid,
-                                 tbl->mit_idmaps[LCL_GIDMAP_IDX], lgid,
-                                 "GID mapping");
-        spin_unlock(&tbl->mit_lock);
-        if (!ge0) {
-                ge0 = idmap_entry_alloc(rgid, lgid);
-                spin_lock(&tbl->mit_lock);
-                if (!ge0) {
-                        ue0->mie_refcount--;
-                        if (ue0->mie_refcount <= 0)
-                                idmap_entry_free(ue0);
-                        spin_unlock(&tbl->mit_lock);
-                        RETURN(-ENOMEM);
-                }
-
-                ge1 = idmap_insert_entry(tbl->mit_idmaps[RMT_GIDMAP_IDX],
-                                         tbl->mit_idmaps[LCL_GIDMAP_IDX],
-                                         ge0, "GID mapping");
-                if (ge1 != NULL) {
-                        ue0->mie_refcount--;
-                        if (ue0->mie_refcount <= 0)
-                                idmap_entry_free(ue0);
-                        idmap_entry_free(ge0);
-                }
-                spin_unlock(&tbl->mit_lock);
-
-                if (IS_ERR(ge1))
-                        RETURN(PTR_ERR(ge1));
-        } else if (IS_ERR(ge0)) {
-                spin_lock(&tbl->mit_lock);
-                ue0->mie_refcount--;
-                if (ue0->mie_refcount <= 0)
-                        idmap_entry_free(ue0);
-                spin_unlock(&tbl->mit_lock);
-                RETURN(PTR_ERR(ge0));
-        }
-
-        RETURN(0);
-}
-
-static int mdt_idmap_del(struct mdt_idmap_table *tbl,
-                         uid_t ruid, uid_t luid,
-                         gid_t rgid, gid_t lgid)
-{
-        ENTRY;
-
-        if (!tbl)
-                RETURN(0);
-
-        spin_lock(&tbl->mit_lock);
-        idmap_remove_entry(tbl->mit_idmaps[RMT_UIDMAP_IDX],
-                           tbl->mit_idmaps[LCL_UIDMAP_IDX],
-                           ruid, luid);
-        idmap_remove_entry(tbl->mit_idmaps[RMT_GIDMAP_IDX],
-                           tbl->mit_idmaps[LCL_GIDMAP_IDX],
-                           rgid, lgid);
-        spin_unlock(&tbl->mit_lock);
-
-        RETURN(0);
-}
-
 int mdt_handle_idmap(struct mdt_thread_info *info)
 {
         struct ptlrpc_request *req = mdt_info_req(info);
         struct mdt_device *mdt = info->mti_mdt;
         struct mdt_export_data *med;
         struct ptlrpc_user_desc *pud = req->rq_user_desc;
 int mdt_handle_idmap(struct mdt_thread_info *info)
 {
         struct ptlrpc_request *req = mdt_info_req(info);
         struct mdt_device *mdt = info->mti_mdt;
         struct mdt_export_data *med;
         struct ptlrpc_user_desc *pud = req->rq_user_desc;
-        struct mdt_identity *identity;
+        struct md_identity *identity;
         __u32 opc;
         int rc = 0;
         __u32 opc;
         int rc = 0;
-
         ENTRY;
 
         if (!req->rq_export)
         ENTRY;
 
         if (!req->rq_export)
@@ -455,9 +176,13 @@ int mdt_handle_idmap(struct mdt_thread_info *info)
             (opc != SEC_CTX_FINI) && (opc != MDS_CONNECT))
                 RETURN(0);
 
             (opc != SEC_CTX_FINI) && (opc != MDS_CONNECT))
                 RETURN(0);
 
-        LASSERT(pud);
         LASSERT(med->med_idmap);
 
         LASSERT(med->med_idmap);
 
+        if (unlikely(!pud)) {
+                CERROR("remote client must run with rq_user_desc present\n");
+                RETURN(-EACCES);
+       }
+
         if (req->rq_auth_mapped_uid == INVALID_UID) {
                 CERROR("invalid authorized mapped uid, please check "
                        "/etc/lustre/idmap.conf!\n");
         if (req->rq_auth_mapped_uid == INVALID_UID) {
                 CERROR("invalid authorized mapped uid, please check "
                        "/etc/lustre/idmap.conf!\n");
@@ -481,12 +206,12 @@ int mdt_handle_idmap(struct mdt_thread_info *info)
         case SEC_CTX_INIT:
         case SEC_CTX_INIT_CONT:
         case MDS_CONNECT:
         case SEC_CTX_INIT:
         case SEC_CTX_INIT_CONT:
         case MDS_CONNECT:
-                rc = mdt_idmap_add(med->med_idmap,
+                        rc = lustre_idmap_add(med->med_idmap,
                                    pud->pud_uid, identity->mi_uid,
                                    pud->pud_gid, identity->mi_gid);
                 break;
         case SEC_CTX_FINI:
                                    pud->pud_uid, identity->mi_uid,
                                    pud->pud_gid, identity->mi_gid);
                 break;
         case SEC_CTX_FINI:
-                rc = mdt_idmap_del(med->med_idmap,
+                        rc = lustre_idmap_del(med->med_idmap,
                                    pud->pud_uid, identity->mi_uid,
                                    pud->pud_gid, identity->mi_gid);
                 break;
                                    pud->pud_uid, identity->mi_uid,
                                    pud->pud_gid, identity->mi_gid);
                 break;
@@ -504,67 +229,15 @@ int mdt_handle_idmap(struct mdt_thread_info *info)
                 mdt_revoke_export_locks(req->rq_export);
                 break;
         }
                 mdt_revoke_export_locks(req->rq_export);
                 break;
         }
-        RETURN(0);
-}
-
-static __u32 idmap_lookup_id(struct list_head *hash, int reverse, __u32 id)
-{
-        struct list_head *head = &hash[MDT_IDMAP_HASHFUNC(id)];
-        struct mdt_idmap_entry *e;
-
-        if (!reverse) {
-                list_for_each_entry(e, head, mie_rmt_hash) {
-                        if (e->mie_rmt_id == id)
-                                return e->mie_lcl_id;
-                }
-        } else {
-                list_for_each_entry(e, head, mie_lcl_hash) {
-                        if (e->mie_lcl_id == id)
-                                return e->mie_rmt_id;
-                }
-        }
-        return MDT_IDMAP_NOTFOUND;
-}
-
-static int mdt_idmap_lookup_uid(struct mdt_idmap_table *tbl, int reverse,
-                                uid_t uid)
-{
-        struct list_head *hash;
-
-        if (!tbl)
-                return MDT_IDMAP_NOTFOUND;
-
-        hash = tbl->mit_idmaps[reverse ? LCL_UIDMAP_IDX : RMT_UIDMAP_IDX];
-
-        spin_lock(&tbl->mit_lock);
-        uid = idmap_lookup_id(hash, reverse, uid);
-        spin_unlock(&tbl->mit_lock);
-
-        return uid;
-}
-
-static int mdt_idmap_lookup_gid(struct mdt_idmap_table *tbl, int reverse,
-                                gid_t gid)
-{
-        struct list_head *hash;
-
-        if (!tbl)
-                return MDT_IDMAP_NOTFOUND;
-
-        hash = tbl->mit_idmaps[reverse ? LCL_GIDMAP_IDX : RMT_GIDMAP_IDX];
-
-        spin_lock(&tbl->mit_lock);
-        gid = idmap_lookup_id(hash, reverse, gid);
-        spin_unlock(&tbl->mit_lock);
 
 
-        return gid;
+        RETURN(0);
 }
 
 int ptlrpc_user_desc_do_idmap(struct ptlrpc_request *req,
                               struct ptlrpc_user_desc *pud)
 {
         struct mdt_export_data *med = mdt_req2med(req);
 }
 
 int ptlrpc_user_desc_do_idmap(struct ptlrpc_request *req,
                               struct ptlrpc_user_desc *pud)
 {
         struct mdt_export_data *med = mdt_req2med(req);
-        struct mdt_idmap_table *idmap = med->med_idmap;
+        struct lustre_idmap_table *idmap = med->med_idmap;
         uid_t uid, fsuid;
         gid_t gid, fsgid;
 
         uid_t uid, fsuid;
         gid_t gid, fsgid;
 
@@ -572,8 +245,8 @@ int ptlrpc_user_desc_do_idmap(struct ptlrpc_request *req,
         if (!med->med_rmtclient)
                 return 0;
 
         if (!med->med_rmtclient)
                 return 0;
 
-        uid = mdt_idmap_lookup_uid(idmap, 0, pud->pud_uid);
-        if (uid == MDT_IDMAP_NOTFOUND) {
+        uid = lustre_idmap_lookup_uid(NULL, idmap, 0, pud->pud_uid);
+        if (uid == CFS_IDMAP_NOTFOUND) {
                 CERROR("no mapping for uid %u\n", pud->pud_uid);
                 return -EACCES;
         }
                 CERROR("no mapping for uid %u\n", pud->pud_uid);
                 return -EACCES;
         }
@@ -581,15 +254,15 @@ int ptlrpc_user_desc_do_idmap(struct ptlrpc_request *req,
         if (pud->pud_uid == pud->pud_fsuid) {
                 fsuid = uid;
         } else {
         if (pud->pud_uid == pud->pud_fsuid) {
                 fsuid = uid;
         } else {
-                fsuid = mdt_idmap_lookup_uid(idmap, 0, pud->pud_fsuid);
-                if (fsuid == MDT_IDMAP_NOTFOUND) {
+                fsuid = lustre_idmap_lookup_uid(NULL, idmap, 0, pud->pud_fsuid);
+                if (fsuid == CFS_IDMAP_NOTFOUND) {
                         CERROR("no mapping for fsuid %u\n", pud->pud_fsuid);
                         return -EACCES;
                 }
         }
 
                         CERROR("no mapping for fsuid %u\n", pud->pud_fsuid);
                         return -EACCES;
                 }
         }
 
-        gid = mdt_idmap_lookup_gid(idmap, 0, pud->pud_gid);
-        if (gid == MDT_IDMAP_NOTFOUND) {
+        gid = lustre_idmap_lookup_gid(NULL, idmap, 0, pud->pud_gid);
+        if (gid == CFS_IDMAP_NOTFOUND) {
                 CERROR("no mapping for gid %u\n", pud->pud_gid);
                 return -EACCES;
         }
                 CERROR("no mapping for gid %u\n", pud->pud_gid);
                 return -EACCES;
         }
@@ -597,8 +270,8 @@ int ptlrpc_user_desc_do_idmap(struct ptlrpc_request *req,
         if (pud->pud_gid == pud->pud_fsgid) {
                 fsgid = gid;
         } else {
         if (pud->pud_gid == pud->pud_fsgid) {
                 fsgid = gid;
         } else {
-                fsgid = mdt_idmap_lookup_gid(idmap, 0, pud->pud_fsgid);
-                if (fsgid == MDT_IDMAP_NOTFOUND) {
+                fsgid = lustre_idmap_lookup_gid(NULL, idmap, 0, pud->pud_fsgid);
+                if (fsgid == CFS_IDMAP_NOTFOUND) {
                         CERROR("no mapping for fsgid %u\n", pud->pud_fsgid);
                         return -EACCES;
                 }
                         CERROR("no mapping for fsgid %u\n", pud->pud_fsgid);
                         return -EACCES;
                 }
@@ -613,37 +286,23 @@ int ptlrpc_user_desc_do_idmap(struct ptlrpc_request *req,
 }
 
 /*
 }
 
 /*
- * Reverse map
- * Do not ignore rootsquash.
+ * Reverse mapping
  */
 void mdt_body_reverse_idmap(struct mdt_thread_info *info, struct mdt_body *body)
 {
         struct ptlrpc_request   *req = mdt_info_req(info);
         struct md_ucred         *uc = mdt_ucred(info);
         struct mdt_export_data  *med = mdt_req2med(req);
  */
 void mdt_body_reverse_idmap(struct mdt_thread_info *info, struct mdt_body *body)
 {
         struct ptlrpc_request   *req = mdt_info_req(info);
         struct md_ucred         *uc = mdt_ucred(info);
         struct mdt_export_data  *med = mdt_req2med(req);
-        struct mdt_idmap_table  *idmap = med->med_idmap;
-        uid_t uid;
-        gid_t gid;
+        struct lustre_idmap_table *idmap = med->med_idmap;
 
         if (!med->med_rmtclient)
                 return;
 
         if (body->valid & OBD_MD_FLUID) {
 
         if (!med->med_rmtclient)
                 return;
 
         if (body->valid & OBD_MD_FLUID) {
-                if (((uc->mu_valid == UCRED_OLD) ||
-                    (uc->mu_valid == UCRED_NEW)) &&
-                    !(uc->mu_squash & SQUASH_UID)) {
-                        if (body->uid == uc->mu_uid)
-                                uid = uc->mu_o_uid;
-                        else if (body->uid == uc->mu_fsuid)
-                                uid = uc->mu_o_fsuid;
-                        else
-                                uid = mdt_idmap_lookup_uid(idmap, 1, body->uid);
-                } else {
-                        uid = mdt_idmap_lookup_uid(idmap, 1, body->uid);
-                }
+                uid_t uid = lustre_idmap_lookup_uid(uc, idmap, 1, body->uid);
 
 
-                if (uid == MDT_IDMAP_NOTFOUND) {
-                        uid = med->med_nllu;
+                if (uid == CFS_IDMAP_NOTFOUND) {
+                        uid = NOBODY_UID;
                         if (body->valid & OBD_MD_FLMODE)
                                 body->mode = (body->mode & ~S_IRWXU) |
                                              ((body->mode & S_IRWXO) << 6);
                         if (body->valid & OBD_MD_FLMODE)
                                 body->mode = (body->mode & ~S_IRWXU) |
                                              ((body->mode & S_IRWXO) << 6);
@@ -653,21 +312,10 @@ void mdt_body_reverse_idmap(struct mdt_thread_info *info, struct mdt_body *body)
         }
 
         if (body->valid & OBD_MD_FLGID) {
         }
 
         if (body->valid & OBD_MD_FLGID) {
-                if (((uc->mu_valid == UCRED_OLD) ||
-                    (uc->mu_valid == UCRED_NEW)) &&
-                    !(uc->mu_squash & SQUASH_GID)) {
-                        if (body->gid == uc->mu_gid)
-                                gid = uc->mu_o_gid;
-                        else if (body->gid == uc->mu_fsgid)
-                                gid = uc->mu_o_fsgid;
-                        else
-                                gid = mdt_idmap_lookup_gid(idmap, 1, body->gid);
-                } else {
-                        gid = mdt_idmap_lookup_gid(idmap, 1, body->gid);
-                }
+                gid_t gid = lustre_idmap_lookup_gid(uc, idmap, 1, body->gid);
 
 
-                if (gid == MDT_IDMAP_NOTFOUND) {
-                        gid = med->med_nllg;
+                if (gid == CFS_IDMAP_NOTFOUND) {
+                        gid = NOBODY_GID;
                         if (body->valid & OBD_MD_FLMODE)
                                 body->mode = (body->mode & ~S_IRWXG) |
                                              ((body->mode & S_IRWXO) << 3);
                         if (body->valid & OBD_MD_FLMODE)
                                 body->mode = (body->mode & ~S_IRWXG) |
                                              ((body->mode & S_IRWXO) << 3);
@@ -677,124 +325,50 @@ void mdt_body_reverse_idmap(struct mdt_thread_info *info, struct mdt_body *body)
         }
 }
 
         }
 }
 
-/* NB: return error if no mapping, so this will look strange:
- * if client hasn't kinit the to map xid for the mapped xid, client
- * will always get -EPERM, and the same for rootsquash case. */
-int mdt_remote_perm_reverse_idmap(struct ptlrpc_request *req,
-                                  struct mdt_remote_perm *perm)
-{
-        struct mdt_export_data *med = mdt_req2med(req);
-        uid_t uid, fsuid;
-        gid_t gid, fsgid;
-
-        LASSERT(med->med_rmtclient);
-
-        uid = mdt_idmap_lookup_uid(med->med_idmap, 1, perm->rp_uid);
-        if (uid == MDT_IDMAP_NOTFOUND) {
-                CERROR("no mapping for uid %u\n", perm->rp_uid);
-                return -EPERM;
-        }
-
-        gid = mdt_idmap_lookup_gid(med->med_idmap, 1, perm->rp_gid);
-        if (gid == MDT_IDMAP_NOTFOUND) {
-                CERROR("no mapping for gid %u\n", perm->rp_gid);
-                return -EPERM;
-        }
-
-        if (perm->rp_uid != perm->rp_fsuid) {
-                fsuid = mdt_idmap_lookup_uid(med->med_idmap, 1, perm->rp_fsuid);
-                if (fsuid == MDT_IDMAP_NOTFOUND) {
-                        CERROR("no mapping for fsuid %u\n", perm->rp_fsuid);
-                        return -EPERM;
-                }
-        } else {
-                fsuid = uid;
-        }
-
-        if (perm->rp_gid != perm->rp_fsgid) {
-                fsgid = mdt_idmap_lookup_gid(med->med_idmap, 1, perm->rp_fsgid);
-                if (fsgid == MDT_IDMAP_NOTFOUND) {
-                        CERROR("no mapping for fsgid %u\n", perm->rp_fsgid);
-                        return -EPERM;
-                }
-        } else {
-                fsgid = gid;
-        }
-
-        perm->rp_uid = uid;
-        perm->rp_gid = gid;
-        perm->rp_fsuid = fsuid;
-        perm->rp_fsgid = fsgid;
-        return 0;
-}
-
-/* Process remote client and rootsquash */
+/* Do not ignore root_squash for non-setattr case. */
 int mdt_fix_attr_ucred(struct mdt_thread_info *info, __u32 op)
 {
         struct ptlrpc_request   *req = mdt_info_req(info);
         struct md_ucred         *uc = mdt_ucred(info);
         struct lu_attr          *attr = &info->mti_attr.ma_attr;
         struct mdt_export_data  *med = mdt_req2med(req);
 int mdt_fix_attr_ucred(struct mdt_thread_info *info, __u32 op)
 {
         struct ptlrpc_request   *req = mdt_info_req(info);
         struct md_ucred         *uc = mdt_ucred(info);
         struct lu_attr          *attr = &info->mti_attr.ma_attr;
         struct mdt_export_data  *med = mdt_req2med(req);
-        struct mdt_idmap_table  *idmap = med->med_idmap;
-
-        ENTRY;
+        struct lustre_idmap_table *idmap = med->med_idmap;
 
         if ((uc->mu_valid != UCRED_OLD) && (uc->mu_valid != UCRED_NEW))
 
         if ((uc->mu_valid != UCRED_OLD) && (uc->mu_valid != UCRED_NEW))
-                RETURN(-EINVAL);
-
-        if (!med->med_rmtclient && (uc->mu_squash == SQUASH_NONE))
-                RETURN(0);
+                return -EINVAL;
 
         if (op != REINT_SETATTR) {
                 if ((attr->la_valid & LA_UID) && (attr->la_uid != -1))
                         attr->la_uid = uc->mu_fsuid;
 
         if (op != REINT_SETATTR) {
                 if ((attr->la_valid & LA_UID) && (attr->la_uid != -1))
                         attr->la_uid = uc->mu_fsuid;
-                if (op != REINT_CREATE) {
+                /* for S_ISGID, inherit gid from his parent, such work will be
+                 * done in cmm/mdd layer, here set all cases as uc->mu_fsgid. */
                         if ((attr->la_valid & LA_GID) && (attr->la_gid != -1))
                                 attr->la_gid = uc->mu_fsgid;
                         if ((attr->la_valid & LA_GID) && (attr->la_gid != -1))
                                 attr->la_gid = uc->mu_fsgid;
-                } else {
-                        /* for S_ISGID, inherit gid from his parent */
-                        if (!(attr->la_mode & S_ISGID) && (attr->la_gid != -1))
-                                attr->la_gid = uc->mu_fsgid;
-                }
         } else if (med->med_rmtclient) {
                 /* NB: -1 case will be handled by mdt_fix_attr() later. */
                 if ((attr->la_valid & LA_UID) && (attr->la_uid != -1)) {
         } else if (med->med_rmtclient) {
                 /* NB: -1 case will be handled by mdt_fix_attr() later. */
                 if ((attr->la_valid & LA_UID) && (attr->la_uid != -1)) {
-                        uid_t uid;
-
-                        if (attr->la_uid == uc->mu_o_uid)
-                                uid = uc->mu_uid;
-                        else if (attr->la_uid == uc->mu_o_fsuid)
-                                uid = uc->mu_fsuid;
-                        else
-                                uid = mdt_idmap_lookup_uid(idmap, 0,
+                        uid_t uid = lustre_idmap_lookup_uid(uc, idmap, 0,
                                                            attr->la_uid);
 
                                                            attr->la_uid);
 
-                        if (uid == MDT_IDMAP_NOTFOUND) {
+                        if (uid == CFS_IDMAP_NOTFOUND) {
                                 CWARN("Deny chown to uid %u\n", attr->la_uid);
                                 CWARN("Deny chown to uid %u\n", attr->la_uid);
-                                RETURN(-EPERM);
+                                return -EPERM;
                         }
 
                         attr->la_uid = uid;
                 }
                 if ((attr->la_valid & LA_GID) && (attr->la_gid != -1)) {
                         }
 
                         attr->la_uid = uid;
                 }
                 if ((attr->la_valid & LA_GID) && (attr->la_gid != -1)) {
-                        gid_t gid;
-
-                        if (attr->la_gid == uc->mu_o_gid)
-                                gid = uc->mu_gid;
-                        else if (attr->la_gid == uc->mu_o_fsgid)
-                                gid = uc->mu_fsgid;
-                        else
-                                gid = mdt_idmap_lookup_gid(idmap, 0,
+                        gid_t gid = lustre_idmap_lookup_gid(uc, idmap, 0,
                                                            attr->la_gid);
 
                                                            attr->la_gid);
 
-                        if (gid == MDT_IDMAP_NOTFOUND) {
+                        if (gid == CFS_IDMAP_NOTFOUND) {
                                 CWARN("Deny chown to gid %u\n", attr->la_gid);
                                 CWARN("Deny chown to gid %u\n", attr->la_gid);
-                                RETURN(-EPERM);
+                                return -EPERM;
                         }
 
                         attr->la_gid = gid;
                 }
         }
 
                         }
 
                         attr->la_gid = gid;
                 }
         }
 
-        RETURN(0);
+        return 0;
 }
 }
index 4ff1b1e..1745876 100644 (file)
@@ -55,6 +55,8 @@
 #include <lustre_disk.h>
 #include <lustre_sec.h>
 #include <lvfs.h>
 #include <lustre_disk.h>
 #include <lustre_sec.h>
 #include <lvfs.h>
+#include <lustre_idmap.h>
+#include <lustre_eacl.h>
 
 
 /* Data stored per client in the last_rcvd file.  In le32 order. */
 
 
 /* Data stored per client in the last_rcvd file.  In le32 order. */
@@ -177,10 +179,10 @@ struct mdt_device {
         unsigned long              mdt_client_bitmap[(LR_MAX_CLIENTS >> 3) / sizeof(long)];
 
         struct upcall_cache        *mdt_identity_cache;
         unsigned long              mdt_client_bitmap[(LR_MAX_CLIENTS >> 3) / sizeof(long)];
 
         struct upcall_cache        *mdt_identity_cache;
-        struct upcall_cache        *mdt_rmtacl_cache;
 
 
-        /* root squash */
-        struct rootsquash_info     *mdt_rootsquash_info;
+        /* sptlrpc rules */
+        rwlock_t                   mdt_sptlrpc_lock;
+        struct sptlrpc_rule_set    mdt_sptlrpc_rset;
 
         /* capability keys */
         unsigned long              mdt_capa_timeout;
 
         /* capability keys */
         unsigned long              mdt_capa_timeout;
@@ -599,17 +601,10 @@ const struct lu_buf *mdt_buf_const(const struct lu_env *env,
 void mdt_dump_lmm(int level, const struct lov_mds_md *lmm);
 
 int mdt_check_ucred(struct mdt_thread_info *);
 void mdt_dump_lmm(int level, const struct lov_mds_md *lmm);
 
 int mdt_check_ucred(struct mdt_thread_info *);
-
 int mdt_init_ucred(struct mdt_thread_info *, struct mdt_body *);
 int mdt_init_ucred(struct mdt_thread_info *, struct mdt_body *);
-
 int mdt_init_ucred_reint(struct mdt_thread_info *);
 int mdt_init_ucred_reint(struct mdt_thread_info *);
-
 void mdt_exit_ucred(struct mdt_thread_info *);
 
 void mdt_exit_ucred(struct mdt_thread_info *);
 
-int groups_from_list(struct group_info *, gid_t *);
-
-void groups_sort(struct group_info *);
-
 /* mdt_idmap.c */
 int mdt_init_idmap(struct mdt_thread_info *);
 
 /* mdt_idmap.c */
 int mdt_init_idmap(struct mdt_thread_info *);
 
@@ -639,23 +634,16 @@ static inline struct mdt_device *mdt_dev(struct lu_device *d)
 
 extern struct upcall_cache_ops mdt_identity_upcall_cache_ops;
 
 
 extern struct upcall_cache_ops mdt_identity_upcall_cache_ops;
 
-struct mdt_identity *mdt_identity_get(struct upcall_cache *, __u32);
+struct md_identity *mdt_identity_get(struct upcall_cache *, __u32);
 
 
-void mdt_identity_put(struct upcall_cache *, struct mdt_identity *);
+void mdt_identity_put(struct upcall_cache *, struct md_identity *);
 
 void mdt_flush_identity(struct upcall_cache *, int);
 
 
 void mdt_flush_identity(struct upcall_cache *, int);
 
-__u32 mdt_identity_get_setxid_perm(struct mdt_identity *, __u32, lnet_nid_t);
+__u32 mdt_identity_get_perm(struct md_identity *, __u32, lnet_nid_t);
 
 int mdt_pack_remote_perm(struct mdt_thread_info *, struct mdt_object *, void *);
 
 
 int mdt_pack_remote_perm(struct mdt_thread_info *, struct mdt_object *, void *);
 
-/* mdt/mdt_rmtacl.c */
-#define MDT_RMTACL_UPCALL_PATH          "/usr/sbin/l_facl"
-
-extern struct upcall_cache_ops mdt_rmtacl_upcall_cache_ops;
-
-int mdt_rmtacl_upcall(struct mdt_thread_info *, char *, struct lu_buf *);
-
 extern struct lu_context_key       mdt_thread_key;
 /* debug issues helper starts here*/
 static inline void mdt_fail_write(const struct lu_env *env,
 extern struct lu_context_key       mdt_thread_key;
 /* debug issues helper starts here*/
 static inline void mdt_fail_write(const struct lu_env *env,
index 28500c9..37cb8f0 100644 (file)
@@ -11,6 +11,7 @@
  *   Author: Mike Shaver <shaver@clusterfs.com>
  *   Author: Nikita Danilov <nikita@clusterfs.com>
  *   Author: Huang Hua <huanghua@clusterfs.com>
  *   Author: Mike Shaver <shaver@clusterfs.com>
  *   Author: Nikita Danilov <nikita@clusterfs.com>
  *   Author: Huang Hua <huanghua@clusterfs.com>
+ *   Author: Fan Yong <fanyong@clusterfs.com>
  *
  *
  *   This file is part of the Lustre file system, http://www.lustre.org
  *
  *
  *   This file is part of the Lustre file system, http://www.lustre.org
@@ -47,55 +48,6 @@ typedef enum ucred_init_type {
         REC_INIT        = 2
 } ucred_init_type_t;
 
         REC_INIT        = 2
 } ucred_init_type_t;
 
-int groups_from_list(struct group_info *ginfo, gid_t *glist)
-{
-        int i;
-        int count = ginfo->ngroups;
-
-        /* fill group_info from gid array */
-        for (i = 0; i < ginfo->nblocks; i++) {
-                int cp_count = min(NGROUPS_PER_BLOCK, count);
-                int off = i * NGROUPS_PER_BLOCK;
-                int len = cp_count * sizeof(*glist);
-
-                if (memcpy(ginfo->blocks[i], glist + off, len))
-                        return -EFAULT;
-
-                count -= cp_count;
-        }
-        return 0;
-}
-
-/* groups_sort() is copied from linux kernel! */
-/* a simple shell-metzner sort */
-void groups_sort(struct group_info *group_info)
-{
-        int base, max, stride;
-        int gidsetsize = group_info->ngroups;
-
-        for (stride = 1; stride < gidsetsize; stride = 3 * stride + 1)
-                ; /* nothing */
-        stride /= 3;
-
-        while (stride) {
-                max = gidsetsize - stride;
-                for (base = 0; base < max; base++) {
-                        int left = base;
-                        int right = left + stride;
-                        gid_t tmp = GROUP_AT(group_info, right);
-
-                        while (left >= 0 && GROUP_AT(group_info, left) > tmp) {
-                                GROUP_AT(group_info, right) =
-                                    GROUP_AT(group_info, left);
-                                right = left;
-                                left -= stride;
-                        }
-                        GROUP_AT(group_info, right) = tmp;
-                }
-                stride /= 3;
-        }
-}
-
 void mdt_exit_ucred(struct mdt_thread_info *info)
 {
         struct md_ucred   *uc  = mdt_ucred(info);
 void mdt_exit_ucred(struct mdt_thread_info *info)
 {
         struct md_ucred   *uc  = mdt_ucred(info);
@@ -116,168 +68,13 @@ void mdt_exit_ucred(struct mdt_thread_info *info)
         }
 }
 
         }
 }
 
-static int old_init_ucred(struct mdt_thread_info *info,
-                          struct mdt_body *body)
+/* XXX: root_squash will be redesigned in Lustre 1.7.
+ * Do not root_squash for inter-MDS operations */
+static int mdt_root_squash(struct mdt_thread_info *info)
 {
 {
-        struct md_ucred     *uc  = mdt_ucred(info);
-        struct mdt_device   *mdt = info->mti_mdt;
-        struct mdt_identity *identity = NULL;
-
-        ENTRY;
-
-        uc->mu_valid = UCRED_INVALID;
-
-        if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
-                /* get identity info of this user */
-                identity = mdt_identity_get(mdt->mdt_identity_cache,
-                                            body->fsuid);
-                if (!identity) {
-                        CERROR("Deny access without identity: uid %d\n",
-                               body->fsuid);
-                        RETURN(-EACCES);
-                }
-        }
-
-        uc->mu_valid = UCRED_OLD;
-        uc->mu_squash = SQUASH_NONE;
-        uc->mu_o_uid = uc->mu_uid = body->uid;
-        uc->mu_o_gid = uc->mu_gid = body->gid;
-        uc->mu_o_fsuid = uc->mu_fsuid = body->fsuid;
-        uc->mu_o_fsgid = uc->mu_fsgid = body->fsgid;
-        uc->mu_suppgids[0] = body->suppgid;
-        uc->mu_suppgids[1] = -1;
-        if (uc->mu_fsuid)
-                uc->mu_cap = body->capability & ~CAP_FS_MASK;
-        else
-                uc->mu_cap = body->capability;
-        uc->mu_ginfo = NULL;
-        uc->mu_identity = identity;
-
-        RETURN(0);
-}
-
-static int old_init_ucred_reint(struct mdt_thread_info *info)
-{
-        struct md_ucred     *uc  = mdt_ucred(info);
-        struct mdt_device   *mdt = info->mti_mdt;
-        struct mdt_identity *identity = NULL;
-
-        ENTRY;
-
-        uc->mu_valid = UCRED_INVALID;
-
-        if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
-                /* get identity info of this user */
-                identity = mdt_identity_get(mdt->mdt_identity_cache,
-                                            uc->mu_fsuid);
-                if (!identity) {
-                        CERROR("Deny access without identity: uid %d\n",
-                               uc->mu_fsuid);
-                        RETURN(-EACCES);
-                }
-        }
-
-        uc->mu_valid = UCRED_OLD;
-        uc->mu_squash = SQUASH_NONE;
-        uc->mu_o_uid = uc->mu_o_fsuid = uc->mu_uid = uc->mu_fsuid;
-        uc->mu_o_gid = uc->mu_o_fsgid = uc->mu_gid = uc->mu_fsgid;
-        if (uc->mu_fsuid)
-                uc->mu_cap &= ~CAP_FS_MASK;
-        uc->mu_ginfo = NULL;
-        uc->mu_identity = identity;
-
-        RETURN(0);
-}
-
-static int nid_nosquash(struct mdt_device *mdt, lnet_nid_t nid)
-{
-        struct rootsquash_info *rsi = mdt->mdt_rootsquash_info;
-        int i;
-
-        for (i = 0; i < rsi->rsi_n_nosquash_nids; i++)
-                if ((rsi->rsi_nosquash_nids[i] == nid) ||
-                    (rsi->rsi_nosquash_nids[i] == LNET_NID_ANY))
-                        return 1;
-
         return 0;
 }
 
         return 0;
 }
 
-static int mdt_squash_root(struct mdt_device *mdt, struct md_ucred *ucred,
-                           struct ptlrpc_user_desc *pud, lnet_nid_t peernid)
-{
-        struct rootsquash_info *rsi = mdt->mdt_rootsquash_info;
-
-        if (!rsi || (!rsi->rsi_uid && !rsi->rsi_gid) ||
-            nid_nosquash(mdt, peernid))
-                return 0;
-
-        CDEBUG(D_SEC, "squash req from "LPX64":"
-               "(%u:%u-%u:%u/%x)=>(%u:%u-%u:%u/%x)\n", peernid,
-               pud->pud_uid, pud->pud_gid,
-               pud->pud_fsuid, pud->pud_fsgid, pud->pud_cap,
-               pud->pud_uid ? pud->pud_uid : rsi->rsi_uid,
-               pud->pud_uid ? pud->pud_gid : rsi->rsi_gid,
-               pud->pud_fsuid ? pud->pud_fsuid : rsi->rsi_uid,
-               pud->pud_fsuid ? pud->pud_fsgid : rsi->rsi_gid,
-               pud->pud_cap & ~CAP_FS_MASK);
-
-        if (rsi->rsi_uid) {
-                if (!pud->pud_uid) {
-                        ucred->mu_uid = rsi->rsi_uid;
-                        ucred->mu_squash |= SQUASH_UID;
-                } else {
-                        ucred->mu_uid = pud->pud_uid;
-                }
-
-                if (!pud->pud_fsuid) {
-                        ucred->mu_fsuid = rsi->rsi_uid;
-                        ucred->mu_squash |= SQUASH_UID;
-                } else {
-                        ucred->mu_fsuid = pud->pud_fsuid;
-                }
-        } else {
-                ucred->mu_uid   = pud->pud_uid;
-                ucred->mu_fsuid = pud->pud_fsuid;
-        }
-
-        if (rsi->rsi_gid) {
-                int i;
-
-                if (!pud->pud_gid) {
-                        ucred->mu_gid = rsi->rsi_gid;
-                        ucred->mu_squash |= SQUASH_GID;
-                } else {
-                        ucred->mu_gid = pud->pud_gid;
-                }
-
-                if (!pud->pud_fsgid) {
-                        ucred->mu_fsgid = rsi->rsi_gid;
-                        ucred->mu_squash |= SQUASH_GID;
-                } else {
-                        ucred->mu_fsgid = pud->pud_fsgid;
-                }
-
-                for (i = 0; i < 2; i++) {
-                        if (!ucred->mu_suppgids[i]) {
-                                ucred->mu_suppgids[i] = rsi->rsi_gid;
-                                ucred->mu_squash |= SQUASH_GID;
-                        }
-                }
-
-                for (i = 0; i < pud->pud_ngroups; i++) {
-                        if (!pud->pud_groups[i]) {
-                                pud->pud_groups[i] = rsi->rsi_gid;
-                                ucred->mu_squash |= SQUASH_GID;
-                        }
-                }
-        } else {
-                ucred->mu_gid   = pud->pud_gid;
-                ucred->mu_fsgid = pud->pud_fsgid;
-        }
-
-        return 1;
-}
-
 static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
                           void *buf)
 {
 static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
                           void *buf)
 {
@@ -286,9 +83,8 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
         struct mdt_device       *mdt = info->mti_mdt;
         struct ptlrpc_user_desc *pud = req->rq_user_desc;
         struct md_ucred         *ucred = mdt_ucred(info);
         struct mdt_device       *mdt = info->mti_mdt;
         struct ptlrpc_user_desc *pud = req->rq_user_desc;
         struct md_ucred         *ucred = mdt_ucred(info);
-        struct mdt_identity     *identity = NULL;
         lnet_nid_t              peernid = req->rq_peer.nid;
         lnet_nid_t              peernid = req->rq_peer.nid;
-        __u32                   setxid_perm = 0;
+        __u32                    perm = 0;
         int                     setuid;
         int                     setgid;
         int                     rc = 0;
         int                     setuid;
         int                     setgid;
         int                     rc = 0;
@@ -324,10 +120,12 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
                         RETURN(-EACCES);
 
                 if (req->rq_auth_mapped_uid != pud->pud_uid) {
                         RETURN(-EACCES);
 
                 if (req->rq_auth_mapped_uid != pud->pud_uid) {
-                        CERROR("remote client "LPU64": auth uid %u "
+                        CERROR("remote client "LPU64": auth/mapped uid %u/%u "
                                "while client claim %u:%u/%u:%u\n",
                                "while client claim %u:%u/%u:%u\n",
-                               peernid, req->rq_auth_uid, pud->pud_uid,
-                               pud->pud_gid, pud->pud_fsuid, pud->pud_fsgid);
+                               peernid, req->rq_auth_uid,
+                               req->rq_auth_mapped_uid,
+                               pud->pud_uid, pud->pud_gid,
+                               pud->pud_fsuid, pud->pud_fsgid);
                         RETURN(-EACCES);
                 }
         } else {
                         RETURN(-EACCES);
                 }
         } else {
@@ -346,87 +144,100 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
                                "enabled!\n");
                         RETURN(-EACCES);
                 } else {
                                "enabled!\n");
                         RETURN(-EACCES);
                 } else {
-                        setxid_perm |= LUSTRE_SETGRP_PERM;
-                        goto check_squash;
+                        ucred->mu_identity = NULL;
+                        perm = CFS_SETUID_PERM | CFS_SETGID_PERM |
+                               CFS_SETGRP_PERM;
                 }
                 }
-        }
-
-        identity = mdt_identity_get(mdt->mdt_identity_cache, pud->pud_uid);
-        if (!identity) {
-                CERROR("Deny access without identity: uid %d\n", pud->pud_uid);
+        } else {
+                ucred->mu_identity = mdt_identity_get(mdt->mdt_identity_cache,
+                                                      pud->pud_uid);
+                if (!ucred->mu_identity) {
+                        CERROR("Deny access without identity: uid %d\n",
+                               pud->pud_uid);
                 RETURN(-EACCES);
                 RETURN(-EACCES);
-        }
-
-        setxid_perm = mdt_identity_get_setxid_perm(identity,
+                } else {
+                        perm = mdt_identity_get_perm(ucred->mu_identity,
                                                    med->med_rmtclient,
                                                    peernid);
                                                    med->med_rmtclient,
                                                    peernid);
+                }
+        }
 
         /* find out the setuid/setgid attempt */
         setuid = (pud->pud_uid != pud->pud_fsuid);
 
         /* find out the setuid/setgid attempt */
         setuid = (pud->pud_uid != pud->pud_fsuid);
-        setgid = (pud->pud_gid != pud->pud_fsgid ||
-                  pud->pud_gid != identity->mi_gid);
+        setgid = ((pud->pud_gid != pud->pud_fsgid) ||
+                  (ucred->mu_identity &&
+                  (pud->pud_gid != ucred->mu_identity->mi_gid)));
 
         /* check permission of setuid */
 
         /* check permission of setuid */
-        if (setuid && !(setxid_perm & LUSTRE_SETUID_PERM)) {
+        if (setuid && !(perm & CFS_SETUID_PERM)) {
                 CWARN("mdt blocked setuid attempt (%u -> %u) from "
                       LPX64"\n", pud->pud_uid, pud->pud_fsuid, peernid);
                 GOTO(out, rc = -EACCES);
         }
 
         /* check permission of setgid */
                 CWARN("mdt blocked setuid attempt (%u -> %u) from "
                       LPX64"\n", pud->pud_uid, pud->pud_fsuid, peernid);
                 GOTO(out, rc = -EACCES);
         }
 
         /* check permission of setgid */
-        if (setgid && !(setxid_perm & LUSTRE_SETGID_PERM)) {
+        if (setgid && !(perm & CFS_SETGID_PERM)) {
                 CWARN("mdt blocked setgid attempt (%u:%u/%u:%u -> %u) "
                       "from "LPX64"\n", pud->pud_uid, pud->pud_gid,
                 CWARN("mdt blocked setgid attempt (%u:%u/%u:%u -> %u) "
                       "from "LPX64"\n", pud->pud_uid, pud->pud_gid,
-                      pud->pud_fsuid, pud->pud_fsgid, identity->mi_gid,
-                      peernid);
+                      pud->pud_fsuid, pud->pud_fsgid,
+                      ucred->mu_identity->mi_gid, peernid);
                 GOTO(out, rc = -EACCES);
         }
 
                 GOTO(out, rc = -EACCES);
         }
 
-check_squash:
-        /* FIXME: The exact behavior of root_squash is not defined. */
-        ucred->mu_squash = SQUASH_NONE;
-        if (mdt_squash_root(mdt, ucred, pud, peernid) == 0) {
-                ucred->mu_uid   = pud->pud_uid;
-                ucred->mu_gid   = pud->pud_gid;
-                ucred->mu_fsuid = pud->pud_fsuid;
-                ucred->mu_fsgid = pud->pud_fsgid;
-        }
-
-        /* remove fs privilege for non-root user */
-        if (ucred->mu_fsuid)
-                ucred->mu_cap = pud->pud_cap & ~CAP_FS_MASK;
-        else
-                ucred->mu_cap = pud->pud_cap;
-
         /*
          * NB: remote client not allowed to setgroups anyway.
          */
         /*
          * NB: remote client not allowed to setgroups anyway.
          */
-        if (!med->med_rmtclient && pud->pud_ngroups &&
-            (setxid_perm & LUSTRE_SETGRP_PERM)) {
-                struct group_info *ginfo;
-
+        if (!med->med_rmtclient && perm & CFS_SETGRP_PERM) {
+                if (pud->pud_ngroups) {
                 /* setgroups for local client */
                 /* setgroups for local client */
-                ginfo = groups_alloc(pud->pud_ngroups);
-                if (!ginfo) {
+                        ucred->mu_ginfo = groups_alloc(pud->pud_ngroups);
+                        if (!ucred->mu_ginfo) {
                         CERROR("failed to alloc %d groups\n",
                                pud->pud_ngroups);
                         GOTO(out, rc = -ENOMEM);
                 }
                         CERROR("failed to alloc %d groups\n",
                                pud->pud_ngroups);
                         GOTO(out, rc = -ENOMEM);
                 }
-                groups_from_list(ginfo, pud->pud_groups);
-                groups_sort(ginfo);
-                ucred->mu_ginfo = ginfo;
+
+                        lustre_groups_from_list(ucred->mu_ginfo,
+                                                pud->pud_groups);
+                        lustre_groups_sort(ucred->mu_ginfo);
         } else {
                 ucred->mu_ginfo = NULL;
         }
         } else {
                 ucred->mu_ginfo = NULL;
         }
+        } else {
+                ucred->mu_suppgids[0] = -1;
+                ucred->mu_suppgids[1] = -1;
+                ucred->mu_ginfo = NULL;
+        }
 
 
-        ucred->mu_identity = identity;
+        ucred->mu_uid   = pud->pud_uid;
+        ucred->mu_gid   = pud->pud_gid;
+        ucred->mu_fsuid = pud->pud_fsuid;
+        ucred->mu_fsgid = pud->pud_fsgid;
+
+        /* XXX: need to process root_squash here. */
+        mdt_root_squash(info);
+
+        /* remove fs privilege for non-root user */
+        if (ucred->mu_fsuid)
+                ucred->mu_cap = pud->pud_cap & ~CAP_FS_MASK;
+        else
+                ucred->mu_cap = pud->pud_cap;
         ucred->mu_valid = UCRED_NEW;
 
         EXIT;
 
 out:
         ucred->mu_valid = UCRED_NEW;
 
         EXIT;
 
 out:
-        if (rc && identity)
-                mdt_identity_put(mdt->mdt_identity_cache, identity);
+        if (rc) {
+                if (ucred->mu_ginfo) {
+                        groups_free(ucred->mu_ginfo);
+                        ucred->mu_ginfo = NULL;
+                }
+                if (ucred->mu_identity) {
+                        mdt_identity_put(mdt->mdt_identity_cache,
+                                         ucred->mu_identity);
+                        ucred->mu_identity = NULL;
+                }
+        }
 
         return rc;
 }
 
         return rc;
 }
@@ -438,20 +249,23 @@ int mdt_check_ucred(struct mdt_thread_info *info)
         struct mdt_device       *mdt = info->mti_mdt;
         struct ptlrpc_user_desc *pud = req->rq_user_desc;
         struct md_ucred         *ucred = mdt_ucred(info);
         struct mdt_device       *mdt = info->mti_mdt;
         struct ptlrpc_user_desc *pud = req->rq_user_desc;
         struct md_ucred         *ucred = mdt_ucred(info);
-        struct mdt_identity     *identity;
+        struct md_identity      *identity = NULL;
         lnet_nid_t              peernid = req->rq_peer.nid;
         lnet_nid_t              peernid = req->rq_peer.nid;
+        __u32                    perm = 0;
+        int                      setuid;
+        int                      setgid;
+        int                      rc = 0;
 
         ENTRY;
 
         if ((ucred->mu_valid == UCRED_OLD) || (ucred->mu_valid == UCRED_NEW))
                 RETURN(0);
 
 
         ENTRY;
 
         if ((ucred->mu_valid == UCRED_OLD) || (ucred->mu_valid == UCRED_NEW))
                 RETURN(0);
 
-        if (!req->rq_user_desc)
+        if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
                 RETURN(0);
 
         /* sanity check: if we use strong authentication, we expect the
          * uid which client claimed is true */
                 RETURN(0);
 
         /* sanity check: if we use strong authentication, we expect the
          * uid which client claimed is true */
-        if (req->rq_auth_gss) {
                 if (med->med_rmtclient) {
                         if (req->rq_auth_mapped_uid == INVALID_UID) {
                                 CWARN("remote user not mapped, deny access!\n");
                 if (med->med_rmtclient) {
                         if (req->rq_auth_mapped_uid == INVALID_UID) {
                                 CWARN("remote user not mapped, deny access!\n");
@@ -462,11 +276,12 @@ int mdt_check_ucred(struct mdt_thread_info *info)
                                 RETURN(-EACCES);
 
                         if (req->rq_auth_mapped_uid != pud->pud_uid) {
                                 RETURN(-EACCES);
 
                         if (req->rq_auth_mapped_uid != pud->pud_uid) {
-                                CERROR("remote client "LPU64": auth uid %u "
+                        CERROR("remote client "LPU64": auth/mapped uid %u/%u "
                                        "while client claim %u:%u/%u:%u\n",
                                        "while client claim %u:%u/%u:%u\n",
-                                       peernid, req->rq_auth_uid, pud->pud_uid,
-                                       pud->pud_gid, pud->pud_fsuid,
-                                       pud->pud_fsgid);
+                               peernid, req->rq_auth_uid,
+                               req->rq_auth_mapped_uid,
+                               pud->pud_uid, pud->pud_gid,
+                               pud->pud_fsuid, pud->pud_fsgid);
                                 RETURN(-EACCES);
                         }
                 } else {
                                 RETURN(-EACCES);
                         }
                 } else {
@@ -479,25 +294,122 @@ int mdt_check_ucred(struct mdt_thread_info *info)
                                 RETURN(-EACCES);
                         }
                 }
                                 RETURN(-EACCES);
                         }
                 }
-        }
 
         if (is_identity_get_disabled(mdt->mdt_identity_cache)) {
                 if (med->med_rmtclient) {
 
         if (is_identity_get_disabled(mdt->mdt_identity_cache)) {
                 if (med->med_rmtclient) {
-                        CERROR("remote client must run with "
-                               "identity_get enabled!\n");
+                        CERROR("remote client must run with identity_get "
+                               "enabled!\n");
                         RETURN(-EACCES);
                 }
                         RETURN(-EACCES);
                 }
-        } else {
+                RETURN(0);
+        }
+
+        identity = mdt_identity_get(mdt->mdt_identity_cache, pud->pud_uid);
+        if (!identity) {
+                CERROR("Deny access without identity: uid %d\n", pud->pud_uid);
+                RETURN(-EACCES);
+        }
+
+        perm = mdt_identity_get_perm(identity, med->med_rmtclient, peernid);
+        /* find out the setuid/setgid attempt */
+        setuid = (pud->pud_uid != pud->pud_fsuid);
+        setgid = (pud->pud_gid != pud->pud_fsgid ||
+                  pud->pud_gid != identity->mi_gid);
+
+        /* check permission of setuid */
+        if (setuid && !(perm & CFS_SETUID_PERM)) {
+                CWARN("mdt blocked setuid attempt (%u -> %u) from "
+                      LPX64"\n", pud->pud_uid, pud->pud_fsuid, peernid);
+                GOTO(out, rc = -EACCES);
+        }
+
+        /* check permission of setgid */
+        if (setgid && !(perm & CFS_SETGID_PERM)) {
+                CWARN("mdt blocked setgid attempt (%u:%u/%u:%u -> %u) "
+                      "from "LPX64"\n", pud->pud_uid, pud->pud_gid,
+                      pud->pud_fsuid, pud->pud_fsgid, identity->mi_gid,
+                      peernid);
+                GOTO(out, rc = -EACCES);
+        }
+
+        EXIT;
+
+out:
+        mdt_identity_put(mdt->mdt_identity_cache, identity);
+        return rc;
+}
+
+static int old_init_ucred(struct mdt_thread_info *info,
+                          struct mdt_body *body)
+{
+        struct md_ucred *uc = mdt_ucred(info);
+        struct mdt_device  *mdt = info->mti_mdt;
+        struct md_identity *identity = NULL;
+
+        ENTRY;
+
+        uc->mu_valid = UCRED_INVALID;
+        uc->mu_o_uid = uc->mu_uid = body->uid;
+        uc->mu_o_gid = uc->mu_gid = body->gid;
+        uc->mu_o_fsuid = uc->mu_fsuid = body->fsuid;
+        uc->mu_o_fsgid = uc->mu_fsgid = body->fsgid;
+        uc->mu_suppgids[0] = body->suppgid;
+        uc->mu_suppgids[1] = -1;
+        uc->mu_ginfo = NULL;
+        if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
                 identity = mdt_identity_get(mdt->mdt_identity_cache,
                 identity = mdt_identity_get(mdt->mdt_identity_cache,
-                                            pud->pud_uid);
+                                            uc->mu_fsuid);
                 if (!identity) {
                         CERROR("Deny access without identity: uid %d\n",
                 if (!identity) {
                         CERROR("Deny access without identity: uid %d\n",
-                               pud->pud_uid);
+                               uc->mu_fsuid);
                         RETURN(-EACCES);
                 }
                         RETURN(-EACCES);
                 }
+        }
+        uc->mu_identity = identity;
+
+        /* XXX: need to process root_squash here. */
+        mdt_root_squash(info);
+
+        /* remove fs privilege for non-root user */
+        if (uc->mu_fsuid)
+                uc->mu_cap = body->capability & ~CAP_FS_MASK;
+        else
+                uc->mu_cap = body->capability;
+        uc->mu_valid = UCRED_OLD;
+
+        RETURN(0);
+}
+
+static int old_init_ucred_reint(struct mdt_thread_info *info)
+{
+        struct md_ucred *uc = mdt_ucred(info);
+        struct mdt_device  *mdt = info->mti_mdt;
+        struct md_identity *identity = NULL;
+
+        ENTRY;
 
 
-                mdt_identity_put(mdt->mdt_identity_cache, identity);
+        uc->mu_valid = UCRED_INVALID;
+        uc->mu_o_uid = uc->mu_o_fsuid = uc->mu_uid = uc->mu_fsuid;
+        uc->mu_o_gid = uc->mu_o_fsgid = uc->mu_gid = uc->mu_fsgid;
+        uc->mu_ginfo = NULL;
+        if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
+                identity = mdt_identity_get(mdt->mdt_identity_cache,
+                                            uc->mu_fsuid);
+                if (!identity) {
+                        CERROR("Deny access without identity: uid %d\n",
+                               uc->mu_fsuid);
+                        RETURN(-EACCES);
+        }
         }
         }
+        uc->mu_identity = identity;
+
+        /* XXX: need to process root_squash here. */
+        mdt_root_squash(info);
+
+        /* remove fs privilege for non-root user */
+        if (uc->mu_fsuid)
+                uc->mu_cap &= ~CAP_FS_MASK;
+        uc->mu_valid = UCRED_OLD;
 
         RETURN(0);
 }
 
         RETURN(0);
 }
index e7565dd..3b2db54 100644 (file)
@@ -227,9 +227,9 @@ static int lprocfs_wr_identity_info(struct file *file, const char *buffer,
                 GOTO(out, rc = -EINVAL);
         }
 
                 GOTO(out, rc = -EINVAL);
         }
 
-        if (sparam.idd_nperms > N_SETXID_PERMS_MAX) {
+        if (sparam.idd_nperms > N_PERMS_MAX) {
                 CERROR("%s: perm count %d more than maximum %d\n",
                 CERROR("%s: perm count %d more than maximum %d\n",
-                       obd->obd_name, sparam.idd_nperms, N_SETXID_PERMS_MAX);
+                       obd->obd_name, sparam.idd_nperms, N_PERMS_MAX);
                 GOTO(out, rc = -EINVAL);
         }
 
                 GOTO(out, rc = -EINVAL);
         }
 
@@ -268,301 +268,6 @@ out:
         return rc ?: count;
 }
 
         return rc ?: count;
 }
 
-static int lprocfs_rd_rmtacl_expire(char *page, char **start, off_t off,
-                                    int count, int *eof, void *data)
-{
-        struct obd_device *obd = data;
-        struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
-
-        *eof = 1;
-        return snprintf(page, count, "%lu\n",
-                        mdt->mdt_rmtacl_cache->uc_entry_expire / HZ);
-}
-
-static int lprocfs_wr_rmtacl_expire(struct file *file, const char *buffer,
-                                    unsigned long count, void *data)
-{
-        struct obd_device *obd = data;
-        struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
-        int rc, val;
-
-        rc = lprocfs_write_helper(buffer, count, &val);
-        if (rc)
-                return rc;
-
-        mdt->mdt_rmtacl_cache->uc_entry_expire = val * HZ;
-        return count;
-}
-
-static int lprocfs_rd_rmtacl_acquire_expire(char *page, char **start,
-                                            off_t off, int count, int *eof,
-                                            void *data)
-{
-        struct obd_device *obd = data;
-        struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
-
-        *eof = 1;
-        return snprintf(page, count, "%lu\n",
-                        mdt->mdt_rmtacl_cache->uc_acquire_expire / HZ);
-}
-
-static int lprocfs_wr_rmtacl_acquire_expire(struct file *file,
-                                            const char *buffer,
-                                            unsigned long count,
-                                            void *data)
-{
-        struct obd_device *obd = data;
-        struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
-        int rc, val;
-
-        rc = lprocfs_write_helper(buffer, count, &val);
-        if (rc)
-                return rc;
-
-        mdt->mdt_rmtacl_cache->uc_acquire_expire = val * HZ;
-        return count;
-}
-
-static int lprocfs_rd_rmtacl_upcall(char *page, char **start, off_t off,
-                                      int count, int *eof, void *data)
-{
-        struct obd_device *obd = data;
-        struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
-
-        *eof = 1;
-        return snprintf(page, count, "%s\n",
-                        mdt->mdt_rmtacl_cache->uc_upcall);
-}
-
-static int lprocfs_wr_rmtacl_upcall(struct file *file, const char *buffer,
-                                      unsigned long count, void *data)
-{
-        struct obd_device *obd = data;
-        struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
-        struct upcall_cache *hash = mdt->mdt_rmtacl_cache;
-        char kernbuf[UC_CACHE_UPCALL_MAXPATH] = { '\0' };
-
-        if (count >= UC_CACHE_UPCALL_MAXPATH) {
-                CERROR("%s: remote ACL upcall too long\n", obd->obd_name);
-                return -EINVAL;
-        }
-
-        if (copy_from_user(kernbuf, buffer,
-                           min(count, UC_CACHE_UPCALL_MAXPATH - 1)))
-                return -EFAULT;
-
-        /* Remove any extraneous bits from the upcall (e.g. linefeeds) */
-        sscanf(kernbuf, "%s", hash->uc_upcall);
-
-        if (strcmp(hash->uc_name, obd->obd_name) != 0)
-                CWARN("%s: write to upcall name %s\n",
-                      obd->obd_name, hash->uc_upcall);
-        CWARN("%s: remote ACL upcall set to %s\n", obd->obd_name, hash->uc_upcall);
-
-        return count;
-}
-
-static int lprocfs_wr_rmtacl_info(struct file *file, const char *buffer,
-                                  unsigned long count, void *data)
-{
-        struct obd_device *obd = data;
-        struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
-        struct rmtacl_downcall_data sparam, *param = &sparam;
-        int size = 0, rc = 0;
-
-        if (count < sizeof(*param)) {
-                CERROR("%s: invalid data size %lu\n", obd->obd_name, count);
-                return count;
-        }
-
-        if (copy_from_user(&sparam, buffer, sizeof(sparam))) {
-                CERROR("%s: bad remote acl data\n", obd->obd_name);
-                GOTO(out, rc = -EFAULT);
-        }
-
-        if (sparam.add_magic != RMTACL_DOWNCALL_MAGIC) {
-                CERROR("%s: MDT remote acl downcall bad params\n", obd->obd_name);
-                GOTO(out, rc = -EINVAL);
-        }
-
-        if (sparam.add_buflen) {
-                size = offsetof(struct rmtacl_downcall_data,
-                                add_buf[sparam.add_buflen]);
-                OBD_ALLOC(param, size);
-                if (!param) {
-                        CERROR("%s: fail to alloc %d bytes for ino "LPU64"\n",
-                               obd->obd_name, size, sparam.add_key);
-                        param = &sparam;
-                        param->add_buflen = 0;
-                } else if (copy_from_user(param, buffer, size)) {
-                        CERROR("%s: ino "LPU64" bad remote acl data\n",
-                               obd->obd_name, sparam.add_key);
-                        OBD_FREE(param, size);
-                        param = &sparam;
-                        param->add_buflen = 0;
-                }
-        }
-
-        rc = upcall_cache_downcall(mdt->mdt_rmtacl_cache, 0, param->add_key,
-                                   param);
-
-out:
-        if (param && (param != &sparam))
-                OBD_FREE(param, size);
-
-        return rc ?: count;
-}
-
-static int lprocfs_rd_rootsquash_uid(char *page, char **start, off_t off,
-                                 int count, int *eof, void *data)
-{
-        struct obd_device *obd = data;
-        struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
-        struct rootsquash_info *rsi = mdt->mdt_rootsquash_info;
-
-        *eof = 1;
-        return snprintf(page, count, "%u\n",
-                        rsi ? rsi->rsi_uid : 0);
-}
-
-static int lprocfs_wr_rootsquash_uid(struct file *file, const char *buffer,
-                                     unsigned long count, void *data)
-{
-        struct obd_device *obd = data;
-        struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
-        int val, rc;
-
-        rc = lprocfs_write_helper(buffer, count, &val);
-        if (rc)
-                return rc;
-
-        if (!mdt->mdt_rootsquash_info)
-                OBD_ALLOC_PTR(mdt->mdt_rootsquash_info);
-        if (!mdt->mdt_rootsquash_info)
-                return -ENOMEM;
-
-        mdt->mdt_rootsquash_info->rsi_uid = val;
-        return count;
-}
-
-static int lprocfs_rd_rootsquash_gid(char *page, char **start, off_t off,
-                                 int count, int *eof, void *data)
-{
-        struct obd_device *obd = data;
-        struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
-        struct rootsquash_info *rsi = mdt->mdt_rootsquash_info;
-
-        *eof = 1;
-        return snprintf(page, count, "%u\n",
-                        rsi ? rsi->rsi_gid : 0);
-}
-
-static int lprocfs_wr_rootsquash_gid(struct file *file, const char *buffer,
-                                     unsigned long count, void *data)
-{
-        struct obd_device *obd = data;
-        struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
-        int val, rc;
-
-        rc = lprocfs_write_helper(buffer, count, &val);
-        if (rc)
-                return rc;
-
-        if (!mdt->mdt_rootsquash_info)
-                OBD_ALLOC_PTR(mdt->mdt_rootsquash_info);
-        if (!mdt->mdt_rootsquash_info)
-                return -ENOMEM;
-
-        mdt->mdt_rootsquash_info->rsi_gid = val;
-        return count;
-}
-
-static int lprocfs_rd_nosquash_nids(char *page, char **start, off_t off,
-                                       int count, int *eof, void *data)
-{
-        struct obd_device *obd = data;
-        struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
-        struct rootsquash_info *rsi = mdt->mdt_rootsquash_info;
-        int i, ret;
-
-        ret = snprintf(page, count, "rootsquash skip list:\n");
-        for (i = 0; rsi && (i < rsi->rsi_n_nosquash_nids); i++) {
-                ret += snprintf(page + ret, count - ret, "%s\n",
-                                libcfs_nid2str(rsi->rsi_nosquash_nids[i]));
-        }
-
-        *eof = 1;
-        return ret;
-}
-
-static inline void remove_newline(char *str)
-{
-        int len = strlen(str);
-
-        if (str[len - 1] == '\n')
-                str[len - 1] = '\0';
-}
-
-/* XXX: This macro is copied from lnet/libcfs/nidstring.c */
-#define LNET_NIDSTR_SIZE   32      /* size of each one (see below for usage) */
-
-static void do_process_nosquash_nids(struct mdt_device *m, char *buf)
-{
-        struct rootsquash_info *rsi = m->mdt_rootsquash_info;
-        char str[LNET_NIDSTR_SIZE], *end;
-        lnet_nid_t nid;
-
-        LASSERT(rsi);
-        rsi->rsi_n_nosquash_nids = 0;
-        while (rsi->rsi_n_nosquash_nids < N_NOSQUASH_NIDS) {
-                end = strchr(buf, ',');
-                memset(str, 0, sizeof(str));
-                if (end)
-                        strncpy(str, buf, min_t(int, sizeof(str), end - buf));
-                else
-                        strncpy(str, buf, min_t(int, sizeof(str), strlen(buf)));
-
-                if (!strcmp(str, "*")) {
-                        nid = LNET_NID_ANY;
-                } else {
-                        nid = libcfs_str2nid(str);
-                        if (nid == LNET_NID_ANY)
-                                goto ignore;
-                }
-                rsi->rsi_nosquash_nids[rsi->rsi_n_nosquash_nids++] = nid;
-ignore:
-                if (!end || (*(end + 1) == 0))
-                        return;
-                buf = end + 1;
-        }
-}
-
-static int lprocfs_wr_nosquash_nids(struct file *file, const char *buffer,
-                                       unsigned long count, void *data)
-{
-        struct obd_device *obd = data;
-        struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
-        char skips[LNET_NIDSTR_SIZE * N_NOSQUASH_NIDS] = "";
-        unsigned long size = sizeof(skips);
-
-        if (count > size) {
-                CERROR("parameter exceeds max limit %lu\n", size);
-                return -EINVAL;
-        }
-
-        if (copy_from_user(skips, buffer, min(size, count)))
-                return -EFAULT;
-
-        if (!mdt->mdt_rootsquash_info)
-                OBD_ALLOC_PTR(mdt->mdt_rootsquash_info);
-        if (!mdt->mdt_rootsquash_info)
-                return -ENOMEM;
-
-        remove_newline(skips);
-        do_process_nosquash_nids(mdt, skips);
-        return count;
-}
-
 /* for debug only */
 static int lprocfs_rd_capa(char *page, char **start, off_t off,
                            int count, int *eof, void *data)
 /* for debug only */
 static int lprocfs_rd_capa(char *page, char **start, off_t off,
                            int count, int *eof, void *data)
@@ -728,19 +433,6 @@ static struct lprocfs_vars lprocfs_mdt_obd_vars[] = {
                                         lprocfs_wr_identity_upcall,         0 },
         { "identity_flush",             0, lprocfs_wr_identity_flush,       0 },
         { "identity_info",              0, lprocfs_wr_identity_info,        0 },
                                         lprocfs_wr_identity_upcall,         0 },
         { "identity_flush",             0, lprocfs_wr_identity_flush,       0 },
         { "identity_info",              0, lprocfs_wr_identity_info,        0 },
-        { "rmtacl_expire",              lprocfs_rd_rmtacl_expire,
-                                        lprocfs_wr_rmtacl_expire,           0 },
-        { "rmtacl_acquire_expire",      lprocfs_rd_rmtacl_acquire_expire,
-                                        lprocfs_wr_rmtacl_acquire_expire,   0 },
-        { "rmtacl_upcall",              lprocfs_rd_rmtacl_upcall,
-                                        lprocfs_wr_rmtacl_upcall,           0 },
-        { "rmtacl_info",                0, lprocfs_wr_rmtacl_info,          0 },
-        { "rootsquash_uid",             lprocfs_rd_rootsquash_uid,
-                                        lprocfs_wr_rootsquash_uid,          0 },
-        { "rootsquash_gid",             lprocfs_rd_rootsquash_gid,
-                                        lprocfs_wr_rootsquash_gid,          0 },
-        { "nosquash_nids",              lprocfs_rd_nosquash_nids,
-                                        lprocfs_wr_nosquash_nids,           0 },
         { "capa",                       lprocfs_rd_capa,
                                         lprocfs_wr_capa,                    0 },
         { "capa_timeout",               lprocfs_rd_capa_timeout,
         { "capa",                       lprocfs_rd_capa,
                                         lprocfs_wr_capa,                    0 },
         { "capa_timeout",               lprocfs_rd_capa_timeout,
diff --git a/lustre/mdt/mdt_rmtacl.c b/lustre/mdt/mdt_rmtacl.c
deleted file mode 100644 (file)
index 13fa70a..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2004-2006 Cluster File Systems, Inc.
- *   Author: Lai Siyao <lsy@clusterfs.com>
- *   Author: Fan Yong <fanyong@clusterfs.com>
- *
- *   This file is part of Lustre, http://www.lustre.org.
- *
- *   Lustre is free software; you can redistribute it and/or
- *   modify it under the terms of version 2 of the GNU General Public
- *   License as published by the Free Software Foundation.
- *
- *   Lustre is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with Lustre; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef EXPORT_SYMTAB
-#define EXPORT_SYMTAB
-#endif
-#define DEBUG_SUBSYSTEM S_MDS
-
-#ifndef AUTOCONF_INCLUDED
-#include <linux/config.h>
-#endif
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/kmod.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/errno.h>
-#include <linux/version.h>
-#include <linux/unistd.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <asm/uaccess.h>
-#include <linux/slab.h>
-#include <asm/segment.h>
-
-#include <libcfs/kp30.h>
-#include <obd.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre_net.h>
-#include <lustre_import.h>
-#include <lustre_dlm.h>
-#include <lustre_lib.h>
-#include <lustre_ucache.h>
-
-#include "mdt_internal.h"
-
-#define MAX_CMD_LEN     256
-
-static __u64 rmtacl_key = 0;
-static spinlock_t rmtacl_key_lock = SPIN_LOCK_UNLOCKED;
-
-/* 
- * For remote acl operation, do NOT cache!
- * Use different key for each remote acl operation.
- */
-static __u64 mdt_rmtacl_getkey(void)
-{
-        __u64 key;
-
-        spin_lock(&rmtacl_key_lock);
-        key = ++rmtacl_key;
-        spin_unlock(&rmtacl_key_lock);
-
-        return key;
-}
-
-static void mdt_rmtacl_entry_init(struct upcall_cache_entry *entry, void *args)
-{
-        struct rmtacl_upcall_data *data = args;
-        struct mdt_rmtacl *acl = &entry->u.acl;
-        char *cmd;
-
-        acl->ra_uid = data->aud_uid;
-        acl->ra_gid = data->aud_gid;
-        /* we use address of this cache entry as handle */
-        acl->ra_handle = (__u32)entry;
-        OBD_ALLOC(cmd, strlen(data->aud_cmd) + 1);
-        if (!cmd)
-                return; /* upcall will fail later! */
-
-        strcpy(cmd, data->aud_cmd);
-        acl->ra_cmd = cmd;
-}
-
-static void mdt_rmtacl_entry_free(struct upcall_cache *cache,
-                                  struct upcall_cache_entry *entry)
-{
-        struct mdt_rmtacl *acl = &entry->u.acl;
-        int len;
-
-        if (acl->ra_cmd) {
-                len = strlen(acl->ra_cmd) + 1;
-                OBD_FREE(acl->ra_cmd, len);
-        }
-
-        if (acl->ra_buf) {
-                len = strlen(acl->ra_buf) + 1;
-                OBD_FREE(acl->ra_buf, len);
-        }
-}
-
-static int mdt_rmtacl_upcall_compare(struct upcall_cache *cache,
-                                     struct upcall_cache_entry *entry,
-                                     __u64 key, void *args)
-{
-        struct rmtacl_upcall_data *data = args;
-
-        LASSERT(entry && data);
-        LASSERT(entry->u.acl.ra_cmd && data->aud_cmd);
-        return strncmp(entry->u.acl.ra_cmd, data->aud_cmd, MAX_CMD_LEN);
-}
-
-static int mdt_rmtacl_downcall_compare(struct upcall_cache *cache,
-                                       struct upcall_cache_entry *entry,
-                                       __u64 key, void *args)
-{
-        struct rmtacl_downcall_data *data = args;
-
-        return entry->u.acl.ra_handle - data->add_handle;
-}
-
-static int mdt_rmtacl_do_upcall(struct upcall_cache *cache,
-                                struct upcall_cache_entry *entry)
-{
-        struct mdt_rmtacl *acl = &entry->u.acl;
-        char uidstr[8] = "";
-        char gidstr[8] = "";
-        char handle[20] = "";
-        char keystr[20] = "";
-        char *argv[] = {
-                  [0] = cache->uc_upcall,
-                  [1] = uidstr,
-                  [2] = gidstr,
-                  [3] = cache->uc_name,
-                  [4] = keystr,
-                  [5] = handle,
-                  [6] = acl->ra_cmd,
-                  [7] = NULL
-        };
-        char *envp[] = {
-                  [0] = "HOME=/",
-                  [1] = "PATH=/bin:/usr/bin:/sbin:/usr/sbin",
-                  [2] = NULL
-        };
-        int rc;
-        ENTRY;
-
-        if (!acl->ra_cmd)
-                RETURN(-ENOMEM);
-
-        snprintf(uidstr, sizeof(uidstr), "%u", acl->ra_uid);
-        snprintf(gidstr, sizeof(gidstr), "%u", acl->ra_gid);
-        snprintf(keystr, sizeof(keystr), LPU64, entry->ue_key);
-        snprintf(handle, sizeof(handle), "%u", acl->ra_handle);
-
-        LASSERTF(strcmp(cache->uc_upcall, "NONE"), "no upcall set!");
-
-        CDEBUG(D_INFO, "%s: remote acl upcall %s %s %s %s %s %s %s\n",
-               cache->uc_name, argv[0], argv[1], argv[2], argv[3], argv[4],
-               argv[5], argv[6]);
-
-        rc = USERMODEHELPER(argv[0], argv, envp);
-        if (rc < 0) {
-                CERROR("%s: error invoking upcall %s %s %s %s %s %s %s: rc %d; "
-                       "check /proc/fs/lustre/mdt/%s/rmtacl_upcall\n",
-                       cache->uc_name, argv[0], argv[1], argv[2], argv[3],
-                       argv[4], argv[5], argv[6], rc, cache->uc_name);
-        } else {
-                CDEBUG(D_HA, "%s: invoked upcall %s %s %s %s %s %s %s\n",
-                       cache->uc_name, argv[0], argv[1], argv[2], argv[3],
-                       argv[4], argv[5], argv[6]);
-                rc = 0;
-        }
-        RETURN(rc);
-}
-
-static int mdt_rmtacl_parse_downcall(struct upcall_cache *cache,
-                                     struct upcall_cache_entry *entry,
-                                     void *args)
-{
-        struct mdt_rmtacl *acl = &entry->u.acl;
-        struct rmtacl_downcall_data *data;
-        char *buf;
-        int len;
-        ENTRY;
-
-        data = (struct rmtacl_downcall_data *)args;
-        LASSERT(data);
-
-        len = strlen(data->add_buf) + 1;
-        OBD_ALLOC(buf, len);
-        if (!buf)
-                RETURN(-ENOMEM);
-
-        memcpy(buf, data->add_buf, len);
-        acl->ra_buf = buf;
-
-        CDEBUG(D_OTHER, "parse mdt acl@%p: %s %s\n",
-               acl, acl->ra_cmd, acl->ra_buf);
-
-        RETURN(0);
-}
-
-struct upcall_cache_ops mdt_rmtacl_upcall_cache_ops = {
-        .init_entry       = mdt_rmtacl_entry_init,
-        .free_entry       = mdt_rmtacl_entry_free,
-        .upcall_compare   = mdt_rmtacl_upcall_compare,
-        .downcall_compare = mdt_rmtacl_downcall_compare,
-        .do_upcall        = mdt_rmtacl_do_upcall,
-        .parse_downcall   = mdt_rmtacl_parse_downcall,
-};
-
-int mdt_rmtacl_upcall(struct mdt_thread_info *info, char *cmd,
-                      struct lu_buf *buf)
-{
-        struct mdt_device              *mdt = info->mti_mdt;
-        struct md_ucred                *uc  = mdt_ucred(info);
-        struct rmtacl_upcall_data       data;
-        struct upcall_cache_entry      *entry;
-        __u64                           key;
-        int                             rc  = 0;
-        ENTRY;
-
-        data.aud_uid = uc->mu_fsuid;
-        data.aud_gid = uc->mu_fsgid;
-        data.aud_cmd = cmd;
-
-        key = mdt_rmtacl_getkey();
-
-        entry = upcall_cache_get_entry(mdt->mdt_rmtacl_cache, key, &data);
-        if (IS_ERR(entry))
-                GOTO(out, rc = PTR_ERR(entry));
-
-        if (buf->lb_len <= strlen(entry->u.acl.ra_buf))
-                GOTO(out, rc = -EFAULT);
-
-        memcpy(buf->lb_buf, entry->u.acl.ra_buf, strlen(entry->u.acl.ra_buf));
-        /* remote acl operation expire at once! */
-        UC_CACHE_SET_EXPIRED(entry);
-        upcall_cache_put_entry(mdt->mdt_rmtacl_cache, entry);
-
-out:
-        if (rc)
-                sprintf(buf->lb_buf, "server processing error: %d\n", rc);
-        RETURN(0);
-}
index 2d80821..b9682a6 100644 (file)
@@ -68,9 +68,6 @@ static int mdt_getxattr_pack_reply(struct mdt_thread_info * info)
                     !strncmp(xattr_name, user_string, sizeof(user_string) - 1))
                         RETURN(-EOPNOTSUPP);
                 
                     !strncmp(xattr_name, user_string, sizeof(user_string) - 1))
                         RETURN(-EOPNOTSUPP);
                 
-                if (!strcmp(xattr_name, XATTR_NAME_LUSTRE_ACL))
-                        size = RMTACL_SIZE_MAX;
-                else
                         size = mo_xattr_get(info->mti_env,
                                             mdt_object_child(info->mti_object),
                                             &LU_BUF_NULL, xattr_name);
                         size = mo_xattr_get(info->mti_env,
                                             mdt_object_child(info->mti_object),
                                             &LU_BUF_NULL, xattr_name);
@@ -108,32 +105,11 @@ static int mdt_getxattr_pack_reply(struct mdt_thread_info * info)
         RETURN(size);
 }
 
         RETURN(size);
 }
 
-static int do_remote_getfacl(struct mdt_thread_info *info, struct lu_buf *buf)
-{
-        struct ptlrpc_request *req = mdt_info_req(info);
-        char *cmd;
-        int rc;
-        ENTRY;
-
-        if (!buf->lb_buf || (buf->lb_len != RMTACL_SIZE_MAX))
-                RETURN(-EINVAL);
-
-        cmd = req_capsule_client_get(&info->mti_pill, &RMF_EADATA);
-        if (!cmd) {
-                CERROR("missing getfacl command!\n");
-                RETURN(-EFAULT);
-        }
-
-        rc = mdt_rmtacl_upcall(info, cmd, buf);
-        if (rc)
-                CERROR("remote acl upcall failed: %d\n", rc);
-
-        lustre_shrink_reply(req, REPLY_REC_OFF + 1, strlen(buf->lb_buf) + 1, 0);
-        RETURN(rc ?: strlen(buf->lb_buf) + 1);
-}
-
 int mdt_getxattr(struct mdt_thread_info *info)
 {
 int mdt_getxattr(struct mdt_thread_info *info)
 {
+        struct ptlrpc_request  *req = mdt_info_req(info);
+        struct mdt_export_data *med = mdt_req2med(req);
+        struct md_ucred        *uc  = mdt_ucred(info);
         struct  mdt_body       *reqbody;
         struct  mdt_body       *repbody = NULL;
         struct  md_object      *next;
         struct  mdt_body       *reqbody;
         struct  mdt_body       *repbody = NULL;
         struct  md_object      *next;
@@ -154,6 +130,23 @@ int mdt_getxattr(struct mdt_thread_info *info)
         if (rc)
                 RETURN(err_serious(rc));
 
         if (rc)
                 RETURN(err_serious(rc));
 
+        next = mdt_object_child(info->mti_object);
+
+        if (info->mti_body->valid & OBD_MD_FLRMTRGETFACL) {
+                __u32 perm = mdt_identity_get_perm(uc->mu_identity,
+                                                   med->med_rmtclient,
+                                                   req->rq_peer.nid);
+
+                LASSERT(med->med_rmtclient);
+                if (!(perm & CFS_RMTACL_PERM))
+                        GOTO(out, rc = err_serious(-EPERM));
+
+                rc = mo_permission(info->mti_env, NULL, next, NULL,
+                                   MAY_RGETFACL);
+                if (rc)
+                        GOTO(out, rc = err_serious(rc));
+        }
+
         easize = mdt_getxattr_pack_reply(info);
         if (easize < 0)
                 GOTO(out, rc = err_serious(easize));
         easize = mdt_getxattr_pack_reply(info);
         if (easize < 0)
                 GOTO(out, rc = err_serious(easize));
@@ -168,20 +161,36 @@ int mdt_getxattr(struct mdt_thread_info *info)
         buf = &info->mti_buf;
         buf->lb_buf = req_capsule_server_get(&info->mti_pill, &RMF_EADATA);
         buf->lb_len = easize;
         buf = &info->mti_buf;
         buf->lb_buf = req_capsule_server_get(&info->mti_pill, &RMF_EADATA);
         buf->lb_len = easize;
-        next = mdt_object_child(info->mti_object);
 
         if (info->mti_body->valid & OBD_MD_FLXATTR) {
 
         if (info->mti_body->valid & OBD_MD_FLXATTR) {
+                int flags = CFS_IC_NOTHING;
                 char *xattr_name = req_capsule_client_get(&info->mti_pill,
                                                           &RMF_NAME);
                 CDEBUG(D_INODE, "getxattr %s\n", xattr_name);
 
                 char *xattr_name = req_capsule_client_get(&info->mti_pill,
                                                           &RMF_NAME);
                 CDEBUG(D_INODE, "getxattr %s\n", xattr_name);
 
-                if (!strcmp(xattr_name, XATTR_NAME_LUSTRE_ACL))
-                        rc = do_remote_getfacl(info, buf);
-                else
                         rc = mo_xattr_get(info->mti_env, next, buf, xattr_name);
                         rc = mo_xattr_get(info->mti_env, next, buf, xattr_name);
-
-                if (rc < 0)
+                if (rc < 0) {
                         CERROR("getxattr failed: %d\n", rc);
                         CERROR("getxattr failed: %d\n", rc);
+                        GOTO(out, rc);
+                }
+
+                if (info->mti_body->valid &
+                    (OBD_MD_FLRMTLSETFACL | OBD_MD_FLRMTLGETFACL))
+                        flags = CFS_IC_ALL;
+                else if (info->mti_body->valid & OBD_MD_FLRMTRGETFACL)
+                        flags = CFS_IC_MAPPED;
+
+                if (rc > 0 && flags != CFS_IC_NOTHING) {
+                        int rc1;
+
+                        LASSERT(med->med_rmtclient);
+                        rc1 = lustre_posix_acl_xattr_id2client(uc,
+                                        med->med_idmap,
+                                        (posix_acl_xattr_header *)(buf->lb_buf),
+                                        rc, flags);
+                        if (unlikely(rc1 < 0))
+                                rc = rc1;
+                }
         } else if (info->mti_body->valid & OBD_MD_FLXATTRLS) {
                 CDEBUG(D_INODE, "listxattr\n");
 
         } else if (info->mti_body->valid & OBD_MD_FLXATTRLS) {
                 CDEBUG(D_INODE, "listxattr\n");
 
@@ -201,60 +210,58 @@ out:
         return rc;
 }
 
         return rc;
 }
 
-/* return EADATA length to the caller. negative value means error */
-static int mdt_setxattr_pack_reply(struct mdt_thread_info * info)
-{
-        struct req_capsule     *pill = &info->mti_pill ;
-        __u64                   valid = info->mti_body->valid;
-        int                     rc = 0, rc1;
-
-        if ((valid & OBD_MD_FLXATTR) == OBD_MD_FLXATTR) {
-                char *xattr_name;
-
-                xattr_name = req_capsule_client_get(pill, &RMF_NAME);
-                if (!xattr_name)
-                        return -EFAULT;
-
-                if (!strcmp(xattr_name, XATTR_NAME_LUSTRE_ACL))
-                        rc = RMTACL_SIZE_MAX;
-        }
-
-        req_capsule_set_size(pill, &RMF_EADATA, RCL_SERVER, rc);
-
-        rc1 = req_capsule_pack(pill);
-
-        return rc = rc1 ? rc1 : rc;
-}
-
-static int do_remote_setfacl(struct mdt_thread_info *info)
+static int mdt_rmtlsetfacl(struct mdt_thread_info *info, char *xattr_name,
+                           ext_acl_xattr_header *header,
+                           posix_acl_xattr_header **out)
 {
         struct ptlrpc_request *req = mdt_info_req(info);
 {
         struct ptlrpc_request *req = mdt_info_req(info);
+        struct mdt_export_data *med = mdt_req2med(req);
+        struct md_ucred *uc = mdt_ucred(info);
+        struct md_object *next = mdt_object_child(info->mti_object);
         struct lu_buf         *buf = &info->mti_buf;
         struct lu_buf         *buf = &info->mti_buf;
-        char *cmd;
         int rc;
         ENTRY;
 
         int rc;
         ENTRY;
 
-        cmd = req_capsule_client_get(&info->mti_pill, &RMF_EADATA);
-        if (!cmd) {
-                CERROR("missing setfacl command!\n");
-                RETURN(-EFAULT);
+        rc = lustre_ext_acl_xattr_id2server(uc, med->med_idmap, header);
+        if (rc)
+                RETURN(rc);
+        rc = mo_xattr_get(info->mti_env, next, &LU_BUF_NULL, xattr_name);
+        if (rc == -ENODATA)
+                rc = 0;
+        else if (rc < 0)
+                RETURN(rc);
+
+        buf->lb_len = rc;
+        if (buf->lb_len > 0) {
+                OBD_ALLOC(buf->lb_buf, buf->lb_len);
+                if (unlikely(buf->lb_buf == NULL))
+                        RETURN(-ENOMEM);
+
+                rc = mo_xattr_get(info->mti_env, next, buf, xattr_name);
+                if (rc < 0) {
+                        CERROR("getxattr failed: %d\n", rc);
+                        GOTO(_out, rc);
         }
         }
+        } else
+                buf->lb_buf = NULL;
 
 
-        buf->lb_buf = req_capsule_server_get(&info->mti_pill, &RMF_EADATA);
-        LASSERT(buf->lb_buf);
-        buf->lb_len = RMTACL_SIZE_MAX;
+        rc = lustre_acl_xattr_merge2posix((posix_acl_xattr_header *)(buf->lb_buf),
+                                          buf->lb_len, header, out);
+        EXIT;
 
 
-        rc = mdt_rmtacl_upcall(info, cmd, buf);
-        if (rc)
-                CERROR("remote acl upcall failed: %d\n", rc);
+_out:
+        if (rc <= 0 && buf->lb_buf != NULL)
+                OBD_FREE(buf->lb_buf, buf->lb_len);
 
 
-        lustre_shrink_reply(req, REPLY_REC_OFF, strlen(buf->lb_buf) + 1, 0);
-        RETURN(rc);
+        return rc;
 }
 
 int mdt_setxattr(struct mdt_thread_info *info)
 {
         struct ptlrpc_request   *req = mdt_info_req(info);
 }
 
 int mdt_setxattr(struct mdt_thread_info *info)
 {
         struct ptlrpc_request   *req = mdt_info_req(info);
+        struct mdt_export_data  *med = mdt_req2med(req);
+        struct md_ucred         *uc  = mdt_ucred(info);
         struct mdt_body         *reqbody;
         const char               user_string[] = "user.";
         const char               trust_string[] = "trusted.";
         struct mdt_body         *reqbody;
         const char               user_string[] = "user.";
         const char               trust_string[] = "trusted.";
@@ -267,9 +274,10 @@ int mdt_setxattr(struct mdt_thread_info *info)
         struct lu_buf           *buf  = &info->mti_buf;
         __u64                    valid  = body->valid;
         char                    *xattr_name;
         struct lu_buf           *buf  = &info->mti_buf;
         __u64                    valid  = body->valid;
         char                    *xattr_name;
-        int                      xattr_len;
+        int                      xattr_len = 0;
         __u64                    lockpart;
         int                      rc;
         __u64                    lockpart;
         int                      rc;
+        posix_acl_xattr_header  *new_xattr = NULL;
         ENTRY;
 
         CDEBUG(D_INODE, "setxattr "DFID"\n", PFID(&body->fid1));
         ENTRY;
 
         CDEBUG(D_INODE, "setxattr "DFID"\n", PFID(&body->fid1));
@@ -285,7 +293,17 @@ int mdt_setxattr(struct mdt_thread_info *info)
         if (rc)
                 RETURN(err_serious(rc));
 
         if (rc)
                 RETURN(err_serious(rc));
 
-        rc = mdt_setxattr_pack_reply(info);
+        if (valid & OBD_MD_FLRMTRSETFACL) {
+                __u32 perm = mdt_identity_get_perm(uc->mu_identity,
+                                                   med->med_rmtclient,
+                                                   req->rq_peer.nid);
+
+                LASSERT(med->med_rmtclient);
+                if (!(perm & CFS_RMTACL_PERM))
+                        GOTO(out, rc = err_serious(-EPERM));
+        }
+
+        rc = req_capsule_pack(pill);
         if (rc < 0)
                 GOTO(out, rc = err_serious(rc));
 
         if (rc < 0)
                 GOTO(out, rc = err_serious(rc));
 
@@ -297,12 +315,6 @@ int mdt_setxattr(struct mdt_thread_info *info)
         CDEBUG(D_INODE, "%s xattr %s\n",
                   body->valid & OBD_MD_FLXATTR ? "set" : "remove", xattr_name);
 
         CDEBUG(D_INODE, "%s xattr %s\n",
                   body->valid & OBD_MD_FLXATTR ? "set" : "remove", xattr_name);
 
-        if (((valid & OBD_MD_FLXATTR) == OBD_MD_FLXATTR) &&
-            (!strcmp(xattr_name, XATTR_NAME_LUSTRE_ACL))) {
-                rc = do_remote_setfacl(info);
-                GOTO(out, rc);
-        }
-
         if (strncmp(xattr_name, trust_string, sizeof(trust_string) - 1) == 0) {
                 if (strcmp(xattr_name + 8, XATTR_NAME_LOV) == 0)
                         GOTO(out, rc = -EACCES);
         if (strncmp(xattr_name, trust_string, sizeof(trust_string) - 1) == 0) {
                 if (strcmp(xattr_name + 8, XATTR_NAME_LOV) == 0)
                         GOTO(out, rc = -EACCES);
@@ -335,6 +347,17 @@ int mdt_setxattr(struct mdt_thread_info *info)
                         int flags = 0;
                         xattr = req_capsule_client_get(pill, &RMF_EADATA);
 
                         int flags = 0;
                         xattr = req_capsule_client_get(pill, &RMF_EADATA);
 
+                        if (valid & OBD_MD_FLRMTLSETFACL) {
+                                LASSERT(med->med_rmtclient);
+                                xattr_len = mdt_rmtlsetfacl(info, xattr_name,
+                                                (ext_acl_xattr_header *)xattr,
+                                                &new_xattr);
+                                if (xattr_len < 0)
+                                        GOTO(out_unlock, rc = xattr_len);
+
+                                xattr = (char *)new_xattr;
+                        }
+
                         if (body->flags & XATTR_REPLACE)
                                 flags |= LU_XATTR_REPLACE;
 
                         if (body->flags & XATTR_REPLACE)
                                 flags |= LU_XATTR_REPLACE;
 
@@ -356,6 +379,8 @@ int mdt_setxattr(struct mdt_thread_info *info)
         }
         EXIT;
 out_unlock:
         }
         EXIT;
 out_unlock:
+        if (unlikely(new_xattr != NULL))
+                lustre_posix_acl_xattr_free(new_xattr, xattr_len);
         mdt_object_unlock(info, obj, lh, rc);
 out:
         mdt_exit_ucred(info);
         mdt_object_unlock(info, obj, lh, rc);
 out:
         mdt_exit_ucred(info);
index 01d85bd..65c8610 100644 (file)
@@ -317,7 +317,7 @@ static int mgc_requeue_add(struct config_llog_data *cld, int later)
         CDEBUG(D_INFO, "log %s: requeue (l=%d r=%d sp=%d st=%x)\n", 
                cld->cld_logname, later, atomic_read(&cld->cld_refcount),
                cld->cld_stopping, rq_state);
         CDEBUG(D_INFO, "log %s: requeue (l=%d r=%d sp=%d st=%x)\n", 
                cld->cld_logname, later, atomic_read(&cld->cld_refcount),
                cld->cld_stopping, rq_state);
-        
+
         /* Hold lock for rq_state */
         spin_lock(&config_list_lock);
         cld->cld_lostlock = 1;
         /* Hold lock for rq_state */
         spin_lock(&config_list_lock);
         cld->cld_lostlock = 1;
index 598ad31..e3d71ad 100644 (file)
@@ -29,6 +29,7 @@
 #include <obd.h>
 #include <obd_class.h>
 #include <lprocfs_status.h>
 #include <obd.h>
 #include <obd_class.h>
 #include <lprocfs_status.h>
+#include <lustre_param.h>
 #include "mgs_internal.h"
 
 #ifdef LPROCFS
 #include "mgs_internal.h"
 
 #ifdef LPROCFS
@@ -88,9 +89,40 @@ int lproc_mgs_setup(struct obd_device *obd)
         return rc;
 }
 
         return rc;
 }
 
+static void seq_show_srpc_rule(struct seq_file *seq, const char *tgtname,
+                               struct sptlrpc_rule_set *rset)
+{
+        struct sptlrpc_rule    *r;
+        char                    dirbuf[10];
+        char                    flvrbuf[40];
+        char                   *net;
+        int                     i;
+
+        for (i = 0; i < rset->srs_nrule; i++) {
+                r = &rset->srs_rules[i];
+
+                if (r->sr_netid == LNET_NIDNET(LNET_NID_ANY))
+                        net = "default";
+                else
+                        net = libcfs_net2str(r->sr_netid);
+
+                if (r->sr_from == LUSTRE_SP_ANY && r->sr_to == LUSTRE_SP_ANY)
+                        dirbuf[0] = '\0';
+                else
+                        snprintf(dirbuf, sizeof(dirbuf), ".%s2%s",
+                                 sptlrpc_part2name(r->sr_from),
+                                 sptlrpc_part2name(r->sr_to));
+
+                sptlrpc_flavor2name(&r->sr_flvr, flvrbuf, sizeof(flvrbuf));
+                seq_printf(seq, "%s.srpc.flavor.%s%s=%s\n", tgtname,
+                           net, dirbuf, flvrbuf);
+        }
+}
+
 static int mgs_live_seq_show(struct seq_file *seq, void *v) 
 {
 static int mgs_live_seq_show(struct seq_file *seq, void *v) 
 {
-        struct fs_db *fsdb = seq->private;
+        struct fs_db             *fsdb = seq->private;
+        struct mgs_tgt_srpc_conf *srpc_tgt;
         int i;
         
         down(&fsdb->fsdb_sem);
         int i;
         
         down(&fsdb->fsdb_sem);
@@ -105,6 +137,18 @@ static int mgs_live_seq_show(struct seq_file *seq, void *v)
                  if (test_bit(i, fsdb->fsdb_ost_index_map)) 
                          seq_printf(seq, "%s-OST%04x\n", fsdb->fsdb_name, i);
 
                  if (test_bit(i, fsdb->fsdb_ost_index_map)) 
                          seq_printf(seq, "%s-OST%04x\n", fsdb->fsdb_name, i);
 
+        seq_printf(seq, "\nSecure RPC Config Rules:\n");
+#if 0
+        seq_printf(seq, "%s.%s=%s\n", fsdb->fsdb_name,
+                   PARAM_SRPC_UDESC, fsdb->fsdb_srpc_fl_udesc ? "yes" : "no");
+#endif
+        for (srpc_tgt = fsdb->fsdb_srpc_tgt; srpc_tgt;
+             srpc_tgt = srpc_tgt->mtsc_next) {
+                seq_show_srpc_rule(seq, srpc_tgt->mtsc_tgt,
+                                   &srpc_tgt->mtsc_rset);
+        }
+        seq_show_srpc_rule(seq, fsdb->fsdb_name, &fsdb->fsdb_srpc_gen);
+
         up(&fsdb->fsdb_sem);
         return 0;
 }
         up(&fsdb->fsdb_sem);
         return 0;
 }
index 786ea2a..1efe1ab 100644 (file)
@@ -65,6 +65,8 @@ static int mgs_connect(const struct lu_env *env,
         exp = class_conn2export(conn);
         LASSERT(exp);
 
         exp = class_conn2export(conn);
         LASSERT(exp);
 
+        exp->exp_flvr.sf_rpc = SPTLRPC_FLVR_NULL;
+
         if (data != NULL) {
                 data->ocd_connect_flags &= MGS_CONNECT_SUPPORTED;
                 exp->exp_connect_flags = data->ocd_connect_flags;
         if (data != NULL) {
                 data->ocd_connect_flags &= MGS_CONNECT_SUPPORTED;
                 exp->exp_connect_flags = data->ocd_connect_flags;
index 69acba9..5f0361f 100644 (file)
@@ -23,6 +23,12 @@ int class_dentry_readdir(struct obd_device *obd, struct dentry *dir,
                          struct vfsmount *inmnt, 
                          struct list_head *dentry_list);
  
                          struct vfsmount *inmnt, 
                          struct list_head *dentry_list);
  
+struct mgs_tgt_srpc_conf {
+        struct mgs_tgt_srpc_conf  *mtsc_next;
+        char                      *mtsc_tgt;
+        struct sptlrpc_rule_set    mtsc_rset;
+};
+
 #define INDEX_MAP_SIZE  8192     /* covers indicies to FFFF */
 #define FSDB_LOG_EMPTY  0x0001  /* missing client log */
 #define FSDB_OLDLOG14   0x0002  /* log starts in old (1.4) style */
 #define INDEX_MAP_SIZE  8192     /* covers indicies to FFFF */
 #define FSDB_LOG_EMPTY  0x0001  /* missing client log */
 #define FSDB_OLDLOG14   0x0002  /* log starts in old (1.4) style */
@@ -43,6 +49,11 @@ struct fs_db {
         /* end COMPAT_146 */
         __u32             fsdb_flags;
         __u32             fsdb_gen;
         /* end COMPAT_146 */
         __u32             fsdb_flags;
         __u32             fsdb_gen;
+
+        /* in-memory copy of the srpc rules, guarded by fsdb_sem */
+        struct sptlrpc_rule_set   fsdb_srpc_gen;
+        struct mgs_tgt_srpc_conf *fsdb_srpc_tgt;
+        unsigned int              fsdb_srpc_fl_udesc:1;
 };
 
 int mgs_init_fsdb_list(struct obd_device *obd);
 };
 
 int mgs_init_fsdb_list(struct obd_device *obd);
index 7f5eb86..e942879 100644 (file)
 #include <lustre_sec.h>
 #include "mgs_internal.h"
 
 #include <lustre_sec.h>
 #include "mgs_internal.h"
 
+static int mgs_get_fsdb_srpc_from_llog(struct obd_device *obd,
+                                       struct fs_db *fsdb);
+static int mgs_get_srpc_conf_log(struct fs_db *fsdb, const char *tgt,
+                                 enum lustre_sec_part from,
+                                 enum lustre_sec_part to,
+                                 struct sptlrpc_conf_log *log);
+
 /********************** Class functions ********************/
 
 /* Caller must list_del and OBD_FREE each dentry from the list */
 /********************** Class functions ********************/
 
 /* Caller must list_del and OBD_FREE each dentry from the list */
@@ -260,6 +267,26 @@ out_pop:
         RETURN(rc);
 }
 
         RETURN(rc);
 }
 
+static void mgs_free_fsdb_srpc(struct fs_db *fsdb)
+{
+        struct mgs_tgt_srpc_conf *tgtconf;
+
+        /* free target-specific rules */
+        while (fsdb->fsdb_srpc_tgt) {
+                tgtconf = fsdb->fsdb_srpc_tgt;
+                fsdb->fsdb_srpc_tgt = tgtconf->mtsc_next;
+
+                LASSERT(tgtconf->mtsc_tgt);
+
+                sptlrpc_rule_set_free(&tgtconf->mtsc_rset);
+                OBD_FREE(tgtconf->mtsc_tgt, strlen(tgtconf->mtsc_tgt) + 1);
+                OBD_FREE_PTR(tgtconf);
+        }
+
+        /* free general rules */
+        sptlrpc_rule_set_free(&fsdb->fsdb_srpc_gen);
+}
+
 static struct fs_db *mgs_find_fsdb(struct obd_device *obd, char *fsname)
 {
         struct mgs_obd *mgs = &obd->u.mgs;
 static struct fs_db *mgs_find_fsdb(struct obd_device *obd, char *fsname)
 {
         struct mgs_obd *mgs = &obd->u.mgs;
@@ -309,6 +336,7 @@ static struct fs_db *mgs_new_fsdb(struct obd_device *obd, char *fsname)
         if (rc) 
                 GOTO(err, rc);
 
         if (rc) 
                 GOTO(err, rc);
 
+        fsdb->fsdb_srpc_fl_udesc = 1;
         sema_init(&fsdb->fsdb_sem, 1);
         list_add(&fsdb->fsdb_list, &mgs->mgs_fs_db_list);
         lproc_mgs_add_live(obd, fsdb);
         sema_init(&fsdb->fsdb_sem, 1);
         list_add(&fsdb->fsdb_list, &mgs->mgs_fs_db_list);
         lproc_mgs_add_live(obd, fsdb);
@@ -340,6 +368,7 @@ static void mgs_free_fsdb(struct obd_device *obd, struct fs_db *fsdb)
         name_destroy(&fsdb->fsdb_mdtlov); 
         name_destroy(&fsdb->fsdb_mdtlmv); 
         name_destroy(&fsdb->fsdb_mdc); 
         name_destroy(&fsdb->fsdb_mdtlov); 
         name_destroy(&fsdb->fsdb_mdtlmv); 
         name_destroy(&fsdb->fsdb_mdc); 
+        mgs_free_fsdb_srpc(fsdb);
         OBD_FREE_PTR(fsdb);
 }
 
         OBD_FREE_PTR(fsdb);
 }
 
@@ -393,6 +422,14 @@ static int mgs_find_or_make_fsdb(struct obd_device *obd, char *name,
                 return rc;
         }
 
                 return rc;
         }
 
+        /* populate srpc rules from params llog */
+        rc = mgs_get_fsdb_srpc_from_llog(obd, fsdb);
+        if (rc) {
+                CERROR("Can't get db from params log %d\n", rc);
+                mgs_free_fsdb(obd, fsdb);
+                return rc;
+        }
+
         *dbh = fsdb;
 
         return 0;
         *dbh = fsdb;
 
         return 0;
@@ -712,17 +749,18 @@ static inline int record_setup(struct obd_device *obd, struct llog_handle *llh,
         return record_base(obd,llh,devname,0,LCFG_SETUP,s1,s2,s3,s4);
 }
 
         return record_base(obd,llh,devname,0,LCFG_SETUP,s1,s2,s3,s4);
 }
 
-static inline int record_sec_flavor(struct obd_device *obd,
-                                    struct llog_handle *llh, char *devname,
-                                    struct sec_flavor_config *conf)
+static inline int record_sptlrpc_conf(struct obd_device *obd,
+                                      struct llog_handle *llh,
+                                      char *devname,
+                                      struct sptlrpc_conf_log *srpc_log)
 {
         struct lustre_cfg_bufs bufs;
         struct lustre_cfg *lcfg;
         int rc;
 
         lustre_cfg_bufs_reset(&bufs, devname);
 {
         struct lustre_cfg_bufs bufs;
         struct lustre_cfg *lcfg;
         int rc;
 
         lustre_cfg_bufs_reset(&bufs, devname);
-        lustre_cfg_bufs_set(&bufs, 1, conf, sizeof(*conf));
-        lcfg = lustre_cfg_new(LCFG_SEC_FLAVOR, &bufs);
+        lustre_cfg_bufs_set(&bufs, 1, srpc_log, sizeof(*srpc_log));
+        lcfg = lustre_cfg_new(LCFG_SPTLRPC_CONF, &bufs);
 
         rc = record_lcfg(obd, llh, lcfg);
 
 
         rc = record_lcfg(obd, llh, lcfg);
 
@@ -952,7 +990,9 @@ int mgs_write_log_direct_all(struct obd_device *obd, struct fs_db *fsdb,
         /* Could use fsdb index maps instead of directory listing */
         list_for_each_entry_safe(dirent, n, &dentry_list, lld_list) {
                 list_del(&dirent->lld_list);
         /* Could use fsdb index maps instead of directory listing */
         list_for_each_entry_safe(dirent, n, &dentry_list, lld_list) {
                 list_del(&dirent->lld_list);
-                if (strncmp(fsname, dirent->lld_name, len) == 0) {
+                /* don't write to sptlrpc rule log */
+                if (strncmp(fsname, dirent->lld_name, len) == 0 &&
+                    strstr(dirent->lld_name, "-sptlrpc") == NULL) {
                         CDEBUG(D_MGS, "Changing log %s\n", dirent->lld_name);
                         /* Erase any old settings of this same parameter */
                         mgs_modify(obd, fsdb, mti, dirent->lld_name, devname, 
                         CDEBUG(D_MGS, "Changing log %s\n", dirent->lld_name);
                         /* Erase any old settings of this same parameter */
                         mgs_modify(obd, fsdb, mti, dirent->lld_name, devname, 
@@ -976,12 +1016,10 @@ struct temp_comp
         struct mgs_target_info   *comp_mti;
         struct fs_db             *comp_fsdb;
         struct obd_device        *comp_obd;
         struct mgs_target_info   *comp_mti;
         struct fs_db             *comp_fsdb;
         struct obd_device        *comp_obd;
-        struct sec_flavor_config  comp_sec;
 };
 
 static int mgs_write_log_mdc_to_mdt(struct obd_device *, struct fs_db *,
 };
 
 static int mgs_write_log_mdc_to_mdt(struct obd_device *, struct fs_db *,
-                                    struct mgs_target_info *,
-                                    struct sec_flavor_config *, char *);
+                                    struct mgs_target_info *, char *);
 
 static int mgs_steal_llog_handler(struct llog_handle *llh,
                                   struct llog_rec_hdr *rec,
 
 static int mgs_steal_llog_handler(struct llog_handle *llh,
                                   struct llog_rec_hdr *rec,
@@ -993,7 +1031,6 @@ static int mgs_steal_llog_handler(struct llog_handle *llh,
         int cfg_len = rec->lrh_len;
         char *cfg_buf = (char*) (rec + 1);
         struct lustre_cfg *lcfg;
         int cfg_len = rec->lrh_len;
         char *cfg_buf = (char*) (rec + 1);
         struct lustre_cfg *lcfg;
-        struct sec_flavor_config *sec_conf;
         int rc = 0;
         struct llog_handle *mdt_llh = NULL;
         static int got_an_osc_or_mdc = 0;
         int rc = 0;
         struct llog_handle *mdt_llh = NULL;
         static int got_an_osc_or_mdc = 0;
@@ -1009,7 +1046,6 @@ static int mgs_steal_llog_handler(struct llog_handle *llh,
         tmti = ((struct temp_comp*)data)->comp_tmti;
         fsdb = ((struct temp_comp*)data)->comp_fsdb;
         obd = ((struct temp_comp*)data)->comp_obd;
         tmti = ((struct temp_comp*)data)->comp_tmti;
         fsdb = ((struct temp_comp*)data)->comp_fsdb;
         obd = ((struct temp_comp*)data)->comp_obd;
-        sec_conf = &((struct temp_comp*)data)->comp_sec;
 
         if (rec->lrh_type != OBD_CFG_REC) {
                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
 
         if (rec->lrh_type != OBD_CFG_REC) {
                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
@@ -1087,10 +1123,9 @@ static int mgs_steal_llog_handler(struct llog_handle *llh,
                 RETURN(rc);
         }
 
                 RETURN(rc);
         }
 
-        if (lcfg->lcfg_command == LCFG_SEC_FLAVOR) {
-                memcpy(sec_conf, lustre_cfg_buf(lcfg, 1), sizeof(*sec_conf));
+        /* ignore client side sptlrpc_conf_log */
+        if (lcfg->lcfg_command == LCFG_SPTLRPC_CONF)
                 RETURN(rc);
                 RETURN(rc);
-        }
 
         if (lcfg->lcfg_command == LCFG_ADD_MDC) {
                 int index;
 
         if (lcfg->lcfg_command == LCFG_ADD_MDC) {
                 int index;
@@ -1102,8 +1137,7 @@ static int mgs_steal_llog_handler(struct llog_handle *llh,
                        strlen(mti->mti_fsname));
                 tmti->mti_stripe_index = index;
 
                        strlen(mti->mti_fsname));
                 tmti->mti_stripe_index = index;
 
-                mgs_write_log_mdc_to_mdt(obd, fsdb, tmti, sec_conf,
-                                         mti->mti_svname);
+                mgs_write_log_mdc_to_mdt(obd, fsdb, tmti, mti->mti_svname);
                 memset(tmti, 0, sizeof(*tmti));
                 RETURN(rc);
         }
                 memset(tmti, 0, sizeof(*tmti));
                 RETURN(rc);
         }
@@ -1283,37 +1317,12 @@ static int mgs_write_log_failnids(struct obd_device *obd,
         return rc;
 }
 
         return rc;
 }
 
-static
-void extract_sec_flavor(char *params, char *key, char **ptr)
-{
-        char *val = NULL, *tail;
-        int   len;
-
-        *ptr = NULL;
-
-        if (class_find_param(params, key, &val))
-                return;
-
-        tail = strchr(val, ' ');
-        if (tail == NULL)
-                len = strlen(val);
-        else
-                len = tail - val;
-
-        OBD_ALLOC(*ptr, len + 1);
-        if (*ptr == NULL)
-                return;
-
-        memcpy(*ptr, val, len);
-        (*ptr)[len] = '\0';
-}
-
 static int mgs_write_log_mdc_to_lmv(struct obd_device *obd, struct fs_db *fsdb,
                                     struct mgs_target_info *mti,
 static int mgs_write_log_mdc_to_lmv(struct obd_device *obd, struct fs_db *fsdb,
                                     struct mgs_target_info *mti,
-                                    struct sec_flavor_config *sec_conf,
                                     char *logname, char *lmvname)
 {
         struct llog_handle *llh = NULL;
                                     char *logname, char *lmvname)
 {
         struct llog_handle *llh = NULL;
+        struct sptlrpc_conf_log *srpc_log;
         char *mdcname, *nodeuuid, *mdcuuid, *lmvuuid;
         char index[5];
         int i, rc;
         char *mdcname, *nodeuuid, *mdcuuid, *lmvuuid;
         char index[5];
         int i, rc;
@@ -1327,6 +1336,16 @@ static int mgs_write_log_mdc_to_lmv(struct obd_device *obd, struct fs_db *fsdb,
         CDEBUG(D_MGS, "adding mdc for %s to log %s:lmv(%s)\n",
                mti->mti_svname, logname, lmvname);
 
         CDEBUG(D_MGS, "adding mdc for %s to log %s:lmv(%s)\n",
                mti->mti_svname, logname, lmvname);
 
+        srpc_log = sptlrpc_conf_log_alloc();
+        if (IS_ERR(srpc_log))
+                RETURN(PTR_ERR(srpc_log));
+        srpc_log->scl_part = LUSTRE_SP_CLI;
+
+        rc = mgs_get_srpc_conf_log(fsdb, mti->mti_svname,
+                                   LUSTRE_SP_CLI, LUSTRE_SP_MDT, srpc_log);
+        if (rc)
+                goto out_srpc;
+
         name_create(&nodeuuid, libcfs_nid2str(mti->mti_nids[0]), "");
         name_create(&mdcname, mti->mti_svname, "-mdc");
         name_create(&mdcuuid, mdcname, "_UUID");
         name_create(&nodeuuid, libcfs_nid2str(mti->mti_nids[0]), "");
         name_create(&mdcname, mti->mti_svname, "-mdc");
         name_create(&mdcuuid, mdcname, "_UUID");
@@ -1345,7 +1364,7 @@ static int mgs_write_log_mdc_to_lmv(struct obd_device *obd, struct fs_db *fsdb,
 
         rc = record_attach(obd, llh, mdcname, LUSTRE_MDC_NAME, lmvuuid);
         rc = record_setup(obd, llh, mdcname, mti->mti_uuid, nodeuuid, 0, 0);
 
         rc = record_attach(obd, llh, mdcname, LUSTRE_MDC_NAME, lmvuuid);
         rc = record_setup(obd, llh, mdcname, mti->mti_uuid, nodeuuid, 0, 0);
-        rc = record_sec_flavor(obd, llh, mdcname, sec_conf);
+        rc = record_sptlrpc_conf(obd, llh, mdcname, srpc_log);
         rc = mgs_write_log_failnids(obd, mti, llh, mdcname);
         snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
         rc = record_mdc_add(obd, llh, lmvname, mdcuuid, mti->mti_uuid,
         rc = mgs_write_log_failnids(obd, mti, llh, mdcname);
         snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
         rc = record_mdc_add(obd, llh, lmvname, mdcuuid, mti->mti_uuid,
@@ -1358,16 +1377,17 @@ static int mgs_write_log_mdc_to_lmv(struct obd_device *obd, struct fs_db *fsdb,
         name_destroy(&mdcuuid);
         name_destroy(&mdcname);
         name_destroy(&nodeuuid);
         name_destroy(&mdcuuid);
         name_destroy(&mdcname);
         name_destroy(&nodeuuid);
+out_srpc:
+        sptlrpc_conf_log_free(srpc_log);
         RETURN(rc);
 }
 
 /* add new mdc to already existent MDS */
 static int mgs_write_log_mdc_to_mdt(struct obd_device *obd, struct fs_db *fsdb,
         RETURN(rc);
 }
 
 /* add new mdc to already existent MDS */
 static int mgs_write_log_mdc_to_mdt(struct obd_device *obd, struct fs_db *fsdb,
-                                    struct mgs_target_info *mti,
-                                    struct sec_flavor_config *sec_conf,
-                                    char *logname)
+                                    struct mgs_target_info *mti, char *logname)
 {
         struct llog_handle *llh = NULL;
 {
         struct llog_handle *llh = NULL;
+        struct sptlrpc_conf_log *srpc_log;
         char *nodeuuid, *mdcname, *mdcuuid, *mdtuuid;
         int idx = mti->mti_stripe_index;
         char index[9];
         char *nodeuuid, *mdcname, *mdcuuid, *mdtuuid;
         int idx = mti->mti_stripe_index;
         char index[9];
@@ -1381,6 +1401,16 @@ static int mgs_write_log_mdc_to_mdt(struct obd_device *obd, struct fs_db *fsdb,
 
         CDEBUG(D_MGS, "adding mdc index %d to %s\n", idx, logname);
 
 
         CDEBUG(D_MGS, "adding mdc index %d to %s\n", idx, logname);
 
+        srpc_log = sptlrpc_conf_log_alloc();
+        if (IS_ERR(srpc_log))
+                RETURN(PTR_ERR(srpc_log));
+        srpc_log->scl_part = LUSTRE_SP_MDT;
+
+        rc = mgs_get_srpc_conf_log(fsdb, mti->mti_svname,
+                                   LUSTRE_SP_MDT, LUSTRE_SP_MDT, srpc_log);
+        if (rc)
+                goto out_srpc;
+
         name_create(&nodeuuid, libcfs_nid2str(mti->mti_nids[0]), "");
         snprintf(index, sizeof(index), "-mdc%04x", idx);
         name_create(&mdcname, logname, index);
         name_create(&nodeuuid, libcfs_nid2str(mti->mti_nids[0]), "");
         snprintf(index, sizeof(index), "-mdc%04x", idx);
         name_create(&mdcname, logname, index);
@@ -1396,7 +1426,7 @@ static int mgs_write_log_mdc_to_mdt(struct obd_device *obd, struct fs_db *fsdb,
         }
         rc = record_attach(obd, llh, mdcname, LUSTRE_MDC_NAME, mdcuuid);
         rc = record_setup(obd, llh, mdcname, mti->mti_uuid, nodeuuid, 0, 0);
         }
         rc = record_attach(obd, llh, mdcname, LUSTRE_MDC_NAME, mdcuuid);
         rc = record_setup(obd, llh, mdcname, mti->mti_uuid, nodeuuid, 0, 0);
-        rc = record_sec_flavor(obd, llh, mdcname, sec_conf);
+        rc = record_sptlrpc_conf(obd, llh, mdcname, srpc_log);
         rc = mgs_write_log_failnids(obd, mti, llh, mdcname);
         snprintf(index, sizeof(index), "%d", idx);
 
         rc = mgs_write_log_failnids(obd, mti, llh, mdcname);
         snprintf(index, sizeof(index), "%d", idx);
 
@@ -1409,6 +1439,8 @@ static int mgs_write_log_mdc_to_mdt(struct obd_device *obd, struct fs_db *fsdb,
         name_destroy(&mdcname);
         name_destroy(&nodeuuid);
         name_destroy(&mdtuuid);
         name_destroy(&mdcname);
         name_destroy(&nodeuuid);
         name_destroy(&mdtuuid);
+out_srpc:
+        sptlrpc_conf_log_free(srpc_log);
         RETURN(rc);
 }
 
         RETURN(rc);
 }
 
@@ -1419,13 +1451,24 @@ static int mgs_write_log_mdt0(struct obd_device *obd, struct fs_db *fsdb,
         struct llog_handle *llh = NULL;
         char *uuid, *lovname;
         char mdt_index[5];
         struct llog_handle *llh = NULL;
         char *uuid, *lovname;
         char mdt_index[5];
+        struct sptlrpc_conf_log *srpc_log;
         char *ptr = mti->mti_params;
         int rc = 0, failout = 0;
         ENTRY;
 
         char *ptr = mti->mti_params;
         int rc = 0, failout = 0;
         ENTRY;
 
+        srpc_log = sptlrpc_conf_log_alloc();
+        if (IS_ERR(srpc_log))
+                RETURN(PTR_ERR(srpc_log));
+        srpc_log->scl_part = LUSTRE_SP_MDT;
+
+        rc = mgs_get_srpc_conf_log(fsdb, mti->mti_svname,
+                                   LUSTRE_SP_ANY, LUSTRE_SP_MDT, srpc_log);
+        if (rc)
+                GOTO(out_srpc, rc);
+
         OBD_ALLOC(uuid, sizeof(struct obd_uuid));
         if (uuid == NULL)
         OBD_ALLOC(uuid, sizeof(struct obd_uuid));
         if (uuid == NULL)
-                RETURN(-ENOMEM);
+                GOTO(out_srpc, rc = -ENOMEM);
 
         if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0) 
                 failout = (strncmp(ptr, "failout", 7) == 0);
 
         if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0) 
                 failout = (strncmp(ptr, "failout", 7) == 0);
@@ -1448,11 +1491,14 @@ static int mgs_write_log_mdt0(struct obd_device *obd, struct fs_db *fsdb,
         rc = record_mount_opt(obd, llh, log, lovname, NULL);
         rc = record_setup(obd, llh, log, uuid, mdt_index, lovname, 
                         failout ? "n" : "f");
         rc = record_mount_opt(obd, llh, log, lovname, NULL);
         rc = record_setup(obd, llh, log, uuid, mdt_index, lovname, 
                         failout ? "n" : "f");
+        rc = record_sptlrpc_conf(obd, llh, log, srpc_log);
         rc = record_marker(obd, llh, fsdb, CM_END, log, "add mdt");
         rc = record_end_log(obd, &llh);
 out:
         name_destroy(&lovname);
         OBD_FREE(uuid, sizeof(struct obd_uuid));
         rc = record_marker(obd, llh, fsdb, CM_END, log, "add mdt");
         rc = record_end_log(obd, &llh);
 out:
         name_destroy(&lovname);
         OBD_FREE(uuid, sizeof(struct obd_uuid));
+out_srpc:
+        sptlrpc_conf_log_free(srpc_log);
         RETURN(rc);
 }
 
         RETURN(rc);
 }
 
@@ -1460,10 +1506,9 @@ out:
 static int mgs_write_log_mdt(struct obd_device *obd, struct fs_db *fsdb,
                               struct mgs_target_info *mti)
 {
 static int mgs_write_log_mdt(struct obd_device *obd, struct fs_db *fsdb,
                               struct mgs_target_info *mti)
 {
-        char *cliname, *sec;
         struct llog_handle *llh = NULL;
         struct llog_handle *llh = NULL;
+        char *cliname;
         struct temp_comp comp = { 0 };
         struct temp_comp comp = { 0 };
-        struct sec_flavor_config sec_conf_mdt, sec_conf_cli;
         char mdt_index[9];
         int rc, i = 0;
         ENTRY;
         char mdt_index[9];
         int rc, i = 0;
         ENTRY;
@@ -1492,19 +1537,6 @@ static int mgs_write_log_mdt(struct obd_device *obd, struct fs_db *fsdb,
                          "%s_UUID", mti->mti_svname);
         }
 
                          "%s_UUID", mti->mti_svname);
         }
 
-        /* security flavor */
-        extract_sec_flavor(mti->mti_params, PARAM_SEC_RPC_MDT, &sec);
-        rc = sptlrpc_parse_flavor(LUSTRE_MDT, LUSTRE_MDT, sec, &sec_conf_mdt);
-        name_destroy(&sec);
-        if (rc)
-                RETURN(rc);
-
-        extract_sec_flavor(mti->mti_params, PARAM_SEC_RPC_CLI, &sec);
-        rc = sptlrpc_parse_flavor(LUSTRE_CLI, LUSTRE_MDT, sec, &sec_conf_cli);
-        name_destroy(&sec);
-        if (rc)
-                RETURN(rc);
-
         /* add mdt */
         rc = mgs_write_log_mdt0(obd, fsdb, mti);
         
         /* add mdt */
         rc = mgs_write_log_mdt0(obd, fsdb, mti);
         
@@ -1559,8 +1591,8 @@ static int mgs_write_log_mdt(struct obd_device *obd, struct fs_db *fsdb,
                 rc = mgs_steal_llog_for_mdt_from_client(obd, cliname, 
                                                         &comp);
 
                 rc = mgs_steal_llog_for_mdt_from_client(obd, cliname, 
                                                         &comp);
 
-                rc = mgs_write_log_mdc_to_lmv(obd, fsdb, mti, &sec_conf_cli,
-                                              cliname, fsdb->fsdb_clilmv);
+                rc = mgs_write_log_mdc_to_lmv(obd, fsdb, mti, cliname,
+                                              fsdb->fsdb_clilmv);
                 /* add mountopts */
                 rc = record_start_log(obd, &llh, cliname);
                 if (rc) 
                 /* add mountopts */
                 rc = record_start_log(obd, &llh, cliname);
                 if (rc) 
@@ -1586,8 +1618,7 @@ out:
                         sprintf(mdt_index,"-MDT%04x",i);
                         
                         name_create(&mdtname, mti->mti_fsname, mdt_index);
                         sprintf(mdt_index,"-MDT%04x",i);
                         
                         name_create(&mdtname, mti->mti_fsname, mdt_index);
-                        rc = mgs_write_log_mdc_to_mdt(obd, fsdb, mti,
-                                                      &sec_conf_mdt, mdtname);
+                        rc = mgs_write_log_mdc_to_mdt(obd, fsdb, mti, mdtname);
                         name_destroy(&mdtname);
                 }
         }
                         name_destroy(&mdtname);
                 }
         }
@@ -1599,10 +1630,10 @@ out:
 static int mgs_write_log_osc_to_lov(struct obd_device *obd, struct fs_db *fsdb,
                                     struct mgs_target_info *mti,
                                     char *logname, char *suffix, char *lovname,
 static int mgs_write_log_osc_to_lov(struct obd_device *obd, struct fs_db *fsdb,
                                     struct mgs_target_info *mti,
                                     char *logname, char *suffix, char *lovname,
-                                    struct sec_flavor_config *sec_conf,
-                                    int flags)
+                                    enum lustre_sec_part sec_part, int flags)
 {
         struct llog_handle *llh = NULL;
 {
         struct llog_handle *llh = NULL;
+        struct sptlrpc_conf_log *srpc_log;
         char *nodeuuid, *oscname, *oscuuid, *lovuuid, *svname;
         char index[5];
         int i, rc;
         char *nodeuuid, *oscname, *oscuuid, *lovuuid, *svname;
         char index[5];
         int i, rc;
@@ -1611,6 +1642,16 @@ static int mgs_write_log_osc_to_lov(struct obd_device *obd, struct fs_db *fsdb,
         CDEBUG(D_INFO, "adding osc for %s to log %s\n",
                mti->mti_svname, logname);
         
         CDEBUG(D_INFO, "adding osc for %s to log %s\n",
                mti->mti_svname, logname);
         
+        srpc_log = sptlrpc_conf_log_alloc();
+        if (IS_ERR(srpc_log))
+                RETURN(PTR_ERR(srpc_log));
+        srpc_log->scl_part = sec_part;
+
+        rc = mgs_get_srpc_conf_log(fsdb, mti->mti_svname,
+                                   sec_part, LUSTRE_SP_OST, srpc_log);
+        if (rc)
+                goto out_srpc;
+
         if (mgs_log_is_empty(obd, logname)) {
                 /* The first item in the log must be the lov, so we have
                    somewhere to add our osc. */
         if (mgs_log_is_empty(obd, logname)) {
                 /* The first item in the log must be the lov, so we have
                    somewhere to add our osc. */
@@ -1647,7 +1688,7 @@ static int mgs_write_log_osc_to_lov(struct obd_device *obd, struct fs_db *fsdb,
         }
         rc = record_attach(obd, llh, oscname, LUSTRE_OSC_NAME, lovuuid);
         rc = record_setup(obd, llh, oscname, mti->mti_uuid, nodeuuid, 0, 0);
         }
         rc = record_attach(obd, llh, oscname, LUSTRE_OSC_NAME, lovuuid);
         rc = record_setup(obd, llh, oscname, mti->mti_uuid, nodeuuid, 0, 0);
-        rc = record_sec_flavor(obd, llh, oscname, sec_conf);
+        rc = record_sptlrpc_conf(obd, llh, oscname, srpc_log);
         rc = mgs_write_log_failnids(obd, mti, llh, oscname);
         snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
         rc = record_lov_add(obd, llh, lovname, mti->mti_uuid, index, "1");
         rc = mgs_write_log_failnids(obd, mti, llh, oscname);
         snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
         rc = record_lov_add(obd, llh, lovname, mti->mti_uuid, index, "1");
@@ -1660,6 +1701,8 @@ out:
         name_destroy(&oscname);
         name_destroy(&svname);
         name_destroy(&nodeuuid);
         name_destroy(&oscname);
         name_destroy(&svname);
         name_destroy(&nodeuuid);
+out_srpc:
+        sptlrpc_conf_log_free(srpc_log);
         RETURN(rc);
 }
 
         RETURN(rc);
 }
 
@@ -1667,10 +1710,10 @@ static int mgs_write_log_ost(struct obd_device *obd, struct fs_db *fsdb,
                              struct mgs_target_info *mti)
 {
         struct llog_handle *llh = NULL;
                              struct mgs_target_info *mti)
 {
         struct llog_handle *llh = NULL;
-        char *logname, *lovname, *sec;
+        struct sptlrpc_conf_log *srpc_log;
+        char *logname, *lovname;
         char mdt_index[9];
         char *ptr = mti->mti_params;
         char mdt_index[9];
         char *ptr = mti->mti_params;
-        struct sec_flavor_config sec_conf_mdt, sec_conf_cli;
         int rc, flags = 0, failout = 0, i;
         ENTRY;
         
         int rc, flags = 0, failout = 0, i;
         ENTRY;
         
@@ -1689,18 +1732,15 @@ static int mgs_write_log_ost(struct obd_device *obd, struct fs_db *fsdb,
                 RETURN(-EALREADY);
         }
 
                 RETURN(-EALREADY);
         }
 
-        /* security flavors */
-        extract_sec_flavor(mti->mti_params, PARAM_SEC_RPC_MDT, &sec);
-        rc = sptlrpc_parse_flavor(LUSTRE_MDT, LUSTRE_OST, sec, &sec_conf_mdt);
-        name_destroy(&sec);
-        if (rc)
-                RETURN(rc);
+        srpc_log = sptlrpc_conf_log_alloc();
+        if (IS_ERR(srpc_log))
+                RETURN(PTR_ERR(srpc_log));
+        srpc_log->scl_part = LUSTRE_SP_OST;
 
 
-        extract_sec_flavor(mti->mti_params, PARAM_SEC_RPC_CLI, &sec);
-        rc = sptlrpc_parse_flavor(LUSTRE_CLI, LUSTRE_OST, sec, &sec_conf_cli);
-        name_destroy(&sec);
+        rc = mgs_get_srpc_conf_log(fsdb, mti->mti_svname,
+                                   LUSTRE_SP_ANY, LUSTRE_SP_OST, srpc_log);
         if (rc)
         if (rc)
-                RETURN(rc);
+                goto out_srpc;
 
         /*
         attach obdfilter ost1 ost1_UUID
 
         /*
         attach obdfilter ost1 ost1_UUID
@@ -1721,6 +1761,7 @@ static int mgs_write_log_ost(struct obd_device *obd, struct fs_db *fsdb,
         rc = record_setup(obd, llh, mti->mti_svname,
                           "dev"/*ignored*/, "type"/*ignored*/,
                           failout ? "n" : "f", 0/*options*/);
         rc = record_setup(obd, llh, mti->mti_svname,
                           "dev"/*ignored*/, "type"/*ignored*/,
                           failout ? "n" : "f", 0/*options*/);
+        rc = record_sptlrpc_conf(obd, llh, mti->mti_svname, srpc_log);
         rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname, "add ost"); 
         rc = record_end_log(obd, &llh);
 
         rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname, "add ost"); 
         rc = record_end_log(obd, &llh);
 
@@ -1751,7 +1792,7 @@ static int mgs_write_log_ost(struct obd_device *obd, struct fs_db *fsdb,
                         name_create(&lovname, logname, "-mdtlov");
                         mgs_write_log_osc_to_lov(obd, fsdb, mti, logname,
                                                  mdt_index, lovname,
                         name_create(&lovname, logname, "-mdtlov");
                         mgs_write_log_osc_to_lov(obd, fsdb, mti, logname,
                                                  mdt_index, lovname,
-                                                 &sec_conf_mdt, flags);
+                                                 LUSTRE_SP_MDT, flags);
                         name_destroy(&logname);
                         name_destroy(&lovname);
                 }
                         name_destroy(&logname);
                         name_destroy(&lovname);
                 }
@@ -1760,9 +1801,10 @@ static int mgs_write_log_ost(struct obd_device *obd, struct fs_db *fsdb,
         /* Append ost info to the client log */
         name_create(&logname, mti->mti_fsname, "-client");
         mgs_write_log_osc_to_lov(obd, fsdb, mti, logname, "",
         /* Append ost info to the client log */
         name_create(&logname, mti->mti_fsname, "-client");
         mgs_write_log_osc_to_lov(obd, fsdb, mti, logname, "",
-                                 fsdb->fsdb_clilov, &sec_conf_cli, 0);
+                                 fsdb->fsdb_clilov, LUSTRE_SP_CLI, 0);
         name_destroy(&logname);
         name_destroy(&logname);
-        
+out_srpc:
+        sptlrpc_conf_log_free(srpc_log);
         RETURN(rc);
 }
 
         RETURN(rc);
 }
 
@@ -1865,6 +1907,662 @@ static int mgs_wlp_lcfg(struct obd_device *obd, struct fs_db *fsdb,
         return rc;
 }
 
         return rc;
 }
 
+/*
+ * populate rules which applied to a target device
+ */
+static int mgs_get_srpc_conf_log(struct fs_db *fsdb, const char *tgt,
+                                 enum lustre_sec_part from,
+                                 enum lustre_sec_part to,
+                                 struct sptlrpc_conf_log *log)
+{
+        struct mgs_tgt_srpc_conf *tgtconf;
+        struct sptlrpc_rule_set  *tgt_rset;
+        int                       found_tgt = 0, rc;
+
+        for (tgtconf = fsdb->fsdb_srpc_tgt; tgtconf;
+             tgtconf = tgtconf->mtsc_next) {
+                if (!strcmp(tgt, tgtconf->mtsc_tgt)) {
+                        found_tgt = 1;
+                        break;
+                }
+        }
+
+        if (found_tgt)
+                tgt_rset = &tgtconf->mtsc_rset;
+        else
+                tgt_rset = NULL;
+
+        rc = sptlrpc_conf_log_populate(&fsdb->fsdb_srpc_gen, tgt_rset,
+                                       from, to, fsdb->fsdb_srpc_fl_udesc, log);
+        if (rc)
+                CERROR("failed to populate srpc log for %s: %d\n", tgt, rc);
+
+        return rc;
+}
+
+struct mgs_msl_data {
+        struct obd_device      *mmd_obd;
+        struct fs_db           *mmd_fsdb;
+        struct mgs_target_info *mmd_mti;
+        int                     mmd_skip;
+        int                     mmd_attached;
+        int                     mmd_server;
+        enum lustre_sec_part    mmd_tgtpart;
+        char                    mmd_tgtname[MTI_NAME_MAXLEN];
+};
+
+static void mgs_msl_data_cleanup(struct mgs_msl_data *mmd)
+{
+        mmd->mmd_attached = 0;
+        mmd->mmd_tgtname[0] = '\0';
+}
+
+static int mgs_msl_tgt_uuid2name(char *tgtname, char *tgtuuid)
+{
+        char    *ptr;
+
+        if (tgtuuid == NULL) {
+                CERROR("missing target UUID???\n");
+                return -EINVAL;
+        }
+
+        ptr = strstr(tgtuuid, "_UUID");
+        if (ptr == NULL) {
+                CERROR("unrecognized UUID: %s\n", tgtuuid);
+                return -EINVAL;
+        }
+
+        *ptr = '\0';;
+        strncpy(tgtname, tgtuuid, MTI_NAME_MAXLEN);
+        tgtname[MTI_NAME_MAXLEN - 1] = '\0';
+
+        return 0;
+}
+
+static int mgs_modify_srpc_log_handler(struct llog_handle *llh,
+                                       struct llog_rec_hdr *rec, 
+                                       void *data)
+{
+        struct mgs_msl_data *mmd = (struct mgs_msl_data *)data;
+        struct cfg_marker   *marker;
+        struct lustre_cfg   *lcfg = (struct lustre_cfg *)(rec + 1);
+        int                  cfg_len, rc;
+        ENTRY;
+
+        if (rec->lrh_type != OBD_CFG_REC) {
+                CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
+                RETURN(-EINVAL);
+        }
+
+        cfg_len = rec->lrh_len - sizeof(struct llog_rec_hdr) - 
+                  sizeof(struct llog_rec_tail);
+
+        rc = lustre_cfg_sanity_check(lcfg, cfg_len);
+        if (rc) {
+                CERROR("Insane cfg\n");
+                RETURN(rc);
+        }
+
+        if (lcfg->lcfg_command == LCFG_MARKER) {
+                marker = lustre_cfg_buf(lcfg, 1);
+
+                if (marker->cm_flags & CM_START &&
+                    marker->cm_flags & CM_SKIP)
+                        mmd->mmd_skip = 1;
+                if (marker->cm_flags & CM_END)
+                        mmd->mmd_skip = 0;
+
+                RETURN(0);
+        }
+
+        if (mmd->mmd_skip)
+                RETURN(0);
+
+        switch (lcfg->lcfg_command) {
+        case LCFG_ATTACH:
+                mmd->mmd_attached = 1;
+
+                if (!strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_OST_NAME)) {
+                        mmd->mmd_server = 1;
+                        mmd->mmd_tgtpart = LUSTRE_SP_OST;
+                } else if (!strcmp(lustre_cfg_string(lcfg, 1),
+                                   LUSTRE_MDT_NAME)) {
+                        mmd->mmd_server = 1;
+                        mmd->mmd_tgtpart = LUSTRE_SP_MDT;
+                } else if (!strcmp(lustre_cfg_string(lcfg, 1),
+                                   LUSTRE_OSC_NAME)) {
+                        mmd->mmd_server = 0;
+                        mmd->mmd_tgtpart = LUSTRE_SP_OST;
+                } else if (!strcmp(lustre_cfg_string(lcfg, 1),
+                                   LUSTRE_MDC_NAME)) {
+                        mmd->mmd_server = 0;
+                        mmd->mmd_tgtpart = LUSTRE_SP_MDT;
+                } else {
+                        mmd->mmd_attached = 0;
+                }
+
+                if (mmd->mmd_attached && mmd->mmd_server) {
+                        rc = mgs_msl_tgt_uuid2name(mmd->mmd_tgtname,
+                                                   lustre_cfg_string(lcfg, 2));
+                        if (rc) {
+                                mgs_msl_data_cleanup(mmd);
+                                break;
+                        }
+                }
+
+                break;
+        case LCFG_SETUP:
+                if (!mmd->mmd_attached)
+                        break;
+
+                /* already got tgtname at LCFG_ATTACH */
+                if (mmd->mmd_server)
+                        break;
+
+                rc = mgs_msl_tgt_uuid2name(mmd->mmd_tgtname,
+                                           lustre_cfg_string(lcfg, 1));
+                if (rc) {
+                        mgs_msl_data_cleanup(mmd);
+                        break;
+                }
+
+                break;
+        case LCFG_SPTLRPC_CONF: {
+                struct sptlrpc_conf_log *log;
+                enum lustre_sec_part from;
+
+                if (!mmd->mmd_attached)
+                        break;
+
+                log = sptlrpc_conf_log_extract(lcfg);
+                if (log == NULL) {
+                        CERROR("missing sptlrpc config log???\n");
+                        mgs_msl_data_cleanup(mmd);
+                        break;
+                }
+
+                if (mmd->mmd_server)
+                        from = LUSTRE_SP_ANY;
+                else
+                        from = log->scl_part;
+
+                /* cleanup the old log */
+                sptlrpc_conf_log_cleanup(log);
+
+                /* populate new log */
+                rc = mgs_get_srpc_conf_log(mmd->mmd_fsdb, mmd->mmd_tgtname,
+                                           from, mmd->mmd_tgtpart, log);
+                if (rc) {
+                        mgs_msl_data_cleanup(mmd);
+                        break;
+                }
+
+                /* Overwrite the log */
+                rec->lrh_len = cfg_len; 
+                rc = llog_write_rec(llh, rec, NULL, 0, (void *)lcfg, 
+                                    rec->lrh_index);
+                if (rc)
+                        CERROR("overwrite sptlrpc conf log failed: %d\n", rc);
+
+                /* append new one */
+                rc = record_marker(mmd->mmd_obd, llh, mmd->mmd_fsdb, CM_START,
+                                   mmd->mmd_mti->mti_svname, "sptlrpc config");
+                rc = record_sptlrpc_conf(mmd->mmd_obd, llh,
+                                         lustre_cfg_string(lcfg, 0), log);
+                rc = record_marker(mmd->mmd_obd, llh, mmd->mmd_fsdb, CM_END,
+                                   mmd->mmd_mti->mti_svname, "sptlrpc config");
+
+                mgs_msl_data_cleanup(mmd);
+                break;
+        }
+        default:
+                /* ignore all others */
+                break;
+        }
+
+        RETURN(rc);
+}
+
+static int mgs_modify_srpc_log(struct obd_device *obd,
+                               struct fs_db *fsdb,
+                               struct mgs_target_info *mti,
+                               char *logname)
+{
+        struct llog_handle   *llh;
+        struct lvfs_run_ctxt  saved;
+        struct mgs_msl_data  *mmd;
+        int rc, rc2;
+        ENTRY;
+
+        CDEBUG(D_MGS, "modify sptlrpc log for %s\n", logname);
+
+        push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
+        
+        rc = llog_create(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
+                         &llh, NULL, logname);
+        if (rc)
+                GOTO(out_pop, rc);
+
+        rc = llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
+        if (rc)
+                GOTO(out_close, rc);
+
+        if (llog_get_size(llh) <= 1)
+                GOTO(out_close, rc = 0);
+
+        OBD_ALLOC_PTR(mmd);
+        if (!mmd) 
+                GOTO(out_close, rc = -ENOMEM);
+
+        mmd->mmd_obd = obd;
+        mmd->mmd_fsdb = fsdb;
+        mmd->mmd_mti = mti;
+
+        rc = llog_process(llh, mgs_modify_srpc_log_handler, (void *) mmd, NULL);
+
+        OBD_FREE_PTR(mmd);
+
+out_close:
+        rc2 = llog_close(llh);
+        if (!rc)
+                rc = rc2;
+
+out_pop:
+        pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
+        if (rc) 
+                CERROR("modify sptlrpc log %s failed %d\n", logname, rc);
+
+        RETURN(rc);
+}
+
+/*
+ * for each of log, remove old conf at first
+ */
+static int mgs_modify_srpc_log_all(struct obd_device *obd,
+                                   struct fs_db *fsdb,
+                                   struct mgs_target_info *mti)
+{
+        char             tgt_index[9];
+        char            *logname;
+        int              i, rc = 0, rc2;
+        ENTRY;
+
+        for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
+                if (test_bit(i,  fsdb->fsdb_mdt_index_map)) {
+                        sprintf(tgt_index,"-MDT%04x",i);
+
+                        name_create(&logname, mti->mti_fsname, tgt_index);
+                        rc2 = mgs_modify(obd, fsdb, mti, logname,
+                                         mti->mti_fsname, "sptlrpc config",
+                                         CM_SKIP);
+                        rc2 = mgs_modify_srpc_log(obd, fsdb, mti, logname);
+                        name_destroy(&logname);
+
+                        if (rc2 && rc == 0)
+                                rc = rc2;
+                }
+        }
+
+        for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
+                if (test_bit(i,  fsdb->fsdb_ost_index_map)) {
+                        sprintf(tgt_index,"-OST%04x",i);
+
+                        name_create(&logname, mti->mti_fsname, tgt_index);
+                        rc2 = mgs_modify(obd, fsdb, mti, logname,
+                                         mti->mti_fsname, "sptlrpc config",
+                                         CM_SKIP);
+                        rc2 = mgs_modify_srpc_log(obd, fsdb, mti, logname);
+                        name_destroy(&logname);
+
+                        if (rc2 && rc == 0)
+                                rc = rc2;
+                }
+        }
+
+        name_create(&logname, mti->mti_fsname, "-client");
+        rc2 = mgs_modify(obd, fsdb, mti, logname,
+                         mti->mti_fsname, "sptlrpc config", CM_SKIP);
+        rc2 = mgs_modify_srpc_log(obd, fsdb, mti, logname);
+        name_destroy(&logname);
+
+        if (rc2 && rc == 0)
+                rc = rc2;
+
+        RETURN(rc);
+}
+
+static int mgs_srpc_set_param_disk(struct obd_device *obd,
+                                   struct fs_db *fsdb,
+                                   struct mgs_target_info *mti,
+                                   char *param)
+{
+        struct llog_handle     *llh = NULL;
+        char                   *logname;
+        char                   *comment, *ptr;
+        struct lustre_cfg_bufs  bufs;
+        struct lustre_cfg      *lcfg;
+        int                     rc, len;
+        ENTRY;
+
+        /* get comment */
+        ptr = strchr(param, '=');
+        LASSERT(ptr);
+        len = ptr - param;
+
+        OBD_ALLOC(comment, len + 1);
+        if (comment == NULL)
+                RETURN(-ENOMEM);
+        strncpy(comment, param, len);
+        comment[len] = '\0';
+
+        /* prepare lcfg */
+        lustre_cfg_bufs_reset(&bufs, mti->mti_svname);
+        lustre_cfg_bufs_set_string(&bufs, 1, param);
+        lcfg = lustre_cfg_new(0, &bufs);
+        if (lcfg == NULL)
+                GOTO(out_comment, rc = -ENOMEM);
+
+        /* construct log name */
+        rc = name_create(&logname, mti->mti_fsname, "-sptlrpc");
+        if (rc)
+                GOTO(out_lcfg, rc);
+
+        if (mgs_log_is_empty(obd, logname)) {
+                rc = record_start_log(obd, &llh, logname);
+                record_end_log(obd, &llh);
+                if (rc) 
+                        GOTO(out, rc);
+        }
+
+        /* obsolete old one */
+        mgs_modify(obd, fsdb, mti, logname, mti->mti_svname, comment, CM_SKIP);
+
+        /* write the new one */
+        rc = mgs_write_log_direct(obd, fsdb, logname, lcfg,
+                                  mti->mti_svname, comment);
+        if (rc)
+                CERROR("err %d writing log %s\n", rc, logname);
+
+out:
+        name_destroy(&logname);
+out_lcfg:
+        lustre_cfg_free(lcfg);
+out_comment:
+        OBD_FREE(comment, len + 1);
+        RETURN(rc);
+}
+
+static int mgs_srpc_set_param_udesc_mem(struct fs_db *fsdb,
+                                        char *param)
+{
+        char    *ptr;
+
+        /* disable the adjustable udesc parameter for now, i.e. use default
+         * setting that client always ship udesc to MDT if possible. to enable
+         * it simply remove the following line */
+        goto error_out;
+
+        ptr = strchr(param, '=');
+        if (ptr == NULL)
+                goto error_out;
+        *ptr++ = '\0';
+
+        if (strcmp(param, PARAM_SRPC_UDESC))
+                goto error_out;
+
+        if (strcmp(ptr, "yes") == 0) {
+                fsdb->fsdb_srpc_fl_udesc = 1;
+                CWARN("Enable user descriptor shipping from client to MDT\n");
+        } else if (strcmp(ptr, "no") == 0) {
+                fsdb->fsdb_srpc_fl_udesc = 0;
+                CWARN("Disable user descriptor shipping from client to MDT\n");
+        } else {
+                *(ptr - 1) = '=';
+                goto error_out;
+        }
+        return 0;
+
+error_out:
+        CERROR("Invalid param: %s\n", param);
+        return -EINVAL;
+}
+
+static int mgs_srpc_set_param_mem(struct fs_db *fsdb,
+                                  const char *svname,
+                                  char *param)
+{
+        struct sptlrpc_rule      rule;
+        struct sptlrpc_rule_set *rset;
+        int                      rc;
+        ENTRY;
+
+        if (strncmp(param, PARAM_SRPC, sizeof(PARAM_SRPC) - 1) != 0) {
+                CERROR("Invalid sptlrpc parameter: %s\n", param);
+                RETURN(-EINVAL);
+        }
+
+        if (strncmp(param, PARAM_SRPC_UDESC,
+                    sizeof(PARAM_SRPC_UDESC) - 1) == 0) {
+                RETURN(mgs_srpc_set_param_udesc_mem(fsdb, param));
+        }
+
+        if (strncmp(param, PARAM_SRPC_FLVR, sizeof(PARAM_SRPC_FLVR) - 1) != 0) {
+                CERROR("Invalid sptlrpc flavor parameter: %s\n", param);
+                RETURN(-EINVAL);
+        }
+
+        param += sizeof(PARAM_SRPC_FLVR) - 1;
+
+        rc = sptlrpc_parse_rule(param, &rule);
+        if (rc)
+                RETURN(rc);
+
+        /* preapre room for this coming rule. svcname format should be:
+         * - fsname: general rule
+         * - fsname-tgtname: target-specific rule
+         */
+        if (strchr(svname, '-')) {
+                struct mgs_tgt_srpc_conf *tgtconf;
+                int                       found = 0;
+
+                for (tgtconf = fsdb->fsdb_srpc_tgt; tgtconf != NULL;
+                     tgtconf = tgtconf->mtsc_next) {
+                        if (!strcmp(tgtconf->mtsc_tgt, svname)) {
+                                found = 1;
+                                break;
+                        }
+                }
+
+                if (!found) {
+                        int name_len;
+
+                        OBD_ALLOC_PTR(tgtconf);
+                        if (tgtconf == NULL)
+                                RETURN(-ENOMEM);
+
+                        name_len = strlen(svname);
+
+                        OBD_ALLOC(tgtconf->mtsc_tgt, name_len + 1);
+                        if (tgtconf->mtsc_tgt == NULL) {
+                                OBD_FREE_PTR(tgtconf);
+                                RETURN(-ENOMEM);
+                        }
+                        memcpy(tgtconf->mtsc_tgt, svname, name_len);
+
+                        tgtconf->mtsc_next = fsdb->fsdb_srpc_tgt;
+                        fsdb->fsdb_srpc_tgt = tgtconf;
+                }
+
+                rset = &tgtconf->mtsc_rset;
+        } else {
+                rset = &fsdb->fsdb_srpc_gen;
+        }
+
+        /* limit the maximum number of rules, but allow deletion in any case */
+        if (rset->srs_nrule >= SPTLRPC_CONF_LOG_MAX / 2 &&
+            rule.sr_flvr.sf_rpc != SPTLRPC_FLVR_INVALID) {
+                CERROR("too many (%d) rules already for %s\n",
+                       rset->srs_nrule, svname);
+                RETURN(-E2BIG);
+        }
+
+        rc = sptlrpc_rule_set_merge(rset, &rule, 1);
+
+        RETURN(rc);
+}
+
+static int mgs_srpc_set_param(struct obd_device *obd,
+                              struct fs_db *fsdb,
+                              struct mgs_target_info *mti,
+                              char *param)
+{
+        char                    *copy;
+        int                      rc, copy_size;
+        ENTRY;
+
+        /* keep a copy of original param, which could be destroied
+         * during parsing */
+        copy_size = strlen(param) + 1;
+        OBD_ALLOC(copy, copy_size);
+        if (copy == NULL)
+                return -ENOMEM;
+        memcpy(copy, param, copy_size);
+
+        rc = mgs_srpc_set_param_mem(fsdb, mti->mti_svname, param);
+        if (rc)
+                goto out_free;
+
+        /* previous steps guaranteed the syntax is correct */
+        rc = mgs_srpc_set_param_disk(obd, fsdb, mti, copy);
+        if (rc)
+                goto out_free;
+
+        /* now apply the new rules to all existing config logs */
+        rc = mgs_modify_srpc_log_all(obd, fsdb, mti);
+
+out_free:
+        OBD_FREE(copy, copy_size);
+        RETURN(rc);
+}
+
+struct mgs_srpc_read_data {
+        struct fs_db   *msrd_fsdb;
+        int             msrd_skip;
+};
+
+static int mgs_srpc_read_handler(struct llog_handle *llh,
+                                 struct llog_rec_hdr *rec, 
+                                 void *data)
+{
+        struct mgs_srpc_read_data *msrd = (struct mgs_srpc_read_data *) data;
+        struct cfg_marker         *marker;
+        struct lustre_cfg         *lcfg = (struct lustre_cfg *)(rec + 1);
+        char                      *svname, *param;
+        int                        cfg_len, rc;
+        ENTRY;
+
+        if (rec->lrh_type != OBD_CFG_REC) {
+                CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
+                RETURN(-EINVAL);
+        }
+
+        cfg_len = rec->lrh_len - sizeof(struct llog_rec_hdr) - 
+                  sizeof(struct llog_rec_tail);
+
+        rc = lustre_cfg_sanity_check(lcfg, cfg_len);
+        if (rc) {
+                CERROR("Insane cfg\n");
+                RETURN(rc);
+        }
+
+        if (lcfg->lcfg_command == LCFG_MARKER) {
+                marker = lustre_cfg_buf(lcfg, 1);
+
+                if (marker->cm_flags & CM_START &&
+                    marker->cm_flags & CM_SKIP)
+                        msrd->msrd_skip = 1;
+                if (marker->cm_flags & CM_END)
+                        msrd->msrd_skip = 0;
+
+                RETURN(0);
+        }
+
+        if (msrd->msrd_skip)
+                RETURN(0);
+
+        if (lcfg->lcfg_command != 0) {
+                CERROR("invalid command (%x)\n", lcfg->lcfg_command);
+                RETURN(0);
+        }
+
+        svname = lustre_cfg_string(lcfg, 0);
+        if (svname == NULL) {
+                CERROR("svname is empty\n");
+                RETURN(0);
+        }
+
+        param = lustre_cfg_string(lcfg, 1);
+        if (param == NULL) {
+                CERROR("param is empty\n");
+                RETURN(0);
+        }
+
+        rc = mgs_srpc_set_param_mem(msrd->msrd_fsdb, svname, param);
+        if (rc)
+                CERROR("read sptlrpc record error (%d): %s\n", rc, param);
+
+        RETURN(0);
+}
+
+static int mgs_get_fsdb_srpc_from_llog(struct obd_device *obd,
+                                       struct fs_db *fsdb)
+{
+        struct llog_handle        *llh = NULL;
+        struct lvfs_run_ctxt       saved;
+        char                      *logname;
+        struct mgs_srpc_read_data  msrd;
+        int                        rc;
+        ENTRY;
+
+        /* construct log name */
+        rc = name_create(&logname, fsdb->fsdb_name, "-sptlrpc");
+        if (rc)
+                RETURN(rc);
+
+        if (mgs_log_is_empty(obd, logname))
+                GOTO(out, rc = 0);
+
+        push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
+
+        rc = llog_create(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
+                         &llh, NULL, logname);
+        if (rc)
+                GOTO(out_pop, rc);
+
+        rc = llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
+        if (rc)
+                GOTO(out_close, rc);
+
+        if (llog_get_size(llh) <= 1)
+                GOTO(out_close, rc = 0);
+
+        msrd.msrd_fsdb = fsdb;
+        msrd.msrd_skip = 0;
+
+        rc = llog_process(llh, mgs_srpc_read_handler, (void *) &msrd, NULL);
+
+out_close:
+        llog_close(llh);
+out_pop:
+        pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
+out:
+        name_destroy(&logname);
+
+        if (rc)
+                CERROR("failed to read sptlrpc config database: %d\n", rc);
+        RETURN(rc);
+}
+
 static int mgs_write_log_params(struct obd_device *obd, struct fs_db *fsdb,
                                 struct mgs_target_info *mti)
 {
 static int mgs_write_log_params(struct obd_device *obd, struct fs_db *fsdb,
                                 struct mgs_target_info *mti)
 {
@@ -1908,10 +2606,11 @@ static int mgs_write_log_params(struct obd_device *obd, struct fs_db *fsdb,
                         }
                         GOTO(end_while, rc);
                 }
                         }
                         GOTO(end_while, rc);
                 }
-                /* Processed in mgs_write_log_mdt/mgs_write_log_ost */
-                if (class_match_param(ptr, PARAM_SEC_RPC_MDT, NULL) == 0 ||
-                    class_match_param(ptr, PARAM_SEC_RPC_CLI, NULL) == 0)
+
+                if (class_match_param(ptr, PARAM_SRPC, NULL) == 0) {
+                        rc = mgs_srpc_set_param(obd, fsdb, mti, ptr);
                         GOTO(end_while, rc);
                         GOTO(end_while, rc);
+                }
 
                 if (class_match_param(ptr, PARAM_FAILNODE, NULL) == 0) {
                         /* Add a failover nidlist */
 
                 if (class_match_param(ptr, PARAM_FAILNODE, NULL) == 0) {
                         /* Add a failover nidlist */
index 11f93a0..eb16d75 100644 (file)
@@ -25,6 +25,7 @@ obdclass-all-objs += debug.o genops.o uuid.o llog_ioctl.o
 obdclass-all-objs += lprocfs_status.o lustre_handles.o lustre_peer.o
 obdclass-all-objs += statfs_pack.o obdo.o obd_config.o obd_mount.o mea.o
 obdclass-all-objs += lu_object.o dt_object.o hash.o capa.o lu_time.o
 obdclass-all-objs += lprocfs_status.o lustre_handles.o lustre_peer.o
 obdclass-all-objs += statfs_pack.o obdo.o obd_config.o obd_mount.o mea.o
 obdclass-all-objs += lu_object.o dt_object.o hash.o capa.o lu_time.o
+obdclass-all-objs += acl.o idmap.o
 
 obdclass-objs := $(obdclass-linux-objs) $(obdclass-all-objs)
 
 
 obdclass-objs := $(obdclass-linux-objs) $(obdclass-all-objs)
 
diff --git a/lustre/obdclass/acl.c b/lustre/obdclass/acl.c
new file mode 100644 (file)
index 0000000..d358f54
--- /dev/null
@@ -0,0 +1,832 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *   lustre/obdclass/acl.c
+ *   Lustre Access Control List.
+ *   Author: Fan Yong <fanyong@clusterfs.com>
+ *
+ * Copyright (c) 2004-2007 Cluster File Systems, Inc.
+ *
+ *   This file is part of Lustre, http://www.lustre.org.
+ *
+ *   Lustre is free software; you can redistribute it and/or
+ *   modify it under the terms of version 2 of the GNU General Public
+ *   License as published by the Free Software Foundation.
+ *
+ *   Lustre is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Lustre; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef EXPORT_SYMTAB
+# define EXPORT_SYMTAB
+#endif
+
+#define DEBUG_SUBSYSTEM S_SEC
+
+#include <linux/lustre_acl.h>
+#include <lustre_eacl.h>
+#include <obd_support.h>
+
+#ifdef CONFIG_FS_POSIX_ACL
+
+#define CFS_ACL_XATTR_VERSION POSIX_ACL_XATTR_VERSION
+
+enum {
+        ES_UNK  = 0,    /* unknown stat */
+        ES_UNC  = 1,    /* ACL entry is not changed */
+        ES_MOD  = 2,    /* ACL entry is modified */
+        ES_ADD  = 3,    /* ACL entry is added */
+        ES_DEL  = 4     /* ACL entry is deleted */
+};
+
+static inline void lustre_ext_acl_le_to_cpu(ext_acl_xattr_entry *d,
+                                            ext_acl_xattr_entry *s)
+{
+        d->e_tag        = le16_to_cpu(s->e_tag);
+        d->e_perm       = le16_to_cpu(s->e_perm);
+        d->e_id         = le32_to_cpu(s->e_id);
+        d->e_stat       = le32_to_cpu(s->e_stat);
+}
+
+static inline void lustre_ext_acl_cpu_to_le(ext_acl_xattr_entry *d,
+                                            ext_acl_xattr_entry *s)
+{
+        d->e_tag        = cpu_to_le16(s->e_tag);
+        d->e_perm       = cpu_to_le16(s->e_perm);
+        d->e_id         = cpu_to_le32(s->e_id);
+        d->e_stat       = cpu_to_le32(s->e_stat);
+}
+
+static inline void lustre_posix_acl_le_to_cpu(posix_acl_xattr_entry *d,
+                                              posix_acl_xattr_entry *s)
+{
+        d->e_tag        = le16_to_cpu(s->e_tag);
+        d->e_perm       = le16_to_cpu(s->e_perm);
+        d->e_id         = le32_to_cpu(s->e_id);
+}
+
+static inline void lustre_posix_acl_cpu_to_le(posix_acl_xattr_entry *d,
+                                              posix_acl_xattr_entry *s)
+{
+        d->e_tag        = cpu_to_le16(s->e_tag);
+        d->e_perm       = cpu_to_le16(s->e_perm);
+        d->e_id         = cpu_to_le32(s->e_id);
+}
+
+/*
+ * Check permission based on POSIX ACL.
+ */
+int lustre_posix_acl_permission(struct md_ucred *mu, struct lu_attr *la,
+                                int want, posix_acl_xattr_entry *entry,
+                                int count)
+{
+        posix_acl_xattr_entry *pa, *pe, *mask_obj;
+        posix_acl_xattr_entry ae, me;
+        int found = 0;
+
+        if (count <= 0)
+                return -EACCES;
+
+        for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
+                lustre_posix_acl_le_to_cpu(&ae, pa);
+                switch (ae.e_tag) {
+                case ACL_USER_OBJ:
+                        /* (May have been checked already) */
+                        if (la->la_uid == mu->mu_fsuid)
+                                goto check_perm;
+                        break;
+                case ACL_USER:
+                        if (ae.e_id == mu->mu_fsuid)
+                                goto mask;
+                        break;
+                case ACL_GROUP_OBJ:
+                        if (lustre_in_group_p(mu, la->la_gid)) {
+                                found = 1;
+                                if ((ae.e_perm & want) == want)
+                                        goto mask;
+                        }
+                        break;
+                case ACL_GROUP:
+                        if (lustre_in_group_p(mu, ae.e_id)) {
+                                found = 1;
+                                if ((ae.e_perm & want) == want)
+                                        goto mask;
+                        }
+                        break;
+                case ACL_MASK:
+                        break;
+                case ACL_OTHER:
+                        if (found)
+                                return -EACCES;
+                        else
+                                goto check_perm;
+                default:
+                        return -EIO;
+                }
+        }
+        return -EIO;
+
+mask:
+        for (mask_obj = pa + 1; mask_obj <= pe; mask_obj++) {
+                lustre_posix_acl_le_to_cpu(&me, mask_obj);
+                if (me.e_tag == ACL_MASK) {
+                        if ((ae.e_perm & me.e_perm & want) == want)
+                                return 0;
+
+                        return -EACCES;
+                }
+        }
+
+check_perm:
+        if ((ae.e_perm & want) == want)
+                return 0;
+
+        return -EACCES;
+}
+EXPORT_SYMBOL(lustre_posix_acl_permission);
+
+/*
+ * Modify the ACL for the chmod.
+ */
+int lustre_posix_acl_chmod_masq(posix_acl_xattr_entry *entry, __u32 mode,
+                                int count)
+{
+       posix_acl_xattr_entry *group_obj = NULL, *mask_obj = NULL, *pa, *pe;
+
+        for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
+               switch (le16_to_cpu(pa->e_tag)) {
+               case ACL_USER_OBJ:
+                       pa->e_perm = cpu_to_le16((mode & S_IRWXU) >> 6);
+                       break;
+               case ACL_USER:
+               case ACL_GROUP:
+                       break;
+               case ACL_GROUP_OBJ:
+                       group_obj = pa;
+                       break;
+               case ACL_MASK:
+                       mask_obj = pa;
+                       break;
+               case ACL_OTHER:
+                       pa->e_perm = cpu_to_le16(mode & S_IRWXO);
+                       break;
+               default:
+                       return -EIO;
+               }
+       }
+
+       if (mask_obj) {
+               mask_obj->e_perm = cpu_to_le16((mode & S_IRWXG) >> 3);
+       } else {
+               if (!group_obj)
+                       return -EIO;
+               group_obj->e_perm = cpu_to_le16((mode & S_IRWXG) >> 3);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(lustre_posix_acl_chmod_masq);
+
+/*
+ * Modify acl when creating a new object.
+ */
+int lustre_posix_acl_create_masq(posix_acl_xattr_entry *entry, __u32 *pmode,
+                                 int count)
+{
+        posix_acl_xattr_entry *group_obj = NULL, *mask_obj = NULL, *pa, *pe;
+        posix_acl_xattr_entry ae;
+       __u32 mode = *pmode;
+       int not_equiv = 0;
+
+        for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
+                lustre_posix_acl_le_to_cpu(&ae, pa);
+                switch (ae.e_tag) {
+                case ACL_USER_OBJ:
+                        ae.e_perm &= (mode >> 6) | ~S_IRWXO;
+                       pa->e_perm = cpu_to_le16(ae.e_perm);
+                       mode &= (ae.e_perm << 6) | ~S_IRWXU;
+                       break;
+               case ACL_USER:
+               case ACL_GROUP:
+                       not_equiv = 1;
+                       break;
+                case ACL_GROUP_OBJ:
+                       group_obj = pa;
+                        break;
+                case ACL_OTHER:
+                        ae.e_perm &= mode | ~S_IRWXO;
+                       pa->e_perm = cpu_to_le16(ae.e_perm);
+                       mode &= ae.e_perm | ~S_IRWXO;
+                        break;
+                case ACL_MASK:
+                       mask_obj = pa;
+                       not_equiv = 1;
+                        break;
+               default:
+                       return -EIO;
+                }
+        }
+
+       if (mask_obj) {
+               ae.e_perm = le16_to_cpu(mask_obj->e_perm) &
+                            ((mode >> 3) | ~S_IRWXO);
+               mode &= (ae.e_perm << 3) | ~S_IRWXG;
+                mask_obj->e_perm = cpu_to_le16(ae.e_perm);
+       } else {
+               if (!group_obj)
+                       return -EIO;
+               ae.e_perm = le16_to_cpu(group_obj->e_perm) &
+                            ((mode >> 3) | ~S_IRWXO);
+               mode &= (ae.e_perm << 3) | ~S_IRWXG;
+                group_obj->e_perm = cpu_to_le16(ae.e_perm);
+       }
+
+       *pmode = (*pmode & ~S_IRWXUGO) | mode;
+        return not_equiv;
+}
+EXPORT_SYMBOL(lustre_posix_acl_create_masq);
+
+/* if "new_count == 0", then "new = {a_version, NULL}", NOT NULL. */
+static int lustre_posix_acl_xattr_reduce_space(posix_acl_xattr_header **header,
+                                               int old_count, int new_count)
+{
+        int old_size = CFS_ACL_XATTR_SIZE(old_count, posix_acl_xattr);
+        int new_size = CFS_ACL_XATTR_SIZE(new_count, posix_acl_xattr);
+        posix_acl_xattr_header *new;
+
+        if (unlikely(old_count <= new_count))
+                return old_size;
+
+        OBD_ALLOC(new, new_size);
+        if (unlikely(new == NULL))
+                return -ENOMEM;
+
+        memcpy(new, *header, new_size);
+        OBD_FREE(*header, old_size);
+        *header = new;
+        return new_size;
+}
+
+/* if "new_count == 0", then "new = {0, NULL}", NOT NULL. */
+static int lustre_ext_acl_xattr_reduce_space(ext_acl_xattr_header **header,
+                                             int old_count)
+{
+        int ext_count = le32_to_cpu((*header)->a_count);
+        int ext_size = CFS_ACL_XATTR_SIZE(ext_count, ext_acl_xattr);
+        int old_size = CFS_ACL_XATTR_SIZE(old_count, ext_acl_xattr);
+        ext_acl_xattr_header *new;
+
+        if (unlikely(old_count <= ext_count))
+                return 0;
+
+        OBD_ALLOC(new, ext_size);
+        if (unlikely(new == NULL))
+                return -ENOMEM;
+
+        memcpy(new, *header, ext_size);
+        OBD_FREE(*header, old_size);
+        *header = new;
+        return 0;
+}
+
+/*
+ * Generate new extended ACL based on the posix ACL.
+ */
+ext_acl_xattr_header *
+lustre_posix_acl_xattr_2ext(posix_acl_xattr_header *header, int size)
+{
+        int count, i, esize;
+        ext_acl_xattr_header *new;
+        ENTRY;
+
+        if (unlikely(size < 0))
+                RETURN(ERR_PTR(-EINVAL));
+        else if (!size)
+                count = 0;
+        else
+                count = CFS_ACL_XATTR_COUNT(size, posix_acl_xattr);
+        esize = CFS_ACL_XATTR_SIZE(count, ext_acl_xattr);
+        OBD_ALLOC(new, esize);
+        if (unlikely(new == NULL))
+                RETURN(ERR_PTR(-ENOMEM));
+
+        new->a_count = cpu_to_le32(count);
+        for (i = 0; i < count; i++) {
+                new->a_entries[i].e_tag  = header->a_entries[i].e_tag;
+                new->a_entries[i].e_perm = header->a_entries[i].e_perm;
+                new->a_entries[i].e_id   = header->a_entries[i].e_id;
+                new->a_entries[i].e_stat = cpu_to_le32(ES_UNK);
+        }
+
+        RETURN(new);
+}
+EXPORT_SYMBOL(lustre_posix_acl_xattr_2ext);
+
+/*
+ * Filter out the "nobody" entries in the posix ACL.
+ */
+int lustre_posix_acl_xattr_filter(posix_acl_xattr_header *header, int size,
+                                  posix_acl_xattr_header **out)
+{
+        int count, i, j, rc = 0;
+        __u32 id;
+        posix_acl_xattr_header *new;
+        ENTRY;
+
+        if (unlikely(size < 0))
+                RETURN(-EINVAL);
+        else if (!size)
+                RETURN(0);
+
+        OBD_ALLOC(new, size);
+        if (unlikely(new == NULL))
+                RETURN(-ENOMEM);
+
+        new->a_version = cpu_to_le32(CFS_ACL_XATTR_VERSION);
+        count = CFS_ACL_XATTR_COUNT(size, posix_acl_xattr);
+        for (i = 0, j = 0; i < count; i++) {
+                id = le32_to_cpu(header->a_entries[i].e_id);
+                switch (le16_to_cpu(header->a_entries[i].e_tag)) {
+                case ACL_USER_OBJ:
+                case ACL_GROUP_OBJ:
+                case ACL_MASK:
+                case ACL_OTHER:
+                        if (id != ACL_UNDEFINED_ID)
+                                GOTO(_out, rc = -EIO);
+
+                        memcpy(&new->a_entries[j++], &header->a_entries[i],
+                               sizeof(posix_acl_xattr_entry));
+                        break;
+                case ACL_USER:
+                        if (id != NOBODY_UID)
+                                memcpy(&new->a_entries[j++],
+                                       &header->a_entries[i],
+                                       sizeof(posix_acl_xattr_entry));
+                        break;
+                case ACL_GROUP:
+                        if (id != NOBODY_GID)
+                                memcpy(&new->a_entries[j++],
+                                       &header->a_entries[i],
+                                       sizeof(posix_acl_xattr_entry));
+                        break;
+                default:
+                        GOTO(_out, rc = -EIO);
+                }
+        }
+
+        /* free unused space. */
+        rc = lustre_posix_acl_xattr_reduce_space(&new, count, j);
+        if (rc >= 0) {
+                size = rc;
+                *out = new;
+                rc = 0;
+        }
+        EXIT;
+
+_out:
+        if (rc) {
+                OBD_FREE(new, size);
+                size = rc;
+        }
+        return size;
+}
+EXPORT_SYMBOL(lustre_posix_acl_xattr_filter);
+
+/*
+ * Convert server-side uid/gid in the posix ACL items to the client-side ones.
+ * convert rule:
+ * @CFS_IC_NOTHING
+ *  nothing to be converted.
+ * @CFS_IC_ALL
+ *  mapped ids are converted to client-side ones,
+ *  unmapped ones are converted to "nobody".
+ * @CFS_IC_MAPPED
+ *  only mapped ids are converted to "nobody".
+ * @CFS_IC_UNMAPPED
+ *  only unmapped ids are converted to "nobody".
+ */
+int lustre_posix_acl_xattr_id2client(struct md_ucred *mu,
+                                     struct lustre_idmap_table *t,
+                                     posix_acl_xattr_header *header,
+                                     int size, int flags)
+{
+        int count, i;
+        __u32 id;
+        ENTRY;
+
+        if (unlikely(size < 0))
+                RETURN(-EINVAL);
+        else if (!size)
+                RETURN(0);
+
+        if (unlikely(flags == CFS_IC_NOTHING))
+                RETURN(0);
+
+        count = CFS_ACL_XATTR_COUNT(size, posix_acl_xattr);
+        for (i = 0; i < count; i++) {
+                id = le32_to_cpu(header->a_entries[i].e_id);
+                switch (le16_to_cpu(header->a_entries[i].e_tag)) {
+                case ACL_USER_OBJ:
+                case ACL_GROUP_OBJ:
+                case ACL_MASK:
+                case ACL_OTHER:
+                        if (id != ACL_UNDEFINED_ID)
+                                RETURN(-EIO);
+                        break;
+                case ACL_USER:
+                        id = lustre_idmap_lookup_uid(mu, t, 1, id);
+                        if (flags == CFS_IC_ALL) {
+                                if (id == CFS_IDMAP_NOTFOUND)
+                                        id = NOBODY_UID;
+                                header->a_entries[i].e_id = cpu_to_le32(id);
+                        } else if (flags == CFS_IC_MAPPED) {
+                                if (id != CFS_IDMAP_NOTFOUND)
+                                        header->a_entries[i].e_id =
+                                                        cpu_to_le32(NOBODY_UID);
+                        } else if (flags == CFS_IC_UNMAPPED) {
+                                if (id == CFS_IDMAP_NOTFOUND)
+                                        header->a_entries[i].e_id =
+                                                        cpu_to_le32(NOBODY_UID);
+                        }
+                        break;
+                case ACL_GROUP:
+                        id = lustre_idmap_lookup_gid(mu, t, 1, id);
+                        if (flags == CFS_IC_ALL) {
+                                if (id == CFS_IDMAP_NOTFOUND)
+                                        id = NOBODY_GID;
+                                header->a_entries[i].e_id = cpu_to_le32(id);
+                        } else if (flags == CFS_IC_MAPPED) {
+                                if (id != CFS_IDMAP_NOTFOUND)
+                                        header->a_entries[i].e_id =
+                                                        cpu_to_le32(NOBODY_GID);
+                        } else if (flags == CFS_IC_UNMAPPED) {
+                                if (id == CFS_IDMAP_NOTFOUND)
+                                        header->a_entries[i].e_id =
+                                                        cpu_to_le32(NOBODY_GID);
+                        }
+                        break;
+                 default:
+                        RETURN(-EIO);
+                }
+        }
+    RETURN(0);
+}
+EXPORT_SYMBOL(lustre_posix_acl_xattr_id2client);
+
+/*
+ * Release the posix ACL space.
+ */
+void lustre_posix_acl_xattr_free(posix_acl_xattr_header *header, int size)
+{
+        OBD_FREE(header, size);
+}
+EXPORT_SYMBOL(lustre_posix_acl_xattr_free);
+
+/*
+ * Converts client-side uid/gid in the extended ACL items to server-side ones.
+ * convert rule:
+ *  mapped ids are converted to server-side ones,
+ *  unmapped ones cause "EPERM" error.
+ */
+int lustre_ext_acl_xattr_id2server(struct md_ucred *mu,
+                                   struct lustre_idmap_table *t,
+                                   ext_acl_xattr_header *header)
+
+{
+        int i, count = le32_to_cpu(header->a_count);
+        __u32 id;
+        ENTRY;
+
+        for (i = 0; i < count; i++) {
+                id = le32_to_cpu(header->a_entries[i].e_id);
+                switch (le16_to_cpu(header->a_entries[i].e_tag)) {
+                case ACL_USER_OBJ:
+                case ACL_GROUP_OBJ:
+                case ACL_MASK:
+                case ACL_OTHER:
+                        if (id != ACL_UNDEFINED_ID)
+                                RETURN(-EIO);
+                        break;
+                case ACL_USER:
+                        id = lustre_idmap_lookup_uid(mu, t, 0, id);
+                        if (id == CFS_IDMAP_NOTFOUND)
+                                RETURN(-EPERM);
+                        else
+                                header->a_entries[i].e_id = cpu_to_le32(id);
+                        break;
+                case ACL_GROUP:
+                        id = lustre_idmap_lookup_gid(mu, t, 0, id);
+                        if (id == CFS_IDMAP_NOTFOUND)
+                                RETURN(-EPERM);
+                        else
+                                header->a_entries[i].e_id = cpu_to_le32(id);
+                        break;
+                default:
+                        RETURN(-EIO);
+                }
+        }
+        RETURN(0);
+}
+EXPORT_SYMBOL(lustre_ext_acl_xattr_id2server);
+
+/*
+ * Release the extended ACL space.
+ */
+void lustre_ext_acl_xattr_free(ext_acl_xattr_header *header)
+{
+        OBD_FREE(header, CFS_ACL_XATTR_SIZE(le32_to_cpu(header->a_count), \
+                                            ext_acl_xattr));
+}
+EXPORT_SYMBOL(lustre_ext_acl_xattr_free);
+
+static ext_acl_xattr_entry *
+lustre_ext_acl_xattr_search(ext_acl_xattr_header *header,
+                            posix_acl_xattr_entry *entry, int *pos)
+{
+        int once, start, end, i, j, count = le32_to_cpu(header->a_count);
+
+        once = 0;
+        start = *pos;
+        end = count;
+
+again:
+        for (i = start; i < end; i++) {
+                if (header->a_entries[i].e_tag == entry->e_tag &&
+                    header->a_entries[i].e_id == entry->e_id) {
+                        j = i;
+                        if (++i >= count)
+                                i = 0;
+                        *pos = i;
+                        return &header->a_entries[j];
+                }
+        }
+
+        if (!once) {
+                once = 1;
+                start = 0;
+                end = *pos;
+                goto again;
+        }
+
+        return NULL;
+}
+
+/*
+ * Merge the posix ACL and the extended ACL into new posix ACL.
+ */
+int lustre_acl_xattr_merge2posix(posix_acl_xattr_header *posix_header, int size,
+                                 ext_acl_xattr_header *ext_header,
+                                 posix_acl_xattr_header **out)
+{
+        int posix_count, posix_size, i, j;
+        int ext_count = le32_to_cpu(ext_header->a_count), pos = 0, rc = 0;
+        posix_acl_xattr_entry pe = {ACL_MASK, 0, ACL_UNDEFINED_ID};
+        posix_acl_xattr_header *new;
+        ext_acl_xattr_entry *ee, ae;
+        ENTRY;
+
+        lustre_posix_acl_cpu_to_le(&pe, &pe);
+        ee = lustre_ext_acl_xattr_search(ext_header, &pe, &pos);
+        if (ee == NULL || le32_to_cpu(ee->e_stat) == ES_DEL) {
+                /* there are only base ACL entries at most. */
+                posix_count = 3;
+                posix_size = CFS_ACL_XATTR_SIZE(posix_count, posix_acl_xattr);
+                OBD_ALLOC(new, posix_size);
+                if (unlikely(new == NULL))
+                        RETURN(-ENOMEM);
+
+                new->a_version = cpu_to_le32(CFS_ACL_XATTR_VERSION);
+                for (i = 0, j = 0; i < ext_count; i++) {
+                        lustre_ext_acl_le_to_cpu(&ae,
+                                                 &ext_header->a_entries[i]);
+                        switch (ae.e_tag) {
+                        case ACL_USER_OBJ:
+                        case ACL_GROUP_OBJ:
+                        case ACL_OTHER:
+                                if (ae.e_id != ACL_UNDEFINED_ID)
+                                        GOTO(_out, rc = -EIO);
+
+                                if (ae.e_stat != ES_DEL) {
+                                        new->a_entries[j].e_tag =
+                                                ext_header->a_entries[i].e_tag;
+                                        new->a_entries[j].e_perm =
+                                                ext_header->a_entries[i].e_perm;
+                                        new->a_entries[j++].e_id =
+                                                ext_header->a_entries[i].e_id;
+                                }
+                                break;
+                        case ACL_MASK:
+                        case ACL_USER:
+                        case ACL_GROUP:
+                                if (ae.e_stat == ES_DEL)
+                                        break;
+                        default:
+                                GOTO(_out, rc = -EIO);
+                        }
+                }
+        } else {
+                /* maybe there are valid ACL_USER or ACL_GROUP entries in the
+                 * original server-side ACL, they are regarded as ES_UNC stat.*/
+                int ori_posix_count;
+
+                if (unlikely(size < 0))
+                        RETURN(-EINVAL);
+                else if (!size)
+                        ori_posix_count = 0;
+                else
+                        ori_posix_count =
+                                CFS_ACL_XATTR_COUNT(size, posix_acl_xattr);
+                posix_count = ori_posix_count + ext_count;
+                posix_size =
+                        CFS_ACL_XATTR_SIZE(posix_count, posix_acl_xattr);
+                OBD_ALLOC(new, posix_size);
+                if (unlikely(new == NULL))
+                        RETURN(-ENOMEM);
+
+                new->a_version = cpu_to_le32(CFS_ACL_XATTR_VERSION);
+                /* 1. process the unchanged ACL entries
+                 *    in the original server-side ACL. */
+                pos = 0;
+                for (i = 0, j = 0; i < ori_posix_count; i++) {
+                        ee = lustre_ext_acl_xattr_search(ext_header,
+                                        &posix_header->a_entries[i], &pos);
+                        if (ee == NULL)
+                                memcpy(&new->a_entries[j++],
+                                       &posix_header->a_entries[i],
+                                       sizeof(posix_acl_xattr_entry));
+                }
+
+                /* 2. process the non-deleted entries
+                 *    from client-side extended ACL. */
+                for (i = 0; i < ext_count; i++) {
+                        if (le16_to_cpu(ext_header->a_entries[i].e_stat) !=
+                            ES_DEL) {
+                                new->a_entries[j].e_tag =
+                                                ext_header->a_entries[i].e_tag;
+                                new->a_entries[j].e_perm =
+                                                ext_header->a_entries[i].e_perm;
+                                new->a_entries[j++].e_id =
+                                                ext_header->a_entries[i].e_id;
+                        }
+                }
+        }
+
+        /* free unused space. */
+        rc = lustre_posix_acl_xattr_reduce_space(&new, posix_count, j);
+        if (rc >= 0) {
+                posix_size = rc;
+                *out = new;
+                rc = 0;
+        }
+        EXIT;
+
+_out:
+        if (rc) {
+                OBD_FREE(new, posix_size);
+                posix_size = rc;
+        }
+        return posix_size;
+}
+EXPORT_SYMBOL(lustre_acl_xattr_merge2posix);
+
+/*
+ * Merge the posix ACL and the extended ACL into new extended ACL.
+ */
+ext_acl_xattr_header *
+lustre_acl_xattr_merge2ext(posix_acl_xattr_header *posix_header, int size,
+                           ext_acl_xattr_header *ext_header)
+{
+        int ori_ext_count, posix_count, ext_count, ext_size;
+        int i, j, pos = 0, rc = 0;
+        posix_acl_xattr_entry pae;
+        ext_acl_xattr_header *new;
+        ext_acl_xattr_entry *ee, eae;
+        ENTRY;
+
+        if (unlikely(size < 0))
+                RETURN(ERR_PTR(-EINVAL));
+        else if (!size)
+                posix_count = 0;
+        else
+                posix_count = CFS_ACL_XATTR_COUNT(size, posix_acl_xattr);
+        ori_ext_count = le32_to_cpu(ext_header->a_count);
+        ext_count = posix_count + ori_ext_count;
+        ext_size = CFS_ACL_XATTR_SIZE(ext_count, ext_acl_xattr);
+
+        OBD_ALLOC(new, ext_size);
+        if (unlikely(new == NULL))
+                RETURN(ERR_PTR(-ENOMEM));
+
+        for (i = 0, j = 0; i < posix_count; i++) {
+                lustre_posix_acl_le_to_cpu(&pae, &posix_header->a_entries[i]);
+                switch (pae.e_tag) {
+                case ACL_USER_OBJ:
+                case ACL_GROUP_OBJ:
+                case ACL_MASK:
+                case ACL_OTHER:
+                        if (pae.e_id != ACL_UNDEFINED_ID)
+                                GOTO(out, rc = -EIO);
+                case ACL_USER:
+                        /* ignore "nobody" entry. */
+                        if (pae.e_id == NOBODY_UID)
+                                break;
+
+                        new->a_entries[j].e_tag =
+                                        posix_header->a_entries[i].e_tag;
+                        new->a_entries[j].e_perm =
+                                        posix_header->a_entries[i].e_perm;
+                        new->a_entries[j].e_id =
+                                        posix_header->a_entries[i].e_id;
+                        ee = lustre_ext_acl_xattr_search(ext_header,
+                                        &posix_header->a_entries[i], &pos);
+                        if (ee) {
+                                if (posix_header->a_entries[i].e_perm !=
+                                                                ee->e_perm)
+                                        /* entry modified. */
+                                        ee->e_perm =
+                                        new->a_entries[j++].e_stat =
+                                                        cpu_to_le32(ES_MOD);
+                                else
+                                        /* entry unchanged. */
+                                        ee->e_perm =
+                                        new->a_entries[j++].e_stat =
+                                                        cpu_to_le32(ES_UNC);
+                        } else {
+                                /* new entry. */
+                                new->a_entries[j++].e_stat =
+                                                        cpu_to_le32(ES_ADD);
+                        }
+                        break;
+                case ACL_GROUP:
+                        /* ignore "nobody" entry. */
+                        if (pae.e_id == NOBODY_GID)
+                                break;
+                        new->a_entries[j].e_tag =
+                                        posix_header->a_entries[i].e_tag;
+                        new->a_entries[j].e_perm =
+                                        posix_header->a_entries[i].e_perm;
+                        new->a_entries[j].e_id =
+                                        posix_header->a_entries[i].e_id;
+                        ee = lustre_ext_acl_xattr_search(ext_header,
+                                        &posix_header->a_entries[i], &pos);
+                        if (ee) {
+                                if (posix_header->a_entries[i].e_perm !=
+                                                                ee->e_perm)
+                                        /* entry modified. */
+                                        ee->e_perm =
+                                        new->a_entries[j++].e_stat =
+                                                        cpu_to_le32(ES_MOD);
+                                else
+                                        /* entry unchanged. */
+                                        ee->e_perm =
+                                        new->a_entries[j++].e_stat =
+                                                        cpu_to_le32(ES_UNC);
+                        } else {
+                                /* new entry. */
+                                new->a_entries[j++].e_stat =
+                                                        cpu_to_le32(ES_ADD);
+                        }
+                        break;
+                default:
+                        GOTO(out, rc = -EIO);
+                }
+        }
+
+        /* process deleted entries. */
+        for (i = 0; i < ori_ext_count; i++) {
+                lustre_ext_acl_le_to_cpu(&eae, &ext_header->a_entries[i]);
+                if (eae.e_stat == ES_UNK) {
+                        /* ignore "nobody" entry. */
+                        if ((eae.e_tag == ACL_USER && eae.e_id == NOBODY_UID) ||
+                            (eae.e_tag == ACL_GROUP && eae.e_id == NOBODY_GID))
+                                continue;
+
+                        new->a_entries[j].e_tag =
+                                                ext_header->a_entries[i].e_tag;
+                        new->a_entries[j].e_perm =
+                                                ext_header->a_entries[i].e_perm;
+                        new->a_entries[j].e_id = ext_header->a_entries[i].e_id;
+                        new->a_entries[j++].e_stat = cpu_to_le32(ES_DEL);
+                }
+        }
+
+        new->a_count = cpu_to_le32(j);
+        /* free unused space. */
+        rc = lustre_ext_acl_xattr_reduce_space(&new, ext_count);
+        EXIT;
+
+out:
+        if (rc) {
+                OBD_FREE(new, ext_size);
+                new = ERR_PTR(rc);
+        }
+        return new;
+}
+EXPORT_SYMBOL(lustre_acl_xattr_merge2ext);
+
+#endif
index ab15541..25d12e4 100644 (file)
@@ -713,6 +713,8 @@ struct obd_export *class_new_export(struct obd_device *obd,
         INIT_HLIST_NODE(&export->exp_uuid_hash);
         INIT_HLIST_NODE(&export->exp_nid_hash);
 
         INIT_HLIST_NODE(&export->exp_uuid_hash);
         INIT_HLIST_NODE(&export->exp_nid_hash);
 
+        export->exp_sp_peer = LUSTRE_SP_ANY;
+        export->exp_flvr.sf_rpc = SPTLRPC_FLVR_INVALID;
         export->exp_client_uuid = *cluuid;
         obd_init_export(export);
 
         export->exp_client_uuid = *cluuid;
         obd_init_export(export);
 
@@ -848,6 +850,7 @@ struct obd_import *class_new_import(struct obd_device *obd)
         imp->imp_last_success_conn = 0;
         imp->imp_state = LUSTRE_IMP_NEW;
         imp->imp_obd = class_incref(obd);
         imp->imp_last_success_conn = 0;
         imp->imp_state = LUSTRE_IMP_NEW;
         imp->imp_obd = class_incref(obd);
+        sema_init(&imp->imp_sec_mutex, 1);
         cfs_waitq_init(&imp->imp_recovery_waitq);
 
         atomic_set(&imp->imp_refcount, 2);
         cfs_waitq_init(&imp->imp_recovery_waitq);
 
         atomic_set(&imp->imp_refcount, 2);
diff --git a/lustre/obdclass/idmap.c b/lustre/obdclass/idmap.c
new file mode 100644 (file)
index 0000000..9f85b98
--- /dev/null
@@ -0,0 +1,458 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *   lustre/obdclass/idmap.c
+ *   Lustre user identity mapping.
+ *   Author: Fan Yong <fanyong@clusterfs.com>
+ *
+ * Copyright (C) 2004-2007 Cluster File Systems, Inc.
+ *
+ *
+ *   This file is part of Lustre, http://www.lustre.org.
+ *
+ *   Lustre is free software; you can redistribute it and/or
+ *   modify it under the terms of version 2 of the GNU General Public
+ *   License as published by the Free Software Foundation.
+ *
+ *   Lustre is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Lustre; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef EXPORT_SYMTAB
+# define EXPORT_SYMTAB
+#endif
+
+#define DEBUG_SUBSYSTEM S_SEC
+
+#include <lustre_idmap.h>
+#include <obd_support.h>
+
+#define lustre_get_group_info(group_info) do {             \
+        atomic_inc(&(group_info)->usage);                  \
+} while (0)
+
+#define lustre_put_group_info(group_info) do {             \
+        if (atomic_dec_and_test(&(group_info)->usage))     \
+                groups_free(group_info);                   \
+} while (0)
+
+/*
+ * groups_search() is copied from linux kernel!
+ * A simple bsearch.
+ */
+static int lustre_groups_search(struct group_info *group_info, gid_t grp)
+{
+        int left, right;
+
+        if (!group_info)
+                return 0;
+
+        left = 0;
+        right = group_info->ngroups;
+        while (left < right) {
+                int mid = (left + right) / 2;
+                int cmp = grp - CFS_GROUP_AT(group_info, mid);
+
+                if (cmp > 0)
+                        left = mid + 1;
+                else if (cmp < 0)
+                        right = mid;
+                else
+                        return 1;
+        }
+        return 0;
+}
+
+void lustre_groups_from_list(struct group_info *ginfo, gid_t *glist)
+{
+        int i;
+        int count = ginfo->ngroups;
+
+        /* fill group_info from gid array */
+        for (i = 0; i < ginfo->nblocks && count > 0; i++) {
+                int cp_count = min(CFS_NGROUPS_PER_BLOCK, count);
+                int off = i * CFS_NGROUPS_PER_BLOCK;
+                int len = cp_count * sizeof(*glist);
+
+                memcpy(ginfo->blocks[i], glist + off, len);
+                count -= cp_count;
+        }
+}
+EXPORT_SYMBOL(lustre_groups_from_list);
+
+/* groups_sort() is copied from linux kernel! */
+/* a simple shell-metzner sort */
+void lustre_groups_sort(struct group_info *group_info)
+{
+        int base, max, stride;
+        int gidsetsize = group_info->ngroups;
+
+        for (stride = 1; stride < gidsetsize; stride = 3 * stride + 1)
+                ; /* nothing */
+        stride /= 3;
+
+        while (stride) {
+                max = gidsetsize - stride;
+                for (base = 0; base < max; base++) {
+                        int left = base;
+                        int right = left + stride;
+                        gid_t tmp = CFS_GROUP_AT(group_info, right);
+
+                        while (left >= 0 &&
+                               CFS_GROUP_AT(group_info, left) > tmp) {
+                                CFS_GROUP_AT(group_info, right) =
+                                    CFS_GROUP_AT(group_info, left);
+                                right = left;
+                                left -= stride;
+                        }
+                        CFS_GROUP_AT(group_info, right) = tmp;
+                }
+                stride /= 3;
+        }
+}
+EXPORT_SYMBOL(lustre_groups_sort);
+
+int lustre_in_group_p(struct md_ucred *mu, gid_t grp)
+{
+        int rc = 1;
+
+        if (grp != mu->mu_fsgid) {
+                struct group_info *group_info = NULL;
+
+                if (mu->mu_ginfo || !mu->mu_identity ||
+                    mu->mu_valid == UCRED_OLD)
+                        if (grp == mu->mu_suppgids[0] ||
+                            grp == mu->mu_suppgids[1])
+                                return 1;
+
+                if (mu->mu_ginfo)
+                        group_info = mu->mu_ginfo;
+                else if (mu->mu_identity)
+                        group_info = mu->mu_identity->mi_ginfo;
+
+                if (!group_info)
+                        return 0;
+
+                lustre_get_group_info(group_info);
+                rc = lustre_groups_search(group_info, grp);
+                lustre_put_group_info(group_info);
+        }
+        return rc;
+}
+EXPORT_SYMBOL(lustre_in_group_p);
+
+struct lustre_idmap_entry {
+        struct list_head lie_rmt_uid_hash; /* hashed as lie_rmt_uid; */
+        struct list_head lie_lcl_uid_hash; /* hashed as lie_lcl_uid; */
+        struct list_head lie_rmt_gid_hash; /* hashed as lie_rmt_gid; */
+        struct list_head lie_lcl_gid_hash; /* hashed as lie_lcl_gid; */
+        uid_t            lie_rmt_uid;      /* remote uid */
+        uid_t            lie_lcl_uid;      /* local uid */
+        gid_t            lie_rmt_gid;      /* remote gid */
+        gid_t            lie_lcl_gid;      /* local gid */
+};
+
+static inline __u32 lustre_idmap_hashfunc(__u32 id)
+{
+        return id & (CFS_IDMAP_HASHSIZE - 1);
+}
+
+static
+struct lustre_idmap_entry *idmap_entry_alloc(uid_t rmt_uid, uid_t lcl_uid,
+                                             gid_t rmt_gid, gid_t lcl_gid)
+{
+        struct lustre_idmap_entry *e;
+
+        OBD_ALLOC_PTR(e);
+        if (e == NULL)
+                return NULL;
+
+        INIT_LIST_HEAD(&e->lie_rmt_uid_hash);
+        INIT_LIST_HEAD(&e->lie_lcl_uid_hash);
+        INIT_LIST_HEAD(&e->lie_rmt_gid_hash);
+        INIT_LIST_HEAD(&e->lie_lcl_gid_hash);
+        e->lie_rmt_uid = rmt_uid;
+        e->lie_lcl_uid = lcl_uid;
+        e->lie_rmt_gid = rmt_gid;
+        e->lie_lcl_gid = lcl_gid;
+
+        return e;
+}
+
+static void idmap_entry_free(struct lustre_idmap_entry *e)
+{
+        if (!list_empty(&e->lie_rmt_uid_hash))
+                list_del(&e->lie_rmt_uid_hash);
+        if (!list_empty(&e->lie_lcl_uid_hash))
+                list_del(&e->lie_lcl_uid_hash);
+        if (!list_empty(&e->lie_rmt_gid_hash))
+                list_del(&e->lie_rmt_gid_hash);
+        if (!list_empty(&e->lie_lcl_gid_hash))
+                list_del(&e->lie_lcl_gid_hash);
+        OBD_FREE_PTR(e);
+}
+
+/*
+ * return value
+ * NULL: not found entry
+ * ERR_PTR(-EACCES): found 1(remote):N(local) mapped entry
+ * others: found normal entry
+ */
+static
+struct lustre_idmap_entry *idmap_search_entry(struct lustre_idmap_table *t,
+                                              uid_t rmt_uid, uid_t lcl_uid,
+                                              gid_t rmt_gid, gid_t lcl_gid)
+{
+        struct list_head *head;
+        struct lustre_idmap_entry *e;
+
+        head = &t->lit_idmaps[RMT_UIDMAP_IDX][lustre_idmap_hashfunc(rmt_uid)];
+        list_for_each_entry(e, head, lie_rmt_uid_hash)
+                if (e->lie_rmt_uid == rmt_uid) {
+                        if (e->lie_lcl_uid == lcl_uid) {
+                                if (e->lie_rmt_gid == rmt_gid &&
+                                    e->lie_lcl_gid == lcl_gid)
+                                        /* must be quaternion match */
+                                        return e;
+                        } else {
+                                /* 1:N uid mapping */
+                                CERROR("rmt uid %u already be mapped to %u"
+                                       " (new %u)\n", e->lie_rmt_uid,
+                                       e->lie_lcl_uid, lcl_uid);
+                                return ERR_PTR(-EACCES);
+                        }
+                }
+
+        head = &t->lit_idmaps[RMT_GIDMAP_IDX][lustre_idmap_hashfunc(rmt_gid)];
+        list_for_each_entry(e, head, lie_rmt_gid_hash)
+                if (e->lie_rmt_gid == rmt_gid) {
+                        if (e->lie_lcl_gid == lcl_gid) {
+                                if (unlikely(e->lie_rmt_uid == rmt_uid &&
+                                    e->lie_lcl_uid == lcl_uid))
+                                        /* after uid mapping search above,
+                                         * we should never come here */
+                                        LBUG();
+                        } else {
+                                /* 1:N gid mapping */
+                                CERROR("rmt gid %u already be mapped to %u"
+                                       " (new %u)\n", e->lie_rmt_gid,
+                                       e->lie_lcl_gid, lcl_gid);
+                                return ERR_PTR(-EACCES);
+                        }
+                }
+
+        return NULL;
+}
+
+static __u32 idmap_lookup_uid(struct list_head *hash, int reverse, __u32 uid)
+{
+        struct list_head *head = &hash[lustre_idmap_hashfunc(uid)];
+        struct lustre_idmap_entry *e;
+
+        if (!reverse) {
+                list_for_each_entry(e, head, lie_rmt_uid_hash)
+                        if (e->lie_rmt_uid == uid)
+                                return e->lie_lcl_uid;
+        } else {
+                list_for_each_entry(e, head, lie_lcl_uid_hash)
+                        if (e->lie_lcl_uid == uid)
+                                return e->lie_rmt_uid;
+        }
+
+        return CFS_IDMAP_NOTFOUND;
+}
+
+static __u32 idmap_lookup_gid(struct list_head *hash, int reverse, __u32 gid)
+{
+        struct list_head *head = &hash[lustre_idmap_hashfunc(gid)];
+        struct lustre_idmap_entry *e;
+
+        if (!reverse) {
+                list_for_each_entry(e, head, lie_rmt_gid_hash)
+                        if (e->lie_rmt_gid == gid)
+                                return e->lie_lcl_gid;
+        } else {
+                list_for_each_entry(e, head, lie_lcl_gid_hash)
+                        if (e->lie_lcl_gid == gid)
+                                return e->lie_rmt_gid;
+        }
+
+        return CFS_IDMAP_NOTFOUND;
+}
+
+int lustre_idmap_add(struct lustre_idmap_table *t,
+                     uid_t ruid, uid_t luid,
+                     gid_t rgid, gid_t lgid)
+{
+        struct lustre_idmap_entry *e0, *e1;
+
+        LASSERT(t);
+
+        spin_lock(&t->lit_lock);
+        e0 = idmap_search_entry(t, ruid, luid, rgid, lgid);
+        spin_unlock(&t->lit_lock);
+        if (!e0) {
+                e0 = idmap_entry_alloc(ruid, luid, rgid, lgid);
+                if (!e0)
+                        return -ENOMEM;
+
+                spin_lock(&t->lit_lock);
+                e1 = idmap_search_entry(t, ruid, luid, rgid, lgid);
+                if (e1 == NULL) {
+                        list_add_tail(&e0->lie_rmt_uid_hash,
+                                      &t->lit_idmaps[RMT_UIDMAP_IDX]
+                                        [lustre_idmap_hashfunc(ruid)]);
+                        list_add_tail(&e0->lie_lcl_uid_hash,
+                                      &t->lit_idmaps[LCL_UIDMAP_IDX]
+                                        [lustre_idmap_hashfunc(luid)]);
+                        list_add_tail(&e0->lie_rmt_gid_hash,
+                                      &t->lit_idmaps[RMT_GIDMAP_IDX]
+                                        [lustre_idmap_hashfunc(rgid)]);
+                        list_add_tail(&e0->lie_lcl_gid_hash,
+                                      &t->lit_idmaps[LCL_GIDMAP_IDX]
+                                        [lustre_idmap_hashfunc(lgid)]);
+                } 
+                spin_unlock(&t->lit_lock);
+                if (e1 != NULL) {
+                        idmap_entry_free(e0);
+                        if (IS_ERR(e1))
+                                return PTR_ERR(e1);
+                }
+        } else if (IS_ERR(e0)) {
+                return PTR_ERR(e0);
+        }
+
+        return 0;
+}
+EXPORT_SYMBOL(lustre_idmap_add);
+
+int lustre_idmap_del(struct lustre_idmap_table *t,
+                    uid_t ruid, uid_t luid,
+                    gid_t rgid, gid_t lgid)
+{
+        struct lustre_idmap_entry *e;
+        int rc = 0;
+
+        LASSERT(t);
+
+        spin_lock(&t->lit_lock);
+        e = idmap_search_entry(t, ruid, luid, rgid, lgid);
+        if (IS_ERR(e))
+                rc = PTR_ERR(e);
+        else if (e)
+                idmap_entry_free(e);
+        spin_unlock(&t->lit_lock);
+
+        return rc;
+}
+EXPORT_SYMBOL(lustre_idmap_del);
+
+int lustre_idmap_lookup_uid(struct md_ucred *mu,
+                            struct lustre_idmap_table *t,
+                            int reverse, uid_t uid)
+{
+        struct list_head *hash;
+
+        if (mu && (mu->mu_valid == UCRED_OLD || mu->mu_valid == UCRED_NEW)) {
+                if (!reverse) {
+                        if (uid == mu->mu_o_uid)
+                                return mu->mu_uid;
+                        else if (uid == mu->mu_o_fsuid)
+                                return mu->mu_fsuid;
+                } else {
+                        if (uid == mu->mu_uid)
+                                return mu->mu_o_uid;
+                        else if (uid == mu->mu_fsuid)
+                                return mu->mu_o_fsuid;
+                }
+        }
+
+        if (t == NULL)
+                return CFS_IDMAP_NOTFOUND;
+
+        hash = t->lit_idmaps[reverse ? LCL_UIDMAP_IDX : RMT_UIDMAP_IDX];
+
+        spin_lock(&t->lit_lock);
+        uid = idmap_lookup_uid(hash, reverse, uid);
+        spin_unlock(&t->lit_lock);
+
+        return uid;
+}
+EXPORT_SYMBOL(lustre_idmap_lookup_uid);
+
+int lustre_idmap_lookup_gid(struct md_ucred *mu, struct lustre_idmap_table *t,
+                            int reverse, gid_t gid)
+{
+        struct list_head *hash;
+
+        if (mu && (mu->mu_valid == UCRED_OLD || mu->mu_valid == UCRED_NEW)) {
+                if (!reverse) {
+                        if (gid == mu->mu_o_gid)
+                                return mu->mu_gid;
+                        else if (gid == mu->mu_o_fsgid)
+                                return mu->mu_fsgid;
+                } else {
+                        if (gid == mu->mu_gid)
+                                return mu->mu_o_gid;
+                        else if (gid == mu->mu_fsgid)
+                                return mu->mu_o_fsgid;
+                }
+        }
+
+        if (t == NULL)
+                return CFS_IDMAP_NOTFOUND;
+
+        hash = t->lit_idmaps[reverse ? LCL_GIDMAP_IDX : RMT_GIDMAP_IDX];
+
+        spin_lock(&t->lit_lock);
+        gid = idmap_lookup_gid(hash, reverse, gid);
+        spin_unlock(&t->lit_lock);
+
+        return gid;
+}
+EXPORT_SYMBOL(lustre_idmap_lookup_gid);
+
+struct lustre_idmap_table *lustre_idmap_init(void)
+{
+        struct lustre_idmap_table *t;
+        int i, j;
+
+        OBD_ALLOC_PTR(t);
+        if(unlikely(t == NULL))
+                return (ERR_PTR(-ENOMEM));
+
+        spin_lock_init(&t->lit_lock);
+        for (i = 0; i < ARRAY_SIZE(t->lit_idmaps); i++)
+                for (j = 0; j < ARRAY_SIZE(t->lit_idmaps[i]); j++)
+                        INIT_LIST_HEAD(&t->lit_idmaps[i][j]);
+
+        return t;
+}
+EXPORT_SYMBOL(lustre_idmap_init);
+
+void lustre_idmap_fini(struct lustre_idmap_table *t)
+{
+        struct list_head *list;
+        struct lustre_idmap_entry *e;
+        int i;
+        LASSERT(t);
+
+        list = t->lit_idmaps[RMT_UIDMAP_IDX];
+        spin_lock(&t->lit_lock);
+        for (i = 0; i < CFS_IDMAP_HASHSIZE; i++)
+                while (!list_empty(&list[i])) {
+                        e = list_entry(list[i].next, struct lustre_idmap_entry,
+                                       lie_rmt_uid_hash);
+                        idmap_entry_free(e);
+                }
+        spin_unlock(&t->lit_lock);
+
+        OBD_FREE_PTR(t);
+}
+EXPORT_SYMBOL(lustre_idmap_fini);
index 3c0da53..646e7fe 100644 (file)
@@ -574,36 +574,6 @@ int class_del_conn(struct obd_device *obd, struct lustre_cfg *lcfg)
         RETURN(rc);
 }
 
         RETURN(rc);
 }
 
-int class_sec_flavor(struct obd_device *obd, struct lustre_cfg *lcfg)
-{
-        struct sec_flavor_config *conf;
-        ENTRY;
-
-        if (strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) &&
-            strcmp(obd->obd_type->typ_name, LUSTRE_OSC_NAME)) {
-                CERROR("Can't set security flavor on obd %s\n",
-                       obd->obd_type->typ_name);
-                RETURN(-EINVAL);
-        }
-
-        if (LUSTRE_CFG_BUFLEN(lcfg, 1) != sizeof(*conf)) {
-                CERROR("invalid data\n");
-                RETURN(-EINVAL);
-        }
-
-        conf = &obd->u.cli.cl_sec_conf;
-        memcpy(conf, lustre_cfg_buf(lcfg, 1), sizeof(*conf));
-
-#ifdef __BIG_ENDIAN
-        __swab32s(&conf->sfc_rpc_flavor);
-        __swab32s(&conf->sfc_bulk_csum);
-        __swab32s(&conf->sfc_bulk_priv);
-        __swab32s(&conf->sfc_flags);
-#endif
-
-        RETURN(0);
-}
-
 CFS_LIST_HEAD(lustre_profile_list);
 
 struct lustre_profile *class_get_profile(const char * prof)
 CFS_LIST_HEAD(lustre_profile_list);
 
 struct lustre_profile *class_get_profile(const char * prof)
@@ -829,10 +799,6 @@ int class_process_config(struct lustre_cfg *lcfg)
                 err = class_del_conn(obd, lcfg);
                 GOTO(out, err = 0);
         }
                 err = class_del_conn(obd, lcfg);
                 GOTO(out, err = 0);
         }
-        case LCFG_SEC_FLAVOR: {
-                err = class_sec_flavor(obd, lcfg);
-                GOTO(out, err = 0);
-        }
         default: {
                 err = obd_process_config(obd, sizeof(*lcfg), lcfg);
                 GOTO(out, err);
         default: {
                 err = obd_process_config(obd, sizeof(*lcfg), lcfg);
                 GOTO(out, err);
index a09dc36..9af2524 100644 (file)
@@ -893,81 +893,10 @@ int server_mti_print(char *title, struct mgs_target_info *mti)
         return(0);
 }
 
         return(0);
 }
 
-static
-int mti_set_sec_opts(struct mgs_target_info *mti, struct lustre_mount_data *lmd)
-{
-        char *s1, *s2;
-
-        if (lmd->lmd_sec_mdt == NULL && lmd->lmd_sec_cli == NULL) {
-                /* just let on-disk params do its work. but we have an
-                 * assumption that any changes of on-disk data by tune2fs
-                 * should lead to server rewrite log.
-                 */
-                return 0;
-        }
-
-        /* filter out existing sec options */
-        s1 = mti->mti_params;
-        while (*s1) {
-                int clear;
-
-                while (*s1 == ' ')
-                        s1++;
-
-                if (strncmp(s1, PARAM_SEC_RPC_MDT,
-                            sizeof(PARAM_SEC_RPC_MDT) - 1) == 0 ||
-                    strncmp(s1, PARAM_SEC_RPC_CLI,
-                            sizeof(PARAM_SEC_RPC_CLI) - 1) == 0)
-                        clear = 1;
-                else
-                        clear = 0;
-
-                s2 = strchr(s1, ' ');
-                if (s2 == NULL) {
-                        if (clear)
-                                *s1 = '\0';
-                        break;
-                }
-                s2++;
-                if (clear)
-                        memmove(s1, s2, strlen(s2) + 1);
-                else
-                        s1 = s2;
-        }
-
-        /* append sec options from lmd */
-        /* FIXME add flag LDD_F_UPDATE after mountconf start supporting
-         * log updating.
-         */
-        if (lmd->lmd_sec_mdt) {
-                if (strlen(mti->mti_params) + strlen(lmd->lmd_sec_mdt) +
-                    sizeof(PARAM_SEC_RPC_MDT) + 1 >= sizeof(mti->mti_params)) {
-                        CERROR("security params too big for mti\n");
-                        return -ENOMEM;
-                }
-                strcat(mti->mti_params, " "PARAM_SEC_RPC_MDT);
-                strcat(mti->mti_params, lmd->lmd_sec_mdt);
-                //mti->mti_flags |= LDD_F_UPDATE;
-        }
-        if (lmd->lmd_sec_cli) {
-                if (strlen(mti->mti_params) + strlen(lmd->lmd_sec_cli) +
-                    sizeof(PARAM_SEC_RPC_CLI) + 2 > sizeof(mti->mti_params)) {
-                        CERROR("security params too big for mti\n");
-                        return -ENOMEM;
-                }
-                strcat(mti->mti_params, " "PARAM_SEC_RPC_CLI);
-                strcat(mti->mti_params, lmd->lmd_sec_cli);
-                //mti->mti_flags |= LDD_F_UPDATE;
-        }
-
-        return 0;
-}
-
 static int server_sb2mti(struct super_block *sb, struct mgs_target_info *mti)
 {
         struct lustre_sb_info    *lsi = s2lsi(sb);
         struct lustre_disk_data  *ldd = lsi->lsi_ldd;
 static int server_sb2mti(struct super_block *sb, struct mgs_target_info *mti)
 {
         struct lustre_sb_info    *lsi = s2lsi(sb);
         struct lustre_disk_data  *ldd = lsi->lsi_ldd;
-        struct lustre_mount_data *lmd = lsi->lsi_lmd;
         lnet_process_id_t         id;
         int i = 0;
         ENTRY;
         lnet_process_id_t         id;
         int i = 0;
         ENTRY;
@@ -1003,8 +932,7 @@ static int server_sb2mti(struct super_block *sb, struct mgs_target_info *mti)
                 RETURN(-ENOMEM);
         }
         memcpy(mti->mti_params, ldd->ldd_params, sizeof(mti->mti_params));
                 RETURN(-ENOMEM);
         }
         memcpy(mti->mti_params, ldd->ldd_params, sizeof(mti->mti_params));
-
-        RETURN(mti_set_sec_opts(mti, lmd));
+        RETURN(0);
 }
 
 /* Register an old or new target with the MGS. If needed MGS will construct
 }
 
 /* Register an old or new target with the MGS. If needed MGS will construct
@@ -1221,8 +1149,6 @@ struct lustre_sb_info *lustre_init_lsi(struct super_block *sb)
         /* Default umount style */
         lsi->lsi_flags = LSI_UMOUNT_FAILOVER;
 
         /* Default umount style */
         lsi->lsi_flags = LSI_UMOUNT_FAILOVER;
 
-        lsi->lsi_lmd->lmd_nllu = NOBODY_UID;
-        lsi->lsi_lmd->lmd_nllg = NOBODY_GID;
         RETURN(lsi);
 }
 
         RETURN(lsi);
 }
 
@@ -1249,12 +1175,6 @@ static int lustre_free_lsi(struct super_block *sb)
                 if (lsi->lsi_lmd->lmd_profile != NULL)
                         OBD_FREE(lsi->lsi_lmd->lmd_profile,
                                  strlen(lsi->lsi_lmd->lmd_profile) + 1);
                 if (lsi->lsi_lmd->lmd_profile != NULL)
                         OBD_FREE(lsi->lsi_lmd->lmd_profile,
                                  strlen(lsi->lsi_lmd->lmd_profile) + 1);
-                if (lsi->lsi_lmd->lmd_sec_mdt != NULL)
-                        OBD_FREE(lsi->lsi_lmd->lmd_sec_mdt,
-                                 strlen(lsi->lsi_lmd->lmd_sec_mdt) + 1);
-                if (lsi->lsi_lmd->lmd_sec_cli != NULL)
-                        OBD_FREE(lsi->lsi_lmd->lmd_sec_cli,
-                                 strlen(lsi->lsi_lmd->lmd_sec_cli) + 1);
                 if (lsi->lsi_lmd->lmd_opts != NULL)
                         OBD_FREE(lsi->lsi_lmd->lmd_opts,
                                  strlen(lsi->lsi_lmd->lmd_opts) + 1);
                 if (lsi->lsi_lmd->lmd_opts != NULL)
                         OBD_FREE(lsi->lsi_lmd->lmd_opts,
                                  strlen(lsi->lsi_lmd->lmd_opts) + 1);
@@ -1743,10 +1663,6 @@ static void lmd_print(struct lustre_mount_data *lmd)
                 PRINT_CMD(PRINT_MASK, "profile: %s\n", lmd->lmd_profile);
         PRINT_CMD(PRINT_MASK, "device:  %s\n", lmd->lmd_dev);
         PRINT_CMD(PRINT_MASK, "flags:   %x\n", lmd->lmd_flags);
                 PRINT_CMD(PRINT_MASK, "profile: %s\n", lmd->lmd_profile);
         PRINT_CMD(PRINT_MASK, "device:  %s\n", lmd->lmd_dev);
         PRINT_CMD(PRINT_MASK, "flags:   %x\n", lmd->lmd_flags);
-        if (lmd->lmd_sec_mdt)
-                PRINT_CMD(PRINT_MASK, "sec_mdt: %s\n", lmd->lmd_sec_mdt);
-        if (lmd->lmd_sec_cli)
-                PRINT_CMD(PRINT_MASK, "sec_cli: %s\n", lmd->lmd_sec_cli);
         if (lmd->lmd_opts)
                 PRINT_CMD(PRINT_MASK, "options: %s\n", lmd->lmd_opts);
         for (i = 0; i < lmd->lmd_exclude_count; i++) {
         if (lmd->lmd_opts)
                 PRINT_CMD(PRINT_MASK, "options: %s\n", lmd->lmd_opts);
         for (i = 0; i < lmd->lmd_exclude_count; i++) {
@@ -1837,66 +1753,6 @@ static int lmd_make_exclusion(struct lustre_mount_data *lmd, char *ptr)
         RETURN(rc);
 }
 
         RETURN(rc);
 }
 
-static
-int lmd_set_sec_opts(char **set, char *opts, int length)
-{
-        if (*set)
-                OBD_FREE(*set, strlen(*set) + 1);
-
-        OBD_ALLOC(*set, length + 1);
-        if (*set == NULL)
-                return -ENOMEM;
-
-        memcpy(*set, opts, length);
-        (*set)[length] = '\0';
-
-        return 0;
-}
-
-static
-int lmd_parse_sec_opts(struct lustre_mount_data *lmd, char *ptr)
-{
-        char  *tail;
-        char **set = NULL;
-        int    length;
-
-        /* check peer name */
-        if (strncmp(ptr, "sec_mdt=", 8) == 0) {
-                set = &lmd->lmd_sec_mdt;
-                ptr += 8;
-        } else if (strncmp(ptr, "sec_cli=", 8) == 0) {
-                set = &lmd->lmd_sec_cli;
-                ptr += 8;
-        } else if (strncmp(ptr, "sec=", 4) == 0) {
-                /* leave 'set' be null */
-                ptr += 4;
-        } else {
-                CERROR("invalid security options: %s\n", ptr);
-                return -EINVAL;
-        }
-
-        tail = strchr(ptr, ',');
-        if (tail == NULL)
-                length = strlen(ptr);
-        else
-                length = tail - ptr;
-
-        if (set) {
-                if (lmd_set_sec_opts(set, ptr, length))
-                        return -EINVAL;
-        } else {
-                if (lmd->lmd_sec_mdt == NULL &&
-                    lmd_set_sec_opts(&lmd->lmd_sec_mdt, ptr, length))
-                        return -EINVAL;
-
-                if (lmd->lmd_sec_cli == NULL &&
-                    lmd_set_sec_opts(&lmd->lmd_sec_cli, ptr, length))
-                        return -EINVAL;
-        }
-
-        return 0;
-}
-
 /* mount -v -t lustre uml1:uml2:/lustre-client /mnt/lustre */
 static int lmd_parse(char *options, struct lustre_mount_data *lmd)
 {
 /* mount -v -t lustre uml1:uml2:/lustre-client /mnt/lustre */
 static int lmd_parse(char *options, struct lustre_mount_data *lmd)
 {
@@ -1947,17 +1803,6 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd)
                         if (rc)
                                 goto invalid;
                         clear++;
                         if (rc)
                                 goto invalid;
                         clear++;
-                } else if (strncmp(s1, "nllu=", 5) == 0) {
-                        lmd->lmd_nllu = simple_strtoul(s1 + 5, NULL, 10);
-                        clear++;
-                } else if (strncmp(s1, "nllg=", 5) == 0) {
-                        lmd->lmd_nllg = simple_strtoul(s1 + 5, NULL, 10);
-                        clear++;
-                } else if (strncmp(s1, "sec", 3) == 0) {
-                        rc = lmd_parse_sec_opts(lmd, s1);
-                        if (rc)
-                                goto invalid;
-                        clear++;
                 }
                 /* Linux 2.4 doesn't pass the device, so we stuck it at the
                    end of the options. */
                 }
                 /* Linux 2.4 doesn't pass the device, so we stuck it at the
                    end of the options. */
index a99a422..457447a 100644 (file)
@@ -1941,6 +1941,9 @@ int filter_common_setup(struct obd_device *obd, struct lustre_cfg* lcfg,
         INIT_LIST_HEAD(&filter->fo_llog_list);
         spin_lock_init(&filter->fo_llog_list_lock);
 
         INIT_LIST_HEAD(&filter->fo_llog_list);
         spin_lock_init(&filter->fo_llog_list_lock);
 
+        filter->fo_sptlrpc_lock = RW_LOCK_UNLOCKED;
+        sptlrpc_rule_set_init(&filter->fo_sptlrpc_rset);
+
         filter->fo_fl_oss_capa = 0;
         INIT_LIST_HEAD(&filter->fo_capa_keys);
         filter->fo_capa_hash = init_capa_hash();
         filter->fo_fl_oss_capa = 0;
         INIT_LIST_HEAD(&filter->fo_capa_keys);
         filter->fo_capa_hash = init_capa_hash();
@@ -2335,6 +2338,8 @@ static int filter_cleanup(struct obd_device *obd)
 
         ldlm_namespace_free(obd->obd_namespace, obd->obd_force);
 
 
         ldlm_namespace_free(obd->obd_namespace, obd->obd_force);
 
+        sptlrpc_rule_set_free(&filter->fo_sptlrpc_rset);
+
         if (obd->u.obt.obt_sb == NULL)
                 RETURN(0);
 
         if (obd->u.obt.obt_sb == NULL)
                 RETURN(0);
 
@@ -2428,7 +2433,8 @@ static int filter_connect_internal(struct obd_export *exp,
         RETURN(0);
 }
 
         RETURN(0);
 }
 
-static int filter_reconnect(struct obd_export *exp, struct obd_device *obd,
+static int filter_reconnect(const struct lu_env *env,
+                            struct obd_export *exp, struct obd_device *obd,
                             struct obd_uuid *cluuid,
                             struct obd_connect_data *data)
 {
                             struct obd_uuid *cluuid,
                             struct obd_connect_data *data)
 {
@@ -4011,9 +4017,43 @@ static int filter_process_config(struct obd_device *obd, obd_count len,
         struct lprocfs_static_vars lvars;
         int rc = 0;
 
         struct lprocfs_static_vars lvars;
         int rc = 0;
 
-        lprocfs_filter_init_vars(&lvars);
+        switch (lcfg->lcfg_command) {
+        case LCFG_SPTLRPC_CONF: {
+                struct filter_obd       *filter = &obd->u.filter;
+                struct sptlrpc_conf_log *log;
+                struct sptlrpc_rule_set  tmp_rset;
+
+                log = sptlrpc_conf_log_extract(lcfg);
+                if (IS_ERR(log)) {
+                        rc = PTR_ERR(log);
+                        break;
+                }
+
+                sptlrpc_rule_set_init(&tmp_rset);
+
+                rc = sptlrpc_rule_set_from_log(&tmp_rset, log);
+                if (rc) {
+                        CERROR("obd %s: failed get sptlrpc rules: %d\n",
+                               obd->obd_name, rc);
+                        break;
+                }
+
+                write_lock(&filter->fo_sptlrpc_lock);
+                sptlrpc_rule_set_free(&filter->fo_sptlrpc_rset);
+                filter->fo_sptlrpc_rset = tmp_rset;
+                write_unlock(&filter->fo_sptlrpc_lock);
+
+                sptlrpc_target_update_exp_flavor(obd, &tmp_rset);
+                break;
+        }
+        default:
+                lprocfs_filter_init_vars(&lvars);
+
+                rc = class_process_proc_param(PARAM_OST, lvars.obd_vars,
+                                              lcfg, obd);
+                break;
+        }
 
 
-        rc = class_process_proc_param(PARAM_OST, lvars.obd_vars, lcfg, obd);
         return rc;
 }
 
         return rc;
 }
 
index a011bdf..7980fd2 100644 (file)
@@ -353,7 +353,6 @@ static struct lprocfs_vars lprocfs_osc_obd_vars[] = {
         { "prealloc_next_id", osc_rd_prealloc_next_id, 0, 0 },
         { "prealloc_last_id", osc_rd_prealloc_last_id, 0, 0 },
         { "checksums",       osc_rd_checksum, osc_wr_checksum, 0 },
         { "prealloc_next_id", osc_rd_prealloc_next_id, 0, 0 },
         { "prealloc_last_id", osc_rd_prealloc_last_id, 0, 0 },
         { "checksums",       osc_rd_checksum, osc_wr_checksum, 0 },
-        { "sptlrpc",         sptlrpc_lprocfs_rd, 0, 0 },
         { "resend_count",    osc_rd_resend_count, osc_wr_resend_count, 0},
         { 0 }
 };
         { "resend_count",    osc_rd_resend_count, osc_wr_resend_count, 0},
         { 0 }
 };
index 68686a1..1ee17bd 100644 (file)
@@ -1085,7 +1085,8 @@ static int osc_brw_prep_request(int cmd, struct client_obd *cli,struct obdo *oa,
 
         /* size[REQ_REC_OFF] still sizeof (*body) */
         if (opc == OST_WRITE) {
 
         /* size[REQ_REC_OFF] still sizeof (*body) */
         if (opc == OST_WRITE) {
-                if (unlikely(cli->cl_checksum)) {
+                if (unlikely(cli->cl_checksum) &&
+                    req->rq_flvr.sf_bulk_csum == BULK_CSUM_ALG_NULL) {
                         body->oa.o_valid |= OBD_MD_FLCKSUM;
                         body->oa.o_cksum = osc_checksum_bulk(requested_nob,
                                                              page_count, pga,
                         body->oa.o_valid |= OBD_MD_FLCKSUM;
                         body->oa.o_cksum = osc_checksum_bulk(requested_nob,
                                                              page_count, pga,
@@ -1104,7 +1105,8 @@ static int osc_brw_prep_request(int cmd, struct client_obd *cli,struct obdo *oa,
                 size[REPLY_REC_OFF + 1] = sizeof(__u32) * niocount;
                 ptlrpc_req_set_repsize(req, 3, size);
         } else {
                 size[REPLY_REC_OFF + 1] = sizeof(__u32) * niocount;
                 ptlrpc_req_set_repsize(req, 3, size);
         } else {
-                if (unlikely(cli->cl_checksum))
+                if (unlikely(cli->cl_checksum) &&
+                    req->rq_flvr.sf_bulk_csum == BULK_CSUM_ALG_NULL)
                         body->oa.o_valid |= OBD_MD_FLCKSUM;
                 /* 1 RC for the whole I/O */
                 ptlrpc_req_set_repsize(req, 2, size);
                         body->oa.o_valid |= OBD_MD_FLCKSUM;
                 /* 1 RC for the whole I/O */
                 ptlrpc_req_set_repsize(req, 2, size);
@@ -3560,7 +3562,8 @@ static int osc_llog_finish(struct obd_device *obd, int count)
         RETURN(rc);
 }
 
         RETURN(rc);
 }
 
-static int osc_reconnect(struct obd_export *exp, struct obd_device *obd,
+static int osc_reconnect(const struct lu_env *env,
+                         struct obd_export *exp, struct obd_device *obd,
                          struct obd_uuid *cluuid,
                          struct obd_connect_data *data)
 {
                          struct obd_uuid *cluuid,
                          struct obd_connect_data *data)
 {
@@ -3698,6 +3701,7 @@ int osc_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
                 lprocfs_osc_init_vars(&lvars);
                 if (lprocfs_obd_setup(obd, lvars.obd_vars) == 0) {
                         lproc_osc_attach_seqstat(obd);
                 lprocfs_osc_init_vars(&lvars);
                 if (lprocfs_obd_setup(obd, lvars.obd_vars) == 0) {
                         lproc_osc_attach_seqstat(obd);
+                        sptlrpc_lprocfs_cliobd_attach(obd);
                         ptlrpc_lprocfs_register_obd(obd);
                 }
 
                         ptlrpc_lprocfs_register_obd(obd);
                 }
 
@@ -3790,7 +3794,16 @@ static int osc_process_config(struct obd_device *obd, obd_count len, void *buf)
 
         lprocfs_osc_init_vars(&lvars);
 
 
         lprocfs_osc_init_vars(&lvars);
 
-        rc = class_process_proc_param(PARAM_OSC, lvars.obd_vars, lcfg, obd);
+        switch (lcfg->lcfg_command) {
+        case LCFG_SPTLRPC_CONF:
+                rc = sptlrpc_cliobd_process_config(obd, lcfg);
+                break;
+        default:
+                rc = class_process_proc_param(PARAM_OSC, lvars.obd_vars,
+                                              lcfg, obd);
+                break;
+        }
+
         return(rc);
 }
 
         return(rc);
 }
 
index 2bc96b3..6ea1654 100644 (file)
@@ -1112,10 +1112,8 @@ static int ost_brw_write(struct ptlrpc_request *req, struct obd_trans_info *oti)
         }
         no_reply = rc != 0;
 
         }
         no_reply = rc != 0;
 
-        if (rc == 0) {
-                /* let client retry if unwrap failed */
-                rc = sptlrpc_svc_unwrap_bulk(req, desc);
-        }
+        if (rc == 0)
+                sptlrpc_svc_unwrap_bulk(req, desc);
 
         repbody = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
                                  sizeof(*repbody));
 
         repbody = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
                                  sizeof(*repbody));
@@ -1352,6 +1350,44 @@ static int ost_llog_handle_connect(struct obd_export *exp,
         RETURN(rc);
 }
 
         RETURN(rc);
 }
 
+static int filter_export_check_flavor(struct filter_obd *filter,
+                                      struct obd_export *exp,
+                                      struct ptlrpc_request *req)
+{
+        int     rc = 0;
+
+        /* FIXME
+         * this should be done in filter_connect()/filter_reconnect(), but
+         * we can't obtain information like NID, which stored in incoming
+         * request, thus can't decide what flavor to use. so we do it here.
+         *
+         * This hack should be removed after the OST stack be rewritten, just
+         * like what we are doing in mdt_obd_connect()/mdt_obd_reconnect().
+         */
+        if (exp->exp_flvr.sf_rpc != SPTLRPC_FLVR_INVALID)
+                return 0;
+
+        CDEBUG(D_SEC, "from %s\n", sptlrpc_part2name(req->rq_sp_from));
+        spin_lock(&exp->exp_lock);
+        exp->exp_sp_peer = req->rq_sp_from;
+
+        read_lock(&filter->fo_sptlrpc_lock);
+        sptlrpc_rule_set_choose(&filter->fo_sptlrpc_rset, exp->exp_sp_peer,
+                                req->rq_peer.nid, &exp->exp_flvr);
+        read_unlock(&filter->fo_sptlrpc_lock);
+
+        if (exp->exp_flvr.sf_rpc != req->rq_flvr.sf_rpc) {
+                CERROR("invalid rpc flavor %x, expect %x, from %s\n",
+                       req->rq_flvr.sf_rpc, exp->exp_flvr.sf_rpc,
+                       libcfs_nid2str(req->rq_peer.nid));
+                exp->exp_flvr.sf_rpc = SPTLRPC_FLVR_INVALID;
+                rc = -EACCES;
+        }
+
+        spin_unlock(&exp->exp_lock);
+
+        return rc;
+}
 
 static int ost_filter_recovery_request(struct ptlrpc_request *req,
                                        struct obd_device *obd, int *process)
 
 static int ost_filter_recovery_request(struct ptlrpc_request *req,
                                        struct obd_device *obd, int *process)
@@ -1508,8 +1544,14 @@ int ost_handle(struct ptlrpc_request *req)
                 if (OBD_FAIL_CHECK(OBD_FAIL_OST_CONNECT_NET))
                         RETURN(0);
                 rc = target_handle_connect(req);
                 if (OBD_FAIL_CHECK(OBD_FAIL_OST_CONNECT_NET))
                         RETURN(0);
                 rc = target_handle_connect(req);
-                if (!rc)
-                        obd = req->rq_export->exp_obd;
+                if (!rc) {
+                        struct obd_export *exp = req->rq_export;
+
+                        obd = exp->exp_obd;
+
+                        rc = filter_export_check_flavor(&obd->u.filter,
+                                                        exp, req);
+                }
                 break;
         }
         case OST_DISCONNECT:
                 break;
         }
         case OST_DISCONNECT:
index 381a77c..caab57d 100644 (file)
@@ -14,7 +14,8 @@ ptlrpc_objs := client.o recover.o connection.o niobuf.o pack_generic.o
 ptlrpc_objs += events.o ptlrpc_module.o service.o pinger.o recov_thread.o
 ptlrpc_objs += llog_net.o llog_client.o llog_server.o import.o ptlrpcd.o
 ptlrpc_objs += pers.o lproc_ptlrpc.o wiretest.o layout.o
 ptlrpc_objs += events.o ptlrpc_module.o service.o pinger.o recov_thread.o
 ptlrpc_objs += llog_net.o llog_client.o llog_server.o import.o ptlrpcd.o
 ptlrpc_objs += pers.o lproc_ptlrpc.o wiretest.o layout.o
-ptlrpc_objs += sec.o sec_bulk.o sec_gc.o sec_null.o sec_plain.o sec_lproc.o
+ptlrpc_objs += sec.o sec_bulk.o sec_gc.o sec_config.o sec_lproc.o
+ptlrpc_objs += sec_null.o sec_plain.o
 
 ptlrpc-objs := $(ldlm_objs) $(ptlrpc_objs)
 
 
 ptlrpc-objs := $(ldlm_objs) $(ptlrpc_objs)
 
index e098d92..7d4754e 100644 (file)
@@ -19,8 +19,8 @@ LDLM_COMM_SOURCES= $(top_srcdir)/lustre/ldlm/l_lock.c \
 COMMON_SOURCES =  client.c recover.c connection.c niobuf.c pack_generic.c   \
     events.c ptlrpc_module.c service.c pinger.c recov_thread.c llog_net.c   \
     llog_client.c llog_server.c import.c ptlrpcd.c pers.c wiretest.c               \
 COMMON_SOURCES =  client.c recover.c connection.c niobuf.c pack_generic.c   \
     events.c ptlrpc_module.c service.c pinger.c recov_thread.c llog_net.c   \
     llog_client.c llog_server.c import.c ptlrpcd.c pers.c wiretest.c               \
-    ptlrpc_internal.h layout.c sec.c sec_bulk.c sec_gc.c sec_null.c         \
-    sec_plain.c sec_lproc.c lproc_ptlrpc.c $(LDLM_COMM_SOURCES)
+    ptlrpc_internal.h layout.c sec.c sec_bulk.c sec_gc.c sec_config.c       \
+    sec_lproc.c sec_null.c sec_plain.c lproc_ptlrpc.c $(LDLM_COMM_SOURCES)
 
 if LIBLUSTRE
 
 
 if LIBLUSTRE
 
@@ -60,6 +60,10 @@ ptlrpc_SOURCES := \
         service.c \
        wiretest.c \
        sec.c \
         service.c \
        wiretest.c \
        sec.c \
+       sec_bulk.c \
+       sec_gc.c \
+       sec_config.c \
+       sec_lproc.c \
        sec_null.c \
        sec_plain.c \
         $(LDLM_COMM_SOURCES)
        sec_null.c \
        sec_plain.c \
         $(LDLM_COMM_SOURCES)
index 3f9be08..12c2547 100644 (file)
@@ -10,6 +10,5 @@ if MODULES
 modulefs_DATA = ptlrpc_gss$(KMODEXT)
 endif # MODULES
 
 modulefs_DATA = ptlrpc_gss$(KMODEXT)
 endif # MODULES
 
-DIST_SOURCES = $(ptlrpc_gss-objs:.o=.c) gss_api.h gss_asn1.h gss_err.h \
-               gss_internal.h gss_krb5.h
+DIST_SOURCES = *.c *.h
 MOSTLYCLEANFILES := @MOSTLYCLEANFILES@ 
 MOSTLYCLEANFILES := @MOSTLYCLEANFILES@ 
index cf31747..d38e4d2 100644 (file)
@@ -67,6 +67,7 @@ __u32 lgss_unwrap(
                 rawobj_t                *out_msg);
 __u32 lgss_plain_encrypt(
                 struct gss_ctx          *ctx,
                 rawobj_t                *out_msg);
 __u32 lgss_plain_encrypt(
                 struct gss_ctx          *ctx,
+                int                      decrypt,
                 int                      length,
                 void                    *in_buf,
                 void                    *out_buf);
                 int                      length,
                 void                    *in_buf,
                 void                    *out_buf);
@@ -128,6 +129,7 @@ struct gss_api_ops {
                         rawobj_t               *out_msg);
         __u32 (*gss_plain_encrypt)(
                         struct gss_ctx         *ctx,
                         rawobj_t               *out_msg);
         __u32 (*gss_plain_encrypt)(
                         struct gss_ctx         *ctx,
+                        int                     decrypt,
                         int                     length,
                         void                   *in_buf,
                         void                   *out_buf);
                         int                     length,
                         void                   *in_buf,
                         void                   *out_buf);
index 7d4864c..9f829ad 100644 (file)
@@ -57,6 +57,7 @@ int do_bulk_privacy(struct gss_ctx *gctx,
 {
         struct crypto_tfm  *tfm;
         struct scatterlist  sg, sg2, *sgd;
 {
         struct crypto_tfm  *tfm;
         struct scatterlist  sg, sg2, *sgd;
+        unsigned int        blksize;
         int                 i, rc;
         __u8                local_iv[sizeof(bsd->bsd_iv)];
 
         int                 i, rc;
         __u8                local_iv[sizeof(bsd->bsd_iv)];
 
@@ -68,12 +69,6 @@ int do_bulk_privacy(struct gss_ctx *gctx,
         if (alg == BULK_PRIV_ALG_NULL)
                 return 0;
 
         if (alg == BULK_PRIV_ALG_NULL)
                 return 0;
 
-        if (encrypt)
-                get_random_bytes(bsd->bsd_iv, sizeof(bsd->bsd_iv));
-
-        /* compute the secret iv */
-        lgss_plain_encrypt(gctx, sizeof(local_iv), bsd->bsd_iv, local_iv);
-
         tfm = crypto_alloc_tfm(sptlrpc_bulk_priv_alg2name(alg),
                                sptlrpc_bulk_priv_alg2flags(alg));
         if (tfm == NULL) {
         tfm = crypto_alloc_tfm(sptlrpc_bulk_priv_alg2name(alg),
                                sptlrpc_bulk_priv_alg2flags(alg));
         if (tfm == NULL) {
@@ -82,12 +77,25 @@ int do_bulk_privacy(struct gss_ctx *gctx,
                 return -ENOMEM;
         }
 
                 return -ENOMEM;
         }
 
+        blksize = crypto_tfm_alg_blocksize(tfm);
+        LASSERT(blksize <= sizeof(local_iv));
+
+        if (encrypt)
+                get_random_bytes(bsd->bsd_iv, sizeof(bsd->bsd_iv));
+
+        /* compute the secret iv */
+        rc = lgss_plain_encrypt(gctx, 0,
+                                sizeof(local_iv), bsd->bsd_iv, local_iv);
+        if (rc) {
+                CERROR("failed to compute secret iv: %d\n", rc);
+                goto out;
+        }
+
         rc = crypto_cipher_setkey(tfm, local_iv, sizeof(local_iv));
         if (rc) {
                 CERROR("Failed to set key for TFM %s: %d\n",
                        sptlrpc_bulk_priv_alg2name(alg), rc);
         rc = crypto_cipher_setkey(tfm, local_iv, sizeof(local_iv));
         if (rc) {
                 CERROR("Failed to set key for TFM %s: %d\n",
                        sptlrpc_bulk_priv_alg2name(alg), rc);
-                crypto_free_tfm(tfm);
-                return rc;
+                goto out;
         }
 
         for (i = 0; i < desc->bd_iov_count; i++) {
         }
 
         for (i = 0; i < desc->bd_iov_count; i++) {
@@ -119,12 +127,12 @@ int do_bulk_privacy(struct gss_ctx *gctx,
                  */
         }
 
                  */
         }
 
-        crypto_free_tfm(tfm);
-
         if (encrypt)
                 bsd->bsd_priv_alg = alg;
 
         if (encrypt)
                 bsd->bsd_priv_alg = alg;
 
-        return 0;
+out:
+        crypto_free_tfm(tfm);
+        return rc;
 }
 
 int gss_cli_ctx_wrap_bulk(struct ptlrpc_cli_ctx *ctx,
 }
 
 int gss_cli_ctx_wrap_bulk(struct ptlrpc_cli_ctx *ctx,
@@ -134,14 +142,13 @@ int gss_cli_ctx_wrap_bulk(struct ptlrpc_cli_ctx *ctx,
         struct gss_cli_ctx              *gctx;
         struct lustre_msg               *msg;
         struct ptlrpc_bulk_sec_desc     *bsdr;
         struct gss_cli_ctx              *gctx;
         struct lustre_msg               *msg;
         struct ptlrpc_bulk_sec_desc     *bsdr;
-        struct sec_flavor_config        *conf;
         int                              offset, rc;
         ENTRY;
 
         int                              offset, rc;
         ENTRY;
 
-        LASSERT(SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor));
+        LASSERT(req->rq_pack_bulk);
         LASSERT(req->rq_bulk_read || req->rq_bulk_write);
 
         LASSERT(req->rq_bulk_read || req->rq_bulk_write);
 
-        switch (SEC_FLAVOR_SVC(req->rq_sec_flavor)) {
+        switch (RPC_FLVR_SVC(req->rq_flvr.sf_rpc)) {
         case SPTLRPC_SVC_NULL:
                 LASSERT(req->rq_reqbuf->lm_bufcount >= 3);
                 msg = req->rq_reqbuf;
         case SPTLRPC_SVC_NULL:
                 LASSERT(req->rq_reqbuf->lm_bufcount >= 3);
                 msg = req->rq_reqbuf;
@@ -163,23 +170,22 @@ int gss_cli_ctx_wrap_bulk(struct ptlrpc_cli_ctx *ctx,
         }
 
         /* make checksum */
         }
 
         /* make checksum */
-        conf = &req->rq_import->imp_obd->u.cli.cl_sec_conf;
-        rc = bulk_csum_cli_request(desc, req->rq_bulk_read, conf->sfc_bulk_csum,
-                                   msg, offset);
+        rc = bulk_csum_cli_request(desc, req->rq_bulk_read,
+                                   req->rq_flvr.sf_bulk_csum, msg, offset);
         if (rc) {
                 CERROR("client bulk %s: failed to generate checksum: %d\n",
                        req->rq_bulk_read ? "read" : "write", rc);
                 RETURN(rc);
         }
 
         if (rc) {
                 CERROR("client bulk %s: failed to generate checksum: %d\n",
                        req->rq_bulk_read ? "read" : "write", rc);
                 RETURN(rc);
         }
 
-        if (conf->sfc_bulk_priv == BULK_PRIV_ALG_NULL)
+        if (req->rq_flvr.sf_bulk_priv == BULK_PRIV_ALG_NULL)
                 RETURN(0);
 
         /* previous bulk_csum_cli_request() has verified bsdr is good */
         bsdr = lustre_msg_buf(msg, offset, 0);
 
         if (req->rq_bulk_read) {
                 RETURN(0);
 
         /* previous bulk_csum_cli_request() has verified bsdr is good */
         bsdr = lustre_msg_buf(msg, offset, 0);
 
         if (req->rq_bulk_read) {
-                bsdr->bsd_priv_alg = conf->sfc_bulk_priv;
+                bsdr->bsd_priv_alg = req->rq_flvr.sf_bulk_priv;
                 RETURN(0);
         }
 
                 RETURN(0);
         }
 
@@ -194,7 +200,7 @@ int gss_cli_ctx_wrap_bulk(struct ptlrpc_cli_ctx *ctx,
         LASSERT(gctx->gc_mechctx);
 
         rc = do_bulk_privacy(gctx->gc_mechctx, desc, 1,
         LASSERT(gctx->gc_mechctx);
 
         rc = do_bulk_privacy(gctx->gc_mechctx, desc, 1,
-                             conf->sfc_bulk_priv, bsdr);
+                             req->rq_flvr.sf_bulk_priv, bsdr);
         if (rc)
                 CERROR("bulk write: client failed to encrypt pages\n");
 
         if (rc)
                 CERROR("bulk write: client failed to encrypt pages\n");
 
@@ -211,10 +217,10 @@ int gss_cli_ctx_unwrap_bulk(struct ptlrpc_cli_ctx *ctx,
         int                              roff, voff, rc;
         ENTRY;
 
         int                              roff, voff, rc;
         ENTRY;
 
-        LASSERT(SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor));
+        LASSERT(req->rq_pack_bulk);
         LASSERT(req->rq_bulk_read || req->rq_bulk_write);
 
         LASSERT(req->rq_bulk_read || req->rq_bulk_write);
 
-        switch (SEC_FLAVOR_SVC(req->rq_sec_flavor)) {
+        switch (RPC_FLVR_SVC(req->rq_flvr.sf_rpc)) {
         case SPTLRPC_SVC_NULL:
                 vmsg = req->rq_repbuf;
                 voff = vmsg->lm_bufcount - 1;
         case SPTLRPC_SVC_NULL:
                 vmsg = req->rq_repbuf;
                 voff = vmsg->lm_bufcount - 1;
@@ -286,6 +292,7 @@ int gss_svc_unwrap_bulk(struct ptlrpc_request *req,
         ENTRY;
 
         LASSERT(req->rq_svc_ctx);
         ENTRY;
 
         LASSERT(req->rq_svc_ctx);
+        LASSERT(req->rq_pack_bulk);
         LASSERT(req->rq_bulk_write);
 
         grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
         LASSERT(req->rq_bulk_write);
 
         grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
@@ -322,6 +329,7 @@ int gss_svc_wrap_bulk(struct ptlrpc_request *req,
         ENTRY;
 
         LASSERT(req->rq_svc_ctx);
         ENTRY;
 
         LASSERT(req->rq_svc_ctx);
+        LASSERT(req->rq_pack_bulk);
         LASSERT(req->rq_bulk_read);
 
         grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
         LASSERT(req->rq_bulk_read);
 
         grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
index fed7c48..610c108 100644 (file)
@@ -72,6 +72,8 @@ int ctx_init_pack_request(struct obd_import *imp,
         rawobj_t                 obj;
 
         LASSERT(msg->lm_bufcount <= 4);
         rawobj_t                 obj;
 
         LASSERT(msg->lm_bufcount <= 4);
+        LASSERT(req->rq_cli_ctx);
+        LASSERT(req->rq_cli_ctx->cc_sec);
 
         /* gss hdr */
         ghdr = lustre_msg_buf(msg, 0, sizeof(*ghdr));
 
         /* gss hdr */
         ghdr = lustre_msg_buf(msg, 0, sizeof(*ghdr));
@@ -83,7 +85,9 @@ int ctx_init_pack_request(struct obd_import *imp,
         ghdr->gh_handle.len = 0;
 
         /* fix the user desc */
         ghdr->gh_handle.len = 0;
 
         /* fix the user desc */
-        if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor)) {
+        if (req->rq_pack_udesc) {
+                ghdr->gh_flags |= LUSTRE_GSS_PACK_USER;
+
                 pud = lustre_msg_buf(msg, offset, sizeof(*pud));
                 LASSERT(pud);
                 pud->pud_uid = pud->pud_fsuid = uid;
                 pud = lustre_msg_buf(msg, offset, sizeof(*pud));
                 LASSERT(pud);
                 pud->pud_uid = pud->pud_fsuid = uid;
@@ -96,6 +100,7 @@ int ctx_init_pack_request(struct obd_import *imp,
         /* security payload */
         p = lustre_msg_buf(msg, offset, 0);
         size = msg->lm_buflens[offset];
         /* security payload */
         p = lustre_msg_buf(msg, offset, 0);
         size = msg->lm_buflens[offset];
+        LASSERT(p);
 
         /* 1. lustre svc type */
         LASSERT(size > 4);
 
         /* 1. lustre svc type */
         LASSERT(size > 4);
@@ -110,7 +115,7 @@ int ctx_init_pack_request(struct obd_import *imp,
 
         /* 3. reverse context handle. actually only needed by root user,
          *    but we send it anyway. */
 
         /* 3. reverse context handle. actually only needed by root user,
          *    but we send it anyway. */
-        gsec = container_of(imp->imp_sec, struct gss_sec, gs_base);
+        gsec = sec2gsec(req->rq_cli_ctx->cc_sec);
         obj.len = sizeof(gsec->gs_rvs_hdl);
         obj.data = (__u8 *) &gsec->gs_rvs_hdl;
         if (rawobj_serialize(&obj, &p, &size))
         obj.len = sizeof(gsec->gs_rvs_hdl);
         obj.data = (__u8 *) &gsec->gs_rvs_hdl;
         if (rawobj_serialize(&obj, &p, &size))
@@ -205,6 +210,7 @@ int ctx_init_parse_reply(struct lustre_msg *msg,
 /* XXX move to where lgssd could see */
 struct lgssd_ioctl_param {
         int             version;        /* in   */
 /* XXX move to where lgssd could see */
 struct lgssd_ioctl_param {
         int             version;        /* in   */
+        int             secid;          /* in   */
         char           *uuid;           /* in   */
         int             lustre_svc;     /* in   */
         uid_t           uid;            /* in   */
         char           *uuid;           /* in   */
         int             lustre_svc;     /* in   */
         uid_t           uid;            /* in   */
@@ -269,6 +275,14 @@ int gss_do_ctx_init_rpc(__user char *buffer, unsigned long count)
                 goto out_copy;
         }
 
                 goto out_copy;
         }
 
+        if (req->rq_cli_ctx->cc_sec->ps_id != param.secid) {
+                CWARN("original secid %d, now has changed to %d, "
+                      "cancel this negotiation\n", param.secid,
+                      req->rq_cli_ctx->cc_sec->ps_id);
+                param.status = -EINVAL;
+                goto out_copy;
+        }
+
         /* get token */
         rc = ctx_init_pack_request(imp, req,
                                    param.lustre_svc,
         /* get token */
         rc = ctx_init_pack_request(imp, req,
                                    param.lustre_svc,
@@ -340,10 +354,11 @@ int gss_do_ctx_fini_rpc(struct gss_cli_ctx *gctx)
 
         might_sleep();
 
 
         might_sleep();
 
-        CDEBUG(D_SEC, "%s ctx %p(%u->%s)\n",
-               sec_is_reverse(ctx->cc_sec) ?
-               "server finishing reverse" : "client finishing forward",
-               ctx, ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec));
+        CWARN("%s ctx %p idx "LPX64" (%u->%s)\n",
+              sec_is_reverse(ctx->cc_sec) ?
+              "server finishing reverse" : "client finishing forward",
+              ctx, gss_handle_to_u64(&gctx->gc_handle),
+              ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec));
 
         gctx->gc_proc = PTLRPC_GSS_PROC_DESTROY;
 
 
         gctx->gc_proc = PTLRPC_GSS_PROC_DESTROY;
 
@@ -356,7 +371,7 @@ int gss_do_ctx_fini_rpc(struct gss_cli_ctx *gctx)
         }
 
         /* fix the user desc */
         }
 
         /* fix the user desc */
-        if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor)) {
+        if (req->rq_pack_udesc) {
                 /* we rely the fact that this request is in AUTH mode,
                  * and user_desc at offset 2. */
                 pud = lustre_msg_buf(req->rq_reqbuf, 2, sizeof(*pud));
                 /* we rely the fact that this request is in AUTH mode,
                  * and user_desc at offset 2. */
                 pud = lustre_msg_buf(req->rq_reqbuf, 2, sizeof(*pud));
index 67083c1..6e98242 100644 (file)
@@ -36,6 +36,7 @@ typedef struct rawobj_buf_s {
         __u8           *buf;
 } rawobj_buf_t;
 
         __u8           *buf;
 } rawobj_buf_t;
 
+int rawobj_empty(rawobj_t *obj);
 int rawobj_alloc(rawobj_t *obj, char *buf, int len);
 void rawobj_free(rawobj_t *obj);
 int rawobj_equal(rawobj_t *a, rawobj_t *b);
 int rawobj_alloc(rawobj_t *obj, char *buf, int len);
 void rawobj_free(rawobj_t *obj);
 int rawobj_equal(rawobj_t *a, rawobj_t *b);
@@ -109,6 +110,11 @@ enum ptlrpc_gss_tgt {
         LUSTRE_GSS_TGT_MGS              = 2,
 };
 
         LUSTRE_GSS_TGT_MGS              = 2,
 };
 
+enum ptlrpc_gss_header_flags {
+        LUSTRE_GSS_PACK_BULK            = 1,
+        LUSTRE_GSS_PACK_USER            = 2,
+};
+
 static inline
 __u32 import_to_gss_svc(struct obd_import *imp)
 {
 static inline
 __u32 import_to_gss_svc(struct obd_import *imp)
 {
@@ -126,7 +132,9 @@ __u32 import_to_gss_svc(struct obd_import *imp)
  * following 3 header must have the same size and offset
  */
 struct gss_header {
  * following 3 header must have the same size and offset
  */
 struct gss_header {
-        __u32                   gh_version;     /* gss version */
+        __u8                    gh_version;     /* gss version */
+        __u8                    gh_sp;          /* sec part */
+        __u16                   gh_pad0;
         __u32                   gh_flags;       /* wrap flags */
         __u32                   gh_proc;        /* proc */
         __u32                   gh_seq;         /* sequence */
         __u32                   gh_flags;       /* wrap flags */
         __u32                   gh_proc;        /* proc */
         __u32                   gh_seq;         /* sequence */
@@ -138,7 +146,9 @@ struct gss_header {
 };
 
 struct gss_rep_header {
 };
 
 struct gss_rep_header {
-        __u32                   gh_version;
+        __u8                    gh_version;
+        __u8                    gh_sp;
+        __u16                   gh_pad0;
         __u32                   gh_flags;
         __u32                   gh_proc;
         __u32                   gh_major;
         __u32                   gh_flags;
         __u32                   gh_proc;
         __u32                   gh_major;
@@ -150,7 +160,9 @@ struct gss_rep_header {
 };
 
 struct gss_err_header {
 };
 
 struct gss_err_header {
-        __u32                   gh_version;
+        __u8                    gh_version;
+        __u8                    gh_sp;
+        __u16                   gh_pad0;
         __u32                   gh_flags;
         __u32                   gh_proc;
         __u32                   gh_major;
         __u32                   gh_flags;
         __u32                   gh_proc;
         __u32                   gh_major;
@@ -166,6 +178,7 @@ struct gss_err_header {
  * used later by server.
  */
 struct gss_wire_ctx {
  * used later by server.
  */
 struct gss_wire_ctx {
+        __u32                   gw_flags;
         __u32                   gw_proc;
         __u32                   gw_seq;
         __u32                   gw_svc;
         __u32                   gw_proc;
         __u32                   gw_seq;
         __u32                   gw_svc;
@@ -177,6 +190,13 @@ struct gss_wire_ctx {
                                          PTLRPC_GSS_MAX_HANDLE_SIZE)
 
 
                                          PTLRPC_GSS_MAX_HANDLE_SIZE)
 
 
+static inline __u64 gss_handle_to_u64(rawobj_t *handle)
+{
+        if (handle->len != PTLRPC_GSS_MAX_HANDLE_SIZE)
+                return -1;
+        return *((__u64 *) handle->data);
+}
+
 #define GSS_SEQ_WIN                     (2048)
 #define GSS_SEQ_WIN_MAIN                GSS_SEQ_WIN
 #define GSS_SEQ_WIN_BACK                (128)
 #define GSS_SEQ_WIN                     (2048)
 #define GSS_SEQ_WIN_MAIN                GSS_SEQ_WIN
 #define GSS_SEQ_WIN_BACK                (128)
@@ -200,15 +220,17 @@ struct gss_svc_seq_data {
 };
 
 struct gss_svc_ctx {
 };
 
 struct gss_svc_ctx {
-        unsigned int            gsc_usr_root:1,
-                                gsc_usr_mds:1,
-                                gsc_remote:1;
+        struct gss_ctx         *gsc_mechctx;
+        struct gss_svc_seq_data gsc_seqdata;
+        rawobj_t                gsc_rvs_hdl;
+        __u32                   gsc_rvs_seq;
         uid_t                   gsc_uid;
         gid_t                   gsc_gid;
         uid_t                   gsc_mapped_uid;
         uid_t                   gsc_uid;
         gid_t                   gsc_gid;
         uid_t                   gsc_mapped_uid;
-        rawobj_t                gsc_rvs_hdl;
-        struct gss_svc_seq_data gsc_seqdata;
-        struct gss_ctx         *gsc_mechctx;
+        unsigned int            gsc_usr_root:1,
+                                gsc_usr_mds:1,
+                                gsc_remote:1,
+                                gsc_reverse:1;
 };
 
 struct gss_svc_reqctx {
 };
 
 struct gss_svc_reqctx {
@@ -242,6 +264,8 @@ struct gss_cli_ctx {
         atomic_t                gc_seq;
         rawobj_t                gc_handle;
         struct gss_ctx         *gc_mechctx;
         atomic_t                gc_seq;
         rawobj_t                gc_handle;
         struct gss_ctx         *gc_mechctx;
+        /* handle for the buddy svc ctx */
+        rawobj_t                gc_svc_handle;
 };
 
 struct gss_cli_ctx_keyring {
 };
 
 struct gss_cli_ctx_keyring {
@@ -271,10 +295,6 @@ struct gss_sec_pipefs {
 struct gss_sec_keyring {
         struct gss_sec          gsk_base;
         /*
 struct gss_sec_keyring {
         struct gss_sec          gsk_base;
         /*
-         * unique sec_id.
-         */
-        int                     gsk_id;
-        /*
          * all contexts listed here. access is protected by sec spinlock.
          */
         struct hlist_head       gsk_clist;
          * all contexts listed here. access is protected by sec spinlock.
          */
         struct hlist_head       gsk_clist;
@@ -337,6 +357,13 @@ struct gss_svc_reqctx *gss_svc_ctx2reqctx(struct ptlrpc_svc_ctx *ctx)
         return container_of(ctx, struct gss_svc_reqctx, src_base);
 }
 
         return container_of(ctx, struct gss_svc_reqctx, src_base);
 }
 
+static inline
+struct gss_svc_ctx *gss_svc_ctx2gssctx(struct ptlrpc_svc_ctx *ctx)
+{
+        LASSERT(ctx);
+        return gss_svc_ctx2reqctx(ctx)->src_ctx;
+}
+
 /* sec_gss.c */
 int gss_cli_ctx_match(struct ptlrpc_cli_ctx *ctx, struct vfs_cred *vcred);
 int gss_cli_ctx_display(struct ptlrpc_cli_ctx *ctx, char *buf, int bufsize);
 /* sec_gss.c */
 int gss_cli_ctx_match(struct ptlrpc_cli_ctx *ctx, struct vfs_cred *vcred);
 int gss_cli_ctx_display(struct ptlrpc_cli_ctx *ctx, char *buf, int bufsize);
@@ -381,9 +408,9 @@ int gss_sec_create_common(struct gss_sec *gsec,
                           struct ptlrpc_sec_policy *policy,
                           struct obd_import *imp,
                           struct ptlrpc_svc_ctx *ctx,
                           struct ptlrpc_sec_policy *policy,
                           struct obd_import *imp,
                           struct ptlrpc_svc_ctx *ctx,
-                          __u32 flavor,
-                          unsigned long flags);
+                          struct sptlrpc_flavor *sf);
 void gss_sec_destroy_common(struct gss_sec *gsec);
 void gss_sec_destroy_common(struct gss_sec *gsec);
+void gss_sec_kill(struct ptlrpc_sec *sec);
 
 int gss_cli_ctx_init_common(struct ptlrpc_sec *sec,
                             struct ptlrpc_cli_ctx *ctx,
 
 int gss_cli_ctx_init_common(struct ptlrpc_sec *sec,
                             struct ptlrpc_cli_ctx *ctx,
@@ -395,7 +422,6 @@ int gss_cli_ctx_fini_common(struct ptlrpc_sec *sec,
 void gss_cli_ctx_flags2str(unsigned long flags, char *buf, int bufsize);
 
 /* gss_keyring.c */
 void gss_cli_ctx_flags2str(unsigned long flags, char *buf, int bufsize);
 
 /* gss_keyring.c */
-extern struct ptlrpc_sec_policy gss_policy_keyring;
 int  __init gss_init_keyring(void);
 void __exit gss_exit_keyring(void);
 
 int  __init gss_init_keyring(void);
 void __exit gss_exit_keyring(void);
 
@@ -438,6 +464,9 @@ __u64 gss_get_next_ctx_index(void);
 int gss_svc_upcall_install_rvs_ctx(struct obd_import *imp,
                                    struct gss_sec *gsec,
                                    struct gss_cli_ctx *gctx);
 int gss_svc_upcall_install_rvs_ctx(struct obd_import *imp,
                                    struct gss_sec *gsec,
                                    struct gss_cli_ctx *gctx);
+int gss_svc_upcall_expire_rvs_ctx(rawobj_t *handle);
+int gss_svc_upcall_dup_handle(rawobj_t *handle, struct gss_svc_ctx *ctx);
+int gss_svc_upcall_update_sequence(rawobj_t *handle, __u32 seq);
 int gss_svc_upcall_handle_init(struct ptlrpc_request *req,
                                struct gss_svc_reqctx *grctx,
                                struct gss_wire_ctx *gw,
 int gss_svc_upcall_handle_init(struct ptlrpc_request *req,
                                struct gss_svc_reqctx *grctx,
                                struct gss_wire_ctx *gw,
index ca5d529..f469791 100644 (file)
@@ -59,6 +59,10 @@ static struct key_type gss_key_type;
 static int sec_install_rctx_kr(struct ptlrpc_sec *sec,
                                struct ptlrpc_svc_ctx *svc_ctx);
 
 static int sec_install_rctx_kr(struct ptlrpc_sec *sec,
                                struct ptlrpc_svc_ctx *svc_ctx);
 
+#ifndef task_aux
+#define task_aux(tsk)           (tsk)
+#endif
+
 /*
  * the timeout is only for the case that upcall child process die abnormally.
  * in any other cases it should finally update kernel key. so we set this
 /*
  * the timeout is only for the case that upcall child process die abnormally.
  * in any other cases it should finally update kernel key. so we set this
@@ -213,37 +217,44 @@ static void ctx_destroy_kr(struct ptlrpc_cli_ctx *ctx)
 {
         struct ptlrpc_sec          *sec = ctx->cc_sec;
         struct gss_cli_ctx_keyring *gctx_kr = ctx2gctx_keyring(ctx);
 {
         struct ptlrpc_sec          *sec = ctx->cc_sec;
         struct gss_cli_ctx_keyring *gctx_kr = ctx2gctx_keyring(ctx);
-        int                         rc;
 
         CDEBUG(D_SEC, "destroying ctx %p\n", ctx);
 
         /* at this time the association with key has been broken. */
         LASSERT(sec);
 
         CDEBUG(D_SEC, "destroying ctx %p\n", ctx);
 
         /* at this time the association with key has been broken. */
         LASSERT(sec);
+        LASSERT(atomic_read(&sec->ps_refcount) > 0);
+        LASSERT(atomic_read(&sec->ps_nctx) > 0);
         LASSERT(test_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags) == 0);
         LASSERT(gctx_kr->gck_key == NULL);
 
         ctx_clear_timer_kr(ctx);
         LASSERT(gctx_kr->gck_timer == NULL);
 
         LASSERT(test_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags) == 0);
         LASSERT(gctx_kr->gck_key == NULL);
 
         ctx_clear_timer_kr(ctx);
         LASSERT(gctx_kr->gck_timer == NULL);
 
-        rc = gss_cli_ctx_fini_common(sec, ctx);
-        if (rc < 0)
+        if (gss_cli_ctx_fini_common(sec, ctx))
                 return;
 
         OBD_FREE_PTR(gctx_kr);
 
                 return;
 
         OBD_FREE_PTR(gctx_kr);
 
-        if (rc > 0) {
-                CWARN("released the last ctx, proceed to destroy sec %s@%p\n",
-                      sec->ps_policy->sp_name, sec);
-                sptlrpc_sec_destroy(sec);
+        atomic_dec(&sec->ps_nctx);
+        sptlrpc_sec_put(sec);
+}
+
+static void ctx_release_kr(struct ptlrpc_cli_ctx *ctx, int sync)
+{
+        if (sync) {
+                ctx_destroy_kr(ctx);
+        } else {
+                atomic_inc(&ctx->cc_refcount);
+                sptlrpc_gc_add_ctx(ctx);
         }
 }
 
         }
 }
 
-static void ctx_put_kr(struct ptlrpc_cli_ctx *ctx)
+static void ctx_put_kr(struct ptlrpc_cli_ctx *ctx, int sync)
 {
         LASSERT(atomic_read(&ctx->cc_refcount) > 0);
 
         if (atomic_dec_and_test(&ctx->cc_refcount))
 {
         LASSERT(atomic_read(&ctx->cc_refcount) > 0);
 
         if (atomic_dec_and_test(&ctx->cc_refcount))
-                ctx_destroy_kr(ctx);
+                ctx_release_kr(ctx, sync);
 }
 
 /*
 }
 
 /*
@@ -272,8 +283,7 @@ static inline void spin_unlock_if(spinlock_t *lock, int condition)
                 spin_unlock(lock);
 }
 
                 spin_unlock(lock);
 }
 
-static
-void ctx_enlist_kr(struct ptlrpc_cli_ctx *ctx, int is_root, int locked)
+static void ctx_enlist_kr(struct ptlrpc_cli_ctx *ctx, int is_root, int locked)
 {
         struct ptlrpc_sec      *sec = ctx->cc_sec;
         struct gss_sec_keyring *gsec_kr = sec2gsec_keyring(sec);
 {
         struct ptlrpc_sec      *sec = ctx->cc_sec;
         struct gss_sec_keyring *gsec_kr = sec2gsec_keyring(sec);
@@ -299,8 +309,7 @@ void ctx_enlist_kr(struct ptlrpc_cli_ctx *ctx, int is_root, int locked)
  *
  * return non-zero if we indeed unlist this ctx.
  */
  *
  * return non-zero if we indeed unlist this ctx.
  */
-static
-int ctx_unlist_kr(struct ptlrpc_cli_ctx *ctx, int locked)
+static int ctx_unlist_kr(struct ptlrpc_cli_ctx *ctx, int locked)
 {
         struct ptlrpc_sec       *sec = ctx->cc_sec;
         struct gss_sec_keyring  *gsec_kr = sec2gsec_keyring(sec);
 {
         struct ptlrpc_sec       *sec = ctx->cc_sec;
         struct gss_sec_keyring  *gsec_kr = sec2gsec_keyring(sec);
@@ -326,8 +335,7 @@ int ctx_unlist_kr(struct ptlrpc_cli_ctx *ctx, int locked)
  * bind a key with a ctx together.
  * caller must hold write lock of the key, as well as ref on key & ctx.
  */
  * bind a key with a ctx together.
  * caller must hold write lock of the key, as well as ref on key & ctx.
  */
-static
-void bind_key_ctx(struct key *key, struct ptlrpc_cli_ctx *ctx)
+static void bind_key_ctx(struct key *key, struct ptlrpc_cli_ctx *ctx)
 {
         LASSERT(atomic_read(&ctx->cc_refcount) > 0);
         LASSERT(atomic_read(&key->usage) > 0);
 {
         LASSERT(atomic_read(&ctx->cc_refcount) > 0);
         LASSERT(atomic_read(&key->usage) > 0);
@@ -345,8 +353,7 @@ void bind_key_ctx(struct key *key, struct ptlrpc_cli_ctx *ctx)
  * unbind a key and a ctx.
  * caller must hold write lock, as well as a ref of the key.
  */
  * unbind a key and a ctx.
  * caller must hold write lock, as well as a ref of the key.
  */
-static
-void unbind_key_ctx(struct key *key, struct ptlrpc_cli_ctx *ctx)
+static void unbind_key_ctx(struct key *key, struct ptlrpc_cli_ctx *ctx)
 {
         LASSERT(key->payload.data == ctx);
         LASSERT(test_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags) == 0);
 {
         LASSERT(key->payload.data == ctx);
         LASSERT(test_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags) == 0);
@@ -360,7 +367,7 @@ void unbind_key_ctx(struct key *key, struct ptlrpc_cli_ctx *ctx)
         /* once ctx get split from key, the timer is meaningless */
         ctx_clear_timer_kr(ctx);
 
         /* once ctx get split from key, the timer is meaningless */
         ctx_clear_timer_kr(ctx);
 
-        ctx_put_kr(ctx);
+        ctx_put_kr(ctx, 1);
         key_put(key);
 }
 
         key_put(key);
 }
 
@@ -434,7 +441,7 @@ static void dispose_ctx_list_kr(struct hlist_head *freelist)
                 sptlrpc_cli_ctx_wakeup(ctx);
 
                 unbind_ctx_kr(ctx);
                 sptlrpc_cli_ctx_wakeup(ctx);
 
                 unbind_ctx_kr(ctx);
-                ctx_put_kr(ctx);
+                ctx_put_kr(ctx, 0);
         }
 }
 
         }
 }
 
@@ -522,7 +529,7 @@ void rvs_sec_install_root_ctx_kr(struct ptlrpc_sec *sec,
 static void construct_key_desc(void *buf, int bufsize,
                                struct ptlrpc_sec *sec, uid_t uid)
 {
 static void construct_key_desc(void *buf, int bufsize,
                                struct ptlrpc_sec *sec, uid_t uid)
 {
-        snprintf(buf, bufsize, "%d@%x", uid, sec2gsec_keyring(sec)->gsk_id);
+        snprintf(buf, bufsize, "%d@%x", uid, sec->ps_id);
         ((char *)buf)[bufsize - 1] = '\0';
 }
 
         ((char *)buf)[bufsize - 1] = '\0';
 }
 
@@ -530,13 +537,10 @@ static void construct_key_desc(void *buf, int bufsize,
  * sec apis                             *
  ****************************************/
 
  * sec apis                             *
  ****************************************/
 
-static atomic_t gss_sec_id_kr = ATOMIC_INIT(0);
-
 static
 struct ptlrpc_sec * gss_sec_create_kr(struct obd_import *imp,
 static
 struct ptlrpc_sec * gss_sec_create_kr(struct obd_import *imp,
-                                      struct ptlrpc_svc_ctx *ctx,
-                                      __u32 flavor,
-                                      unsigned long flags)
+                                      struct ptlrpc_svc_ctx *svcctx,
+                                      struct sptlrpc_flavor *sf)
 {
         struct gss_sec_keyring  *gsec_kr;
         ENTRY;
 {
         struct gss_sec_keyring  *gsec_kr;
         ENTRY;
@@ -545,7 +549,6 @@ struct ptlrpc_sec * gss_sec_create_kr(struct obd_import *imp,
         if (gsec_kr == NULL)
                 RETURN(NULL);
 
         if (gsec_kr == NULL)
                 RETURN(NULL);
 
-        gsec_kr->gsk_id = atomic_inc_return(&gss_sec_id_kr);
         CFS_INIT_HLIST_HEAD(&gsec_kr->gsk_clist);
         gsec_kr->gsk_root_ctx = NULL;
         mutex_init(&gsec_kr->gsk_root_uc_lock);
         CFS_INIT_HLIST_HEAD(&gsec_kr->gsk_clist);
         gsec_kr->gsk_root_ctx = NULL;
         mutex_init(&gsec_kr->gsk_root_uc_lock);
@@ -554,14 +557,13 @@ struct ptlrpc_sec * gss_sec_create_kr(struct obd_import *imp,
 #endif
 
         if (gss_sec_create_common(&gsec_kr->gsk_base, &gss_policy_keyring,
 #endif
 
         if (gss_sec_create_common(&gsec_kr->gsk_base, &gss_policy_keyring,
-                                  imp, ctx, flavor, flags))
+                                  imp, svcctx, sf))
                 goto err_free;
 
                 goto err_free;
 
-        if (ctx != NULL) {
-                if (sec_install_rctx_kr(&gsec_kr->gsk_base.gs_base, ctx)) {
-                        gss_sec_destroy_common(&gsec_kr->gsk_base);
-                        goto err_free;
-                }
+        if (svcctx != NULL &&
+            sec_install_rctx_kr(&gsec_kr->gsk_base.gs_base, svcctx)) {
+                gss_sec_destroy_common(&gsec_kr->gsk_base);
+                goto err_free;
         }
 
         RETURN(&gsec_kr->gsk_base.gs_base);
         }
 
         RETURN(&gsec_kr->gsk_base.gs_base);
@@ -587,16 +589,14 @@ void gss_sec_destroy_kr(struct ptlrpc_sec *sec)
         OBD_FREE(gsec_kr, sizeof(*gsec_kr));
 }
 
         OBD_FREE(gsec_kr, sizeof(*gsec_kr));
 }
 
-static
-int user_is_root(struct ptlrpc_sec *sec, struct vfs_cred *vcred)
+static inline int user_is_root(struct ptlrpc_sec *sec, struct vfs_cred *vcred)
 {
 {
-        if (sec->ps_flags & PTLRPC_SEC_FL_ROOTONLY)
+        /* except the ROOTONLY flag, treat it as root user only if real uid
+         * is 0, euid/fsuid being 0 are handled as setuid scenarios */
+        if (sec_is_rootonly(sec) || (vcred->vc_uid == 0))
                 return 1;
                 return 1;
-
-        /* FIXME
-         * more precisely deal with setuid. maybe add more infomation
-         * into vfs_cred ?? */
-        return (vcred->vc_uid == 0);
+        else
+                return 0;
 }
 
 /*
 }
 
 /*
@@ -654,7 +654,7 @@ struct ptlrpc_cli_ctx * gss_sec_lookup_ctx_kr(struct ptlrpc_sec *sec,
         struct key              *key;
         char                     desc[24];
         char                    *coinfo;
         struct key              *key;
         char                     desc[24];
         char                    *coinfo;
-        const int                coinfo_size = sizeof(struct obd_uuid) + 64;
+        int                      coinfo_size;
         char                    *co_flags = "";
         ENTRY;
 
         char                    *co_flags = "";
         ENTRY;
 
@@ -691,15 +691,29 @@ struct ptlrpc_cli_ctx * gss_sec_lookup_ctx_kr(struct ptlrpc_sec *sec,
                 co_flags = "r";
         }
 
                 co_flags = "r";
         }
 
+        /* in case of setuid, key will be constructed as owner of fsuid/fsgid,
+         * but we do authentication based on real uid/gid. the key permission
+         * bits will be exactly as POS_ALL, so only processes who subscribed
+         * this key could have the access, although the quota might be counted
+         * on others (fsuid/fsgid).
+         *
+         * keyring will use fsuid/fsgid as upcall parameters, so we have to
+         * encode real uid/gid into callout info.
+         */
+
         construct_key_desc(desc, sizeof(desc), sec, vcred->vc_uid);
 
         construct_key_desc(desc, sizeof(desc), sec, vcred->vc_uid);
 
-        /* callout info: mech:flags:svc_type:peer_nid:target_uuid */
+        /* callout info format:
+         * secid:mech:uid:gid:flags:svc_type:peer_nid:target_uuid
+         */
+        coinfo_size = sizeof(struct obd_uuid) + MAX_OBD_NAME + 64;
         OBD_ALLOC(coinfo, coinfo_size);
         if (coinfo == NULL)
                 goto out;
 
         OBD_ALLOC(coinfo, coinfo_size);
         if (coinfo == NULL)
                 goto out;
 
-        snprintf(coinfo, coinfo_size, "%s:%s:%d:"LPX64":%s",
-                 sec2gsec(sec)->gs_mech->gm_name,
+        snprintf(coinfo, coinfo_size, "%d:%s:%u:%u:%s:%d:"LPX64":%s",
+                 sec->ps_id, sec2gsec(sec)->gs_mech->gm_name,
+                 vcred->vc_uid, vcred->vc_gid,
                  co_flags, import_to_gss_svc(imp),
                  imp->imp_connection->c_peer.nid, imp->imp_obd->obd_name);
 
                  co_flags, import_to_gss_svc(imp),
                  imp->imp_connection->c_peer.nid, imp->imp_obd->obd_name);
 
@@ -769,14 +783,9 @@ void gss_sec_release_ctx_kr(struct ptlrpc_sec *sec,
                             struct ptlrpc_cli_ctx *ctx,
                             int sync)
 {
                             struct ptlrpc_cli_ctx *ctx,
                             int sync)
 {
+        LASSERT(atomic_read(&sec->ps_refcount) > 0);
         LASSERT(atomic_read(&ctx->cc_refcount) == 0);
         LASSERT(atomic_read(&ctx->cc_refcount) == 0);
-
-        if (sync) {
-                ctx_destroy_kr(ctx);
-        } else {
-                atomic_inc(&ctx->cc_refcount);
-                sptlrpc_gc_add_ctx(ctx);
-        }
+        ctx_release_kr(ctx, sync);
 }
 
 /*
 }
 
 /*
@@ -865,13 +874,12 @@ void flush_spec_ctx_cache_kr(struct ptlrpc_sec *sec,
 
                 atomic_inc(&ctx->cc_refcount);
 
 
                 atomic_inc(&ctx->cc_refcount);
 
-                if (ctx_unlist_kr(ctx, 1))
+                if (ctx_unlist_kr(ctx, 1)) {
                         hlist_add_head(&ctx->cc_cache, &freelist);
                         hlist_add_head(&ctx->cc_cache, &freelist);
-                else {
+                else {
                         LASSERT(atomic_read(&ctx->cc_refcount) >= 2);
                         atomic_dec(&ctx->cc_refcount);
                 }
                         LASSERT(atomic_read(&ctx->cc_refcount) >= 2);
                         atomic_dec(&ctx->cc_refcount);
                 }
-
         }
         spin_unlock(&sec->ps_lock);
 
         }
         spin_unlock(&sec->ps_lock);
 
@@ -886,8 +894,8 @@ int gss_sec_flush_ctx_cache_kr(struct ptlrpc_sec *sec,
 {
         ENTRY;
 
 {
         ENTRY;
 
-        CDEBUG(D_SEC, "sec %p(%d, busy %d), uid %d, grace %d, force %d\n",
-               sec, atomic_read(&sec->ps_refcount), atomic_read(&sec->ps_busy),
+        CDEBUG(D_SEC, "sec %p(%d, nctx %d), uid %d, grace %d, force %d\n",
+               sec, atomic_read(&sec->ps_refcount), atomic_read(&sec->ps_nctx),
                uid, grace, force);
 
         if (uid != -1 && uid != 0)
                uid, grace, force);
 
         if (uid != -1 && uid != 0)
@@ -932,25 +940,21 @@ void gss_sec_gc_ctx_kr(struct ptlrpc_sec *sec)
 }
 
 static
 }
 
 static
-int gss_sec_display_kr(struct ptlrpc_sec *sec, char *buf, int bufsize)
+int gss_sec_display_kr(struct ptlrpc_sec *sec, struct seq_file *seq)
 {
         struct gss_sec_keyring *gsec_kr = sec2gsec_keyring(sec);
         struct hlist_node      *pos, *next;
         struct ptlrpc_cli_ctx  *ctx;
 {
         struct gss_sec_keyring *gsec_kr = sec2gsec_keyring(sec);
         struct hlist_node      *pos, *next;
         struct ptlrpc_cli_ctx  *ctx;
-        int                     written = 0;
+        struct gss_cli_ctx     *gctx;
+        time_t                  now = cfs_time_current_sec();
         ENTRY;
 
         ENTRY;
 
-        written = snprintf(buf, bufsize, "context list ===>\n");
-        bufsize -= written;
-        buf += written;
-
         spin_lock(&sec->ps_lock);
         hlist_for_each_entry_safe(ctx, pos, next,
                                   &gsec_kr->gsk_clist, cc_cache) {
         spin_lock(&sec->ps_lock);
         hlist_for_each_entry_safe(ctx, pos, next,
                                   &gsec_kr->gsk_clist, cc_cache) {
-                struct gss_cli_ctx     *gctx;
                 struct key             *key;
                 char                    flags_str[40];
                 struct key             *key;
                 char                    flags_str[40];
-                int                     len;
+                char                    mech[40];
 
                 gctx = ctx2gctx(ctx);
                 key = ctx2gctx_keyring(ctx)->gck_key;
 
                 gctx = ctx2gctx(ctx);
                 key = ctx2gctx_keyring(ctx)->gck_key;
@@ -958,40 +962,31 @@ int gss_sec_display_kr(struct ptlrpc_sec *sec, char *buf, int bufsize)
                 gss_cli_ctx_flags2str(ctx->cc_flags,
                                       flags_str, sizeof(flags_str));
 
                 gss_cli_ctx_flags2str(ctx->cc_flags,
                                       flags_str, sizeof(flags_str));
 
-                len = snprintf(buf, bufsize, "%p(%d): uid %u, exp %ld(%ld)s, "
-                               "fl %s, seq %d, win %u, key %08x(%d), ",
-                               ctx, atomic_read(&ctx->cc_refcount),
-                               ctx->cc_vcred.vc_uid,
-                               ctx->cc_expire,
-                               ctx->cc_expire - cfs_time_current_sec(),
-                               flags_str,
-                               atomic_read(&gctx->gc_seq),
-                               gctx->gc_win,
-                               key ? key->serial : 0,
-                               key ? atomic_read(&key->usage) : 0);
-
-                written += len;
-                buf += len;
-                bufsize -= len;
-
-                if (bufsize <= 0)
-                        break;
-
                 if (gctx->gc_mechctx)
                 if (gctx->gc_mechctx)
-                        len = lgss_display(gctx->gc_mechctx, buf, bufsize);
+                        lgss_display(gctx->gc_mechctx, mech, sizeof(mech));
                 else
                 else
-                        len = snprintf(buf, bufsize, "mech N/A\n");
-
-                written += len;
-                buf += len;
-                bufsize -= len;
-
-                if (bufsize <= 0)
-                        break;
+                        snprintf(mech, sizeof(mech), "N/A");
+                mech[sizeof(mech) - 1] = '\0';
+
+                seq_printf(seq, "%p: uid %u, ref %d, expire %ld(%+ld), fl %s, "
+                           "seq %d, win %u, key %08x(ref %d), "
+                           "hdl "LPX64":"LPX64", mech: %s\n",
+                           ctx, ctx->cc_vcred.vc_uid,
+                           atomic_read(&ctx->cc_refcount),
+                           ctx->cc_expire,
+                           ctx->cc_expire ?  ctx->cc_expire - now : 0,
+                           flags_str,
+                           atomic_read(&gctx->gc_seq),
+                           gctx->gc_win,
+                           key ? key->serial : 0,
+                           key ? atomic_read(&key->usage) : 0,
+                           gss_handle_to_u64(&gctx->gc_handle),
+                           gss_handle_to_u64(&gctx->gc_svc_handle),
+                           mech);
         }
         spin_unlock(&sec->ps_lock);
 
         }
         spin_unlock(&sec->ps_lock);
 
-        RETURN(written);
+        RETURN(0);
 }
 
 /****************************************
 }
 
 /****************************************
@@ -1063,13 +1058,13 @@ int sec_install_rctx_kr(struct ptlrpc_sec *sec,
         if (rc) {
                 CERROR("failed copy reverse cli ctx: %d\n", rc);
 
         if (rc) {
                 CERROR("failed copy reverse cli ctx: %d\n", rc);
 
-                ctx_put_kr(cli_ctx);
+                ctx_put_kr(cli_ctx, 1);
                 return rc;
         }
 
         rvs_sec_install_root_ctx_kr(sec, cli_ctx, NULL);
 
                 return rc;
         }
 
         rvs_sec_install_root_ctx_kr(sec, cli_ctx, NULL);
 
-        ctx_put_kr(cli_ctx);
+        ctx_put_kr(cli_ctx, 1);
 
         return 0;
 }
 
         return 0;
 }
@@ -1123,7 +1118,7 @@ int sec_install_rctx_kr(struct ptlrpc_sec *sec,
 
         rvs_sec_install_root_ctx_kr(sec, cli_ctx, key);
 
 
         rvs_sec_install_root_ctx_kr(sec, cli_ctx, key);
 
-        ctx_put_kr(cli_ctx);
+        ctx_put_kr(cli_ctx, 1);
         up_write(&key->sem);
 
         rc = 0;
         up_write(&key->sem);
 
         rc = 0;
@@ -1133,7 +1128,7 @@ out:
         return rc;
 
 err_put:
         return rc;
 
 err_put:
-        ctx_put_kr(cli_ctx);
+        ctx_put_kr(cli_ctx, 1);
 err_up:
         up_write(&key->sem);
 err_revoke:
 err_up:
         up_write(&key->sem);
 err_revoke:
@@ -1157,9 +1152,16 @@ static
 int gss_svc_install_rctx_kr(struct obd_import *imp,
                             struct ptlrpc_svc_ctx *svc_ctx)
 {
 int gss_svc_install_rctx_kr(struct obd_import *imp,
                             struct ptlrpc_svc_ctx *svc_ctx)
 {
-        LASSERT(imp->imp_sec);
+        struct ptlrpc_sec *sec;
+        int                rc;
 
 
-        return sec_install_rctx_kr(imp->imp_sec, svc_ctx);
+        sec = sptlrpc_import_sec_ref(imp);
+        LASSERT(sec);
+
+        rc = sec_install_rctx_kr(sec, svc_ctx);
+        sptlrpc_sec_put(sec);
+
+        return rc;
 }
 
 /****************************************
 }
 
 /****************************************
@@ -1169,6 +1171,7 @@ int gss_svc_install_rctx_kr(struct obd_import *imp,
 static
 int gss_kt_instantiate(struct key *key, const void *data, size_t datalen)
 {
 static
 int gss_kt_instantiate(struct key *key, const void *data, size_t datalen)
 {
+        int             rc;
         ENTRY;
 
         if (data != NULL || datalen != 0) {
         ENTRY;
 
         if (data != NULL || datalen != 0) {
@@ -1181,8 +1184,26 @@ int gss_kt_instantiate(struct key *key, const void *data, size_t datalen)
                 RETURN(-EINVAL);
         }
 
                 RETURN(-EINVAL);
         }
 
-        /* XXX */
-        key->perm |= KEY_POS_ALL | KEY_USR_ALL;
+        /* link the key to session keyring, so following context negotiation
+         * rpc fired from user space could find this key. This will be unlinked
+         * automatically when upcall processes die.
+         *
+         * we can't do this through keyctl from userspace, because the upcall
+         * might be neither possessor nor owner of the key (setuid).
+         *
+         * the session keyring is created upon upcall, and don't change all
+         * the way until upcall finished, so rcu lock is not needed here.
+         */
+        LASSERT(cfs_current()->signal->session_keyring);
+
+        rc = key_link(cfs_current()->signal->session_keyring, key);
+        if (unlikely(rc)) {
+                CERROR("failed to link key %08x to keyring %08x: %d\n",
+                       key->serial,
+                       cfs_current()->signal->session_keyring->serial, rc);
+                RETURN(rc);
+        }
+
         CDEBUG(D_SEC, "key %p instantiated, ctx %p\n", key, key->payload.data);
         RETURN(0);
 }
         CDEBUG(D_SEC, "key %p instantiated, ctx %p\n", key, key->payload.data);
         RETURN(0);
 }
@@ -1365,6 +1386,7 @@ static struct ptlrpc_ctx_ops gss_keyring_ctxops = {
 static struct ptlrpc_sec_cops gss_sec_keyring_cops = {
         .create_sec             = gss_sec_create_kr,
         .destroy_sec            = gss_sec_destroy_kr,
 static struct ptlrpc_sec_cops gss_sec_keyring_cops = {
         .create_sec             = gss_sec_create_kr,
         .destroy_sec            = gss_sec_destroy_kr,
+        .kill_sec               = gss_sec_kill,
         .lookup_ctx             = gss_sec_lookup_ctx_kr,
         .release_ctx            = gss_sec_release_ctx_kr,
         .flush_ctx_cache        = gss_sec_flush_ctx_cache_kr,
         .lookup_ctx             = gss_sec_lookup_ctx_kr,
         .release_ctx            = gss_sec_release_ctx_kr,
         .flush_ctx_cache        = gss_sec_flush_ctx_cache_kr,
index 50dcace..c2e068a 100644 (file)
@@ -1167,6 +1167,7 @@ out_free:
 
 static
 __u32 gss_plain_encrypt_kerberos(struct gss_ctx  *ctx,
 
 static
 __u32 gss_plain_encrypt_kerberos(struct gss_ctx  *ctx,
+                                 int              decrypt,
                                  int              length,
                                  void            *in_buf,
                                  void            *out_buf)
                                  int              length,
                                  void            *in_buf,
                                  void            *out_buf)
@@ -1174,7 +1175,7 @@ __u32 gss_plain_encrypt_kerberos(struct gss_ctx  *ctx,
         struct krb5_ctx        *kctx = ctx->internal_ctx_id;
         __u32                   rc;
 
         struct krb5_ctx        *kctx = ctx->internal_ctx_id;
         __u32                   rc;
 
-        rc = krb5_encrypt(kctx->kc_keye.kb_tfm, 0,
+        rc = krb5_encrypt(kctx->kc_keye.kb_tfm, decrypt,
                           NULL, in_buf, out_buf, length);
         if (rc)
                 CERROR("plain encrypt error: %d\n", rc);
                           NULL, in_buf, out_buf, length);
         if (rc)
                 CERROR("plain encrypt error: %d\n", rc);
@@ -1189,7 +1190,7 @@ int gss_display_kerberos(struct gss_ctx        *ctx,
         struct krb5_ctx    *kctx = ctx->internal_ctx_id;
         int                 written;
 
         struct krb5_ctx    *kctx = ctx->internal_ctx_id;
         int                 written;
 
-        written = snprintf(buf, bufsize, "mech: krb5 (%s)\n",
+        written = snprintf(buf, bufsize, "krb5 (%s)",
                            enctype2str(kctx->kc_enctype));
         return written;
 }
                            enctype2str(kctx->kc_enctype));
         return written;
 }
index 6e6386f..9b2965d 100644 (file)
@@ -290,6 +290,7 @@ __u32 lgss_unwrap(struct gss_ctx *context_handle,
 
 
 __u32 lgss_plain_encrypt(struct gss_ctx *ctx,
 
 
 __u32 lgss_plain_encrypt(struct gss_ctx *ctx,
+                         int decrypt,
                          int length,
                          void *in_buf,
                          void *out_buf)
                          int length,
                          void *in_buf,
                          void *out_buf)
@@ -300,7 +301,7 @@ __u32 lgss_plain_encrypt(struct gss_ctx *ctx,
         LASSERT(ctx->mech_type->gm_ops->gss_plain_encrypt);
 
         return ctx->mech_type->gm_ops
         LASSERT(ctx->mech_type->gm_ops->gss_plain_encrypt);
 
         return ctx->mech_type->gm_ops
-                ->gss_plain_encrypt(ctx, length, in_buf, out_buf);
+                ->gss_plain_encrypt(ctx, decrypt, length, in_buf, out_buf);
 }
 
 /* gss_delete_sec_context: free all resources associated with context_handle.
 }
 
 /* gss_delete_sec_context: free all resources associated with context_handle.
index d0a3456..53caace 100644 (file)
@@ -120,19 +120,14 @@ static
 void ctx_destroy_pf(struct ptlrpc_sec *sec, struct ptlrpc_cli_ctx *ctx)
 {
         struct gss_cli_ctx *gctx = ctx2gctx(ctx);
 void ctx_destroy_pf(struct ptlrpc_sec *sec, struct ptlrpc_cli_ctx *ctx)
 {
         struct gss_cli_ctx *gctx = ctx2gctx(ctx);
-        int                 rc;
 
 
-        rc = gss_cli_ctx_fini_common(sec, ctx);
-        if (rc < 0)
+        if (gss_cli_ctx_fini_common(sec, ctx))
                 return;
 
         OBD_FREE_PTR(gctx);
 
                 return;
 
         OBD_FREE_PTR(gctx);
 
-        if (rc > 0) {
-                CWARN("released the last ctx, proceed to destroy sec %s@%p\n",
-                      sec->ps_policy->sp_name, sec);
-                sptlrpc_sec_destroy(sec);
-        }
+        atomic_dec(&sec->ps_nctx);
+        sptlrpc_sec_put(sec);
 }
 
 static
 }
 
 static
@@ -292,7 +287,6 @@ void gss_sec_ctx_replace_pf(struct gss_sec *gsec,
         }
 
         ctx_enhash_pf(new, &gsec_pf->gsp_chash[hash]);
         }
 
         ctx_enhash_pf(new, &gsec_pf->gsp_chash[hash]);
-        atomic_inc(&gsec->gs_base.ps_busy);
 
         spin_unlock(&gsec->gs_base.ps_lock);
 
 
         spin_unlock(&gsec->gs_base.ps_lock);
 
@@ -353,8 +347,7 @@ void gss_ctx_cache_gc_pf(struct gss_sec_pipefs *gsec_pf,
 static
 struct ptlrpc_sec* gss_sec_create_pf(struct obd_import *imp,
                                      struct ptlrpc_svc_ctx *ctx,
 static
 struct ptlrpc_sec* gss_sec_create_pf(struct obd_import *imp,
                                      struct ptlrpc_svc_ctx *ctx,
-                                     __u32 flavor,
-                                     unsigned long flags)
+                                     struct sptlrpc_flavor *sf)
 {
         struct gss_sec_pipefs   *gsec_pf;
         int                      alloc_size, hash_size, i;
 {
         struct gss_sec_pipefs   *gsec_pf;
         int                      alloc_size, hash_size, i;
@@ -362,7 +355,8 @@ struct ptlrpc_sec* gss_sec_create_pf(struct obd_import *imp,
 
 #define GSS_SEC_PIPEFS_CTX_HASH_SIZE    (32)
 
 
 #define GSS_SEC_PIPEFS_CTX_HASH_SIZE    (32)
 
-        if (ctx || flags & (PTLRPC_SEC_FL_ROOTONLY | PTLRPC_SEC_FL_REVERSE))
+        if (ctx ||
+            sf->sf_flags & (PTLRPC_SEC_FL_ROOTONLY | PTLRPC_SEC_FL_REVERSE))
                 hash_size = 1;
         else
                 hash_size = GSS_SEC_PIPEFS_CTX_HASH_SIZE;
                 hash_size = 1;
         else
                 hash_size = GSS_SEC_PIPEFS_CTX_HASH_SIZE;
@@ -379,7 +373,7 @@ struct ptlrpc_sec* gss_sec_create_pf(struct obd_import *imp,
                 CFS_INIT_HLIST_HEAD(&gsec_pf->gsp_chash[i]);
 
         if (gss_sec_create_common(&gsec_pf->gsp_base, &gss_policy_pipefs,
                 CFS_INIT_HLIST_HEAD(&gsec_pf->gsp_chash[i]);
 
         if (gss_sec_create_common(&gsec_pf->gsp_base, &gss_policy_pipefs,
-                                  imp, ctx, flavor, flags))
+                                  imp, ctx, sf))
                 goto err_free;
 
         if (ctx == NULL) {
                 goto err_free;
 
         if (ctx == NULL) {
@@ -609,13 +603,15 @@ static
 int gss_svc_install_rctx_pf(struct obd_import *imp,
                             struct ptlrpc_svc_ctx *ctx)
 {
 int gss_svc_install_rctx_pf(struct obd_import *imp,
                             struct ptlrpc_svc_ctx *ctx)
 {
-        struct gss_sec *gsec;
+        struct ptlrpc_sec *sec;
+        int                rc;
 
 
-        LASSERT(imp->imp_sec);
-        LASSERT(ctx);
+        sec = sptlrpc_import_sec_ref(imp);
+        LASSERT(sec);
+        rc = gss_install_rvs_cli_ctx_pf(sec2gsec(sec), ctx);
 
 
-        gsec = container_of(imp->imp_sec, struct gss_sec, gs_base);
-        return gss_install_rvs_cli_ctx_pf(gsec, ctx);
+        sptlrpc_sec_put(sec);
+        return rc;
 }
 
 /****************************************
 }
 
 /****************************************
@@ -1154,6 +1150,7 @@ static struct ptlrpc_ctx_ops gss_pipefs_ctxops = {
 static struct ptlrpc_sec_cops gss_sec_pipefs_cops = {
         .create_sec             = gss_sec_create_pf,
         .destroy_sec            = gss_sec_destroy_pf,
 static struct ptlrpc_sec_cops gss_sec_pipefs_cops = {
         .create_sec             = gss_sec_create_pf,
         .destroy_sec            = gss_sec_destroy_pf,
+        .kill_sec               = gss_sec_kill,
         .lookup_ctx             = gss_sec_lookup_ctx_pf,
         .release_ctx            = gss_sec_release_ctx_pf,
         .flush_ctx_cache        = gss_sec_flush_ctx_cache_pf,
         .lookup_ctx             = gss_sec_lookup_ctx_pf,
         .release_ctx            = gss_sec_release_ctx_pf,
         .flush_ctx_cache        = gss_sec_flush_ctx_cache_pf,
index 75343c9..5765f41 100644 (file)
 
 #include "gss_internal.h"
 
 
 #include "gss_internal.h"
 
+int rawobj_empty(rawobj_t *obj)
+{
+        LASSERT(equi(obj->len, obj->data));
+        return (obj->len == 0);
+}
+
 int rawobj_alloc(rawobj_t *obj, char *buf, int len)
 {
         LASSERT(obj);
 int rawobj_alloc(rawobj_t *obj, char *buf, int len)
 {
         LASSERT(obj);
index 76c6b4d..72438ae 100644 (file)
 #include <linux/slab.h>
 #include <linux/hash.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/hash.h>
 #include <linux/mutex.h>
+#include <linux/sunrpc/cache.h>
 #else
 #include <liblustre.h>
 #endif
 
 #else
 #include <liblustre.h>
 #endif
 
-#include <linux/sunrpc/cache.h>
-
 #include <obd.h>
 #include <obd_class.h>
 #include <obd_support.h>
 #include <obd.h>
 #include <obd_class.h>
 #include <obd_support.h>
@@ -88,8 +87,7 @@ __u64 gss_get_next_ctx_index(void)
         return idx;
 }
 
         return idx;
 }
 
-static inline
-unsigned long hash_mem(char *buf, int length, int bits)
+static inline unsigned long hash_mem(char *buf, int length, int bits)
 {
         unsigned long hash = 0;
         unsigned long l = 0;
 {
         unsigned long hash = 0;
         unsigned long l = 0;
@@ -135,8 +133,7 @@ static struct cache_head *rsi_table[RSI_HASHMAX];
 static struct cache_detail rsi_cache;
 static struct rsi *rsi_lookup(struct rsi *item, int set);
 
 static struct cache_detail rsi_cache;
 static struct rsi *rsi_lookup(struct rsi *item, int set);
 
-static
-void rsi_free(struct rsi *rsi)
+static void rsi_free(struct rsi *rsi)
 {
         rawobj_free(&rsi->in_handle);
         rawobj_free(&rsi->in_token);
 {
         rawobj_free(&rsi->in_handle);
         rawobj_free(&rsi->in_token);
@@ -144,8 +141,7 @@ void rsi_free(struct rsi *rsi)
         rawobj_free(&rsi->out_token);
 }
 
         rawobj_free(&rsi->out_token);
 }
 
-static
-void rsi_put(struct cache_head *item, struct cache_detail *cd)
+static void rsi_put(struct cache_head *item, struct cache_detail *cd)
 {
         struct rsi *rsi = container_of(item, struct rsi, h);
 
 {
         struct rsi *rsi = container_of(item, struct rsi, h);
 
@@ -158,8 +154,7 @@ void rsi_put(struct cache_head *item, struct cache_detail *cd)
         }
 }
 
         }
 }
 
-static inline
-int rsi_hash(struct rsi *item)
+static inline int rsi_hash(struct rsi *item)
 {
         return hash_mem((char *)item->in_handle.data, item->in_handle.len,
                         RSI_HASHBITS) ^
 {
         return hash_mem((char *)item->in_handle.data, item->in_handle.len,
                         RSI_HASHBITS) ^
@@ -167,15 +162,13 @@ int rsi_hash(struct rsi *item)
                         RSI_HASHBITS);
 }
 
                         RSI_HASHBITS);
 }
 
-static inline
-int rsi_match(struct rsi *item, struct rsi *tmp)
+static inline int rsi_match(struct rsi *item, struct rsi *tmp)
 {
         return (rawobj_equal(&item->in_handle, &tmp->in_handle) &&
                 rawobj_equal(&item->in_token, &tmp->in_token));
 }
 
 {
         return (rawobj_equal(&item->in_handle, &tmp->in_handle) &&
                 rawobj_equal(&item->in_token, &tmp->in_token));
 }
 
-static
-void rsi_request(struct cache_detail *cd,
+static void rsi_request(struct cache_detail *cd,
                  struct cache_head *h,
                  char **bpp, int *blen)
 {
                  struct cache_head *h,
                  char **bpp, int *blen)
 {
@@ -195,8 +188,7 @@ void rsi_request(struct cache_detail *cd,
         (*bpp)[-1] = '\n';
 }
 
         (*bpp)[-1] = '\n';
 }
 
-static inline
-void rsi_init(struct rsi *new, struct rsi *item)
+static inline void rsi_init(struct rsi *new, struct rsi *item)
 {
         new->out_handle = RAWOBJ_EMPTY;
         new->out_token = RAWOBJ_EMPTY;
 {
         new->out_handle = RAWOBJ_EMPTY;
         new->out_token = RAWOBJ_EMPTY;
@@ -211,8 +203,7 @@ void rsi_init(struct rsi *new, struct rsi *item)
         init_waitqueue_head(&new->waitq);
 }
 
         init_waitqueue_head(&new->waitq);
 }
 
-static inline
-void rsi_update(struct rsi *new, struct rsi *item)
+static inline void rsi_update(struct rsi *new, struct rsi *item)
 {
         LASSERT(new->out_handle.len == 0);
         LASSERT(new->out_token.len == 0);
 {
         LASSERT(new->out_handle.len == 0);
         LASSERT(new->out_token.len == 0);
@@ -226,8 +217,7 @@ void rsi_update(struct rsi *new, struct rsi *item)
         new->minor_status = item->minor_status;
 }
 
         new->minor_status = item->minor_status;
 }
 
-static
-int rsi_parse(struct cache_detail *cd, char *mesg, int mlen)
+static int rsi_parse(struct cache_detail *cd, char *mesg, int mlen)
 {
         char           *buf = mesg;
         char           *ep;
 {
         char           *buf = mesg;
         char           *ep;
@@ -343,16 +333,14 @@ static struct cache_head *rsc_table[RSC_HASHMAX];
 static struct cache_detail rsc_cache;
 static struct rsc *rsc_lookup(struct rsc *item, int set);
 
 static struct cache_detail rsc_cache;
 static struct rsc *rsc_lookup(struct rsc *item, int set);
 
-static
-void rsc_free(struct rsc *rsci)
+static void rsc_free(struct rsc *rsci)
 {
         rawobj_free(&rsci->handle);
         rawobj_free(&rsci->ctx.gsc_rvs_hdl);
         lgss_delete_sec_context(&rsci->ctx.gsc_mechctx);
 }
 
 {
         rawobj_free(&rsci->handle);
         rawobj_free(&rsci->ctx.gsc_rvs_hdl);
         lgss_delete_sec_context(&rsci->ctx.gsc_mechctx);
 }
 
-static
-void rsc_put(struct cache_head *item, struct cache_detail *cd)
+static void rsc_put(struct cache_head *item, struct cache_detail *cd)
 {
         struct rsc *rsci = container_of(item, struct rsc, h);
 
 {
         struct rsc *rsci = container_of(item, struct rsc, h);
 
@@ -365,21 +353,18 @@ void rsc_put(struct cache_head *item, struct cache_detail *cd)
         }
 }
 
         }
 }
 
-static inline
-int rsc_hash(struct rsc *rsci)
+static inline int rsc_hash(struct rsc *rsci)
 {
         return hash_mem((char *)rsci->handle.data,
                         rsci->handle.len, RSC_HASHBITS);
 }
 
 {
         return hash_mem((char *)rsci->handle.data,
                         rsci->handle.len, RSC_HASHBITS);
 }
 
-static inline
-int rsc_match(struct rsc *new, struct rsc *tmp)
+static inline int rsc_match(struct rsc *new, struct rsc *tmp)
 {
         return rawobj_equal(&new->handle, &tmp->handle);
 }
 
 {
         return rawobj_equal(&new->handle, &tmp->handle);
 }
 
-static inline
-void rsc_init(struct rsc *new, struct rsc *tmp)
+static inline void rsc_init(struct rsc *new, struct rsc *tmp)
 {
         new->handle = tmp->handle;
         tmp->handle = RAWOBJ_EMPTY;
 {
         new->handle = tmp->handle;
         tmp->handle = RAWOBJ_EMPTY;
@@ -389,8 +374,7 @@ void rsc_init(struct rsc *new, struct rsc *tmp)
         new->ctx.gsc_rvs_hdl = RAWOBJ_EMPTY;
 }
 
         new->ctx.gsc_rvs_hdl = RAWOBJ_EMPTY;
 }
 
-static inline
-void rsc_update(struct rsc *new, struct rsc *tmp)
+static inline void rsc_update(struct rsc *new, struct rsc *tmp)
 {
         new->ctx = tmp->ctx;
         tmp->ctx.gsc_rvs_hdl = RAWOBJ_EMPTY;
 {
         new->ctx = tmp->ctx;
         tmp->ctx.gsc_rvs_hdl = RAWOBJ_EMPTY;
@@ -400,8 +384,7 @@ void rsc_update(struct rsc *new, struct rsc *tmp)
         spin_lock_init(&new->ctx.gsc_seqdata.ssd_lock);
 }
 
         spin_lock_init(&new->ctx.gsc_seqdata.ssd_lock);
 }
 
-static
-int rsc_parse(struct cache_detail *cd, char *mesg, int mlen)
+static int rsc_parse(struct cache_detail *cd, char *mesg, int mlen)
 {
         char       *buf = mesg;
         int         len, rv, tmp_int;
 {
         char       *buf = mesg;
         int         len, rv, tmp_int;
@@ -527,8 +510,7 @@ out:
 
 typedef int rsc_entry_match(struct rsc *rscp, long data);
 
 
 typedef int rsc_entry_match(struct rsc *rscp, long data);
 
-static
-void rsc_flush(rsc_entry_match *match, long data)
+static void rsc_flush(rsc_entry_match *match, long data)
 {
         struct cache_head **ch;
         struct rsc *rscp;
 {
         struct cache_head **ch;
         struct rsc *rscp;
@@ -558,22 +540,19 @@ void rsc_flush(rsc_entry_match *match, long data)
         EXIT;
 }
 
         EXIT;
 }
 
-static
-int match_uid(struct rsc *rscp, long uid)
+static int match_uid(struct rsc *rscp, long uid)
 {
         if ((int) uid == -1)
                 return 1;
         return ((int) rscp->ctx.gsc_uid == (int) uid);
 }
 
 {
         if ((int) uid == -1)
                 return 1;
         return ((int) rscp->ctx.gsc_uid == (int) uid);
 }
 
-static
-int match_target(struct rsc *rscp, long target)
+static int match_target(struct rsc *rscp, long target)
 {
         return (rscp->target == (struct obd_device *) target);
 }
 
 {
         return (rscp->target == (struct obd_device *) target);
 }
 
-static inline
-void rsc_flush_uid(int uid)
+static inline void rsc_flush_uid(int uid)
 {
         if (uid == -1)
                 CWARN("flush all gss contexts...\n");
 {
         if (uid == -1)
                 CWARN("flush all gss contexts...\n");
@@ -581,8 +560,7 @@ void rsc_flush_uid(int uid)
         rsc_flush(match_uid, (long) uid);
 }
 
         rsc_flush(match_uid, (long) uid);
 }
 
-static inline
-void rsc_flush_target(struct obd_device *target)
+static inline void rsc_flush_target(struct obd_device *target)
 {
         rsc_flush(match_target, (long) target);
 }
 {
         rsc_flush(match_target, (long) target);
 }
@@ -603,8 +581,7 @@ static struct cache_detail rsc_cache = {
 
 static DefineSimpleCacheLookup(rsc, 0);
 
 
 static DefineSimpleCacheLookup(rsc, 0);
 
-static
-struct rsc *gss_svc_searchbyctx(rawobj_t *handle)
+static struct rsc *gss_svc_searchbyctx(rawobj_t *handle)
 {
         struct rsc  rsci;
         struct rsc *found;
 {
         struct rsc  rsci;
         struct rsc *found;
@@ -658,17 +635,63 @@ int gss_svc_upcall_install_rvs_ctx(struct obd_import *imp,
 
         rscp = rsc_lookup(&rsci, 1);
         rsc_free(&rsci);
 
         rscp = rsc_lookup(&rsci, 1);
         rsc_free(&rsci);
-        if (rscp)
-                rsc_put(&rscp->h, &rsc_cache);
+        if (rscp) {
+                /* FIXME */
+                rscp->ctx.gsc_usr_root = 1;
+                rscp->ctx.gsc_usr_mds= 1;
+                rscp->ctx.gsc_reverse = 1;
+
+                rawobj_dup(&gctx->gc_svc_handle, &rscp->handle);
 
 
-        CDEBUG(D_SEC, "client installed reverse svc ctx to %s: idx "LPX64"\n",
-               imp->imp_obd->u.cli.cl_target_uuid.uuid, gsec->gs_rvs_hdl);
+                CWARN("create reverse svc ctx %p to %s: idx "LPX64"\n",
+                      &rscp->ctx, obd2cli_tgt(imp->imp_obd),
+                      gsec->gs_rvs_hdl);
+
+                rsc_put(&rscp->h, &rsc_cache);
+        }
 
         RETURN(0);
 }
 
 
         RETURN(0);
 }
 
-static
-struct cache_deferred_req* cache_upcall_defer(struct cache_req *req)
+int gss_svc_upcall_expire_rvs_ctx(rawobj_t *handle)
+{
+        const cfs_time_t        expire = 20;
+        struct rsc             *rscp;
+
+        rscp = gss_svc_searchbyctx(handle);
+        if (rscp) {
+                CDEBUG(D_SEC, "reverse svcctx %p (rsc %p) expire soon\n",
+                       &rscp->ctx, rscp);
+
+                rscp->h.expiry_time = cfs_time_current_sec() + expire;
+                rsc_put(&rscp->h, &rsc_cache);
+        }
+        return 0;
+}
+
+int gss_svc_upcall_dup_handle(rawobj_t *handle, struct gss_svc_ctx *ctx)
+{
+        struct rsc *rscp = container_of(ctx, struct rsc, ctx);
+
+        return rawobj_dup(handle, &rscp->handle);
+}
+
+int gss_svc_upcall_update_sequence(rawobj_t *handle, __u32 seq)
+{
+        struct rsc             *rscp;
+
+        rscp = gss_svc_searchbyctx(handle);
+        if (rscp) {
+                CDEBUG(D_SEC, "reverse svcctx %p (rsc %p) update seq to %u\n",
+                       &rscp->ctx, rscp, seq + 1);
+
+                rscp->ctx.gsc_rvs_seq = seq + 1;
+                rsc_put(&rscp->h, &rsc_cache);
+        }
+        return 0;
+}
+
+static struct cache_deferred_req* cache_upcall_defer(struct cache_req *req)
 {
         return NULL;
 }
 {
         return NULL;
 }
@@ -844,6 +867,9 @@ out:
                 /* if anything went wrong, we don't keep the context too */
                 if (rc != SECSVC_OK)
                         set_bit(CACHE_NEGATIVE, &rsci->h.flags);
                 /* if anything went wrong, we don't keep the context too */
                 if (rc != SECSVC_OK)
                         set_bit(CACHE_NEGATIVE, &rsci->h.flags);
+                else
+                        CDEBUG(D_SEC, "create rsc with idx "LPX64"\n",
+                               gss_handle_to_u64(&rsci->handle));
 
                 rsc_put(&rsci->h, &rsc_cache);
         }
 
                 rsc_put(&rsci->h, &rsc_cache);
         }
@@ -857,7 +883,8 @@ struct gss_svc_ctx *gss_svc_upcall_get_ctx(struct ptlrpc_request *req,
 
         rsc = gss_svc_searchbyctx(&gw->gw_handle);
         if (!rsc) {
 
         rsc = gss_svc_searchbyctx(&gw->gw_handle);
         if (!rsc) {
-                CWARN("Invalid gss context handle from %s\n",
+                CWARN("Invalid gss ctx idx "LPX64" from %s\n",
+                      gss_handle_to_u64(&gw->gw_handle),
                       libcfs_nid2str(req->rq_peer.nid));
                 return NULL;
         }
                       libcfs_nid2str(req->rq_peer.nid));
                 return NULL;
         }
@@ -876,7 +903,10 @@ void gss_svc_upcall_destroy_ctx(struct gss_svc_ctx *ctx)
 {
         struct rsc *rsc = container_of(ctx, struct rsc, ctx);
 
 {
         struct rsc *rsc = container_of(ctx, struct rsc, ctx);
 
+        /* can't be found */
         set_bit(CACHE_NEGATIVE, &rsc->h.flags);
         set_bit(CACHE_NEGATIVE, &rsc->h.flags);
+        /* to be removed at next scan */
+        rsc->h.expiry_time = 1;
 }
 
 int __init gss_init_svc_upcall(void)
 }
 
 int __init gss_init_svc_upcall(void)
index 1337b8e..8f19122 100644 (file)
@@ -94,14 +94,11 @@ static inline int msg_last_seglen(struct lustre_msg *msg)
 static
 void gss_header_swabber(struct gss_header *ghdr)
 {
 static
 void gss_header_swabber(struct gss_header *ghdr)
 {
-        __swab32s(&ghdr->gh_version);
         __swab32s(&ghdr->gh_flags);
         __swab32s(&ghdr->gh_proc);
         __swab32s(&ghdr->gh_seq);
         __swab32s(&ghdr->gh_svc);
         __swab32s(&ghdr->gh_pad1);
         __swab32s(&ghdr->gh_flags);
         __swab32s(&ghdr->gh_proc);
         __swab32s(&ghdr->gh_seq);
         __swab32s(&ghdr->gh_svc);
         __swab32s(&ghdr->gh_pad1);
-        __swab32s(&ghdr->gh_pad2);
-        __swab32s(&ghdr->gh_pad3);
         __swab32s(&ghdr->gh_handle.len);
 }
 
         __swab32s(&ghdr->gh_handle.len);
 }
 
@@ -167,11 +164,11 @@ int gss_estimate_payload(struct gss_ctx *mechctx, int msgsize, int privacy)
 /*
  * return signature size, otherwise < 0 to indicate error
  */
 /*
  * return signature size, otherwise < 0 to indicate error
  */
-static
-int gss_sign_msg(struct lustre_msg *msg,
-                 struct gss_ctx *mechctx,
-                 __u32 proc, __u32 seq, __u32 svc,
-                 rawobj_t *handle)
+static int gss_sign_msg(struct lustre_msg *msg,
+                        struct gss_ctx *mechctx,
+                        enum lustre_sec_part sp,
+                        __u32 flags, __u32 proc, __u32 seq, __u32 svc,
+                        rawobj_t *handle)
 {
         struct gss_header      *ghdr;
         rawobj_t                text[3], mic;
 {
         struct gss_header      *ghdr;
         rawobj_t                text[3], mic;
@@ -186,7 +183,8 @@ int gss_sign_msg(struct lustre_msg *msg,
         ghdr = lustre_msg_buf(msg, 0, 0);
 
         ghdr->gh_version = PTLRPC_GSS_VERSION;
         ghdr = lustre_msg_buf(msg, 0, 0);
 
         ghdr->gh_version = PTLRPC_GSS_VERSION;
-        ghdr->gh_flags = 0;
+        ghdr->gh_sp = (__u8) sp;
+        ghdr->gh_flags = flags;
         ghdr->gh_proc = proc;
         ghdr->gh_seq = seq;
         ghdr->gh_svc = svc;
         ghdr->gh_proc = proc;
         ghdr->gh_seq = seq;
         ghdr->gh_svc = svc;
@@ -329,26 +327,18 @@ int cli_ctx_expire(struct ptlrpc_cli_ctx *ctx)
         LASSERT(atomic_read(&ctx->cc_refcount));
 
         if (!test_and_set_bit(PTLRPC_CTX_DEAD_BIT, &ctx->cc_flags)) {
         LASSERT(atomic_read(&ctx->cc_refcount));
 
         if (!test_and_set_bit(PTLRPC_CTX_DEAD_BIT, &ctx->cc_flags)) {
-                cfs_time_t now;
-
                 if (!ctx->cc_early_expire)
                         clear_bit(PTLRPC_CTX_UPTODATE_BIT, &ctx->cc_flags);
 
                 if (!ctx->cc_early_expire)
                         clear_bit(PTLRPC_CTX_UPTODATE_BIT, &ctx->cc_flags);
 
-                now = cfs_time_current_sec();
-                if (ctx->cc_expire && cfs_time_aftereq(now, ctx->cc_expire))
-                        CWARN("ctx %p(%u->%s): get expired (%lds exceeds)\n",
-                              ctx, ctx->cc_vcred.vc_uid,
-                              sec2target_str(ctx->cc_sec),
-                              cfs_time_sub(now, ctx->cc_expire));
-                else
-                        CWARN("ctx %p(%u->%s): force to die (%lds remains)\n",
-                              ctx, ctx->cc_vcred.vc_uid,
-                              sec2target_str(ctx->cc_sec),
-                              ctx->cc_expire == 0 ? 0 :
-                              cfs_time_sub(ctx->cc_expire, now));
+                CWARN("ctx %p(%u->%s) get expired: %lu(%+lds)\n",
+                      ctx, ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec),
+                      ctx->cc_expire,
+                      ctx->cc_expire == 0 ? 0 :
+                      cfs_time_sub(ctx->cc_expire, cfs_time_current_sec()));
 
                 return 1;
         }
 
                 return 1;
         }
+
         return 0;
 }
 
         return 0;
 }
 
@@ -385,7 +375,7 @@ void gss_cli_ctx_uptodate(struct gss_cli_ctx *gctx)
         }
 
         ctx->cc_expire = gss_round_ctx_expiry(ctx_expiry,
         }
 
         ctx->cc_expire = gss_round_ctx_expiry(ctx_expiry,
-                                              ctx->cc_sec->ps_flags);
+                                              ctx->cc_sec->ps_flvr.sf_flags);
 
         /* At this point this ctx might have been marked as dead by
          * someone else, in which case nobody will make further use
 
         /* At this point this ctx might have been marked as dead by
          * someone else, in which case nobody will make further use
@@ -393,33 +383,46 @@ void gss_cli_ctx_uptodate(struct gss_cli_ctx *gctx)
          * destroying server side context when it be destroied. */
         set_bit(PTLRPC_CTX_UPTODATE_BIT, &ctx->cc_flags);
 
          * destroying server side context when it be destroied. */
         set_bit(PTLRPC_CTX_UPTODATE_BIT, &ctx->cc_flags);
 
-        if (sec_is_reverse(ctx->cc_sec))
-                CDEBUG(D_SEC, "server installed reverse ctx %p, "
-                       "will expire at %lu(%lds lifetime)\n",
-                       ctx, ctx->cc_expire,
-                       ctx->cc_expire - cfs_time_current_sec());
-        else
-                CWARN("client refreshed ctx %p(%u->%s), will expire at "
-                      "%lu(%lds lifetime)\n", ctx, ctx->cc_vcred.vc_uid,
-                      sec2target_str(ctx->cc_sec), ctx->cc_expire,
-                      ctx->cc_expire - cfs_time_current_sec());
+        if (sec_is_reverse(ctx->cc_sec)) {
+                CWARN("server installed reverse ctx %p idx "LPX64", "
+                      "expiry %lu(%+lds)\n", ctx,
+                      gss_handle_to_u64(&gctx->gc_handle),
+                      ctx->cc_expire, ctx->cc_expire - cfs_time_current_sec());
+        } else {
+                CWARN("client refreshed ctx %p idx "LPX64" (%u->%s), "
+                      "expiry %lu(%+lds)\n", ctx,
+                      gss_handle_to_u64(&gctx->gc_handle),
+                      ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec),
+                      ctx->cc_expire, ctx->cc_expire - cfs_time_current_sec());
 
 
-        /* install reverse svc ctx, but only for forward connection
-         * and root context */
-        if (!sec_is_reverse(ctx->cc_sec) && ctx->cc_vcred.vc_uid == 0) {
-                gss_sec_install_rctx(ctx->cc_sec->ps_import,
-                                     ctx->cc_sec, ctx);
+                /* install reverse svc ctx for root context */
+                if (ctx->cc_vcred.vc_uid == 0)
+                        gss_sec_install_rctx(ctx->cc_sec->ps_import,
+                                             ctx->cc_sec, ctx);
         }
 }
 
         }
 }
 
-static
-void gss_cli_ctx_finalize(struct gss_cli_ctx *gctx)
+static void gss_cli_ctx_finalize(struct gss_cli_ctx *gctx)
 {
 {
+        LASSERT(gctx->gc_base.cc_sec);
+
         if (gctx->gc_mechctx) {
                 lgss_delete_sec_context(&gctx->gc_mechctx);
                 gctx->gc_mechctx = NULL;
         }
 
         if (gctx->gc_mechctx) {
                 lgss_delete_sec_context(&gctx->gc_mechctx);
                 gctx->gc_mechctx = NULL;
         }
 
+        if (!rawobj_empty(&gctx->gc_svc_handle)) {
+                /* forward ctx: mark buddy reverse svcctx soon-expire.
+                 * reverse ctx: update current seq to buddy svcctx. */
+                if (!sec_is_reverse(gctx->gc_base.cc_sec))
+                        gss_svc_upcall_expire_rvs_ctx(&gctx->gc_svc_handle);
+                else
+                        gss_svc_upcall_update_sequence(&gctx->gc_svc_handle,
+                                        (__u32) atomic_read(&gctx->gc_seq));
+
+                rawobj_free(&gctx->gc_svc_handle);
+        }
+
         rawobj_free(&gctx->gc_handle);
 }
 
         rawobj_free(&gctx->gc_handle);
 }
 
@@ -612,8 +615,8 @@ void gss_cli_ctx_flags2str(unsigned long flags, char *buf, int bufsize)
 int gss_cli_ctx_sign(struct ptlrpc_cli_ctx *ctx,
                      struct ptlrpc_request *req)
 {
 int gss_cli_ctx_sign(struct ptlrpc_cli_ctx *ctx,
                      struct ptlrpc_request *req)
 {
-        struct gss_cli_ctx      *gctx;
-        __u32                    seq, svc;
+        struct gss_cli_ctx      *gctx = ctx2gctx(ctx);
+        __u32                    flags = 0, seq, svc;
         int                      rc;
         ENTRY;
 
         int                      rc;
         ENTRY;
 
@@ -625,13 +628,18 @@ int gss_cli_ctx_sign(struct ptlrpc_cli_ctx *ctx,
         if (req->rq_ctx_init)
                 RETURN(0);
 
         if (req->rq_ctx_init)
                 RETURN(0);
 
-        gctx = container_of(ctx, struct gss_cli_ctx, gc_base);
-        svc = SEC_FLAVOR_SVC(req->rq_sec_flavor);
+        svc = RPC_FLVR_SVC(req->rq_flvr.sf_rpc);
+        if (req->rq_pack_bulk)
+                flags |= LUSTRE_GSS_PACK_BULK;
+        if (req->rq_pack_udesc)
+                flags |= LUSTRE_GSS_PACK_USER;
+
 redo:
         seq = atomic_inc_return(&gctx->gc_seq);
 
         rc = gss_sign_msg(req->rq_reqbuf, gctx->gc_mechctx,
 redo:
         seq = atomic_inc_return(&gctx->gc_seq);
 
         rc = gss_sign_msg(req->rq_reqbuf, gctx->gc_mechctx,
-                          gctx->gc_proc, seq, svc,
+                          ctx->cc_sec->ps_part,
+                          flags, gctx->gc_proc, seq, svc,
                           &gctx->gc_handle);
         if (rc < 0)
                 RETURN(rc);
                           &gctx->gc_handle);
         if (rc < 0)
                 RETURN(rc);
@@ -688,6 +696,7 @@ int gss_cli_ctx_handle_err_notify(struct ptlrpc_cli_ctx *ctx,
         } else if (sec_is_reverse(ctx->cc_sec)) {
                 CWARN("reverse server respond error (%08x/%08x)\n",
                       errhdr->gh_major, errhdr->gh_minor);
         } else if (sec_is_reverse(ctx->cc_sec)) {
                 CWARN("reverse server respond error (%08x/%08x)\n",
                       errhdr->gh_major, errhdr->gh_minor);
+                sptlrpc_cli_ctx_expire(ctx);
                 rc = -EINVAL;
         } else if (errhdr->gh_major == GSS_S_NO_CONTEXT ||
                    errhdr->gh_major == GSS_S_BAD_SIG) {
                 rc = -EINVAL;
         } else if (errhdr->gh_major == GSS_S_NO_CONTEXT ||
                    errhdr->gh_major == GSS_S_BAD_SIG) {
@@ -763,6 +772,13 @@ int gss_cli_ctx_verify(struct ptlrpc_cli_ctx *ctx,
 
         switch (ghdr->gh_proc) {
         case PTLRPC_GSS_PROC_DATA:
 
         switch (ghdr->gh_proc) {
         case PTLRPC_GSS_PROC_DATA:
+                if (!equi(req->rq_pack_bulk == 1,
+                          ghdr->gh_flags & LUSTRE_GSS_PACK_BULK)) {
+                        CERROR("%s bulk flag in reply\n",
+                               req->rq_pack_bulk ? "missing" : "unexpected");
+                        RETURN(-EPROTO);
+                }
+
                 if (ghdr->gh_seq != reqhdr->gh_seq) {
                         CERROR("seqnum %u mismatch, expect %u\n",
                                ghdr->gh_seq, reqhdr->gh_seq);
                 if (ghdr->gh_seq != reqhdr->gh_seq) {
                         CERROR("seqnum %u mismatch, expect %u\n",
                                ghdr->gh_seq, reqhdr->gh_seq);
@@ -785,7 +801,7 @@ int gss_cli_ctx_verify(struct ptlrpc_cli_ctx *ctx,
                 req->rq_repmsg = lustre_msg_buf(msg, 1, 0);
                 req->rq_replen = msg->lm_buflens[1];
 
                 req->rq_repmsg = lustre_msg_buf(msg, 1, 0);
                 req->rq_replen = msg->lm_buflens[1];
 
-                if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
+                if (req->rq_pack_bulk) {
                         if (msg->lm_bufcount < 4) {
                                 CERROR("Invalid reply bufcount %u\n",
                                        msg->lm_bufcount);
                         if (msg->lm_bufcount < 4) {
                                 CERROR("Invalid reply bufcount %u\n",
                                        msg->lm_bufcount);
@@ -847,17 +863,22 @@ int gss_cli_ctx_seal(struct ptlrpc_cli_ctx *ctx,
         }
 
         lustre_init_msg_v2(req->rq_reqbuf, 3, buflens, NULL);
         }
 
         lustre_init_msg_v2(req->rq_reqbuf, 3, buflens, NULL);
-        req->rq_reqbuf->lm_secflvr = req->rq_sec_flavor;
+        req->rq_reqbuf->lm_secflvr = req->rq_flvr.sf_rpc;
 
         /* gss header */
         ghdr = lustre_msg_buf(req->rq_reqbuf, 0, 0);
         ghdr->gh_version = PTLRPC_GSS_VERSION;
 
         /* gss header */
         ghdr = lustre_msg_buf(req->rq_reqbuf, 0, 0);
         ghdr->gh_version = PTLRPC_GSS_VERSION;
+        ghdr->gh_sp = (__u8) ctx->cc_sec->ps_part;
         ghdr->gh_flags = 0;
         ghdr->gh_proc = gctx->gc_proc;
         ghdr->gh_seq = atomic_inc_return(&gctx->gc_seq);
         ghdr->gh_svc = SPTLRPC_SVC_PRIV;
         ghdr->gh_handle.len = gctx->gc_handle.len;
         memcpy(ghdr->gh_handle.data, gctx->gc_handle.data, gctx->gc_handle.len);
         ghdr->gh_flags = 0;
         ghdr->gh_proc = gctx->gc_proc;
         ghdr->gh_seq = atomic_inc_return(&gctx->gc_seq);
         ghdr->gh_svc = SPTLRPC_SVC_PRIV;
         ghdr->gh_handle.len = gctx->gc_handle.len;
         memcpy(ghdr->gh_handle.data, gctx->gc_handle.data, gctx->gc_handle.len);
+        if (req->rq_pack_bulk)
+                ghdr->gh_flags |= LUSTRE_GSS_PACK_BULK;
+        if (req->rq_pack_udesc)
+                ghdr->gh_flags |= LUSTRE_GSS_PACK_USER;
 
 redo:
         /* header signature */
 
 redo:
         /* header signature */
@@ -948,6 +969,13 @@ int gss_cli_ctx_unseal(struct ptlrpc_cli_ctx *ctx,
 
         switch (ghdr->gh_proc) {
         case PTLRPC_GSS_PROC_DATA:
 
         switch (ghdr->gh_proc) {
         case PTLRPC_GSS_PROC_DATA:
+                if (!equi(req->rq_pack_bulk == 1,
+                          ghdr->gh_flags & LUSTRE_GSS_PACK_BULK)) {
+                        CERROR("%s bulk flag in reply\n",
+                               req->rq_pack_bulk ? "missing" : "unexpected");
+                        RETURN(-EPROTO);
+                }
+
                 if (lustre_msg_swabbed(req->rq_repbuf))
                         gss_header_swabber(ghdr);
 
                 if (lustre_msg_swabbed(req->rq_repbuf))
                         gss_header_swabber(ghdr);
 
@@ -969,7 +997,7 @@ int gss_cli_ctx_unseal(struct ptlrpc_cli_ctx *ctx,
                         RETURN(-EPROTO);
                 }
 
                         RETURN(-EPROTO);
                 }
 
-                if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
+                if (req->rq_pack_bulk) {
                         if (req->rq_repbuf->lm_bufcount < 2) {
                                 CERROR("Too few request buffer segments %d\n",
                                        req->rq_repbuf->lm_bufcount);
                         if (req->rq_repbuf->lm_bufcount < 2) {
                                 CERROR("Too few request buffer segments %d\n",
                                        req->rq_repbuf->lm_bufcount);
@@ -1016,18 +1044,18 @@ int gss_install_rvs_svc_ctx(struct obd_import *imp,
 int gss_sec_create_common(struct gss_sec *gsec,
                           struct ptlrpc_sec_policy *policy,
                           struct obd_import *imp,
 int gss_sec_create_common(struct gss_sec *gsec,
                           struct ptlrpc_sec_policy *policy,
                           struct obd_import *imp,
-                          struct ptlrpc_svc_ctx *ctx,
-                          __u32 flavor,
-                          unsigned long flags)
+                          struct ptlrpc_svc_ctx *svcctx,
+                          struct sptlrpc_flavor *sf)
 {
         struct ptlrpc_sec   *sec;
 
         LASSERT(imp);
 {
         struct ptlrpc_sec   *sec;
 
         LASSERT(imp);
-        LASSERT(SEC_FLAVOR_POLICY(flavor) == SPTLRPC_POLICY_GSS);
+        LASSERT(RPC_FLVR_POLICY(sf->sf_rpc) == SPTLRPC_POLICY_GSS);
 
 
-        gsec->gs_mech = lgss_subflavor_to_mech(SEC_FLAVOR_SUB(flavor));
+        gsec->gs_mech = lgss_subflavor_to_mech(RPC_FLVR_SUB(sf->sf_rpc));
         if (!gsec->gs_mech) {
         if (!gsec->gs_mech) {
-                CERROR("gss backend 0x%x not found\n", SEC_FLAVOR_SUB(flavor));
+                CERROR("gss backend 0x%x not found\n",
+                       RPC_FLVR_SUB(sf->sf_rpc));
                 return -EOPNOTSUPP;
         }
 
                 return -EOPNOTSUPP;
         }
 
@@ -1037,29 +1065,28 @@ int gss_sec_create_common(struct gss_sec *gsec,
         /* initialize upper ptlrpc_sec */
         sec = &gsec->gs_base;
         sec->ps_policy = policy;
         /* initialize upper ptlrpc_sec */
         sec = &gsec->gs_base;
         sec->ps_policy = policy;
-        sec->ps_flavor = flavor;
-        sec->ps_flags = flags;
+        atomic_set(&sec->ps_refcount, 0);
+        atomic_set(&sec->ps_nctx, 0);
+        sec->ps_id = sptlrpc_get_next_secid();
+        sec->ps_flvr = *sf;
         sec->ps_import = class_import_get(imp);
         sec->ps_lock = SPIN_LOCK_UNLOCKED;
         sec->ps_import = class_import_get(imp);
         sec->ps_lock = SPIN_LOCK_UNLOCKED;
-        atomic_set(&sec->ps_busy, 0);
         CFS_INIT_LIST_HEAD(&sec->ps_gc_list);
 
         CFS_INIT_LIST_HEAD(&sec->ps_gc_list);
 
-        if (!ctx) {
+        if (!svcctx) {
                 sec->ps_gc_interval = GSS_GC_INTERVAL;
                 sec->ps_gc_interval = GSS_GC_INTERVAL;
-                sec->ps_gc_next = cfs_time_current_sec() + sec->ps_gc_interval;
         } else {
                 LASSERT(sec_is_reverse(sec));
 
                 /* never do gc on reverse sec */
                 sec->ps_gc_interval = 0;
         } else {
                 LASSERT(sec_is_reverse(sec));
 
                 /* never do gc on reverse sec */
                 sec->ps_gc_interval = 0;
-                sec->ps_gc_next = 0;
         }
 
         }
 
-        if (SEC_FLAVOR_SVC(flavor) == SPTLRPC_SVC_PRIV &&
-            flags & PTLRPC_SEC_FL_BULK)
+        if (sec->ps_flvr.sf_bulk_priv != BULK_PRIV_ALG_NULL &&
+            sec->ps_flvr.sf_flags & PTLRPC_SEC_FL_BULK)
                 sptlrpc_enc_pool_add_user();
 
                 sptlrpc_enc_pool_add_user();
 
-        CDEBUG(D_SEC, "create %s%s@%p\n", (ctx ? "reverse " : ""),
+        CDEBUG(D_SEC, "create %s%s@%p\n", (svcctx ? "reverse " : ""),
                policy->sp_name, gsec);
         return 0;
 }
                policy->sp_name, gsec);
         return 0;
 }
@@ -1071,7 +1098,7 @@ void gss_sec_destroy_common(struct gss_sec *gsec)
 
         LASSERT(sec->ps_import);
         LASSERT(atomic_read(&sec->ps_refcount) == 0);
 
         LASSERT(sec->ps_import);
         LASSERT(atomic_read(&sec->ps_refcount) == 0);
-        LASSERT(atomic_read(&sec->ps_busy) == 0);
+        LASSERT(atomic_read(&sec->ps_nctx) == 0);
 
         if (gsec->gs_mech) {
                 lgss_mech_put(gsec->gs_mech);
 
         if (gsec->gs_mech) {
                 lgss_mech_put(gsec->gs_mech);
@@ -1080,13 +1107,18 @@ void gss_sec_destroy_common(struct gss_sec *gsec)
 
         class_import_put(sec->ps_import);
 
 
         class_import_put(sec->ps_import);
 
-        if (SEC_FLAVOR_SVC(sec->ps_flavor) == SPTLRPC_SVC_PRIV &&
-            sec->ps_flags & PTLRPC_SEC_FL_BULK)
+        if (sec->ps_flvr.sf_bulk_priv != BULK_PRIV_ALG_NULL &&
+            sec->ps_flvr.sf_flags & PTLRPC_SEC_FL_BULK)
                 sptlrpc_enc_pool_del_user();
 
         EXIT;
 }
 
                 sptlrpc_enc_pool_del_user();
 
         EXIT;
 }
 
+void gss_sec_kill(struct ptlrpc_sec *sec)
+{
+        sec->ps_dying = 1;
+}
+
 int gss_cli_ctx_init_common(struct ptlrpc_sec *sec,
                             struct ptlrpc_cli_ctx *ctx,
                             struct ptlrpc_ctx_ops *ctxops,
 int gss_cli_ctx_init_common(struct ptlrpc_sec *sec,
                             struct ptlrpc_cli_ctx *ctx,
                             struct ptlrpc_ctx_ops *ctxops,
@@ -1108,8 +1140,10 @@ int gss_cli_ctx_init_common(struct ptlrpc_sec *sec,
         CFS_INIT_LIST_HEAD(&ctx->cc_req_list);
         CFS_INIT_LIST_HEAD(&ctx->cc_gc_chain);
 
         CFS_INIT_LIST_HEAD(&ctx->cc_req_list);
         CFS_INIT_LIST_HEAD(&ctx->cc_gc_chain);
 
-        /* take a ref on belonging sec */
-        atomic_inc(&sec->ps_busy);
+        /* take a ref on belonging sec, balanced in ctx destroying */
+        atomic_inc(&sec->ps_refcount);
+        /* statistic only */
+        atomic_inc(&sec->ps_nctx);
 
         CDEBUG(D_SEC, "%s@%p: create ctx %p(%u->%s)\n",
                sec->ps_policy->sp_name, ctx->cc_sec,
 
         CDEBUG(D_SEC, "%s@%p: create ctx %p(%u->%s)\n",
                sec->ps_policy->sp_name, ctx->cc_sec,
@@ -1118,19 +1152,18 @@ int gss_cli_ctx_init_common(struct ptlrpc_sec *sec,
 }
 
 /*
 }
 
 /*
- * return:
- *  -1: the destroy has been taken care of by someone else
- *   0: proceed to destroy the ctx
- *   1: busy count dropped to 0, proceed to destroy ctx and sec
+ * return value:
+ *   1: the context has been taken care of by someone else
+ *   0: proceed to really destroy the context locally
  */
 int gss_cli_ctx_fini_common(struct ptlrpc_sec *sec,
                             struct ptlrpc_cli_ctx *ctx)
 {
         struct gss_cli_ctx *gctx = ctx2gctx(ctx);
 
  */
 int gss_cli_ctx_fini_common(struct ptlrpc_sec *sec,
                             struct ptlrpc_cli_ctx *ctx)
 {
         struct gss_cli_ctx *gctx = ctx2gctx(ctx);
 
-        LASSERT(ctx->cc_sec == sec);
+        LASSERT(atomic_read(&sec->ps_nctx) > 0);
         LASSERT(atomic_read(&ctx->cc_refcount) == 0);
         LASSERT(atomic_read(&ctx->cc_refcount) == 0);
-        LASSERT(atomic_read(&sec->ps_busy) > 0);
+        LASSERT(ctx->cc_sec == sec);
 
         if (gctx->gc_mechctx) {
                 /* the final context fini rpc will use this ctx too, and it's
 
         if (gctx->gc_mechctx) {
                 /* the final context fini rpc will use this ctx too, and it's
@@ -1143,22 +1176,17 @@ int gss_cli_ctx_fini_common(struct ptlrpc_sec *sec,
                 gss_cli_ctx_finalize(gctx);
 
                 if (!atomic_dec_and_test(&ctx->cc_refcount))
                 gss_cli_ctx_finalize(gctx);
 
                 if (!atomic_dec_and_test(&ctx->cc_refcount))
-                        return -1;
+                        return 1;
         }
 
         if (sec_is_reverse(sec))
         }
 
         if (sec_is_reverse(sec))
-                CDEBUG(D_SEC, "reverse sec %p: destroy ctx %p\n",
-                       ctx->cc_sec, ctx);
+                CWARN("reverse sec %p: destroy ctx %p\n",
+                      ctx->cc_sec, ctx);
         else
                 CWARN("%s@%p: destroy ctx %p(%u->%s)\n",
                       sec->ps_policy->sp_name, ctx->cc_sec,
                       ctx, ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec));
 
         else
                 CWARN("%s@%p: destroy ctx %p(%u->%s)\n",
                       sec->ps_policy->sp_name, ctx->cc_sec,
                       ctx, ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec));
 
-        if (atomic_dec_and_test(&sec->ps_busy)) {
-                LASSERT(atomic_read(&sec->ps_refcount) == 0);
-                return 1;
-        }
-
         return 0;
 }
 
         return 0;
 }
 
@@ -1167,7 +1195,6 @@ int gss_alloc_reqbuf_intg(struct ptlrpc_sec *sec,
                           struct ptlrpc_request *req,
                           int svc, int msgsize)
 {
                           struct ptlrpc_request *req,
                           int svc, int msgsize)
 {
-        struct sec_flavor_config *conf;
         int                       bufsize, txtsize;
         int                       buflens[5], bufcnt = 2;
         ENTRY;
         int                       bufsize, txtsize;
         int                       buflens[5], bufcnt = 2;
         ENTRY;
@@ -1194,17 +1221,17 @@ int gss_alloc_reqbuf_intg(struct ptlrpc_sec *sec,
         if (svc == SPTLRPC_SVC_INTG)
                 txtsize += buflens[1];
 
         if (svc == SPTLRPC_SVC_INTG)
                 txtsize += buflens[1];
 
-        if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor)) {
+        if (req->rq_pack_udesc) {
                 buflens[bufcnt] = sptlrpc_current_user_desc_size();
                 if (svc == SPTLRPC_SVC_INTG)
                         txtsize += buflens[bufcnt];
                 bufcnt++;
         }
 
                 buflens[bufcnt] = sptlrpc_current_user_desc_size();
                 if (svc == SPTLRPC_SVC_INTG)
                         txtsize += buflens[bufcnt];
                 bufcnt++;
         }
 
-        if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
-                conf = &req->rq_import->imp_obd->u.cli.cl_sec_conf;
-                buflens[bufcnt] = bulk_sec_desc_size(conf->sfc_bulk_csum, 1,
-                                                     req->rq_bulk_read);
+        if (req->rq_pack_bulk) {
+                buflens[bufcnt] = bulk_sec_desc_size(
+                                                req->rq_flvr.sf_bulk_csum, 1,
+                                                req->rq_bulk_read);
                 if (svc == SPTLRPC_SVC_INTG)
                         txtsize += buflens[bufcnt];
                 bufcnt++;
                 if (svc == SPTLRPC_SVC_INTG)
                         txtsize += buflens[bufcnt];
                 bufcnt++;
@@ -1232,13 +1259,13 @@ int gss_alloc_reqbuf_intg(struct ptlrpc_sec *sec,
         }
 
         lustre_init_msg_v2(req->rq_reqbuf, bufcnt, buflens, NULL);
         }
 
         lustre_init_msg_v2(req->rq_reqbuf, bufcnt, buflens, NULL);
-        req->rq_reqbuf->lm_secflvr = req->rq_sec_flavor;
+        req->rq_reqbuf->lm_secflvr = req->rq_flvr.sf_rpc;
 
         req->rq_reqmsg = lustre_msg_buf(req->rq_reqbuf, 1, msgsize);
         LASSERT(req->rq_reqmsg);
 
         /* pack user desc here, later we might leave current user's process */
 
         req->rq_reqmsg = lustre_msg_buf(req->rq_reqbuf, 1, msgsize);
         LASSERT(req->rq_reqmsg);
 
         /* pack user desc here, later we might leave current user's process */
-        if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor))
+        if (req->rq_pack_udesc)
                 sptlrpc_pack_user_desc(req->rq_reqbuf, 2);
 
         RETURN(0);
                 sptlrpc_pack_user_desc(req->rq_reqbuf, 2);
 
         RETURN(0);
@@ -1249,7 +1276,6 @@ int gss_alloc_reqbuf_priv(struct ptlrpc_sec *sec,
                           struct ptlrpc_request *req,
                           int msgsize)
 {
                           struct ptlrpc_request *req,
                           int msgsize)
 {
-        struct sec_flavor_config *conf;
         int                       ibuflens[3], ibufcnt;
         int                       buflens[3];
         int                       clearsize, wiresize;
         int                       ibuflens[3], ibufcnt;
         int                       buflens[3];
         int                       clearsize, wiresize;
@@ -1267,13 +1293,13 @@ int gss_alloc_reqbuf_priv(struct ptlrpc_sec *sec,
         ibufcnt = 1;
         ibuflens[0] = msgsize;
 
         ibufcnt = 1;
         ibuflens[0] = msgsize;
 
-        if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor))
+        if (req->rq_pack_udesc)
                 ibuflens[ibufcnt++] = sptlrpc_current_user_desc_size();
                 ibuflens[ibufcnt++] = sptlrpc_current_user_desc_size();
-        if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
-                conf = &req->rq_import->imp_obd->u.cli.cl_sec_conf;
-                ibuflens[ibufcnt++] = bulk_sec_desc_size(conf->sfc_bulk_csum, 1,
-                                                         req->rq_bulk_read);
-        }
+        if (req->rq_pack_bulk)
+                ibuflens[ibufcnt++] = bulk_sec_desc_size(
+                                                req->rq_flvr.sf_bulk_csum, 1,
+                                                req->rq_bulk_read);
+
         clearsize = lustre_msg_size_v2(ibufcnt, ibuflens);
         /* to allow append padding during encryption */
         clearsize += GSS_MAX_CIPHER_BLOCK;
         clearsize = lustre_msg_size_v2(ibufcnt, ibuflens);
         /* to allow append padding during encryption */
         clearsize += GSS_MAX_CIPHER_BLOCK;
@@ -1321,7 +1347,7 @@ int gss_alloc_reqbuf_priv(struct ptlrpc_sec *sec,
         lustre_init_msg_v2(req->rq_clrbuf, ibufcnt, ibuflens, NULL);
         req->rq_reqmsg = lustre_msg_buf(req->rq_clrbuf, 0, msgsize);
 
         lustre_init_msg_v2(req->rq_clrbuf, ibufcnt, ibuflens, NULL);
         req->rq_reqmsg = lustre_msg_buf(req->rq_clrbuf, 0, msgsize);
 
-        if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor))
+        if (req->rq_pack_udesc)
                 sptlrpc_pack_user_desc(req->rq_clrbuf, 1);
 
         RETURN(0);
                 sptlrpc_pack_user_desc(req->rq_clrbuf, 1);
 
         RETURN(0);
@@ -1335,9 +1361,9 @@ int gss_alloc_reqbuf(struct ptlrpc_sec *sec,
                      struct ptlrpc_request *req,
                      int msgsize)
 {
                      struct ptlrpc_request *req,
                      int msgsize)
 {
-        int     svc = SEC_FLAVOR_SVC(req->rq_sec_flavor);
+        int     svc = RPC_FLVR_SVC(req->rq_flvr.sf_rpc);
 
 
-        LASSERT(!SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor) ||
+        LASSERT(!req->rq_pack_bulk ||
                 (req->rq_bulk_read || req->rq_bulk_write));
 
         switch (svc) {
                 (req->rq_bulk_read || req->rq_bulk_write));
 
         switch (svc) {
@@ -1348,7 +1374,7 @@ int gss_alloc_reqbuf(struct ptlrpc_sec *sec,
         case SPTLRPC_SVC_PRIV:
                 return gss_alloc_reqbuf_priv(sec, req, msgsize);
         default:
         case SPTLRPC_SVC_PRIV:
                 return gss_alloc_reqbuf_priv(sec, req, msgsize);
         default:
-                LASSERTF(0, "bad flavor %x\n", req->rq_sec_flavor);
+                LASSERTF(0, "bad rpc flavor %x\n", req->rq_flvr.sf_rpc);
                 return 0;
         }
 }
                 return 0;
         }
 }
@@ -1360,7 +1386,7 @@ void gss_free_reqbuf(struct ptlrpc_sec *sec,
         ENTRY;
 
         LASSERT(!req->rq_pool || req->rq_reqbuf);
         ENTRY;
 
         LASSERT(!req->rq_pool || req->rq_reqbuf);
-        privacy = SEC_FLAVOR_SVC(req->rq_sec_flavor) == SPTLRPC_SVC_PRIV;
+        privacy = RPC_FLVR_SVC(req->rq_flvr.sf_rpc) == SPTLRPC_SVC_PRIV;
 
         if (!req->rq_clrbuf)
                 goto release_reqbuf;
 
         if (!req->rq_clrbuf)
                 goto release_reqbuf;
@@ -1381,11 +1407,15 @@ void gss_free_reqbuf(struct ptlrpc_sec *sec,
 
 release_reqbuf:
         if (!req->rq_pool && req->rq_reqbuf) {
 
 release_reqbuf:
         if (!req->rq_pool && req->rq_reqbuf) {
+                LASSERT(req->rq_reqbuf_len);
+
                 OBD_FREE(req->rq_reqbuf, req->rq_reqbuf_len);
                 req->rq_reqbuf = NULL;
                 req->rq_reqbuf_len = 0;
         }
 
                 OBD_FREE(req->rq_reqbuf, req->rq_reqbuf_len);
                 req->rq_reqbuf = NULL;
                 req->rq_reqbuf_len = 0;
         }
 
+        req->rq_reqmsg = NULL;
+
         EXIT;
 }
 
         EXIT;
 }
 
@@ -1406,7 +1436,6 @@ int gss_alloc_repbuf_intg(struct ptlrpc_sec *sec,
                           struct ptlrpc_request *req,
                           int svc, int msgsize)
 {
                           struct ptlrpc_request *req,
                           int svc, int msgsize)
 {
-        struct sec_flavor_config *conf;
         int                       txtsize;
         int                       buflens[4], bufcnt = 2;
 
         int                       txtsize;
         int                       buflens[4], bufcnt = 2;
 
@@ -1431,10 +1460,10 @@ int gss_alloc_repbuf_intg(struct ptlrpc_sec *sec,
         if (svc == SPTLRPC_SVC_INTG)
                 txtsize += buflens[1];
 
         if (svc == SPTLRPC_SVC_INTG)
                 txtsize += buflens[1];
 
-        if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
-                conf = &req->rq_import->imp_obd->u.cli.cl_sec_conf;
-                buflens[bufcnt] = bulk_sec_desc_size(conf->sfc_bulk_csum, 0,
-                                                     req->rq_bulk_read);
+        if (req->rq_pack_bulk) {
+                buflens[bufcnt] = bulk_sec_desc_size(
+                                                req->rq_flvr.sf_bulk_csum, 0,
+                                                req->rq_bulk_read);
                 if (svc == SPTLRPC_SVC_INTG)
                         txtsize += buflens[bufcnt];
                 bufcnt++;
                 if (svc == SPTLRPC_SVC_INTG)
                         txtsize += buflens[bufcnt];
                 bufcnt++;
@@ -1453,7 +1482,6 @@ int gss_alloc_repbuf_priv(struct ptlrpc_sec *sec,
                           struct ptlrpc_request *req,
                           int msgsize)
 {
                           struct ptlrpc_request *req,
                           int msgsize)
 {
-        struct sec_flavor_config *conf;
         int                       txtsize;
         int                       buflens[3], bufcnt;
 
         int                       txtsize;
         int                       buflens[3], bufcnt;
 
@@ -1465,10 +1493,9 @@ int gss_alloc_repbuf_priv(struct ptlrpc_sec *sec,
         bufcnt = 1;
         buflens[0] = msgsize;
 
         bufcnt = 1;
         buflens[0] = msgsize;
 
-        if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
-                conf = &req->rq_import->imp_obd->u.cli.cl_sec_conf;
+        if (req->rq_pack_bulk) {
                 buflens[bufcnt++] = bulk_sec_desc_size(
                 buflens[bufcnt++] = bulk_sec_desc_size(
-                                                conf->sfc_bulk_csum, 0,
+                                                req->rq_flvr.sf_bulk_csum, 0,
                                                 req->rq_bulk_read);
         }
         txtsize = lustre_msg_size_v2(bufcnt, buflens);
                                                 req->rq_bulk_read);
         }
         txtsize = lustre_msg_size_v2(bufcnt, buflens);
@@ -1492,10 +1519,10 @@ int gss_alloc_repbuf(struct ptlrpc_sec *sec,
                      struct ptlrpc_request *req,
                      int msgsize)
 {
                      struct ptlrpc_request *req,
                      int msgsize)
 {
-        int     svc = SEC_FLAVOR_SVC(req->rq_sec_flavor);
+        int     svc = RPC_FLVR_SVC(req->rq_flvr.sf_rpc);
         ENTRY;
 
         ENTRY;
 
-        LASSERT(!SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor) ||
+        LASSERT(!req->rq_pack_bulk ||
                 (req->rq_bulk_read || req->rq_bulk_write));
 
         switch (svc) {
                 (req->rq_bulk_read || req->rq_bulk_write));
 
         switch (svc) {
@@ -1506,7 +1533,7 @@ int gss_alloc_repbuf(struct ptlrpc_sec *sec,
         case SPTLRPC_SVC_PRIV:
                 return gss_alloc_repbuf_priv(sec, req, msgsize);
         default:
         case SPTLRPC_SVC_PRIV:
                 return gss_alloc_repbuf_priv(sec, req, msgsize);
         default:
-                LASSERTF(0, "bad flavor %x\n", req->rq_sec_flavor);
+                LASSERTF(0, "bad rpc flavor %x\n", req->rq_flvr.sf_rpc);
                 return 0;
         }
 }
                 return 0;
         }
 }
@@ -1517,6 +1544,8 @@ void gss_free_repbuf(struct ptlrpc_sec *sec,
         OBD_FREE(req->rq_repbuf, req->rq_repbuf_len);
         req->rq_repbuf = NULL;
         req->rq_repbuf_len = 0;
         OBD_FREE(req->rq_repbuf, req->rq_repbuf_len);
         req->rq_repbuf = NULL;
         req->rq_repbuf_len = 0;
+
+        req->rq_repmsg = NULL;
 }
 
 static int get_enlarged_msgsize(struct lustre_msg *msg,
 }
 
 static int get_enlarged_msgsize(struct lustre_msg *msg,
@@ -1726,7 +1755,7 @@ int gss_enlarge_reqbuf(struct ptlrpc_sec *sec,
                        struct ptlrpc_request *req,
                        int segment, int newsize)
 {
                        struct ptlrpc_request *req,
                        int segment, int newsize)
 {
-        int     svc = SEC_FLAVOR_SVC(req->rq_sec_flavor);
+        int     svc = RPC_FLVR_SVC(req->rq_flvr.sf_rpc);
 
         LASSERT(!req->rq_ctx_init && !req->rq_ctx_fini);
 
 
         LASSERT(!req->rq_ctx_init && !req->rq_ctx_fini);
 
@@ -1738,7 +1767,7 @@ int gss_enlarge_reqbuf(struct ptlrpc_sec *sec,
         case SPTLRPC_SVC_PRIV:
                 return gss_enlarge_reqbuf_priv(sec, req, segment, newsize);
         default:
         case SPTLRPC_SVC_PRIV:
                 return gss_enlarge_reqbuf_priv(sec, req, segment, newsize);
         default:
-                LASSERTF(0, "bad flavor %x\n", req->rq_sec_flavor);
+                LASSERTF(0, "bad rpc flavor %x\n", req->rq_flvr.sf_rpc);
                 return 0;
         }
 }
                 return 0;
         }
 }
@@ -1800,8 +1829,9 @@ static
 int gss_svc_sign(struct ptlrpc_request *req,
                  struct ptlrpc_reply_state *rs,
                  struct gss_svc_reqctx *grctx,
 int gss_svc_sign(struct ptlrpc_request *req,
                  struct ptlrpc_reply_state *rs,
                  struct gss_svc_reqctx *grctx,
-                 int svc)
+                 __u32 svc)
 {
 {
+        __u32   flags = 0;
         int     rc;
         ENTRY;
 
         int     rc;
         ENTRY;
 
@@ -1811,9 +1841,12 @@ int gss_svc_sign(struct ptlrpc_request *req,
         if (req->rq_replen != rs->rs_repbuf->lm_buflens[1])
                 lustre_shrink_msg(rs->rs_repbuf, 1, req->rq_replen, 1);
 
         if (req->rq_replen != rs->rs_repbuf->lm_buflens[1])
                 lustre_shrink_msg(rs->rs_repbuf, 1, req->rq_replen, 1);
 
+        if (req->rq_pack_bulk)
+                flags |= LUSTRE_GSS_PACK_BULK;
+
         rc = gss_sign_msg(rs->rs_repbuf, grctx->src_ctx->gsc_mechctx,
         rc = gss_sign_msg(rs->rs_repbuf, grctx->src_ctx->gsc_mechctx,
-                          PTLRPC_GSS_PROC_DATA, grctx->src_wirectx.gw_seq,
-                          svc, NULL);
+                          LUSTRE_SP_ANY, flags, PTLRPC_GSS_PROC_DATA,
+                          grctx->src_wirectx.gw_seq, svc, NULL);
         if (rc < 0)
                 RETURN(rc);
 
         if (rc < 0)
                 RETURN(rc);
 
@@ -1880,6 +1913,11 @@ int gss_svc_handle_init(struct ptlrpc_request *req,
 
         req->rq_ctx_init = 1;
 
 
         req->rq_ctx_init = 1;
 
+        if (gw->gw_flags & LUSTRE_GSS_PACK_BULK) {
+                CERROR("unexpected bulk flag\n");
+                RETURN(SECSVC_DROP);
+        }
+
         if (gw->gw_proc == PTLRPC_GSS_PROC_INIT && gw->gw_handle.len != 0) {
                 CERROR("proc %u: invalid handle length %u\n",
                        gw->gw_proc, gw->gw_handle.len);
         if (gw->gw_proc == PTLRPC_GSS_PROC_INIT && gw->gw_handle.len != 0) {
                 CERROR("proc %u: invalid handle length %u\n",
                        gw->gw_proc, gw->gw_handle.len);
@@ -1915,7 +1953,7 @@ int gss_svc_handle_init(struct ptlrpc_request *req,
         uuid = (struct obd_uuid *) uuid_obj.data;
         target = class_uuid2obd(uuid);
         if (!target || target->obd_stopping || !target->obd_set_up) {
         uuid = (struct obd_uuid *) uuid_obj.data;
         target = class_uuid2obd(uuid);
         if (!target || target->obd_stopping || !target->obd_set_up) {
-                CERROR("target '%s' is not available for context init (%s)",
+                CERROR("target '%s' is not available for context init (%s)\n",
                        uuid->uuid, target == NULL ? "no target" :
                        (target->obd_stopping ? "stopping" : "not set up"));
                 RETURN(SECSVC_DROP);
                        uuid->uuid, target == NULL ? "no target" :
                        (target->obd_stopping ? "stopping" : "not set up"));
                 RETURN(SECSVC_DROP);
@@ -1939,14 +1977,15 @@ int gss_svc_handle_init(struct ptlrpc_request *req,
                 RETURN(rc);
 
         if (grctx->src_ctx->gsc_usr_mds || grctx->src_ctx->gsc_usr_root)
                 RETURN(rc);
 
         if (grctx->src_ctx->gsc_usr_mds || grctx->src_ctx->gsc_usr_root)
-                CWARN("user from %s authenticated as %s\n",
-                      libcfs_nid2str(req->rq_peer.nid),
+                CWARN("create svc ctx %p: user from %s authenticated as %s\n",
+                      grctx->src_ctx, libcfs_nid2str(req->rq_peer.nid),
                       grctx->src_ctx->gsc_usr_mds ? "mds" : "root");
         else
                       grctx->src_ctx->gsc_usr_mds ? "mds" : "root");
         else
-                CWARN("accept user %u from %s\n", grctx->src_ctx->gsc_uid,
+                CWARN("create svc ctx %p: accept user %u from %s\n",
+                      grctx->src_ctx, grctx->src_ctx->gsc_uid,
                       libcfs_nid2str(req->rq_peer.nid));
 
                       libcfs_nid2str(req->rq_peer.nid));
 
-        if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor)) {
+        if (gw->gw_flags & LUSTRE_GSS_PACK_USER) {
                 if (reqbuf->lm_bufcount < 4) {
                         CERROR("missing user descriptor\n");
                         RETURN(SECSVC_DROP);
                 if (reqbuf->lm_bufcount < 4) {
                         CERROR("missing user descriptor\n");
                         RETURN(SECSVC_DROP);
@@ -1955,6 +1994,8 @@ int gss_svc_handle_init(struct ptlrpc_request *req,
                         CERROR("Mal-formed user descriptor\n");
                         RETURN(SECSVC_DROP);
                 }
                         CERROR("Mal-formed user descriptor\n");
                         RETURN(SECSVC_DROP);
                 }
+
+                req->rq_pack_udesc = 1;
                 req->rq_user_desc = lustre_msg_buf(reqbuf, 2, 0);
         }
 
                 req->rq_user_desc = lustre_msg_buf(reqbuf, 2, 0);
         }
 
@@ -1998,7 +2039,8 @@ int gss_svc_verify_request(struct ptlrpc_request *req,
         if (*major != GSS_S_COMPLETE)
                 RETURN(-EACCES);
 
         if (*major != GSS_S_COMPLETE)
                 RETURN(-EACCES);
 
-        if (gss_check_seq_num(&gctx->gsc_seqdata, gw->gw_seq, 1)) {
+        if (gctx->gsc_reverse == 0 &&
+            gss_check_seq_num(&gctx->gsc_seqdata, gw->gw_seq, 1)) {
                 CERROR("phase 1+: discard replayed req: seq %u\n", gw->gw_seq);
                 *major = GSS_S_DUPLICATE_TOKEN;
                 RETURN(-EACCES);
                 CERROR("phase 1+: discard replayed req: seq %u\n", gw->gw_seq);
                 *major = GSS_S_DUPLICATE_TOKEN;
                 RETURN(-EACCES);
@@ -2006,7 +2048,7 @@ int gss_svc_verify_request(struct ptlrpc_request *req,
 
 verified:
         /* user descriptor */
 
 verified:
         /* user descriptor */
-        if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor)) {
+        if (gw->gw_flags & LUSTRE_GSS_PACK_USER) {
                 if (msg->lm_bufcount < (offset + 1)) {
                         CERROR("no user desc included\n");
                         RETURN(-EINVAL);
                 if (msg->lm_bufcount < (offset + 1)) {
                         CERROR("no user desc included\n");
                         RETURN(-EINVAL);
@@ -2017,12 +2059,13 @@ verified:
                         RETURN(-EINVAL);
                 }
 
                         RETURN(-EINVAL);
                 }
 
+                req->rq_pack_udesc = 1;
                 req->rq_user_desc = lustre_msg_buf(msg, offset, 0);
                 offset++;
         }
 
         /* check bulk cksum data */
                 req->rq_user_desc = lustre_msg_buf(msg, offset, 0);
                 offset++;
         }
 
         /* check bulk cksum data */
-        if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
+        if (gw->gw_flags & LUSTRE_GSS_PACK_BULK) {
                 if (msg->lm_bufcount < (offset + 1)) {
                         CERROR("no bulk checksum included\n");
                         RETURN(-EINVAL);
                 if (msg->lm_bufcount < (offset + 1)) {
                         CERROR("no bulk checksum included\n");
                         RETURN(-EINVAL);
@@ -2031,6 +2074,7 @@ verified:
                 if (bulk_sec_desc_unpack(msg, offset))
                         RETURN(-EINVAL);
 
                 if (bulk_sec_desc_unpack(msg, offset))
                         RETURN(-EINVAL);
 
+                req->rq_pack_bulk = 1;
                 grctx->src_reqbsd = lustre_msg_buf(msg, offset, 0);
                 grctx->src_reqbsd_size = lustre_msg_buflen(msg, offset);
         }
                 grctx->src_reqbsd = lustre_msg_buf(msg, offset, 0);
                 grctx->src_reqbsd_size = lustre_msg_buflen(msg, offset);
         }
@@ -2079,7 +2123,7 @@ int gss_svc_unseal_request(struct ptlrpc_request *req,
                 RETURN(-EINVAL);
         }
 
                 RETURN(-EINVAL);
         }
 
-        if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor)) {
+        if (gw->gw_flags & LUSTRE_GSS_PACK_USER) {
                 if (msg->lm_bufcount < offset + 1) {
                         CERROR("no user descriptor included\n");
                         RETURN(-EINVAL);
                 if (msg->lm_bufcount < offset + 1) {
                         CERROR("no user descriptor included\n");
                         RETURN(-EINVAL);
@@ -2090,11 +2134,12 @@ int gss_svc_unseal_request(struct ptlrpc_request *req,
                         RETURN(-EINVAL);
                 }
 
                         RETURN(-EINVAL);
                 }
 
+                req->rq_pack_udesc = 1;
                 req->rq_user_desc = lustre_msg_buf(msg, offset, 0);
                 offset++;
         }
 
                 req->rq_user_desc = lustre_msg_buf(msg, offset, 0);
                 offset++;
         }
 
-        if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
+        if (gw->gw_flags & LUSTRE_GSS_PACK_BULK) {
                 if (msg->lm_bufcount < offset + 1) {
                         CERROR("no bulk checksum included\n");
                         RETURN(-EINVAL);
                 if (msg->lm_bufcount < offset + 1) {
                         CERROR("no bulk checksum included\n");
                         RETURN(-EINVAL);
@@ -2103,6 +2148,7 @@ int gss_svc_unseal_request(struct ptlrpc_request *req,
                 if (bulk_sec_desc_unpack(msg, offset))
                         RETURN(-EINVAL);
 
                 if (bulk_sec_desc_unpack(msg, offset))
                         RETURN(-EINVAL);
 
+                req->rq_pack_bulk = 1;
                 grctx->src_reqbsd = lustre_msg_buf(msg, offset, 0);
                 grctx->src_reqbsd_size = lustre_msg_buflen(msg, offset);
         }
                 grctx->src_reqbsd = lustre_msg_buf(msg, offset, 0);
                 grctx->src_reqbsd_size = lustre_msg_buflen(msg, offset);
         }
@@ -2170,7 +2216,7 @@ int gss_svc_handle_destroy(struct ptlrpc_request *req,
 
         grctx->src_ctx = gss_svc_upcall_get_ctx(req, gw);
         if (!grctx->src_ctx) {
 
         grctx->src_ctx = gss_svc_upcall_get_ctx(req, gw);
         if (!grctx->src_ctx) {
-                CWARN("invalid gss context handle for destroy.\n");
+                CDEBUG(D_SEC, "invalid gss context handle for destroy.\n");
                 RETURN(SECSVC_DROP);
         }
 
                 RETURN(SECSVC_DROP);
         }
 
@@ -2182,12 +2228,13 @@ int gss_svc_handle_destroy(struct ptlrpc_request *req,
         if (gss_svc_verify_request(req, grctx, gw, &major))
                 RETURN(SECSVC_DROP);
 
         if (gss_svc_verify_request(req, grctx, gw, &major))
                 RETURN(SECSVC_DROP);
 
-        CWARN("destroy svc ctx %p(%u->%s)\n", grctx->src_ctx,
-               grctx->src_ctx->gsc_uid, libcfs_nid2str(req->rq_peer.nid));
+        CWARN("destroy svc ctx %p idx "LPX64" (%u->%s)\n",
+              grctx->src_ctx, gss_handle_to_u64(&gw->gw_handle),
+              grctx->src_ctx->gsc_uid, libcfs_nid2str(req->rq_peer.nid));
 
         gss_svc_upcall_destroy_ctx(grctx->src_ctx);
 
 
         gss_svc_upcall_destroy_ctx(grctx->src_ctx);
 
-        if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor)) {
+        if (gw->gw_flags & LUSTRE_GSS_PACK_USER) {
                 if (req->rq_reqbuf->lm_bufcount < 4) {
                         CERROR("missing user descriptor, ignore it\n");
                         RETURN(SECSVC_OK);
                 if (req->rq_reqbuf->lm_bufcount < 4) {
                         CERROR("missing user descriptor, ignore it\n");
                         RETURN(SECSVC_OK);
@@ -2196,6 +2243,8 @@ int gss_svc_handle_destroy(struct ptlrpc_request *req,
                         CERROR("Mal-formed user descriptor, ignore it\n");
                         RETURN(SECSVC_OK);
                 }
                         CERROR("Mal-formed user descriptor, ignore it\n");
                         RETURN(SECSVC_OK);
                 }
+
+                req->rq_pack_udesc = 1;
                 req->rq_user_desc = lustre_msg_buf(req->rq_reqbuf, 2, 0);
         }
 
                 req->rq_user_desc = lustre_msg_buf(req->rq_reqbuf, 2, 0);
         }
 
@@ -2231,6 +2280,8 @@ int gss_svc_accept(struct ptlrpc_sec_policy *policy, struct ptlrpc_request *req)
                 RETURN(SECSVC_DROP);
         }
 
                 RETURN(SECSVC_DROP);
         }
 
+        req->rq_sp_from = ghdr->gh_sp;
+
         /* alloc grctx data */
         OBD_ALLOC_PTR(grctx);
         if (!grctx) {
         /* alloc grctx data */
         OBD_ALLOC_PTR(grctx);
         if (!grctx) {
@@ -2243,6 +2294,7 @@ int gss_svc_accept(struct ptlrpc_sec_policy *policy, struct ptlrpc_request *req)
         gw = &grctx->src_wirectx;
 
         /* save wire context */
         gw = &grctx->src_wirectx;
 
         /* save wire context */
+        gw->gw_flags = ghdr->gh_flags;
         gw->gw_proc = ghdr->gh_proc;
         gw->gw_seq = ghdr->gh_seq;
         gw->gw_svc = ghdr->gh_svc;
         gw->gw_proc = ghdr->gh_proc;
         gw->gw_seq = ghdr->gh_seq;
         gw->gw_svc = ghdr->gh_svc;
@@ -2331,13 +2383,12 @@ int gss_svc_alloc_rs(struct ptlrpc_request *req, int msglen)
 
         LASSERT(msglen % 8 == 0);
 
 
         LASSERT(msglen % 8 == 0);
 
-        if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor) &&
-            !req->rq_bulk_read && !req->rq_bulk_write) {
+        if (req->rq_pack_bulk && !req->rq_bulk_read && !req->rq_bulk_write) {
                 CERROR("client request bulk sec on non-bulk rpc\n");
                 RETURN(-EPROTO);
         }
 
                 CERROR("client request bulk sec on non-bulk rpc\n");
                 RETURN(-EPROTO);
         }
 
-        svc = SEC_FLAVOR_SVC(req->rq_sec_flavor);
+        svc = RPC_FLVR_SVC(req->rq_flvr.sf_rpc);
 
         grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
         if (gss_svc_reqctx_is_special(grctx))
 
         grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
         if (gss_svc_reqctx_is_special(grctx))
@@ -2350,7 +2401,7 @@ int gss_svc_alloc_rs(struct ptlrpc_request *req, int msglen)
                 ibufcnt = 1;
                 ibuflens[0] = msglen;
 
                 ibufcnt = 1;
                 ibuflens[0] = msglen;
 
-                if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
+                if (req->rq_pack_bulk) {
                         LASSERT(grctx->src_reqbsd);
 
                         bsd_off = ibufcnt;
                         LASSERT(grctx->src_reqbsd);
 
                         bsd_off = ibufcnt;
@@ -2376,7 +2427,7 @@ int gss_svc_alloc_rs(struct ptlrpc_request *req, int msglen)
                 if (svc == SPTLRPC_SVC_INTG)
                         txtsize += buflens[1];
 
                 if (svc == SPTLRPC_SVC_INTG)
                         txtsize += buflens[1];
 
-                if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
+                if (req->rq_pack_bulk) {
                         LASSERT(grctx->src_reqbsd);
 
                         bsd_off = bufcnt;
                         LASSERT(grctx->src_reqbsd);
 
                         bsd_off = bufcnt;
@@ -2418,7 +2469,7 @@ int gss_svc_alloc_rs(struct ptlrpc_request *req, int msglen)
                 rs->rs_msg = lustre_msg_buf(rs->rs_repbuf, 0, msglen);
         } else {
                 lustre_init_msg_v2(rs->rs_repbuf, bufcnt, buflens, NULL);
                 rs->rs_msg = lustre_msg_buf(rs->rs_repbuf, 0, msglen);
         } else {
                 lustre_init_msg_v2(rs->rs_repbuf, bufcnt, buflens, NULL);
-                rs->rs_repbuf->lm_secflvr = req->rq_sec_flavor;
+                rs->rs_repbuf->lm_secflvr = req->rq_flvr.sf_rpc;
 
                 rs->rs_msg = lustre_msg_buf(rs->rs_repbuf, 1, 0);
         }
 
                 rs->rs_msg = lustre_msg_buf(rs->rs_repbuf, 1, 0);
         }
@@ -2492,7 +2543,7 @@ int gss_svc_seal(struct ptlrpc_request *req,
 
         LASSERT(lustre_msg_size_v2(3, buflens) <= rs->rs_repbuf_len);
         lustre_init_msg_v2(rs->rs_repbuf, 3, buflens, NULL);
 
         LASSERT(lustre_msg_size_v2(3, buflens) <= rs->rs_repbuf_len);
         lustre_init_msg_v2(rs->rs_repbuf, 3, buflens, NULL);
-        rs->rs_repbuf->lm_secflvr = req->rq_sec_flavor;
+        rs->rs_repbuf->lm_secflvr = req->rq_flvr.sf_rpc;
 
         /* gss header */
         ghdr = lustre_msg_buf(rs->rs_repbuf, 0, 0);
 
         /* gss header */
         ghdr = lustre_msg_buf(rs->rs_repbuf, 0, 0);
@@ -2502,6 +2553,8 @@ int gss_svc_seal(struct ptlrpc_request *req,
         ghdr->gh_seq = grctx->src_wirectx.gw_seq;
         ghdr->gh_svc = SPTLRPC_SVC_PRIV;
         ghdr->gh_handle.len = 0;
         ghdr->gh_seq = grctx->src_wirectx.gw_seq;
         ghdr->gh_svc = SPTLRPC_SVC_PRIV;
         ghdr->gh_handle.len = 0;
+        if (req->rq_pack_bulk)
+                ghdr->gh_flags |= LUSTRE_GSS_PACK_BULK;
 
         /* header signature */
         msgobj.len = rs->rs_repbuf->lm_buflens[0];
 
         /* header signature */
         msgobj.len = rs->rs_repbuf->lm_buflens[0];
@@ -2601,33 +2654,53 @@ int gss_copy_rvc_cli_ctx(struct ptlrpc_cli_ctx *cli_ctx,
                          struct ptlrpc_svc_ctx *svc_ctx)
 {
         struct gss_cli_ctx     *cli_gctx = ctx2gctx(cli_ctx);
                          struct ptlrpc_svc_ctx *svc_ctx)
 {
         struct gss_cli_ctx     *cli_gctx = ctx2gctx(cli_ctx);
-        struct gss_svc_reqctx  *grctx;
+        struct gss_svc_ctx     *svc_gctx = gss_svc_ctx2gssctx(svc_ctx);
         struct gss_ctx         *mechctx = NULL;
 
         struct gss_ctx         *mechctx = NULL;
 
+        LASSERT(cli_gctx);
+        LASSERT(svc_gctx && svc_gctx->gsc_mechctx);
+
         cli_gctx->gc_proc = PTLRPC_GSS_PROC_DATA;
         cli_gctx->gc_win = GSS_SEQ_WIN;
         cli_gctx->gc_proc = PTLRPC_GSS_PROC_DATA;
         cli_gctx->gc_win = GSS_SEQ_WIN;
-        atomic_set(&cli_gctx->gc_seq, 0);
 
 
-        grctx = container_of(svc_ctx, struct gss_svc_reqctx, src_base);
-        LASSERT(grctx->src_ctx);
-        LASSERT(grctx->src_ctx->gsc_mechctx);
+        /* The problem is the reverse ctx might get lost in some recovery
+         * situations, and the same svc_ctx will be used to re-create it.
+         * if there's callback be sentout before that, new reverse ctx start
+         * with sequence 0 will lead to future callback rpc be treated as
+         * replay.
+         *
+         * each reverse root ctx will record its latest sequence number on its
+         * buddy svcctx before be destroied, so here we continue use it.
+         */
+        atomic_set(&cli_gctx->gc_seq, svc_gctx->gsc_rvs_seq);
+
+        if (gss_svc_upcall_dup_handle(&cli_gctx->gc_svc_handle, svc_gctx)) {
+                CERROR("failed to dup svc handle\n");
+                goto err_out;
+        }
 
 
-        if (lgss_copy_reverse_context(grctx->src_ctx->gsc_mechctx, &mechctx) !=
+        if (lgss_copy_reverse_context(svc_gctx->gsc_mechctx, &mechctx) !=
             GSS_S_COMPLETE) {
                 CERROR("failed to copy mech context\n");
             GSS_S_COMPLETE) {
                 CERROR("failed to copy mech context\n");
-                return -ENOMEM;
+                goto err_svc_handle;
         }
 
         }
 
-        if (rawobj_dup(&cli_gctx->gc_handle, &grctx->src_ctx->gsc_rvs_hdl)) {
+        if (rawobj_dup(&cli_gctx->gc_handle, &svc_gctx->gsc_rvs_hdl)) {
                 CERROR("failed to dup reverse handle\n");
                 CERROR("failed to dup reverse handle\n");
-                lgss_delete_sec_context(&mechctx);
-                return -ENOMEM;
+                goto err_ctx;
         }
 
         cli_gctx->gc_mechctx = mechctx;
         gss_cli_ctx_uptodate(cli_gctx);
 
         return 0;
         }
 
         cli_gctx->gc_mechctx = mechctx;
         gss_cli_ctx_uptodate(cli_gctx);
 
         return 0;
+
+err_ctx:
+        lgss_delete_sec_context(&mechctx);
+err_svc_handle:
+        rawobj_free(&cli_gctx->gc_svc_handle);
+err_out:
+        return -ENOMEM;
 }
 
 int __init sptlrpc_gss_init(void)
 }
 
 int __init sptlrpc_gss_init(void)
index a854214..e282302 100644 (file)
@@ -445,10 +445,14 @@ int ptlrpc_connect_import(struct obd_import *imp, char *new_uuid)
                 }
         }
 
                 }
         }
 
+        rc = sptlrpc_import_sec_adapt(imp, NULL, 0);
+        if (rc)
+                GOTO(out, rc);
+
         /* Reset connect flags to the originally requested flags, in case
          * the server is updated on-the-fly we will get the new features. */
         imp->imp_connect_data.ocd_connect_flags = imp->imp_connect_flags_orig;
         /* Reset connect flags to the originally requested flags, in case
          * the server is updated on-the-fly we will get the new features. */
         imp->imp_connect_data.ocd_connect_flags = imp->imp_connect_flags_orig;
-        rc = obd_reconnect(imp->imp_obd->obd_self_export, obd,
+        rc = obd_reconnect(NULL, imp->imp_obd->obd_self_export, obd,
                            &obd->obd_uuid, &imp->imp_connect_data);
         if (rc)
                 GOTO(out, rc);
                            &obd->obd_uuid, &imp->imp_connect_data);
         if (rc)
                 GOTO(out, rc);
@@ -805,7 +809,7 @@ out:
                         struct obd_connect_data *ocd;
 
                         /* reply message might not be ready */
                         struct obd_connect_data *ocd;
 
                         /* reply message might not be ready */
-                        if (request->rq_repmsg != NULL)
+                        if (request->rq_repmsg == NULL)
                                 RETURN(-EPROTO);
 
                         ocd = lustre_swab_repbuf(request, REPLY_REC_OFF,
                                 RETURN(-EPROTO);
 
                         ocd = lustre_swab_repbuf(request, REPLY_REC_OFF,
index e223d5f..05295b8 100644 (file)
@@ -330,8 +330,7 @@ static const struct req_msg_field *mds_setxattr_client[] = {
 };
 
 static const struct req_msg_field *mds_setxattr_server[] = {
 };
 
 static const struct req_msg_field *mds_setxattr_server[] = {
-        &RMF_PTLRPC_BODY,
-        &RMF_EADATA
+        &RMF_PTLRPC_BODY
 };
 
 static const struct req_msg_field *mds_getattr_server[] = {
 };
 
 static const struct req_msg_field *mds_getattr_server[] = {
index 7d92ba6..0965e4e 100644 (file)
@@ -310,12 +310,13 @@ int ptlrpc_send_reply (struct ptlrpc_request *req, int may_be_difficult)
         int                        rc;
 
         /* We must already have a reply buffer (only ptlrpc_error() may be
         int                        rc;
 
         /* We must already have a reply buffer (only ptlrpc_error() may be
-         * called without one). The reply generated by security layer (e.g.
+         * called without one). The reply generated by sptlrpc layer (e.g.
          * error notify, etc.) might have NULL rq->reqmsg; Otherwise we must
          * have a request buffer which is either the actual (swabbed) incoming
          * request, or a saved copy if this is a req saved in
          * target_queue_final_reply().
          */
          * error notify, etc.) might have NULL rq->reqmsg; Otherwise we must
          * have a request buffer which is either the actual (swabbed) incoming
          * request, or a saved copy if this is a req saved in
          * target_queue_final_reply().
          */
+        LASSERT (req->rq_no_reply == 0);
         LASSERT (req->rq_reqbuf != NULL);
         LASSERT (rs != NULL);
         LASSERT (may_be_difficult || !rs->rs_difficult);
         LASSERT (req->rq_reqbuf != NULL);
         LASSERT (rs != NULL);
         LASSERT (may_be_difficult || !rs->rs_difficult);
@@ -375,7 +376,10 @@ out:
 
 int ptlrpc_reply (struct ptlrpc_request *req)
 {
 
 int ptlrpc_reply (struct ptlrpc_request *req)
 {
-        return (ptlrpc_send_reply (req, 0));
+        if (req->rq_no_reply)
+                return 0;
+        else
+                return (ptlrpc_send_reply(req, 0));
 }
 
 int ptlrpc_error(struct ptlrpc_request *req)
 }
 
 int ptlrpc_error(struct ptlrpc_request *req)
@@ -383,6 +387,9 @@ int ptlrpc_error(struct ptlrpc_request *req)
         int rc;
         ENTRY;
 
         int rc;
         ENTRY;
 
+        if (req->rq_no_reply)
+                RETURN(0);
+
         if (!req->rq_repmsg) {
                 rc = lustre_pack_reply(req, 1, NULL, NULL);
                 if (rc)
         if (!req->rq_repmsg) {
                 rc = lustre_pack_reply(req, 1, NULL, NULL);
                 if (rc)
index 146dd55..c59a312 100644 (file)
@@ -254,12 +254,8 @@ int lustre_pack_request(struct ptlrpc_request *req, __u32 magic, int count,
         LASSERT(count > 0);
         LASSERT(lens[MSG_PTLRPC_BODY_OFF] == sizeof(struct ptlrpc_body));
 
         LASSERT(count > 0);
         LASSERT(lens[MSG_PTLRPC_BODY_OFF] == sizeof(struct ptlrpc_body));
 
-        /* if we choose policy other than null, we have also choosed
-         * to use new message format.
-         */
-        if (magic == LUSTRE_MSG_MAGIC_V1 &&
-            req->rq_sec_flavor != SPTLRPC_FLVR_NULL)
-                magic = LUSTRE_MSG_MAGIC_V2;
+        /* only use new format, we don't need to be compatible with 1.4 */
+        magic = LUSTRE_MSG_MAGIC_V2;
 
         switch (magic) {
         case LUSTRE_MSG_MAGIC_V1:
 
         switch (magic) {
         case LUSTRE_MSG_MAGIC_V1:
index efa11e5..4d80f48 100644 (file)
@@ -190,7 +190,6 @@ int  sptlrpc_enc_pool_init(void);
 void sptlrpc_enc_pool_fini(void);
 int sptlrpc_proc_read_enc_pool(char *page, char **start, off_t off, int count,
                                int *eof, void *data);
 void sptlrpc_enc_pool_fini(void);
 int sptlrpc_proc_read_enc_pool(char *page, char **start, off_t off, int count,
                                int *eof, void *data);
-const char * sptlrpc_bulk_csum_alg2name(__u32 csum_alg);
 
 /* sec_lproc.c */
 int  sptlrpc_lproc_init(void);
 
 /* sec_lproc.c */
 int  sptlrpc_lproc_init(void);
index 7511b94..059c3f3 100644 (file)
@@ -1,7 +1,8 @@
 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  * vim:expandtab:shiftwidth=8:tabstop=8:
  *
 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  * vim:expandtab:shiftwidth=8:tabstop=8:
  *
- * Copyright (C) 2004-2006 Cluster File Systems, Inc.
+ * Copyright (C) 2004-2007 Cluster File Systems, Inc.
+ *   Author: Eric Mei <ericm@clusterfs.com>
  *
  *   This file is part of Lustre, http://www.lustre.org.
  *
  *
  *   This file is part of Lustre, http://www.lustre.org.
  *
@@ -54,7 +55,7 @@ static struct ptlrpc_sec_policy *policies[SPTLRPC_POLICY_MAX] = {
 
 int sptlrpc_register_policy(struct ptlrpc_sec_policy *policy)
 {
 
 int sptlrpc_register_policy(struct ptlrpc_sec_policy *policy)
 {
-        __u32 number = policy->sp_policy;
+        __u16 number = policy->sp_policy;
 
         LASSERT(policy->sp_name);
         LASSERT(policy->sp_cops);
 
         LASSERT(policy->sp_name);
         LASSERT(policy->sp_cops);
@@ -78,7 +79,7 @@ EXPORT_SYMBOL(sptlrpc_register_policy);
 
 int sptlrpc_unregister_policy(struct ptlrpc_sec_policy *policy)
 {
 
 int sptlrpc_unregister_policy(struct ptlrpc_sec_policy *policy)
 {
-        __u32 number = policy->sp_policy;
+        __u16 number = policy->sp_policy;
 
         LASSERT(number < SPTLRPC_POLICY_MAX);
 
 
         LASSERT(number < SPTLRPC_POLICY_MAX);
 
@@ -99,21 +100,17 @@ int sptlrpc_unregister_policy(struct ptlrpc_sec_policy *policy)
 EXPORT_SYMBOL(sptlrpc_unregister_policy);
 
 static
 EXPORT_SYMBOL(sptlrpc_unregister_policy);
 
 static
-struct ptlrpc_sec_policy * sptlrpc_flavor2policy(ptlrpc_sec_flavor_t flavor)
+struct ptlrpc_sec_policy * sptlrpc_rpcflavor2policy(__u16 flavor)
 {
 {
-#ifdef CONFIG_KMOD
         static DECLARE_MUTEX(load_mutex);
         static DECLARE_MUTEX(load_mutex);
-#endif
-        static atomic_t         loaded = ATOMIC_INIT(0);
-        struct                  ptlrpc_sec_policy *policy;
-        __u32                   number = SEC_FLAVOR_POLICY(flavor), flag = 0;
+        static atomic_t           loaded = ATOMIC_INIT(0);
+        struct ptlrpc_sec_policy *policy;
+        __u16                     number = RPC_FLVR_POLICY(flavor), flag = 0;
 
         if (number >= SPTLRPC_POLICY_MAX)
                 return NULL;
 
 
         if (number >= SPTLRPC_POLICY_MAX)
                 return NULL;
 
-#ifdef CONFIG_KMOD
 again:
 again:
-#endif
         read_lock(&policy_lock);
         policy = policies[number];
         if (policy && !try_module_get(policy->sp_owner))
         read_lock(&policy_lock);
         policy = policies[number];
         if (policy && !try_module_get(policy->sp_owner))
@@ -122,18 +119,15 @@ again:
                 flag = atomic_read(&loaded);
         read_unlock(&policy_lock);
 
                 flag = atomic_read(&loaded);
         read_unlock(&policy_lock);
 
-#ifdef CONFIG_KMOD
         /* if failure, try to load gss module, once */
         /* if failure, try to load gss module, once */
-        if (unlikely(policy == NULL) &&
-            flag == 0 &&
-            (number == SPTLRPC_POLICY_GSS ||
-             number == SPTLRPC_POLICY_GSS_PIPEFS)) {
+        if (unlikely(policy == NULL) && flag == 0 &&
+            number == SPTLRPC_POLICY_GSS) {
                 mutex_down(&load_mutex);
                 if (atomic_read(&loaded) == 0) {
                         if (request_module("ptlrpc_gss") != 0)
                                 CERROR("Unable to load module ptlrpc_gss\n");
                         else
                 mutex_down(&load_mutex);
                 if (atomic_read(&loaded) == 0) {
                         if (request_module("ptlrpc_gss") != 0)
                                 CERROR("Unable to load module ptlrpc_gss\n");
                         else
-                                CWARN("module ptlrpc_gss loaded\n");
+                                CWARN("module ptlrpc_gss loaded on demand\n");
 
                         atomic_set(&loaded, 1);
                 }
 
                         atomic_set(&loaded, 1);
                 }
@@ -141,12 +135,11 @@ again:
 
                 goto again;
         }
 
                 goto again;
         }
-#endif
 
         return policy;
 }
 
 
         return policy;
 }
 
-ptlrpc_sec_flavor_t sptlrpc_name2flavor(const char *name)
+__u16 sptlrpc_name2rpcflavor(const char *name)
 {
         if (!strcmp(name, "null"))
                 return SPTLRPC_FLVR_NULL;
 {
         if (!strcmp(name, "null"))
                 return SPTLRPC_FLVR_NULL;
@@ -161,9 +154,9 @@ ptlrpc_sec_flavor_t sptlrpc_name2flavor(const char *name)
 
         return SPTLRPC_FLVR_INVALID;
 }
 
         return SPTLRPC_FLVR_INVALID;
 }
-EXPORT_SYMBOL(sptlrpc_name2flavor);
+EXPORT_SYMBOL(sptlrpc_name2rpcflavor);
 
 
-char *sptlrpc_flavor2name(ptlrpc_sec_flavor_t flavor)
+const char *sptlrpc_rpcflavor2name(__u16 flavor)
 {
         switch (flavor) {
         case SPTLRPC_FLVR_NULL:
 {
         switch (flavor) {
         case SPTLRPC_FLVR_NULL:
@@ -179,11 +172,30 @@ char *sptlrpc_flavor2name(ptlrpc_sec_flavor_t flavor)
         case SPTLRPC_FLVR_KRB5P:
                 return "krb5p";
         default:
         case SPTLRPC_FLVR_KRB5P:
                 return "krb5p";
         default:
-                CERROR("invalid flavor 0x%x(p%u,s%u,v%u)\n", flavor,
-                       SEC_FLAVOR_POLICY(flavor), SEC_FLAVOR_MECH(flavor),
-                       SEC_FLAVOR_SVC(flavor));
+                CERROR("invalid rpc flavor 0x%x(p%u,s%u,v%u)\n", flavor,
+                       RPC_FLVR_POLICY(flavor), RPC_FLVR_MECH(flavor),
+                       RPC_FLVR_SVC(flavor));
         }
         }
-        return "UNKNOWN";
+        return "unknown";
+}
+EXPORT_SYMBOL(sptlrpc_rpcflavor2name);
+
+int sptlrpc_flavor2name(struct sptlrpc_flavor *sf, char *buf, int bufsize)
+{
+        char           *bulk;
+
+        if (sf->sf_bulk_priv != BULK_PRIV_ALG_NULL)
+                bulk = "bulkp";
+        else if (sf->sf_bulk_csum != BULK_CSUM_ALG_NULL)
+                bulk = "bulki";
+        else
+                bulk = "bulkn";
+
+        snprintf(buf, bufsize, "%s-%s:%s/%s",
+                 sptlrpc_rpcflavor2name(sf->sf_rpc), bulk,
+                 sptlrpc_bulk_csum_alg2name(sf->sf_bulk_csum),
+                 sptlrpc_bulk_priv_alg2name(sf->sf_bulk_priv));
+        return 0;
 }
 EXPORT_SYMBOL(sptlrpc_flavor2name);
 
 }
 EXPORT_SYMBOL(sptlrpc_flavor2name);
 
@@ -200,10 +212,11 @@ struct ptlrpc_cli_ctx *get_my_ctx(struct ptlrpc_sec *sec)
         LASSERT(sec);
         LASSERT(sec->ps_policy->sp_cops->lookup_ctx);
 
         LASSERT(sec);
         LASSERT(sec->ps_policy->sp_cops->lookup_ctx);
 
-        if (sec->ps_flags & (PTLRPC_SEC_FL_REVERSE | PTLRPC_SEC_FL_ROOTONLY)) {
+        if (sec->ps_flvr.sf_flags & (PTLRPC_SEC_FL_REVERSE |
+                                     PTLRPC_SEC_FL_ROOTONLY)) {
                 vcred.vc_uid = 0;
                 vcred.vc_gid = 0;
                 vcred.vc_uid = 0;
                 vcred.vc_gid = 0;
-                if (sec->ps_flags & PTLRPC_SEC_FL_REVERSE) {
+                if (sec->ps_flvr.sf_flags & PTLRPC_SEC_FL_REVERSE) {
                         create = 0;
                         remove_dead = 0;
                 }
                         create = 0;
                         remove_dead = 0;
                 }
@@ -272,21 +285,56 @@ int sptlrpc_cli_ctx_display(struct ptlrpc_cli_ctx *ctx, char *buf, int bufsize)
         return ctx->cc_ops->display(ctx, buf, bufsize);
 }
 
         return ctx->cc_ops->display(ctx, buf, bufsize);
 }
 
+static int sptlrpc_import_sec_check_expire(struct obd_import *imp)
+{
+        int     adapt = 0;
+
+        spin_lock(&imp->imp_lock);
+        if (imp->imp_sec_expire &&
+            imp->imp_sec_expire < cfs_time_current_sec()) {
+                adapt = 1;
+                imp->imp_sec_expire = 0;
+        }
+        spin_unlock(&imp->imp_lock);
+
+        if (!adapt)
+                return 0;
+
+        CDEBUG(D_SEC, "found delayed sec adapt expired, do it now\n");
+        return sptlrpc_import_sec_adapt(imp, NULL, 0);
+}
+
 int sptlrpc_req_get_ctx(struct ptlrpc_request *req)
 {
         struct obd_import *imp = req->rq_import;
 int sptlrpc_req_get_ctx(struct ptlrpc_request *req)
 {
         struct obd_import *imp = req->rq_import;
+        struct ptlrpc_sec *sec;
+        int                rc;
         ENTRY;
 
         LASSERT(!req->rq_cli_ctx);
         LASSERT(imp);
 
         ENTRY;
 
         LASSERT(!req->rq_cli_ctx);
         LASSERT(imp);
 
-        if (imp->imp_sec == NULL) {
-                CERROR("import %p (%s) with no sec pointer\n",
+        if (unlikely(imp->imp_sec_expire)) {
+                rc = sptlrpc_import_sec_check_expire(imp);
+                if (rc)
+                        RETURN(rc);
+        }
+
+        sec = sptlrpc_import_sec_ref(imp);
+        if (sec == NULL) {
+                CERROR("import %p (%s) with no ptlrpc_sec\n",
                        imp, ptlrpc_import_state_name(imp->imp_state));
                 RETURN(-EACCES);
         }
 
                        imp, ptlrpc_import_state_name(imp->imp_state));
                 RETURN(-EACCES);
         }
 
-        req->rq_cli_ctx = get_my_ctx(imp->imp_sec);
+        if (unlikely(sec->ps_dying)) {
+                CERROR("attempt to use dying sec %p\n", sec);
+                return -EACCES;
+        }
+
+        req->rq_cli_ctx = get_my_ctx(sec);
+
+        sptlrpc_sec_put(sec);
 
         if (!req->rq_cli_ctx) {
                 CERROR("req %p: fail to get context\n", req);
 
         if (!req->rq_cli_ctx) {
                 CERROR("req %p: fail to get context\n", req);
@@ -321,35 +369,115 @@ void sptlrpc_req_put_ctx(struct ptlrpc_request *req, int sync)
         EXIT;
 }
 
         EXIT;
 }
 
+static
+int sptlrpc_req_ctx_switch(struct ptlrpc_request *req,
+                           struct ptlrpc_cli_ctx *oldctx,
+                           struct ptlrpc_cli_ctx *newctx)
+{
+        struct sptlrpc_flavor   old_flvr;
+        char                   *reqmsg;
+        int                     reqmsg_size;
+        int                     rc;
+
+        if (likely(oldctx->cc_sec == newctx->cc_sec))
+                return 0;
+
+        LASSERT(req->rq_reqmsg);
+        LASSERT(req->rq_reqlen);
+        LASSERT(req->rq_replen);
+
+        CWARN("req %p: switch ctx %p -> %p, switch sec %p(%s) -> %p(%s)\n",
+              req, oldctx, newctx,
+              oldctx->cc_sec, oldctx->cc_sec->ps_policy->sp_name,
+              newctx->cc_sec, newctx->cc_sec->ps_policy->sp_name);
+
+        /* save flavor */
+        old_flvr = req->rq_flvr;
+
+        /* save request message */
+        reqmsg_size = req->rq_reqlen;
+        OBD_ALLOC(reqmsg, reqmsg_size);
+        if (reqmsg == NULL)
+                return -ENOMEM;
+        memcpy(reqmsg, req->rq_reqmsg, reqmsg_size);
+
+        /* release old req/rep buf */
+        req->rq_cli_ctx = oldctx;
+        sptlrpc_cli_free_reqbuf(req);
+        sptlrpc_cli_free_repbuf(req);
+        req->rq_cli_ctx = newctx;
+
+        /* recalculate the flavor */
+        sptlrpc_req_set_flavor(req, 0);
+
+        /* alloc new request buffer
+         * we don't need to alloc reply buffer here, leave it to the
+         * rest procedure of ptlrpc
+         */
+        rc = sptlrpc_cli_alloc_reqbuf(req, reqmsg_size);
+        if (!rc) {
+                LASSERT(req->rq_reqmsg);
+                memcpy(req->rq_reqmsg, reqmsg, reqmsg_size);
+        } else {
+                CWARN("failed to alloc reqbuf: %d\n", rc);
+                req->rq_flvr = old_flvr;
+        }
+
+        OBD_FREE(reqmsg, reqmsg_size);
+        return rc;
+}
+
 /*
 /*
- * request must have a context. if failed to get new context,
- * just restore the old one
+ * request must have a context. in any case of failure, restore the
+ * restore the old one. a request must have a ctx.
  */
 int sptlrpc_req_replace_dead_ctx(struct ptlrpc_request *req)
 {
  */
 int sptlrpc_req_replace_dead_ctx(struct ptlrpc_request *req)
 {
-        struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx;
-        int rc;
+        struct ptlrpc_cli_ctx *oldctx = req->rq_cli_ctx;
+        struct ptlrpc_cli_ctx *newctx;
+        int                    rc;
         ENTRY;
 
         ENTRY;
 
-        LASSERT(ctx);
-        LASSERT(test_bit(PTLRPC_CTX_DEAD_BIT, &ctx->cc_flags));
-
-        /* make sure not on context waiting list */
-        spin_lock(&ctx->cc_lock);
-        list_del_init(&req->rq_ctx_chain);
-        spin_unlock(&ctx->cc_lock);
+        LASSERT(oldctx);
+        LASSERT(test_bit(PTLRPC_CTX_DEAD_BIT, &oldctx->cc_flags));
 
 
-        sptlrpc_cli_ctx_get(ctx);
+        sptlrpc_cli_ctx_get(oldctx);
         sptlrpc_req_put_ctx(req, 0);
         sptlrpc_req_put_ctx(req, 0);
+
         rc = sptlrpc_req_get_ctx(req);
         rc = sptlrpc_req_get_ctx(req);
-        if (!rc) {
-                LASSERT(req->rq_cli_ctx);
-                sptlrpc_cli_ctx_put(ctx, 1);
-        } else {
+        if (unlikely(rc)) {
                 LASSERT(!req->rq_cli_ctx);
                 LASSERT(!req->rq_cli_ctx);
-                req->rq_cli_ctx = ctx;
+
+                /* restore old ctx */
+                req->rq_cli_ctx = oldctx;
+                RETURN(rc);
         }
         }
-        RETURN(rc);
+
+        newctx = req->rq_cli_ctx;
+        LASSERT(newctx);
+
+        if (unlikely(newctx == oldctx)) {
+                /*
+                 * still get the old ctx, usually means system busy
+                 */
+                CWARN("ctx (%p, fl %lx) doesn't switch, relax a little bit\n",
+                      newctx, newctx->cc_flags);
+
+                schedule_timeout(HZ);
+        } else {
+                rc = sptlrpc_req_ctx_switch(req, oldctx, newctx);
+                if (rc) {
+                        /* restore old ctx */
+                        sptlrpc_req_put_ctx(req, 0);
+                        req->rq_cli_ctx = oldctx;
+                        RETURN(rc);
+                }
+
+                LASSERT(req->rq_cli_ctx == newctx);
+        }
+
+        sptlrpc_cli_ctx_put(oldctx, 1);
+        RETURN(0);
 }
 EXPORT_SYMBOL(sptlrpc_req_replace_dead_ctx);
 
 }
 EXPORT_SYMBOL(sptlrpc_req_replace_dead_ctx);
 
@@ -422,6 +550,12 @@ int sptlrpc_req_refresh_ctx(struct ptlrpc_request *req, long timeout)
 
         LASSERT(ctx);
 
 
         LASSERT(ctx);
 
+        /*
+         * during the process a request's context might change type even
+         * (e.g. from gss ctx to plain ctx), so each loop we need to re-check
+         * everything
+         */
+again:
         /* skip special ctxs */
         if (cli_ctx_is_eternal(ctx) || req->rq_ctx_init || req->rq_ctx_fini)
                 RETURN(0);
         /* skip special ctxs */
         if (cli_ctx_is_eternal(ctx) || req->rq_ctx_init || req->rq_ctx_fini)
                 RETURN(0);
@@ -432,7 +566,6 @@ int sptlrpc_req_refresh_ctx(struct ptlrpc_request *req, long timeout)
         }
         LASSERT(test_bit(PTLRPC_CTX_NEW_BIT, &ctx->cc_flags) == 0);
 
         }
         LASSERT(test_bit(PTLRPC_CTX_NEW_BIT, &ctx->cc_flags) == 0);
 
-again:
         LASSERT(ctx->cc_ops->validate);
         if (ctx->cc_ops->validate(ctx) == 0) {
                 req_off_ctx_list(req, ctx);
         LASSERT(ctx->cc_ops->validate);
         if (ctx->cc_ops->validate(ctx) == 0) {
                 req_off_ctx_list(req, ctx);
@@ -477,32 +610,21 @@ again:
         }
 
         if (unlikely(test_bit(PTLRPC_CTX_DEAD_BIT, &ctx->cc_flags))) {
         }
 
         if (unlikely(test_bit(PTLRPC_CTX_DEAD_BIT, &ctx->cc_flags))) {
-                /* don't have to, but we don't want to release it too soon */
-                sptlrpc_cli_ctx_get(ctx);
-
                 rc = sptlrpc_req_replace_dead_ctx(req);
                 if (rc) {
                         LASSERT(ctx == req->rq_cli_ctx);
                 rc = sptlrpc_req_replace_dead_ctx(req);
                 if (rc) {
                         LASSERT(ctx == req->rq_cli_ctx);
-                        CERROR("req %p: failed to replace dead ctx %p\n",
-                                req, ctx);
+                        CERROR("req %p: failed to replace dead ctx %p: %d\n",
+                                req, ctx, rc);
                         req->rq_err = 1;
                         LASSERT(list_empty(&req->rq_ctx_chain));
                         req->rq_err = 1;
                         LASSERT(list_empty(&req->rq_ctx_chain));
-                        sptlrpc_cli_ctx_put(ctx, 1);
-                        RETURN(-ENOMEM);
+                        RETURN(rc);
                 }
 
                 }
 
-                /* FIXME
-                 * if ctx didn't really switch, might be cpu tight or sth,
-                 * we just relax a little bit.
-                 */
-                if (ctx == req->rq_cli_ctx)
-                        schedule();
-
-                CWARN("req %p: replace dead ctx %p(%u->%s) => %p\n",
-                      req, ctx, ctx->cc_vcred.vc_uid,
-                      sec2target_str(ctx->cc_sec), req->rq_cli_ctx);
+                CWARN("req %p: replace dead ctx %p => ctx %p (%u->%s)\n",
+                      req, ctx, req->rq_cli_ctx,
+                      req->rq_cli_ctx->cc_vcred.vc_uid,
+                      sec2target_str(req->rq_cli_ctx->cc_sec));
 
 
-                sptlrpc_cli_ctx_put(ctx, 1);
                 ctx = req->rq_cli_ctx;
                 LASSERT(list_empty(&req->rq_ctx_chain));
 
                 ctx = req->rq_cli_ctx;
                 LASSERT(list_empty(&req->rq_ctx_chain));
 
@@ -534,12 +656,14 @@ again:
                                ctx_refresh_interrupt, req);
         rc = l_wait_event(req->rq_reply_waitq, ctx_check_refresh(ctx), &lwi);
 
                                ctx_refresh_interrupt, req);
         rc = l_wait_event(req->rq_reply_waitq, ctx_check_refresh(ctx), &lwi);
 
-        /* five cases we are here:
-         * 1. successfully refreshed;
-         * 2. someone else mark this ctx dead by force;
-         * 3. interruptted;
-         * 4. timedout, and we don't want recover from the failure;
-         * 5. timedout, and waked up upon recovery finished;
+        /* following cases we could be here:
+         * - successfully refreshed;
+         * - interruptted;
+         * - timedout, and we don't want recover from the failure;
+         * - timedout, and waked up upon recovery finished;
+         * - someone else mark this ctx dead by force;
+         * - someone invalidate the req and call wake_client_req(),
+         *   e.g. ptlrpc_abort_inflight();
          */
         if (!cli_ctx_is_refreshed(ctx)) {
                 /* timed out or interruptted */
          */
         if (!cli_ctx_is_refreshed(ctx)) {
                 /* timed out or interruptted */
@@ -552,12 +676,16 @@ again:
         goto again;
 }
 
         goto again;
 }
 
+/*
+ * Note this could be called in two situations:
+ * - new request from ptlrpc_pre_req(), with proper @opcode
+ * - old request which changed ctx in the middle, with @opcode == 0
+ */
 void sptlrpc_req_set_flavor(struct ptlrpc_request *req, int opcode)
 {
 void sptlrpc_req_set_flavor(struct ptlrpc_request *req, int opcode)
 {
-        struct sec_flavor_config *conf;
+        struct ptlrpc_sec *sec;
 
         LASSERT(req->rq_import);
 
         LASSERT(req->rq_import);
-        LASSERT(req->rq_import->imp_sec);
         LASSERT(req->rq_cli_ctx);
         LASSERT(req->rq_cli_ctx->cc_sec);
         LASSERT(req->rq_bulk_read == 0 || req->rq_bulk_write == 0);
         LASSERT(req->rq_cli_ctx);
         LASSERT(req->rq_cli_ctx->cc_sec);
         LASSERT(req->rq_bulk_read == 0 || req->rq_bulk_write == 0);
@@ -576,44 +704,45 @@ void sptlrpc_req_set_flavor(struct ptlrpc_request *req, int opcode)
         case SEC_CTX_FINI:
                 req->rq_ctx_fini = 1;
                 break;
         case SEC_CTX_FINI:
                 req->rq_ctx_fini = 1;
                 break;
+        case 0:
+                /* init/fini rpc won't be resend, so can't be here */
+                LASSERT(req->rq_ctx_init == 0);
+                LASSERT(req->rq_ctx_fini == 0);
+
+                /* cleanup flags, which should be recalculated */
+                req->rq_pack_udesc = 0;
+                req->rq_pack_bulk = 0;
+                break;
         }
 
         }
 
-        req->rq_sec_flavor = req->rq_cli_ctx->cc_sec->ps_flavor;
+        sec = req->rq_cli_ctx->cc_sec;
+
+        spin_lock(&sec->ps_lock);
+        req->rq_flvr = sec->ps_flvr;
+        spin_unlock(&sec->ps_lock);
 
         /* force SVC_NULL for context initiation rpc, SVC_INTG for context
 
         /* force SVC_NULL for context initiation rpc, SVC_INTG for context
-         * destruction rpc
-         */
-        if (unlikely(req->rq_ctx_init)) {
-                req->rq_sec_flavor = SEC_MAKE_RPC_FLAVOR(
-                                SEC_FLAVOR_POLICY(req->rq_sec_flavor),
-                                SEC_FLAVOR_MECH(req->rq_sec_flavor),
-                                SPTLRPC_SVC_NULL);
-        } else if (unlikely(req->rq_ctx_fini)) {
-                req->rq_sec_flavor = SEC_MAKE_RPC_FLAVOR(
-                                SEC_FLAVOR_POLICY(req->rq_sec_flavor),
-                                SEC_FLAVOR_MECH(req->rq_sec_flavor),
-                                SPTLRPC_SVC_INTG);
-        }
-
-        conf = &req->rq_import->imp_obd->u.cli.cl_sec_conf;
-
-        /* user descriptor flag, except ROOTONLY which don't need, and
-         * null security which can't
-         */
-        if ((conf->sfc_flags & PTLRPC_SEC_FL_ROOTONLY) == 0 &&
-            req->rq_sec_flavor != SPTLRPC_FLVR_NULL)
-                req->rq_sec_flavor |= SEC_FLAVOR_FL_USER;
+         * destruction rpc */
+        if (unlikely(req->rq_ctx_init))
+                rpc_flvr_set_svc(&req->rq_flvr.sf_rpc, SPTLRPC_SVC_NULL);
+        else if (unlikely(req->rq_ctx_fini))
+                rpc_flvr_set_svc(&req->rq_flvr.sf_rpc, SPTLRPC_SVC_INTG);
+
+        /* user descriptor flag, null security can't do it anyway */
+        if ((sec->ps_flvr.sf_flags & PTLRPC_SEC_FL_UDESC) &&
+            (req->rq_flvr.sf_rpc != SPTLRPC_FLVR_NULL))
+                req->rq_pack_udesc = 1;
 
         /* bulk security flag */
         if ((req->rq_bulk_read || req->rq_bulk_write) &&
 
         /* bulk security flag */
         if ((req->rq_bulk_read || req->rq_bulk_write) &&
-            (conf->sfc_bulk_priv != BULK_PRIV_ALG_NULL ||
-             conf->sfc_bulk_csum != BULK_CSUM_ALG_NULL))
-                req->rq_sec_flavor |= SEC_FLAVOR_FL_BULK;
+            (req->rq_flvr.sf_bulk_priv != BULK_PRIV_ALG_NULL ||
+             req->rq_flvr.sf_bulk_csum != BULK_CSUM_ALG_NULL))
+                req->rq_pack_bulk = 1;
 }
 
 void sptlrpc_request_out_callback(struct ptlrpc_request *req)
 {
 }
 
 void sptlrpc_request_out_callback(struct ptlrpc_request *req)
 {
-        if (SEC_FLAVOR_SVC(req->rq_sec_flavor) != SPTLRPC_SVC_PRIV)
+        if (RPC_FLVR_SVC(req->rq_flvr.sf_rpc) != SPTLRPC_SVC_PRIV)
                 return;
 
         LASSERT(req->rq_clrbuf);
                 return;
 
         LASSERT(req->rq_clrbuf);
@@ -632,6 +761,7 @@ void sptlrpc_request_out_callback(struct ptlrpc_request *req)
  */
 int sptlrpc_import_check_ctx(struct obd_import *imp)
 {
  */
 int sptlrpc_import_check_ctx(struct obd_import *imp)
 {
+        struct ptlrpc_sec     *sec;
         struct ptlrpc_cli_ctx *ctx;
         struct ptlrpc_request *req = NULL;
         int rc;
         struct ptlrpc_cli_ctx *ctx;
         struct ptlrpc_request *req = NULL;
         int rc;
@@ -639,7 +769,10 @@ int sptlrpc_import_check_ctx(struct obd_import *imp)
 
         might_sleep();
 
 
         might_sleep();
 
-        ctx = get_my_ctx(imp->imp_sec);
+        sec = sptlrpc_import_sec_ref(imp);
+        ctx = get_my_ctx(sec);
+        sptlrpc_sec_put(sec);
+
         if (!ctx)
                 RETURN(1);
 
         if (!ctx)
                 RETURN(1);
 
@@ -687,7 +820,7 @@ int sptlrpc_cli_wrap_request(struct ptlrpc_request *req)
                         RETURN(rc);
         }
 
                         RETURN(rc);
         }
 
-        switch (SEC_FLAVOR_SVC(req->rq_sec_flavor)) {
+        switch (RPC_FLVR_SVC(req->rq_flvr.sf_rpc)) {
         case SPTLRPC_SVC_NULL:
         case SPTLRPC_SVC_AUTH:
         case SPTLRPC_SVC_INTG:
         case SPTLRPC_SVC_NULL:
         case SPTLRPC_SVC_AUTH:
         case SPTLRPC_SVC_INTG:
@@ -717,7 +850,7 @@ int sptlrpc_cli_wrap_request(struct ptlrpc_request *req)
 int sptlrpc_cli_unwrap_reply(struct ptlrpc_request *req)
 {
         struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx;
 int sptlrpc_cli_unwrap_reply(struct ptlrpc_request *req)
 {
         struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx;
-        int rc;
+        int                    rc;
         ENTRY;
 
         LASSERT(ctx);
         ENTRY;
 
         LASSERT(ctx);
@@ -733,38 +866,45 @@ int sptlrpc_cli_unwrap_reply(struct ptlrpc_request *req)
                 RETURN(-EPROTO);
         }
 
                 RETURN(-EPROTO);
         }
 
+
         if (req->rq_repbuf->lm_magic == LUSTRE_MSG_MAGIC_V1 ||
             req->rq_repbuf->lm_magic == LUSTRE_MSG_MAGIC_V1_SWABBED) {
         if (req->rq_repbuf->lm_magic == LUSTRE_MSG_MAGIC_V1 ||
             req->rq_repbuf->lm_magic == LUSTRE_MSG_MAGIC_V1_SWABBED) {
-                /* it's must be null flavor, so our requets also should be
-                 * in null flavor */
-                if (SEC_FLAVOR_POLICY(req->rq_sec_flavor) !=
+                /*
+                 * v1 message, it's must be null flavor, so our requets also
+                 * should be in null flavor
+                 */
+                if (RPC_FLVR_POLICY(req->rq_flvr.sf_rpc) !=
                     SPTLRPC_POLICY_NULL) {
                     SPTLRPC_POLICY_NULL) {
-                        CERROR("request flavor is %x but reply with null\n",
-                               req->rq_sec_flavor);
+                        CERROR("request was %s but reply with null\n",
+                               sptlrpc_rpcflavor2name(req->rq_flvr.sf_rpc));
                         RETURN(-EPROTO);
                 }
         } else {
                         RETURN(-EPROTO);
                 }
         } else {
-                /* v2 message... */
-                ptlrpc_sec_flavor_t tmpf = req->rq_repbuf->lm_secflvr;
+                /*
+                 * v2 message, check request/reply policy match
+                 */
+                __u16 rpc_flvr = WIRE_FLVR_RPC(req->rq_repbuf->lm_secflvr);
 
                 if (req->rq_repbuf->lm_magic == LUSTRE_MSG_MAGIC_V2_SWABBED)
 
                 if (req->rq_repbuf->lm_magic == LUSTRE_MSG_MAGIC_V2_SWABBED)
-                        __swab32s(&tmpf);
+                        __swab16s(&rpc_flvr);
 
 
-                if (SEC_FLAVOR_POLICY(tmpf) !=
-                    SEC_FLAVOR_POLICY(req->rq_sec_flavor)) {
-                        CERROR("request policy %u while reply with %d\n",
-                               SEC_FLAVOR_POLICY(req->rq_sec_flavor),
-                               SEC_FLAVOR_POLICY(tmpf));
+                if (RPC_FLVR_POLICY(rpc_flvr) !=
+                    RPC_FLVR_POLICY(req->rq_flvr.sf_rpc)) {
+                        CERROR("request policy was %u while reply with %u\n",
+                               RPC_FLVR_POLICY(req->rq_flvr.sf_rpc),
+                               RPC_FLVR_POLICY(rpc_flvr));
                         RETURN(-EPROTO);
                 }
 
                         RETURN(-EPROTO);
                 }
 
-                if ((SEC_FLAVOR_POLICY(req->rq_sec_flavor) !=
-                     SPTLRPC_POLICY_NULL) &&
+                /* do nothing if it's null policy; otherwise unpack the
+                 * wrapper message
+                 */
+                if (RPC_FLVR_POLICY(rpc_flvr) != SPTLRPC_POLICY_NULL &&
                     lustre_unpack_msg(req->rq_repbuf, req->rq_nob_received))
                         RETURN(-EPROTO);
         }
 
                     lustre_unpack_msg(req->rq_repbuf, req->rq_nob_received))
                         RETURN(-EPROTO);
         }
 
-        switch (SEC_FLAVOR_SVC(req->rq_sec_flavor)) {
+        switch (RPC_FLVR_SVC(req->rq_flvr.sf_rpc)) {
         case SPTLRPC_SVC_NULL:
         case SPTLRPC_SVC_AUTH:
         case SPTLRPC_SVC_INTG:
         case SPTLRPC_SVC_NULL:
         case SPTLRPC_SVC_AUTH:
         case SPTLRPC_SVC_INTG:
@@ -784,16 +924,41 @@ int sptlrpc_cli_unwrap_reply(struct ptlrpc_request *req)
 }
 
 /**************************************************
 }
 
 /**************************************************
+ * sec ID                                         *
+ **************************************************/
+
+/*
+ * "fixed" sec (e.g. null) use sec_id < 0
+ */
+static atomic_t sptlrpc_sec_id = ATOMIC_INIT(1);
+
+int sptlrpc_get_next_secid(void)
+{
+        return atomic_inc_return(&sptlrpc_sec_id);
+}
+EXPORT_SYMBOL(sptlrpc_get_next_secid);
+
+/**************************************************
  * client side high-level security APIs           *
  **************************************************/
 
  * client side high-level security APIs           *
  **************************************************/
 
-static
-void sec_cop_destroy_sec(struct ptlrpc_sec *sec)
+static int sec_cop_flush_ctx_cache(struct ptlrpc_sec *sec, uid_t uid,
+                                   int grace, int force)
+{
+        struct ptlrpc_sec_policy *policy = sec->ps_policy;
+
+        LASSERT(policy->sp_cops);
+        LASSERT(policy->sp_cops->flush_ctx_cache);
+
+        return policy->sp_cops->flush_ctx_cache(sec, uid, grace, force);
+}
+
+static void sec_cop_destroy_sec(struct ptlrpc_sec *sec)
 {
         struct ptlrpc_sec_policy *policy = sec->ps_policy;
 
         LASSERT(atomic_read(&sec->ps_refcount) == 0);
 {
         struct ptlrpc_sec_policy *policy = sec->ps_policy;
 
         LASSERT(atomic_read(&sec->ps_refcount) == 0);
-        LASSERT(atomic_read(&sec->ps_busy) == 0);
+        LASSERT(atomic_read(&sec->ps_nctx) == 0);
         LASSERT(policy->sp_cops->destroy_sec);
 
         CDEBUG(D_SEC, "%s@%p: being destroied\n", sec->ps_policy->sp_name, sec);
         LASSERT(policy->sp_cops->destroy_sec);
 
         CDEBUG(D_SEC, "%s@%p: being destroied\n", sec->ps_policy->sp_name, sec);
@@ -802,156 +967,316 @@ void sec_cop_destroy_sec(struct ptlrpc_sec *sec)
         sptlrpc_policy_put(policy);
 }
 
         sptlrpc_policy_put(policy);
 }
 
-static
-int sec_cop_flush_ctx_cache(struct ptlrpc_sec *sec, uid_t uid,
-                            int grace, int force)
+void sptlrpc_sec_destroy(struct ptlrpc_sec *sec)
 {
 {
-        struct ptlrpc_sec_policy *policy = sec->ps_policy;
+        sec_cop_destroy_sec(sec);
+}
+EXPORT_SYMBOL(sptlrpc_sec_destroy);
 
 
-        LASSERT(policy->sp_cops);
-        LASSERT(policy->sp_cops->flush_ctx_cache);
+static void sptlrpc_sec_kill(struct ptlrpc_sec *sec)
+{
+        LASSERT(atomic_read(&sec->ps_refcount) > 0);
 
 
-        return policy->sp_cops->flush_ctx_cache(sec, uid, grace, force);
+        if (sec->ps_policy->sp_cops->kill_sec) {
+                sec->ps_policy->sp_cops->kill_sec(sec);
+
+                sec_cop_flush_ctx_cache(sec, -1, 1, 1);
+        }
 }
 
 }
 
-void sptlrpc_sec_destroy(struct ptlrpc_sec *sec)
+struct ptlrpc_sec *sptlrpc_sec_get(struct ptlrpc_sec *sec)
 {
 {
-        sec_cop_destroy_sec(sec);
+        if (sec) {
+                LASSERT(atomic_read(&sec->ps_refcount) > 0);
+                atomic_inc(&sec->ps_refcount);
+        }
+
+        return sec;
 }
 }
-EXPORT_SYMBOL(sptlrpc_sec_destroy);
+EXPORT_SYMBOL(sptlrpc_sec_get);
+
+void sptlrpc_sec_put(struct ptlrpc_sec *sec)
+{
+        if (sec) {
+                LASSERT(atomic_read(&sec->ps_refcount) > 0);
+
+                if (atomic_dec_and_test(&sec->ps_refcount)) {
+                        LASSERT(atomic_read(&sec->ps_nctx) == 0);
+
+                        sptlrpc_gc_del_sec(sec);
+                        sec_cop_destroy_sec(sec);
+                }
+        }
+}
+EXPORT_SYMBOL(sptlrpc_sec_put);
 
 /*
 
 /*
- * let policy module to determine whether take refrence of
- * import or not.
+ * it's policy module responsible for taking refrence of import
  */
 static
  */
 static
-struct ptlrpc_sec * import_create_sec(struct obd_import *imp,
-                                      struct ptlrpc_svc_ctx *ctx,
-                                      __u32 flavor,
-                                      unsigned long flags)
+struct ptlrpc_sec * sptlrpc_sec_create(struct obd_import *imp,
+                                       struct ptlrpc_svc_ctx *svc_ctx,
+                                       struct sptlrpc_flavor *sf,
+                                       enum lustre_sec_part sp)
 {
         struct ptlrpc_sec_policy *policy;
 {
         struct ptlrpc_sec_policy *policy;
-        struct ptlrpc_sec *sec;
+        struct ptlrpc_sec        *sec;
         ENTRY;
 
         ENTRY;
 
-        flavor = SEC_FLAVOR_RPC(flavor);
-
-        if (ctx) {
+        if (svc_ctx) {
                 LASSERT(imp->imp_dlm_fake == 1);
 
                 CDEBUG(D_SEC, "%s %s: reverse sec using flavor %s\n",
                        imp->imp_obd->obd_type->typ_name,
                        imp->imp_obd->obd_name,
                 LASSERT(imp->imp_dlm_fake == 1);
 
                 CDEBUG(D_SEC, "%s %s: reverse sec using flavor %s\n",
                        imp->imp_obd->obd_type->typ_name,
                        imp->imp_obd->obd_name,
-                       sptlrpc_flavor2name(flavor));
+                       sptlrpc_rpcflavor2name(sf->sf_rpc));
 
 
-                policy = sptlrpc_policy_get(ctx->sc_policy);
-                flags |= PTLRPC_SEC_FL_REVERSE | PTLRPC_SEC_FL_ROOTONLY;
+                policy = sptlrpc_policy_get(svc_ctx->sc_policy);
+                sf->sf_flags |= PTLRPC_SEC_FL_REVERSE | PTLRPC_SEC_FL_ROOTONLY;
         } else {
                 LASSERT(imp->imp_dlm_fake == 0);
 
                 CDEBUG(D_SEC, "%s %s: select security flavor %s\n",
                        imp->imp_obd->obd_type->typ_name,
                        imp->imp_obd->obd_name,
         } else {
                 LASSERT(imp->imp_dlm_fake == 0);
 
                 CDEBUG(D_SEC, "%s %s: select security flavor %s\n",
                        imp->imp_obd->obd_type->typ_name,
                        imp->imp_obd->obd_name,
-                       sptlrpc_flavor2name(flavor));
+                       sptlrpc_rpcflavor2name(sf->sf_rpc));
 
 
-                policy = sptlrpc_flavor2policy(flavor);
+                policy = sptlrpc_rpcflavor2policy(sf->sf_rpc);
                 if (!policy) {
                 if (!policy) {
-                        CERROR("invalid flavor 0x%x\n", flavor);
+                        CERROR("invalid flavor 0x%x\n", sf->sf_rpc);
                         RETURN(NULL);
                 }
         }
 
                         RETURN(NULL);
                 }
         }
 
-        sec = policy->sp_cops->create_sec(imp, ctx, flavor, flags);
+        sec = policy->sp_cops->create_sec(imp, svc_ctx, sf);
         if (sec) {
                 atomic_inc(&sec->ps_refcount);
 
         if (sec) {
                 atomic_inc(&sec->ps_refcount);
 
-                /* take 1 busy count on behalf of sec itself,
-                 * balanced in sptlrpc_set_put()
-                 */
-                atomic_inc(&sec->ps_busy);
+                sec->ps_part = sp;
 
                 if (sec->ps_gc_interval && policy->sp_cops->gc_ctx)
                         sptlrpc_gc_add_sec(sec);
 
                 if (sec->ps_gc_interval && policy->sp_cops->gc_ctx)
                         sptlrpc_gc_add_sec(sec);
-        } else
+        } else {
                 sptlrpc_policy_put(policy);
                 sptlrpc_policy_put(policy);
+        }
 
         RETURN(sec);
 }
 
 
         RETURN(sec);
 }
 
-int sptlrpc_import_get_sec(struct obd_import *imp,
-                           struct ptlrpc_svc_ctx *ctx,
-                           __u32 flavor,
-                           unsigned long flags)
+struct ptlrpc_sec *sptlrpc_import_sec_ref(struct obd_import *imp)
 {
 {
-        might_sleep();
+        struct ptlrpc_sec *sec;
 
 
-        /* old sec might be still there in reconnecting */
-        if (imp->imp_sec)
-                return 0;
+        spin_lock(&imp->imp_lock);
+        sec = sptlrpc_sec_get(imp->imp_sec);
+        spin_unlock(&imp->imp_lock);
 
 
-        imp->imp_sec = import_create_sec(imp, ctx, flavor, flags);
-        if (!imp->imp_sec)
-                return -EINVAL;
+        return sec;
+}
+EXPORT_SYMBOL(sptlrpc_import_sec_ref);
 
 
-        return 0;
+static void sptlrpc_import_sec_install(struct obd_import *imp,
+                                       struct ptlrpc_sec *sec)
+{
+        struct ptlrpc_sec *old_sec;
+
+        LASSERT(atomic_read(&sec->ps_refcount) > 0);
+
+        spin_lock(&imp->imp_lock);
+        old_sec = imp->imp_sec;
+        imp->imp_sec = sec;
+        spin_unlock(&imp->imp_lock);
+
+        if (old_sec) {
+                sptlrpc_sec_kill(old_sec);
+
+                /* balance the ref taken by this import */
+                sptlrpc_sec_put(old_sec);
+        }
+}
+
+static void sptlrpc_import_sec_adapt_inplace(struct obd_import *imp,
+                                             struct ptlrpc_sec *sec,
+                                             struct sptlrpc_flavor *sf)
+{
+        if (sf->sf_bulk_priv != sec->ps_flvr.sf_bulk_priv ||
+            sf->sf_bulk_csum != sec->ps_flvr.sf_bulk_csum) {
+                CWARN("imp %p (%s->%s): changing bulk flavor %s/%s -> %s/%s\n",
+                      imp, imp->imp_obd->obd_name,
+                      obd_uuid2str(&imp->imp_connection->c_remote_uuid),
+                      sptlrpc_bulk_priv_alg2name(sec->ps_flvr.sf_bulk_priv),
+                      sptlrpc_bulk_csum_alg2name(sec->ps_flvr.sf_bulk_csum),
+                      sptlrpc_bulk_priv_alg2name(sf->sf_bulk_priv),
+                      sptlrpc_bulk_csum_alg2name(sf->sf_bulk_csum));
+
+                spin_lock(&sec->ps_lock);
+                sec->ps_flvr.sf_bulk_priv = sf->sf_bulk_priv;
+                sec->ps_flvr.sf_bulk_csum = sf->sf_bulk_csum;
+                spin_unlock(&sec->ps_lock);
+        }
+
+        if (!equi(sf->sf_flags & PTLRPC_SEC_FL_UDESC,
+                  sec->ps_flvr.sf_flags & PTLRPC_SEC_FL_UDESC)) {
+                CWARN("imp %p (%s->%s): %s shipping user descriptor\n",
+                      imp, imp->imp_obd->obd_name,
+                      obd_uuid2str(&imp->imp_connection->c_remote_uuid),
+                      (sf->sf_flags & PTLRPC_SEC_FL_UDESC) ? "start" : "stop");
+
+                spin_lock(&sec->ps_lock);
+                sec->ps_flvr.sf_flags &= ~PTLRPC_SEC_FL_UDESC;
+                sec->ps_flvr.sf_flags |= sf->sf_flags & PTLRPC_SEC_FL_UDESC;
+                spin_unlock(&sec->ps_lock);
+        }
 }
 
 }
 
-void sptlrpc_import_put_sec(struct obd_import *imp)
+/*
+ * for normal import, @svc_ctx should be NULL and @rpc_flavor is ignored;
+ * for reverse import, @svc_ctx and @rpc_flavor is from incoming request.
+ */
+int sptlrpc_import_sec_adapt(struct obd_import *imp,
+                             struct ptlrpc_svc_ctx *svc_ctx,
+                             __u16 rpc_flavor)
 {
 {
-        struct ptlrpc_sec        *sec;
-        struct ptlrpc_sec_policy *policy;
+        struct ptlrpc_connection   *conn;
+        struct sptlrpc_flavor       sf;
+        struct ptlrpc_sec          *sec, *newsec;
+        enum lustre_sec_part        sp;
+        int                         rc;
 
 
-        might_sleep();
+        if (imp == NULL)
+                return 0;
 
 
-        if (imp->imp_sec == NULL)
-                return;
+        conn = imp->imp_connection;
 
 
-        sec = imp->imp_sec;
-        policy = sec->ps_policy;
+        if (svc_ctx == NULL) {
+                /* normal import, determine flavor from rule set */
+                sptlrpc_rule_set_choose(&imp->imp_obd->u.cli.cl_sptlrpc_rset,
+                                        LUSTRE_SP_ANY, conn->c_self, &sf);
 
 
-        if (atomic_dec_and_test(&sec->ps_refcount)) {
-                sec_cop_flush_ctx_cache(sec, -1, 1, 1);
-                sptlrpc_gc_del_sec(sec);
+                sp = imp->imp_obd->u.cli.cl_sec_part;
+        } else {
+                /* reverse import, determine flavor from incoming reqeust */
+                sf.sf_rpc = rpc_flavor;
+                sf.sf_bulk_priv = BULK_PRIV_ALG_NULL;
+                sf.sf_bulk_csum = BULK_CSUM_ALG_NULL;
+                sf.sf_flags = PTLRPC_SEC_FL_REVERSE | PTLRPC_SEC_FL_ROOTONLY;
 
 
-                if (atomic_dec_and_test(&sec->ps_busy))
-                        sec_cop_destroy_sec(sec);
-                else {
-                        CWARN("delay destroying busy sec %s %p\n",
-                              policy->sp_name, sec);
+                sp = sptlrpc_target_sec_part(imp->imp_obd);
+        }
+
+        sec = sptlrpc_import_sec_ref(imp);
+        if (sec) {
+                if (svc_ctx == NULL) {
+                        /* normal import, only check rpc flavor, if just bulk
+                         * flavor or flags changed, we can handle it on the fly
+                         * without switching sec. */
+                        if (sf.sf_rpc == sec->ps_flvr.sf_rpc) {
+                                sptlrpc_import_sec_adapt_inplace(imp, sec, &sf);
+
+                                rc = 0;
+                                goto out;
+                        }
+                } else {
+                        /* reverse import, do not compare bulk flavor */
+                        if (sf.sf_rpc == sec->ps_flvr.sf_rpc) {
+                                rc = 0;
+                                goto out;
+                        }
                 }
                 }
+
+                CWARN("%simport %p (%s%s%s): changing flavor "
+                      "(%s, %s/%s) -> (%s, %s/%s)\n",
+                      svc_ctx ? "reverse " : "",
+                      imp, imp->imp_obd->obd_name,
+                      svc_ctx == NULL ? "->" : "<-",
+                      obd_uuid2str(&conn->c_remote_uuid),
+                      sptlrpc_rpcflavor2name(sec->ps_flvr.sf_rpc),
+                      sptlrpc_bulk_csum_alg2name(sec->ps_flvr.sf_bulk_csum),
+                      sptlrpc_bulk_priv_alg2name(sec->ps_flvr.sf_bulk_priv),
+                      sptlrpc_rpcflavor2name(sf.sf_rpc),
+                      sptlrpc_bulk_csum_alg2name(sf.sf_bulk_csum),
+                      sptlrpc_bulk_priv_alg2name(sf.sf_bulk_priv));
         } else {
         } else {
-                sptlrpc_policy_put(policy);
+                CWARN("%simport %p (%s%s%s) netid %x: "
+                      "select initial flavor (%s, %s/%s)\n",
+                      svc_ctx == NULL ? "" : "reverse ",
+                      imp, imp->imp_obd->obd_name,
+                      svc_ctx == NULL ? "->" : "<-",
+                      obd_uuid2str(&conn->c_remote_uuid),
+                      LNET_NIDNET(conn->c_self),
+                      sptlrpc_rpcflavor2name(sf.sf_rpc),
+                      sptlrpc_bulk_csum_alg2name(sf.sf_bulk_csum),
+                      sptlrpc_bulk_priv_alg2name(sf.sf_bulk_priv));
+        }
+
+        mutex_down(&imp->imp_sec_mutex);
+
+        newsec = sptlrpc_sec_create(imp, svc_ctx, &sf, sp);
+        if (newsec) {
+                sptlrpc_import_sec_install(imp, newsec);
+                rc = 0;
+        } else {
+                CERROR("%simport %p (%s): failed to create new sec\n",
+                       svc_ctx == NULL ? "" : "reverse ",
+                       imp, obd_uuid2str(&conn->c_remote_uuid));
+                rc = -EPERM;
         }
 
         }
 
-        imp->imp_sec = NULL;
+        mutex_up(&imp->imp_sec_mutex);
+
+out:
+        sptlrpc_sec_put(sec);
+        return 0;
 }
 
 }
 
-void sptlrpc_import_flush_root_ctx(struct obd_import *imp)
+void sptlrpc_import_sec_put(struct obd_import *imp)
 {
 {
-        if (imp == NULL || imp->imp_sec == NULL)
+        if (imp->imp_sec) {
+                sptlrpc_sec_kill(imp->imp_sec);
+
+                sptlrpc_sec_put(imp->imp_sec);
+                imp->imp_sec = NULL;
+        }
+}
+
+static void import_flush_ctx_common(struct obd_import *imp,
+                                    uid_t uid, int grace, int force)
+{
+        struct ptlrpc_sec *sec;
+
+        if (imp == NULL)
+                return;
+
+        sec = sptlrpc_import_sec_ref(imp);
+        if (sec == NULL)
                 return;
 
                 return;
 
+        sec_cop_flush_ctx_cache(sec, uid, grace, force);
+        sptlrpc_sec_put(sec);
+}
+
+void sptlrpc_import_inval_all_ctx(struct obd_import *imp)
+{
+        /* use grace == 0 */
+        import_flush_ctx_common(imp, -1, 0, 1);
+}
+
+void sptlrpc_import_flush_root_ctx(struct obd_import *imp)
+{
         /* it's important to use grace mode, see explain in
         /* it's important to use grace mode, see explain in
-         * sptlrpc_req_refresh_ctx()
-         */
-        sec_cop_flush_ctx_cache(imp->imp_sec, 0, 1, 1);
+         * sptlrpc_req_refresh_ctx() */
+        import_flush_ctx_common(imp, 0, 1, 1);
 }
 
 void sptlrpc_import_flush_my_ctx(struct obd_import *imp)
 {
 }
 
 void sptlrpc_import_flush_my_ctx(struct obd_import *imp)
 {
-        if (imp == NULL || imp->imp_sec == NULL)
-                return;
-
-        sec_cop_flush_ctx_cache(imp->imp_sec, cfs_current()->uid, 1, 1);
+        import_flush_ctx_common(imp, cfs_current()->uid, 1, 1);
 }
 EXPORT_SYMBOL(sptlrpc_import_flush_my_ctx);
 
 void sptlrpc_import_flush_all_ctx(struct obd_import *imp)
 {
 }
 EXPORT_SYMBOL(sptlrpc_import_flush_my_ctx);
 
 void sptlrpc_import_flush_all_ctx(struct obd_import *imp)
 {
-        if (imp == NULL || imp->imp_sec == NULL)
-                return;
-
-        sec_cop_flush_ctx_cache(imp->imp_sec, -1, 1, 1);
+        import_flush_ctx_common(imp, -1, 1, 1);
 }
 EXPORT_SYMBOL(sptlrpc_import_flush_all_ctx);
 
 }
 EXPORT_SYMBOL(sptlrpc_import_flush_all_ctx);
 
@@ -994,7 +1319,9 @@ void sptlrpc_cli_free_reqbuf(struct ptlrpc_request *req)
         LASSERT(atomic_read(&ctx->cc_refcount));
         LASSERT(ctx->cc_sec);
         LASSERT(ctx->cc_sec->ps_policy);
         LASSERT(atomic_read(&ctx->cc_refcount));
         LASSERT(ctx->cc_sec);
         LASSERT(ctx->cc_sec->ps_policy);
-        LASSERT(req->rq_reqbuf || req->rq_clrbuf);
+
+        if (req->rq_reqbuf == NULL && req->rq_clrbuf == NULL)
+                return;
 
         policy = ctx->cc_sec->ps_policy;
         policy->sp_cops->free_reqbuf(ctx->cc_sec, req);
 
         policy = ctx->cc_sec->ps_policy;
         policy->sp_cops->free_reqbuf(ctx->cc_sec, req);
@@ -1101,7 +1428,10 @@ void sptlrpc_cli_free_repbuf(struct ptlrpc_request *req)
         LASSERT(atomic_read(&ctx->cc_refcount));
         LASSERT(ctx->cc_sec);
         LASSERT(ctx->cc_sec->ps_policy);
         LASSERT(atomic_read(&ctx->cc_refcount));
         LASSERT(ctx->cc_sec);
         LASSERT(ctx->cc_sec->ps_policy);
-        LASSERT(req->rq_repbuf);
+
+        if (req->rq_repbuf == NULL)
+                return;
+        LASSERT(req->rq_repbuf_len);
 
         policy = ctx->cc_sec->ps_policy;
         policy->sp_cops->free_repbuf(ctx->cc_sec, req);
 
         policy = ctx->cc_sec->ps_policy;
         policy->sp_cops->free_repbuf(ctx->cc_sec, req);
@@ -1132,19 +1462,259 @@ int sptlrpc_svc_install_rvs_ctx(struct obd_import *imp,
  * server side security                 *
  ****************************************/
 
  * server side security                 *
  ****************************************/
 
+static int flavor_allowed(struct sptlrpc_flavor *exp,
+                          struct ptlrpc_request *req)
+{
+        struct sptlrpc_flavor *flvr = &req->rq_flvr;
+
+        if (exp->sf_rpc == flvr->sf_rpc)
+                return 1;
+
+        if ((req->rq_ctx_init || req->rq_ctx_fini) &&
+            RPC_FLVR_POLICY(exp->sf_rpc) == RPC_FLVR_POLICY(flvr->sf_rpc) &&
+            RPC_FLVR_MECH(exp->sf_rpc) == RPC_FLVR_MECH(flvr->sf_rpc))
+                return 1;
+
+        return 0;
+}
+
+#define EXP_FLVR_UPDATE_EXPIRE      (OBD_TIMEOUT_DEFAULT + 10)
+
 int sptlrpc_target_export_check(struct obd_export *exp,
                                 struct ptlrpc_request *req)
 {
 int sptlrpc_target_export_check(struct obd_export *exp,
                                 struct ptlrpc_request *req)
 {
-        if (!req->rq_auth_gss ||
-            (!req->rq_auth_usr_root && !req->rq_auth_usr_mdt))
+        struct sptlrpc_flavor   flavor;
+
+        if (exp == NULL)
                 return 0;
 
                 return 0;
 
-        if (!req->rq_ctx_init)
+        /* client side export has no imp_reverse, skip
+         * FIXME maybe we should check flavor this as well??? */
+        if (exp->exp_imp_reverse == NULL)
                 return 0;
 
                 return 0;
 
-        LASSERT(exp->exp_imp_reverse);
-        sptlrpc_svc_install_rvs_ctx(exp->exp_imp_reverse, req->rq_svc_ctx);
-        return 0;
+        /* don't care about ctx fini rpc */
+        if (req->rq_ctx_fini)
+                return 0;
+
+        spin_lock(&exp->exp_lock);
+
+        /* if flavor just changed (exp->exp_flvr_changed != 0), we wait for
+         * the first req with the new flavor, then treat it as current flavor,
+         * adapt reverse sec according to it.
+         * note the first rpc with new flavor might not be with root ctx, in
+         * which case delay the sec_adapt by leaving exp_flvr_adapt == 1. */
+        if (unlikely(exp->exp_flvr_changed) &&
+            flavor_allowed(&exp->exp_flvr_old[1], req)) {
+                /* make the new flavor as "current", and old ones as
+                 * about-to-expire */
+                CDEBUG(D_SEC, "exp %p: just changed: %x->%x\n", exp,
+                       exp->exp_flvr.sf_rpc, exp->exp_flvr_old[1].sf_rpc);
+                flavor = exp->exp_flvr_old[1];
+                exp->exp_flvr_old[1] = exp->exp_flvr_old[0];
+                exp->exp_flvr_expire[1] = exp->exp_flvr_expire[0];
+                exp->exp_flvr_old[0] = exp->exp_flvr;
+                exp->exp_flvr_expire[0] = cfs_time_current_sec() +
+                                          EXP_FLVR_UPDATE_EXPIRE;
+                exp->exp_flvr = flavor;
+
+                /* flavor change finished */
+                exp->exp_flvr_changed = 0;
+                LASSERT(exp->exp_flvr_adapt == 1);
+
+                /* if it's gss, we only interested in root ctx init */
+                if (req->rq_auth_gss &&
+                    !(req->rq_ctx_init && (req->rq_auth_usr_root ||
+                                           req->rq_auth_usr_mdt))) {
+                        spin_unlock(&exp->exp_lock);
+                        CDEBUG(D_SEC, "is good but not root(%d:%d:%d:%d)\n",
+                               req->rq_auth_gss, req->rq_ctx_init,
+                               req->rq_auth_usr_root, req->rq_auth_usr_mdt);
+                        return 0;
+                }
+
+                exp->exp_flvr_adapt = 0;
+                spin_unlock(&exp->exp_lock);
+
+                return sptlrpc_import_sec_adapt(exp->exp_imp_reverse,
+                                                req->rq_svc_ctx, flavor.sf_rpc);
+        }
+
+        /* if it equals to the current flavor, we accept it, but need to
+         * dealing with reverse sec/ctx */
+        if (likely(flavor_allowed(&exp->exp_flvr, req))) {
+                /* most cases should return here, we only interested in
+                 * gss root ctx init */
+                if (!req->rq_auth_gss || !req->rq_ctx_init ||
+                    (!req->rq_auth_usr_root && !req->rq_auth_usr_mdt)) {
+                        spin_unlock(&exp->exp_lock);
+                        return 0;
+                }
+
+                if (exp->exp_flvr_adapt) {
+                        exp->exp_flvr_adapt = 0;
+                        CDEBUG(D_SEC, "exp %p (%x|%x|%x): do delayed adapt\n",
+                               exp, exp->exp_flvr.sf_rpc,
+                               exp->exp_flvr_old[0].sf_rpc,
+                               exp->exp_flvr_old[1].sf_rpc);
+                        flavor = exp->exp_flvr;
+                        spin_unlock(&exp->exp_lock);
+
+                        return sptlrpc_import_sec_adapt(exp->exp_imp_reverse,
+                                                        req->rq_svc_ctx,
+                                                        flavor.sf_rpc);
+                } else {
+                        CDEBUG(D_SEC, "exp %p (%x|%x|%x): is current flavor, "
+                               "install rvs ctx\n", exp, exp->exp_flvr.sf_rpc,
+                               exp->exp_flvr_old[0].sf_rpc,
+                               exp->exp_flvr_old[1].sf_rpc);
+                        spin_unlock(&exp->exp_lock);
+
+                        return sptlrpc_svc_install_rvs_ctx(exp->exp_imp_reverse,
+                                                           req->rq_svc_ctx);
+                }
+        }
+
+        if (exp->exp_flvr_expire[0]) {
+                if (exp->exp_flvr_expire[0] >= cfs_time_current_sec()) {
+                        if (flavor_allowed(&exp->exp_flvr_old[0], req)) {
+                                CDEBUG(D_SEC, "exp %p (%x|%x|%x): match the "
+                                       "middle one (%lu)\n", exp,
+                                       exp->exp_flvr.sf_rpc,
+                                       exp->exp_flvr_old[0].sf_rpc,
+                                       exp->exp_flvr_old[1].sf_rpc,
+                                       exp->exp_flvr_expire[0] -
+                                                cfs_time_current_sec());
+                                spin_unlock(&exp->exp_lock);
+                                return 0;
+                        }
+                } else {
+                        CDEBUG(D_SEC, "mark middle expired\n");
+                        exp->exp_flvr_expire[0] = 0;
+                }
+                CDEBUG(D_SEC, "exp %p (%x|%x|%x): %x not match middle\n", exp,
+                       exp->exp_flvr.sf_rpc,
+                       exp->exp_flvr_old[0].sf_rpc, exp->exp_flvr_old[1].sf_rpc,
+                       req->rq_flvr.sf_rpc);
+        }
+
+        /* now it doesn't match the current flavor, the only chance we can
+         * accept it is match the old flavors which is not expired. */
+        if (exp->exp_flvr_changed == 0 && exp->exp_flvr_expire[1]) {
+                if (exp->exp_flvr_expire[1] >= cfs_time_current_sec()) {
+                        if (flavor_allowed(&exp->exp_flvr_old[1], req)) {
+                                CDEBUG(D_SEC, "exp %p (%x|%x|%x): match the "
+                                       "oldest one (%lu)\n", exp,
+                                       exp->exp_flvr.sf_rpc,
+                                       exp->exp_flvr_old[0].sf_rpc,
+                                       exp->exp_flvr_old[1].sf_rpc,
+                                       exp->exp_flvr_expire[1] -
+                                                cfs_time_current_sec());
+                                spin_unlock(&exp->exp_lock);
+                                return 0;
+                        }
+                } else {
+                        CDEBUG(D_SEC, "mark oldest expired\n");
+                        exp->exp_flvr_expire[1] = 0;
+                }
+                CDEBUG(D_SEC, "exp %p (%x|%x|%x): %x not match found\n",
+                       exp, exp->exp_flvr.sf_rpc,
+                       exp->exp_flvr_old[0].sf_rpc, exp->exp_flvr_old[1].sf_rpc,
+                       req->rq_flvr.sf_rpc);
+        } else {
+                CDEBUG(D_SEC, "exp %p (%x|%x|%x): skip the last one\n",
+                       exp, exp->exp_flvr.sf_rpc, exp->exp_flvr_old[0].sf_rpc,
+                       exp->exp_flvr_old[1].sf_rpc);
+        }
+
+        spin_unlock(&exp->exp_lock);
+
+        CWARN("req %p: (%u|%u|%u|%u|%u) with unauthorized flavor %x\n",
+              req, req->rq_auth_gss, req->rq_ctx_init, req->rq_ctx_fini,
+              req->rq_auth_usr_root, req->rq_auth_usr_mdt, req->rq_flvr.sf_rpc);
+        return -EACCES;
+}
+
+void sptlrpc_target_update_exp_flavor(struct obd_device *obd,
+                                      struct sptlrpc_rule_set *rset)
+{
+        struct obd_export       *exp;
+        struct sptlrpc_flavor    new_flvr;
+
+        LASSERT(obd);
+
+        spin_lock(&obd->obd_dev_lock);
+
+        list_for_each_entry(exp, &obd->obd_exports, exp_obd_chain) {
+                if (exp->exp_connection == NULL)
+                        continue;
+
+                /* note if this export had just been updated flavor
+                 * (exp_flvr_changed == 1), this will override the
+                 * previous one. */
+                spin_lock(&exp->exp_lock);
+                sptlrpc_rule_set_choose(rset, exp->exp_sp_peer,
+                                        exp->exp_connection->c_peer.nid,
+                                        &new_flvr);
+                if (exp->exp_flvr_changed ||
+                    memcmp(&new_flvr, &exp->exp_flvr, sizeof(new_flvr))) {
+                        exp->exp_flvr_old[1] = new_flvr;
+                        exp->exp_flvr_expire[1] = 0;
+                        exp->exp_flvr_changed = 1;
+                        exp->exp_flvr_adapt = 1;
+                        CDEBUG(D_SEC, "exp %p (%s): updated flavor %x->%x\n",
+                               exp, sptlrpc_part2name(exp->exp_sp_peer),
+                               exp->exp_flvr.sf_rpc,
+                               exp->exp_flvr_old[1].sf_rpc);
+                }
+                spin_unlock(&exp->exp_lock);
+        }
+
+        spin_unlock(&obd->obd_dev_lock);
+}
+EXPORT_SYMBOL(sptlrpc_target_update_exp_flavor);
+
+static int sptlrpc_svc_check_from(struct ptlrpc_request *req, int svc_rc)
+{
+        if (svc_rc == SECSVC_DROP)
+                return SECSVC_DROP;
+
+        switch (req->rq_sp_from) {
+        case LUSTRE_SP_CLI:
+        case LUSTRE_SP_MDT:
+        case LUSTRE_SP_OST:
+        case LUSTRE_SP_MGS:
+        case LUSTRE_SP_ANY:
+                break;
+        default:
+                DEBUG_REQ(D_ERROR, req, "invalid source %u", req->rq_sp_from);
+                return SECSVC_DROP;
+        }
+
+        if (!req->rq_auth_gss)
+                return svc_rc;
+
+        if (unlikely(req->rq_sp_from == LUSTRE_SP_ANY)) {
+                CERROR("not specific part\n");
+                return SECSVC_DROP;
+        }
+
+        /* from MDT, must be authenticated as MDT */
+        if (unlikely(req->rq_sp_from == LUSTRE_SP_MDT &&
+                     !req->rq_auth_usr_mdt)) {
+                DEBUG_REQ(D_ERROR, req, "fake source MDT");
+                return SECSVC_DROP;
+        }
+
+        /* from OST, must be callback to MDT and CLI, the reverse sec
+         * was from mdt/root keytab, so it should be MDT or root FIXME */
+        if (unlikely(req->rq_sp_from == LUSTRE_SP_OST &&
+                     !req->rq_auth_usr_mdt && !req->rq_auth_usr_root)) {
+                DEBUG_REQ(D_ERROR, req, "fake source OST");
+                return SECSVC_DROP;
+        }
+
+        return svc_rc;
 }
 
 int sptlrpc_svc_unwrap_request(struct ptlrpc_request *req)
 }
 
 int sptlrpc_svc_unwrap_request(struct ptlrpc_request *req)
@@ -1158,10 +1728,10 @@ int sptlrpc_svc_unwrap_request(struct ptlrpc_request *req)
         LASSERT(req->rq_reqmsg == NULL);
         LASSERT(req->rq_repmsg == NULL);
 
         LASSERT(req->rq_reqmsg == NULL);
         LASSERT(req->rq_repmsg == NULL);
 
-        /* 
-         * in any case we avoid to call unpack_msg() for request of null flavor
-         * which will later be done by ptlrpc_server_handle_request().
-         */
+        req->rq_sp_from = LUSTRE_SP_ANY;
+        req->rq_auth_uid = INVALID_UID;
+        req->rq_auth_mapped_uid = INVALID_UID;
+
         if (req->rq_reqdata_len < sizeof(struct lustre_msg)) {
                 CERROR("request size %d too small\n", req->rq_reqdata_len);
                 RETURN(SECSVC_DROP);
         if (req->rq_reqdata_len < sizeof(struct lustre_msg)) {
                 CERROR("request size %d too small\n", req->rq_reqdata_len);
                 RETURN(SECSVC_DROP);
@@ -1169,22 +1739,30 @@ int sptlrpc_svc_unwrap_request(struct ptlrpc_request *req)
 
         if (msg->lm_magic == LUSTRE_MSG_MAGIC_V1 ||
             msg->lm_magic == LUSTRE_MSG_MAGIC_V1_SWABBED) {
 
         if (msg->lm_magic == LUSTRE_MSG_MAGIC_V1 ||
             msg->lm_magic == LUSTRE_MSG_MAGIC_V1_SWABBED) {
-                req->rq_sec_flavor = SPTLRPC_FLVR_NULL;
+                /*
+                 * v1 message, treat as to be null
+                 */
+                req->rq_flvr.sf_rpc = SPTLRPC_FLVR_NULL;
         } else {
         } else {
-                req->rq_sec_flavor = msg->lm_secflvr;
-
-                if (msg->lm_magic == LUSTRE_MSG_MAGIC_V2_SWABBED)
-                        __swab32s(&req->rq_sec_flavor);
-
-                if ((SEC_FLAVOR_POLICY(req->rq_sec_flavor) !=
+                /*
+                 * v2 message.
+                 */
+                if (msg->lm_magic == LUSTRE_MSG_MAGIC_V2)
+                        req->rq_flvr.sf_rpc = WIRE_FLVR_RPC(msg->lm_secflvr);
+                else
+                        req->rq_flvr.sf_rpc = WIRE_FLVR_RPC(
+                                                __swab32(msg->lm_secflvr));
+
+                /* unpack the wrapper message if the policy is not null */
+                if ((RPC_FLVR_POLICY(req->rq_flvr.sf_rpc) !=
                      SPTLRPC_POLICY_NULL) &&
                     lustre_unpack_msg(msg, req->rq_reqdata_len))
                         RETURN(SECSVC_DROP);
         }
 
                      SPTLRPC_POLICY_NULL) &&
                     lustre_unpack_msg(msg, req->rq_reqdata_len))
                         RETURN(SECSVC_DROP);
         }
 
-        policy = sptlrpc_flavor2policy(req->rq_sec_flavor);
+        policy = sptlrpc_rpcflavor2policy(req->rq_flvr.sf_rpc);
         if (!policy) {
         if (!policy) {
-                CERROR("unsupported security flavor %x\n", req->rq_sec_flavor);
+                CERROR("unsupported rpc flavor %x\n", req->rq_flvr.sf_rpc);
                 RETURN(SECSVC_DROP);
         }
 
                 RETURN(SECSVC_DROP);
         }
 
@@ -1194,6 +1772,9 @@ int sptlrpc_svc_unwrap_request(struct ptlrpc_request *req)
         LASSERT(req->rq_reqmsg || rc != SECSVC_OK);
         sptlrpc_policy_put(policy);
 
         LASSERT(req->rq_reqmsg || rc != SECSVC_OK);
         sptlrpc_policy_put(policy);
 
+        /* sanity check for the request source */
+        rc = sptlrpc_svc_check_from(req, rc);
+
         /* FIXME move to proper place */
         if (rc == SECSVC_OK) {
                 __u32 opc = lustre_msg_get_opc(req->rq_reqmsg);
         /* FIXME move to proper place */
         if (rc == SECSVC_OK) {
                 __u32 opc = lustre_msg_get_opc(req->rq_reqmsg);
@@ -1329,7 +1910,7 @@ int sptlrpc_cli_wrap_bulk(struct ptlrpc_request *req,
 {
         struct ptlrpc_cli_ctx *ctx;
 
 {
         struct ptlrpc_cli_ctx *ctx;
 
-        if (!SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor))
+        if (!req->rq_pack_bulk)
                 return 0;
 
         LASSERT(req->rq_bulk_read || req->rq_bulk_write);
                 return 0;
 
         LASSERT(req->rq_bulk_read || req->rq_bulk_write);
@@ -1376,7 +1957,7 @@ int sptlrpc_cli_unwrap_bulk_read(struct ptlrpc_request *req,
         struct ptlrpc_cli_ctx *ctx;
         int rc = 0;
 
         struct ptlrpc_cli_ctx *ctx;
         int rc = 0;
 
-        if (!SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor))
+        if (!req->rq_pack_bulk)
                 return 0;
 
         LASSERT(req->rq_bulk_read && !req->rq_bulk_write);
                 return 0;
 
         LASSERT(req->rq_bulk_read && !req->rq_bulk_write);
@@ -1404,7 +1985,7 @@ int sptlrpc_cli_unwrap_bulk_write(struct ptlrpc_request *req,
 {
         struct ptlrpc_cli_ctx *ctx;
 
 {
         struct ptlrpc_cli_ctx *ctx;
 
-        if (!SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor))
+        if (!req->rq_pack_bulk)
                 return 0;
 
         LASSERT(!req->rq_bulk_read && req->rq_bulk_write);
                 return 0;
 
         LASSERT(!req->rq_bulk_read && req->rq_bulk_write);
@@ -1422,7 +2003,7 @@ int sptlrpc_svc_wrap_bulk(struct ptlrpc_request *req,
 {
         struct ptlrpc_svc_ctx *ctx;
 
 {
         struct ptlrpc_svc_ctx *ctx;
 
-        if (!SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor))
+        if (!req->rq_pack_bulk)
                 return 0;
 
         LASSERT(req->rq_bulk_read || req->rq_bulk_write);
                 return 0;
 
         LASSERT(req->rq_bulk_read || req->rq_bulk_write);
@@ -1440,7 +2021,7 @@ int sptlrpc_svc_unwrap_bulk(struct ptlrpc_request *req,
 {
         struct ptlrpc_svc_ctx *ctx;
 
 {
         struct ptlrpc_svc_ctx *ctx;
 
-        if (!SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor))
+        if (!req->rq_pack_bulk)
                 return 0;
 
         LASSERT(req->rq_bulk_read || req->rq_bulk_write);
                 return 0;
 
         LASSERT(req->rq_bulk_read || req->rq_bulk_write);
@@ -1540,225 +2121,6 @@ int sptlrpc_unpack_user_desc(struct lustre_msg *msg, int offset)
 EXPORT_SYMBOL(sptlrpc_unpack_user_desc);
 
 /****************************************
 EXPORT_SYMBOL(sptlrpc_unpack_user_desc);
 
 /****************************************
- * user supplied flavor string parsing  *
- ****************************************/
-
-static
-int get_default_flavor(enum lustre_part to_part, struct sec_flavor_config *conf)
-{
-        conf->sfc_bulk_priv = BULK_PRIV_ALG_NULL;
-        conf->sfc_bulk_csum = BULK_CSUM_ALG_NULL;
-        conf->sfc_flags = 0;
-
-        switch (to_part) {
-        case LUSTRE_MDT:
-                conf->sfc_rpc_flavor = SPTLRPC_FLVR_PLAIN;
-                return 0;
-        case LUSTRE_OST:
-                conf->sfc_rpc_flavor = SPTLRPC_FLVR_NULL;
-                return 0;
-        default:
-                CERROR("Unknown to lustre part %d, apply defaults\n", to_part);
-                conf->sfc_rpc_flavor = SPTLRPC_FLVR_NULL;
-                return -EINVAL;
-        }
-}
-
-static
-void get_flavor_by_rpc(__u32 rpc_flavor, struct sec_flavor_config *conf)
-{
-        conf->sfc_rpc_flavor = rpc_flavor;
-        conf->sfc_bulk_priv = BULK_PRIV_ALG_NULL;
-        conf->sfc_bulk_csum = BULK_CSUM_ALG_NULL;
-        conf->sfc_flags = 0;
-
-        switch (rpc_flavor) {
-        case SPTLRPC_FLVR_NULL:
-        case SPTLRPC_FLVR_PLAIN:
-        case SPTLRPC_FLVR_KRB5N:
-        case SPTLRPC_FLVR_KRB5A:
-                break;
-        case SPTLRPC_FLVR_KRB5P:
-                conf->sfc_bulk_priv = BULK_PRIV_ALG_ARC4;
-                /* fall through */
-        case SPTLRPC_FLVR_KRB5I:
-                conf->sfc_bulk_csum = BULK_CSUM_ALG_SHA1;
-                break;
-        default:
-                LBUG();
-        }
-}
-
-static
-void get_flavor_by_rpc_bulk(__u32 rpc_flavor, int bulk_priv,
-                            struct sec_flavor_config *conf)
-{
-        if (bulk_priv)
-                conf->sfc_bulk_priv = BULK_PRIV_ALG_ARC4;
-        else
-                conf->sfc_bulk_priv = BULK_PRIV_ALG_NULL;
-
-        switch (rpc_flavor) {
-        case SPTLRPC_FLVR_PLAIN:
-                conf->sfc_bulk_csum = BULK_CSUM_ALG_MD5;
-                break;
-        case SPTLRPC_FLVR_KRB5N:
-        case SPTLRPC_FLVR_KRB5A:
-        case SPTLRPC_FLVR_KRB5I:
-        case SPTLRPC_FLVR_KRB5P:
-                conf->sfc_bulk_csum = BULK_CSUM_ALG_SHA1;
-                break;
-        default:
-                LBUG();
-        }
-}
-
-static __u32 __flavors[] = {
-        SPTLRPC_FLVR_NULL,
-        SPTLRPC_FLVR_PLAIN,
-        SPTLRPC_FLVR_KRB5N,
-        SPTLRPC_FLVR_KRB5A,
-        SPTLRPC_FLVR_KRB5I,
-        SPTLRPC_FLVR_KRB5P,
-};
-
-#define __nflavors      (sizeof(__flavors)/sizeof(__u32))
-
-/*
- * flavor string format: rpc[-bulk{n|i|p}[:cksum/enc]]
- * for examples:
- *  null
- *  plain-bulki
- *  krb5p-bulkn
- *  krb5i-bulkp
- *  krb5i-bulkp:sha512/arc4
- */
-int sptlrpc_parse_flavor(enum lustre_part from_part, enum lustre_part to_part,
-                         char *str, struct sec_flavor_config *conf)
-{
-        char   *f, *bulk, *alg, *enc;
-        char    buf[64];
-        int     i, bulk_priv;
-        ENTRY;
-
-        if (str == NULL) {
-                if (get_default_flavor(to_part, conf))
-                        return -EINVAL;
-                goto set_flags;
-        }
-
-        for (i = 0; i < __nflavors; i++) {
-                f = sptlrpc_flavor2name(__flavors[i]);
-                if (strncmp(str, f, strlen(f)) == 0)
-                        break;
-        }
-
-        if (i >= __nflavors)
-                GOTO(invalid, -EINVAL);
-
-        /* prepare local buffer thus we can modify it as we want */
-        strncpy(buf, str, 64);
-        buf[64 - 1] = '\0';
-
-        /* find bulk string */
-        bulk = strchr(buf, '-');
-        if (bulk)
-                *bulk++ = '\0';
-
-        /* now the first part must equal to rpc flavor name */
-        if (strcmp(buf, f) != 0)
-                GOTO(invalid, -EINVAL);
-
-        get_flavor_by_rpc(__flavors[i], conf);
-
-        if (bulk == NULL)
-                goto set_flags;
-
-        /* null flavor should not have any suffix */
-        if (__flavors[i] == SPTLRPC_FLVR_NULL)
-                GOTO(invalid, -EINVAL);
-
-        /* find bulk algorithm string */
-        alg = strchr(bulk, ':');
-        if (alg)
-                *alg++ = '\0';
-
-        /* verify bulk section */
-        if (strcmp(bulk, "bulkn") == 0) {
-                conf->sfc_bulk_csum = BULK_CSUM_ALG_NULL;
-                conf->sfc_bulk_priv = BULK_PRIV_ALG_NULL;
-                goto set_flags;
-        }
-
-        if (strcmp(bulk, "bulki") == 0)
-                bulk_priv = 0;
-        else if (strcmp(bulk, "bulkp") == 0)
-                bulk_priv = 1;
-        else
-                GOTO(invalid, -EINVAL);
-
-        /* plain policy dosen't support bulk encryption */
-        if (bulk_priv && __flavors[i] == SPTLRPC_FLVR_PLAIN)
-                GOTO(invalid, -EINVAL);
-
-        get_flavor_by_rpc_bulk(__flavors[i], bulk_priv, conf);
-
-        if (alg == NULL)
-                goto set_flags;
-
-        /* find encryption algorithm string */
-        enc = strchr(alg, '/');
-        if (enc)
-                *enc++ = '\0';
-
-        /* bulk combination sanity check */
-        if ((bulk_priv && enc == NULL) || (bulk_priv == 0 && enc))
-                GOTO(invalid, -EINVAL);
-
-        /* checksum algorithm */
-        for (i = 0; i < BULK_CSUM_ALG_MAX; i++) {
-                if (strcmp(alg, sptlrpc_bulk_csum_alg2name(i)) == 0) {
-                        conf->sfc_bulk_csum = i;
-                        break;
-                }
-        }
-        if (i >= BULK_CSUM_ALG_MAX)
-                GOTO(invalid, -EINVAL);
-
-        /* privacy algorithm */
-        if (enc) {
-                if (strcmp(enc, "arc4") != 0)
-                        GOTO(invalid, -EINVAL);
-                conf->sfc_bulk_priv = BULK_PRIV_ALG_ARC4;
-        }
-
-set_flags:
-        /* * set ROOTONLY flag:
-         *   - to OST
-         *   - from MDT to MDT
-         * * set BULK flag for:
-         *   - from CLI to OST
-         */
-        if (to_part == LUSTRE_OST ||
-            (from_part == LUSTRE_MDT && to_part == LUSTRE_MDT))
-                conf->sfc_flags |= PTLRPC_SEC_FL_ROOTONLY;
-        if (from_part == LUSTRE_CLI && to_part == LUSTRE_OST)
-                conf->sfc_flags |= PTLRPC_SEC_FL_BULK;
-
-#ifdef __BIG_ENDIAN
-        __swab32s(&conf->sfc_rpc_flavor);
-        __swab32s(&conf->sfc_bulk_csum);
-        __swab32s(&conf->sfc_bulk_priv);
-        __swab32s(&conf->sfc_flags);
-#endif
-        return 0;
-invalid:
-        CERROR("invalid flavor string: %s\n", str);
-        return -EINVAL;
-}
-EXPORT_SYMBOL(sptlrpc_parse_flavor);
-
-/****************************************
  * misc helpers                         *
  ****************************************/
 
  * misc helpers                         *
  ****************************************/
 
index 6620bd0..5740220 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  * vim:expandtab:shiftwidth=8:tabstop=8:
  *
 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  * vim:expandtab:shiftwidth=8:tabstop=8:
  *
- * Copyright (C) 2006 Cluster File Systems, Inc.
+ * Copyright (C) 2006-2007 Cluster File Systems, Inc.
  *   Author: Eric Mei <ericm@clusterfs.com>
  *
  *   This file is part of Lustre, http://www.lustre.org.
  *   Author: Eric Mei <ericm@clusterfs.com>
  *
  *   This file is part of Lustre, http://www.lustre.org.
 #define PTRS_PER_PAGE   (CFS_PAGE_SIZE / sizeof(void *))
 #define PAGES_PER_POOL  (PTRS_PER_PAGE)
 
 #define PTRS_PER_PAGE   (CFS_PAGE_SIZE / sizeof(void *))
 #define PAGES_PER_POOL  (PTRS_PER_PAGE)
 
+#define IDLE_IDX_MAX            (100)
+#define IDLE_IDX_WEIGHT         (3)
+
+#define CACHE_QUIESCENCE_PERIOD (20)
+
 static struct ptlrpc_enc_page_pool {
         /*
          * constants
          */
         unsigned long    epp_max_pages;   /* maximum pages can hold, const */
         unsigned int     epp_max_pools;   /* number of pools, const */
 static struct ptlrpc_enc_page_pool {
         /*
          * constants
          */
         unsigned long    epp_max_pages;   /* maximum pages can hold, const */
         unsigned int     epp_max_pools;   /* number of pools, const */
-        /*
-         * users of the pools. the capacity grow as more user added,
-         * but doesn't shrink when users gone -- just current policy.
-         * during failover there might be user add/remove activities.
-         */
-        atomic_t         epp_users;       /* shared by how many users (osc) */
-        atomic_t         epp_users_gone;  /* users removed */
+
         /*
          * wait queue in case of not enough free pages.
          */
         cfs_waitq_t      epp_waitq;       /* waiting threads */
         unsigned int     epp_waitqlen;    /* wait queue length */
         unsigned long    epp_pages_short; /* # of pages wanted of in-q users */
         /*
          * wait queue in case of not enough free pages.
          */
         cfs_waitq_t      epp_waitq;       /* waiting threads */
         unsigned int     epp_waitqlen;    /* wait queue length */
         unsigned long    epp_pages_short; /* # of pages wanted of in-q users */
-        unsigned long    epp_adding:1,    /* during adding pages */
-                         epp_full:1;      /* pools are all full */
+        unsigned int     epp_growing:1;   /* during adding pages */
+
+        /*
+         * indicating how idle the pools are, from 0 to MAX_IDLE_IDX
+         * this is counted based on each time when getting pages from
+         * the pools, not based on time. which means in case that system
+         * is idled for a while but the idle_idx might still be low if no
+         * activities happened in the pools.
+         */
+        unsigned long    epp_idle_idx;
+
+        /* last shrink time due to mem tight */
+        long             epp_last_shrink;
+        long             epp_last_access;
+
         /*
          * in-pool pages bookkeeping
          */
         spinlock_t       epp_lock;        /* protect following fields */
         unsigned long    epp_total_pages; /* total pages in pools */
         unsigned long    epp_free_pages;  /* current pages available */
         /*
          * in-pool pages bookkeeping
          */
         spinlock_t       epp_lock;        /* protect following fields */
         unsigned long    epp_total_pages; /* total pages in pools */
         unsigned long    epp_free_pages;  /* current pages available */
+
         /*
          * statistics
          */
         /*
          * statistics
          */
-        unsigned int     epp_st_adds;
-        unsigned int     epp_st_failadds; /* # of add pages failures */
-        unsigned long    epp_st_reqs;     /* # of get_pages requests */
-        unsigned long    epp_st_missings; /* # of cache missing */
-        unsigned long    epp_st_lowfree;  /* lowest free pages ever reached */
-        unsigned long    epp_st_max_wqlen;/* highest waitqueue length ever */
-        cfs_time_t       epp_st_max_wait; /* in jeffies */
+        unsigned int     epp_st_grows;          /* # of grows */
+        unsigned int     epp_st_grow_fails;     /* # of add pages failures */
+        unsigned int     epp_st_shrinks;        /* # of shrinks */
+        unsigned long    epp_st_access;         /* # of access */
+        unsigned long    epp_st_missings;       /* # of cache missing */
+        unsigned long    epp_st_lowfree;        /* lowest free pages reached */
+        unsigned long    epp_st_max_wqlen;      /* highest waitqueue length */
+        cfs_time_t       epp_st_max_wait;       /* in jeffies */
         /*
          * pointers to pools
          */
         cfs_page_t    ***epp_pools;
 } page_pools;
 
         /*
          * pointers to pools
          */
         cfs_page_t    ***epp_pools;
 } page_pools;
 
+/*
+ * memory shrinker
+ */
+const int pools_shrinker_seeks = DEFAULT_SEEKS;
+static struct shrinker *pools_shrinker = NULL;
+
+
+/*
+ * /proc/fs/lustre/sptlrpc/encrypt_page_pools
+ */
 int sptlrpc_proc_read_enc_pool(char *page, char **start, off_t off, int count,
                                int *eof, void *data)
 {
 int sptlrpc_proc_read_enc_pool(char *page, char **start, off_t off, int count,
                                int *eof, void *data)
 {
@@ -107,42 +131,118 @@ int sptlrpc_proc_read_enc_pool(char *page, char **start, off_t off, int count,
                       "pages per pool:          %lu\n"
                       "max pages:               %lu\n"
                       "max pools:               %u\n"
                       "pages per pool:          %lu\n"
                       "max pages:               %lu\n"
                       "max pools:               %u\n"
-                      "users:                   %d - %d\n"
-                      "current waitqueue len:   %u\n"
-                      "current pages in short:  %lu\n"
                       "total pages:             %lu\n"
                       "total free:              %lu\n"
                       "total pages:             %lu\n"
                       "total free:              %lu\n"
-                      "add page times:          %u\n"
-                      "add page failed times:   %u\n"
-                      "total requests:          %lu\n"
+                      "idle index:              %lu/100\n"
+                      "last shrink:             %lds\n"
+                      "last access:             %lds\n"
+                      "grows:                   %u\n"
+                      "grows failure:           %u\n"
+                      "shrinks:                 %u\n"
+                      "cache access:            %lu\n"
                       "cache missing:           %lu\n"
                       "cache missing:           %lu\n"
-                      "lowest free pages:       %lu\n"
+                      "low free mark:           %lu\n"
                       "max waitqueue depth:     %lu\n"
                       "max waitqueue depth:     %lu\n"
-                      "max wait time:           "CFS_TIME_T"\n"
+                      "max wait time:           "CFS_TIME_T"/%u\n"
                       ,
                       num_physpages,
                       PAGES_PER_POOL,
                       page_pools.epp_max_pages,
                       page_pools.epp_max_pools,
                       ,
                       num_physpages,
                       PAGES_PER_POOL,
                       page_pools.epp_max_pages,
                       page_pools.epp_max_pools,
-                      atomic_read(&page_pools.epp_users),
-                      atomic_read(&page_pools.epp_users_gone),
-                      page_pools.epp_waitqlen,
-                      page_pools.epp_pages_short,
                       page_pools.epp_total_pages,
                       page_pools.epp_free_pages,
                       page_pools.epp_total_pages,
                       page_pools.epp_free_pages,
-                      page_pools.epp_st_adds,
-                      page_pools.epp_st_failadds,
-                      page_pools.epp_st_reqs,
+                      page_pools.epp_idle_idx,
+                      cfs_time_current_sec() - page_pools.epp_last_shrink,
+                      cfs_time_current_sec() - page_pools.epp_last_access,
+                      page_pools.epp_st_grows,
+                      page_pools.epp_st_grow_fails,
+                      page_pools.epp_st_shrinks,
+                      page_pools.epp_st_access,
                       page_pools.epp_st_missings,
                       page_pools.epp_st_lowfree,
                       page_pools.epp_st_max_wqlen,
                       page_pools.epp_st_missings,
                       page_pools.epp_st_lowfree,
                       page_pools.epp_st_max_wqlen,
-                      page_pools.epp_st_max_wait
+                      page_pools.epp_st_max_wait, HZ
                      );
 
         spin_unlock(&page_pools.epp_lock);
         return rc;
 }
 
                      );
 
         spin_unlock(&page_pools.epp_lock);
         return rc;
 }
 
+static void enc_pools_release_free_pages(long npages)
+{
+        int     p_idx, g_idx;
+
+        LASSERT(npages <= page_pools.epp_free_pages);
+
+        p_idx = (page_pools.epp_free_pages - 1) / PAGES_PER_POOL;
+        g_idx = (page_pools.epp_free_pages - 1) % PAGES_PER_POOL;
+        LASSERT(page_pools.epp_pools[p_idx]);
+
+        page_pools.epp_free_pages -= npages;
+        page_pools.epp_total_pages -= npages;
+
+        while (npages-- > 0) {
+                LASSERT(page_pools.epp_pools[p_idx][g_idx] != NULL);
+
+                cfs_free_page(page_pools.epp_pools[p_idx][g_idx]);
+                page_pools.epp_pools[p_idx][g_idx] = NULL;
+
+                if (g_idx-- == 0) {
+                        p_idx--;
+                        g_idx = PAGES_PER_POOL - 1;
+
+                        LASSERT(page_pools.epp_pools[p_idx]);
+                }
+        }
+}
+
+/*
+ * could be called frequently for query (@nr_to_scan == 0)
+ */
+static int enc_pools_shrink(int nr_to_scan, unsigned int gfp_mask)
+{
+        unsigned long   ret;
+
+        spin_lock(&page_pools.epp_lock);
+
+        if (nr_to_scan) {
+                if (nr_to_scan > page_pools.epp_free_pages)
+                        nr_to_scan = page_pools.epp_free_pages;
+
+                enc_pools_release_free_pages(nr_to_scan);
+                CDEBUG(D_SEC, "released %d pages, %ld left\n",
+                       nr_to_scan, page_pools.epp_free_pages);
+
+                page_pools.epp_st_shrinks++;
+                page_pools.epp_last_shrink = cfs_time_current_sec();
+        }
+
+        /*
+         * try to keep at least PTLRPC_MAX_BRW_PAGES pages in the pool
+         */
+        if (page_pools.epp_free_pages <= PTLRPC_MAX_BRW_PAGES) {
+                ret = 0;
+                goto out_unlock;
+        }
+
+        /*
+         * if no pool access for a long time, we consider it's fully idle
+         */
+        if (cfs_time_current_sec() - page_pools.epp_last_access >
+            CACHE_QUIESCENCE_PERIOD)
+                page_pools.epp_idle_idx = IDLE_IDX_MAX;
+
+        LASSERT(page_pools.epp_idle_idx <= IDLE_IDX_MAX);
+        ret = (page_pools.epp_free_pages * page_pools.epp_idle_idx /
+               IDLE_IDX_MAX);
+        if (page_pools.epp_free_pages - ret < PTLRPC_MAX_BRW_PAGES)
+                ret = page_pools.epp_free_pages - PTLRPC_MAX_BRW_PAGES;
+
+out_unlock:
+        spin_unlock(&page_pools.epp_lock);
+        return ret;
+}
+
 static inline
 int npages_to_npools(unsigned long npages)
 {
 static inline
 int npages_to_npools(unsigned long npages)
 {
@@ -152,7 +252,7 @@ int npages_to_npools(unsigned long npages)
 /*
  * return how many pages cleaned up.
  */
 /*
  * return how many pages cleaned up.
  */
-static unsigned long enc_cleanup_pools(cfs_page_t ***pools, int npools)
+static unsigned long enc_pools_cleanup(cfs_page_t ***pools, int npools)
 {
         unsigned long cleaned = 0;
         int           i, j;
 {
         unsigned long cleaned = 0;
         int           i, j;
@@ -180,7 +280,7 @@ static unsigned long enc_cleanup_pools(cfs_page_t ***pools, int npools)
  * we have options to avoid most memory copy with some tricks. but we choose
  * the simplest way to avoid complexity. It's not frequently called.
  */
  * we have options to avoid most memory copy with some tricks. but we choose
  * the simplest way to avoid complexity. It's not frequently called.
  */
-static void enc_insert_pool(cfs_page_t ***pools, int npools, int npages)
+static void enc_pools_insert(cfs_page_t ***pools, int npools, int npages)
 {
         int     freeslot;
         int     op_idx, np_idx, og_idx, ng_idx;
 {
         int     freeslot;
         int     op_idx, np_idx, og_idx, ng_idx;
@@ -251,9 +351,6 @@ static void enc_insert_pool(cfs_page_t ***pools, int npools, int npages)
         page_pools.epp_free_pages += npages;
         page_pools.epp_st_lowfree = page_pools.epp_free_pages;
 
         page_pools.epp_free_pages += npages;
         page_pools.epp_st_lowfree = page_pools.epp_free_pages;
 
-        if (page_pools.epp_total_pages == page_pools.epp_max_pages)
-                page_pools.epp_full = 1;
-
         CDEBUG(D_SEC, "add %d pages to total %lu\n", npages,
                page_pools.epp_total_pages);
 
         CDEBUG(D_SEC, "add %d pages to total %lu\n", npages,
                page_pools.epp_total_pages);
 
@@ -267,16 +364,16 @@ static int enc_pools_add_pages(int npages)
         int             npools, alloced = 0;
         int             i, j, rc = -ENOMEM;
 
         int             npools, alloced = 0;
         int             i, j, rc = -ENOMEM;
 
+        if (npages < PTLRPC_MAX_BRW_PAGES)
+                npages = PTLRPC_MAX_BRW_PAGES;
+
         down(&sem_add_pages);
 
         down(&sem_add_pages);
 
-        if (npages > page_pools.epp_max_pages - page_pools.epp_total_pages)
+        if (npages + page_pools.epp_total_pages > page_pools.epp_max_pages)
                 npages = page_pools.epp_max_pages - page_pools.epp_total_pages;
                 npages = page_pools.epp_max_pages - page_pools.epp_total_pages;
-        if (npages == 0) {
-                rc = 0;
-                goto out;
-        }
+        LASSERT(npages > 0);
 
 
-        page_pools.epp_st_adds++;
+        page_pools.epp_st_grows++;
 
         npools = npages_to_npools(npages);
         OBD_ALLOC(pools, npools * sizeof(*pools));
 
         npools = npages_to_npools(npages);
         OBD_ALLOC(pools, npools * sizeof(*pools));
@@ -298,64 +395,59 @@ static int enc_pools_add_pages(int npages)
                 }
         }
 
                 }
         }
 
-        enc_insert_pool(pools, npools, npages);
-        CDEBUG(D_SEC, "add %d pages into enc page pools\n", npages);
+        enc_pools_insert(pools, npools, npages);
+        CDEBUG(D_SEC, "added %d pages into pools\n", npages);
         rc = 0;
 
 out_pools:
         rc = 0;
 
 out_pools:
-        enc_cleanup_pools(pools, npools);
+        enc_pools_cleanup(pools, npools);
         OBD_FREE(pools, npools * sizeof(*pools));
 out:
         if (rc) {
         OBD_FREE(pools, npools * sizeof(*pools));
 out:
         if (rc) {
-                page_pools.epp_st_failadds++;
-                CERROR("Failed to pre-allocate %d enc pages\n", npages);
+                page_pools.epp_st_grow_fails++;
+                CERROR("Failed to allocate %d enc pages\n", npages);
         }
 
         up(&sem_add_pages);
         return rc;
 }
 
         }
 
         up(&sem_add_pages);
         return rc;
 }
 
-/*
- * both "max bulk rpcs inflight" and "lnet MTU" are tunable, we use the
- * default fixed value initially.
- */
-int sptlrpc_enc_pool_add_user(void)
+static inline void enc_pools_wakeup(void)
 {
 {
-        int page_plus = PTLRPC_MAX_BRW_PAGES * OSC_MAX_RIF_DEFAULT;
-        int users, users_gone, shift, rc;
+        if (unlikely(page_pools.epp_waitqlen)) {
+                LASSERT(page_pools.epp_waitqlen > 0);
+                LASSERT(cfs_waitq_active(&page_pools.epp_waitq));
+                cfs_waitq_broadcast(&page_pools.epp_waitq);
+        }
+}
 
 
-        LASSERT(!in_interrupt());
-        LASSERT(atomic_read(&page_pools.epp_users) >= 0);
+static int enc_pools_should_grow(int page_needed, long now)
+{
+        /* don't grow if someone else is growing the pools right now,
+         * or the pools has reached its full capacity
+         */
+        if (page_pools.epp_growing ||
+            page_pools.epp_total_pages == page_pools.epp_max_pages)
+                return 0;
 
 
-        users_gone = atomic_dec_return(&page_pools.epp_users_gone);
-        if (users_gone >= 0) {
-                CWARN("%d users gone, skip\n", users_gone + 1);
+        /* if total pages is not enough, we need to grow */
+        if (page_pools.epp_total_pages < page_needed)
+                return 1;
+
+        /* if we just did a shrink due to memory tight, we'd better
+         * wait a while to grow again.
+         */
+        if (now - page_pools.epp_last_shrink < 2)
                 return 0;
                 return 0;
-        }
-        atomic_inc(&page_pools.epp_users_gone);
 
         /*
 
         /*
-         * prepare full pages for first 2 users; 1/2 for next 2 users;
-         * 1/4 for next 4 users; 1/8 for next 8 users; 1/16 for next 16 users;
-         * ...
+         * here we perhaps need consider other factors like wait queue
+         * length, idle index, etc. ?
          */
          */
-        users = atomic_add_return(1, &page_pools.epp_users);
-        shift = fls(users - 1);
-        shift = shift > 1 ? shift - 1 : 0;
-        page_plus = page_plus >> shift;
-        page_plus = page_plus > 2 ? page_plus : 2;
 
 
-        rc = enc_pools_add_pages(page_plus);
-        return 0;
-}
-EXPORT_SYMBOL(sptlrpc_enc_pool_add_user);
-
-int sptlrpc_enc_pool_del_user(void)
-{
-        atomic_inc(&page_pools.epp_users_gone);
-        return 0;
+        /* grow the pools in any other cases */
+        return 1;
 }
 }
-EXPORT_SYMBOL(sptlrpc_enc_pool_del_user);
 
 /*
  * we allocate the requested pages atomically.
 
 /*
  * we allocate the requested pages atomically.
@@ -363,12 +455,14 @@ EXPORT_SYMBOL(sptlrpc_enc_pool_del_user);
 int sptlrpc_enc_pool_get_pages(struct ptlrpc_bulk_desc *desc)
 {
         cfs_waitlink_t  waitlink;
 int sptlrpc_enc_pool_get_pages(struct ptlrpc_bulk_desc *desc)
 {
         cfs_waitlink_t  waitlink;
-        cfs_time_t      tick1 = 0, tick2;
+        unsigned long   this_idle = -1;
+        cfs_time_t      tick = 0;
+        long            now;
         int             p_idx, g_idx;
         int             i;
 
         LASSERT(desc->bd_max_iov > 0);
         int             p_idx, g_idx;
         int             i;
 
         LASSERT(desc->bd_max_iov > 0);
-        LASSERT(desc->bd_max_iov <= page_pools.epp_total_pages);
+        LASSERT(desc->bd_max_iov <= page_pools.epp_max_pages);
 
         /* resent bulk, enc pages might have been allocated previously */
         if (desc->bd_enc_pages != NULL)
 
         /* resent bulk, enc pages might have been allocated previously */
         if (desc->bd_enc_pages != NULL)
@@ -380,57 +474,56 @@ int sptlrpc_enc_pool_get_pages(struct ptlrpc_bulk_desc *desc)
                 return -ENOMEM;
 
         spin_lock(&page_pools.epp_lock);
                 return -ENOMEM;
 
         spin_lock(&page_pools.epp_lock);
-again:
-        page_pools.epp_st_reqs++;
 
 
+        page_pools.epp_st_access++;
+again:
         if (unlikely(page_pools.epp_free_pages < desc->bd_max_iov)) {
         if (unlikely(page_pools.epp_free_pages < desc->bd_max_iov)) {
-                if (tick1 == 0)
-                        tick1 = cfs_time_current();
+                if (tick == 0)
+                        tick = cfs_time_current();
+
+                now = cfs_time_current_sec();
 
                 page_pools.epp_st_missings++;
                 page_pools.epp_pages_short += desc->bd_max_iov;
 
 
                 page_pools.epp_st_missings++;
                 page_pools.epp_pages_short += desc->bd_max_iov;
 
-                if (++page_pools.epp_waitqlen > page_pools.epp_st_max_wqlen)
-                        page_pools.epp_st_max_wqlen = page_pools.epp_waitqlen;
-
-                /* we just wait if someone else is adding more pages, or
-                 * wait queue length is not deep enough. otherwise try to
-                 * add more pages in the pools.
-                 *
-                 * FIXME the policy of detecting resource tight & growing pool
-                 * need to be reconsidered. */
-                if (page_pools.epp_adding || page_pools.epp_waitqlen < 2 ||
-                    page_pools.epp_full) {
-                        set_current_state(TASK_UNINTERRUPTIBLE);
-                        cfs_waitlink_init(&waitlink);
-                        cfs_waitq_add(&page_pools.epp_waitq, &waitlink);
+                if (enc_pools_should_grow(desc->bd_max_iov, now)) {
+                        page_pools.epp_growing = 1;
 
                         spin_unlock(&page_pools.epp_lock);
 
                         spin_unlock(&page_pools.epp_lock);
-                        cfs_schedule();
+                        enc_pools_add_pages(page_pools.epp_pages_short / 2);
                         spin_lock(&page_pools.epp_lock);
                         spin_lock(&page_pools.epp_lock);
+
+                        page_pools.epp_growing = 0;
                 } else {
                 } else {
-                        page_pools.epp_adding = 1;
+                        if (++page_pools.epp_waitqlen >
+                            page_pools.epp_st_max_wqlen)
+                                page_pools.epp_st_max_wqlen =
+                                                page_pools.epp_waitqlen;
+
+                        set_current_state(TASK_UNINTERRUPTIBLE);
+                        cfs_waitlink_init(&waitlink);
+                        cfs_waitq_add(&page_pools.epp_waitq, &waitlink);
 
                         spin_unlock(&page_pools.epp_lock);
 
                         spin_unlock(&page_pools.epp_lock);
-                        enc_pools_add_pages(page_pools.epp_pages_short / 2);
+                        cfs_schedule();
                         spin_lock(&page_pools.epp_lock);
 
                         spin_lock(&page_pools.epp_lock);
 
-                        page_pools.epp_adding = 0;
+                        LASSERT(page_pools.epp_waitqlen > 0);
+                        page_pools.epp_waitqlen--;
                 }
 
                 LASSERT(page_pools.epp_pages_short >= desc->bd_max_iov);
                 }
 
                 LASSERT(page_pools.epp_pages_short >= desc->bd_max_iov);
-                LASSERT(page_pools.epp_waitqlen > 0);
                 page_pools.epp_pages_short -= desc->bd_max_iov;
                 page_pools.epp_pages_short -= desc->bd_max_iov;
-                page_pools.epp_waitqlen--;
 
 
+                this_idle = 0;
                 goto again;
         }
 
         /* record max wait time */
                 goto again;
         }
 
         /* record max wait time */
-        if (unlikely(tick1 != 0)) {
-                tick2 = cfs_time_current();
-                if (tick2 - tick1 > page_pools.epp_st_max_wait)
-                        page_pools.epp_st_max_wait = tick2 - tick1;
+        if (unlikely(tick != 0)) {
+                tick = cfs_time_current() - tick;
+                if (tick > page_pools.epp_st_max_wait)
+                        page_pools.epp_st_max_wait = tick;
         }
 
         /* proceed with rest of allocation */
         }
 
         /* proceed with rest of allocation */
@@ -453,6 +546,19 @@ again:
         if (page_pools.epp_free_pages < page_pools.epp_st_lowfree)
                 page_pools.epp_st_lowfree = page_pools.epp_free_pages;
 
         if (page_pools.epp_free_pages < page_pools.epp_st_lowfree)
                 page_pools.epp_st_lowfree = page_pools.epp_free_pages;
 
+        /*
+         * new idle index = (old * weight + new) / (weight + 1)
+         */
+        if (this_idle == -1) {
+                this_idle = page_pools.epp_free_pages * IDLE_IDX_MAX /
+                            page_pools.epp_total_pages;
+        }
+        page_pools.epp_idle_idx = (page_pools.epp_idle_idx * IDLE_IDX_WEIGHT +
+                                   this_idle) /
+                                  (IDLE_IDX_WEIGHT + 1);
+
+        page_pools.epp_last_access = cfs_time_current_sec();
+
         spin_unlock(&page_pools.epp_lock);
         return 0;
 }
         spin_unlock(&page_pools.epp_lock);
         return 0;
 }
@@ -492,11 +598,7 @@ void sptlrpc_enc_pool_put_pages(struct ptlrpc_bulk_desc *desc)
 
         page_pools.epp_free_pages += desc->bd_max_iov;
 
 
         page_pools.epp_free_pages += desc->bd_max_iov;
 
-        if (unlikely(page_pools.epp_waitqlen)) {
-                LASSERT(page_pools.epp_waitqlen > 0);
-                LASSERT(cfs_waitq_active(&page_pools.epp_waitq));
-                cfs_waitq_broadcast(&page_pools.epp_waitq);
-        }
+        enc_pools_wakeup();
 
         spin_unlock(&page_pools.epp_lock);
 
 
         spin_unlock(&page_pools.epp_lock);
 
@@ -506,39 +608,103 @@ void sptlrpc_enc_pool_put_pages(struct ptlrpc_bulk_desc *desc)
 }
 EXPORT_SYMBOL(sptlrpc_enc_pool_put_pages);
 
 }
 EXPORT_SYMBOL(sptlrpc_enc_pool_put_pages);
 
+/*
+ * we don't do much stuff for add_user/del_user anymore, except adding some
+ * initial pages in add_user() if current pools are empty, rest would be
+ * handled by the pools's self-adaption.
+ */
+int sptlrpc_enc_pool_add_user(void)
+{
+        int     need_grow = 0;
+
+        spin_lock(&page_pools.epp_lock);
+        if (page_pools.epp_growing == 0 && page_pools.epp_total_pages == 0) {
+                page_pools.epp_growing = 1;
+                need_grow = 1;
+        }
+        spin_unlock(&page_pools.epp_lock);
+
+        if (need_grow) {
+                enc_pools_add_pages(PTLRPC_MAX_BRW_PAGES);
+
+                spin_lock(&page_pools.epp_lock);
+                page_pools.epp_growing = 0;
+                enc_pools_wakeup();
+                spin_unlock(&page_pools.epp_lock);
+        }
+        return 0;
+}
+EXPORT_SYMBOL(sptlrpc_enc_pool_add_user);
+
+int sptlrpc_enc_pool_del_user(void)
+{
+        return 0;
+}
+EXPORT_SYMBOL(sptlrpc_enc_pool_del_user);
+
+static inline void enc_pools_alloc(void)
+{
+        LASSERT(page_pools.epp_max_pools);
+        /*
+         * on system with huge memory but small page size, this might lead to
+         * high-order allocation. but it's not common, and we suppose memory
+         * be not too much fragmented at module loading time.
+         */
+        OBD_ALLOC(page_pools.epp_pools,
+                  page_pools.epp_max_pools * sizeof(*page_pools.epp_pools));
+}
+
+static inline void enc_pools_free(void)
+{
+        LASSERT(page_pools.epp_max_pools);
+        LASSERT(page_pools.epp_pools);
+
+        OBD_FREE(page_pools.epp_pools,
+                 page_pools.epp_max_pools * sizeof(*page_pools.epp_pools));
+}
+
 int sptlrpc_enc_pool_init(void)
 {
 int sptlrpc_enc_pool_init(void)
 {
-        /* constants */
-        page_pools.epp_max_pages = num_physpages / 4;
+        /*
+         * maximum capacity is 1/8 of total physical memory.
+         * is the 1/8 a good number?
+         */
+        page_pools.epp_max_pages = num_physpages / 8;
         page_pools.epp_max_pools = npages_to_npools(page_pools.epp_max_pages);
 
         page_pools.epp_max_pools = npages_to_npools(page_pools.epp_max_pages);
 
-        atomic_set(&page_pools.epp_users, 0);
-        atomic_set(&page_pools.epp_users_gone, 0);
-
         cfs_waitq_init(&page_pools.epp_waitq);
         page_pools.epp_waitqlen = 0;
         page_pools.epp_pages_short = 0;
 
         cfs_waitq_init(&page_pools.epp_waitq);
         page_pools.epp_waitqlen = 0;
         page_pools.epp_pages_short = 0;
 
-        page_pools.epp_adding = 0;
-        page_pools.epp_full = 0;
+        page_pools.epp_growing = 0;
+
+        page_pools.epp_idle_idx = 0;
+        page_pools.epp_last_shrink = cfs_time_current_sec();
+        page_pools.epp_last_access = cfs_time_current_sec();
 
         spin_lock_init(&page_pools.epp_lock);
         page_pools.epp_total_pages = 0;
         page_pools.epp_free_pages = 0;
 
 
         spin_lock_init(&page_pools.epp_lock);
         page_pools.epp_total_pages = 0;
         page_pools.epp_free_pages = 0;
 
-        page_pools.epp_st_adds = 0;
-        page_pools.epp_st_failadds = 0;
-        page_pools.epp_st_reqs = 0;
+        page_pools.epp_st_grows = 0;
+        page_pools.epp_st_grow_fails = 0;
+        page_pools.epp_st_shrinks = 0;
+        page_pools.epp_st_access = 0;
         page_pools.epp_st_missings = 0;
         page_pools.epp_st_lowfree = 0;
         page_pools.epp_st_max_wqlen = 0;
         page_pools.epp_st_max_wait = 0;
 
         page_pools.epp_st_missings = 0;
         page_pools.epp_st_lowfree = 0;
         page_pools.epp_st_max_wqlen = 0;
         page_pools.epp_st_max_wait = 0;
 
-        OBD_ALLOC(page_pools.epp_pools,
-                  page_pools.epp_max_pools * sizeof(*page_pools.epp_pools));
+        enc_pools_alloc();
         if (page_pools.epp_pools == NULL)
                 return -ENOMEM;
 
         if (page_pools.epp_pools == NULL)
                 return -ENOMEM;
 
+        pools_shrinker = set_shrinker(pools_shrinker_seeks, enc_pools_shrink);
+        if (pools_shrinker == NULL) {
+                enc_pools_free();
+                return -ENOMEM;
+        }
+
         return 0;
 }
 
         return 0;
 }
 
@@ -546,15 +712,17 @@ void sptlrpc_enc_pool_fini(void)
 {
         unsigned long cleaned, npools;
 
 {
         unsigned long cleaned, npools;
 
+        LASSERT(pools_shrinker);
         LASSERT(page_pools.epp_pools);
         LASSERT(page_pools.epp_total_pages == page_pools.epp_free_pages);
 
         LASSERT(page_pools.epp_pools);
         LASSERT(page_pools.epp_total_pages == page_pools.epp_free_pages);
 
+        remove_shrinker(pools_shrinker);
+
         npools = npages_to_npools(page_pools.epp_total_pages);
         npools = npages_to_npools(page_pools.epp_total_pages);
-        cleaned = enc_cleanup_pools(page_pools.epp_pools, npools);
+        cleaned = enc_pools_cleanup(page_pools.epp_pools, npools);
         LASSERT(cleaned == page_pools.epp_total_pages);
 
         LASSERT(cleaned == page_pools.epp_total_pages);
 
-        OBD_FREE(page_pools.epp_pools,
-                 page_pools.epp_max_pools * sizeof(*page_pools.epp_pools));
+        enc_pools_free();
 }
 
 #else /* !__KERNEL__ */
 }
 
 #else /* !__KERNEL__ */
@@ -596,15 +764,15 @@ static struct {
         [BULK_CSUM_ALG_SHA512]  = { "sha512",  64 },
 };
 
         [BULK_CSUM_ALG_SHA512]  = { "sha512",  64 },
 };
 
-const char * sptlrpc_bulk_csum_alg2name(__u32 csum_alg)
+const char * sptlrpc_bulk_csum_alg2name(__u8 csum_alg)
 {
         if (csum_alg < BULK_CSUM_ALG_MAX)
                 return csum_types[csum_alg].name;
 {
         if (csum_alg < BULK_CSUM_ALG_MAX)
                 return csum_types[csum_alg].name;
-        return "unknown_cksum";
+        return "unknown";
 }
 EXPORT_SYMBOL(sptlrpc_bulk_csum_alg2name);
 
 }
 EXPORT_SYMBOL(sptlrpc_bulk_csum_alg2name);
 
-int bulk_sec_desc_size(__u32 csum_alg, int request, int read)
+int bulk_sec_desc_size(__u8 csum_alg, int request, int read)
 {
         int size = sizeof(struct ptlrpc_bulk_sec_desc);
 
 {
         int size = sizeof(struct ptlrpc_bulk_sec_desc);
 
@@ -631,9 +799,7 @@ int bulk_sec_desc_unpack(struct lustre_msg *msg, int offset)
 
         if (lustre_msg_swabbed(msg)) {
                 __swab32s(&bsd->bsd_version);
 
         if (lustre_msg_swabbed(msg)) {
                 __swab32s(&bsd->bsd_version);
-                __swab32s(&bsd->bsd_pad);
-                __swab32s(&bsd->bsd_csum_alg);
-                __swab32s(&bsd->bsd_priv_alg);
+                __swab16s(&bsd->bsd_pad);
         }
 
         if (bsd->bsd_version != 0) {
         }
 
         if (bsd->bsd_version != 0) {
@@ -852,14 +1018,19 @@ int bulk_csum_cli_request(struct ptlrpc_bulk_desc *desc, int read,
         LASSERT(rsize >= sizeof(*bsdr));
         LASSERT(alg < BULK_CSUM_ALG_MAX);
 
         LASSERT(rsize >= sizeof(*bsdr));
         LASSERT(alg < BULK_CSUM_ALG_MAX);
 
-        if (read)
+        if (read) {
                 bsdr->bsd_csum_alg = alg;
                 bsdr->bsd_csum_alg = alg;
-        else {
+        else {
                 rc = generate_bulk_csum(desc, alg, bsdr, rsize);
                 rc = generate_bulk_csum(desc, alg, bsdr, rsize);
-                if (rc) {
-                        CERROR("client bulk write: failed to perform "
+                if (rc)
+                        CERROR("bulk write: client failed to compute "
                                "checksum: %d\n", rc);
                                "checksum: %d\n", rc);
-                }
+
+                /* For sending we only compute the wrong checksum instead
+                 * of corrupting the data so it is still correct on a redo */
+                if (rc == 0 && OBD_FAIL_CHECK(OBD_FAIL_OSC_CHECKSUM_SEND) &&
+                    bsdr->bsd_csum_alg != BULK_CSUM_ALG_NULL)
+                        bsdr->bsd_csum[0] ^= 0x1;
         }
 
         return rc;
         }
 
         return rc;
@@ -919,7 +1090,7 @@ int bulk_csum_cli_reply(struct ptlrpc_bulk_desc *desc, int read,
                 if (!memcmp(cli, srv, csum_size)) {
                         /* checksum confirmed */
                         CDEBUG(D_SEC, "bulk write checksum (%s) confirmed\n",
                 if (!memcmp(cli, srv, csum_size)) {
                         /* checksum confirmed */
                         CDEBUG(D_SEC, "bulk write checksum (%s) confirmed\n",
-                              csum_types[bsdr->bsd_csum_alg].name);
+                               csum_types[bsdr->bsd_csum_alg].name);
                         return 0;
                 }
 
                         return 0;
                 }
 
@@ -953,6 +1124,29 @@ int bulk_csum_cli_reply(struct ptlrpc_bulk_desc *desc, int read,
 }
 EXPORT_SYMBOL(bulk_csum_cli_reply);
 
 }
 EXPORT_SYMBOL(bulk_csum_cli_reply);
 
+#ifdef __KERNEL__
+static void corrupt_bulk_data(struct ptlrpc_bulk_desc *desc)
+{
+        char           *ptr;
+        unsigned int    off, i;
+
+        for (i = 0; i < desc->bd_iov_count; i++) {
+                if (desc->bd_iov[i].kiov_len == 0)
+                        continue;
+
+                ptr = cfs_kmap(desc->bd_iov[i].kiov_page);
+                off = desc->bd_iov[i].kiov_offset & ~CFS_PAGE_MASK;
+                ptr[off] ^= 0x1;
+                cfs_kunmap(desc->bd_iov[i].kiov_page);
+                return;
+        }
+}
+#else
+static void corrupt_bulk_data(struct ptlrpc_bulk_desc *desc)
+{
+}
+#endif /* __KERNEL__ */
+
 int bulk_csum_svc(struct ptlrpc_bulk_desc *desc, int read,
                   struct ptlrpc_bulk_sec_desc *bsdv, int vsize,
                   struct ptlrpc_bulk_sec_desc *bsdr, int rsize)
 int bulk_csum_svc(struct ptlrpc_bulk_desc *desc, int read,
                   struct ptlrpc_bulk_sec_desc *bsdv, int vsize,
                   struct ptlrpc_bulk_sec_desc *bsdr, int rsize)
@@ -969,8 +1163,14 @@ int bulk_csum_svc(struct ptlrpc_bulk_desc *desc, int read,
                         CERROR("bulk read: server failed to generate %s "
                                "checksum: %d\n",
                                csum_types[bsdv->bsd_csum_alg].name, rc);
                         CERROR("bulk read: server failed to generate %s "
                                "checksum: %d\n",
                                csum_types[bsdv->bsd_csum_alg].name, rc);
-        } else
+
+                /* corrupt the data after we compute the checksum, to
+                 * simulate an OST->client data error */
+                if (rc == 0 && OBD_FAIL_CHECK(OBD_FAIL_OSC_CHECKSUM_RECEIVE))
+                        corrupt_bulk_data(desc);
+        } else {
                 rc = verify_bulk_csum(desc, 0, bsdv, vsize, bsdr, rsize);
                 rc = verify_bulk_csum(desc, 0, bsdv, vsize, bsdr, rsize);
+        }
 
         return rc;
 }
 
         return rc;
 }
@@ -992,15 +1192,15 @@ static struct {
         [BULK_PRIV_ALG_ARC4]   = { "arc4", 0   },
 };
 
         [BULK_PRIV_ALG_ARC4]   = { "arc4", 0   },
 };
 
-const char * sptlrpc_bulk_priv_alg2name(__u32 priv_alg)
+const char * sptlrpc_bulk_priv_alg2name(__u8 priv_alg)
 {
         if (priv_alg < BULK_PRIV_ALG_MAX)
                 return priv_types[priv_alg].name;
 {
         if (priv_alg < BULK_PRIV_ALG_MAX)
                 return priv_types[priv_alg].name;
-        return "unknown_priv";
+        return "unknown";
 }
 EXPORT_SYMBOL(sptlrpc_bulk_priv_alg2name);
 
 }
 EXPORT_SYMBOL(sptlrpc_bulk_priv_alg2name);
 
-__u32 sptlrpc_bulk_priv_alg2flags(__u32 priv_alg)
+__u32 sptlrpc_bulk_priv_alg2flags(__u8 priv_alg)
 {
         if (priv_alg < BULK_PRIV_ALG_MAX)
                 return priv_types[priv_alg].flags;
 {
         if (priv_alg < BULK_PRIV_ALG_MAX)
                 return priv_types[priv_alg].flags;
diff --git a/lustre/ptlrpc/sec_config.c b/lustre/ptlrpc/sec_config.c
new file mode 100644 (file)
index 0000000..3534ba2
--- /dev/null
@@ -0,0 +1,796 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * Copyright (C) 2007 Cluster File Systems, Inc.
+ *
+ *   This file is part of Lustre, http://www.lustre.org.
+ *
+ *   Lustre is free software; you can redistribute it and/or
+ *   modify it under the terms of version 2 of the GNU General Public
+ *   License as published by the Free Software Foundation.
+ *
+ *   Lustre is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Lustre; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef EXPORT_SYMTAB
+#define EXPORT_SYMTAB
+#endif
+#define DEBUG_SUBSYSTEM S_SEC
+
+#include <libcfs/libcfs.h>
+#ifndef __KERNEL__
+#include <liblustre.h>
+#include <libcfs/list.h>
+#else
+#include <linux/crypto.h>
+#include <linux/key.h>
+#endif
+
+#include <obd.h>
+#include <obd_class.h>
+#include <obd_support.h>
+#include <lustre_net.h>
+#include <lustre_import.h>
+#include <lustre_dlm.h>
+#include <lustre_sec.h>
+
+#include "ptlrpc_internal.h"
+
+const char *sptlrpc_part2name(enum lustre_sec_part part)
+{
+        switch (part) {
+        case LUSTRE_SP_CLI:
+                return "cli";
+        case LUSTRE_SP_MDT:
+                return "mdt";
+        case LUSTRE_SP_OST:
+                return "ost";
+        case LUSTRE_SP_MGS:
+                return "mgs";
+        case LUSTRE_SP_ANY:
+                return "any";
+        default:
+                return "err";
+        }
+}
+EXPORT_SYMBOL(sptlrpc_part2name);
+
+enum lustre_sec_part sptlrpc_target_sec_part(struct obd_device *obd)
+{
+        const char *type = obd->obd_type->typ_name;
+
+        if (!strcmp(type, LUSTRE_MDT_NAME))
+                return LUSTRE_SP_MDT;
+        if (!strcmp(type, LUSTRE_OST_NAME))
+                return LUSTRE_SP_OST;
+        if (!strcmp(type, LUSTRE_MGS_NAME))
+                return LUSTRE_SP_MGS;
+
+        CERROR("unknown target %p(%s)\n", obd, type);
+        return LUSTRE_SP_ANY;
+}
+EXPORT_SYMBOL(sptlrpc_target_sec_part);
+
+/****************************************
+ * user supplied flavor string parsing  *
+ ****************************************/
+
+typedef enum {
+        BULK_TYPE_N = 0,
+        BULK_TYPE_I = 1,
+        BULK_TYPE_P = 2
+} bulk_type_t;
+
+static void get_default_flavor(struct sptlrpc_flavor *sf)
+{
+        sf->sf_rpc = SPTLRPC_FLVR_NULL;
+        sf->sf_bulk_priv = BULK_PRIV_ALG_NULL;
+        sf->sf_bulk_csum = BULK_CSUM_ALG_NULL;
+        sf->sf_flags = 0;
+}
+
+static void get_flavor_by_rpc(struct sptlrpc_rule *rule, __u16 rpc_flavor)
+{
+        get_default_flavor(&rule->sr_flvr);
+
+        rule->sr_flvr.sf_rpc = rpc_flavor;
+
+        switch (rpc_flavor) {
+        case SPTLRPC_FLVR_NULL:
+        case SPTLRPC_FLVR_PLAIN:
+        case SPTLRPC_FLVR_KRB5N:
+        case SPTLRPC_FLVR_KRB5A:
+                break;
+        case SPTLRPC_FLVR_KRB5P:
+                rule->sr_flvr.sf_bulk_priv = BULK_PRIV_ALG_ARC4;
+                /* fall through */
+        case SPTLRPC_FLVR_KRB5I:
+                rule->sr_flvr.sf_bulk_csum = BULK_CSUM_ALG_SHA1;
+                break;
+        default:
+                LBUG();
+        }
+}
+
+static void get_flavor_by_bulk(struct sptlrpc_rule *rule, bulk_type_t bulk_type)
+{
+        switch (bulk_type) {
+        case BULK_TYPE_N:
+                rule->sr_flvr.sf_bulk_csum = BULK_CSUM_ALG_NULL;
+                rule->sr_flvr.sf_bulk_priv = BULK_PRIV_ALG_NULL;
+                break;
+        case BULK_TYPE_I:
+                rule->sr_flvr.sf_bulk_csum = BULK_CSUM_ALG_SHA1;
+                rule->sr_flvr.sf_bulk_priv = BULK_PRIV_ALG_NULL;
+                break;
+        case BULK_TYPE_P:
+                rule->sr_flvr.sf_bulk_csum = BULK_CSUM_ALG_SHA1;
+                rule->sr_flvr.sf_bulk_priv = BULK_PRIV_ALG_ARC4;
+                break;
+        default:
+                LBUG();
+        }
+}
+
+static __u16 __flavors[] = {
+        SPTLRPC_FLVR_NULL,
+        SPTLRPC_FLVR_PLAIN,
+        SPTLRPC_FLVR_KRB5N,
+        SPTLRPC_FLVR_KRB5A,
+        SPTLRPC_FLVR_KRB5I,
+        SPTLRPC_FLVR_KRB5P,
+};
+
+#define __nflavors      ARRAY_SIZE(__flavors)
+
+/*
+ * flavor string format: rpc[-bulk{n|i|p}[:cksum/enc]]
+ * for examples:
+ *  null
+ *  plain-bulki
+ *  krb5p-bulkn
+ *  krb5i-bulkp
+ *  krb5i-bulkp:sha512/arc4
+ */
+static int parse_flavor(char *str, struct sptlrpc_rule *rule)
+{
+        const char     *f;
+        char           *bulk, *alg, *enc;
+        char            buf[64];
+        bulk_type_t     bulk_type;
+        __u8            i;
+        ENTRY;
+
+        if (str == NULL || str[0] == '\0') {
+                rule->sr_flvr.sf_rpc = SPTLRPC_FLVR_INVALID;
+                goto out;
+        }
+
+        for (i = 0; i < __nflavors; i++) {
+                f = sptlrpc_rpcflavor2name(__flavors[i]);
+                if (strncmp(str, f, strlen(f)) == 0)
+                        break;
+        }
+
+        if (i >= __nflavors)
+                GOTO(invalid, -EINVAL);
+
+        /* prepare local buffer thus we can modify it as we want */
+        strncpy(buf, str, 64);
+        buf[64 - 1] = '\0';
+
+        /* find bulk string */
+        bulk = strchr(buf, '-');
+        if (bulk)
+                *bulk++ = '\0';
+
+        /* now the first part must equal to rpc flavor name */
+        if (strcmp(buf, f) != 0)
+                GOTO(invalid, -EINVAL);
+
+        get_flavor_by_rpc(rule, __flavors[i]);
+
+        if (bulk == NULL)
+                goto out;
+
+        /* find bulk algorithm string */
+        alg = strchr(bulk, ':');
+        if (alg)
+                *alg++ = '\0';
+
+        /* verify bulk section */
+        if (strcmp(bulk, "bulkn") == 0) {
+                rule->sr_flvr.sf_bulk_csum = BULK_CSUM_ALG_NULL;
+                rule->sr_flvr.sf_bulk_priv = BULK_PRIV_ALG_NULL;
+                bulk_type = BULK_TYPE_N;
+        } else if (strcmp(bulk, "bulki") == 0)
+                bulk_type = BULK_TYPE_I;
+        else if (strcmp(bulk, "bulkp") == 0)
+                bulk_type = BULK_TYPE_P;
+        else
+                GOTO(invalid, -EINVAL);
+
+        /* null flavor don't support bulk i/p */
+        if (__flavors[i] == SPTLRPC_FLVR_NULL && bulk_type != BULK_TYPE_N)
+                GOTO(invalid, -EINVAL);
+
+        /* plain policy dosen't support bulk p */
+        if (__flavors[i] == SPTLRPC_FLVR_PLAIN && bulk_type == BULK_TYPE_P)
+                GOTO(invalid, -EINVAL);
+
+        get_flavor_by_bulk(rule, bulk_type);
+
+        if (alg == NULL)
+                goto out;
+
+        /* find encryption algorithm string */
+        enc = strchr(alg, '/');
+        if (enc)
+                *enc++ = '\0';
+
+        /* checksum algorithm */
+        for (i = 0; i < BULK_CSUM_ALG_MAX; i++) {
+                if (strcmp(alg, sptlrpc_bulk_csum_alg2name(i)) == 0) {
+                        rule->sr_flvr.sf_bulk_csum = i;
+                        break;
+                }
+        }
+        if (i >= BULK_CSUM_ALG_MAX)
+                GOTO(invalid, -EINVAL);
+
+        /* privacy algorithm */
+        if (enc) {
+                for (i = 0; i < BULK_PRIV_ALG_MAX; i++) {
+                        if (strcmp(enc, sptlrpc_bulk_priv_alg2name(i)) == 0) {
+                                rule->sr_flvr.sf_bulk_priv = i;
+                                break;
+                        }
+                }
+                if (i >= BULK_PRIV_ALG_MAX)
+                        GOTO(invalid, -EINVAL);
+        }
+
+        /*
+         * bulk combination sanity checks
+         */
+        if (bulk_type == BULK_TYPE_P &&
+            rule->sr_flvr.sf_bulk_priv == BULK_PRIV_ALG_NULL)
+                GOTO(invalid, -EINVAL);
+
+        if (bulk_type == BULK_TYPE_I &&
+            (rule->sr_flvr.sf_bulk_csum == BULK_CSUM_ALG_NULL ||
+             rule->sr_flvr.sf_bulk_priv != BULK_PRIV_ALG_NULL))
+                GOTO(invalid, -EINVAL);
+
+        if (bulk_type == BULK_TYPE_N &&
+            (rule->sr_flvr.sf_bulk_csum != BULK_CSUM_ALG_NULL ||
+             rule->sr_flvr.sf_bulk_priv != BULK_PRIV_ALG_NULL))
+                GOTO(invalid, -EINVAL);
+
+out:
+        return 0;
+invalid:
+        CERROR("invalid flavor string: %s\n", str);
+        return -EINVAL;
+}
+
+/****************************************
+ * configure rules                      *
+ ****************************************/
+
+static void sptlrpc_rule_init(struct sptlrpc_rule *rule)
+{
+        rule->sr_netid = LNET_NIDNET(LNET_NID_ANY);
+        rule->sr_from = LUSTRE_SP_ANY;
+        rule->sr_to = LUSTRE_SP_ANY;
+        rule->sr_padding = 0;
+
+        get_default_flavor(&rule->sr_flvr);
+}
+
+/*
+ * format: network[.direction]=flavor
+ */
+int sptlrpc_parse_rule(char *param, struct sptlrpc_rule *rule)
+{
+        char           *flavor, *dir;
+        int             rc;
+
+        sptlrpc_rule_init(rule);
+
+        flavor = strchr(param, '=');
+        if (flavor == NULL) {
+                CERROR("invalid param, no '='\n");
+                RETURN(-EINVAL);
+        }
+        *flavor++ = '\0';
+
+        dir = strchr(param, '.');
+        if (dir)
+                *dir++ = '\0';
+
+        /* 1.1 network */
+        if (strcmp(param, "default")) {
+                rule->sr_netid = libcfs_str2net(param);
+                if (rule->sr_netid == LNET_NIDNET(LNET_NID_ANY)) {
+                        CERROR("invalid network name: %s\n", param);
+                        RETURN(-EINVAL);
+                }
+        }
+
+        /* 1.2 direction */
+        if (dir) {
+                if (!strcmp(dir, "mdt2ost")) {
+                        rule->sr_from = LUSTRE_SP_MDT;
+                        rule->sr_to = LUSTRE_SP_OST;
+                } else if (!strcmp(dir, "mdt2mdt")) {
+                        rule->sr_from = LUSTRE_SP_MDT;
+                        rule->sr_to = LUSTRE_SP_MDT;
+                } else if (!strcmp(dir, "cli2ost")) {
+                        rule->sr_from = LUSTRE_SP_CLI;
+                        rule->sr_to = LUSTRE_SP_OST;
+                } else if (!strcmp(dir, "cli2mdt")) {
+                        rule->sr_from = LUSTRE_SP_CLI;
+                        rule->sr_to = LUSTRE_SP_MDT;
+                } else {
+                        CERROR("invalid rule dir segment: %s\n", dir);
+                        RETURN(-EINVAL);
+                }
+        }
+
+        /* 2.1 flavor */
+        rc = parse_flavor(flavor, rule);
+        if (rc)
+                RETURN(-EINVAL);
+
+        RETURN(0);
+}
+EXPORT_SYMBOL(sptlrpc_parse_rule);
+
+void sptlrpc_rule_set_free(struct sptlrpc_rule_set *rset)
+{
+        LASSERT(rset->srs_nslot ||
+                (rset->srs_nrule == 0 && rset->srs_rules == NULL));
+
+        if (rset->srs_nslot) {
+                OBD_FREE(rset->srs_rules,
+                         rset->srs_nslot * sizeof(*rset->srs_rules));
+                sptlrpc_rule_set_init(rset);
+        }
+}
+EXPORT_SYMBOL(sptlrpc_rule_set_free);
+
+/*
+ * return 0 if the rule set could accomodate one more rule.
+ * if @expand != 0, the rule set might be expanded.
+ */
+int sptlrpc_rule_set_expand(struct sptlrpc_rule_set *rset, int expand)
+{
+        struct sptlrpc_rule *rules;
+        int nslot;
+
+        if (rset->srs_nrule < rset->srs_nslot)
+                return 0; 
+
+        if (expand == 0)
+                return -E2BIG;
+
+        if (rset->srs_nslot == 0)
+                nslot = 8;
+        else
+                nslot = rset->srs_nslot + 8;
+
+        /* better use realloc() if available */
+        OBD_ALLOC(rules, nslot * sizeof(*rset->srs_rules));
+        if (rules == NULL)
+                return -ENOMEM;
+
+        memcpy(rules, rset->srs_rules,
+               rset->srs_nrule * sizeof(*rset->srs_rules));
+
+        if (rset->srs_rules)
+                OBD_FREE(rset->srs_rules,
+                         rset->srs_nslot * sizeof(*rset->srs_rules));
+
+        rset->srs_rules = rules;
+        rset->srs_nslot = nslot;
+        return 0;
+}
+EXPORT_SYMBOL(sptlrpc_rule_set_expand);
+
+static inline int rule_spec_dir(struct sptlrpc_rule *rule)
+{
+        return (rule->sr_from != LUSTRE_SP_ANY ||
+                rule->sr_to != LUSTRE_SP_ANY);
+}
+static inline int rule_spec_net(struct sptlrpc_rule *rule)
+{
+        return (rule->sr_netid != LNET_NIDNET(LNET_NID_ANY));
+}
+static inline int rule_match_dir(struct sptlrpc_rule *r1,
+                                 struct sptlrpc_rule *r2)
+{
+        return (r1->sr_from == r2->sr_from && r1->sr_to == r2->sr_to);
+}
+static inline int rule_match_net(struct sptlrpc_rule *r1,
+                                 struct sptlrpc_rule *r2)
+{
+        return (r1->sr_netid == r2->sr_netid);
+}
+
+/*
+ * merge @rule into @rset.
+ * if @expand != 0 then @rset slots might be expanded.
+ */
+int sptlrpc_rule_set_merge(struct sptlrpc_rule_set *rset, 
+                           struct sptlrpc_rule *rule,
+                           int expand)
+{
+        struct sptlrpc_rule      *p = rset->srs_rules;
+        int                       spec_dir, spec_net;
+        int                       rc, n, match = 0;
+
+        spec_net = rule_spec_net(rule);
+        spec_dir = rule_spec_dir(rule);
+
+        for (n = 0; n < rset->srs_nrule; n++) {
+                p = &rset->srs_rules[n]; 
+
+                /* test network match, if failed:
+                 * - spec rule: skip rules which is also spec rule match, until
+                 *   we hit a wild rule, which means no more chance
+                 * - wild rule: skip until reach the one which is also wild
+                 *   and matches
+                 */
+                if (!rule_match_net(p, rule)) {
+                        if (spec_net) {
+                                if (rule_spec_net(p))
+                                        continue;
+                                else
+                                        break;
+                        } else {
+                                continue;
+                        }
+                }
+
+                /* test dir match, same logic as net matching */
+                if (!rule_match_dir(p, rule)) {
+                        if (spec_dir) {
+                                if (rule_spec_dir(p))
+                                        continue;
+                                else
+                                        break;
+                        } else {
+                                continue;
+                        }
+                }
+
+                /* find a match */
+                match = 1;
+                break;
+        }
+
+        if (match) {
+                LASSERT(n >= 0 && n < rset->srs_nrule);
+
+                if (rule->sr_flvr.sf_rpc == SPTLRPC_FLVR_INVALID) {
+                        /* remove this rule */
+                        if (n < rset->srs_nrule - 1)
+                                memmove(&rset->srs_rules[n],
+                                        &rset->srs_rules[n + 1],
+                                        (rset->srs_nrule - n - 1) *
+                                        sizeof(*rule));
+                        rset->srs_nrule--;
+                } else {
+                        /* override the rule */
+                        memcpy(&rset->srs_rules[n], rule, sizeof(*rule));
+                }
+        } else {
+                LASSERT(n >= 0 && n <= rset->srs_nrule);
+
+                if (rule->sr_flvr.sf_rpc != SPTLRPC_FLVR_INVALID) {
+                        rc = sptlrpc_rule_set_expand(rset, expand);
+                        if (rc)
+                                return rc;
+
+                        if (n < rset->srs_nrule)
+                                memmove(&rset->srs_rules[n + 1],
+                                        &rset->srs_rules[n],
+                                        (rset->srs_nrule - n) * sizeof(*rule));
+                        memcpy(&rset->srs_rules[n], rule, sizeof(*rule));
+                        rset->srs_nrule++;
+                } else {
+                        CWARN("ignore the unmatched deletion\n");
+                }
+        }
+
+        return 0;
+}
+EXPORT_SYMBOL(sptlrpc_rule_set_merge);
+
+int sptlrpc_rule_set_from_log(struct sptlrpc_rule_set *rset,
+                              struct sptlrpc_conf_log *log)
+{
+        LASSERT(rset);
+        LASSERT(log);
+
+        sptlrpc_rule_set_free(rset);
+
+        if (log->scl_nrule == 0)
+                return 0;
+
+        OBD_ALLOC(rset->srs_rules, log->scl_nrule * sizeof(*log->scl_rules));
+        if (!rset->srs_rules)
+                return -ENOMEM;
+
+        memcpy(rset->srs_rules, log->scl_rules,
+               log->scl_nrule * sizeof(*log->scl_rules));
+        rset->srs_nslot = rset->srs_nrule = log->scl_nrule;
+        return 0;
+}
+EXPORT_SYMBOL(sptlrpc_rule_set_from_log);
+
+/*
+ * according to NID/from choose a flavor from rule set.
+ */
+void sptlrpc_rule_set_choose(struct sptlrpc_rule_set *rset,
+                             enum lustre_sec_part from,
+                             lnet_nid_t nid,
+                             struct sptlrpc_flavor *sf)
+{
+        struct sptlrpc_rule    *r;
+        int                     n;
+
+        for (n = 0; n < rset->srs_nrule; n++) {
+                r = &rset->srs_rules[n];
+
+                if (LNET_NIDNET(nid) != LNET_NIDNET(LNET_NID_ANY) &&
+                    r->sr_netid != LNET_NIDNET(LNET_NID_ANY) &&
+                    LNET_NIDNET(nid) != r->sr_netid)
+                        continue;
+
+                if (from != LUSTRE_SP_ANY && r->sr_from != LUSTRE_SP_ANY &&
+                    from != r->sr_from)
+                        continue;
+
+                *sf = r->sr_flvr;
+                return;
+        }
+
+        /* no match found, set as default flavor */
+        get_default_flavor(sf);
+}
+EXPORT_SYMBOL(sptlrpc_rule_set_choose);
+
+void sptlrpc_rule_set_dump(struct sptlrpc_rule_set *rset)
+{
+        struct sptlrpc_rule *r;
+        int     n;
+
+        for (n = 0; n < rset->srs_nrule; n++) {
+                r = &rset->srs_rules[n];
+                CWARN("<%02d> from %x to %x, net %x, rpc %x\n", n,
+                      r->sr_from, r->sr_to, r->sr_netid, r->sr_flvr.sf_rpc);
+        }
+}
+EXPORT_SYMBOL(sptlrpc_rule_set_dump);
+
+/****************************************
+ * sptlrpc config log                   *
+ ****************************************/
+
+struct sptlrpc_conf_log *sptlrpc_conf_log_alloc(void)
+{
+        struct sptlrpc_conf_log *log;
+
+        OBD_ALLOC_PTR(log);
+        if (log == NULL)
+                return ERR_PTR(-ENOMEM);
+
+        log->scl_max = SPTLRPC_CONF_LOG_MAX;
+        return log;
+}
+EXPORT_SYMBOL(sptlrpc_conf_log_alloc);
+
+void sptlrpc_conf_log_free(struct sptlrpc_conf_log *log)
+{
+        LASSERT(log->scl_max == SPTLRPC_CONF_LOG_MAX);
+        OBD_FREE_PTR(log);
+}
+EXPORT_SYMBOL(sptlrpc_conf_log_free);
+
+static __u32 get_log_rule_flags(enum lustre_sec_part from,
+                                enum lustre_sec_part to,
+                                unsigned int fl_udesc)
+{
+        /* MDT->MDT; MDT->OST */
+        if (from == LUSTRE_SP_MDT)
+                return PTLRPC_SEC_FL_ROOTONLY;
+        /* CLI->OST */
+        if (from == LUSTRE_SP_CLI && to == LUSTRE_SP_OST)
+                return PTLRPC_SEC_FL_ROOTONLY | PTLRPC_SEC_FL_BULK;
+        /* CLI->MDT */
+        if (from == LUSTRE_SP_CLI && to == LUSTRE_SP_MDT)
+                if (fl_udesc)
+                        return PTLRPC_SEC_FL_UDESC;
+
+        return 0;
+}
+
+/*
+ * generate config log: merge general and target rules, which
+ * match @from @to
+ */
+int sptlrpc_conf_log_populate(struct sptlrpc_rule_set *gen,
+                              struct sptlrpc_rule_set *tgt,
+                              enum lustre_sec_part from,
+                              enum lustre_sec_part to,
+                              unsigned int fl_udesc,
+                              struct sptlrpc_conf_log *log)
+{
+        struct sptlrpc_rule_set *src[2] = { gen, tgt };
+        struct sptlrpc_rule_set  dst;
+        struct sptlrpc_rule     *rule;
+        __u32                    flags;
+        int                      i, n, rc;
+
+        LASSERT(log);
+
+        dst.srs_nslot = log->scl_max;
+        dst.srs_nrule = 0;
+        dst.srs_rules = log->scl_rules;
+
+        /* merge general rules firstly, then target-specific rules */
+        for (i = 0; i < 2; i++) {
+                if (src[i] == NULL)
+                        continue;
+
+                for (n = 0; n < src[i]->srs_nrule; n++) {
+                        rule = &src[i]->srs_rules[n];
+
+                        if (from != LUSTRE_SP_ANY &&
+                            rule->sr_from != LUSTRE_SP_ANY &&
+                            rule->sr_from != from)
+                                continue;
+                        if (to != LUSTRE_SP_ANY &&
+                            rule->sr_to != LUSTRE_SP_ANY &&
+                            rule->sr_to != to)
+                                continue;
+
+                        rc = sptlrpc_rule_set_merge(&dst, rule, 0);
+                        if (rc) {
+                                CERROR("can't merge: %d\n", rc);
+                                return rc;
+                        }
+                }
+        }
+
+        log->scl_nrule = dst.srs_nrule;
+
+        /* set flags for each rule */
+        flags = get_log_rule_flags(from, to, fl_udesc);
+
+        for (i = 0; i < log->scl_nrule; i++) {
+                log->scl_rules[i].sr_flvr.sf_flags = flags;
+
+                /* also clear the from/to fields which don't need to be known
+                 * accordingly. @from == ANY means this log is for target,
+                 * otherwise for client. */
+                if (from != LUSTRE_SP_ANY)
+                        log->scl_rules[i].sr_from = LUSTRE_SP_ANY;
+                log->scl_rules[i].sr_to = LUSTRE_SP_ANY;
+        }
+
+        return 0;
+}
+EXPORT_SYMBOL(sptlrpc_conf_log_populate);
+
+/*
+ * extract config log from @lcfg
+ */
+struct sptlrpc_conf_log *sptlrpc_conf_log_extract(struct lustre_cfg *lcfg)
+{
+        struct sptlrpc_conf_log *log;
+        struct sptlrpc_rule     *r;
+        int                      i;
+        ENTRY;
+
+        log = lustre_cfg_buf(lcfg, 1);
+        if (log == NULL) {
+                CERROR("no sptlrpc config data\n");
+                RETURN(ERR_PTR(-EINVAL));
+        }
+
+        if (lcfg->lcfg_version == __swab32(LUSTRE_CFG_VERSION)) {
+                __swab32s(&log->scl_max);
+                __swab32s(&log->scl_nrule);
+        }
+
+        if (LUSTRE_CFG_BUFLEN(lcfg, 1) <
+            log->scl_max * sizeof(log->scl_rules[0])) {
+                CERROR("mal-formed config log\n");
+                RETURN(ERR_PTR(-EINVAL));
+        }
+
+        if (lcfg->lcfg_version == __swab32(LUSTRE_CFG_VERSION)) {
+                for (i = 0; i < log->scl_nrule; i++) {
+                        r = &log->scl_rules[i];
+                        __swab32s(&r->sr_netid);
+                        __swab16s(&r->sr_flvr.sf_rpc);
+                        __swab32s(&r->sr_flvr.sf_flags);
+                }
+        }
+
+        RETURN(log);
+}
+EXPORT_SYMBOL(sptlrpc_conf_log_extract);
+
+void sptlrpc_conf_log_cleanup(struct sptlrpc_conf_log *log)
+{
+        log->scl_nrule = 0;
+        memset(log->scl_rules, 0, sizeof(log->scl_rules));
+}
+EXPORT_SYMBOL(sptlrpc_conf_log_cleanup);
+
+void sptlrpc_conf_log_dump(struct sptlrpc_conf_log *log)
+{
+        struct sptlrpc_rule    *r;
+        int                     n;
+
+        CWARN("max %u, rule# %u part %u\n",
+              log->scl_max, log->scl_nrule, log->scl_part);
+
+        for (n = 0; n < log->scl_nrule; n++) {
+                r = &log->scl_rules[n];
+                CWARN("<%02d> %x -> %x, net %x, rpc %x\n", n,
+                      r->sr_from, r->sr_to, r->sr_netid, r->sr_flvr.sf_rpc);
+        }
+}
+EXPORT_SYMBOL(sptlrpc_conf_log_dump);
+
+/*
+ * caller should guarantee that no concurrent calls to this function
+ */
+#define SEC_ADAPT_DELAY         (10)
+
+int sptlrpc_cliobd_process_config(struct obd_device *obd,
+                                  struct lustre_cfg *lcfg)
+{
+        struct sptlrpc_conf_log *log;
+        struct obd_import       *imp;
+        int                      rc;
+
+        log = sptlrpc_conf_log_extract(lcfg);
+        if (IS_ERR(log)) {
+                CERROR("extract log error: %ld\n", PTR_ERR(log));
+                return PTR_ERR(log);
+        }
+
+        obd->u.cli.cl_sec_part = log->scl_part;
+
+        rc = sptlrpc_rule_set_from_log(&obd->u.cli.cl_sptlrpc_rset, log);
+        if (rc) {
+                CERROR("failed create rule set: %d\n", rc);
+                return rc;
+        }
+
+        imp = obd->u.cli.cl_import;
+        if (imp == NULL)
+                return 0;
+
+        /* even if imp_sec_expire is already set, we'll override it to a
+         * newer (later) time */
+        spin_lock(&imp->imp_lock);
+        if (imp->imp_sec)
+                imp->imp_sec_expire = cfs_time_current_sec() + SEC_ADAPT_DELAY;
+        spin_unlock(&imp->imp_lock);
+        return 0;
+}
+EXPORT_SYMBOL(sptlrpc_cliobd_process_config);
index 96ce6ef..930a7dc 100644 (file)
@@ -27,6 +27,8 @@
 
 #ifndef __KERNEL__
 #include <liblustre.h>
 
 #ifndef __KERNEL__
 #include <liblustre.h>
+#else
+#include <libcfs/libcfs.h>
 #endif
 
 #include <obd_support.h>
 #endif
 
 #include <obd_support.h>
@@ -51,11 +53,11 @@ static atomic_t sec_gc_wait_del = ATOMIC_INIT(0);
 
 void sptlrpc_gc_add_sec(struct ptlrpc_sec *sec)
 {
 
 void sptlrpc_gc_add_sec(struct ptlrpc_sec *sec)
 {
-        if (!list_empty(&sec->ps_gc_list)) {
-                CERROR("sec %p(%s) already in gc list\n",
-                       sec, sec->ps_policy->sp_name);
-                return;
-        }
+        LASSERT(sec->ps_policy->sp_cops->gc_ctx);
+        LASSERT(sec->ps_gc_interval > 0);
+        LASSERT(list_empty(&sec->ps_gc_list));
+
+        sec->ps_gc_next = cfs_time_current_sec() + sec->ps_gc_interval;
 
         spin_lock(&sec_gc_list_lock);
         list_add_tail(&sec_gc_list, &sec->ps_gc_list);
 
         spin_lock(&sec_gc_list_lock);
         list_add_tail(&sec_gc_list, &sec->ps_gc_list);
@@ -72,14 +74,17 @@ void sptlrpc_gc_del_sec(struct ptlrpc_sec *sec)
 
         might_sleep();
 
 
         might_sleep();
 
+        /* signal before list_del to make iteration in gc thread safe */
+        atomic_inc(&sec_gc_wait_del);
+
         spin_lock(&sec_gc_list_lock);
         list_del_init(&sec->ps_gc_list);
         spin_unlock(&sec_gc_list_lock);
 
         /* barrier */
         spin_lock(&sec_gc_list_lock);
         list_del_init(&sec->ps_gc_list);
         spin_unlock(&sec_gc_list_lock);
 
         /* barrier */
-        atomic_inc(&sec_gc_wait_del);
         mutex_down(&sec_gc_mutex);
         mutex_up(&sec_gc_mutex);
         mutex_down(&sec_gc_mutex);
         mutex_up(&sec_gc_mutex);
+
         atomic_dec(&sec_gc_wait_del);
 
         CDEBUG(D_SEC, "del sec %p(%s)\n", sec, sec->ps_policy->sp_name);
         atomic_dec(&sec_gc_wait_del);
 
         CDEBUG(D_SEC, "del sec %p(%s)\n", sec, sec->ps_policy->sp_name);
@@ -127,7 +132,7 @@ static void sec_process_ctx_list(void)
 
 static void sec_do_gc(struct ptlrpc_sec *sec)
 {
 
 static void sec_do_gc(struct ptlrpc_sec *sec)
 {
-        cfs_time_t      now = cfs_time_current_sec();
+        LASSERT(sec->ps_policy->sp_cops->gc_ctx);
 
         if (unlikely(sec->ps_gc_next == 0)) {
                 CWARN("sec %p(%s) has 0 gc time\n",
 
         if (unlikely(sec->ps_gc_next == 0)) {
                 CWARN("sec %p(%s) has 0 gc time\n",
@@ -135,19 +140,13 @@ static void sec_do_gc(struct ptlrpc_sec *sec)
                 return;
         }
 
                 return;
         }
 
-        if (unlikely(sec->ps_policy->sp_cops->gc_ctx == NULL)) {
-                CWARN("sec %p(%s) is not prepared for gc\n",
-                      sec, sec->ps_policy->sp_name);
-                return;
-        }
-
         CDEBUG(D_SEC, "check on sec %p(%s)\n", sec, sec->ps_policy->sp_name);
 
         CDEBUG(D_SEC, "check on sec %p(%s)\n", sec, sec->ps_policy->sp_name);
 
-        if (time_after(sec->ps_gc_next, now))
+        if (cfs_time_after(sec->ps_gc_next, cfs_time_current_sec()))
                 return;
 
         sec->ps_policy->sp_cops->gc_ctx(sec);
                 return;
 
         sec->ps_policy->sp_cops->gc_ctx(sec);
-        sec->ps_gc_next = now + sec->ps_gc_interval;
+        sec->ps_gc_next = cfs_time_current_sec() + sec->ps_gc_interval;
 }
 
 static int sec_gc_main(void *arg)
 }
 
 static int sec_gc_main(void *arg)
@@ -155,24 +154,30 @@ static int sec_gc_main(void *arg)
         struct ptlrpc_thread *thread = (struct ptlrpc_thread *) arg;
         struct l_wait_info    lwi;
 
         struct ptlrpc_thread *thread = (struct ptlrpc_thread *) arg;
         struct l_wait_info    lwi;
 
-        cfs_daemonize("sptlrpc_ctx_gc");
+        cfs_daemonize("sptlrpc_gc");
 
         /* Record that the thread is running */
         thread->t_flags = SVC_RUNNING;
         cfs_waitq_signal(&thread->t_ctl_waitq);
 
         while (1) {
 
         /* Record that the thread is running */
         thread->t_flags = SVC_RUNNING;
         cfs_waitq_signal(&thread->t_ctl_waitq);
 
         while (1) {
-                struct ptlrpc_sec *sec, *next;
+                struct ptlrpc_sec *sec;
 
                 thread->t_flags &= ~SVC_SIGNAL;
                 sec_process_ctx_list();
 again:
 
                 thread->t_flags &= ~SVC_SIGNAL;
                 sec_process_ctx_list();
 again:
+                /* go through sec list do gc.
+                 * FIXME here we iterate through the whole list each time which
+                 * is not optimal. we perhaps want to use balanced binary tree
+                 * to trace each sec as order of expiry time.
+                 * another issue here is we wakeup as fixed interval instead of
+                 * according to each sec's expiry time */
                 mutex_down(&sec_gc_mutex);
                 mutex_down(&sec_gc_mutex);
-                list_for_each_entry_safe(sec, next, &sec_gc_list, ps_gc_list) {
+                list_for_each_entry(sec, &sec_gc_list, ps_gc_list) {
                         /* if someone is waiting to be deleted, let it
                          * proceed as soon as possible. */
                         if (atomic_read(&sec_gc_wait_del)) {
                         /* if someone is waiting to be deleted, let it
                          * proceed as soon as possible. */
                         if (atomic_read(&sec_gc_wait_del)) {
-                                CWARN("deletion pending, retry\n");
+                                CWARN("deletion pending, start over\n");
                                 mutex_up(&sec_gc_mutex);
                                 goto again;
                         }
                                 mutex_up(&sec_gc_mutex);
                                 goto again;
                         }
@@ -181,6 +186,9 @@ again:
                 }
                 mutex_up(&sec_gc_mutex);
 
                 }
                 mutex_up(&sec_gc_mutex);
 
+                /* check ctx list again before sleep */
+                sec_process_ctx_list();
+
                 lwi = LWI_TIMEOUT(SEC_GC_INTERVAL * HZ, NULL, NULL);
                 l_wait_event(thread->t_ctl_waitq,
                              thread->t_flags & (SVC_STOPPING | SVC_SIGNAL),
                 lwi = LWI_TIMEOUT(SEC_GC_INTERVAL * HZ, NULL, NULL);
                 l_wait_event(thread->t_ctl_waitq,
                              thread->t_flags & (SVC_STOPPING | SVC_SIGNAL),
index df81d9c..115eae6 100644 (file)
@@ -56,6 +56,8 @@ void sec_flags2str(unsigned long flags, char *buf, int bufsize)
                 strncat(buf, "reverse,", bufsize);
         if (flags & PTLRPC_SEC_FL_ROOTONLY)
                 strncat(buf, "rootonly,", bufsize);
                 strncat(buf, "reverse,", bufsize);
         if (flags & PTLRPC_SEC_FL_ROOTONLY)
                 strncat(buf, "rootonly,", bufsize);
+        if (flags & PTLRPC_SEC_FL_UDESC)
+                strncat(buf, "udesc,", bufsize);
         if (flags & PTLRPC_SEC_FL_BULK)
                 strncat(buf, "bulk,", bufsize);
         if (buf[0] == '\0')
         if (flags & PTLRPC_SEC_FL_BULK)
                 strncat(buf, "bulk,", bufsize);
         if (buf[0] == '\0')
@@ -65,64 +67,102 @@ void sec_flags2str(unsigned long flags, char *buf, int bufsize)
 
 }
 
 
 }
 
-int sptlrpc_lprocfs_rd(char *page, char **start, off_t off, int count,
-                       int *eof, void *data)
+static int sptlrpc_info_lprocfs_seq_show(struct seq_file *seq, void *v)
 {
 {
-        struct obd_device        *obd = data;
-        struct sec_flavor_config *conf = &obd->u.cli.cl_sec_conf;
-        struct ptlrpc_sec        *sec = NULL;
-        char                      flags_str[32];
-        int                       written;
-
-        if (obd == NULL)
-                return 0;
-
-        LASSERT(strcmp(obd->obd_type->typ_name, LUSTRE_OSC_NAME) == 0 ||
-                strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) == 0 ||
-                strcmp(obd->obd_type->typ_name, LUSTRE_MGC_NAME) == 0);
-        LASSERT(conf->sfc_bulk_csum < BULK_CSUM_ALG_MAX);
-        LASSERT(conf->sfc_bulk_priv < BULK_PRIV_ALG_MAX);
-
-        if (obd->u.cli.cl_import)
-                sec = obd->u.cli.cl_import->imp_sec;
-
-        if (sec == NULL) {
-                written = snprintf(page, count, "\n");
+        struct obd_device *dev = seq->private;
+        struct client_obd *cli = &dev->u.cli;
+        struct ptlrpc_sec *sec = NULL;
+        char               flags_str[32];
+
+        LASSERT(strcmp(dev->obd_type->typ_name, LUSTRE_OSC_NAME) == 0 ||
+                strcmp(dev->obd_type->typ_name, LUSTRE_MDC_NAME) == 0 ||
+                strcmp(dev->obd_type->typ_name, LUSTRE_MGC_NAME) == 0);
+
+        if (cli->cl_import)
+                sec = sptlrpc_import_sec_ref(cli->cl_import);
+        if (sec == NULL)
                 goto out;
                 goto out;
+
+        sec_flags2str(sec->ps_flvr.sf_flags, flags_str, sizeof(flags_str));
+
+        seq_printf(seq, "rpc flavor:    %s\n",
+                   sptlrpc_rpcflavor2name(sec->ps_flvr.sf_rpc));
+        seq_printf(seq, "bulk flavor:   %s/%s\n",
+                   sptlrpc_bulk_csum_alg2name(sec->ps_flvr.sf_bulk_csum),
+                   sptlrpc_bulk_priv_alg2name(sec->ps_flvr.sf_bulk_priv));
+        seq_printf(seq, "flags:         %s\n", flags_str);
+        seq_printf(seq, "id:            %d\n", sec->ps_id);
+        seq_printf(seq, "refcount:      %d\n", atomic_read(&sec->ps_refcount));
+        seq_printf(seq, "nctx:          %d\n", atomic_read(&sec->ps_nctx));
+        seq_printf(seq, "gc internal    %ld\n", sec->ps_gc_interval);
+        seq_printf(seq, "gc next        %ld\n",
+                   sec->ps_gc_interval ?
+                   sec->ps_gc_next - cfs_time_current_sec() : 0);
+
+        sptlrpc_sec_put(sec);
+out:
+        return 0;
+}
+LPROC_SEQ_FOPS_RO(sptlrpc_info_lprocfs);
+
+static int sptlrpc_ctxs_lprocfs_seq_show(struct seq_file *seq, void *v)
+{
+        struct obd_device *dev = seq->private;
+        struct client_obd *cli = &dev->u.cli;
+        struct ptlrpc_sec *sec = NULL;
+
+        LASSERT(strcmp(dev->obd_type->typ_name, LUSTRE_OSC_NAME) == 0 ||
+                strcmp(dev->obd_type->typ_name, LUSTRE_MDC_NAME) == 0 ||
+                strcmp(dev->obd_type->typ_name, LUSTRE_MGC_NAME) == 0);
+
+        if (cli->cl_import)
+                sec = sptlrpc_import_sec_ref(cli->cl_import);
+        if (sec == NULL)
+                goto out;
+
+        if (sec->ps_policy->sp_cops->display)
+                sec->ps_policy->sp_cops->display(sec, seq);
+
+        sptlrpc_sec_put(sec);
+out:
+        return 0;
+}
+LPROC_SEQ_FOPS_RO(sptlrpc_ctxs_lprocfs);
+
+int sptlrpc_lprocfs_cliobd_attach(struct obd_device *dev)
+{
+        int     rc;
+
+        if (strcmp(dev->obd_type->typ_name, LUSTRE_OSC_NAME) != 0 &&
+            strcmp(dev->obd_type->typ_name, LUSTRE_MDC_NAME) != 0 &&
+            strcmp(dev->obd_type->typ_name, LUSTRE_MGC_NAME) != 0) {
+                CERROR("can't register lproc for obd type %s\n",
+                       dev->obd_type->typ_name);
+                return -EINVAL;
         }
 
         }
 
-        sec_flags2str(sec->ps_flags, flags_str, sizeof(flags_str));
-
-        written = snprintf(page, count,
-                        "rpc msg flavor:        %s\n"
-                        "bulk checksum:         %s\n"
-                        "bulk encrypt:          %s\n"
-                        "flags:                 %s\n"
-                        "ctx cache busy         %d\n"
-                        "gc interval            %lu\n"
-                        "gc next                %ld\n",
-                        sptlrpc_flavor2name(sec->ps_flavor),
-                        sptlrpc_bulk_csum_alg2name(conf->sfc_bulk_csum),
-                        sptlrpc_bulk_priv_alg2name(conf->sfc_bulk_priv),
-                        flags_str,
-                        atomic_read(&sec->ps_busy),
-                        sec->ps_gc_interval,
-                        sec->ps_gc_interval ?
-                                sec->ps_gc_next - cfs_time_current_sec() : 0
-                          );
-
-        if (sec->ps_policy->sp_cops->display) {
-                written += sec->ps_policy->sp_cops->display(
-                                        sec, page + written, count - written);
+        rc = lprocfs_obd_seq_create(dev, "srpc.info", 0444,
+                                    &sptlrpc_info_lprocfs_fops, dev);
+        if (rc) {
+                CERROR("create proc entry srpc.info for %s: %d\n",
+                       dev->obd_name, rc);
+                return rc;
         }
 
         }
 
-out:
-        return written;
+        rc = lprocfs_obd_seq_create(dev, "srpc.contexts", 0444,
+                                    &sptlrpc_ctxs_lprocfs_fops, dev);
+        if (rc) {
+                CERROR("create proc entry srpc.contexts for %s: %d\n",
+                       dev->obd_name, rc);
+                return rc;
+        }
+
+        return 0;
 }
 }
-EXPORT_SYMBOL(sptlrpc_lprocfs_rd);
+EXPORT_SYMBOL(sptlrpc_lprocfs_cliobd_attach);
 
 static struct lprocfs_vars sptlrpc_lprocfs_vars[] = {
 
 static struct lprocfs_vars sptlrpc_lprocfs_vars[] = {
-        { "enc_pool", sptlrpc_proc_read_enc_pool, NULL, NULL },
+        { "encrypt_page_pools", sptlrpc_proc_read_enc_pool, NULL, NULL },
         { NULL }
 };
 
         { NULL }
 };
 
@@ -152,6 +192,11 @@ void sptlrpc_lproc_fini(void)
 
 #else /* !__KERNEL__ */
 
 
 #else /* !__KERNEL__ */
 
+int sptlrpc_lprocfs_cliobd_attach(struct obd_device *dev)
+{
+        return 0;
+}
+
 int sptlrpc_lproc_init(void)
 {
         return 0;
 int sptlrpc_lproc_init(void)
 {
         return 0;
index 2c86055..dddf7e2 100644 (file)
@@ -39,6 +39,29 @@ static struct ptlrpc_sec        null_sec;
 static struct ptlrpc_cli_ctx    null_cli_ctx;
 static struct ptlrpc_svc_ctx    null_svc_ctx;
 
 static struct ptlrpc_cli_ctx    null_cli_ctx;
 static struct ptlrpc_svc_ctx    null_svc_ctx;
 
+/*
+ * null sec temporarily use the third byte of lm_secflvr to identify
+ * the source sec part.
+ */
+static inline
+void null_encode_sec_part(struct lustre_msg *msg, enum lustre_sec_part sp)
+{
+        msg->lm_secflvr |= (((__u32) sp) & 0xFF) << 16;
+}
+
+static inline
+enum lustre_sec_part null_decode_sec_part(struct lustre_msg *msg)
+{
+        switch (msg->lm_magic) {
+        case LUSTRE_MSG_MAGIC_V2:
+                return (msg->lm_secflvr >> 16) & 0xFF;
+        case LUSTRE_MSG_MAGIC_V2_SWABBED:
+                return (msg->lm_secflvr >> 8) & 0xFF;
+        default:
+                return LUSTRE_SP_ANY;
+        }
+}
+
 static
 int null_ctx_refresh(struct ptlrpc_cli_ctx *ctx)
 {
 static
 int null_ctx_refresh(struct ptlrpc_cli_ctx *ctx)
 {
@@ -50,8 +73,15 @@ int null_ctx_refresh(struct ptlrpc_cli_ctx *ctx)
 static
 int null_ctx_sign(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
 {
 static
 int null_ctx_sign(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
 {
-        if (req->rq_reqbuf->lm_magic != LUSTRE_MSG_MAGIC_V1)
+        if (req->rq_reqbuf->lm_magic != LUSTRE_MSG_MAGIC_V1) {
                 req->rq_reqbuf->lm_secflvr = SPTLRPC_FLVR_NULL;
                 req->rq_reqbuf->lm_secflvr = SPTLRPC_FLVR_NULL;
+
+                if (!req->rq_import->imp_dlm_fake) {
+                        struct obd_device *obd = req->rq_import->imp_obd;
+                        null_encode_sec_part(req->rq_reqbuf,
+                                             obd->u.cli.cl_sec_part);
+                }
+        }
         req->rq_reqdata_len = req->rq_reqlen;
         return 0;
 }
         req->rq_reqdata_len = req->rq_reqlen;
         return 0;
 }
@@ -76,12 +106,23 @@ static struct ptlrpc_svc_ctx null_svc_ctx = {
 };
 
 static
 };
 
 static
-struct ptlrpc_sec* null_create_sec(struct obd_import *imp,
-                                   struct ptlrpc_svc_ctx *ctx,
-                                   __u32 flavor,
-                                   unsigned long flags)
+struct ptlrpc_sec *null_create_sec(struct obd_import *imp,
+                                   struct ptlrpc_svc_ctx *svc_ctx,
+                                   struct sptlrpc_flavor *sf)
 {
 {
-        LASSERT(SEC_FLAVOR_POLICY(flavor) == SPTLRPC_POLICY_NULL);
+        LASSERT(RPC_FLVR_POLICY(sf->sf_rpc) == SPTLRPC_POLICY_NULL);
+
+        if (sf->sf_bulk_priv != BULK_PRIV_ALG_NULL ||
+            sf->sf_bulk_csum != BULK_CSUM_ALG_NULL) {
+                CERROR("null sec don't support bulk algorithm: %u/%u\n",
+                       sf->sf_bulk_priv, sf->sf_bulk_csum);
+                return NULL;
+        }
+
+        /* general layer has take a module reference for us, because we never
+         * really destroy the sec, simply release the reference here.
+         */
+        sptlrpc_policy_put(&null_policy);
         return &null_sec;
 }
 
         return &null_sec;
 }
 
@@ -138,16 +179,18 @@ void null_free_reqbuf(struct ptlrpc_sec *sec,
 {
         if (!req->rq_pool) {
                 LASSERTF(req->rq_reqmsg == req->rq_reqbuf,
 {
         if (!req->rq_pool) {
                 LASSERTF(req->rq_reqmsg == req->rq_reqbuf,
-                         "reqmsg %p is not reqbuf %p in null sec\n",
-                         req->rq_reqmsg, req->rq_reqbuf);
+                         "req %p: reqmsg %p is not reqbuf %p in null sec\n",
+                         req, req->rq_reqmsg, req->rq_reqbuf);
                 LASSERTF(req->rq_reqbuf_len >= req->rq_reqlen,
                 LASSERTF(req->rq_reqbuf_len >= req->rq_reqlen,
-                         "reqlen %d should smaller than buflen %d\n",
-                         req->rq_reqlen, req->rq_reqbuf_len);
+                         "req %p: reqlen %d should smaller than buflen %d\n",
+                         req, req->rq_reqlen, req->rq_reqbuf_len);
 
                 OBD_FREE(req->rq_reqbuf, req->rq_reqbuf_len);
                 req->rq_reqmsg = req->rq_reqbuf = NULL;
                 req->rq_reqbuf_len = 0;
         }
 
                 OBD_FREE(req->rq_reqbuf, req->rq_reqbuf_len);
                 req->rq_reqmsg = req->rq_reqbuf = NULL;
                 req->rq_reqbuf_len = 0;
         }
+
+        req->rq_reqmsg = NULL;
 }
 
 static
 }
 
 static
@@ -172,6 +215,8 @@ void null_free_repbuf(struct ptlrpc_sec *sec,
         OBD_FREE(req->rq_repbuf, req->rq_repbuf_len);
         req->rq_repbuf = NULL;
         req->rq_repbuf_len = 0;
         OBD_FREE(req->rq_repbuf, req->rq_repbuf_len);
         req->rq_repbuf = NULL;
         req->rq_repbuf_len = 0;
+
+        req->rq_repmsg = NULL;
 }
 
 static
 }
 
 static
@@ -220,13 +265,15 @@ int null_enlarge_reqbuf(struct ptlrpc_sec *sec,
 static
 int null_accept(struct ptlrpc_request *req)
 {
 static
 int null_accept(struct ptlrpc_request *req)
 {
-        LASSERT(SEC_FLAVOR_POLICY(req->rq_sec_flavor) == SPTLRPC_POLICY_NULL);
+        LASSERT(RPC_FLVR_POLICY(req->rq_flvr.sf_rpc) == SPTLRPC_POLICY_NULL);
 
 
-        if (SEC_FLAVOR_RPC(req->rq_sec_flavor) != SPTLRPC_FLVR_NULL) {
-                CERROR("Invalid flavor 0x%x\n", req->rq_sec_flavor);
+        if (req->rq_flvr.sf_rpc != SPTLRPC_FLVR_NULL) {
+                CERROR("Invalid rpc flavor 0x%x\n", req->rq_flvr.sf_rpc);
                 return SECSVC_DROP;
         }
 
                 return SECSVC_DROP;
         }
 
+        req->rq_sp_from = null_decode_sec_part(req->rq_reqbuf);
+
         req->rq_reqmsg = req->rq_reqbuf;
         req->rq_reqlen = req->rq_reqdata_len;
 
         req->rq_reqmsg = req->rq_reqbuf;
         req->rq_reqlen = req->rq_reqdata_len;
 
@@ -324,11 +371,16 @@ void null_init_internal(void)
 
         null_sec.ps_policy = &null_policy;
         atomic_set(&null_sec.ps_refcount, 1);     /* always busy */
 
         null_sec.ps_policy = &null_policy;
         atomic_set(&null_sec.ps_refcount, 1);     /* always busy */
+        null_sec.ps_id = -1;
         null_sec.ps_import = NULL;
         null_sec.ps_import = NULL;
-        null_sec.ps_flavor = SPTLRPC_FLVR_NULL;
-        null_sec.ps_flags = 0;
+        null_sec.ps_flvr.sf_rpc = SPTLRPC_FLVR_NULL;
+        null_sec.ps_flvr.sf_bulk_priv = BULK_PRIV_ALG_NULL;
+        null_sec.ps_flvr.sf_bulk_csum = BULK_CSUM_ALG_NULL;
+        null_sec.ps_flvr.sf_flags = 0;
+        null_sec.ps_part = LUSTRE_SP_ANY;
+        null_sec.ps_dying = 0;
         spin_lock_init(&null_sec.ps_lock);
         spin_lock_init(&null_sec.ps_lock);
-        atomic_set(&null_sec.ps_busy, 1);         /* for "null_cli_ctx" */
+        atomic_set(&null_sec.ps_nctx, 1);         /* for "null_cli_ctx" */
         INIT_LIST_HEAD(&null_sec.ps_gc_list);
         null_sec.ps_gc_interval = 0;
         null_sec.ps_gc_next = 0;
         INIT_LIST_HEAD(&null_sec.ps_gc_list);
         null_sec.ps_gc_interval = 0;
         null_sec.ps_gc_next = 0;
index e15a69e..5c75f66 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  * vim:expandtab:shiftwidth=8:tabstop=8:
  *
 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  * vim:expandtab:shiftwidth=8:tabstop=8:
  *
- * Copyright (C) 2006 Cluster File Systems, Inc.
+ * Copyright (C) 2006-2007 Cluster File Systems, Inc.
  *   Author: Eric Mei <ericm@clusterfs.com>
  *
  *   This file is part of Lustre, http://www.lustre.org.
  *   Author: Eric Mei <ericm@clusterfs.com>
  *
  *   This file is part of Lustre, http://www.lustre.org.
 #include <lustre_net.h>
 #include <lustre_sec.h>
 
 #include <lustre_net.h>
 #include <lustre_sec.h>
 
+struct plain_sec {
+        struct ptlrpc_sec       pls_base;
+        rwlock_t                pls_lock;
+        struct ptlrpc_cli_ctx  *pls_ctx;
+};
+
+static inline struct plain_sec *sec2plsec(struct ptlrpc_sec *sec)
+{
+        return container_of(sec, struct plain_sec, pls_base);
+}
+
 static struct ptlrpc_sec_policy plain_policy;
 static struct ptlrpc_ctx_ops    plain_ctx_ops;
 static struct ptlrpc_sec_policy plain_policy;
 static struct ptlrpc_ctx_ops    plain_ctx_ops;
-static struct ptlrpc_sec        plain_sec;
-static struct ptlrpc_cli_ctx    plain_cli_ctx;
 static struct ptlrpc_svc_ctx    plain_svc_ctx;
 
 static struct ptlrpc_svc_ctx    plain_svc_ctx;
 
+/*
+ * flavor flags (maximum 8 flags)
+ */
+#define PLAIN_WFLVR_FLAGS_OFFSET        (12)
+#define PLAIN_WFLVR_FLAG_BULK           (1 << (0 + PLAIN_WFLVR_FLAGS_OFFSET))
+#define PLAIN_WFLVR_FLAG_USER           (1 << (1 + PLAIN_WFLVR_FLAGS_OFFSET))
+
+#define PLAIN_WFLVR_HAS_BULK(wflvr)      \
+        (((wflvr) & PLAIN_WFLVR_FLAG_BULK) != 0)
+#define PLAIN_WFLVR_HAS_USER(wflvr)      \
+        (((wflvr) & PLAIN_WFLVR_FLAG_USER) != 0)
+
+#define PLAIN_WFLVR_TO_RPC(wflvr)       \
+        ((wflvr) & ((1 << PLAIN_WFLVR_FLAGS_OFFSET) - 1))
+
+/*
+ * similar to null sec, temporarily use the third byte of lm_secflvr to identify
+ * the source sec part.
+ */
+static inline
+void plain_encode_sec_part(struct lustre_msg *msg, enum lustre_sec_part sp)
+{
+        msg->lm_secflvr |= (((__u32) sp) & 0xFF) << 16;
+}
+
+static inline
+enum lustre_sec_part plain_decode_sec_part(struct lustre_msg *msg)
+{
+        return (msg->lm_secflvr >> 16) & 0xFF;
+}
+
+/*
+ * for simplicity, plain policy rpc use fixed layout.
+ */
+#define PLAIN_PACK_SEGMENTS             (3)
+
+#define PLAIN_PACK_MSG_OFF              (0)
+#define PLAIN_PACK_USER_OFF             (1)
+#define PLAIN_PACK_BULK_OFF             (2)
+
 /****************************************
  * cli_ctx apis                         *
  ****************************************/
 /****************************************
  * cli_ctx apis                         *
  ****************************************/
@@ -53,12 +102,25 @@ int plain_ctx_refresh(struct ptlrpc_cli_ctx *ctx)
 }
 
 static
 }
 
 static
+int plain_ctx_validate(struct ptlrpc_cli_ctx *ctx)
+{
+        return 0;
+}
+
+static
 int plain_ctx_sign(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
 {
         struct lustre_msg_v2 *msg = req->rq_reqbuf;
         ENTRY;
 
 int plain_ctx_sign(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
 {
         struct lustre_msg_v2 *msg = req->rq_reqbuf;
         ENTRY;
 
-        msg->lm_secflvr = req->rq_sec_flavor;
+        msg->lm_secflvr = req->rq_flvr.sf_rpc;
+        if (req->rq_pack_bulk)
+                msg->lm_secflvr |= PLAIN_WFLVR_FLAG_BULK;
+        if (req->rq_pack_udesc)
+                msg->lm_secflvr |= PLAIN_WFLVR_FLAG_USER;
+
+        plain_encode_sec_part(msg, ctx->cc_sec->ps_part);
+
         req->rq_reqdata_len = lustre_msg_size_v2(msg->lm_bufcount,
                                                  msg->lm_buflens);
         RETURN(0);
         req->rq_reqdata_len = lustre_msg_size_v2(msg->lm_bufcount,
                                                  msg->lm_buflens);
         RETURN(0);
@@ -68,23 +130,37 @@ static
 int plain_ctx_verify(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
 {
         struct lustre_msg *msg = req->rq_repbuf;
 int plain_ctx_verify(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
 {
         struct lustre_msg *msg = req->rq_repbuf;
+        __u16              wflvr;
         ENTRY;
 
         ENTRY;
 
-        if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
-                if (msg->lm_bufcount != 2) {
-                        CERROR("Protocol error: invalid buf count %d\n",
-                               msg->lm_bufcount);
-                        RETURN(-EPROTO);
-                }
+        if (msg->lm_bufcount != PLAIN_PACK_SEGMENTS) {
+                CERROR("unexpected reply buf count %u\n", msg->lm_bufcount);
+                RETURN(-EPROTO);
+        }
 
 
-                if (bulk_sec_desc_unpack(msg, 1)) {
-                        CERROR("Mal-formed bulk checksum reply\n");
-                        RETURN(-EINVAL);
-                }
+        wflvr = WIRE_FLVR_RPC(msg->lm_secflvr);
+
+        /* expect no user desc in reply */
+        if (PLAIN_WFLVR_HAS_USER(wflvr)) {
+                CERROR("Unexpected udesc flag in reply\n");
+                RETURN(-EPROTO);
+        }
+
+        /* whether we sent with bulk or not, we expect the same in reply */
+        if (!equi(req->rq_pack_bulk == 1, PLAIN_WFLVR_HAS_BULK(wflvr))) {
+                CERROR("%s bulk checksum in reply\n",
+                       req->rq_pack_bulk ? "Missing" : "Unexpected");
+                RETURN(-EPROTO);
         }
 
         }
 
-        req->rq_repmsg = lustre_msg_buf(msg, 0, 0);
-        req->rq_replen = msg->lm_buflens[0];
+        if (req->rq_pack_bulk &&
+            bulk_sec_desc_unpack(msg, PLAIN_PACK_BULK_OFF)) {
+                CERROR("Mal-formed bulk checksum reply\n");
+                RETURN(-EINVAL);
+        }
+
+        req->rq_repmsg = lustre_msg_buf(msg, PLAIN_PACK_MSG_OFF, 0);
+        req->rq_replen = msg->lm_buflens[PLAIN_PACK_MSG_OFF];
         RETURN(0);
 }
 
         RETURN(0);
 }
 
@@ -93,17 +169,13 @@ int plain_cli_wrap_bulk(struct ptlrpc_cli_ctx *ctx,
                         struct ptlrpc_request *req,
                         struct ptlrpc_bulk_desc *desc)
 {
                         struct ptlrpc_request *req,
                         struct ptlrpc_bulk_desc *desc)
 {
-        struct sec_flavor_config *conf;
-
-        LASSERT(req->rq_import);
-        LASSERT(SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor));
-        LASSERT(req->rq_reqbuf->lm_bufcount >= 2);
+        LASSERT(req->rq_pack_bulk);
+        LASSERT(req->rq_reqbuf->lm_bufcount == PLAIN_PACK_SEGMENTS);
 
 
-        conf = &req->rq_import->imp_obd->u.cli.cl_sec_conf;
         return bulk_csum_cli_request(desc, req->rq_bulk_read,
         return bulk_csum_cli_request(desc, req->rq_bulk_read,
-                                     conf->sfc_bulk_csum,
+                                     req->rq_flvr.sf_bulk_csum,
                                      req->rq_reqbuf,
                                      req->rq_reqbuf,
-                                     req->rq_reqbuf->lm_bufcount - 1);
+                                     PLAIN_PACK_BULK_OFF);
 }
 
 static
 }
 
 static
@@ -111,15 +183,13 @@ int plain_cli_unwrap_bulk(struct ptlrpc_cli_ctx *ctx,
                           struct ptlrpc_request *req,
                           struct ptlrpc_bulk_desc *desc)
 {
                           struct ptlrpc_request *req,
                           struct ptlrpc_bulk_desc *desc)
 {
-        LASSERT(SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor));
-        LASSERT(req->rq_reqbuf->lm_bufcount >= 2);
-        LASSERT(req->rq_repbuf->lm_bufcount >= 2);
+        LASSERT(req->rq_pack_bulk);
+        LASSERT(req->rq_reqbuf->lm_bufcount == PLAIN_PACK_SEGMENTS);
+        LASSERT(req->rq_repbuf->lm_bufcount == PLAIN_PACK_SEGMENTS);
 
         return bulk_csum_cli_reply(desc, req->rq_bulk_read,
 
         return bulk_csum_cli_reply(desc, req->rq_bulk_read,
-                                   req->rq_reqbuf,
-                                   req->rq_reqbuf->lm_bufcount - 1,
-                                   req->rq_repbuf,
-                                   req->rq_repbuf->lm_bufcount - 1);
+                                   req->rq_reqbuf, PLAIN_PACK_BULK_OFF,
+                                   req->rq_repbuf, PLAIN_PACK_BULK_OFF);
 }
 
 /****************************************
 }
 
 /****************************************
@@ -127,40 +197,178 @@ int plain_cli_unwrap_bulk(struct ptlrpc_cli_ctx *ctx,
  ****************************************/
 
 static
  ****************************************/
 
 static
-struct ptlrpc_sec* plain_create_sec(struct obd_import *imp,
-                                    struct ptlrpc_svc_ctx *ctx,
-                                    __u32 flavor,
-                                    unsigned long flags)
+struct ptlrpc_cli_ctx *plain_sec_install_ctx(struct plain_sec *plsec)
 {
 {
-        ENTRY;
-        LASSERT(SEC_FLAVOR_POLICY(flavor) == SPTLRPC_POLICY_PLAIN);
-        RETURN(&plain_sec);
+        struct ptlrpc_cli_ctx  *ctx, *ctx_new;
+
+        OBD_ALLOC_PTR(ctx_new);
+
+        write_lock(&plsec->pls_lock);
+
+        ctx = plsec->pls_ctx;
+        if (ctx) {
+                atomic_inc(&ctx->cc_refcount);
+
+                if (ctx_new)
+                        OBD_FREE_PTR(ctx_new);
+        } else if (ctx_new) {
+                ctx = ctx_new;
+
+                atomic_set(&ctx->cc_refcount, 1); /* for cache */
+                ctx->cc_sec = &plsec->pls_base;
+                ctx->cc_ops = &plain_ctx_ops;
+                ctx->cc_expire = 0;
+                ctx->cc_flags = PTLRPC_CTX_CACHED | PTLRPC_CTX_UPTODATE;
+                ctx->cc_vcred.vc_uid = 0;
+                spin_lock_init(&ctx->cc_lock);
+                INIT_LIST_HEAD(&ctx->cc_req_list);
+                INIT_LIST_HEAD(&ctx->cc_gc_chain);
+
+                plsec->pls_ctx = ctx;
+                atomic_inc(&plsec->pls_base.ps_nctx);
+                atomic_inc(&plsec->pls_base.ps_refcount);
+
+                atomic_inc(&ctx->cc_refcount); /* for caller */
+        }
+
+        write_unlock(&plsec->pls_lock);
+
+        return ctx;
 }
 
 static
 void plain_destroy_sec(struct ptlrpc_sec *sec)
 {
 }
 
 static
 void plain_destroy_sec(struct ptlrpc_sec *sec)
 {
+        struct plain_sec       *plsec = sec2plsec(sec);
         ENTRY;
         ENTRY;
-        LASSERT(sec == &plain_sec);
+
+        LASSERT(sec->ps_policy == &plain_policy);
+        LASSERT(sec->ps_import);
+        LASSERT(atomic_read(&sec->ps_refcount) == 0);
+        LASSERT(atomic_read(&sec->ps_nctx) == 0);
+        LASSERT(plsec->pls_ctx == NULL);
+
+        class_import_put(sec->ps_import);
+
+        OBD_FREE_PTR(plsec);
         EXIT;
 }
 
 static
         EXIT;
 }
 
 static
+void plain_kill_sec(struct ptlrpc_sec *sec)
+{
+        sec->ps_dying = 1;
+}
+
+static
+struct ptlrpc_sec *plain_create_sec(struct obd_import *imp,
+                                    struct ptlrpc_svc_ctx *svc_ctx,
+                                    struct sptlrpc_flavor *sf)
+{
+        struct plain_sec       *plsec;
+        struct ptlrpc_sec      *sec;
+        struct ptlrpc_cli_ctx  *ctx;
+        ENTRY;
+
+        LASSERT(RPC_FLVR_POLICY(sf->sf_rpc) == SPTLRPC_POLICY_PLAIN);
+
+        if (sf->sf_bulk_priv != BULK_PRIV_ALG_NULL) {
+                CERROR("plain policy don't support bulk encryption: %u\n",
+                       sf->sf_bulk_priv);
+                RETURN(NULL);
+        }
+
+        OBD_ALLOC_PTR(plsec);
+        if (plsec == NULL)
+                RETURN(NULL);
+
+        /*
+         * initialize plain_sec
+         */
+        plsec->pls_lock = RW_LOCK_UNLOCKED;
+        plsec->pls_ctx = NULL;
+
+        sec = &plsec->pls_base;
+        sec->ps_policy = &plain_policy;
+        atomic_set(&sec->ps_refcount, 0);
+        atomic_set(&sec->ps_nctx, 0);
+        sec->ps_id = sptlrpc_get_next_secid();
+        sec->ps_import = class_import_get(imp);
+        sec->ps_flvr = *sf;
+        sec->ps_lock = SPIN_LOCK_UNLOCKED;
+        INIT_LIST_HEAD(&sec->ps_gc_list);
+        sec->ps_gc_interval = 0;
+        sec->ps_gc_next = 0;
+
+        /* install ctx immediately if this is a reverse sec */
+        if (svc_ctx) {
+                ctx = plain_sec_install_ctx(plsec);
+                if (ctx == NULL) {
+                        plain_destroy_sec(sec);
+                        RETURN(NULL);
+                }
+                sptlrpc_cli_ctx_put(ctx, 1);
+        }
+
+        RETURN(sec);
+}
+
+static
 struct ptlrpc_cli_ctx *plain_lookup_ctx(struct ptlrpc_sec *sec,
                                         struct vfs_cred *vcred,
                                         int create, int remove_dead)
 {
 struct ptlrpc_cli_ctx *plain_lookup_ctx(struct ptlrpc_sec *sec,
                                         struct vfs_cred *vcred,
                                         int create, int remove_dead)
 {
+        struct plain_sec       *plsec = sec2plsec(sec);
+        struct ptlrpc_cli_ctx  *ctx;
         ENTRY;
         ENTRY;
-        atomic_inc(&plain_cli_ctx.cc_refcount);
-        RETURN(&plain_cli_ctx);
+
+        read_lock(&plsec->pls_lock);
+        ctx = plsec->pls_ctx;
+        if (ctx)
+                atomic_inc(&ctx->cc_refcount);
+        read_unlock(&plsec->pls_lock);
+
+        if (unlikely(ctx == NULL))
+                ctx = plain_sec_install_ctx(plsec);
+
+        RETURN(ctx);
+}
+
+static
+void plain_release_ctx(struct ptlrpc_sec *sec,
+                       struct ptlrpc_cli_ctx *ctx, int sync)
+{
+        LASSERT(atomic_read(&sec->ps_refcount) > 0);
+        LASSERT(atomic_read(&sec->ps_nctx) > 0);
+        LASSERT(atomic_read(&ctx->cc_refcount) == 0);
+        LASSERT(ctx->cc_sec == sec);
+
+        OBD_FREE_PTR(ctx);
+
+        atomic_dec(&sec->ps_nctx);
+        sptlrpc_sec_put(sec);
 }
 
 static
 int plain_flush_ctx_cache(struct ptlrpc_sec *sec,
 }
 
 static
 int plain_flush_ctx_cache(struct ptlrpc_sec *sec,
-                          uid_t uid,
-                          int grace, int force)
+                          uid_t uid, int grace, int force)
 {
 {
-        return 0;
+        struct plain_sec       *plsec = sec2plsec(sec);
+        struct ptlrpc_cli_ctx  *ctx;
+        ENTRY;
+
+        /* do nothing unless caller want to flush for 'all' */
+        if (uid != -1)
+                RETURN(0);
+
+        write_lock(&plsec->pls_lock);
+        ctx = plsec->pls_ctx;
+        plsec->pls_ctx = NULL;
+        write_unlock(&plsec->pls_lock);
+
+        if (ctx)
+                sptlrpc_cli_ctx_put(ctx, 1);
+        RETURN(0);
 }
 
 static
 }
 
 static
@@ -168,24 +376,24 @@ int plain_alloc_reqbuf(struct ptlrpc_sec *sec,
                        struct ptlrpc_request *req,
                        int msgsize)
 {
                        struct ptlrpc_request *req,
                        int msgsize)
 {
-        struct sec_flavor_config *conf;
-        int bufcnt = 1, buflens[2], alloc_len;
+        int buflens[PLAIN_PACK_SEGMENTS] = { 0, };
+        int alloc_len;
         ENTRY;
 
         ENTRY;
 
-        buflens[0] = msgsize;
+        buflens[PLAIN_PACK_MSG_OFF] = msgsize;
 
 
-        if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor))
-                buflens[bufcnt++] = sptlrpc_current_user_desc_size();
+        if (req->rq_pack_udesc)
+                buflens[PLAIN_PACK_USER_OFF] = sptlrpc_current_user_desc_size();
 
 
-        if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
+        if (req->rq_pack_bulk) {
                 LASSERT(req->rq_bulk_read || req->rq_bulk_write);
 
                 LASSERT(req->rq_bulk_read || req->rq_bulk_write);
 
-                conf = &req->rq_import->imp_obd->u.cli.cl_sec_conf;
-                buflens[bufcnt++] = bulk_sec_desc_size(conf->sfc_bulk_csum, 1,
-                                                       req->rq_bulk_read);
+                buflens[PLAIN_PACK_BULK_OFF] = bulk_sec_desc_size(
+                                                req->rq_flvr.sf_bulk_csum, 1,
+                                                req->rq_bulk_read);
         }
 
         }
 
-        alloc_len = lustre_msg_size_v2(bufcnt, buflens);
+        alloc_len = lustre_msg_size_v2(PLAIN_PACK_SEGMENTS, buflens);
 
         if (!req->rq_reqbuf) {
                 LASSERT(!req->rq_pool);
 
         if (!req->rq_reqbuf) {
                 LASSERT(!req->rq_pool);
@@ -202,11 +410,11 @@ int plain_alloc_reqbuf(struct ptlrpc_sec *sec,
                 memset(req->rq_reqbuf, 0, alloc_len);
         }
 
                 memset(req->rq_reqbuf, 0, alloc_len);
         }
 
-        lustre_init_msg_v2(req->rq_reqbuf, bufcnt, buflens, NULL);
+        lustre_init_msg_v2(req->rq_reqbuf, PLAIN_PACK_SEGMENTS, buflens, NULL);
         req->rq_reqmsg = lustre_msg_buf_v2(req->rq_reqbuf, 0, 0);
 
         req->rq_reqmsg = lustre_msg_buf_v2(req->rq_reqbuf, 0, 0);
 
-        if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor))
-                sptlrpc_pack_user_desc(req->rq_reqbuf, 1);
+        if (req->rq_pack_udesc)
+                sptlrpc_pack_user_desc(req->rq_reqbuf, PLAIN_PACK_USER_OFF);
 
         RETURN(0);
 }
 
         RETURN(0);
 }
@@ -221,6 +429,8 @@ void plain_free_reqbuf(struct ptlrpc_sec *sec,
                 req->rq_reqbuf = NULL;
                 req->rq_reqbuf_len = 0;
         }
                 req->rq_reqbuf = NULL;
                 req->rq_reqbuf_len = 0;
         }
+
+        req->rq_reqmsg = NULL;
         EXIT;
 }
 
         EXIT;
 }
 
@@ -229,21 +439,21 @@ int plain_alloc_repbuf(struct ptlrpc_sec *sec,
                        struct ptlrpc_request *req,
                        int msgsize)
 {
                        struct ptlrpc_request *req,
                        int msgsize)
 {
-        struct sec_flavor_config *conf;
-        int bufcnt = 1, buflens[2], alloc_len;
+        int buflens[PLAIN_PACK_SEGMENTS] = { 0, };
+        int alloc_len;
         ENTRY;
 
         ENTRY;
 
-        buflens[0] = msgsize;
+        buflens[PLAIN_PACK_MSG_OFF] = msgsize;
 
 
-        if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
+        if (req->rq_pack_bulk) {
                 LASSERT(req->rq_bulk_read || req->rq_bulk_write);
 
                 LASSERT(req->rq_bulk_read || req->rq_bulk_write);
 
-                conf = &req->rq_import->imp_obd->u.cli.cl_sec_conf;
-                buflens[bufcnt++] = bulk_sec_desc_size(conf->sfc_bulk_csum, 0,
-                                                       req->rq_bulk_read);
+                buflens[PLAIN_PACK_BULK_OFF] = bulk_sec_desc_size(
+                                                req->rq_flvr.sf_bulk_csum, 0,
+                                                req->rq_bulk_read);
         }
 
         }
 
-        alloc_len = lustre_msg_size_v2(bufcnt, buflens);
+        alloc_len = lustre_msg_size_v2(PLAIN_PACK_SEGMENTS, buflens);
         alloc_len = size_roundup_power2(alloc_len);
 
         OBD_ALLOC(req->rq_repbuf, alloc_len);
         alloc_len = size_roundup_power2(alloc_len);
 
         OBD_ALLOC(req->rq_repbuf, alloc_len);
@@ -262,6 +472,8 @@ void plain_free_repbuf(struct ptlrpc_sec *sec,
         OBD_FREE(req->rq_repbuf, req->rq_repbuf_len);
         req->rq_repbuf = NULL;
         req->rq_repbuf_len = 0;
         OBD_FREE(req->rq_repbuf, req->rq_repbuf_len);
         req->rq_repbuf = NULL;
         req->rq_repbuf_len = 0;
+
+        req->rq_repmsg = NULL;
         EXIT;
 }
 
         EXIT;
 }
 
@@ -275,10 +487,10 @@ int plain_enlarge_reqbuf(struct ptlrpc_sec *sec,
         int                     newmsg_size, newbuf_size;
         ENTRY;
 
         int                     newmsg_size, newbuf_size;
         ENTRY;
 
-        /* embedded msg always at seg 0 */
         LASSERT(req->rq_reqbuf);
         LASSERT(req->rq_reqbuf_len >= req->rq_reqlen);
         LASSERT(req->rq_reqbuf);
         LASSERT(req->rq_reqbuf_len >= req->rq_reqlen);
-        LASSERT(lustre_msg_buf(req->rq_reqbuf, 0, 0) == req->rq_reqmsg);
+        LASSERT(lustre_msg_buf(req->rq_reqbuf, PLAIN_PACK_MSG_OFF, 0) ==
+                req->rq_reqmsg);
 
         /* compute new embedded msg size.  */
         oldsize = req->rq_reqmsg->lm_buflens[segment];
 
         /* compute new embedded msg size.  */
         oldsize = req->rq_reqmsg->lm_buflens[segment];
@@ -288,11 +500,11 @@ int plain_enlarge_reqbuf(struct ptlrpc_sec *sec,
         req->rq_reqmsg->lm_buflens[segment] = oldsize;
 
         /* compute new wrapper msg size.  */
         req->rq_reqmsg->lm_buflens[segment] = oldsize;
 
         /* compute new wrapper msg size.  */
-        oldsize = req->rq_reqbuf->lm_buflens[0];
-        req->rq_reqbuf->lm_buflens[0] = newmsg_size;
+        oldsize = req->rq_reqbuf->lm_buflens[PLAIN_PACK_MSG_OFF];
+        req->rq_reqbuf->lm_buflens[PLAIN_PACK_MSG_OFF] = newmsg_size;
         newbuf_size = lustre_msg_size_v2(req->rq_reqbuf->lm_bufcount,
                                          req->rq_reqbuf->lm_buflens);
         newbuf_size = lustre_msg_size_v2(req->rq_reqbuf->lm_bufcount,
                                          req->rq_reqbuf->lm_buflens);
-        req->rq_reqbuf->lm_buflens[0] = oldsize;
+        req->rq_reqbuf->lm_buflens[PLAIN_PACK_MSG_OFF] = oldsize;
 
         /* request from pool should always have enough buffer */
         LASSERT(!req->rq_pool || req->rq_reqbuf_len >= newbuf_size);
 
         /* request from pool should always have enough buffer */
         LASSERT(!req->rq_pool || req->rq_reqbuf_len >= newbuf_size);
@@ -309,10 +521,12 @@ int plain_enlarge_reqbuf(struct ptlrpc_sec *sec,
                 OBD_FREE(req->rq_reqbuf, req->rq_reqbuf_len);
                 req->rq_reqbuf = newbuf;
                 req->rq_reqbuf_len = newbuf_size;
                 OBD_FREE(req->rq_reqbuf, req->rq_reqbuf_len);
                 req->rq_reqbuf = newbuf;
                 req->rq_reqbuf_len = newbuf_size;
-                req->rq_reqmsg = lustre_msg_buf(req->rq_reqbuf, 0, 0);
+                req->rq_reqmsg = lustre_msg_buf(req->rq_reqbuf,
+                                                PLAIN_PACK_MSG_OFF, 0);
         }
 
         }
 
-        _sptlrpc_enlarge_msg_inplace(req->rq_reqbuf, 0, newmsg_size);
+        _sptlrpc_enlarge_msg_inplace(req->rq_reqbuf, PLAIN_PACK_MSG_OFF,
+                                     newmsg_size);
         _sptlrpc_enlarge_msg_inplace(req->rq_reqmsg, segment, newsize);
 
         req->rq_reqlen = newmsg_size;
         _sptlrpc_enlarge_msg_inplace(req->rq_reqmsg, segment, newsize);
 
         req->rq_reqlen = newmsg_size;
@@ -332,46 +546,43 @@ static
 int plain_accept(struct ptlrpc_request *req)
 {
         struct lustre_msg *msg = req->rq_reqbuf;
 int plain_accept(struct ptlrpc_request *req)
 {
         struct lustre_msg *msg = req->rq_reqbuf;
-        int                bufcnt = 1;
         ENTRY;
 
         ENTRY;
 
-        LASSERT(SEC_FLAVOR_POLICY(req->rq_sec_flavor) == SPTLRPC_POLICY_PLAIN);
+        LASSERT(RPC_FLVR_POLICY(req->rq_flvr.sf_rpc) == SPTLRPC_POLICY_PLAIN);
 
 
-        if (SEC_FLAVOR_RPC(req->rq_sec_flavor) != SPTLRPC_FLVR_PLAIN) {
-                CERROR("Invalid flavor 0x%x\n", req->rq_sec_flavor);
-                return SECSVC_DROP;
+        if (msg->lm_bufcount < PLAIN_PACK_SEGMENTS) {
+                CERROR("unexpected request buf count %u\n", msg->lm_bufcount);
+                RETURN(SECSVC_DROP);
         }
 
         }
 
-        if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor)) {
-                if (msg->lm_bufcount < ++bufcnt) {
-                        CERROR("Protocal error: too small buf count %d\n",
-                               msg->lm_bufcount);
-                        RETURN(SECSVC_DROP);
-                }
+        if (req->rq_flvr.sf_rpc != SPTLRPC_FLVR_PLAIN) {
+                CERROR("Invalid rpc flavor %x\n", req->rq_flvr.sf_rpc);
+                RETURN(SECSVC_DROP);
+        }
+
+        req->rq_sp_from = plain_decode_sec_part(msg);
 
 
-                if (sptlrpc_unpack_user_desc(msg, bufcnt - 1)) {
+        if (PLAIN_WFLVR_HAS_USER(msg->lm_secflvr)) {
+                if (sptlrpc_unpack_user_desc(msg, PLAIN_PACK_USER_OFF)) {
                         CERROR("Mal-formed user descriptor\n");
                         RETURN(SECSVC_DROP);
                 }
 
                         CERROR("Mal-formed user descriptor\n");
                         RETURN(SECSVC_DROP);
                 }
 
-                req->rq_user_desc = lustre_msg_buf(msg, bufcnt - 1, 0);
+                req->rq_pack_udesc = 1;
+                req->rq_user_desc = lustre_msg_buf(msg, PLAIN_PACK_USER_OFF, 0);
         }
 
         }
 
-        if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
-                if (msg->lm_bufcount != ++bufcnt) {
-                        CERROR("Protocal error: invalid buf count %d\n",
-                               msg->lm_bufcount);
-                        RETURN(SECSVC_DROP);
-                }
-
-                if (bulk_sec_desc_unpack(msg, bufcnt - 1)) {
+        if (PLAIN_WFLVR_HAS_BULK(msg->lm_secflvr)) {
+                if (bulk_sec_desc_unpack(msg, PLAIN_PACK_BULK_OFF)) {
                         CERROR("Mal-formed bulk checksum request\n");
                         RETURN(SECSVC_DROP);
                 }
                         CERROR("Mal-formed bulk checksum request\n");
                         RETURN(SECSVC_DROP);
                 }
+
+                req->rq_pack_bulk = 1;
         }
 
         }
 
-        req->rq_reqmsg = lustre_msg_buf(msg, 0, 0);
-        req->rq_reqlen = msg->lm_buflens[0];
+        req->rq_reqmsg = lustre_msg_buf(msg, PLAIN_PACK_MSG_OFF, 0);
+        req->rq_reqlen = msg->lm_buflens[PLAIN_PACK_MSG_OFF];
 
         req->rq_svc_ctx = &plain_svc_ctx;
         atomic_inc(&req->rq_svc_ctx->sc_refcount);
 
         req->rq_svc_ctx = &plain_svc_ctx;
         atomic_inc(&req->rq_svc_ctx->sc_refcount);
@@ -382,26 +593,26 @@ int plain_accept(struct ptlrpc_request *req)
 static
 int plain_alloc_rs(struct ptlrpc_request *req, int msgsize)
 {
 static
 int plain_alloc_rs(struct ptlrpc_request *req, int msgsize)
 {
-        struct ptlrpc_reply_state *rs;
+        struct ptlrpc_reply_state   *rs;
         struct ptlrpc_bulk_sec_desc *bsd;
         struct ptlrpc_bulk_sec_desc *bsd;
-        int bufcnt = 1, buflens[2];
-        int rs_size = sizeof(*rs);
+        int                          buflens[PLAIN_PACK_SEGMENTS] = { 0, };
+        int                          rs_size = sizeof(*rs);
         ENTRY;
 
         LASSERT(msgsize % 8 == 0);
 
         ENTRY;
 
         LASSERT(msgsize % 8 == 0);
 
-        buflens[0] = msgsize;
-        if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor) &&
-            (req->rq_bulk_read || req->rq_bulk_write)) {
+        buflens[PLAIN_PACK_MSG_OFF] = msgsize;
+
+        if (req->rq_pack_bulk && (req->rq_bulk_read || req->rq_bulk_write)) {
                 bsd = lustre_msg_buf(req->rq_reqbuf,
                 bsd = lustre_msg_buf(req->rq_reqbuf,
-                                     req->rq_reqbuf->lm_bufcount - 1,
-                                     sizeof(*bsd));
+                                     PLAIN_PACK_BULK_OFF, sizeof(*bsd));
                 LASSERT(bsd);
 
                 LASSERT(bsd);
 
-                buflens[bufcnt++] = bulk_sec_desc_size(bsd->bsd_csum_alg, 0,
-                                                       req->rq_bulk_read);
+                buflens[PLAIN_PACK_BULK_OFF] = bulk_sec_desc_size(
+                                                        bsd->bsd_csum_alg, 0,
+                                                        req->rq_bulk_read);
         }
         }
-        rs_size += lustre_msg_size_v2(bufcnt, buflens);
+        rs_size += lustre_msg_size_v2(PLAIN_PACK_SEGMENTS, buflens);
 
         rs = req->rq_reply_state;
 
 
         rs = req->rq_reply_state;
 
@@ -421,8 +632,8 @@ int plain_alloc_rs(struct ptlrpc_request *req, int msgsize)
         rs->rs_repbuf = (struct lustre_msg *) (rs + 1);
         rs->rs_repbuf_len = rs_size - sizeof(*rs);
 
         rs->rs_repbuf = (struct lustre_msg *) (rs + 1);
         rs->rs_repbuf_len = rs_size - sizeof(*rs);
 
-        lustre_init_msg_v2(rs->rs_repbuf, bufcnt, buflens, NULL);
-        rs->rs_msg = lustre_msg_buf_v2(rs->rs_repbuf, 0, 0);
+        lustre_init_msg_v2(rs->rs_repbuf, PLAIN_PACK_SEGMENTS, buflens, NULL);
+        rs->rs_msg = lustre_msg_buf_v2(rs->rs_repbuf, PLAIN_PACK_MSG_OFF, 0);
 
         req->rq_reply_state = rs;
         RETURN(0);
 
         req->rq_reply_state = rs;
         RETURN(0);
@@ -452,12 +663,16 @@ int plain_authorize(struct ptlrpc_request *req)
         LASSERT(rs);
         LASSERT(msg);
 
         LASSERT(rs);
         LASSERT(msg);
 
-        if (req->rq_replen != msg->lm_buflens[0])
-                len = lustre_shrink_msg(msg, 0, req->rq_replen, 1);
+        if (req->rq_replen != msg->lm_buflens[PLAIN_PACK_MSG_OFF])
+                len = lustre_shrink_msg(msg, PLAIN_PACK_MSG_OFF,
+                                        req->rq_replen, 1);
         else
                 len = lustre_msg_size_v2(msg->lm_bufcount, msg->lm_buflens);
 
         else
                 len = lustre_msg_size_v2(msg->lm_bufcount, msg->lm_buflens);
 
-        msg->lm_secflvr = req->rq_sec_flavor;
+        msg->lm_secflvr = req->rq_flvr.sf_rpc;
+        if (req->rq_pack_bulk)
+                msg->lm_secflvr |= PLAIN_WFLVR_FLAG_BULK;
+
         rs->rs_repdata_len = len;
         RETURN(0);
 }
         rs->rs_repdata_len = len;
         RETURN(0);
 }
@@ -467,18 +682,21 @@ int plain_svc_unwrap_bulk(struct ptlrpc_request *req,
                           struct ptlrpc_bulk_desc *desc)
 {
         struct ptlrpc_reply_state      *rs = req->rq_reply_state;
                           struct ptlrpc_bulk_desc *desc)
 {
         struct ptlrpc_reply_state      *rs = req->rq_reply_state;
-        int                             voff, roff;
 
         LASSERT(rs);
 
         LASSERT(rs);
-
-        voff = req->rq_reqbuf->lm_bufcount - 1;
-        roff = rs->rs_repbuf->lm_bufcount - 1;
+        LASSERT(req->rq_pack_bulk);
+        LASSERT(req->rq_reqbuf->lm_bufcount >= PLAIN_PACK_SEGMENTS);
+        LASSERT(rs->rs_repbuf->lm_bufcount == PLAIN_PACK_SEGMENTS);
 
         return bulk_csum_svc(desc, req->rq_bulk_read,
 
         return bulk_csum_svc(desc, req->rq_bulk_read,
-                             lustre_msg_buf(req->rq_reqbuf, voff, 0),
-                             lustre_msg_buflen(req->rq_reqbuf, voff),
-                             lustre_msg_buf(rs->rs_repbuf, roff, 0),
-                             lustre_msg_buflen(rs->rs_repbuf, roff));
+                             lustre_msg_buf(req->rq_reqbuf,
+                                            PLAIN_PACK_BULK_OFF, 0),
+                             lustre_msg_buflen(req->rq_reqbuf,
+                                               PLAIN_PACK_BULK_OFF),
+                             lustre_msg_buf(rs->rs_repbuf,
+                                            PLAIN_PACK_BULK_OFF, 0),
+                             lustre_msg_buflen(rs->rs_repbuf,
+                                               PLAIN_PACK_BULK_OFF));
 }
 
 static
 }
 
 static
@@ -486,22 +704,26 @@ int plain_svc_wrap_bulk(struct ptlrpc_request *req,
                         struct ptlrpc_bulk_desc *desc)
 {
         struct ptlrpc_reply_state      *rs = req->rq_reply_state;
                         struct ptlrpc_bulk_desc *desc)
 {
         struct ptlrpc_reply_state      *rs = req->rq_reply_state;
-        int                             voff, roff;
 
         LASSERT(rs);
 
         LASSERT(rs);
-
-        voff = req->rq_reqbuf->lm_bufcount - 1;
-        roff = rs->rs_repbuf->lm_bufcount - 1;
+        LASSERT(req->rq_pack_bulk);
+        LASSERT(req->rq_reqbuf->lm_bufcount >= PLAIN_PACK_SEGMENTS);
+        LASSERT(rs->rs_repbuf->lm_bufcount == PLAIN_PACK_SEGMENTS);
 
         return bulk_csum_svc(desc, req->rq_bulk_read,
 
         return bulk_csum_svc(desc, req->rq_bulk_read,
-                             lustre_msg_buf(req->rq_reqbuf, voff, 0),
-                             lustre_msg_buflen(req->rq_reqbuf, voff),
-                             lustre_msg_buf(rs->rs_repbuf, roff, 0),
-                             lustre_msg_buflen(rs->rs_repbuf, roff));
+                             lustre_msg_buf(req->rq_reqbuf,
+                                            PLAIN_PACK_BULK_OFF, 0),
+                             lustre_msg_buflen(req->rq_reqbuf,
+                                               PLAIN_PACK_BULK_OFF),
+                             lustre_msg_buf(rs->rs_repbuf,
+                                            PLAIN_PACK_BULK_OFF, 0),
+                             lustre_msg_buflen(rs->rs_repbuf,
+                                               PLAIN_PACK_BULK_OFF));
 }
 
 static struct ptlrpc_ctx_ops plain_ctx_ops = {
         .refresh                = plain_ctx_refresh,
 }
 
 static struct ptlrpc_ctx_ops plain_ctx_ops = {
         .refresh                = plain_ctx_refresh,
+        .validate               = plain_ctx_validate,
         .sign                   = plain_ctx_sign,
         .verify                 = plain_ctx_verify,
         .wrap_bulk              = plain_cli_wrap_bulk,
         .sign                   = plain_ctx_sign,
         .verify                 = plain_ctx_verify,
         .wrap_bulk              = plain_cli_wrap_bulk,
@@ -511,7 +733,9 @@ static struct ptlrpc_ctx_ops plain_ctx_ops = {
 static struct ptlrpc_sec_cops plain_sec_cops = {
         .create_sec             = plain_create_sec,
         .destroy_sec            = plain_destroy_sec,
 static struct ptlrpc_sec_cops plain_sec_cops = {
         .create_sec             = plain_create_sec,
         .destroy_sec            = plain_destroy_sec,
+        .kill_sec               = plain_kill_sec,
         .lookup_ctx             = plain_lookup_ctx,
         .lookup_ctx             = plain_lookup_ctx,
+        .release_ctx            = plain_release_ctx,
         .flush_ctx_cache        = plain_flush_ctx_cache,
         .alloc_reqbuf           = plain_alloc_reqbuf,
         .alloc_repbuf           = plain_alloc_repbuf,
         .flush_ctx_cache        = plain_flush_ctx_cache,
         .alloc_reqbuf           = plain_alloc_reqbuf,
         .alloc_repbuf           = plain_alloc_repbuf,
@@ -531,50 +755,19 @@ static struct ptlrpc_sec_sops plain_sec_sops = {
 
 static struct ptlrpc_sec_policy plain_policy = {
         .sp_owner               = THIS_MODULE,
 
 static struct ptlrpc_sec_policy plain_policy = {
         .sp_owner               = THIS_MODULE,
-        .sp_name                = "sec.plain",
+        .sp_name                = "plain",
         .sp_policy              = SPTLRPC_POLICY_PLAIN,
         .sp_cops                = &plain_sec_cops,
         .sp_sops                = &plain_sec_sops,
 };
 
         .sp_policy              = SPTLRPC_POLICY_PLAIN,
         .sp_cops                = &plain_sec_cops,
         .sp_sops                = &plain_sec_sops,
 };
 
-static
-void plain_init_internal(void)
-{
-        static HLIST_HEAD(__list);
-
-        plain_sec.ps_policy = &plain_policy;
-        atomic_set(&plain_sec.ps_refcount, 1);     /* always busy */
-        plain_sec.ps_import = NULL;
-        plain_sec.ps_flavor = SPTLRPC_FLVR_PLAIN;
-        plain_sec.ps_flags = 0;
-        spin_lock_init(&plain_sec.ps_lock);
-        atomic_set(&plain_sec.ps_busy, 1);         /* for "plain_cli_ctx" */
-        CFS_INIT_LIST_HEAD(&plain_sec.ps_gc_list);
-        plain_sec.ps_gc_interval = 0;
-        plain_sec.ps_gc_next = 0;
-
-        hlist_add_head(&plain_cli_ctx.cc_cache, &__list);
-        atomic_set(&plain_cli_ctx.cc_refcount, 1);    /* for hash */
-        plain_cli_ctx.cc_sec = &plain_sec;
-        plain_cli_ctx.cc_ops = &plain_ctx_ops;
-        plain_cli_ctx.cc_expire = 0;
-        plain_cli_ctx.cc_flags = PTLRPC_CTX_CACHED | PTLRPC_CTX_ETERNAL |
-                                 PTLRPC_CTX_UPTODATE;
-        plain_cli_ctx.cc_vcred.vc_uid = 0;
-        spin_lock_init(&plain_cli_ctx.cc_lock);
-        CFS_INIT_LIST_HEAD(&plain_cli_ctx.cc_req_list);
-        CFS_INIT_LIST_HEAD(&plain_cli_ctx.cc_gc_chain);
-}
-
 int sptlrpc_plain_init(void)
 {
         int rc;
 
 int sptlrpc_plain_init(void)
 {
         int rc;
 
-        plain_init_internal();
-
         rc = sptlrpc_register_policy(&plain_policy);
         if (rc)
         rc = sptlrpc_register_policy(&plain_policy);
         if (rc)
-                CERROR("failed to register sec.plain: %d\n", rc);
+                CERROR("failed to register: %d\n", rc);
 
         return rc;
 }
 
         return rc;
 }
@@ -585,5 +778,5 @@ void sptlrpc_plain_fini(void)
 
         rc = sptlrpc_unregister_policy(&plain_policy);
         if (rc)
 
         rc = sptlrpc_unregister_policy(&plain_policy);
         if (rc)
-                CERROR("cannot unregister sec.plain: %d\n", rc);
+                CERROR("cannot unregister: %d\n", rc);
 }
 }
index dc1106e..1e6a812 100644 (file)
@@ -591,9 +591,6 @@ ptlrpc_server_handle_request(struct ptlrpc_service *svc,
         }
 
         /* go through security check/transform */
         }
 
         /* go through security check/transform */
-        request->rq_auth_uid = INVALID_UID;
-        request->rq_auth_mapped_uid = INVALID_UID;
-
         rc = sptlrpc_svc_unwrap_request(request);
         switch (rc) {
         case SECSVC_OK:
         rc = sptlrpc_svc_unwrap_request(request);
         switch (rc) {
         case SECSVC_OK:
@@ -674,7 +671,7 @@ ptlrpc_server_handle_request(struct ptlrpc_service *svc,
                 rc = sptlrpc_target_export_check(request->rq_export, request);
                 if (unlikely(rc)) {
                         DEBUG_REQ(D_ERROR, request,
                 rc = sptlrpc_target_export_check(request->rq_export, request);
                 if (unlikely(rc)) {
                         DEBUG_REQ(D_ERROR, request,
-                                  "DROPPING req with illeagle security flavor");
+                                  "DROPPING req with illegal security flavor,");
                         goto put_conn;
                 }
 
                         goto put_conn;
                 }
 
index 2d16b87..b14261f 100644 (file)
@@ -12,10 +12,15 @@ noinst_SCRIPTS += conf-sanity.sh insanity.sh lfscktest.sh oos.sh oos2.sh
 noinst_SCRIPTS += llog-test.sh recovery-small.sh replay-dual.sh sanity-quota.sh
 noinst_SCRIPTS += replay-ost-single.sh replay-single.sh run-llog.sh sanityN.sh
 noinst_SCRIPTS += lockorder.sh socketclient socketserver sanity-sec.sh
 noinst_SCRIPTS += llog-test.sh recovery-small.sh replay-dual.sh sanity-quota.sh
 noinst_SCRIPTS += replay-ost-single.sh replay-single.sh run-llog.sh sanityN.sh
 noinst_SCRIPTS += lockorder.sh socketclient socketserver sanity-sec.sh
+noinst_SCRIPTS += sanity-gss.sh krb5_login.sh
 nobase_noinst_SCRIPTS = cfg/insanity-local.sh cfg/insanity-ltest.sh
 nobase_noinst_SCRIPTS += cfg/local.sh acl/make-tree acl/run
 nobase_noinst_SCRIPTS = cfg/insanity-local.sh cfg/insanity-ltest.sh
 nobase_noinst_SCRIPTS += cfg/local.sh acl/make-tree acl/run
+nobase_noinst_SCRIPTS += rmtacl/make-tree rmtacl/run
 nobase_noinst_DATA = acl/cp.test acl/getfacl-noacl.test acl/inheritance.test
 nobase_noinst_DATA += acl/misc.test acl/permissions.test acl/setfacl.test
 nobase_noinst_DATA = acl/cp.test acl/getfacl-noacl.test acl/inheritance.test
 nobase_noinst_DATA += acl/misc.test acl/permissions.test acl/setfacl.test
+nobase_noinst_DATA += rmtacl/misc.test rmtacl/permissions.test
+nobase_noinst_DATA += rmtacl/setfacl.test rmtacl/cp.test
+nobase_noinst_DATA += rmtacl/getfacl-noacl.test rmtacl/inheritance.test
 
 EXTRA_DIST = $(noinst_SCRIPTS) $(noinst_DATA) \
              $(nobase_noinst_SCRIPTS) $(nobase_noinst_DATA)
 
 EXTRA_DIST = $(noinst_SCRIPTS) $(noinst_DATA) \
              $(nobase_noinst_SCRIPTS) $(nobase_noinst_DATA)
index c5b6b40..4c27f95 100755 (executable)
@@ -25,7 +25,7 @@ fi
 [ "$DEBUG_OFF" ] || DEBUG_OFF="eval sysctl -w lnet.debug=\"$DEBUG_LVL\""
 [ "$DEBUG_ON" ] || DEBUG_ON="eval sysctl -w lnet.debug=0x33f0484"
 
 [ "$DEBUG_OFF" ] || DEBUG_OFF="eval sysctl -w lnet.debug=\"$DEBUG_LVL\""
 [ "$DEBUG_ON" ] || DEBUG_ON="eval sysctl -w lnet.debug=0x33f0484"
 
-export TESTSUITE_LIST="RUNTESTS SANITY DBENCH BONNIE IOZONE FSX SANITYN LFSCK LIBLUSTRE REPLAY_SINGLE CONF_SANITY RECOVERY_SMALL REPLAY_OST_SINGLE REPLAY_DUAL INSANITY SANITY_QUOTA"
+export TESTSUITE_LIST="RUNTESTS SANITY DBENCH BONNIE IOZONE FSX SANITYN LFSCK LIBLUSTRE REPLAY_SINGLE CONF_SANITY RECOVERY_SMALL REPLAY_OST_SINGLE REPLAY_DUAL INSANITY SANITY_QUOTA SANITY_SEC"
 
 if [ "$SLOW" = "no" ]; then
 #          5 min  
 
 if [ "$SLOW" = "no" ]; then
 #          5 min  
@@ -52,6 +52,11 @@ LUSTRE=${LUSTRE:-`dirname $0`/..}
 . $LUSTRE/tests/test-framework.sh
 init_test_env $@
 
 . $LUSTRE/tests/test-framework.sh
 init_test_env $@
 
+if $GSS; then
+    # liblustre doesn't support GSS
+    export LIBLUSTRE=no
+fi
+
 SETUP=${SETUP:-setupall}
 FORMAT=${FORMAT:-formatall}
 CLEANUP=${CLEANUP:-stopall}
 SETUP=${SETUP:-setupall}
 FORMAT=${FORMAT:-formatall}
 CLEANUP=${CLEANUP:-stopall}
@@ -311,6 +316,10 @@ if [ "$SANITY_QUOTA" != "no" ]; then
         SANITY_QUOTA="done"
 fi
 
         SANITY_QUOTA="done"
 fi
 
+if [ "$SANITY_SEC" != "no" ]; then
+        title sanity-sec
+        bash sanity-sec.sh
+fi
 
 RC=$?
 title FINISHED
 
 RC=$?
 title FINISHED
index fd4de0e..dbd9b6b 100644 (file)
@@ -174,7 +174,7 @@ fi
 
 gen_config
 
 
 gen_config
 
-init_krb5_env
+init_gss
 
 test_0() {
         setup
 
 test_0() {
         setup
@@ -1493,7 +1493,7 @@ run_test 38 "MDS recreates missing lov_objid file from OST data"
 
 umount_client $MOUNT
 cleanup_nocli
 
 umount_client $MOUNT
 cleanup_nocli
-cleanup_krb5_env
+cleanup_gss
 
 equals_msg `basename $0`: test complete
 [ -f "$TESTSUITELOG" ] && cat $TESTSUITELOG || true
 
 equals_msg `basename $0`: test complete
 [ -f "$TESTSUITELOG" ] && cat $TESTSUITELOG || true
index e80ae7c..b2a4205 100755 (executable)
@@ -7,11 +7,7 @@ if [ $UID -eq 0 ]; then
     exit 0
 fi
 
     exit 0
 fi
 
-if [ -z "$KRB5DIR" ]; then
-    KRB5DIR=/usr/kerberos
-fi
-
-$KRB5DIR/bin/klist -5 -s
+klist -5 -s
 invalid=$?
 
 if [ $invalid -eq 0 ]; then
 invalid=$?
 
 if [ $invalid -eq 0 ]; then
@@ -20,7 +16,7 @@ fi
 
 echo "***** refresh Kerberos V5 TGT for uid $UID *****"
 if [ -z "$GSS_PASS" ]; then
 
 echo "***** refresh Kerberos V5 TGT for uid $UID *****"
 if [ -z "$GSS_PASS" ]; then
-    $KRB5DIR/bin/kinit
+    kinit
 else
     expect <<EOF
 set timeout 30 
 else
     expect <<EOF
 set timeout 30 
@@ -34,7 +30,7 @@ expect {
     "user@host $ "
 }
 
     "user@host $ "
 }
 
-send "$KRB5DIR/bin/kinit\r"
+send "kinit\r"
 expect {
     timeout {puts "timeout" ;exit 1}
     "Password for "
 expect {
     timeout {puts "timeout" ;exit 1}
     "Password for "
index 07b45e7..a6aae0d 100755 (executable)
@@ -422,6 +422,8 @@ test_18() { # bug 3822 - evicting client with enqueued lock
     wait $OPENPID
     dmesg | grep "entering recovery in server" && \
         error "client not evicted" || true
     wait $OPENPID
     dmesg | grep "entering recovery in server" && \
         error "client not evicted" || true
+    do_facet client "sysctl -w lustre.fail_loc=0"
+    do_facet $SINGLEMDS "sysctl -w lustre.fail_loc=0"
 }
 run_test 18 "ldlm_handle_enqueue succeeds on evicted export (3822)"
 
 }
 run_test 18 "ldlm_handle_enqueue succeeds on evicted export (3822)"
 
diff --git a/lustre/tests/rmtacl/README b/lustre/tests/rmtacl/README
new file mode 100644 (file)
index 0000000..aa5230b
--- /dev/null
@@ -0,0 +1 @@
+- adapt based on test/acl/
diff --git a/lustre/tests/rmtacl/cp.test b/lustre/tests/rmtacl/cp.test
new file mode 100644 (file)
index 0000000..2384dac
--- /dev/null
@@ -0,0 +1,50 @@
+The "lfs cp" utility should only copy ACLs if `-p' is given.
+       $ umask 022
+       $ mkdir d
+       $ cd d
+       $ touch f
+       $ lfs lsetfacl -m u:bin:rw f
+       $ lfs ls -l f | awk -- '{ print $1 }'
+       > -rw-rw-r--+
+       
+       $ lfs cp f g
+       $ lfs ls -l g | awk -- '{ print $1 }'
+       > -rw-r--r--
+       
+       $ rm g
+       $ lfs cp -p f g
+       $ lfs ls -l f | awk -- '{ print $1 }'
+       > -rw-rw-r--+
+       
+       $ mkdir h
+       $ echo blubb > h/x
+       $ lfs cp -rp h i
+       $ cat i/x
+       > blubb
+
+       $ rm -r i
+
+Use to be "$lfs lsetfacl -R -m u:bin:rwX h", but RHEL4 uncorrectly set the x flag,
+so we change to the following test
+
+       $ lfs lsetfacl -R -m u:bin:rwx h
+       $ lfs lgetfacl --omit-header h/x
+       > user::rw-
+       > user:bin:rwx
+       > group::r--
+       > mask::rwx
+       > other::r--
+       >
+
+       $ lfs cp -rp h i
+       $ lfs lgetfacl --omit-header i/x
+       > user::rw-
+       > user:bin:rwx
+       > group::r--
+       > mask::rwx
+       > other::r--
+       >
+
+       $ cd ..
+       $ rm -r d
diff --git a/lustre/tests/rmtacl/getfacl-noacl.test b/lustre/tests/rmtacl/getfacl-noacl.test
new file mode 100644 (file)
index 0000000..8f1f69a
--- /dev/null
@@ -0,0 +1,59 @@
+Getfacl utility option parsing tests. This test can be run on a
+filesystem with or without ACL support.
+
+       $ mkdir test
+       $ cd test
+       $ umask 027
+       $ touch x
+       $ lfs lgetfacl --omit-header x
+       > user::rw-
+       > group::r--
+       > other::---
+       > 
+
+       $ lfs lgetfacl --omit-header --access x
+       > user::rw-
+       > group::r--
+       > other::---
+       > 
+
+       $ lfs lgetfacl --omit-header -d x
+       $ lfs lgetfacl --omit-header -d .
+       $ lfs lgetfacl --omit-header -d /
+       > getfacl: Removing leading '/' from absolute path names
+       
+       $ lfs lgetfacl --skip-base x
+       $ lfs lgetfacl --omit-header --all-effective x
+       > user::rw-
+       > group::r--
+       > other::---
+       > 
+       
+       $ lfs lgetfacl --omit-header --no-effective x
+       > user::rw-
+       > group::r--
+       > other::---
+       > 
+       
+       $ mkdir d
+       $ touch d/y
+       $ ln -s d l
+The result of "lfs lgetfacl -dR . | grep file | sort" is related with
+the dentry item order in parent directory. Such order depends on
+FS implementation. Fix with -P (--physical) option.
+#      $ lfs lgetfacl -dR . | grep file | sort
+       $ lfs lgetfacl -dRP . | grep file | sort
+       > # file: .
+       > # file: d
+       > # file: d/y
+       > # file: x
+       
+       $ ln -s l ll
+       $ lfs lgetfacl -dLR ll | grep file | sort
+       > # file: ll
+       > # file: ll/y
+       
+       $ rm l ll x
+       $ rm -rf d
+       $ cd ..
+       $ rmdir test
diff --git a/lustre/tests/rmtacl/inheritance.test b/lustre/tests/rmtacl/inheritance.test
new file mode 100644 (file)
index 0000000..40d25cb
--- /dev/null
@@ -0,0 +1,131 @@
+ACL inheritance test.  Run these tests on a filesystem with ACL support.
+
+       $ id -u
+        > 0
+
+       $ mkdir d
+        $ lfs lsetfacl -d -m group:bin:r-x d
+        $ lfs lgetfacl d
+       > # file: d
+       > # owner: root
+       > # group: root
+       > user::rwx
+       > group::r-x
+       > other::r-x
+       > default:user::rwx
+       > default:group::r-x
+       > default:group:bin:r-x
+       > default:mask::r-x
+       > default:other::r-x
+        >
+
+       $ mkdir d/subdir
+        $ lfs lgetfacl d/subdir
+       > # file: d/subdir
+       > # owner: root
+       > # group: root
+       > user::rwx
+       > group::r-x
+       > group:bin:r-x
+       > mask::r-x
+       > other::r-x
+       > default:user::rwx
+       > default:group::r-x
+       > default:group:bin:r-x
+       > default:mask::r-x
+       > default:other::r-x
+       >
+
+        $ touch d/f
+        $ lfs ls -l d/f | awk -- '{ print $1 }'
+        > -rw-r--r--+
+       $ lfs lgetfacl d/f
+       > # file: d/f
+       > # owner: root
+       > # group: root
+       > user::rw-
+       > group::r-x    #effective:r--
+       > group:bin:r-x #effective:r--
+       > mask::r--
+       > other::r--
+       >
+
+        $ su bin
+        $ echo i >> d/f
+       > d/f: Permission denied
+
+Changed by CFS: (1). reduce the tree level to 2 (for shortening
+time of local tests). (2). add one more lfs lgetfacl test since dir
+might be distributed around MDS's.
+
+        $ su
+        $ rm d/f
+        $ rmdir d/subdir
+        $ mv d tree 
+        $ ./make-tree
+        $ lfs lgetfacl tree/dir0/dir5/file4 
+       > # file: tree/dir0/dir5/file4
+       > # owner: root
+       > # group: root
+       > user::rw-
+       > group::r-x    #effective:r--
+       > group:bin:r-x #effective:r--
+       > mask::r--
+       > other::r--
+       >
+        $ lfs lgetfacl tree/dir0/dir6/file4 
+       > # file: tree/dir0/dir6/file4
+       > # owner: root
+       > # group: root
+       > user::rw-
+       > group::r-x    #effective:r--
+       > group:bin:r-x #effective:r--
+       > mask::r--
+       > other::r--
+       >
+       $ echo i >> tree/dir6/dir2/file2
+       $ echo i > tree/dir1/f
+       $ lfs ls -l tree/dir1/f | awk -- '{ print $1 }'
+       > -rw-r--r--+
+in following item, the error message is dependant on distributions.
+success on FC3, but not on FC2 and SLES3 etc. comment out by CFS.
+#      $ su bin
+#      $ echo i > tree/dir6/dir2/f
+#      > tree/dir6/dir2/f: No such file or directory
+#      $ su
+
+        $ rm -rf tree
+
+
+Original scripts, comment out by CFS.
+#
+#        $ su
+#        $ rm d/f
+#        $ rmdir d/subdir
+#        $ mv d tree 
+#        $ ./make-tree
+#        $ lfs lgetfacl tree/dir0/dir5/dir7/file4 
+#      > # file: tree/dir0/dir5/dir7/file4
+#      > # owner: root
+#      > # group: root
+#      > user::rw-
+#      > group::r-x    #effective:r--
+#      > group:bin:r-x #effective:r--
+#      > mask::r--
+#      > other::r--
+#      >
+#      $ echo i >> tree/dir6/dir2/dir1/file2
+#      $ echo i > tree/dir1/f
+#      $ lfs ls -l tree/dir1/f | awk -- '{ print $1 }'
+#      > -rw-r--r--+
+#      $ su bin
+#      $ echo i > tree/dir6/dir2/f
+#      > tree/dir6/dir2/f: No such file or directory
+#      $ su
+#
+#        $ rm -rf tree
+
+
+
diff --git a/lustre/tests/rmtacl/make-tree b/lustre/tests/rmtacl/make-tree
new file mode 100755 (executable)
index 0000000..6ade51d
--- /dev/null
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+# reduce LEVELS from 3 => 2 by CFS
+LEVELS=2 ;             [ -z "$1" ] || LEVELS=$1
+DIRS=10 ;              [ -z "$2" ] || DIRS=$2
+FILES=10 ;             [ -z "$2" ] || FILES=$3
+NUMBER_OF_ACLS=50 ;    [ -z "$3" ] || NUMBER_OF_ACLS=$4
+
+function random_dir() {
+       mkdir -p $1
+       #lfs lsetfacl -s "u::rwx,u:$[($RANDOM % $NUMBER_OF_ACLS)+1000]:rwx,g::rx,o:-" $1
+}
+
+function random_file() {
+       touch $1
+       #lfs lsetfacl -s "u::rw,u:$[($RANDOM % $NUMBER_OF_ACLS)+1000]:rw,g::r,o:-" $1
+}
+
+function create () {
+       local LEVEL=$1
+       if [ $LEVEL -eq 0 ]; then
+               local I=0
+               while [ $I -lt $FILES ]; do
+                       random_file file$I
+                       I=$[$I+1]
+               done
+       else
+               local I=0
+               while [ $I -lt $DIRS ]; do
+                       random_dir dir$I
+                       cd dir$I
+                       create $[$LEVEL-1]
+                       cd ..
+                       I=$[$I+1]
+               done
+       fi
+       return
+}
+
+mkdir -p tree
+cd tree
+create $LEVELS
+cd ..
+exit 0
+
diff --git a/lustre/tests/rmtacl/misc.test b/lustre/tests/rmtacl/misc.test
new file mode 100644 (file)
index 0000000..aa7d7bd
--- /dev/null
@@ -0,0 +1,426 @@
+Pretty comprehensive ACL tests.
+This must be run on a filesystem with ACL support. Also, you will need
+two dummy users (bin and daemon) and a dummy group (daemon).
+       $ umask 027
+       $ touch f
+         
+Only change a base ACL:
+       $ lfs lsetfacl -m u::r f
+       $ lfs lsetfacl -m u::rw,u:bin:rw f
+       $ lfs ls -dl f | awk '{print $1}'
+       > -rw-rw----+
+       
+       $ lfs lgetfacl --omit-header f
+       > user::rw-
+       > user:bin:rw-
+       > group::r--
+       > mask::rw-
+       > other::---
+       > 
+
+       $ rm f
+       $ umask 022
+       $ touch f
+       $ lfs lsetfacl -m u:bin:rw f
+       $ lfs ls -dl f | awk '{print $1}'
+       > -rw-rw-r--+
+
+       $ lfs lgetfacl --omit-header f
+       > user::rw-
+       > user:bin:rw-
+       > group::r--
+       > mask::rw-
+       > other::r--
+       > 
+
+       $rm f
+       $ umask 027
+       $ mkdir d
+       $ lfs lsetfacl -m u:bin:rwx d
+       $ lfs ls -dl d | awk '{print $1}'
+       > drwxrwx---+
+
+       $ lfs lgetfacl --omit-header d
+       > user::rwx
+       > user:bin:rwx
+       > group::r-x
+       > mask::rwx
+       > other::---
+       > 
+
+       $ rmdir d
+       $ umask 022
+       $ mkdir d
+       $ lfs lsetfacl -m u:bin:rwx d
+       $ lfs ls -dl d | awk '{print $1}'
+       > drwxrwxr-x+
+
+       $ lfs lgetfacl --omit-header d
+       > user::rwx
+       > user:bin:rwx
+       > group::r-x
+       > mask::rwx
+       > other::r-x
+       > 
+
+       $ rmdir d
+        
+
+Multiple users
+        
+       $ umask 022
+       $ touch f
+       $ lfs lsetfacl -m u:bin:rw,u:daemon:r f
+       $ lfs ls -dl f | awk '{print $1}'
+       > -rw-rw-r--+
+
+       $ lfs lgetfacl --omit-header f
+       > user::rw-
+       > user:bin:rw-
+       > user:daemon:r--
+       > group::r--
+       > mask::rw-
+       > other::r--
+       > 
+        
+Multiple groups
+        
+       $ lfs lsetfacl -m g:users:rw,g:daemon:r f
+       $ lfs ls -dl f | awk '{print $1}'
+       > -rw-rw-r--+
+
+       $ lfs lgetfacl --omit-header f
+       > user::rw-
+       > user:bin:rw-
+       > user:daemon:r--
+       > group::r--
+       > group:daemon:r--
+       > group:users:rw-
+       > mask::rw-
+       > other::r--
+       > 
+        
+Remove one group
+        
+       $ lfs lsetfacl -x g:users f
+       $ lfs ls -dl f | awk '{print $1}'
+       > -rw-rw-r--+
+
+       $ lfs lgetfacl --omit-header f
+       > user::rw-
+       > user:bin:rw-
+       > user:daemon:r--
+       > group::r--
+       > group:daemon:r--
+       > mask::rw-
+       > other::r--
+       > 
+        
+Remove one user
+        
+       $ lfs lsetfacl -x u:daemon f
+       $ lfs ls -dl f | awk '{print $1}'
+       > -rw-rw-r--+
+
+       $ lfs lgetfacl --omit-header f
+       > user::rw-
+       > user:bin:rw-
+       > group::r--
+       > group:daemon:r--
+       > mask::rw-
+       > other::r--
+       > 
+
+       $ rm f
+        
+Default ACL
+        
+       $ umask 027
+       $ mkdir d
+       $ lfs lsetfacl -m u:bin:rwx,u:daemon:rw,d:u:bin:rwx,d:m:rx d
+       $ lfs ls -dl d | awk '{print $1}'
+       > drwxrwx---+
+
+       $ lfs lgetfacl --omit-header d
+       > user::rwx
+       > user:bin:rwx
+       > user:daemon:rw-
+       > group::r-x
+       > mask::rwx
+       > other::---
+       > default:user::rwx
+       > default:user:bin:rwx  #effective:r-x
+       > default:group::r-x
+       > default:mask::r-x
+       > default:other::---
+       > 
+        
+Umask now ignored?
+       $ umask 027
+       $ touch d/f
+       $ lfs ls -dl d/f | awk '{print $1}'
+       > -rw-r-----+
+
+       $ lfs lgetfacl --omit-header d/f
+       > user::rw-
+       > user:bin:rwx  #effective:r--
+       > group::r-x    #effective:r--
+       > mask::r--
+       > other::---
+       > 
+
+       $ rm d/f
+       $ umask 022
+       $ touch d/f
+       $ lfs ls -dl d/f | awk '{print $1}'
+       > -rw-r-----+
+
+       $ lfs lgetfacl --omit-header d/f
+       > user::rw-
+       > user:bin:rwx  #effective:r--
+       > group::r-x    #effective:r--
+       > mask::r--
+       > other::---
+       > 
+
+       $ rm d/f
+        
+Default ACL copying
+       $ umask 000
+       $ mkdir d/d
+       $ lfs ls -dl d/d | awk '{print $1}'
+       > drwxr-x---+
+
+       $ lfs lgetfacl --omit-header d/d
+       > user::rwx
+       > user:bin:rwx  #effective:r-x
+       > group::r-x
+       > mask::r-x
+       > other::---
+       > default:user::rwx
+       > default:user:bin:rwx  #effective:r-x
+       > default:group::r-x
+       > default:mask::r-x
+       > default:other::---
+       > 
+
+       $ rmdir d/d
+       $ umask 022
+       $ mkdir d/d
+       $ lfs ls -dl d/d | awk '{print $1}'
+       > drwxr-x---+
+
+       $ lfs lgetfacl --omit-header d/d
+       > user::rwx
+       > user:bin:rwx  #effective:r-x
+       > group::r-x
+       > mask::r-x
+       > other::---
+       > default:user::rwx
+       > default:user:bin:rwx  #effective:r-x
+       > default:group::r-x
+       > default:mask::r-x
+       > default:other::---
+       > 
+        
+Add some users and groups
+       $ lfs lsetfacl -nm u:daemon:rx,d:u:daemon:rx,g:users:rx,g:daemon:rwx d/d
+       $ lfs ls -dl d/d | awk '{print $1}'
+       > drwxr-x---+
+
+       $ lfs lgetfacl --omit-header d/d
+       > user::rwx
+       > user:bin:rwx  #effective:r-x
+       > user:daemon:r-x
+       > group::r-x
+       > group:daemon:rwx      #effective:r-x
+       > group:users:r-x
+       > mask::r-x
+       > other::---
+       > default:user::rwx
+       > default:user:bin:rwx  #effective:r-x
+       > default:user:daemon:r-x
+       > default:group::r-x
+       > default:mask::r-x
+       > default:other::---
+       > 
+        
+Symlink in directory with default ACL?
+        
+       $ ln -s d d/l
+       $ lfs ls -dl d/l | awk '{print $1}'
+       > lrwxrwxrwx
+
+       $ lfs ls -dl -L d/l | awk '{print $1}'
+       > drwxr-x---+
+
+       $ lfs lgetfacl --omit-header d/l
+       > user::rwx
+       > user:bin:rwx  #effective:r-x
+       > user:daemon:r-x
+       > group::r-x
+       > group:daemon:rwx      #effective:r-x
+       > group:users:r-x
+       > mask::r-x
+       > other::---
+       > default:user::rwx
+       > default:user:bin:rwx  #effective:r-x
+       > default:user:daemon:r-x
+       > default:group::r-x
+       > default:mask::r-x
+       > default:other::---
+       > 
+
+       $ rm d/l
+        
+Does mask manipulation work?
+        
+       $ lfs lsetfacl -m g:daemon:rx,u:bin:rx d/d
+       $ lfs ls -dl d/d | awk '{print $1}'
+       > drwxr-x---+
+
+       $ lfs lgetfacl --omit-header d/d
+       > user::rwx
+       > user:bin:r-x
+       > user:daemon:r-x
+       > group::r-x
+       > group:daemon:r-x
+       > group:users:r-x
+       > mask::r-x
+       > other::---
+       > default:user::rwx
+       > default:user:bin:rwx  #effective:r-x
+       > default:user:daemon:r-x
+       > default:group::r-x
+       > default:mask::r-x
+       > default:other::---
+       > 
+
+       $ lfs lsetfacl -m d:u:bin:rwx d/d
+       $ lfs ls -dl d/d | awk '{print $1}'
+       > drwxr-x---+
+
+       $ lfs lgetfacl --omit-header d/d
+       > user::rwx
+       > user:bin:r-x
+       > user:daemon:r-x
+       > group::r-x
+       > group:daemon:r-x
+       > group:users:r-x
+       > mask::r-x
+       > other::---
+       > default:user::rwx
+       > default:user:bin:rwx
+       > default:user:daemon:r-x
+       > default:group::r-x
+       > default:mask::rwx
+       > default:other::---
+       > 
+
+       $ rmdir d/d
+        
+Remove the default ACL
+        
+       $ lfs lsetfacl -k d
+       $ lfs ls -dl d | awk '{print $1}'
+       > drwxrwx---+
+
+       $ lfs lgetfacl --omit-header d
+       > user::rwx
+       > user:bin:rwx
+       > user:daemon:rw-
+       > group::r-x
+       > mask::rwx
+       > other::---
+       > 
+        
+Reset to base entries
+        
+       $ lfs lsetfacl -b d
+       $ lfs ls -dl d | awk '{print $1}'
+       > drwxr-x---
+
+       $ lfs lgetfacl --omit-header d
+       > user::rwx
+       > group::r-x
+       > other::---
+       > 
+        
+Now, chmod should change the group_obj entry
+        
+       $ chmod 775 d
+       $ lfs ls -dl d | awk '{print $1}'
+       > drwxrwxr-x
+       
+       $ lfs lgetfacl --omit-header d
+       > user::rwx
+       > group::rwx
+       > other::r-x
+       > 
+
+       $ rmdir d
+       $ umask 002
+       $ mkdir d
+       $ lfs lsetfacl -m u:daemon:rwx,u:bin:rx,d:u:daemon:rwx,d:u:bin:rx d
+       $ lfs ls -dl d | awk '{print $1}'
+       > drwxrwxr-x+
+
+       $ lfs lgetfacl --omit-header d
+       > user::rwx
+       > user:bin:r-x
+       > user:daemon:rwx
+       > group::rwx
+       > mask::rwx
+       > other::r-x
+       > default:user::rwx
+       > default:user:bin:r-x
+       > default:user:daemon:rwx
+       > default:group::rwx
+       > default:mask::rwx
+       > default:other::r-x
+       > 
+
+       $ chmod 750 d
+       $ lfs ls -dl d | awk '{print $1}'
+       > drwxr-x---+
+
+       $ lfs lgetfacl --omit-header d
+       > user::rwx
+       > user:bin:r-x
+       > user:daemon:rwx       #effective:r-x
+       > group::rwx    #effective:r-x
+       > mask::r-x
+       > other::---
+       > default:user::rwx
+       > default:user:bin:r-x
+       > default:user:daemon:rwx
+       > default:group::rwx
+       > default:mask::rwx
+       > default:other::r-x
+       > 
+
+       $ chmod 750 d
+       $ lfs ls -dl d | awk '{print $1}'
+       > drwxr-x---+
+
+       $ lfs lgetfacl --omit-header d
+       > user::rwx
+       > user:bin:r-x
+       > user:daemon:rwx       #effective:r-x
+       > group::rwx    #effective:r-x
+       > mask::r-x
+       > other::---
+       > default:user::rwx
+       > default:user:bin:r-x
+       > default:user:daemon:rwx
+       > default:group::rwx
+       > default:mask::rwx
+       > default:other::r-x
+       > 
+
+       $ rmdir d
diff --git a/lustre/tests/rmtacl/permissions.test b/lustre/tests/rmtacl/permissions.test
new file mode 100644 (file)
index 0000000..b7cb587
--- /dev/null
@@ -0,0 +1,284 @@
+This script tests if file permissions are properly checked with and
+without ACLs. The script must be run as root to allow switching users.
+The following users are required. They must be a member in the groups
+listed in parentheses.
+
+       bin (bin)
+       daemon (bin, daemon)
+
+
+Cry immediately if we are not running as root.
+
+       $ id -u
+       > 0
+
+
+First, set up a temporary directory and create a regular file with
+defined permissions.
+
+       $ mkdir d
+       $ cd d
+       $ umask 027
+       $ touch f
+       $ lfs ls -l f | awk -- '{ print $1, $3, $4 }'
+       > -rw-r----- root root
+
+
+Make sure root has access to the file.  Verify that user daemon does not
+have access to the file owned by root.
+
+       $ echo root > f
+
+       $ su daemon
+       $ echo daemon >> f
+       > f: Permission denied
+
+       $ su
+
+
+Now, change the ownership of the file to bin:bin and verify that this
+gives user bin write access.
+
+       $ chown bin:bin f
+       $ lfs ls -l f | awk -- '{ print $1, $3, $4 }'
+       > -rw-r----- bin bin
+       $ su bin
+       $ echo bin >> f
+
+
+User daemon is a member in the owning group, which has only read access.
+Verify this.
+
+       $ su daemon
+       $ cat f
+       > root
+       > bin
+
+       $ echo daemon >> f
+       > f: Permission denied
+
+
+Now, add an ACL entry for user daemon that grants him rw- access. File
+owners and users capable of CAP_FOWNER are allowed to change ACLs.
+
+       $ su bin
+       $ lfs lsetfacl -m u:daemon:rw f
+       $ lfs lgetfacl --omit-header f
+       > user::rw-
+       > user:daemon:rw-
+       > group::r--
+       > mask::rw-
+       > other::---
+       >
+
+
+Verify that the additional ACL entry grants user daemon write access.
+
+       $ su daemon
+       $ echo daemon >> f
+       $ cat f
+       > root
+       > bin
+       > daemon
+
+
+Remove write access from the group class permission bits, and
+verify that this masks daemon's write permission.
+
+       $ su bin
+       $ chmod g-w f
+       $ lfs lgetfacl --omit-header f
+       > user::rw-
+       > user:daemon:rw-       #effective:r--
+       > group::r--
+       > mask::r--
+       > other::---
+       >
+
+       $ su daemon
+       $ echo daemon >> f
+       > f: Permission denied
+
+
+Add an entry for group daemon with rw- access, and change the
+permissions for user daemon to r--. Also change the others permissions t
+rw-. The user entry should take precedence, so daemon should be denied
+access.
+
+       $ su bin
+       $ lfs lsetfacl -m u:daemon:r,g:daemon:rw-,o::rw- f
+
+       $ su daemon
+       $ echo daemon >> f
+       > f: Permission denied
+
+
+Remove the entry for user daemon. The group daemon permissions should
+now give user daemon rw- access.
+
+       $ su bin
+       $ lfs lsetfacl -x u:daemon f
+
+       $ su daemon
+       $ echo daemon2 >> f
+       $ cat f
+       > root
+       > bin
+       > daemon
+       > daemon2
+
+
+Set the group daemon permissions to r-- and verify that after than, user
+daemon does not have write access anymore.
+
+       $ su bin
+       $ lfs lsetfacl -m g:daemon:r f
+
+       $ su daemon
+       $ echo daemon3 >> f
+       > f: Permission denied
+
+
+Now, remove the group daemon entry. Because user daemon is a member in
+the owning group, he should still have no write access.
+
+       $ su bin
+       $ lfs lsetfacl -x g:daemon f
+
+       $ su daemon
+       $ echo daemon4 >> f
+       > f: Permission denied
+
+
+Change the owning group. The other permissions should now grant user
+daemon write access.
+
+       $ su
+       $ chgrp root f
+
+       $ su daemon
+       $ echo daemon5 >> f
+       $ cat f
+       > root
+       > bin
+       > daemon
+       > daemon2
+       > daemon5
+
+
+Verify that permissions in separate matching ACL entries do not
+accumulate.
+
+       $ su
+       $ lfs lsetfacl -m g:bin:r,g:daemon:w f
+
+       $ su daemon
+       $ : < f  # open for reading
+       $ : > f  # open for writing
+       $ : <> f  # open for read-write
+       > f: Permission denied
+
+
+Test if directories can have ACLs.  We assume that only one access check
+algorithm is used for all file types the file system, so these tests
+only need to verify that ACL permissions make a difference.
+
+       $ su
+       $ mkdir -m 750 e
+       $ touch e/h
+
+       $ su bin
+       $ shopt -s nullglob ; echo e/*
+       >
+
+       $ echo i > e/i
+       > e/i: Permission denied
+
+       $ su
+       $ lfs lsetfacl -m u:bin:rx e
+
+       $ su bin
+       $ echo e/*
+       > e/h
+following 2 lines seems not valid, which also failed on ext3 in FC3 enviroment,
+although it pass in FC2. commented out by CFS (agreed with HP)
+Replaced "echo" with "touch" can resolve such problem.
+#      $ echo i > e/i
+#      > e/i: Permission denied
+        $ touch e/i
+        > touch: cannot touch `e/i': Permission denied
+
+       $ su
+       $ lfs lsetfacl -m u:bin:rwx e
+
+       $ su bin
+       $ echo i > e/i
+
+
+Test if symlinks are properly followed.
+
+       $ su
+       $ touch g
+       $ ln -s g l
+       $ lfs lsetfacl -m u:bin:rw l
+       $ lfs ls -l g | awk -- '{ print $1, $3, $4 }'
+       > -rw-rw----+ root root
+
+
+Test if ACLs are effective for block and character special files, fifos,
+sockets. This is done by creating special files locally. The devices do
+not need to exist: The access check is earlier in the code path than the
+test if the device exists.
+
+
+       $ mknod -m 0660 hdt b 91 64     # /dev/hdt
+       $ mknod -m 0660 null c 1 3      # /dev/null
+       $ mkfifo -m 0660 fifo
+
+       $ su bin
+       $ : < hdt
+       > hdt: Permission denied
+       $ : < null
+       > null: Permission denied
+       $ : < fifo
+       > fifo: Permission denied
+
+       $ su
+       $ lfs lsetfacl -m u:bin:rw hdt null fifo
+
+       $ su bin
+       $ : < hdt
+       > hdt: No such device or address
+       $ : < null
+       $ ( echo blah > fifo & ) ; cat fifo
+       > blah
+
+
+Test if CAP_FOWNER is properly honored for directories. This addresses a
+specific bug in XFS 1.2, which does not grant root access to files in
+directories if the file has an ACL and only CAP_FOWNER would grant them.
+
+       $ su
+       $ mkdir -m 600 x
+       $ chown daemon:daemon x
+       $ echo j > x/j
+       $ lfs ls -l x/j | awk -- '{ print $1, $3, $4 }'
+       > -rw-r----- root root
+
+       $ lfs lsetfacl -m u:daemon:r x
+
+       $ lfs ls -l x/j | awk -- '{ print $1, $3, $4 }'
+       > -rw-r----- root root
+       (With the bug this gives: `ls: x/j: Permission denied'.)
+
+       $ echo k > x/k
+       (With the bug this gives: `x/k: Permission denied'.)
+
+       $ chmod 750 x
+
+
+Clean up.
+
+       $ su
+       $ cd ..
+       $ rm -rf d
diff --git a/lustre/tests/rmtacl/run b/lustre/tests/rmtacl/run
new file mode 100755 (executable)
index 0000000..cfc8c05
--- /dev/null
@@ -0,0 +1,275 @@
+#!/usr/bin/perl -w -U
+
+#
+# Possible improvements:
+#
+# - distinguish stdout and stderr output
+# - add environment variable like assignments
+# - run up to a specific line
+# - resume at a specific line
+#
+
+use strict;
+use FileHandle;
+use Getopt::Std;
+use POSIX qw(isatty setuid);
+use vars qw($opt_v);
+
+no warnings qw(taint);
+
+getopts('v');
+
+my ($OK, $FAILED) = ("ok", "failed");
+if (isatty(fileno(STDOUT))) {
+       $OK = "\033[32m" . $OK . "\033[m";
+       $FAILED = "\033[31m\033[1m" . $FAILED . "\033[m";
+}
+
+sub exec_test($$);
+sub process_test($$$$);
+
+my ($prog, $in, $out) = ([], [], []);
+my $line_number = 0;
+my $prog_line;
+my ($tests, $failed) = (0,0);
+
+for (;;) {
+  my $line = <>; $line_number++;
+  if (defined $line) {
+    # Substitute %VAR and %{VAR} with environment variables.
+    $line =~ s[%(?:(\w+)|\{(\w+)\})][$ENV{"$1$2"}]eg;
+  }
+  if (defined $line) {
+    if ($line =~ s/^\s*< ?//) {
+      push @$in, $line;
+    } elsif ($line =~ s/^\s*> ?//) {
+      push @$out, $line;
+    } else {
+      process_test($prog, $prog_line, $in, $out);
+
+      $prog = [];
+      $prog_line = 0;
+    }
+    if ($line =~ s/^\s*\$ ?//) {
+      $line =~ s/\s+#.*//;  # remove comments here...
+      $prog = [ map { s/\\(.)/$1/g; $_ } split /(?<!\\)\s+/, $line ];
+      $prog_line = $line_number;
+      $in = [];
+      $out = [];
+    }
+  } else {
+    process_test($prog, $prog_line, $in, $out);
+    last;
+  }
+}
+
+my $status = sprintf("%d commands (%d passed, %d failed)",
+       $tests, $tests-$failed, $failed);
+if (isatty(fileno(STDOUT))) {
+       if ($failed) {
+               $status = "\033[31m\033[1m" . $status . "\033[m";
+       } else {
+               $status = "\033[32m" . $status . "\033[m";
+       }
+}
+print $status, "\n";
+exit $failed ? 1 : 0;
+
+
+sub process_test($$$$) {
+  my ($prog, $prog_line, $in, $out) = @_;
+
+  return unless @$prog;
+
+       my $p = [ @$prog ];
+       print "[$prog_line] \$ ", join(' ',
+             map { s/\s/\\$&/g; $_ } @$p), " -- ";
+       my $result = exec_test($prog, $in);
+       my $good = 1;
+       my $nmax = (@$out > @$result) ? @$out : @$result;
+       for (my $n=0; $n < $nmax; $n++) {
+        if (!defined($out->[$n]) || !defined($result->[$n]) ||
+            $out->[$n] ne $result->[$n]) {
+                $good = 0;
+        }
+       }
+       $tests++;
+       $failed++ unless $good;
+       print $good ? $OK : $FAILED, "\n";
+       if (!$good) {
+         for (my $n=0; $n < $nmax; $n++) {
+          my $l = defined($out->[$n]) ? $out->[$n] : "~";
+          chomp $l;
+          my $r = defined($result->[$n]) ? $result->[$n] : "~";
+          chomp $r;
+          print sprintf("%-37s %s %-39s\n", $l, $l eq $r ? "|" : "?", $r);
+         }
+       } elsif ($opt_v) {
+        print join('', @$result);
+       }
+}
+
+
+sub su($) {
+  my ($user) = @_;
+
+  $user ||= "root";
+
+  my ($login, $pass, $uid, $gid) = getpwnam($user)
+    or return [ "su: user $user does not exist\n" ];
+  my @groups = ();
+  my $fh = new FileHandle("/etc/group")
+    or return [ "opening /etc/group: $!\n" ];
+  while (<$fh>) {
+    chomp;
+    my ($group, $passwd, $gid, $users) = split /:/;
+    foreach my $u (split /,/, $users) {
+      push @groups, $gid
+       if ($user eq $u);
+    }
+  }
+  $fh->close;
+
+  my $groups = join(" ", ($gid, $gid, @groups));
+  #print STDERR "[[$groups]]\n";
+  $! = 0;  # reset errno
+  $> = 0;
+  $( = $gid;
+  $) = $groups;
+  if ($!) {
+    return [ "su: $!\n" ];
+  }
+  if ($uid != 0) {
+    $> = $uid;
+    #$< = $uid;
+    if ($!) {
+      return [ "su: $prog->[1]: $!\n" ];
+    }
+  }
+  #print STDERR "[($>,$<)($(,$))]";
+  return [];
+}
+
+
+sub sg($) {
+  my ($group) = @_;
+
+  my $gid = getgrnam($group)
+    or return [ "sg: group $group does not exist\n" ];
+  my %groups = map { $_ eq $gid ? () : ($_ => 1) } (split /\s/, $));
+  
+  #print STDERR "<<", join("/", keys %groups), ">>\n";
+  my $groups = join(" ", ($gid, $gid, keys %groups));
+  #print STDERR "[[$groups]]\n";
+  $! = 0;  # reset errno
+  if ($> != 0) {
+         my $uid = $>;
+         $> = 0;
+         $( = $gid;
+         $) = $groups;
+         $> = $uid;
+  } else {
+         $( = $gid;
+         $) = $groups;
+  }
+  if ($!) {
+    return [ "sg: $!\n" ];
+  }
+  print STDERR "[($>,$<)($(,$))]";
+  return [];
+}
+
+
+sub exec_test($$) {
+  my ($prog, $in) = @_;
+  local (*IN, *IN_DUP, *IN2, *OUT_DUP, *OUT, *OUT2);
+  my $needs_shell = (join('', @$prog) =~ /[][|<>"'`\$\*\?]/);
+
+  if ($prog->[0] eq "umask") {
+    umask oct $prog->[1];
+    return [];
+  } elsif ($prog->[0] eq "cd") {
+    if (!chdir $prog->[1]) {
+      return [ "chdir: $prog->[1]: $!\n" ];
+    }
+    return [];
+  } elsif ($prog->[0] eq "su") {
+    return su($prog->[1]);
+  } elsif ($prog->[0] eq "sg") {
+    return sg($prog->[1]);
+  }
+
+  pipe *IN2, *OUT
+    or die "Can't create pipe for reading: $!";
+  open *IN_DUP, "<&STDIN"
+    or *IN_DUP = undef;
+  open *STDIN, "<&IN2"
+    or die "Can't duplicate pipe for reading: $!";
+  close *IN2;
+
+  open *OUT_DUP, ">&STDOUT"
+    or die "Can't duplicate STDOUT: $!";
+  pipe *IN, *OUT2
+    or die "Can't create pipe for writing: $!";
+  open *STDOUT, ">&OUT2"
+    or die "Can't duplicate pipe for writing: $!";
+  close *OUT2;
+
+  *STDOUT->autoflush();
+  *OUT->autoflush();
+
+  if (fork()) {
+    # Server
+    if (*IN_DUP) {
+      open *STDIN, "<&IN_DUP"
+        or die "Can't duplicate STDIN: $!";
+      close *IN_DUP
+        or die "Can't close STDIN duplicate: $!";
+    }
+    open *STDOUT, ">&OUT_DUP"
+      or die "Can't duplicate STDOUT: $!";
+    close *OUT_DUP
+      or die "Can't close STDOUT duplicate: $!";
+
+    foreach my $line (@$in) {
+      #print "> $line";
+      print OUT $line;
+    }
+    close *OUT
+      or die "Can't close pipe for writing: $!";
+
+    my $result = [];
+    while (<IN>) {
+      #print "< $_";
+      if ($needs_shell) {
+       s#^/bin/sh: line \d+: ##;
+       s#^/bin/sh: ##; # temporarily added by ericm
+      }
+      push @$result, $_;
+    }
+    return $result;
+  } else {
+    # Client
+    $< = $>;
+    close IN
+      or die "Can't close read end for input pipe: $!";
+    close OUT
+      or die "Can't close write end for output pipe: $!";
+    close OUT_DUP
+      or die "Can't close STDOUT duplicate: $!";
+    local *ERR_DUP;
+    open ERR_DUP, ">&STDERR"
+      or die "Can't duplicate STDERR: $!";
+    open STDERR, ">&STDOUT"
+      or die "Can't join STDOUT and STDERR: $!";
+
+    if ($needs_shell) {
+      exec ('/bin/sh', '-c', join(" ", @$prog));
+    } else {
+      exec @$prog;
+    }
+    print STDERR $prog->[0], ": $!\n";
+    exit;
+  }
+}
+
diff --git a/lustre/tests/rmtacl/setfacl.test b/lustre/tests/rmtacl/setfacl.test
new file mode 100644 (file)
index 0000000..14c473a
--- /dev/null
@@ -0,0 +1,144 @@
+Setfacl utility tests. Run these tests on a filesystem with ACL support.
+       $ mkdir d
+       $ chown bin:bin d
+       $ cd d
+
+       $ su bin
+       $ sg bin
+       $ umask 027
+       $ touch g
+       $ lfs ls -dl g | awk '{print $1}'
+       > -rw-r-----
+       
+       $ lfs lsetfacl -m m:- g
+       $ lfs ls -dl g | awk '{print $1}'
+       > -rw-------+
+       
+       $ lfs lgetfacl g
+       > # file: g
+       > # owner: bin
+       > # group: bin
+       > user::rw-
+       > group::r--    #effective:---
+       > mask::---
+       > other::---
+       > 
+       
+       $ lfs lsetfacl -x m g
+       $ lfs lgetfacl g
+       > # file: g
+       > # owner: bin
+       > # group: bin
+       > user::rw-
+       > group::r--
+       > other::---
+       > 
+       
+       $ lfs lsetfacl -m u:daemon:rw g
+       $ lfs lgetfacl g
+       > # file: g
+       > # owner: bin
+       > # group: bin
+       > user::rw-
+       > user:daemon:rw-
+       > group::r--
+       > mask::rw-
+       > other::---
+       > 
+       
+       $ lfs lsetfacl -m u::rwx,g::r-x,o:- g
+       $ lfs lgetfacl g
+       > # file: g
+       > # owner: bin
+       > # group: bin
+       > user::rwx
+       > user:daemon:rw-
+       > group::r-x
+       > mask::rwx
+       > other::---
+       > 
+       
+       $ lfs lsetfacl -m u::rwx,g::r-x,o:-,m:- g
+       $ lfs lgetfacl g
+       > # file: g
+       > # owner: bin
+       > # group: bin
+       > user::rwx
+       > user:daemon:rw-       #effective:---
+       > group::r-x    #effective:---
+       > mask::---
+       > other::---
+       > 
+       
+       $ lfs lsetfacl -m u::rwx,g::r-x,o:-,u:root:-,m:- g
+       $ lfs lgetfacl g
+       > # file: g
+       > # owner: bin
+       > # group: bin
+       > user::rwx
+       > user:root:---
+       > user:daemon:rw-       #effective:---
+       > group::r-x    #effective:---
+       > mask::---
+       > other::---
+       > 
+       
+       $ lfs lsetfacl -m u::rwx,g::r-x,o:-,u:root:-,m:- g
+       $ lfs lgetfacl g
+       > # file: g
+       > # owner: bin
+       > # group: bin
+       > user::rwx
+       > user:root:---
+       > user:daemon:rw-       #effective:---
+       > group::r-x    #effective:---
+       > mask::---
+       > other::---
+       > 
+       
+       $ lfs lsetfacl -m u::rwx,g::r-x,o:-,u:root:- g
+       $ lfs lgetfacl g
+       > # file: g
+       > # owner: bin
+       > # group: bin
+       > user::rwx
+       > user:root:---
+       > user:daemon:rw-
+       > group::r-x
+       > mask::rwx
+       > other::---
+       > 
+       
+       $ lfs lsetfacl --test -x u: g
+       > setfacl: g: Malformed access ACL `user:root:---,user:daemon:rw-,group::r-x,mask::rwx,other::---': Missing or wrong entry at entry 1
+       
+       $ lfs lsetfacl --test -x u:x
+       > setfacl: Option -x: Invalid argument near character 3
+       
+       $ lfs lsetfacl -m d:u:root:rwx g
+       > setfacl: g: Only directories can have default ACLs
+       
+       $ lfs lsetfacl -x m g
+       > setfacl: g: Malformed access ACL `user::rwx,user:root:---,user:daemon:rw-,group::r-x,other::---': Missing or wrong entry at entry 5
+        lfs lsetfacl --test -m d:u:daemon:rwx lfs lsetfacl
+        lfs lsetfacl --test -n -m d:u:daemon:rwx lfs lsetfacl
+       
+Check if the mask is properly recalculated
+       $ mkdir d
+       $ lfs lsetfacl --test -m u::rwx,u:bin:rwx,g::r-x,o::--- d
+       > d: u::rwx,u:bin:rwx,g::r-x,m::rwx,o::---,*
+       
+       $ lfs lsetfacl --test -m u::rwx,u:bin:rwx,g::r-x,m::---,o::--- d
+       > d: u::rwx,u:bin:rwx,g::r-x,m::---,o::---,*
+       
+       $ lfs lsetfacl --test -d -m u::rwx,u:bin:rwx,g::r-x,o::--- d
+       > d: *,d:u::rwx,d:u:bin:rwx,d:g::r-x,d:m::rwx,d:o::---
+       
+       $ lfs lsetfacl --test -d -m u::rwx,u:bin:rwx,g::r-x,m::---,o::--- d
+       > d: *,d:u::rwx,d:u:bin:rwx,d:g::r-x,d:m::---,d:o::---
+       
+       $ su
+       $ cd ..
+       $ rm -r d
index 4e3111a..69d23c7 100644 (file)
@@ -9,15 +9,12 @@ set -e
 
 ONLY=${ONLY:-"$*"}
 # bug number for skipped test:
 
 ONLY=${ONLY:-"$*"}
 # bug number for skipped test:
-ALWAYS_EXCEPT=${ALWAYS_EXCEPT:-""}
+ALWAYS_EXCEPT=${ALWAYS_EXCEPT:-"$SANITY_GSS_EXCEPT"}
 # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
 # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
-if [ "x$GSS_PIPEFS" != "xy" ]; then
-    ALWAYS_EXCEPT="$ALWAYS_EXCEPT 4"
-fi
 
 
-[ "$SLOW" = "no" ] && EXCEPT="$EXCEPT"
+[ "$SLOW" = "no" ] && EXCEPT_SLOW="100 101"
 
 
-# Tests that fail on uml, maybe elsewhere, FIXME
+# Tests that fail on uml
 CPU=`awk '/model/ {print $4}' /proc/cpuinfo`
 [ "$CPU" = "UML" ] && EXCEPT="$EXCEPT"
 
 CPU=`awk '/model/ {print $4}' /proc/cpuinfo`
 [ "$CPU" = "UML" ] && EXCEPT="$EXCEPT"
 
@@ -28,17 +25,16 @@ esac
 
 SRCDIR=`dirname $0`
 export PATH=$PWD/$SRCDIR:$SRCDIR:$SRCDIR/../utils:$SRCDIR/../utils/gss:$PATH:/sbin
 
 SRCDIR=`dirname $0`
 export PATH=$PWD/$SRCDIR:$SRCDIR:$SRCDIR/../utils:$SRCDIR/../utils/gss:$PATH:/sbin
+export NAME=${NAME:-local}
+SAVE_PWD=$PWD
 
 
-TMP=${TMP:-/tmp}
+CLEANUP=${CLEANUP:-""}
+SETUP=${SETUP:-""}
 
 
-CHECKSTAT=${CHECKSTAT:-"checkstat -v"}
-CREATETEST=${CREATETEST:-createtest}
-LFS=${LFS:-lfs}
-LCTL=${LCTL:-lctl}
-MEMHOG=${MEMHOG:-memhog}
-DIRECTIO=${DIRECTIO:-directio}
-ACCEPTOR_PORT=${ACCEPTOR_PORT:-988}
-UMOUNT=${UMOUNT:-"umount -d"}
+LUSTRE=${LUSTRE:-`dirname $0`/..}
+. $LUSTRE/tests/test-framework.sh
+init_test_env $@
+. ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
 
 if [ $UID -ne 0 ]; then
     echo "Warning: running as non-root uid $UID"
 
 if [ $UID -ne 0 ]; then
     echo "Warning: running as non-root uid $UID"
@@ -49,96 +45,315 @@ else
     RUNAS=${RUNAS:-"runas -u $RUNAS_ID"}
 
     # $RUNAS_ID may get set incorrectly somewhere else
     RUNAS=${RUNAS:-"runas -u $RUNAS_ID"}
 
     # $RUNAS_ID may get set incorrectly somewhere else
-    if [ $RUNAS_ID -eq 0 ]; then
-        echo "Error: \$RUNAS_ID set to 0, but \$UID is also 0!"
-        exit 1
-    fi
+    [ $RUNAS_ID -eq 0 ] && error "\$RUNAS_ID set to 0, but \$UID is also 0!"
 fi
 
 fi
 
-SANITYLOG=${SANITYLOG:-/tmp/sanity-gss.log}
-
-export NAME=${NAME:-local}
-
-SAVE_PWD=$PWD
-
-export SEC=${SEC:-krb5p}
-export KRB5_CCACHE_DIR=/tmp
-export KRB5_CRED=$KRB5_CCACHE_DIR/krb5cc_$RUNAS_ID
-export KRB5_CRED_SAVE=$KRB5_CCACHE_DIR/krb5cc.sanity.save
+# remove $SEC, we'd like to control everything by ourselves
+unset SEC
 
 #
 
 #
-# check pre-set $SEC
+# global variables of this sanity
 #
 #
-case "x$SEC" in
-    xkrb5*)
-        echo "Using ptlrpc security flavor $SEC"
-        ;;
-    *)
-        echo "SEC=$SEC is invalid, it has to be gss/krb5 flavor"
-        exit 1
-        ;;
-esac
+KRB5_CCACHE_DIR=/tmp
+KRB5_CRED=$KRB5_CCACHE_DIR/krb5cc_$RUNAS_ID
+KRB5_CRED_SAVE=$KRB5_CCACHE_DIR/krb5cc.sanity.save
+CLICOUNT=2
+cnt_mdt2ost=0
+cnt_mdt2mdt=0
+cnt_cli2ost=0
+cnt_cli2mdt=0
+cnt_all2ost=0
+cnt_all2mdt=0
+cnt_all2all=0
+DBENCH_PID=0
+PROC_CLI="srpc.info"
+
+# set manually
+GSS=true
+GSS_KRB5=true
+
+# we want double mount
+MOUNT_2=${MOUNT_2:-"yes"}
+cleanup_and_setup_lustre
+
+rm -rf $DIR/${TESTSUITE}/[df][0-9]*
+rm -rf $DIR/[df][0-9]*
+
+check_runas_id $RUNAS_ID $RUNAS
 
 
-LUSTRE=${LUSTRE:-`dirname $0`/..}
-. $LUSTRE/tests/test-framework.sh
-init_test_env $@
-. ${CONFIG:=$LUSTRE/tests/cfg/local.sh}
+build_test_filter
 
 prepare_krb5_creds() {
 
 prepare_krb5_creds() {
-    rm -f $CRED_SAVE
+    rm -f $KRB5_CRED_SAVE
     $RUNAS krb5_login.sh || exit 1
     [ -f $KRB5_CRED ] || exit 2
     cp $KRB5_CRED $KRB5_CRED_SAVE
 }
 
     $RUNAS krb5_login.sh || exit 1
     [ -f $KRB5_CRED ] || exit 2
     cp $KRB5_CRED $KRB5_CRED_SAVE
 }
 
-cleanup() {
-    echo -n "cln.."
-    cleanupall ${FORCE} $* || { echo "FAILed to clean up"; exit 20; }
+combination()
+{
+    local M=$1
+    local N=$2
+    local R=1
+
+    if [ $M -lt $N ]; then
+        R=0
+    else
+        N=$((N + 1))
+        while [ $N -le $M ]; do
+            R=$((R * N))
+            N=$((N + 1))
+        done
+    fi
+
+    echo $R
+    return 0
 }
 }
-CLEANUP=${CLEANUP:-:}
 
 
-setup() {
-    echo -n "mnt.."
-    load_modules
-    setupall || exit 10
-    echo "done"
+calc_connection_cnt() {
+    # MDT->MDT = 2 * C(M, 2)
+    # MDT->OST = M * O
+    # CLI->OST = C * O
+    # CLI->MDT = C * M
+    comb_m2=$(combination $MDSCOUNT 2)
+
+    cnt_mdt2mdt=$((comb_m2 * 2))
+    cnt_mdt2ost=$((MDSCOUNT * OSTCOUNT))
+    cnt_cli2ost=$((CLICOUNT * OSTCOUNT))
+    cnt_cli2mdt=$((CLICOUNT * MDSCOUNT))
+    cnt_all2ost=$((cnt_mdt2ost + cnt_cli2ost))
+    cnt_all2mdt=$((cnt_mdt2mdt + cnt_cli2mdt))
+    cnt_all2all=$((cnt_mdt2ost + cnt_mdt2mdt + cnt_cli2ost + cnt_cli2mdt))
 }
 }
-SETUP=${SETUP:-:}
 
 
-trace() {
-    log "STARTING: $*"
-    strace -o $TMP/$1.strace -ttt $*
-    RC=$?
-    log "FINISHED: $*: rc $RC"
-    return 1
+set_rule()
+{
+    local tgt=$1
+    local net=$2
+    local dir=$3
+    local flavor=$4
+    local cmd="$tgt.srpc.flavor"
+
+    if [ $net == "any" ]; then
+        net="default"
+    fi
+    cmd="$cmd.$net"
+
+    if [ $dir != "any" ]; then
+        cmd="$cmd.$dir"
+    fi
+
+    cmd="$cmd=$flavor"
+    log "Setting sptlrpc rule: $cmd"
+    do_facet mgs "$LCTL conf_param $cmd"
+}
+
+count_flvr()
+{
+    output=$1
+    flavor=$2
+
+    echo "$output" | grep rpc | grep $flavor | wc -l
 }
 }
-TRACE=${TRACE:-""}
 
 
-check_kernel_version() {
-    VERSION_FILE=$LPROC/kernel_version
-    WANT_VER=$1
-    [ ! -f $VERSION_FILE ] && echo "can't find kernel version" && return 1
-    GOT_VER=`cat $VERSION_FILE`
-    [ $GOT_VER -ge $WANT_VER ] && return 0
-    log "test needs at least kernel version $WANT_VER, running $GOT_VER"
+flvr_cnt_cli2mdt()
+{
+    local flavor=$1
+
+    output=`do_facet client cat $LPROC/mdc/*-MDT*-mdc-*/$PROC_CLI 2>/dev/null`
+    count_flvr "$output" $flavor
+}
+
+flvr_cnt_cli2ost()
+{
+    local flavor=$1
+
+    output=`do_facet client cat $LPROC/osc/*OST*-osc-[^M][^D][^T]*/$PROC_CLI 2>/dev/null`
+    count_flvr "$output" $flavor
+}
+
+flvr_cnt_mdt2mdt()
+{
+    local flavor=$1
+    local cnt=0
+
+    if [ $MDSCOUNT -le 1 ]; then
+        echo 0
+        return
+    fi
+
+    for num in `seq $MDSCOUNT`; do
+        output=`do_facet mds$num cat $LPROC/mdc/*-MDT*-mdc[0-9]*/$PROC_CLI 2>/dev/null`
+        tmpcnt=`count_flvr "$output" $flavor`
+        cnt=$((cnt + tmpcnt))
+    done
+    echo $cnt;
+}
+
+flvr_cnt_mdt2ost()
+{
+    local flavor=$1
+    local cnt=0
+
+    for num in `seq $MDSCOUNT`; do
+        output=`do_facet mds$num cat $LPROC/osc/*OST*-osc-MDT*/$PROC_CLI 2>/dev/null`
+        tmpcnt=`count_flvr "$output" $flavor`
+        cnt=$((cnt + tmpcnt))
+    done
+    echo $cnt;
+}
+
+do_check_flavor()
+{
+    local dir=$1        # from to
+    local flavor=$2     # flavor expected
+    local res=0
+
+    if [ $dir == "cli2mdt" ]; then
+        res=`flvr_cnt_cli2mdt $flavor`
+    elif [ $dir == "cli2ost" ]; then
+        res=`flvr_cnt_cli2ost $flavor`
+    elif [ $dir == "mdt2mdt" ]; then
+        res=`flvr_cnt_mdt2mdt $flavor`
+    elif [ $dir == "mdt2ost" ]; then
+        res=`flvr_cnt_mdt2ost $flavor`
+    elif [ $dir == "all2ost" ]; then
+        res1=`flvr_cnt_mdt2ost $flavor`
+        res2=`flvr_cnt_cli2ost $flavor`
+        res=$((res1 + res2))
+    elif [ $dir == "all2mdt" ]; then
+        res1=`flvr_cnt_mdt2mdt $flavor`
+        res2=`flvr_cnt_cli2mdt $flavor`
+        res=$((res1 + res2))
+    elif [ $dir == "all2all" ]; then
+        res1=`flvr_cnt_mdt2ost $flavor`
+        res2=`flvr_cnt_cli2ost $flavor`
+        res3=`flvr_cnt_mdt2mdt $flavor`
+        res4=`flvr_cnt_cli2mdt $flavor`
+        res=$((res1 + res2 + res3 + res4))
+    fi
+
+    echo $res
+}
+
+wait_flavor()
+{
+    local dir=$1        # from to
+    local flavor=$2     # flavor expected
+    local expect=$3     # number expected
+    local res=0
+
+    for ((i=0;i<20;i++)); do
+        echo -n "checking..."
+        res=$(do_check_flavor $dir $flavor)
+        if [ $res -eq $expect ]; then
+            echo "found $res $flavor connections of $dir, OK"
+            return 0
+        else
+            echo "found $res $flavor connections of $dir, not ready ($expect)"
+            sleep 4
+        fi
+    done
+
+    echo "Error checking $flavor of $dir: expect $expect, actual $res"
     return 1
 }
 
     return 1
 }
 
-_basetest() {
-    echo $*
+restore_to_default_flavor()
+{
+    local proc=$LPROC/mgs/MGS/live/$FSNAME
+
+    echo "restoring to default flavor..."
+
+    nrule=`do_facet mgs cat $proc 2>/dev/null | grep "$FSNAME.srpc.flavor." | wc -l`
+
+    # remove all existing rules if any
+    if [ $nrule -ne 0 ]; then
+        echo "remove existing $nrule rules"
+        for rule in `do_facet mgs cat $proc 2>/dev/null | grep "$FSNAME.srpc.flavor."`; do
+            spec=`echo $rule | awk -F = '{print $1}'`
+            do_facet mgs "$LCTL conf_param $spec="
+        done
+    fi
+
+    # verify no rules left
+    nrule=`do_facet mgs cat $proc 2>/dev/null | grep "$FSNAME.srpc.flavor." | wc -l`
+    [ $nrule -ne 0 ] && error "still $nrule rules left"
+
+    # wait for default flavor to be applied
+    # currently default flavor for all connections are 'null'
+    wait_flavor all2all null $cnt_all2all
+    echo "now at default flavor settings"
 }
 
 }
 
-[ "$SANITYLOG" ] && rm -f $SANITYLOG || true
+set_flavor_all()
+{
+    local flavor=$1
 
 
+    echo "setting all flavor to $flavor"
 
 
-prepare_krb5_creds
-build_test_filter
-umask 077
+    res=$(do_check_flavor all2all $flavor)
+    if [ $res -eq $cnt_all2all ]; then
+        echo "already have total $res $flavor connections"
+        return
+    fi
 
 
-# setup filesystem
-formatall
-setupall
-chmod a+rwx $MOUNT
+    echo "found $res $flavor out of total $cnt_all2all connections"
+    restore_to_default_flavor
+
+    set_rule $FSNAME any any $flavor
+    wait_flavor all2all $flavor $cnt_all2all
+}
+
+start_dbench()
+{
+    NPROC=`cat /proc/cpuinfo 2>/dev/null | grep ^processor | wc -l`
+    [ $NPROC -lt 2 ] && NPROC=2
+    sh rundbench $NPROC 1>/dev/null &
+    DBENCH_PID=$!
+    sleep 2
+
+    num=`ps --no-headers -p $DBENCH_PID 2>/dev/null | wc -l`
+    if [ $num -ne 1 ]; then
+        error "failed to start dbench $NPROC"
+    else
+        echo "started dbench with $NPROC processes at background"
+    fi
+
+    return 0
+}
+
+check_dbench()
+{
+    num=`ps --no-headers -p $DBENCH_PID 2>/dev/null | wc -l`
+    if [ $num -eq 0 ]; then
+        echo "dbench $DBENCH_PID already finished"
+        wait $DBENCH_PID || error "dbench $PID exit with error"
+        start_dbench
+    elif [ $num -ne 1 ]; then
+        killall -9 dbench
+        error "found $num instance of pid $DBENCH_PID ???"
+    fi
+
+    return 0
+}
+
+stop_dbench()
+{
+    for ((;;)); do
+        killall dbench 2>/dev/null
+        num=`ps --no-headers -p $DBENCH_PID | wc -l`
+        if [ $num -eq 0 ]; then
+            echo "dbench finished"
+            break
+        fi
+        echo "dbench $DBENCH_PID is still running, waiting 2s..."
+        sleep 2
+    done
+
+    wait $DBENCH_PID || true
+    sync || true
+}
 
 restore_krb5_cred() {
     cp $KRB5_CRED_SAVE $KRB5_CRED
 
 restore_krb5_cred() {
     cp $KRB5_CRED_SAVE $KRB5_CRED
@@ -146,37 +361,102 @@ restore_krb5_cred() {
     chmod 0600 $KRB5_CRED
 }
 
     chmod 0600 $KRB5_CRED
 }
 
+check_multiple_gss_daemons() {
+    local facet=$1
+    local gssd=$2
+    local gssd_name=`basename $gssd`
+
+    for ((i=0;i<10;i++)); do
+        do_facet $facet "$gssd -v &"
+    done
+
+    # wait daemons entering "stable" status
+    sleep 5
+
+    num=`do_facet $facet ps -o cmd -C $gssd_name | grep $gssd_name | wc -l`
+    echo "$num instance(s) of $gssd_name are running"
+
+    if [ $num -ne 1 ]; then
+        error "$gssd_name not unique"
+    fi
+}
+
+prepare_krb5_creds
+calc_connection_cnt
+umask 077
+
+test_0() {
+    local my_facet=mds
+
+    echo "bring up gss daemons..."
+    start_gss_daemons
+
+    echo "check with someone already running..."
+    check_multiple_gss_daemons $my_facet $LSVCGSSD
+    if $GSS_PIPEFS; then
+        check_multiple_gss_daemons $my_facet $LGSSD
+    fi
+
+    echo "check with someone run & finished..."
+    do_facet $my_facet killall -q -2 lgssd lsvcgssd || true
+    sleep 5 # wait fully exit
+    check_multiple_gss_daemons $my_facet $LSVCGSSD
+    if $GSS_PIPEFS; then
+        check_multiple_gss_daemons $my_facet $LGSSD
+    fi
+
+    echo "check refresh..."
+    do_facet $my_facet killall -q -2 lgssd lsvcgssd || true
+    sleep 5 # wait fully exit
+    do_facet $my_facet ipcrm -S 0x3b92d473
+    check_multiple_gss_daemons $my_facet $LSVCGSSD
+    if $GSS_PIPEFS; then
+        do_facet $my_facet ipcrm -S 0x3a92d473
+        check_multiple_gss_daemons $my_facet $LGSSD
+    fi
+}
+run_test 0 "start multiple gss daemons"
+
+set_flavor_all krb5p
+
 test_1() {
 test_1() {
+    local file=$DIR/$tfile
+
+    chmod 0777 $DIR || error "chmod $DIR failed"
     # access w/o cred
     $RUNAS kdestroy
     # access w/o cred
     $RUNAS kdestroy
-    $RUNAS touch $MOUNT/f1 && error "unexpected success"
+    $RUNAS touch $file && error "unexpected success"
 
     # access w/ cred
     restore_krb5_cred
 
     # access w/ cred
     restore_krb5_cred
-    $RUNAS touch $MOUNT/f1 || error "should not fail"
-    [ -f $MOUNT/f1 ] || error "$MOUNT/f1 not found"
+    $RUNAS touch $file || error "should not fail"
+    [ -f $file ] || error "$file not found"
 }
 run_test 1 "access with or without krb5 credential"
 
 test_2() {
 }
 run_test 1 "access with or without krb5 credential"
 
 test_2() {
+    local file1=$DIR/$tfile-1
+    local file2=$DIR/$tfile-2
+
+    chmod 0777 $DIR || error "chmod $DIR failed"
     # current access should be ok
     # current access should be ok
-    $RUNAS touch $MOUNT/f2_1 || error "can't touch $MOUNT/f2_1"
-    [ -f $MOUNT/f2_1 ] || error "$MOUNT/f2_1 not found"
+    $RUNAS touch $file1 || error "can't touch $file1"
+    [ -f $file1 ] || error "$file1 not found"
 
     # cleanup all cred/ctx and touch
     $RUNAS kdestroy
     $RUNAS $LFS flushctx || error "can't flush ctx"
 
     # cleanup all cred/ctx and touch
     $RUNAS kdestroy
     $RUNAS $LFS flushctx || error "can't flush ctx"
-    $RUNAS touch $MOUNT/f2_2 && error "unexpected success"
+    $RUNAS touch $file2 && error "unexpected success"
 
     # restore and touch
     restore_krb5_cred
 
     # restore and touch
     restore_krb5_cred
-    $RUNAS touch $MOUNT/f2_2 || error "should not fail"
-    [ -f $MOUNT/f2_2 ] || error "$MOUNT/f2_2 not found"
+    $RUNAS touch $file2 || error "should not fail"
+    [ -f $file2 ] || error "$file2 not found"
 }
 run_test 2 "lfs flushctx"
 
 test_3() {
 }
 run_test 2 "lfs flushctx"
 
 test_3() {
-    local file=$MOUNT/f3
+    local file=$DIR/$tfile
 
     # create file
     echo "aaaaaaaaaaaaaaaaa" > $file
 
     # create file
     echo "aaaaaaaaaaaaaaaaa" > $file
@@ -215,9 +495,12 @@ test_3() {
 run_test 3 "local cache under DLM lock"
 
 test_4() {
 run_test 3 "local cache under DLM lock"
 
 test_4() {
-    local file1=$MOUNT/f4_1
-    local file2=$MOUNT/f4_2
+    local file1=$DIR/$tfile-1
+    local file2=$DIR/$tfile-2
 
 
+    ! $GSS_PIPEFS && skip "pipefs not used" && return
+
+    chmod 0777 $DIR || error "chmod $DIR failed"
     # current access should be ok
     $RUNAS touch $file1 || error "can't touch $file1"
     [ -f $file1 ] || error "$file1 not found"
     # current access should be ok
     $RUNAS touch $file1 || error "can't touch $file1"
     [ -f $file1 ] || error "$file1 not found"
@@ -246,10 +529,11 @@ test_4() {
 run_test 4 "lgssd dead, operations should wait timeout and fail"
 
 test_5() {
 run_test 4 "lgssd dead, operations should wait timeout and fail"
 
 test_5() {
-    local file1=$MOUNT/f5_1
-    local file2=$MOUNT/f5_2
-    local wait_time=`expr $TIMEOUT + $TIMEOUT`
+    local file1=$DIR/$tfile-1
+    local file2=$DIR/$tfile-2
+    local wait_time=$((TIMEOUT + TIMEOUT / 2))
 
 
+    chmod 0777 $DIR || error "chmod $DIR failed"
     # current access should be ok
     $RUNAS touch $file1 || error "can't touch $file1"
     [ -f $file1 ] || error "$file1 not found"
     # current access should be ok
     $RUNAS touch $file1 || error "can't touch $file1"
     [ -f $file1 ] || error "$file1 not found"
@@ -282,26 +566,15 @@ test_5() {
 run_test 5 "lsvcgssd dead, operations lead to recovery"
 
 test_6() {
 run_test 5 "lsvcgssd dead, operations lead to recovery"
 
 test_6() {
-    NPROC=`cat /proc/cpuinfo 2>/dev/null | grep ^processor | wc -l`
-    [ $NPROC -ne 0 ] || NPROC=2
-
-    echo "starting dbench $NPROC"
-    sh rundbench $NPROC &
-    RUNPID=$!
-
-    for ((n=0;;n++)); do
-        sleep 2
-        num=`ps --no-headers -p $RUNPID | wc -l`
-        [ $num -ne 0 ] || break
-        echo "flush ctx ..."
-        $LFS flushctx
-    done
-    wait $RUNPID || error "dbench detect error"
+    mkdir $DIR/d6 || error "mkdir $DIR/d6 failed"
+    cp -a /etc/* $DIR/d6/ || error "cp failed"
+    ls -l $DIR/d6/* > /dev/null || error "ls failed"
+    rm -rf $DIR2/d6/* || error "rm failed"
 }
 }
-run_test 6 "recoverable from losing context"
+run_test 6 "test basic DLM callback works"
 
 test_7() {
 
 test_7() {
-    local tdir=$MOUNT/dir7
+    local tdir=$DIR/d7
     local num_osts
 
     #
     local num_osts
 
     #
@@ -333,74 +606,298 @@ test_7() {
 }
 run_test 7 "exercise enlarge_reqbuf()"
 
 }
 run_test 7 "exercise enlarge_reqbuf()"
 
-check_multiple_gss_daemons() {
-    local facet=$1
-    local gssd=$2
-    local gssd_name=`basename $gssd`
+test_90() {
+    if [ "$SLOW" = "no" ]; then
+        total=10
+    else
+        total=60
+    fi
 
 
-    for ((i=0;i<10;i++)); do
-        do_facet $facet "$gssd -v &"
+    start_dbench
+
+    for ((n=0;n<$total;n++)); do
+        sleep 2
+        check_dbench
+        echo "flush ctx ($n/$total) ..."
+        $LFS flushctx
     done
     done
+    check_dbench
+    stop_dbench
+}
+run_test 90 "recoverable from losing contexts under load"
 
 
-    # wait daemons entering "stable" status
-    sleep 5
+test_99() {
+    local nrule_old=0
+    local nrule_new=0
+    local max=32
 
 
-    num=`do_facet $facet ps -o cmd -C $gssd_name | grep $gssd_name | wc -l`
-    echo "$num instance(s) of $gssd_name are running"
+    #
+    # general rules
+    #
+    nrule_old=`do_facet mgs cat $LPROC/mgs/MGS/live/$FSNAME 2>/dev/null \
+               | grep "$FSNAME.srpc.flavor." | wc -l`
+    echo "original general rules: $nrule_old"
 
 
-    if [ $num -ne 1 ]; then
-        error "$gssd_name not unique"
+    for ((i = $nrule_old; i < $max; i++)); do
+        set_rule $FSNAME elan$i any krb5n || error "set rule $i"
+    done
+    set_rule $FSNAME elan100 any krb5n && error "set $max rule should fail"
+    for ((i = $nrule_old; i < $max; i++)); do
+        set_rule $FSNAME elan$i any || error "remove rule $i"
+    done
+
+    nrule_new=`do_facet mgs cat $LPROC/mgs/MGS/live/$FSNAME 2>/dev/null \
+               | grep "$FSNAME.srpc.flavor." | wc -l`
+    if [ $nrule_new != $nrule_old ]; then
+        error "general rule: $nrule_new != $nrule_old"
     fi
     fi
+
+    #
+    # target-specific rules
+    #
+    nrule_old=`do_facet mgs cat $LPROC/mgs/MGS/live/$FSNAME 2>/dev/null \
+               | grep "$FSNAME-MDT0000.srpc.flavor." | wc -l`
+    echo "original target rules: $nrule_old"
+
+    for ((i = $nrule_old; i < $max; i++)); do
+        set_rule $FSNAME-MDT0000 elan$i any krb5i || error "set rule $i"
+    done
+    set_rule $FSNAME-MDT0000 elan100 any krb5i && error "set $max rule should fail"
+    for ((i = $nrule_old; i < $max; i++)); do
+        set_rule $FSNAME-MDT0000 elan$i any || error "remove rule $i"
+    done
+
+    nrule_new=`do_facet mgs cat $LPROC/mgs/MGS/live/$FSNAME 2>/dev/null \
+               | grep "$FSNAME-MDT0000.srpc.flavor." | wc -l`
+    if [ $nrule_new != $nrule_old ]; then
+        error "general rule: $nrule_new != $nrule_old"
+    fi
+}
+run_test 99 "maximum sptlrpc rules limitation"
+
+error_dbench()
+{
+    local err_str=$1
+
+    killall -9 dbench
+    sleep 1
+
+    error $err_str
 }
 
 test_100() {
 }
 
 test_100() {
-    local facet=mds
+    # started from default flavors
+    restore_to_default_flavor
 
 
-    # cleanup everything at first
-    cleanupall
+    # running dbench background
+    start_dbench
 
 
-    echo "bring up gss daemons..."
-    start_gss_daemons
+    #
+    # all: null -> krb5n -> krb5a -> krb5i -> krb5p -> plain
+    #
+    set_rule $FSNAME any any krb5n
+    wait_flavor all2all krb5n $cnt_all2all || error_dbench "1"
+    check_dbench
 
 
-    echo "check with someone already running..."
-    check_multiple_gss_daemons $facet $LSVCGSSD
-    if [ "x$GSS_PIPEFS" == "xy" ]; then
-        check_multiple_gss_daemons $facet $LGSSD
-    fi
+    set_rule $FSNAME any any krb5a
+    wait_flavor all2all krb5a $cnt_all2all || error_dbench "2"
+    check_dbench
 
 
-    echo "check with someone run & finished..."
-    do_facet $facet killall -q -2 lgssd lsvcgssd || true
-    sleep 5 # wait fully exit
-    check_multiple_gss_daemons $facet $LSVCGSSD
-    if [ "x$GSS_PIPEFS" == "xy" ]; then
-        check_multiple_gss_daemons $facet $LGSSD
-    fi
+    set_rule $FSNAME any any krb5i
+    wait_flavor all2all krb5i $cnt_all2all || error_dbench "3"
+    check_dbench
 
 
-    echo "check refresh..."
-    do_facet $facet killall -q -2 lgssd lsvcgssd || true
-    sleep 5 # wait fully exit
-    do_facet $facet ipcrm -S 0x3b92d473
-    check_multiple_gss_daemons $facet $LSVCGSSD
-    if [ "x$GSS_PIPEFS" == "xy" ]; then
-        do_facet $facet ipcrm -S 0x3a92d473
-        check_multiple_gss_daemons $facet $LGSSD
+    set_rule $FSNAME any any krb5p
+    wait_flavor all2all krb5p $cnt_all2all || error_dbench "4"
+    check_dbench
+
+    set_rule $FSNAME any any plain
+    wait_flavor all2all plain $cnt_all2all || error_dbench "5"
+    check_dbench
+
+    #
+    # M - M: krb5a
+    # C - M: krb5i
+    # M - O: krb5p
+    # C - O: krb5n
+    #
+    set_rule $FSNAME any mdt2mdt krb5a
+    wait_flavor mdt2mdt krb5a $cnt_mdt2mdt || error_dbench "6"
+    check_dbench
+
+    set_rule $FSNAME any cli2mdt krb5i
+    wait_flavor cli2mdt krb5i $cnt_cli2mdt || error_dbench "7"
+    check_dbench
+
+    set_rule $FSNAME any mdt2ost krb5p
+    wait_flavor mdt2ost krb5p $cnt_mdt2ost || error_dbench "8"
+    check_dbench
+
+    set_rule $FSNAME any cli2ost krb5n
+    wait_flavor cli2ost krb5n $cnt_cli2ost || error_dbench "9"
+    check_dbench
+
+    #
+    # * - MDT0: krb5p
+    # * - OST0: krb5i
+    #
+    # nothing should be changed because they are override by above dir rules
+    #
+    set_rule $FSNAME-MDT0000 any any krb5p
+    set_rule $FSNAME-OST0000 any any krb5i
+    wait_flavor mdt2mdt krb5a $cnt_mdt2mdt || error_dbench "10"
+    wait_flavor cli2mdt krb5i $cnt_cli2mdt || error_dbench "11"
+    check_dbench
+    wait_flavor mdt2ost krb5p $cnt_mdt2ost || error_dbench "12"
+    wait_flavor cli2ost krb5n $cnt_cli2ost || error_dbench "13"
+
+    #
+    # delete all dir-specific rules
+    #
+    set_rule $FSNAME any mdt2mdt
+    set_rule $FSNAME any cli2mdt
+    set_rule $FSNAME any mdt2ost
+    set_rule $FSNAME any cli2ost
+    wait_flavor mdt2mdt krb5p $((MDSCOUNT - 1)) || error_dbench "14"
+    wait_flavor cli2mdt krb5p $CLICOUNT || error_dbench "15"
+    check_dbench
+    wait_flavor mdt2ost krb5i $MDSCOUNT || error_dbench "16"
+    wait_flavor cli2ost krb5i $CLICOUNT || error_dbench "17"
+    check_dbench
+
+    #
+    # remove:
+    #  * - MDT0: krb5p
+    #  * - OST0: krb5i
+    #
+    set_rule $FSNAME-MDT0000 any any
+    set_rule $FSNAME-OST0000 any any || error_dbench "18"
+    wait_flavor all2all plain $cnt_all2all || error_dbench "19"
+    check_dbench
+
+    stop_dbench
+}
+run_test 100 "change security flavor on the fly under load"
+
+switch_sec_test()
+{
+    local count=$1
+    local flavor0=$2
+    local flavor1=$3
+    local flavor2=$4
+    local df_pid=0
+    local wait_time=$((TIMEOUT + TIMEOUT / 4))
+    local num
+
+    #
+    # stop gss daemon, then switch to flavor1 (which should be a gss flavor),
+    # and run a 'df' which should hanging, wait the request timeout and
+    # resend, then switch the flavor to another one. To exercise the code of
+    # switching ctx/sec for a resend request.
+    #
+    echo ">>>>>>>>>>>>>>> Testing $flavor0 -> $flavor1 -> $flavor2..."
+
+    echo "(0) set base flavor $flavor0"
+    set_rule $FSNAME any cli2mdt $flavor0
+    wait_flavor cli2mdt $flavor0 $count
+    df $MOUNT
+    if [ $? -ne 0 ]; then
+        error "initial df failed"
     fi
 
     stop_gss_daemons
     fi
 
     stop_gss_daemons
+    sleep 1
+
+    echo "(1) $flavor0 -> $flavor1"
+    set_rule $FSNAME any cli2mdt $flavor1
+    wait_flavor cli2mdt $flavor1 $count
+    df $MOUNT &
+    df_pid=$!
+    sleep 1
+
+    echo "waiting $wait_time seconds for df ($df_pid)"
+    sleep $wait_time
+    num=`ps --no-headers -p $df_pid 2>/dev/null | wc -l`
+    [ $num -eq 1 ] || error "df already ended ($num)"
+    echo "process $df_pid is still hanging there... OK"
+
+    echo "(2) set end flavor $flavor2"
+    set_rule $FSNAME any cli2mdt $flavor2
+    wait_flavor cli2mdt $flavor2 $count
+    start_gss_daemons
+    wait $df_pid || error "df returned error"
 }
 }
-run_test 100 "start multiple gss daemons"
 
 
-TMPDIR=$OLDTMPDIR
-TMP=$OLDTMP
-HOME=$OLDHOME
+test_101()
+{
+    # started from default flavors
+    restore_to_default_flavor
+
+    switch_sec_test $cnt_cli2mdt null krb5n null
+    switch_sec_test $cnt_cli2mdt null krb5a null
+    switch_sec_test $cnt_cli2mdt null krb5i null
+    switch_sec_test $cnt_cli2mdt null krb5p null
+    switch_sec_test $cnt_cli2mdt null krb5i plain
+    switch_sec_test $cnt_cli2mdt plain krb5p plain
+    switch_sec_test $cnt_cli2mdt plain krb5n krb5a
+    switch_sec_test $cnt_cli2mdt krb5a krb5i krb5p
+    switch_sec_test $cnt_cli2mdt krb5p krb5a krb5n
+    switch_sec_test $cnt_cli2mdt krb5n krb5p krb5i
+}
+run_test 101 "switch ctx as well as sec for resending request"
 
 
-log "cleanup: ======================================================"
-if [ "`mount | grep ^$NAME`" ]; then
-    rm -rf $DIR/[Rdfs][1-9]*
-fi
+error_102()
+{
+    local err_str=$1
 
 
-cleanupall -f || error "cleanup failed"
+    killall -9 dbench
+    sleep 1
 
 
+    error $err_str
+}
+
+test_102() {
+    # started from default flavors
+    restore_to_default_flavor
+
+    # run dbench background
+    start_dbench
+
+    echo "Testing null->krb5n->krb5a->krb5i->krb5p->plain->null"
+    set_rule $FSNAME any any krb5n
+    set_rule $FSNAME any any krb5a
+    set_rule $FSNAME any any krb5i
+    set_rule $FSNAME any any krb5p
+    set_rule $FSNAME any any plain
+    set_rule $FSNAME any any null
+
+    check_dbench
+    wait_flavor all2all null $cnt_all2all || error_dbench "1"
+    check_dbench
+
+    echo "waiting for 15s and check again"
+    sleep 15
+    check_dbench
+
+    echo "Testing null->krb5i->null->krb5i->null..."
+    for ((i=0; i<10; i++)); do
+        set_rule $FSNAME any any krb5i
+        set_rule $FSNAME any any null
+    done
+    set_rule $FSNAME any any krb5i
+
+    check_dbench
+    wait_flavor all2all krb5i $cnt_all2all || error_dbench "2"
+    check_dbench
+
+    echo "waiting for 15s and check again"
+    sleep 15
+    check_dbench
+
+    stop_dbench
+}
+run_test 102 "survive from insanely fast flavor switch"
 
 
-echo '=========================== finished ==============================='
-[ -f "$SANITYLOG" ] && cat $SANITYLOG && exit 1 || true
+equals_msg `basename $0`: test complete, cleaning up
+check_and_cleanup_lustre
+[ -f "$TESTSUITELOG" ] && cat $TESTSUITELOG || true
index d68531d..a348768 100644 (file)
 #!/bin/bash
 #
 #!/bin/bash
 #
-# Run select tests by setting SEC_ONLY, or as arguments to the script.
-# Skip specific tests by setting SEC_EXCEPT.
+# Run select tests by setting ONLY, or as arguments to the script.
+# Skip specific tests by setting EXCEPT.
 #
 
 set -e
 
 #
 
 set -e
 
+ONLY=${ONLY:-"$*"}
+[ "$EXCEPT" ] && echo "Skipping tests: `echo $EXCEPT`"
+
 SRCDIR=`dirname $0`
 export PATH=$PWD/$SRCDIR:$SRCDIR:$PWD/$SRCDIR/../utils:$PATH:/sbin
 SRCDIR=`dirname $0`
 export PATH=$PWD/$SRCDIR:$SRCDIR:$PWD/$SRCDIR/../utils:$PATH:/sbin
+export NAME=${NAME:-local}
+
+LUSTRE=${LUSTRE:-`dirname $0`/..} 
+. $LUSTRE/tests/test-framework.sh
+init_test_env $@
+. ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
+
+RUNAS=${RUNAS:-"$LUSTRE/tests/runas"}
+WTL=${WTL:-"$LUSTRE/tests/write_time_limit"}
 
 
-SEC_ONLY=${SEC_ONLY:-"$*"}
-[ "$SEC_EXCEPT" ] && echo "Skipping tests: `echo $SEC_EXCEPT`"
-
-TMP=${TMP:-/tmp}
-LFS=${LFS:-lfs}
-LCTL=${LCTL:-lctl}
-RUNAS=${RUNAS:-runas}
-WTL=${WTL:-write_time_limit}
-
-LPROC=/proc/fs/lustre
-ENABLE_IDENTITY=/usr/sbin/l_getidentity
-DISABLE_IDENTITY=NONE
-LUSTRE_CONF_DIR=/etc/lustre
-PERM_CONF=$LUSTRE_CONF_DIR/perm.conf
-LDLM_LPROC=$LPROC/ldlm
+PERM_CONF=/etc/lustre/perm.conf
 LLITE_LPROC=$LPROC/llite
 MDC_LPROC=$LPROC/mdc
 MDT_LPROC=$LPROC/mdt
 OST_LPROC=$LPROC/obdfilter
 
 LLITE_LPROC=$LPROC/llite
 MDC_LPROC=$LPROC/mdc
 MDT_LPROC=$LPROC/mdt
 OST_LPROC=$LPROC/obdfilter
 
-sec_log() {
-       echo "$*"
-       $LCTL mark "$*" 2> /dev/null || true
-}
-
-SANITYSECLOG=${SANITYSECLOG:-/tmp/sanity-sec.log}
-[ "$SANITYSECLOG" ] && rm -f $SANITYSECLOG || true
-
-sec_error() { 
-       sec_log "FAIL: $TESTNAME $@"
-       if [ "$SANITYSECLOG" ]; then
-               echo "FAIL: $TESTNAME $@" >> $SANITYSECLOG
-       else
-               exit 1
-       fi
-}
-
-sec_pass() { 
-       echo PASS $@
-}
-
-sec_skip () {
-       sec_log "$0: SKIP: $TESTNAME $@"
-       [ "$SANITYSECLOG" ] && echo "$0: SKIP: $TESTNAME $@" >> $SANITYSECLOG
-}
-
-ID1=500
-ID2=501
+SANITYSECLOG=${TESTSUITELOG:-$TMP/$(basename $0 .sh).log}
+FAIL_ON_ERROR=false
 
 
+ID0=${ID0:-500}
+ID1=${ID1:-501}
+USER0=`cat /etc/passwd|grep :$ID0:$ID0:|cut -d: -f1`
 USER1=`cat /etc/passwd|grep :$ID1:$ID1:|cut -d: -f1`
 USER1=`cat /etc/passwd|grep :$ID1:$ID1:|cut -d: -f1`
-USER2=`cat /etc/passwd|grep :$ID2:$ID2:|cut -d: -f1`
 
 
-if [ -z "$USER1" ]; then
-       echo "===== Please add user1 (uid=$ID1 gid=$ID1)! Skip sanity-sec ====="
-       sec_error "===== Please add user1 (uid=$ID1 gid=$ID1)! ====="
-       exit 0
-fi
+[ -z "$USER0" ] && \
+       echo "Please add user0 (uid=$ID0 gid=$ID0)! Skip sanity-sec" && exit 0
 
 
-if [ -z "$USER2" ]; then
-       echo "===== Please add user2 (uid=$ID2 gid=$ID2)! Skip sanity-sec ====="
-       sec_error "===== Please add user2 (uid=$ID2 gid=$ID2)! ====="
-       exit 0
-fi
+[ -z "$USER1" ] && \
+       echo "Please add user1 (uid=$ID1 gid=$ID1)! Skip sanity-sec" && exit 0
 
 
-export NAME=${NAME:-local}
-
-LUSTRE=${LUSTRE:-`dirname $0`/..} 
-. $LUSTRE/tests/test-framework.sh
-init_test_env $@
-. ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
-
-mounted_lustre_filesystems() {
-       awk '($3 ~ "lustre" && $1 ~ ":") { print $2 }' /proc/mounts
-}
-
-MOUNTED="`mounted_lustre_filesystems`"
-if [ -z "$MOUNTED" ]; then
-        formatall
-        setupall
-       MOUNTED="`mounted_lustre_filesystems`"
-       [ -z "$MOUNTED" ] && sec_error "NAME=$NAME not mounted"
-       S_MOUNTED=yes
-fi
-
-[ `echo $MOUNT | wc -w` -gt 1 ] && sec_error "NAME=$NAME mounted more than once"
+check_and_setup_lustre
 
 DIR=${DIR:-$MOUNT}
 
 DIR=${DIR:-$MOUNT}
-[ -z "`echo $DIR | grep $MOUNT`" ] && echo "$DIR not in $MOUNT" && \
-       sec_cleanup && exit 99
+[ -z "`echo $DIR | grep $MOUNT`" ] && \
+       error "$DIR not in $MOUNT" && sec_cleanup && exit 1
 
 
-[ `ls -l $LDLM_LPROC/namespaces 2>/dev/null | grep *-mdc-* | wc -l` -gt 1 ] \
-       && echo "skip multi-MDS test" && sec_cleanup && exit 0
+[ `echo $MOUNT | wc -w` -gt 1 ] && \
+       echo "NAME=$MOUNT mounted more than once" && sec_cleanup && exit 0
 
 
-OST_COUNT=$(ls -l $LDLM_LPROC/namespaces 2>/dev/null | grep osc | grep -v MDT | wc -l)
+[ $MDSCOUNT -gt 1 ] && \
+       echo "skip multi-MDS test" && sec_cleanup && exit 0
 
 # for GSS_SUP
 GSS_REF=$(lsmod | grep ^ptlrpc_gss | awk '{print $3}')
 
 # for GSS_SUP
 GSS_REF=$(lsmod | grep ^ptlrpc_gss | awk '{print $3}')
@@ -114,24 +63,9 @@ else
        echo "without GSS support"
 fi
 
        echo "without GSS support"
 fi
 
-# for MDT_TYPE
-MDT_REF=$(lsmod | grep ^mdt | awk '{print $3}')
-if [ ! -z "$MDT_REF" -a "$MDT_REF" != "0" ]; then
-        MDT_TYPE="local"
-        echo "local mdt"
-else
-        MDT_TYPE="remote"
-        echo "remote mdt"
-fi
-
-MDT="`do_facet $SINGLEMDS ls -l $MDT_LPROC/ | grep MDT | awk '{print $9}'`"
+MDT="`do_facet $SINGLEMDS \"ls -l $MDT_LPROC/ 2>/dev/null\" | grep MDT | awk '{print $9}'`"
 if [ ! -z "$MDT" ]; then
 if [ ! -z "$MDT" ]; then
-       IDENTITY_UPCALL=$MDT_LPROC/$MDT/identity_upcall
-       IDENTITY_UPCALL_BAK="`more $IDENTITY_UPCALL`"
        IDENTITY_FLUSH=$MDT_LPROC/$MDT/identity_flush
        IDENTITY_FLUSH=$MDT_LPROC/$MDT/identity_flush
-       ROOTSQUASH_UID=$MDT_LPROC/$MDT/rootsquash_uid
-       ROOTSQUASH_GID=$MDT_LPROC/$MDT/rootsquash_gid
-       NOSQUASH_NIDS=$MDT_LPROC/$MDT/nosquash_nids
        MDSCAPA=$MDT_LPROC/$MDT/capa
        CAPA_TIMEOUT=$MDT_LPROC/$MDT/capa_timeout
 fi
        MDSCAPA=$MDT_LPROC/$MDT/capa
        CAPA_TIMEOUT=$MDT_LPROC/$MDT/capa_timeout
 fi
@@ -147,62 +81,6 @@ fi
 
 SAVE_PWD=$PWD
 
 
 SAVE_PWD=$PWD
 
-sec_run_one() {
-       BEFORE=`date +%s`
-       sec_log "== test $1 $2= `date +%H:%M:%S` ($BEFORE)"
-       export TESTNAME=test_$1
-       test_$1 || sec_error "exit with rc=$?"
-       unset TESTNAME
-       sec_pass "($((`date +%s` - $BEFORE))s)"
-}
-
-build_test_filter() {
-        for O in $SEC_ONLY; do
-            eval SEC_ONLY_${O}=true
-        done
-        for E in $SEC_EXCEPT; do
-            eval SEC_EXCEPT_${E}=true
-        done
-}
-
-_basetest() {
-       echo $*
-}
-
-basetest() {
-       IFS=abcdefghijklmnopqrstuvwxyz _basetest $1
-}
-
-sec_run_test() {
-         base=`basetest $1`
-         if [ "$SEC_ONLY" ]; then
-                 testname=SEC_ONLY_$1
-                 if [ ${!testname}x != x ]; then
-                       sec_run_one $1 "$2"
-                       return $?
-                 fi
-                 testname=SEC_ONLY_$base
-                 if [ ${!testname}x != x ]; then
-                         sec_run_one $1 "$2"
-                         return $?
-                 fi
-                 echo -n "."
-                 return 0
-       fi
-        testname=SEC_EXCEPT_$1
-        if [ ${!testname}x != x ]; then
-                 echo "skipping excluded test $1"
-                 return 0
-        fi
-        testname=SEC_EXCEPT_$base
-        if [ ${!testname}x != x ]; then
-                 echo "skipping excluded test $1 (base $base)"
-                 return 0
-        fi
-        sec_run_one $1 "$2"
-       return $?
-}
-
 build_test_filter
 
 sec_login() {
 build_test_filter
 
 sec_login() {
@@ -210,169 +88,165 @@ sec_login() {
        local group=$2
 
        if ! $RUNAS -u $user krb5_login.sh; then
        local group=$2
 
        if ! $RUNAS -u $user krb5_login.sh; then
-               echo "$user login kerberos failed."
+               error "$user login kerberos failed."
                exit 1
        fi
 
                exit 1
        fi
 
-       if ! $RUNAS -u $user -g $group ls $DIR > /dev/null; then
+       if ! $RUNAS -u $user -g $group ls $DIR > /dev/null 2>&1; then
                $RUNAS -u $user lfs flushctx -k
                $RUNAS -u $user krb5_login.sh
                $RUNAS -u $user lfs flushctx -k
                $RUNAS -u $user krb5_login.sh
-                if ! $RUNAS -u $user -g $group ls $DIR > /dev/null; then
-                        echo "init $user $group failed."
+                if ! $RUNAS -u $user -g $group ls $DIR > /dev/null 2>&1; then
+                        error "init $user $group failed."
                         exit 2
                 fi
        fi
 }
 
                         exit 2
                 fi
        fi
 }
 
-setup() {
-       if [ ! -z "$MDT" ]; then
-               do_facet $SINGLEMDS echo $ENABLE_IDENTITY > $IDENTITY_UPCALL
-               do_facet $SINGLEMDS echo -1 > $IDENTITY_FLUSH
+declare -a identity_old
+
+sec_setup() {
+               for num in `seq $MDSCOUNT`; do
+                       switch_identity $num true || identity_old[$num]=$?
+               done
+
+       if ! $RUNAS -u $ID0 ls $DIR > /dev/null 2>&1; then
+               sec_login $USER0 $USER0
        fi
 
        if ! $RUNAS -u $ID1 ls $DIR > /dev/null 2>&1; then
                sec_login $USER1 $USER1
        fi
        fi
 
        if ! $RUNAS -u $ID1 ls $DIR > /dev/null 2>&1; then
                sec_login $USER1 $USER1
        fi
-
-       if ! $RUNAS -u $ID2 ls $DIR > /dev/null 2>&1; then
-               sec_login $USER2 $USER2
-       fi
 }
 }
-setup
+sec_setup
 
 # run as different user
 test_0() {
        rm -rf $DIR/d0
        mkdir $DIR/d0
 
 
 # run as different user
 test_0() {
        rm -rf $DIR/d0
        mkdir $DIR/d0
 
-       chown $USER1 $DIR/d0 || sec_error
-       $RUNAS -u $ID1 ls $DIR || sec_error
-       $RUNAS -u $ID1 touch $DIR/f0 && sec_error
-       $RUNAS -u $ID1 touch $DIR/d0/f1 || sec_error
-       $RUNAS -u $ID2 touch $DIR/d0/f2 && sec_error
-       touch $DIR/d0/f3 || sec_error
-       chown root $DIR/d0
-       chgrp $USER1 $DIR/d0
-       chmod 775 $DIR/d0
-       $RUNAS -u $ID1 touch $DIR/d0/f4 || sec_error
-       $RUNAS -u $ID2 touch $DIR/d0/f5 && sec_error
-       touch $DIR/d0/f6 || sec_error
+       chown $USER0 $DIR/d0 || error "chown (1)"
+       $RUNAS -u $ID0 ls $DIR || error "ls (2)"
+       $RUNAS -u $ID0 touch $DIR/f0 && error "touch (3)"
+       $RUNAS -u $ID0 touch $DIR/d0/f1 || error "touch (4)"
+       $RUNAS -u $ID1 touch $DIR/d0/f2 && error "touch (5)"
+       touch $DIR/d0/f3 || error "touch (6)"
+       chown root $DIR/d0 || error "chown (7)"
+       chgrp $USER0 $DIR/d0 || error "chgrp (8)"
+       chmod 775 $DIR/d0 || error "chmod (9)"
+       $RUNAS -u $ID0 touch $DIR/d0/f4 || error "touch (10)"
+       $RUNAS -u $ID1 touch $DIR/d0/f5 && error "touch (11)"
+       touch $DIR/d0/f6 || error "touch (12)"
 
        rm -rf $DIR/d0
 }
 
        rm -rf $DIR/d0
 }
-sec_run_test 0 "uid permission ============================="
+run_test 0 "uid permission ============================="
 
 # setuid/gid
 test_1() {
 
 # setuid/gid
 test_1() {
-       [ $GSS_SUP = 0 ] && sec_skip "without GSS support." && return
-       [ -z "$MDT" ] && sec_skip "do not support do_facet operations." && return
+       [ $GSS_SUP = 0 ] && skip "without GSS support." && return
+       [ -z "$MDT" ] && skip "do not support do_facet operations." && return
+       [ "$CLIENT_TYPE" = "remote" ] && \
+               skip "test_1 for local client only" && return
 
 
-       do_facet $SINGLEMDS rm -f $PERM_CONF
-       do_facet $SINGLEMDS echo -1 > $IDENTITY_FLUSH
+       do_facet $SINGLEMDS "rm -f $PERM_CONF"
+       do_facet $SINGLEMDS "echo -1 > $IDENTITY_FLUSH"
 
        rm -rf $DIR/d1
        mkdir $DIR/d1
 
 
        rm -rf $DIR/d1
        mkdir $DIR/d1
 
-       chown $USER1 $DIR/d1 || sec_error
-       $RUNAS -u $ID2 -v $ID1 touch $DIR/d1/f0 && sec_error
-       do_facet $SINGLEMDS echo "\* $ID2 setuid" > $PERM_CONF
-       echo "enable uid $ID2 setuid"
-       do_facet $SINGLEMDS echo -1 > $IDENTITY_FLUSH
-       $RUNAS -u $ID2 -v $ID1 touch $DIR/d1/f1 || sec_error
-
-       chown root $DIR/d1
-       chgrp $USER1 $DIR/d1
-       chmod 770 $DIR/d1
-       $RUNAS -u $ID2 -g $ID2 touch $DIR/d1/f2 && sec_error
-       $RUNAS -u $ID2 -g $ID2 -j $ID1 touch $DIR/d1/f3 && sec_error
-       do_facet $SINGLEMDS echo "\* $ID2 setuid,setgid" > $PERM_CONF
-       echo "enable uid $ID2 setuid,setgid"
-       do_facet $SINGLEMDS echo -1 > $IDENTITY_FLUSH
-       $RUNAS -u $ID2 -g $ID2 -j $ID1 touch $DIR/d1/f4 || sec_error
-       $RUNAS -u $ID2 -v $ID1 -g $ID2 -j $ID1 touch $DIR/d1/f5 || sec_error
+       chown $USER0 $DIR/d1 || error "chown (1)"
+       $RUNAS -u $ID1 -v $ID0 touch $DIR/d1/f0 && error "touch (2)"
+       do_facet $SINGLEMDS "echo '* $ID1 setuid' > $PERM_CONF"
+       echo "enable uid $ID1 setuid"
+       do_facet $SINGLEMDS "echo -1 > $IDENTITY_FLUSH"
+       $RUNAS -u $ID1 -v $ID0 touch $DIR/d1/f1 || error "touch (3)"
+
+       chown root $DIR/d1 || error "chown (4)"
+       chgrp $USER0 $DIR/d1 || error "chgrp (5)"
+       chmod 770 $DIR/d1 || error "chmod (6)"
+       $RUNAS -u $ID1 -g $ID1 touch $DIR/d1/f2 && error "touch (7)"
+       $RUNAS -u $ID1 -g $ID1 -j $ID0 touch $DIR/d1/f3 && error "touch (8)"
+       do_facet $SINGLEMDS "echo '* $ID1 setuid,setgid' > $PERM_CONF"
+       echo "enable uid $ID1 setuid,setgid"
+       do_facet $SINGLEMDS "echo -1 > $IDENTITY_FLUSH"
+       $RUNAS -u $ID1 -g $ID1 -j $ID0 touch $DIR/d1/f4 || error "touch (9)"
+       $RUNAS -u $ID1 -v $ID0 -g $ID1 -j $ID0 touch $DIR/d1/f5 || error "touch (10)"
 
        rm -rf $DIR/d1
 
 
        rm -rf $DIR/d1
 
-       do_facet $SINGLEMDS rm -f $PERM_CONF
-       do_facet $SINGLEMDS echo -1 > $IDENTITY_FLUSH
+       do_facet $SINGLEMDS "rm -f $PERM_CONF"
+       do_facet $SINGLEMDS "echo -1 > $IDENTITY_FLUSH"
+}
+run_test 1 "setuid/gid ============================="
+
+run_rmtacl_subtest() {
+    $SAVE_PWD/rmtacl/run $SAVE_PWD/rmtacl/$1.test
+    return $?
 }
 }
-sec_run_test 1 "setuid/gid ============================="
 
 # remote_acl
 # for remote client only
 test_2 () {
        [ "$CLIENT_TYPE" = "local" ] && \
 
 # remote_acl
 # for remote client only
 test_2 () {
        [ "$CLIENT_TYPE" = "local" ] && \
-               sec_skip "remote_acl for remote client only" && return
+               skip "remote_acl for remote client only" && return
        [ -z "$(grep ^acl $MDC_LPROC/*-mdc-*/connect_flags)" ] && \
        [ -z "$(grep ^acl $MDC_LPROC/*-mdc-*/connect_flags)" ] && \
-               sec_skip "must have acl enabled" && return
+               skip "must have acl enabled" && return
        [ -z "$(which setfacl 2>/dev/null)" ] && \
        [ -z "$(which setfacl 2>/dev/null)" ] && \
-               sec_skip "could not find setfacl" && return
-       [ "$UID" != 0 ] && sec_skip "must run as root" && return
-
-       rm -rf $DIR/d2
-       mkdir $DIR/d2
-       chmod 755 $DIR/d2
-       echo xxx > $DIR/d2/f0
-       chmod 644 $DIR/d2/f0
-
-       $LFS getfacl $DIR/d2/f0 || sec_error
-       $RUNAS -u $ID1 cat $DIR/d2/f0 || sec_error
-       $RUNAS -u $ID1 touch $DIR/d2/f0 && sec_error
-
-       $LFS setfacl -m u:$USER1:w $DIR/d2/f0 || sec_error
-       $LFS getfacl $DIR/d2/f0 || sec_error
-       echo "set user $USER1 write permission on file $DIR/d2/f0"
-       $RUNAS -u $ID1 touch $DIR/d2/f0 || sec_error
-       $RUNAS -u $ID1 cat $DIR/d2/f0 && sec_error
-
-       rm -rf $DIR/d2
+               skip "could not find setfacl" && return
+       [ "$UID" != 0 ] && skip "must run as root" && return
+
+       sec_login root root
+       sec_login bin bin
+       sec_login daemon daemon
+       sec_login games users
+
+       SAVE_UMASK=`umask`
+       umask 0022
+       cd $DIR
+
+       if [ ! -z "$MDT" ]; then
+               do_facet $SINGLEMDS "echo '* 0 rmtacl' > $PERM_CONF"
+               do_facet $SINGLEMDS "echo -1 > $IDENTITY_FLUSH"
+       fi
+
+        if lfs rgetfacl $DIR; then
+                echo "performing cp ..."
+                run_rmtacl_subtest cp || error "cp"
+        else
+                echo "server doesn't permit current user 'lfs r{s,g}etfacl', skip cp test."
+        fi
+       echo "performing getfacl-noacl..."
+       run_rmtacl_subtest getfacl-noacl || error "getfacl-noacl"
+       echo "performing misc..."
+       run_rmtacl_subtest misc || error "misc"
+       echo "performing permissions..."
+       run_rmtacl_subtest permissions || error "permissions"
+       echo "performing setfacl..."
+       run_rmtacl_subtest setfacl || error "setfacl"
+
+       # inheritance test got from HP
+       echo "performing inheritance..."
+       cp $SAVE_PWD/rmtacl/make-tree .
+       chmod +x make-tree
+       run_rmtacl_subtest inheritance || error "inheritance"
+       rm -f make-tree
+
+       if [ ! -z "$MDT" ]; then
+               do_facet $SINGLEMDS "rm -f $PERM_CONF"
+               do_facet $SINGLEMDS "echo -1 > $IDENTITY_FLUSH"
+       fi
+
+       cd $SAVE_PWD
+       umask $SAVE_UMASK
 }
 }
-sec_run_test 2 "rmtacl ============================="
+run_test 2 "rmtacl ============================="
 
 # rootsquash
 
 # rootsquash
-# for remote mdt only
+# root_squash will be redesigned in Lustre 1.7
 test_3() {
 test_3() {
-       [ $GSS_SUP = 0 ] && sec_skip "without GSS support." && return
-       [ -z "$MDT" ] && sec_skip "do not support do_facet operations." && return
-        [ "$MDT_TYPE" = "local" ] && sec_skip "rootsquash for remote mdt only" && return
-
-       do_facet $SINGLEMDS echo "-\*" > $NOSQUASH_NIDS 
-       do_facet $SINGLEMDS echo 0 > $ROOTSQUASH_UID
-       do_facet $SINGLEMDS echo 0 > $ROOTSQUASH_GID
-
-       rm -rf $DIR/d3
-       mkdir $DIR/d3
-       chown $USER1 $DIR/d3
-       chmod 700 $DIR/d3
-       do_facet $SINGLEMDS echo $ID1 > $ROOTSQUASH_UID
-       echo "set rootsquash uid = $ID1"
-       touch $DIR/f3_0 && sec_error
-       touch $DIR/d3/f3_1 || sec_error
-
-       do_facet $SINGLEMDS echo 0 > $ROOTSQUASH_UID
-       echo "disable rootsquash"
-       chown root $DIR/d3
-       chgrp $USER2 $DIR/d3
-       chmod 770 $DIR/d3
-
-       do_facet $SINGLEMDS echo $ID1 > $ROOTSQUASH_UID
-       echo "set rootsquash uid = $ID1"
-       touch $DIR/d3/f3_2 && sec_error
-       do_facet $SINGLEMDS echo $ID2 > $ROOTSQUASH_GID
-       echo "set rootsquash gid = $ID2"
-       touch $DIR/d3/f3_3 || sec_error
-
-       do_facet $SINGLEMDS echo "+\*" > $NOSQUASH_NIDS
-       echo "add host in rootsquash skip list"
-       touch $DIR/f3_4 || sec_error
-
-       do_facet $SINGLEMDS echo 0 > $ROOTSQUASH_UID
-       do_facet $SINGLEMDS echo 0 > $ROOTSQUASH_GID
-       do_facet $SINGLEMDS echo "-\*" > $NOSQUASH_NIDS
-       rm -rf $DIR/d3
-       rm -f $DIR/f3_?
+        skip "root_squash will be redesigned in Lustre 1.7" && return
 }
 }
-sec_run_test 3 "rootsquash ============================="
+run_test 3 "rootsquash ============================="
 
 # bug 3285 - supplementary group should always succeed.
 # NB: the supplementary groups are set for local client only,
 
 # bug 3285 - supplementary group should always succeed.
 # NB: the supplementary groups are set for local client only,
@@ -382,29 +256,29 @@ test_4() {
        rm -rf $DIR/d4
         mkdir $DIR/d4
         chmod 771 $DIR/d4
        rm -rf $DIR/d4
         mkdir $DIR/d4
         chmod 771 $DIR/d4
-        chgrp $ID1 $DIR/d4
-       $RUNAS -u $ID1 ls $DIR/d4 || sec_error "setgroups(1) failed"
+        chgrp $ID0 $DIR/d4
+       $RUNAS -u $ID0 ls $DIR/d4 || error "setgroups (1)"
        if [ "$CLIENT_TYPE" != "remote" ]; then
                if [ ! -z "$MDT" ]; then
        if [ "$CLIENT_TYPE" != "remote" ]; then
                if [ ! -z "$MDT" ]; then
-                       do_facet $SINGLEMDS echo "\* $ID2 setgrp" > $PERM_CONF
-                       do_facet $SINGLEMDS echo -1 > $IDENTITY_FLUSH
+                       do_facet $SINGLEMDS "echo '* $ID1 setgrp' > $PERM_CONF"
+                       do_facet $SINGLEMDS "echo -1 > $IDENTITY_FLUSH"
                fi
                fi
-               $RUNAS -u $ID2 -G1,2,$ID1 ls $DIR/d4 || sec_error "setgroups(2) failed"
+               $RUNAS -u $ID1 -G1,2,$ID0 ls $DIR/d4 || error "setgroups (2)"
                if [ ! -z "$MDT" ]; then
                if [ ! -z "$MDT" ]; then
-                       do_facet $SINGLEMDS rm -f $PERM_CONF
-                       do_facet $SINGLEMDS echo -1 > $IDENTITY_FLUSH
+                       do_facet $SINGLEMDS "rm -f $PERM_CONF"
+                       do_facet $SINGLEMDS "echo -1 > $IDENTITY_FLUSH"
                fi
        fi
                fi
        fi
-       $RUNAS -u $ID2 -G1,2 ls $DIR/d4 && sec_error "setgroups(3) failed"
+       $RUNAS -u $ID1 -G1,2 ls $DIR/d4 && error "setgroups (3)"
        rm -rf $DIR/d4
 }
        rm -rf $DIR/d4
 }
-sec_run_test 4 "set supplementary group ==============="
+run_test 4 "set supplementary group ==============="
 
 mds_capability_timeout() {
         [ $# -lt 1 ] && echo "Miss mds capability timeout value" && return 1
 
         echo "Set mds capability timeout as $1 seconds"
 
 mds_capability_timeout() {
         [ $# -lt 1 ] && echo "Miss mds capability timeout value" && return 1
 
         echo "Set mds capability timeout as $1 seconds"
-       do_facet $SINGLEMDS echo $1 > $CAPA_TIMEOUT
+       do_facet $SINGLEMDS "echo $1 > $CAPA_TIMEOUT"
         return 0
 }
 
         return 0
 }
 
@@ -417,7 +291,7 @@ mds_capability_switch() {
                 *) echo "Invalid mds capability switch value" && return 2;;
         esac
 
                 *) echo "Invalid mds capability switch value" && return 2;;
         esac
 
-       do_facet $SINGLEMDS echo $1 > $MDSCAPA
+       do_facet $SINGLEMDS "echo $1 > $MDSCAPA"
         return 0
 }
 
         return 0
 }
 
@@ -430,12 +304,10 @@ oss_capability_switch() {
                 *) echo "Invalid oss capability switch value" && return 2;;
         esac
 
                 *) echo "Invalid oss capability switch value" && return 2;;
         esac
 
-       i=0;
-       while [ $i -lt $OST_COUNT ]; do
-               j=$i;
-               i=`expr $i + 1`
-               OST="`do_facet ost$i ls -l $OST_LPROC/ | grep OST | awk '{print $9}' | grep $j$`"
-               do_facet ost$i echo $1 > $OST_LPROC/$OST/capa
+       for i in `seq $OSTCOUNT`; do
+               local j=`expr $i - 1`
+               local OST="`do_facet ost$i \"ls -l $OST_LPROC/\" | grep OST | awk '{print $9}' | grep $j$`"
+               do_facet ost$i "echo $1 > $OST_LPROC/$OST/capa"
        done
         return 0
 }
        done
         return 0
 }
@@ -475,13 +347,25 @@ turn_capability_off() {
 test_5() {
         local file=$DIR/f5
 
 test_5() {
         local file=$DIR/f5
 
-       [ -z "$MDT" ] && sec_skip "do not support do_facet operations." && return
+       [ -z "$MDT" ] && skip "do not support do_facet operations." && return
        turn_capability_off
        turn_capability_off
+       if [ $? != 0 ]; then
+               error "turn_capability_off"
+               return 1
+       fi
        rm -f $file
 
         # Disable proc variable
        rm -f $file
 
         # Disable proc variable
-        mds_capability_switch 0 || return 1
-        oss_capability_switch 1 || return 2
+        mds_capability_switch 0
+       if [ $? != 0 ]; then
+               error "mds_capability_switch 0"
+               return 2
+       fi
+        oss_capability_switch 1
+       if [ $? != 0 ]; then
+               error "oss_capability_switch 1"
+               return 3
+       fi
 
         # proc variable disabled -- access to the objects in the filesystem
         # is not allowed 
 
         # proc variable disabled -- access to the objects in the filesystem
         # is not allowed 
@@ -489,11 +373,15 @@ test_5() {
             "-- access to the objects in the filesystem is denied."
        $WTL $file 30
        if [ $? == 0 ]; then
             "-- access to the objects in the filesystem is denied."
        $WTL $file 30
        if [ $? == 0 ]; then
-               echo "Write worked well even though secrets not supplied."
-               return 3
+               error "Write worked well even though secrets not supplied."
+               return 4
         fi
 
         fi
 
-        turn_capability_on || return 4
+        turn_capability_on
+       if [ $? != 0 ]; then
+               error "turn_capability_on"
+               return 4
+       fi
         sleep 5
 
         # proc variable enabled, secrets supplied -- write should work now
         sleep 5
 
         # proc variable enabled, secrets supplied -- write should work now
@@ -501,14 +389,18 @@ test_5() {
             "-- write should work now)."
        $WTL $file 30
        if [ $? != 0 ]; then
             "-- write should work now)."
        $WTL $file 30
        if [ $? != 0 ]; then
-               echo "Write failed even though secrets supplied."
+               error "Write failed even though secrets supplied."
                return 5
         fi
 
        turn_capability_off
                return 5
         fi
 
        turn_capability_off
+       if [ $? != 0 ]; then
+               error "turn_capability_off"
+               return 7
+       fi
        rm -f $file
 }
        rm -f $file
 }
-sec_run_test 5 "capa secrets ========================="
+run_test 5 "capa secrets ========================="
 
 # Expiry: A test program is performing I/O on a file. It has credential
 # with an expiry half a minute later. While the program is running the
 
 # Expiry: A test program is performing I/O on a file. It has credential
 # with an expiry half a minute later. While the program is running the
@@ -517,51 +409,76 @@ sec_run_test 5 "capa secrets ========================="
 test_6() {
         local file=$DIR/f6
 
 test_6() {
         local file=$DIR/f6
 
-       [ -z "$MDT" ] && sec_skip "do not support do_facet operations." && return
+       [ -z "$MDT" ] && skip "do not support do_facet operations." && return
        turn_capability_off
        turn_capability_off
+       if [ $? != 0 ]; then
+               error "turn_capability_off"
+               return 1
+       fi
        rm -f $file
 
        rm -f $file
 
-        turn_capability_on 30 || return 1
+        turn_capability_on 30
+       if [ $? != 0 ]; then
+               error "turn_capability_on 30"
+               return 2
+       fi
         # Token expiry
         # Token expiry
-       $WTL $file 60 || return 2
+       $WTL $file 60
+       if [ $? != 0 ]; then
+               error "$WTL $file 60"
+               return 3
+       fi
 
        # Reset MDS capability timeout
 
        # Reset MDS capability timeout
-       mds_capability_timeout 30 || exit 3
+       mds_capability_timeout 30
+       if [ $? != 0 ]; then
+               error "mds_capability_timeout 30"
+               return 4
+       fi
        $WTL $file 60 &
        local PID=$!
        sleep 5
 
         # To disable automatic renew, only need turn capa off on MDS.
        $WTL $file 60 &
        local PID=$!
        sleep 5
 
         # To disable automatic renew, only need turn capa off on MDS.
-        mds_capability_switch 0 || return 4
+        mds_capability_switch 0
+       if [ $? != 0 ]; then
+               error "mds_capability_switch 0"
+               return 5
+       fi
 
        echo "We expect I/O failure."
         wait $PID
        if [ $? == 0 ]; then
                echo "no I/O failure got."
 
        echo "We expect I/O failure."
         wait $PID
        if [ $? == 0 ]; then
                echo "no I/O failure got."
-               return 5
+               return 6
        fi
 
        turn_capability_off
        fi
 
        turn_capability_off
+       if [ $? != 0 ]; then
+               error "turn_capability_off"
+               return 7
+       fi
        rm -f $file
 }
        rm -f $file
 }
-sec_run_test 6 "capa expiry ========================="
+run_test 6 "capa expiry ========================="
 
 log "cleanup: ======================================================"
 
 
 log "cleanup: ======================================================"
 
-unsetup() {
-       if [ ! -z "$MDT"  ]; then
-               do_facet $SINGLEMDS echo $IDENTITY_UPCALL_BAK > $IDENTITY_UPCALL
-               do_facet $SINGLEMDS echo -1 > $IDENTITY_FLUSH
-       fi
+sec_unsetup() {
+               for num in `seq $MDSCOUNT`; do
+               if [ "${identity_old[$num]}" = 1 ]; then
+                               switch_identity $num false || identity_old[$num]=$?
+               fi
+               done
 
 
+       $RUNAS -u $ID0 ls $DIR
        $RUNAS -u $ID1 ls $DIR
        $RUNAS -u $ID1 ls $DIR
-       $RUNAS -u $ID2 ls $DIR
 }
 }
-unsetup
+sec_unsetup
 
 sec_cleanup() {
 
 sec_cleanup() {
-       if [ "$S_MOUNTED" = "yes" ]; then
-               cleanupall -f || sec_error "cleanup failed"
+       if [ "$I_MOUNTED" = "yes" ]; then
+               cleanupall -f || error "sec_cleanup"
        fi
 }
 sec_cleanup
        fi
 }
 sec_cleanup
index a29a855..fd9c990 100644 (file)
@@ -830,7 +830,7 @@ test_27c() {
        [ `$GETSTRIPE $DIR/d27/f01 | grep -A 10 obdidx | wc -l` -eq 4 ] ||
                error "two-stripe file doesn't have two stripes"
        pass
        [ `$GETSTRIPE $DIR/d27/f01 | grep -A 10 obdidx | wc -l` -eq 4 ] ||
                error "two-stripe file doesn't have two stripes"
        pass
-       log "== test_27d: write to two stripe file file f01 ================"
+       log "== test_27c: write to two stripe file file f01 ================"
        dd if=/dev/zero of=$DIR/d27/f01 bs=4k count=4 || error "dd failed"
 }
 run_test 27c "create two stripe file f01 ======================="
        dd if=/dev/zero of=$DIR/d27/f01 bs=4k count=4 || error "dd failed"
 }
 run_test 27c "create two stripe file f01 ======================="
@@ -2921,12 +2921,6 @@ test_66() {
 }
 run_test 66 "update inode blocks count on client ==============="
 
 }
 run_test 66 "update inode blocks count on client ==============="
 
-test_67() {
-        [ ! -f sanity-sec.sh ] && skip "missing subtest sanity-sec.sh" && return
-       sh sanity-sec.sh
-}
-run_test 67 "security test ====================================="
-
 LLOOP=
 cleanup_68() {
        trap 0
 LLOOP=
 cleanup_68() {
        trap 0
@@ -3274,6 +3268,13 @@ run_test 76 "destroy duplicate inodes in client inode cache ===="
 export ORIG_CSUM=""
 set_checksums()
 {
 export ORIG_CSUM=""
 set_checksums()
 {
+       # Note: in sptlrpc modes which enable its own bulk checksum, the
+       # original crc32_le bulk checksum will be automatically disabled,
+       # and the OBD_FAIL_OSC_CHECKSUM_SEND/OBD_FAIL_OSC_CHECKSUM_RECEIVE
+       # will be checked by sptlrpc code against sptlrpc bulk checksum.
+       # In this case set_checksums() will not be no-op, because sptlrpc
+       # bulk checksum will be enabled all through the test.
+
        [ "$ORIG_CSUM" ] || ORIG_CSUM=`cat $LPROC/osc/*/checksums | head -n1`
        for f in $LPROC/osc/*/checksums; do
                echo $1 >> $f
        [ "$ORIG_CSUM" ] || ORIG_CSUM=`cat $LPROC/osc/*/checksums | head -n1`
        for f in $LPROC/osc/*/checksums; do
                echo $1 >> $f
@@ -3872,6 +3873,12 @@ test_103 () {
     [ -z "$(which setfacl 2>/dev/null)" ] && skip "could not find setfacl" && return
     $GSS && skip "could not run under gss" && return
 
     [ -z "$(which setfacl 2>/dev/null)" ] && skip "could not find setfacl" && return
     $GSS && skip "could not run under gss" && return
 
+    declare -a identity_old
+
+    for num in `seq $MDSCOUNT`; do
+        switch_identity $num true || identity_old[$num]=$?
+    done
+
     SAVE_UMASK=`umask`
     umask 0022
     cd $DIR
     SAVE_UMASK=`umask`
     umask 0022
     cd $DIR
@@ -3882,9 +3889,8 @@ test_103 () {
     run_acl_subtest getfacl-noacl || error
     echo "performing misc..."
     run_acl_subtest misc || error
     run_acl_subtest getfacl-noacl || error
     echo "performing misc..."
     run_acl_subtest misc || error
-#    XXX add back permission test when we support supplementary groups.
-#    echo "performing permissions..."
-#    run_acl_subtest permissions || error
+    echo "performing permissions..."
+    run_acl_subtest permissions || error
     echo "performing setfacl..."
     run_acl_subtest setfacl || error
 
     echo "performing setfacl..."
     run_acl_subtest setfacl || error
 
@@ -3897,6 +3903,12 @@ test_103 () {
 
     cd $SAVE_PWD
     umask $SAVE_UMASK
 
     cd $SAVE_PWD
     umask $SAVE_UMASK
+
+    for num in `seq $MDSCOUNT`; do
+       if [ "${identity_old[$num]}" = 1 ]; then
+            switch_identity $num false || identity_old[$num]=$?
+       fi
+    done
 }
 run_test 103 "acl test ========================================="
 
 }
 run_test 103 "acl test ========================================="
 
index 2633f1a..d7fafbe 100644 (file)
@@ -13,6 +13,7 @@ export CATASTROPHE=${CATASTROPHE:-/proc/sys/lnet/catastrophe}
 export GSS=false
 export GSS_KRB5=false
 export GSS_PIPEFS=false
 export GSS=false
 export GSS_KRB5=false
 export GSS_PIPEFS=false
+export IDENTITY_UPCALL=false
 #export PDSH="pdsh -S -Rssh -w"
 
 # eg, assert_env LUSTRE MDSNODES OSTNODES CLIENTS
 #export PDSH="pdsh -S -Rssh -w"
 
 # eg, assert_env LUSTRE MDSNODES OSTNODES CLIENTS
@@ -77,10 +78,17 @@ init_test_env() {
 
     export PATH=:$PATH:$LUSTRE/utils:$LUSTRE/utils/gss:$LUSTRE/tests
     export LCTL=${LCTL:-"$LUSTRE/utils/lctl"}
 
     export PATH=:$PATH:$LUSTRE/utils:$LUSTRE/utils/gss:$LUSTRE/tests
     export LCTL=${LCTL:-"$LUSTRE/utils/lctl"}
-    export LFS=${LFS:-"$LUSTRE/utils/lfs"}
     [ ! -f "$LCTL" ] && export LCTL=$(which lctl) 
     export LFS=${LFS:-"$LUSTRE/utils/lfs"}
     [ ! -f "$LFS" ] && export LFS=$(which lfs) 
     [ ! -f "$LCTL" ] && export LCTL=$(which lctl) 
     export LFS=${LFS:-"$LUSTRE/utils/lfs"}
     [ ! -f "$LFS" ] && export LFS=$(which lfs) 
+    export L_GETIDENTITY=${L_GETIDENTITY:-"$LUSTRE/utils/l_getidentity"}
+    if [ ! -f "$L_GETIDENTITY" ]; then
+        if `which l_getidentity > /dev/null 2>&1`; then
+            export L_GETIDENTITY=$(which l_getidentity)
+        else
+            export L_GETIDENTITY=NONE
+        fi
+    fi
     export MKFS=${MKFS:-"$LUSTRE/utils/mkfs.lustre"}
     [ ! -f "$MKFS" ] && export MKFS=$(which mkfs.lustre) 
     export TUNEFS=${TUNEFS:-"$LUSTRE/utils/tunefs.lustre"}
     export MKFS=${MKFS:-"$LUSTRE/utils/mkfs.lustre"}
     [ ! -f "$MKFS" ] && export MKFS=$(which mkfs.lustre) 
     export TUNEFS=${TUNEFS:-"$LUSTRE/utils/tunefs.lustre"}
@@ -90,7 +98,10 @@ init_test_env() {
     export NAME=${NAME:-local}
     export LPROC=/proc/fs/lustre
     export LGSSD=${LGSSD:-"$LUSTRE/utils/gss/lgssd"}
     export NAME=${NAME:-local}
     export LPROC=/proc/fs/lustre
     export LGSSD=${LGSSD:-"$LUSTRE/utils/gss/lgssd"}
+    [ "$GSS_PIPEFS" = "true" ] && [ ! -f "$LGSSD" ] && \
+        export LGSSD=$(which lgssd)
     export LSVCGSSD=${LSVCGSSD:-"$LUSTRE/utils/gss/lsvcgssd"}
     export LSVCGSSD=${LSVCGSSD:-"$LUSTRE/utils/gss/lsvcgssd"}
+    [ ! -f "$LSVCGSSD" ] && export LSVCGSSD=$(which lsvcgssd) 
     export KRB5DIR=${KRB5DIR:-"/usr/kerberos"}
     export DIR2
 
     export KRB5DIR=${KRB5DIR:-"/usr/kerberos"}
     export DIR2
 
@@ -106,6 +117,15 @@ init_test_env() {
             ;;
     esac
 
             ;;
     esac
 
+    case "x$ID" in
+        xtrue)
+            IDENTITY_UPCALL=true
+            ;;
+        xfalse)
+            IDENTITY_UPCALL=false
+            ;;
+    esac
+
     # Paths on remote nodes, if different 
     export RLUSTRE=${RLUSTRE:-$LUSTRE}
     export RPWD=${RPWD:-$PWD}
     # Paths on remote nodes, if different 
     export RLUSTRE=${RLUSTRE:-$LUSTRE}
     export RPWD=${RPWD:-$PWD}
@@ -339,18 +359,13 @@ stop_gss_daemons() {
     send_sigint client lgssd
 }
 
     send_sigint client lgssd
 }
 
-init_krb5_env() {
-    if [ ! -z $SEC ]; then
-        MDS_MOUNT_OPTS=$MDS_MOUNT_OPTS,sec=$SEC
-        OST_MOUNT_OPTS=$OST_MOUNT_OPTS,sec=$SEC
-    fi
-
+init_gss() {
     if $GSS; then
         start_gss_daemons
     fi
 }
 
     if $GSS; then
         start_gss_daemons
     fi
 }
 
-cleanup_krb5_env() {
+cleanup_gss() {
     if $GSS; then
         stop_gss_daemons
         # maybe cleanup credential cache?
     if $GSS; then
         stop_gss_daemons
         # maybe cleanup credential cache?
@@ -847,7 +862,7 @@ stopall() {
 cleanupall() {
     stopall $*
     unload_modules
 cleanupall() {
     stopall $*
     unload_modules
-    cleanup_krb5_env
+    cleanup_gss
 }
 
 mdsmkfsopts()
 }
 
 mdsmkfsopts()
@@ -859,6 +874,11 @@ mdsmkfsopts()
 formatall() {
     [ "$FSTYPE" ] && FSTYPE_OPT="--backfstype $FSTYPE"
 
 formatall() {
     [ "$FSTYPE" ] && FSTYPE_OPT="--backfstype $FSTYPE"
 
+    if [ ! -z $SEC ]; then
+        MDS_MKFS_OPTS="$MDS_MKFS_OPTS --param srpc.flavor.default=$SEC"
+        OST_MKFS_OPTS="$OST_MKFS_OPTS --param srpc.flavor.default=$SEC"
+    fi
+
     stopall
     # We need ldiskfs here, may as well load them all
     load_modules
     stopall
     # We need ldiskfs here, may as well load them all
     load_modules
@@ -887,9 +907,40 @@ mount_client() {
     grep " $1 " /proc/mounts || zconf_mount `hostname` $*
 }
 
     grep " $1 " /proc/mounts || zconf_mount `hostname` $*
 }
 
+# return value:
+# 0: success, the old identity set already.
+# 1: success, the old identity does not set.
+# 2: fail.
+switch_identity() {
+    local num=$1
+    local switch=$2
+    local j=`expr $num - 1`
+    local MDT="`do_facet mds$num ls -l $LPROC/mdt/ 2>/dev/null | grep MDT | awk '{print $9}' | grep $j$`"
+
+    if [ -z "$MDT" ]; then
+        return 2
+    fi
+
+    local old="`do_facet mds$num cat $LPROC/mdt/$MDT/identity_upcall`"
+
+    if [ $switch ]; then
+        do_facet mds$num "echo \"$L_GETIDENTITY\" > $LPROC/mdt/$MDT/identity_upcall"
+    else
+        do_facet mds$num "echo \"NONE\" > $LPROC/mdt/$MDT/identity_upcall"
+    fi
+
+    do_facet mds$num "echo \"-1\" > $LPROC/mdt/$MDT/identity_flush"
+
+    if [ $old = "NONE" ]; then
+        return 1
+    else
+        return 0
+    fi
+}
+
 setupall() {
     load_modules
 setupall() {
     load_modules
-    init_krb5_env
+    init_gss
     if [ -z "$CLIENTONLY" ]; then
         echo "Setup mdts, osts"
         for num in `seq $MDSCOUNT`; do
     if [ -z "$CLIENTONLY" ]; then
         echo "Setup mdts, osts"
         for num in `seq $MDSCOUNT`; do
@@ -897,6 +948,7 @@ setupall() {
             echo $REFORMAT | grep -q "reformat" \
             || do_facet mds$num "$TUNEFS --writeconf $DEVNAME"
             start mds$num $DEVNAME $MDS_MOUNT_OPTS
             echo $REFORMAT | grep -q "reformat" \
             || do_facet mds$num "$TUNEFS --writeconf $DEVNAME"
             start mds$num $DEVNAME $MDS_MOUNT_OPTS
+            switch_identity $num $IDENTITY_UPCALL
         done
         for num in `seq $OSTCOUNT`; do
             DEVNAME=$(ostdevname $num)
         done
         for num in `seq $OSTCOUNT`; do
             DEVNAME=$(ostdevname $num)
index a7ee8f4..f0339d6 100644 (file)
@@ -19,7 +19,7 @@ noinst_PROGRAMS = wirecheck wiretest obdio obdbarrier
 # mount only finds helpers in /sbin
 rootsbin_PROGRAMS = mount.lustre
 sbin_PROGRAMS = mkfs.lustre tunefs.lustre lctl \
 # mount only finds helpers in /sbin
 rootsbin_PROGRAMS = mount.lustre
 sbin_PROGRAMS = mkfs.lustre tunefs.lustre lctl \
-       l_getidentity l_facl llverfs llverdev \
+       l_getidentity llverfs llverdev \
        llog_reader lr_reader
 if LIBPTHREAD
 sbin_PROGRAMS += loadgen
        llog_reader lr_reader
 if LIBPTHREAD
 sbin_PROGRAMS += loadgen
@@ -97,10 +97,6 @@ l_getidentity_SOURCES = l_getidentity.c
 l_getidentity_LDADD := $(LIBPTLCTL)
 l_getidentity_DEPENDENCIES := $(LIBPTLCTL)
 
 l_getidentity_LDADD := $(LIBPTLCTL)
 l_getidentity_DEPENDENCIES := $(LIBPTLCTL)
 
-l_facl_SOURCES = l_facl.c
-l_facl_LDADD := liblustreapi.a
-l_facl_DEPENDENCIES := liblustreapi.a
-
 EXTRA_DIST = $(sbin_scripts) $(bin_scripts)
 
 # NOTE: this should only be run on i386.
 EXTRA_DIST = $(sbin_scripts) $(bin_scripts)
 
 # NOTE: this should only be run on i386.
index cf267ad..840e14c 100644 (file)
@@ -53,6 +53,8 @@ static char *g_service = NULL;
  */
 struct lgss_nego_data {
         uint32_t        lnd_established:1;
  */
 struct lgss_nego_data {
         uint32_t        lnd_established:1;
+
+        int             lnd_secid;
         uint32_t        lnd_uid;
         uint32_t        lnd_lsvc;
         char           *lnd_uuid;
         uint32_t        lnd_uid;
         uint32_t        lnd_lsvc;
         char           *lnd_uuid;
@@ -82,8 +84,11 @@ struct lgss_init_res {
 
 struct keyring_upcall_param {
         uint32_t        kup_ver;
 
 struct keyring_upcall_param {
         uint32_t        kup_ver;
+        uint32_t        kup_secid;
         uint32_t        kup_uid;
         uint32_t        kup_uid;
+        uint32_t        kup_fsuid;
         uint32_t        kup_gid;
         uint32_t        kup_gid;
+        uint32_t        kup_fsgid;
         uint32_t        kup_svc;
         uint64_t        kup_nid;
         char            kup_tgt[64];
         uint32_t        kup_svc;
         uint64_t        kup_nid;
         char            kup_tgt[64];
@@ -118,6 +123,7 @@ int do_nego_rpc(struct lgss_nego_data *lnd,
         }
 
         param.version = GSSD_INTERFACE_VERSION;
         }
 
         param.version = GSSD_INTERFACE_VERSION;
+        param.secid = lnd->lnd_secid;
         param.uuid = lnd->lnd_uuid;
         param.lustre_svc = lnd->lnd_lsvc;
         param.uid = lnd->lnd_uid;
         param.uuid = lnd->lnd_uuid;
         param.lustre_svc = lnd->lnd_lsvc;
         param.uid = lnd->lnd_uid;
@@ -184,7 +190,7 @@ int do_nego_rpc(struct lgss_nego_data *lnd,
 /*
  * if return error, the lnd_rpc_err or lnd_gss_err is set.
  */
 /*
  * if return error, the lnd_rpc_err or lnd_gss_err is set.
  */
-int lgssc_negotiation(struct lgss_nego_data *lnd)
+static int lgssc_negotiation(struct lgss_nego_data *lnd)
 {
         struct lgss_init_res    gr;
         gss_buffer_desc        *recv_tokenp, send_token;
 {
         struct lgss_init_res    gr;
         gss_buffer_desc        *recv_tokenp, send_token;
@@ -289,15 +295,16 @@ int lgssc_negotiation(struct lgss_nego_data *lnd)
 /*
  * if return error, the lnd_rpc_err or lnd_gss_err is set.
  */
 /*
  * if return error, the lnd_rpc_err or lnd_gss_err is set.
  */
-int lgssc_init_nego_data(struct lgss_nego_data *lnd,
-                         struct keyring_upcall_param *kup,
-                         lgss_mech_t mech)
+static int lgssc_init_nego_data(struct lgss_nego_data *lnd,
+                                struct keyring_upcall_param *kup,
+                                lgss_mech_t mech)
 {
         gss_buffer_desc         sname;
         OM_uint32               maj_stat, min_stat;
 
         memset(lnd, 0, sizeof(*lnd));
 
 {
         gss_buffer_desc         sname;
         OM_uint32               maj_stat, min_stat;
 
         memset(lnd, 0, sizeof(*lnd));
 
+        lnd->lnd_secid = kup->kup_secid;
         lnd->lnd_uid = kup->kup_uid;
         lnd->lnd_lsvc = kup->kup_svc;
         lnd->lnd_uuid = kup->kup_tgt;
         lnd->lnd_uid = kup->kup_uid;
         lnd->lnd_lsvc = kup->kup_svc;
         lnd->lnd_uuid = kup->kup_tgt;
@@ -443,10 +450,10 @@ out:
 }
 
 /*
 }
 
 /*
- * note we can't assume authority in child process
+ * note we inherited assumed authority from parent process
  */
  */
-int lgssc_kr_negotiate(key_serial_t keyid, struct lgss_cred *cred,
-                       struct keyring_upcall_param *kup)
+static int lgssc_kr_negotiate(key_serial_t keyid, struct lgss_cred *cred,
+                              struct keyring_upcall_param *kup)
 {
         struct lgss_nego_data   lnd;
         gss_buffer_desc         token = GSS_C_EMPTY_BUFFER;
 {
         struct lgss_nego_data   lnd;
         gss_buffer_desc         token = GSS_C_EMPTY_BUFFER;
@@ -454,47 +461,28 @@ int lgssc_kr_negotiate(key_serial_t keyid, struct lgss_cred *cred,
         int                     rc = -1;
 
         logmsg(LL_TRACE, "child start on behalf of key %08x: "
         int                     rc = -1;
 
         logmsg(LL_TRACE, "child start on behalf of key %08x: "
-               "cred %p, uid %u, svc %u, nid %Lx\n", keyid, cred,
-               cred->lc_uid, cred->lc_tgt_svc, cred->lc_tgt_nid);
-
-        if (kup->kup_gid != 0 && setregid(kup->kup_gid, kup->kup_gid)) {
-                logmsg(LL_WARN, "key %08x, failed set gids to %u: %s\n",
-                       keyid, kup->kup_gid, strerror(errno));
-        }
-
-        if (kup->kup_uid != 0 && setreuid(kup->kup_uid, kup->kup_uid)) {
-                logmsg(LL_WARN, "key %08x, failed set uids to %u: %s\n",
-                       keyid, kup->kup_uid, strerror(errno));
-        }
-
-        /*
-         * link to session keyring, allow the key to be found.
-         */
-        if (keyctl_link(keyid, KEY_SPEC_SESSION_KEYRING)) {
-                logmsg(LL_ERR, "key %08x, failed to link to session "
-                       "keyring: %s\n", keyid, strerror(errno));
-                error_kernel_key(keyid, -EACCES, 0);
-                goto out_cred;
-        }
+               "cred %p, uid %u, svc %u, nid %Lx, uids: %u:%u/%u:%u\n",
+               keyid, cred, cred->lc_uid, cred->lc_tgt_svc, cred->lc_tgt_nid,
+               kup->kup_uid, kup->kup_gid, kup->kup_fsuid, kup->kup_fsgid);
 
         if (lgss_get_service_str(&g_service, kup->kup_svc, kup->kup_nid)) {
                 logmsg(LL_ERR, "key %08x: failed to construct service "
                        "string\n", keyid);
                 error_kernel_key(keyid, -EACCES, 0);
 
         if (lgss_get_service_str(&g_service, kup->kup_svc, kup->kup_nid)) {
                 logmsg(LL_ERR, "key %08x: failed to construct service "
                        "string\n", keyid);
                 error_kernel_key(keyid, -EACCES, 0);
-                goto out_unlink;
+                goto out_cred;
         }
 
         if (lgss_using_cred(cred)) {
                 logmsg(LL_ERR, "key %08x: can't using cred\n", keyid);
                 error_kernel_key(keyid, -EACCES, 0);
         }
 
         if (lgss_using_cred(cred)) {
                 logmsg(LL_ERR, "key %08x: can't using cred\n", keyid);
                 error_kernel_key(keyid, -EACCES, 0);
-                goto out_unlink;
+                goto out_cred;
         }
 
         if (lgssc_init_nego_data(&lnd, kup, cred->lc_mech->lmt_mech_n)) {
                 logmsg(LL_ERR, "key %08x: failed to initialize "
                        "negotiation data\n", keyid);
                 error_kernel_key(keyid, lnd.lnd_rpc_err, lnd.lnd_gss_err);
         }
 
         if (lgssc_init_nego_data(&lnd, kup, cred->lc_mech->lmt_mech_n)) {
                 logmsg(LL_ERR, "key %08x: failed to initialize "
                        "negotiation data\n", keyid);
                 error_kernel_key(keyid, lnd.lnd_rpc_err, lnd.lnd_gss_err);
-                goto out_unlink;
+                goto out_cred;
         }
 
         rc = lgssc_negotiation(&lnd);
         }
 
         rc = lgssc_negotiation(&lnd);
@@ -524,12 +512,6 @@ out:
 
         lgssc_fini_nego_data(&lnd);
 
 
         lgssc_fini_nego_data(&lnd);
 
-out_unlink:
-        if (keyctl_unlink(keyid, KEY_SPEC_SESSION_KEYRING)) {
-                logmsg(LL_WARN, "failed to unlink key %08x: %s\n",
-                       keyid, strerror(errno));
-        }
-
 out_cred:
         lgss_release_cred(cred);
         return rc;
 out_cred:
         lgss_release_cred(cred);
         return rc;
@@ -537,21 +519,24 @@ out_cred:
 
 /*
  * call out info format: s[:s]...
 
 /*
  * call out info format: s[:s]...
- *  [0]: mech_name      (string)
- *  [1]: flags          (chars) FMT: r-root; m-mds
- *  [2]: lustre_svc     (uint)
- *  [3]: target_nid     (uint64)
- *  [4]: target_uuid    (string)
+ *  [0]: secid          (uint)
+ *  [1]: mech_name      (string)
+ *  [2]: uid            (uint)
+ *  [3]: gid            (uint)
+ *  [4]: flags          (chars) FMT: r-root; m-mds
+ *  [5]: lustre_svc     (uint)
+ *  [6]: target_nid     (uint64)
+ *  [7]: target_uuid    (string)
  */
  */
-static
-int parse_callout_info(const char *coinfo,
-                       struct keyring_upcall_param *uparam)
+static int parse_callout_info(const char *coinfo,
+                              struct keyring_upcall_param *uparam)
 {
 {
-        char    buf[1024];
-        char   *string = buf;
-        int     length, i;
-        char   *data[5];
-        char   *pos;
+        const int       nargs = 8;
+        char            buf[1024];
+        char           *string = buf;
+        int             length, i;
+        char           *data[nargs];
+        char           *pos;
 
         length = strlen(coinfo) + 1;
         if (length > 1024) {
 
         length = strlen(coinfo) + 1;
         if (length > 1024) {
@@ -560,7 +545,7 @@ int parse_callout_info(const char *coinfo,
         }
         memcpy(buf, coinfo, length);
 
         }
         memcpy(buf, coinfo, length);
 
-        for (i = 0; i < 4; i++) {
+        for (i = 0; i < nargs - 1; i++) {
                 pos = strchr(string, ':');
                 if (pos == NULL) {
                         logmsg(LL_ERR, "short of components\n");
                 pos = strchr(string, ':');
                 if (pos == NULL) {
                         logmsg(LL_ERR, "short of components\n");
@@ -573,22 +558,28 @@ int parse_callout_info(const char *coinfo,
         }
         data[i] = string;
 
         }
         data[i] = string;
 
-        logmsg(LL_TRACE, "components: %s,%s,%s,%s,%s\n",
-               data[0], data[1], data[2], data[3], data[4], data[5]);
+        logmsg(LL_TRACE, "components: %s,%s,%s,%s,%s,%s,%s,%s\n",
+               data[0], data[1], data[2], data[3], data[4], data[5],
+               data[6], data[7]);
 
 
-        strncpy(uparam->kup_mech, data[0], sizeof(uparam->kup_mech));
-        if (strchr(data[1], 'r'))
+        uparam->kup_secid = strtol(data[0], NULL, 0);
+        strncpy(uparam->kup_mech, data[1], sizeof(uparam->kup_mech));
+        uparam->kup_uid = strtol(data[2], NULL, 0);
+        uparam->kup_gid = strtol(data[3], NULL, 0);
+        if (strchr(data[4], 'r'))
                 uparam->kup_is_root = 1;
                 uparam->kup_is_root = 1;
-        if (strchr(data[1], 'm'))
+        if (strchr(data[4], 'm'))
                 uparam->kup_is_mds = 1;
                 uparam->kup_is_mds = 1;
-        uparam->kup_svc = strtol(data[2], NULL, 0);
-        uparam->kup_nid = strtoll(data[3], NULL, 0);
-        strncpy(uparam->kup_tgt, data[4], sizeof(uparam->kup_tgt));
-
-        logmsg(LL_DEBUG, "parse call out info: mech %s, is_root %d, "
-               "is_mds %d, svc %d, nid 0x%Lx, tgt %s\n",
-               uparam->kup_mech, uparam->kup_is_root, uparam->kup_is_mds,
-               uparam->kup_svc, uparam->kup_nid, uparam->kup_tgt);
+        uparam->kup_svc = strtol(data[5], NULL, 0);
+        uparam->kup_nid = strtoll(data[6], NULL, 0);
+        strncpy(uparam->kup_tgt, data[7], sizeof(uparam->kup_tgt));
+
+        logmsg(LL_DEBUG, "parse call out info: secid %d, mech %s, ugid %u:%u "
+               "is_root %d, is_mds %d, svc %d, nid 0x%Lx, tgt %s\n",
+               uparam->kup_secid, uparam->kup_mech,
+               uparam->kup_uid, uparam->kup_gid,
+               uparam->kup_is_root, uparam->kup_is_mds, uparam->kup_svc,
+               uparam->kup_nid, uparam->kup_tgt);
         return 0;
 }
 
         return 0;
 }
 
@@ -625,8 +616,8 @@ int main(int argc, char *argv[])
                 return 1;
         }
 
                 return 1;
         }
 
-        logmsg(LL_INFO, "key %s, desc %s, uid %s, sring %s, coinfo %s\n",
-               argv[2], argv[4], argv[6], argv[10], argv[5]);
+        logmsg(LL_INFO, "key %s, desc %s, ugid %s:%s, sring %s, coinfo %s\n",
+               argv[2], argv[4], argv[6], argv[7], argv[10], argv[5]);
 
         memset(&uparam, 0, sizeof(uparam));
 
 
         memset(&uparam, 0, sizeof(uparam));
 
@@ -640,11 +631,16 @@ int main(int argc, char *argv[])
                 return 1;
         }
 
                 return 1;
         }
 
-        if (sscanf(argv[6], "%d", &uparam.kup_uid) != 1) {
+        if (sscanf(argv[6], "%d", &uparam.kup_fsuid) != 1) {
                 logmsg(LL_ERR, "can't extract UID: %s\n", argv[6]);
                 return 1;
         }
 
                 logmsg(LL_ERR, "can't extract UID: %s\n", argv[6]);
                 return 1;
         }
 
+        if (sscanf(argv[7], "%d", &uparam.kup_fsgid) != 1) {
+                logmsg(LL_ERR, "can't extract GID: %s\n", argv[7]);
+                return 1;
+        }
+
         if (sscanf(argv[10], "%d", &sring) != 1) {
                 logmsg(LL_ERR, "can't extract session keyring: %s\n", argv[10]);
                 return 1;
         if (sscanf(argv[10], "%d", &sring) != 1) {
                 logmsg(LL_ERR, "can't extract session keyring: %s\n", argv[10]);
                 return 1;
@@ -692,11 +688,16 @@ int main(int argc, char *argv[])
                 return 1;
         }
 
                 return 1;
         }
 
-        /*
-         * pre initialize the key
+        /* pre initialize the key. note the keyring linked to is actually of the
+         * original requesting process, not _this_ upcall process. if it's for
+         * root user, don't link to any keyrings because we want fully control
+         * on it, and share it among all root sessions; otherswise link to
+         * session keyring.
          */
          */
-        inst_keyring = (cred->lc_fl_root || cred->lc_fl_mds) ?
-                                0 : KEY_SPEC_SESSION_KEYRING;
+        if (cred->lc_fl_root || cred->lc_fl_mds)
+                inst_keyring = 0;
+        else
+                inst_keyring = KEY_SPEC_SESSION_KEYRING;
 
         if (keyctl_instantiate(keyid, NULL, 0, inst_keyring)) {
                 logmsg(LL_ERR, "instantiate key %08x: %s\n",
 
         if (keyctl_instantiate(keyid, NULL, 0, inst_keyring)) {
                 logmsg(LL_ERR, "instantiate key %08x: %s\n",
index 0a4d44d..7ebbfd2 100644 (file)
@@ -232,9 +232,9 @@ int princ_is_local_realm(krb5_context ctx, krb5_principal princ)
 }
 
 static
 }
 
 static
-int svc_princ_is_local_host(krb5_context ctx,
-                            krb5_principal princ,
-                            loglevel_t loglevel)
+int svc_princ_verify_host(krb5_context ctx,
+                          krb5_principal princ,
+                          loglevel_t loglevel)
 {
         struct utsname utsbuf;
         struct hostent *host;
 {
         struct utsname utsbuf;
         struct hostent *host;
@@ -297,17 +297,24 @@ int lkrb5_cc_check_tgt_princ(krb5_context ctx,
                 return -1;
         }
 
                 return -1;
         }
 
-        /* if it's mds service principal, check hostname */
+        /* if it's mds service principal, or lustre_root principal
+         * with host part, verify the hostname.
+         * note we allow lustre_root without host part */
         if (lgss_krb5_strcmp(krb5_princ_name(ctx, princ),
                              LGSS_SVC_MDS_STR) == 0) {
         if (lgss_krb5_strcmp(krb5_princ_name(ctx, princ),
                              LGSS_SVC_MDS_STR) == 0) {
-                if (svc_princ_is_local_host(ctx, princ, LL_WARN)) {
-                        logmsg(LL_WARN, "mds service principal not belongs "
+                if (svc_princ_verify_host(ctx, princ, LL_WARN)) {
+                        logmsg(LL_WARN, "mds service principal doesn't belong "
                                "to this node\n");
                         return -1;
                 }
         } else if (lgss_krb5_strcmp(krb5_princ_name(ctx, princ),
                                "to this node\n");
                         return -1;
                 }
         } else if (lgss_krb5_strcmp(krb5_princ_name(ctx, princ),
-                                    LGSS_USR_ROOT_STR)) {
-                /* do nothing */
+                                    LGSS_USR_ROOT_STR) == 0) {
+                if (krb5_princ_component(ctx, princ, 1) != NULL &&
+                    svc_princ_verify_host(ctx, princ, LL_WARN)) {
+                        logmsg(LL_WARN, "lustre_root principal doesn't belong "
+                               "to this node\n");
+                        return -1;
+                }
         } else {
                 logmsg(LL_WARN, "unexpected krb5 cc principal name %.*s\n",
                        krb5_princ_name(ctx, princ)->length,
         } else {
                 logmsg(LL_WARN, "unexpected krb5 cc principal name %.*s\n",
                        krb5_princ_name(ctx, princ)->length,
@@ -556,8 +563,9 @@ int lkrb5_refresh_root_tgt_cc(krb5_context ctx,
         krb5_keytab             kt;
         krb5_keytab_entry       kte;
         krb5_kt_cursor          cursor;
         krb5_keytab             kt;
         krb5_keytab_entry       kte;
         krb5_kt_cursor          cursor;
-        krb5_principal          princ = NULL;
+        krb5_principal          princ = NULL, princ2;
         krb5_error_code         code;
         krb5_error_code         code;
+        int                     general_root = 0;
         int                     rc = -1;
 
         /* prepare parsing the keytab file */
         int                     rc = -1;
 
         /* prepare parsing the keytab file */
@@ -592,32 +600,59 @@ int lkrb5_refresh_root_tgt_cc(krb5_context ctx,
                 if (!princ_is_local_realm(ctx, kte.principal))
                         continue;
 
                 if (!princ_is_local_realm(ctx, kte.principal))
                         continue;
 
-                /* lustre_root@realm */
+                /* lustre_root[/host]@realm */
                 if (lgss_krb5_strcmp(krb5_princ_name(ctx, kte.principal),
                                      LGSS_USR_ROOT_STR) == 0) {
                 if (lgss_krb5_strcmp(krb5_princ_name(ctx, kte.principal),
                                      LGSS_USR_ROOT_STR) == 0) {
-                        if (princ != NULL) {
-                                logmsg(LL_WARN, "already picked one? "
-                                       "how could it possible???\n");
-                                continue;
+                        int tmp_general_root = 0;
+
+                        if (krb5_princ_component(ctx, kte.principal,1) == NULL){
+                                if (princ != NULL) {
+                                        logmsg(LL_TRACE, "lustre_root: "
+                                               "already picked one, skip\n");
+                                        continue;
+                                }
+
+                                tmp_general_root = 1;
+                        } else {
+                                if (svc_princ_verify_host(ctx, kte.principal,
+                                                          LL_TRACE)) {
+                                        logmsg(LL_TRACE, "lustre_root: "
+                                               "doesn't belong to this node\n");
+                                        continue;
+                                }
+
+                                if (princ != NULL && !general_root) {
+                                        logmsg(LL_TRACE, "lustre_root: already "
+                                               "have a host-specific one, "
+                                               "skip\n");
+                                        continue;
+                                }
                         }
 
                         }
 
-                        code = krb5_copy_principal(ctx, kte.principal, &princ);
-                        if (code)
+                        code = krb5_copy_principal(ctx, kte.principal, &princ2);
+                        if (code) {
                                 logmsg(LL_ERR, "copy lustre_root princ: %s\n",
                                        krb5_err_msg(code));
                                 logmsg(LL_ERR, "copy lustre_root princ: %s\n",
                                        krb5_err_msg(code));
+                                continue;
+                        }
+
+                        if (princ != NULL) {
+                                logmsg(LL_TRACE, "release a lustre_root one\n");
+                                krb5_free_principal(ctx, princ);
+                        }
+                        princ = princ2;
 
 
+                        general_root = tmp_general_root;
                         continue;
                 }
 
                 /* lustre_mds/host@realm */
                 if (lgss_krb5_strcmp(krb5_princ_name(ctx, kte.principal),
                                      LGSS_SVC_MDS_STR) == 0) {
                         continue;
                 }
 
                 /* lustre_mds/host@realm */
                 if (lgss_krb5_strcmp(krb5_princ_name(ctx, kte.principal),
                                      LGSS_SVC_MDS_STR) == 0) {
-                        krb5_principal  princ2;
-
-                        if (svc_princ_is_local_host(ctx, kte.principal,
-                                                    LL_TRACE)) {
+                        if (svc_princ_verify_host(ctx, kte.principal,
+                                                  LL_TRACE)) {
                                 logmsg(LL_TRACE, "mds service principal: "
                                 logmsg(LL_TRACE, "mds service principal: "
-                                       "not belongs to this node\n");
+                                       "doesn't belong to this node\n");
                                 continue;
                         }
 
                                 continue;
                         }
 
index a5f0146..b629cb6 100644 (file)
@@ -586,7 +586,7 @@ libcfs_str2nid(char *str)
 #define MAX_LINE_LEN            256
 
 struct user_map_item {
 #define MAX_LINE_LEN            256
 
 struct user_map_item {
-        char        *principal; /* NULL means match all, will cause multi->single mapped, FORBID */
+        char        *principal; /* NULL means match all */
         lnet_nid_t   nid;
         uid_t        uid;
 };
         lnet_nid_t   nid;
         uid_t        uid;
 };
@@ -604,7 +604,9 @@ void cleanup_mapping(void)
 {
         if (mapping.items) {
                 for (; mapping.nitems > 0; mapping.nitems--)
 {
         if (mapping.items) {
                 for (; mapping.nitems > 0; mapping.nitems--)
-                        free(mapping.items[mapping.nitems - 1].principal);
+                        if (mapping.items[mapping.nitems-1].principal)
+                                free(mapping.items[mapping.nitems-1].principal);
+
                 free(mapping.items);
                 mapping.items = NULL;
         }
                 free(mapping.items);
                 mapping.items = NULL;
         }
@@ -630,7 +632,8 @@ static int grow_mapping(int nitems)
         }
 
         if (mapping.items) {
         }
 
         if (mapping.items) {
-                memcpy(new, mapping.items, mapping.nitems * sizeof(struct user_map_item));
+                memcpy(new, mapping.items,
+                       mapping.nitems * sizeof(struct user_map_item));
                 free(mapping.items);
         }
         mapping.items = new;
                 free(mapping.items);
         }
         mapping.items = new;
@@ -690,8 +693,7 @@ static int read_mapping_db(void)
                 }
 
                 if (!strcmp(princ, "*")) {
                 }
 
                 if (!strcmp(princ, "*")) {
-                        printerr(0, "NOT permit \"*\" princ, it will cause multi->single mapped\n");
-                        continue;
+                        name = NULL;
                 } else {
                         name = strdup(princ);
                         if (!name) {
                 } else {
                         name = strdup(princ);
                         if (!name) {
@@ -706,6 +708,7 @@ static int read_mapping_db(void)
                         nid = libcfs_str2nid(nid_str);
                         if (nid == LNET_NID_ANY) {
                                 printerr(0, "fail to parse nid %s\n", nid_str);
                         nid = libcfs_str2nid(nid_str);
                         if (nid == LNET_NID_ANY) {
                                 printerr(0, "fail to parse nid %s\n", nid_str);
+                                if (name)
                                 free(name);
                                 continue;
                         }
                                 free(name);
                                 continue;
                         }
@@ -714,6 +717,7 @@ static int read_mapping_db(void)
                 dest_uid = parse_uid(dest);
                 if (dest_uid == -1) {
                         printerr(0, "no valid user: %s\n", dest);
                 dest_uid = parse_uid(dest);
                 if (dest_uid == -1) {
                         printerr(0, "no valid user: %s\n", dest);
+                        if (name)
                         free(name);
                         continue;
                 }
                         free(name);
                         continue;
                 }
@@ -721,6 +725,7 @@ static int read_mapping_db(void)
                 if (grow_mapping(mapping.nitems + 1)) {
                         printerr(0, "fail to grow mapping to %d\n",
                                  mapping.nitems + 1);
                 if (grow_mapping(mapping.nitems + 1)) {
                         printerr(0, "fail to grow mapping to %d\n",
                                  mapping.nitems + 1);
+                        if (name)
                         free(name);
                         fclose(f);
                         return -1;
                         free(name);
                         fclose(f);
                         return -1;
@@ -780,7 +785,7 @@ int lookup_mapping(char *princ, lnet_nid_t nid, uid_t *uid)
 
                 if (entry->nid != LNET_NID_ANY && entry->nid != nid)
                         continue;
 
                 if (entry->nid != LNET_NID_ANY && entry->nid != nid)
                         continue;
-                if (!strcasecmp(entry->principal, princ)) {
+                if (!entry->principal || !strcasecmp(entry->principal, princ)) {
                         printerr(1, "found mapping: %s ==> %d\n",
                                  princ, entry->uid);
                         *uid = entry->uid;
                         printerr(1, "found mapping: %s ==> %d\n",
                                  princ, entry->uid);
                         *uid = entry->uid;
index 6739804..6748ecd 100644 (file)
@@ -36,6 +36,7 @@ struct lgssd_upcall_data {
 
 struct lgssd_ioctl_param {
         int             version;        /* in   */
 
 struct lgssd_ioctl_param {
         int             version;        /* in   */
+        int             secid;          /* in   */
         char           *uuid;           /* in   */
         int             lustre_svc;     /* in   */
         uid_t           uid;            /* in   */
         char           *uuid;           /* in   */
         int             lustre_svc;     /* in   */
         uid_t           uid;            /* in   */
index 46efbcf..e0f551b 100644 (file)
@@ -1,6 +1,6 @@
-diff -Nrup nfs-utils-1.0.11/configure.in nfs-utils-1.0.11.lustre/configure.in
---- nfs-utils-1.0.11/configure.in      2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11.lustre/configure.in       2007-06-29 12:29:20.000000000 -0600
+diff -Nrup nfs-utils-1.0.11.lustre/configure.in nfs-utils-1.0.11/configure.in
+--- nfs-utils-1.0.11.lustre/configure.in       2007-02-21 21:50:03.000000000 -0700
++++ nfs-utils-1.0.11/configure.in      2008-01-02 18:10:29.000000000 -0700
 @@ -18,61 +18,14 @@ AC_ARG_WITH(release,
        RELEASE=$withval,
        RELEASE=1)
 @@ -18,61 +18,14 @@ AC_ARG_WITH(release,
        RELEASE=$withval,
        RELEASE=1)
@@ -191,9 +191,9 @@ diff -Nrup nfs-utils-1.0.11/configure.in nfs-utils-1.0.11.lustre/configure.in
 +      utils/gssd/Makefile])
  AC_OUTPUT
  
 +      utils/gssd/Makefile])
  AC_OUTPUT
  
-diff -Nrup nfs-utils-1.0.11/Makefile.am nfs-utils-1.0.11.lustre/Makefile.am
---- nfs-utils-1.0.11/Makefile.am       2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11.lustre/Makefile.am        2007-06-29 12:29:20.000000000 -0600
+diff -Nrup nfs-utils-1.0.11.lustre/Makefile.am nfs-utils-1.0.11/Makefile.am
+--- nfs-utils-1.0.11.lustre/Makefile.am        2007-02-21 21:50:03.000000000 -0700
++++ nfs-utils-1.0.11/Makefile.am       2008-01-02 18:10:29.000000000 -0700
 @@ -1,6 +1,6 @@
  ## Process this file with automake to produce Makefile.in
  
 @@ -1,6 +1,6 @@
  ## Process this file with automake to produce Makefile.in
  
@@ -202,9 +202,9 @@ diff -Nrup nfs-utils-1.0.11/Makefile.am nfs-utils-1.0.11.lustre/Makefile.am
  
  MAINTAINERCLEANFILES = Makefile.in
  
  
  MAINTAINERCLEANFILES = Makefile.in
  
-diff -Nrup nfs-utils-1.0.11/utils/gssd/cacheio.c nfs-utils-1.0.11.lustre/utils/gssd/cacheio.c
---- nfs-utils-1.0.11/utils/gssd/cacheio.c      2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11.lustre/utils/gssd/cacheio.c       2007-06-29 12:32:27.000000000 -0600
+diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/cacheio.c nfs-utils-1.0.11/utils/gssd/cacheio.c
+--- nfs-utils-1.0.11.lustre/utils/gssd/cacheio.c       2007-02-21 21:50:03.000000000 -0700
++++ nfs-utils-1.0.11/utils/gssd/cacheio.c      2008-01-02 18:11:38.000000000 -0700
 @@ -240,7 +240,8 @@ int qword_get(char **bpp, char *dest, in
                return -1;
        while (*bp == ' ') bp++;
 @@ -240,7 +240,8 @@ int qword_get(char **bpp, char *dest, in
                return -1;
        while (*bp == ' ') bp++;
@@ -215,9 +215,9 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/cacheio.c nfs-utils-1.0.11.lustre/utils/g
        return len;
  }
  
        return len;
  }
  
-diff -Nrup nfs-utils-1.0.11/utils/gssd/context.c nfs-utils-1.0.11.lustre/utils/gssd/context.c
---- nfs-utils-1.0.11/utils/gssd/context.c      2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11.lustre/utils/gssd/context.c       2007-06-29 12:32:28.000000000 -0600
+diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context.c nfs-utils-1.0.11/utils/gssd/context.c
+--- nfs-utils-1.0.11.lustre/utils/gssd/context.c       2007-02-21 21:50:03.000000000 -0700
++++ nfs-utils-1.0.11/utils/gssd/context.c      2008-01-02 18:11:38.000000000 -0700
 @@ -33,11 +33,14 @@
  #include <syslog.h>
  #include <string.h>
 @@ -33,11 +33,14 @@
  #include <syslog.h>
  #include <string.h>
@@ -238,9 +238,9 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/context.c nfs-utils-1.0.11.lustre/utils/g
  #include "context.h"
  
  int
  #include "context.h"
  
  int
-diff -Nrup nfs-utils-1.0.11/utils/gssd/context.h nfs-utils-1.0.11.lustre/utils/gssd/context.h
---- nfs-utils-1.0.11/utils/gssd/context.h      2007-06-29 12:28:01.000000000 -0600
-+++ nfs-utils-1.0.11.lustre/utils/gssd/context.h       2007-06-29 12:32:29.000000000 -0600
+diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context.h nfs-utils-1.0.11/utils/gssd/context.h
+--- nfs-utils-1.0.11.lustre/utils/gssd/context.h       2008-01-02 17:22:48.000000000 -0700
++++ nfs-utils-1.0.11/utils/gssd/context.h      2008-01-02 18:11:38.000000000 -0700
 @@ -31,8 +31,6 @@
  #ifndef _CONTEXT_H_
  #define _CONTEXT_H_
 @@ -31,8 +31,6 @@
  #ifndef _CONTEXT_H_
  #define _CONTEXT_H_
@@ -250,9 +250,9 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/context.h nfs-utils-1.0.11.lustre/utils/g
  /* Hopefully big enough to hold any serialized context */
  #define MAX_CTX_LEN 4096
  
  /* Hopefully big enough to hold any serialized context */
  #define MAX_CTX_LEN 4096
  
-diff -Nrup nfs-utils-1.0.11/utils/gssd/context_heimdal.c nfs-utils-1.0.11.lustre/utils/gssd/context_heimdal.c
---- nfs-utils-1.0.11/utils/gssd/context_heimdal.c      2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11.lustre/utils/gssd/context_heimdal.c       2007-06-29 12:32:29.000000000 -0600
+diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context_heimdal.c nfs-utils-1.0.11/utils/gssd/context_heimdal.c
+--- nfs-utils-1.0.11.lustre/utils/gssd/context_heimdal.c       2007-02-21 21:50:03.000000000 -0700
++++ nfs-utils-1.0.11/utils/gssd/context_heimdal.c      2008-01-02 18:11:38.000000000 -0700
 @@ -43,8 +43,13 @@
  #ifdef HAVE_COM_ERR_H
  #include <com_err.h>
 @@ -43,8 +43,13 @@
  #ifdef HAVE_COM_ERR_H
  #include <com_err.h>
@@ -269,9 +269,9 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/context_heimdal.c nfs-utils-1.0.11.lustre
  #include "write_bytes.h"
  
  int write_heimdal_keyblock(char **p, char *end, krb5_keyblock *key)
  #include "write_bytes.h"
  
  int write_heimdal_keyblock(char **p, char *end, krb5_keyblock *key)
-diff -Nrup nfs-utils-1.0.11/utils/gssd/context_lucid.c nfs-utils-1.0.11.lustre/utils/gssd/context_lucid.c
---- nfs-utils-1.0.11/utils/gssd/context_lucid.c        2007-06-29 12:28:01.000000000 -0600
-+++ nfs-utils-1.0.11.lustre/utils/gssd/context_lucid.c 2007-06-29 12:32:30.000000000 -0600
+diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context_lucid.c nfs-utils-1.0.11/utils/gssd/context_lucid.c
+--- nfs-utils-1.0.11.lustre/utils/gssd/context_lucid.c 2008-01-02 17:22:48.000000000 -0700
++++ nfs-utils-1.0.11/utils/gssd/context_lucid.c        2008-01-02 18:11:38.000000000 -0700
 @@ -41,11 +41,7 @@
  #include <syslog.h>
  #include <string.h>
 @@ -41,11 +41,7 @@
  #include <syslog.h>
  #include <string.h>
@@ -410,10 +410,10 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/context_lucid.c nfs-utils-1.0.11.lustre/u
        maj_stat = gss_export_lucid_sec_context(&min_stat, &ctx,
                                                1, &return_ctx);
        if (maj_stat != GSS_S_COMPLETE) {
        maj_stat = gss_export_lucid_sec_context(&min_stat, &ctx,
                                                1, &return_ctx);
        if (maj_stat != GSS_S_COMPLETE) {
-diff -Nrup nfs-utils-1.0.11/utils/gssd/context_mit.c nfs-utils-1.0.11.lustre/utils/gssd/context_mit.c
---- nfs-utils-1.0.11/utils/gssd/context_mit.c  2007-06-29 12:28:01.000000000 -0600
-+++ nfs-utils-1.0.11.lustre/utils/gssd/context_mit.c   2007-06-29 12:32:30.000000000 -0600
-@@ -39,10 +39,14 @@
+diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context_mit.c nfs-utils-1.0.11/utils/gssd/context_mit.c
+--- nfs-utils-1.0.11.lustre/utils/gssd/context_mit.c   2008-01-02 17:22:48.000000000 -0700
++++ nfs-utils-1.0.11/utils/gssd/context_mit.c  2008-01-02 18:11:38.000000000 -0700
+@@ -39,10 +39,15 @@
  #include <errno.h>
  #include <gssapi/gssapi.h>
  #include <rpc/rpc.h>
  #include <errno.h>
  #include <gssapi/gssapi.h>
  #include <rpc/rpc.h>
@@ -424,6 +424,7 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/context_mit.c nfs-utils-1.0.11.lustre/uti
 +
 +#ifdef _NEW_BUILD_
 +# include "lgss_utils.h"
 +
 +#ifdef _NEW_BUILD_
 +# include "lgss_utils.h"
++# include "write_bytes.h"
 +#else
 +# include "gss_util.h"
 +# include "gss_oids.h"
 +#else
 +# include "gss_util.h"
 +# include "gss_oids.h"
@@ -432,7 +433,7 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/context_mit.c nfs-utils-1.0.11.lustre/uti
  #include "context.h"
  
  #include <krb5.h>
  #include "context.h"
  
  #include <krb5.h>
-@@ -333,12 +337,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
+@@ -333,12 +338,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
                 * keydata-2;                (  Ki  (Kseq for DES3) )
                 * keydata-3;                (  Kc (derived checksum key) )
                 */
                 * keydata-2;                (  Ki  (Kseq for DES3) )
                 * keydata-3;                (  Kc (derived checksum key) )
                 */
@@ -446,9 +447,9 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/context_mit.c nfs-utils-1.0.11.lustre/uti
                if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
  
                /* Only applicable flag for this is initiator */
                if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
  
                /* Only applicable flag for this is initiator */
-diff -Nrup nfs-utils-1.0.11/utils/gssd/context_spkm3.c nfs-utils-1.0.11.lustre/utils/gssd/context_spkm3.c
---- nfs-utils-1.0.11/utils/gssd/context_spkm3.c        2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11.lustre/utils/gssd/context_spkm3.c 2007-06-29 12:32:31.000000000 -0600
+diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context_spkm3.c nfs-utils-1.0.11/utils/gssd/context_spkm3.c
+--- nfs-utils-1.0.11.lustre/utils/gssd/context_spkm3.c 2007-02-21 21:50:03.000000000 -0700
++++ nfs-utils-1.0.11/utils/gssd/context_spkm3.c        2008-01-02 18:11:38.000000000 -0700
 @@ -33,8 +33,6 @@
  #include <syslog.h>
  #include <string.h>
 @@ -33,8 +33,6 @@
  #include <syslog.h>
  #include <string.h>
@@ -458,9 +459,9 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/context_spkm3.c nfs-utils-1.0.11.lustre/u
  #include "gss_util.h"
  #include "gss_oids.h"
  #include "err_util.h"
  #include "gss_util.h"
  #include "gss_oids.h"
  #include "err_util.h"
-diff -Nrup nfs-utils-1.0.11/utils/gssd/err_util.c nfs-utils-1.0.11.lustre/utils/gssd/err_util.c
---- nfs-utils-1.0.11/utils/gssd/err_util.c     2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11.lustre/utils/gssd/err_util.c      2007-06-29 12:32:31.000000000 -0600
+diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/err_util.c nfs-utils-1.0.11/utils/gssd/err_util.c
+--- nfs-utils-1.0.11.lustre/utils/gssd/err_util.c      2007-02-21 21:50:03.000000000 -0700
++++ nfs-utils-1.0.11/utils/gssd/err_util.c     2008-01-02 18:11:38.000000000 -0700
 @@ -32,6 +32,8 @@
  #include <stdarg.h>
  #include <syslog.h>
 @@ -32,6 +32,8 @@
  #include <stdarg.h>
  #include <syslog.h>
@@ -511,9 +512,9 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/err_util.c nfs-utils-1.0.11.lustre/utils/
 +      }
 +}
 +
 +      }
 +}
 +
-diff -Nrup nfs-utils-1.0.11/utils/gssd/err_util.h nfs-utils-1.0.11.lustre/utils/gssd/err_util.h
---- nfs-utils-1.0.11/utils/gssd/err_util.h     2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11.lustre/utils/gssd/err_util.h      2007-06-29 12:32:32.000000000 -0600
+diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/err_util.h nfs-utils-1.0.11/utils/gssd/err_util.h
+--- nfs-utils-1.0.11.lustre/utils/gssd/err_util.h      2007-02-21 21:50:03.000000000 -0700
++++ nfs-utils-1.0.11/utils/gssd/err_util.h     2008-01-02 18:11:38.000000000 -0700
 @@ -33,5 +33,6 @@
  
  void initerr(char *progname, int verbosity, int fg);
 @@ -33,5 +33,6 @@
  
  void initerr(char *progname, int verbosity, int fg);
@@ -521,9 +522,9 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/err_util.h nfs-utils-1.0.11.lustre/utils/
 +void print_hexl(int pri, unsigned char *cp, int length);
  
  #endif /* _ERR_UTIL_H_ */
 +void print_hexl(int pri, unsigned char *cp, int length);
  
  #endif /* _ERR_UTIL_H_ */
-diff -Nrup nfs-utils-1.0.11/utils/gssd/gss_clnt_send_err.c nfs-utils-1.0.11.lustre/utils/gssd/gss_clnt_send_err.c
---- nfs-utils-1.0.11/utils/gssd/gss_clnt_send_err.c    2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11.lustre/utils/gssd/gss_clnt_send_err.c     2007-06-29 12:29:20.000000000 -0600
+diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gss_clnt_send_err.c nfs-utils-1.0.11/utils/gssd/gss_clnt_send_err.c
+--- nfs-utils-1.0.11.lustre/utils/gssd/gss_clnt_send_err.c     2007-02-21 21:50:03.000000000 -0700
++++ nfs-utils-1.0.11/utils/gssd/gss_clnt_send_err.c    2008-01-02 18:10:29.000000000 -0700
 @@ -47,6 +47,7 @@
  #include "gssd.h"
  #include "write_bytes.h"
 @@ -47,6 +47,7 @@
  #include "gssd.h"
  #include "write_bytes.h"
@@ -537,9 +538,9 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/gss_clnt_send_err.c nfs-utils-1.0.11.lust
        exit(0);
  }
 +#endif
        exit(0);
  }
 +#endif
-diff -Nrup nfs-utils-1.0.11/utils/gssd/gssd.c nfs-utils-1.0.11.lustre/utils/gssd/gssd.c
---- nfs-utils-1.0.11/utils/gssd/gssd.c 2007-06-29 12:28:01.000000000 -0600
-+++ nfs-utils-1.0.11.lustre/utils/gssd/gssd.c  2007-06-29 12:32:36.000000000 -0600
+diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gssd.c nfs-utils-1.0.11/utils/gssd/gssd.c
+--- nfs-utils-1.0.11.lustre/utils/gssd/gssd.c  2008-01-02 17:22:48.000000000 -0700
++++ nfs-utils-1.0.11/utils/gssd/gssd.c 2008-01-02 18:11:38.000000000 -0700
 @@ -38,9 +38,12 @@
  
  #include "config.h"
 @@ -38,9 +38,12 @@
  
  #include "config.h"
@@ -766,9 +767,9 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/gssd.c nfs-utils-1.0.11.lustre/utils/gssd
 +      printerr(0, "lgssd exiting\n");
 +      return 0;
  }
 +      printerr(0, "lgssd exiting\n");
 +      return 0;
  }
-diff -Nrup nfs-utils-1.0.11/utils/gssd/gssd.h nfs-utils-1.0.11.lustre/utils/gssd/gssd.h
---- nfs-utils-1.0.11/utils/gssd/gssd.h 2007-06-29 12:28:01.000000000 -0600
-+++ nfs-utils-1.0.11.lustre/utils/gssd/gssd.h  2007-06-29 12:32:37.000000000 -0600
+diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gssd.h nfs-utils-1.0.11/utils/gssd/gssd.h
+--- nfs-utils-1.0.11.lustre/utils/gssd/gssd.h  2008-01-02 17:22:48.000000000 -0700
++++ nfs-utils-1.0.11/utils/gssd/gssd.h 2008-01-02 18:11:38.000000000 -0700
 @@ -48,8 +48,13 @@
  #define GSSD_DEFAULT_CRED_PREFIX              "krb5cc_"
  #define GSSD_DEFAULT_MACHINE_CRED_SUFFIX      "machine"
 @@ -48,8 +48,13 @@
  #define GSSD_DEFAULT_CRED_PREFIX              "krb5cc_"
  #define GSSD_DEFAULT_MACHINE_CRED_SUFFIX      "machine"
@@ -824,10 +825,21 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/gssd.h nfs-utils-1.0.11.lustre/utils/gssd
 +void lgssd_mutex_put(int semid);
  
  #endif /* _RPC_GSSD_H_ */
 +void lgssd_mutex_put(int semid);
  
  #endif /* _RPC_GSSD_H_ */
-diff -Nrup nfs-utils-1.0.11/utils/gssd/gssd_main_loop.c nfs-utils-1.0.11.lustre/utils/gssd/gssd_main_loop.c
---- nfs-utils-1.0.11/utils/gssd/gssd_main_loop.c       2007-06-29 12:28:01.000000000 -0600
-+++ nfs-utils-1.0.11.lustre/utils/gssd/gssd_main_loop.c        2007-06-29 12:32:38.000000000 -0600
-@@ -94,11 +94,13 @@ scan_poll_results(int ret)
+diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gssd_main_loop.c nfs-utils-1.0.11/utils/gssd/gssd_main_loop.c
+--- nfs-utils-1.0.11.lustre/utils/gssd/gssd_main_loop.c        2008-01-02 17:22:48.000000000 -0700
++++ nfs-utils-1.0.11/utils/gssd/gssd_main_loop.c       2008-01-02 18:11:38.000000000 -0700
+@@ -44,6 +44,10 @@
+ #include <fcntl.h>
+ #include <signal.h>
+ #include <unistd.h>
++/* For time() */
++#include <time.h>
++/* For waitpid() */
++#include <wait.h>
+ #include "gssd.h"
+ #include "err_util.h"
+@@ -94,11 +98,13 @@ scan_poll_results(int ret)
  };
  
  void
  };
  
  void
@@ -842,7 +854,7 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/gssd_main_loop.c nfs-utils-1.0.11.lustre/
  
        /* Taken from linux/Documentation/dnotify.txt: */
        dn_act.sa_sigaction = dir_notify_handler;
  
        /* Taken from linux/Documentation/dnotify.txt: */
        dn_act.sa_sigaction = dir_notify_handler;
-@@ -106,10 +108,10 @@ gssd_run()
+@@ -106,10 +112,10 @@ gssd_run()
        dn_act.sa_flags = SA_SIGINFO;
        sigaction(DNOTIFY_SIGNAL, &dn_act, NULL);
  
        dn_act.sa_flags = SA_SIGINFO;
        sigaction(DNOTIFY_SIGNAL, &dn_act, NULL);
  
@@ -856,7 +868,7 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/gssd_main_loop.c nfs-utils-1.0.11.lustre/
        }
        fcntl(fd, F_SETSIG, DNOTIFY_SIGNAL);
        fcntl(fd, F_NOTIFY, DN_CREATE|DN_DELETE|DN_MODIFY|DN_MULTISHOT);
        }
        fcntl(fd, F_SETSIG, DNOTIFY_SIGNAL);
        fcntl(fd, F_NOTIFY, DN_CREATE|DN_DELETE|DN_MODIFY|DN_MULTISHOT);
-@@ -119,12 +121,30 @@ gssd_run()
+@@ -119,12 +125,30 @@ gssd_run()
        while (1) {
                while (dir_changed) {
                        dir_changed = 0;
        while (1) {
                while (dir_changed) {
                        dir_changed = 0;
@@ -888,7 +900,7 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/gssd_main_loop.c nfs-utils-1.0.11.lustre/
                /* race condition here: dir_changed could be set before we
                 * enter the poll, and we'd never notice if it weren't for the
                 * timeout. */
                /* race condition here: dir_changed could be set before we
                 * enter the poll, and we'd never notice if it weren't for the
                 * timeout. */
-@@ -139,6 +159,7 @@ gssd_run()
+@@ -139,6 +163,7 @@ gssd_run()
                        scan_poll_results(ret);
                }
        }
                        scan_poll_results(ret);
                }
        }
@@ -896,9 +908,9 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/gssd_main_loop.c nfs-utils-1.0.11.lustre/
        close(fd);
        return;
  }
        close(fd);
        return;
  }
-diff -Nrup nfs-utils-1.0.11/utils/gssd/gssd_proc.c nfs-utils-1.0.11.lustre/utils/gssd/gssd_proc.c
---- nfs-utils-1.0.11/utils/gssd/gssd_proc.c    2007-06-29 12:28:01.000000000 -0600
-+++ nfs-utils-1.0.11.lustre/utils/gssd/gssd_proc.c     2007-06-29 12:32:38.000000000 -0600
+diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gssd_proc.c nfs-utils-1.0.11/utils/gssd/gssd_proc.c
+--- nfs-utils-1.0.11.lustre/utils/gssd/gssd_proc.c     2008-01-02 17:22:48.000000000 -0700
++++ nfs-utils-1.0.11/utils/gssd/gssd_proc.c    2008-01-02 18:11:38.000000000 -0700
 @@ -43,7 +43,6 @@
  #endif
  #include "config.h"
 @@ -43,7 +43,6 @@
  #endif
  #include "config.h"
@@ -1700,9 +1712,9 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/gssd_proc.c nfs-utils-1.0.11.lustre/utils
        goto out;
 +#endif
  }
        goto out;
 +#endif
  }
-diff -Nrup nfs-utils-1.0.11/utils/gssd/gss_util.c nfs-utils-1.0.11.lustre/utils/gssd/gss_util.c
---- nfs-utils-1.0.11/utils/gssd/gss_util.c     2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11.lustre/utils/gssd/gss_util.c      2007-06-29 12:32:40.000000000 -0600
+diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gss_util.c nfs-utils-1.0.11/utils/gssd/gss_util.c
+--- nfs-utils-1.0.11.lustre/utils/gssd/gss_util.c      2007-02-21 21:50:03.000000000 -0700
++++ nfs-utils-1.0.11/utils/gssd/gss_util.c     2008-01-02 18:11:38.000000000 -0700
 @@ -87,9 +87,16 @@
  #ifdef HAVE_COM_ERR_H
  #include <com_err.h>
 @@ -87,9 +87,16 @@
  #ifdef HAVE_COM_ERR_H
  #include <com_err.h>
@@ -1916,9 +1928,9 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/gss_util.c nfs-utils-1.0.11.lustre/utils/
 +      return retval;
 +}
 +
 +      return retval;
 +}
 +
-diff -Nrup nfs-utils-1.0.11/utils/gssd/gss_util.h nfs-utils-1.0.11.lustre/utils/gssd/gss_util.h
---- nfs-utils-1.0.11/utils/gssd/gss_util.h     2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11.lustre/utils/gssd/gss_util.h      2007-06-29 12:32:41.000000000 -0600
+diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gss_util.h nfs-utils-1.0.11/utils/gssd/gss_util.h
+--- nfs-utils-1.0.11.lustre/utils/gssd/gss_util.h      2007-02-21 21:50:03.000000000 -0700
++++ nfs-utils-1.0.11/utils/gssd/gss_util.h     2008-01-02 18:11:38.000000000 -0700
 @@ -32,14 +32,14 @@
  #define _GSS_UTIL_H_
  
 @@ -32,14 +32,14 @@
  #define _GSS_UTIL_H_
  
@@ -1936,9 +1948,9 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/gss_util.h nfs-utils-1.0.11.lustre/utils/
 +int gssd_get_local_realm(void);
  
  #endif /* _GSS_UTIL_H_ */
 +int gssd_get_local_realm(void);
  
  #endif /* _GSS_UTIL_H_ */
-diff -Nrup nfs-utils-1.0.11/utils/gssd/krb5_util.c nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.c
---- nfs-utils-1.0.11/utils/gssd/krb5_util.c    2007-06-29 12:28:01.000000000 -0600
-+++ nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.c     2007-06-29 12:32:42.000000000 -0600
+diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.c nfs-utils-1.0.11/utils/gssd/krb5_util.c
+--- nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.c     2008-01-02 17:22:48.000000000 -0700
++++ nfs-utils-1.0.11/utils/gssd/krb5_util.c    2008-01-02 18:11:38.000000000 -0700
 @@ -99,12 +99,15 @@
  #include <rpc/rpc.h>
  #include <sys/types.h>
 @@ -99,12 +99,15 @@
  #include <rpc/rpc.h>
  #include <sys/types.h>
@@ -2404,9 +2416,9 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/krb5_util.c nfs-utils-1.0.11.lustre/utils
        }
  }
 +#endif
        }
  }
 +#endif
-diff -Nrup nfs-utils-1.0.11/utils/gssd/krb5_util.h nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.h
---- nfs-utils-1.0.11/utils/gssd/krb5_util.h    2007-06-29 12:28:01.000000000 -0600
-+++ nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.h     2007-06-29 12:32:42.000000000 -0600
+diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.h nfs-utils-1.0.11/utils/gssd/krb5_util.h
+--- nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.h     2008-01-02 17:22:48.000000000 -0700
++++ nfs-utils-1.0.11/utils/gssd/krb5_util.h    2008-01-02 18:11:38.000000000 -0700
 @@ -10,6 +10,8 @@
  struct gssd_k5_kt_princ {
        struct gssd_k5_kt_princ *next;
 @@ -10,6 +10,8 @@
  struct gssd_k5_kt_princ {
        struct gssd_k5_kt_princ *next;
@@ -2425,893 +2437,9 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/krb5_util.h nfs-utils-1.0.11.lustre/utils
 -#endif
 -
  #endif /* KRB5_UTIL_H */
 -#endif
 -
  #endif /* KRB5_UTIL_H */
-diff -Nrup nfs-utils-1.0.11/utils/gssd/lsupport.c nfs-utils-1.0.11.lustre/utils/gssd/lsupport.c
---- nfs-utils-1.0.11/utils/gssd/lsupport.c     1969-12-31 17:00:00.000000000 -0700
-+++ nfs-utils-1.0.11.lustre/utils/gssd/lsupport.c      2007-06-29 12:32:43.000000000 -0600
-@@ -0,0 +1,787 @@
-+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
-+ * vim:expandtab:shiftwidth=8:tabstop=8:
-+ *
-+ *  Copyright (c) 2005 Cluster File Systems, Inc.
-+ *
-+ *   This file is part of Lustre, http://www.lustre.org.
-+ *
-+ *   Lustre is free software; you can redistribute it and/or
-+ *   modify it under the terms of version 2 of the GNU General Public
-+ *   License as published by the Free Software Foundation.
-+ *
-+ *   Lustre is distributed in the hope that it will be useful,
-+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *   GNU General Public License for more details.
-+ *
-+ *   You should have received a copy of the GNU General Public License
-+ *   along with Lustre; if not, write to the Free Software
-+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
-+
-+#ifndef _GNU_SOURCE
-+#define _GNU_SOURCE
-+#endif
-+#include "config.h"
-+#include <sys/param.h>
-+#include <sys/utsname.h>
-+#include <sys/stat.h>
-+#include <sys/socket.h>
-+#include <arpa/inet.h>
-+#include <sys/types.h>
-+#include <sys/ipc.h>
-+#include <sys/sem.h>
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <pwd.h>
-+#include <grp.h>
-+#include <string.h>
-+#include <dirent.h>
-+#include <poll.h>
-+#include <fcntl.h>
-+#include <signal.h>
-+#include <unistd.h>
-+#include <errno.h>
-+#include <assert.h>
-+#ifdef HAVE_GETHOSTBYNAME
-+# include <netdb.h>
-+#endif
-+
-+#ifdef _NEW_BUILD_
-+# include "lgss_utils.h"
-+#else
-+# include "err_util.h"
-+# include "gssd.h"
-+#endif
-+#include "lsupport.h"
-+
-+/****************************************
-+ * exclusive startup                    *
-+ ****************************************/
-+
-+static struct __sem_s {
-+        char           *name;
-+        key_t           sem_key;
-+        int             sem_id;
-+} sems[2] = {
-+        [GSSD_CLI] = { "client",  0x3a92d473, 0 },
-+        [GSSD_SVC] = { "server",  0x3b92d473, 0 },
-+};
-+
-+void gssd_init_unique(int type)
-+{
-+        struct __sem_s *sem = &sems[type];
-+        struct sembuf   sembuf;
-+
-+        assert(type == GSSD_CLI || type == GSSD_SVC);
-+
-+again:
-+        sem->sem_id = semget(sem->sem_key, 1, IPC_CREAT | IPC_EXCL | 0700);
-+        if (sem->sem_id == -1) {
-+                if (errno != EEXIST) {
-+                        printerr(0, "Create sem: %s\n", strerror(errno));
-+                        exit(-1);
-+                }
-+
-+                /* already exist. Note there's still a small window racing
-+                 * with other processes, due to the stupid semaphore semantics.
-+                 */
-+                sem->sem_id = semget(sem->sem_key, 0, 0700);
-+                if (sem->sem_id == -1) {
-+                        if (errno == ENOENT) {
-+                                printerr(0, "another instance just exit, "
-+                                         "try again\n");
-+                                goto again;
-+                        }
-+
-+                        printerr(0, "Obtain sem: %s\n", strerror(errno));
-+                        exit(-1);
-+                }
-+        } else {
-+                int val = 1;
-+
-+                if (semctl(sem->sem_id, 0, SETVAL, val) == -1) {
-+                        printerr(0, "Initialize sem: %s\n",
-+                                 strerror(errno));
-+                        exit(-1);
-+                }
-+        }
-+
-+        sembuf.sem_num = 0;
-+        sembuf.sem_op = -1;
-+        sembuf.sem_flg = IPC_NOWAIT | SEM_UNDO;
-+
-+        if (semop(sem->sem_id, &sembuf, 1) != 0) {
-+                if (errno == EAGAIN) {
-+                        printerr(0, "Another instance is running, exit\n");
-+                        exit(0);
-+                }
-+                printerr(0, "Grab sem: %s\n", strerror(errno));
-+                exit(0);
-+        }
-+
-+        printerr(2, "Successfully created %s global identity\n", sem->name);
-+}
-+
-+void gssd_exit_unique(int type)
-+{
-+        assert(type == GSSD_CLI || type == GSSD_SVC);
-+
-+        /*
-+         * do nothing. we can't remove the sem here, otherwise the race
-+         * window would be much bigger. So it's sad we have to leave the
-+         * sem in the system forever.
-+         */
-+}
-+
-+/****************************************
-+ * client side resolvation:             *
-+ *    lnd/netid/nid => hostname         *
-+ ****************************************/
-+
-+char gethostname_ex[PATH_MAX] = GSSD_DEFAULT_GETHOSTNAME_EX;
-+
-+typedef int lnd_nid2hostname_t(char *lnd, uint32_t net, uint32_t addr,
-+                               char *buf, int buflen);
-+
-+/* FIXME what about IPv6? */
-+static
-+int ipv4_nid2hostname(char *lnd, uint32_t net, uint32_t addr,
-+                      char *buf, int buflen)
-+{
-+        struct hostent  *ent;
-+
-+        addr = htonl(addr);
-+        ent = gethostbyaddr(&addr, sizeof(addr), AF_INET);
-+        if (!ent) {
-+                printerr(0, "%s: can't resolve 0x%x\n", lnd, addr);
-+                return -1;
-+        }
-+        if (strlen(ent->h_name) >= buflen) {
-+                printerr(0, "%s: name too long: %s\n", lnd, ent->h_name);
-+                return -1;
-+        }
-+        strcpy(buf, ent->h_name);
-+
-+        printerr(2, "%s: net 0x%x, addr 0x%x => %s\n",
-+                 lnd, net, addr, buf);
-+        return 0;
-+}
-+
-+static
-+int lolnd_nid2hostname(char *lnd, uint32_t net, uint32_t addr,
-+                       char *buf, int buflen)
-+{
-+        struct utsname   uts;
-+        struct hostent  *ent;
-+
-+        if (addr) {
-+                printerr(0, "%s: addr is 0x%x, we expect 0\n", lnd, addr);
-+                return -1;
-+        }
-+
-+        if (uname(&uts)) {
-+                printerr(0, "%s: failed obtain local machine name\n", lnd);
-+                return -1;
-+        }
-+
-+        ent = gethostbyname(uts.nodename);
-+        if (!ent) {
-+                printerr(0, "%s: failed obtain canonical name of %s\n",
-+                         lnd, uts.nodename);
-+                return -1;
-+        }
-+
-+        if (strlen(ent->h_name) >= buflen) {
-+                printerr(0, "%s: name too long: %s\n", lnd, ent->h_name);
-+                return -1;
-+        }
-+        strcpy(buf, ent->h_name);
-+
-+        printerr(3, "%s: addr 0x%x => %s\n", lnd, addr, buf);
-+        return 0;
-+}
-+
-+static int is_space(char c)
-+{
-+        return (c == ' ' || c == '\t' || c == '\n');
-+}
-+
-+static
-+int external_nid2hostname(char *lnd, uint32_t net, uint32_t addr,
-+                          char *namebuf, int namebuflen)
-+{
-+        const int bufsize = PATH_MAX + 256;
-+        char buf[bufsize], *head, *tail;
-+        FILE *fghn;
-+
-+        sprintf(buf, "%s %s 0x%x 0x%x", gethostname_ex, lnd, net, addr);
-+        printerr(2, "cmd: %s\n", buf);
-+
-+        fghn = popen(buf, "r");
-+        if (fghn == NULL) {
-+                printerr(0, "failed to call %s\n", gethostname_ex);
-+                return -1;
-+        }
-+
-+        head = fgets(buf, bufsize, fghn);
-+        if (head == NULL) {
-+                printerr(0, "can't read from %s\n", gethostname_ex);
-+                return -1;
-+        }
-+        if (pclose(fghn) == -1)
-+                printerr(1, "pclose failed, continue\n");
-+
-+        /* trim head/tail space */
-+        while (is_space(*head))
-+                head++;
-+
-+        tail = head + strlen(head);
-+        if (tail <= head) {
-+                printerr(0, "no output from %s\n", gethostname_ex);
-+                return -1;
-+        }
-+        while (is_space(*(tail - 1)))
-+                tail--;
-+        if (tail <= head) {
-+                printerr(0, "output are all space from %s\n", gethostname_ex);
-+                return -1;
-+        }
-+        *tail = '\0';
-+
-+        /* start with '@' means error msg */
-+        if (head[0] == '@') {
-+                printerr(0, "error from %s: %s\n", gethostname_ex, &head[1]);
-+                return -1;
-+        }
-+
-+        if (tail - head > namebuflen) {
-+                printerr(0, "external hostname too long: %s\n", head);
-+                return -1;
-+        }
-+
-+        printerr(2, "%s: net 0x%x, addr 0x%x => %s\n",
-+                 lnd, net, addr, head);
-+        strcpy(namebuf, head);
-+        return 0;
-+}
-+
-+static struct {
-+        char                    *name;
-+        lnd_nid2hostname_t      *nid2name;
-+} converter[LND_ENUM_END_MARKER] = {
-+        {"UNUSED0",     NULL},
-+        [QSWLND]        = { "QSWLND",   external_nid2hostname},
-+        [SOCKLND]       = { "SOCKLND",  ipv4_nid2hostname },
-+        [GMLND]         = { "GMLND",    external_nid2hostname},
-+        [PTLLND]        = { "PTLLND",   external_nid2hostname },
-+        [O2IBLND]       = { "O2IBLND",  ipv4_nid2hostname },
-+        [CIBLND]        = { "CIBLND",   external_nid2hostname },
-+        [OPENIBLND]     = { "OPENIBLND",external_nid2hostname },
-+        [IIBLND]        = { "IIBLND",   external_nid2hostname },
-+        [LOLND]         = { "LOLND",    lolnd_nid2hostname },
-+        [RALND]         = { "RALND",    external_nid2hostname },
-+        [VIBLND]        = { "VIBLND",   external_nid2hostname },
-+};
-+
-+int lnet_nid2hostname(lnet_nid_t nid, char *buf, int buflen)
-+{
-+        uint32_t lnd, net, addr;
-+
-+        addr = LNET_NIDADDR(nid);
-+        net = LNET_NIDNET(nid);
-+        lnd = LNET_NETTYP(net);
-+
-+        if (lnd >= LND_ENUM_END_MARKER) {
-+                printerr(0, "ERROR: Unrecognized LND %u\n", lnd);
-+                return -1;
-+        }
-+
-+        if (converter[lnd].nid2name == NULL) {
-+                printerr(0, "ERROR: %s converter not ready\n",
-+                        converter[lnd].name);
-+                return -1;
-+        }
-+
-+        return converter[lnd].nid2name(converter[lnd].name, net, addr,
-+                                       buf, buflen);
-+}
-+
-+
-+/****************************************
-+ * lnet support routine                 *
-+ * (from lnet/libcfs/nidstrings.c       *
-+ ****************************************/
-+
-+#define LNET_NIDSTR_SIZE   32      /* size of each one (see below for usage) */
-+
-+static int  libcfs_lo_str2addr(char *str, int nob, uint32_t *addr);
-+static void libcfs_ip_addr2str(uint32_t addr, char *str);
-+static int  libcfs_ip_str2addr(char *str, int nob, uint32_t *addr);
-+static void libcfs_decnum_addr2str(uint32_t addr, char *str);
-+static void libcfs_hexnum_addr2str(uint32_t addr, char *str);
-+static int  libcfs_num_str2addr(char *str, int nob, uint32_t *addr);
-+
-+struct netstrfns {
-+        int          nf_type;
-+        char        *nf_name;
-+        char        *nf_modname;
-+        void       (*nf_addr2str)(uint32_t addr, char *str);
-+        int        (*nf_str2addr)(char *str, int nob, uint32_t *addr);
-+};
-+
-+static struct netstrfns  libcfs_netstrfns[] = {
-+        {/* .nf_type      */  LOLND,
-+         /* .nf_name      */  "lo",
-+         /* .nf_modname   */  "klolnd",
-+         /* .nf_addr2str  */  libcfs_decnum_addr2str,
-+         /* .nf_str2addr  */  libcfs_lo_str2addr},
-+        {/* .nf_type      */  SOCKLND,
-+         /* .nf_name      */  "tcp",
-+         /* .nf_modname   */  "ksocklnd",
-+         /* .nf_addr2str  */  libcfs_ip_addr2str,
-+         /* .nf_str2addr  */  libcfs_ip_str2addr},
-+        {/* .nf_type      */  O2IBLND,
-+         /* .nf_name      */  "o2ib",
-+         /* .nf_modname   */  "ko2iblnd",
-+         /* .nf_addr2str  */  libcfs_ip_addr2str,
-+         /* .nf_str2addr  */  libcfs_ip_str2addr},
-+        {/* .nf_type      */  CIBLND,
-+         /* .nf_name      */  "cib",
-+         /* .nf_modname   */  "kciblnd",
-+         /* .nf_addr2str  */  libcfs_ip_addr2str,
-+         /* .nf_str2addr  */  libcfs_ip_str2addr},
-+        {/* .nf_type      */  OPENIBLND,
-+         /* .nf_name      */  "openib",
-+         /* .nf_modname   */  "kopeniblnd",
-+         /* .nf_addr2str  */  libcfs_ip_addr2str,
-+         /* .nf_str2addr  */  libcfs_ip_str2addr},
-+        {/* .nf_type      */  IIBLND,
-+         /* .nf_name      */  "iib",
-+         /* .nf_modname   */  "kiiblnd",
-+         /* .nf_addr2str  */  libcfs_ip_addr2str,
-+         /* .nf_str2addr  */  libcfs_ip_str2addr},
-+        {/* .nf_type      */  VIBLND,
-+         /* .nf_name      */  "vib",
-+         /* .nf_modname   */  "kviblnd",
-+         /* .nf_addr2str  */  libcfs_ip_addr2str,
-+         /* .nf_str2addr  */  libcfs_ip_str2addr},
-+        {/* .nf_type      */  RALND,
-+         /* .nf_name      */  "ra",
-+         /* .nf_modname   */  "kralnd",
-+         /* .nf_addr2str  */  libcfs_ip_addr2str,
-+         /* .nf_str2addr  */  libcfs_ip_str2addr},
-+        {/* .nf_type      */  QSWLND,
-+         /* .nf_name      */  "elan",
-+         /* .nf_modname   */  "kqswlnd",
-+         /* .nf_addr2str  */  libcfs_decnum_addr2str,
-+         /* .nf_str2addr  */  libcfs_num_str2addr},
-+        {/* .nf_type      */  GMLND,
-+         /* .nf_name      */  "gm",
-+         /* .nf_modname   */  "kgmlnd",
-+         /* .nf_addr2str  */  libcfs_hexnum_addr2str,
-+         /* .nf_str2addr  */  libcfs_num_str2addr},
-+        {/* .nf_type      */  PTLLND,
-+         /* .nf_name      */  "ptl",
-+         /* .nf_modname   */  "kptllnd",
-+         /* .nf_addr2str  */  libcfs_decnum_addr2str,
-+         /* .nf_str2addr  */  libcfs_num_str2addr},
-+        /* placeholder for net0 alias.  It MUST BE THE LAST ENTRY */
-+        {/* .nf_type      */  -1},
-+};
-+
-+const int libcfs_nnetstrfns = sizeof(libcfs_netstrfns)/sizeof(libcfs_netstrfns[0]);
-+
-+static int
-+libcfs_lo_str2addr(char *str, int nob, uint32_t *addr)
-+{
-+        *addr = 0;
-+        return 1;
-+}
-+
-+static void
-+libcfs_ip_addr2str(uint32_t addr, char *str)
-+{
-+        snprintf(str, LNET_NIDSTR_SIZE, "%u.%u.%u.%u",
-+                 (addr >> 24) & 0xff, (addr >> 16) & 0xff,
-+                 (addr >> 8) & 0xff, addr & 0xff);
-+}
-+
-+/* CAVEAT EMPTOR XscanfX
-+ * I use "%n" at the end of a sscanf format to detect trailing junk.  However
-+ * sscanf may return immediately if it sees the terminating '0' in a string, so
-+ * I initialise the %n variable to the expected length.  If sscanf sets it;
-+ * fine, if it doesn't, then the scan ended at the end of the string, which is
-+ * fine too :) */
-+
-+static int
-+libcfs_ip_str2addr(char *str, int nob, uint32_t *addr)
-+{
-+        int   a;
-+        int   b;
-+        int   c;
-+        int   d;
-+        int   n = nob;                          /* XscanfX */
-+
-+        /* numeric IP? */
-+        if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 &&
-+            n == nob &&
-+            (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
-+            (c & ~0xff) == 0 && (d & ~0xff) == 0) {
-+                *addr = ((a<<24)|(b<<16)|(c<<8)|d);
-+                return 1;
-+        }
-+
-+#ifdef HAVE_GETHOSTBYNAME
-+        /* known hostname? */
-+        if (('a' <= str[0] && str[0] <= 'z') ||
-+            ('A' <= str[0] && str[0] <= 'Z')) {
-+                char *tmp;
-+
-+                tmp = malloc(nob + 1);
-+                if (tmp != NULL) {
-+                        struct hostent *he;
-+
-+                        memcpy(tmp, str, nob);
-+                        tmp[nob] = 0;
-+
-+                        he = gethostbyname(tmp);
-+
-+                        free(tmp);
-+                        tmp = NULL;
-+
-+                        if (he != NULL) {
-+                                uint32_t ip = *(uint32_t *)he->h_addr;
-+
-+                                *addr = ntohl(ip);
-+                                return 1;
-+                        }
-+                }
-+        }
-+#endif
-+        return 0;
-+}
-+
-+static void
-+libcfs_decnum_addr2str(uint32_t addr, char *str)
-+{
-+        snprintf(str, LNET_NIDSTR_SIZE, "%u", addr);
-+}
-+
-+static void
-+libcfs_hexnum_addr2str(uint32_t addr, char *str)
-+{
-+        snprintf(str, LNET_NIDSTR_SIZE, "0x%x", addr);
-+}
-+
-+static int
-+libcfs_num_str2addr(char *str, int nob, uint32_t *addr)
-+{
-+        int     n;
-+
-+        n = nob;
-+        if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob)
-+                return 1;
-+
-+        n = nob;
-+        if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob)
-+                return 1;
-+
-+        n = nob;
-+        if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob)
-+                return 1;
-+        
-+        return 0;
-+}
-+
-+static struct netstrfns *
-+libcfs_lnd2netstrfns(int lnd)
-+{
-+        int    i;
-+
-+        if (lnd >= 0)
-+                for (i = 0; i < libcfs_nnetstrfns; i++)
-+                        if (lnd == libcfs_netstrfns[i].nf_type)
-+                                return &libcfs_netstrfns[i];
-+
-+        return NULL;
-+}
-+
-+static struct netstrfns *
-+libcfs_str2net_internal(char *str, uint32_t *net)
-+{
-+        struct netstrfns *nf;
-+        int               nob;
-+        int               netnum;
-+        int               i;
-+
-+        for (i = 0; i < libcfs_nnetstrfns; i++) {
-+                nf = &libcfs_netstrfns[i];
-+                if (nf->nf_type >= 0 &&
-+                    !strncmp(str, nf->nf_name, strlen(nf->nf_name)))
-+                        break;
-+        }
-+
-+        if (i == libcfs_nnetstrfns)
-+                return NULL;
-+
-+        nob = strlen(nf->nf_name);
-+
-+        if (strlen(str) == (unsigned int)nob) {
-+                netnum = 0;
-+        } else {
-+                if (nf->nf_type == LOLND) /* net number not allowed */
-+                        return NULL;
-+
-+                str += nob;
-+                i = strlen(str);
-+                if (sscanf(str, "%u%n", &netnum, &i) < 1 ||
-+                    i != (int)strlen(str))
-+                        return NULL;
-+        }
-+
-+        *net = LNET_MKNET(nf->nf_type, netnum);
-+        return nf;
-+}
-+
-+lnet_nid_t
-+libcfs_str2nid(char *str)
-+{
-+        char             *sep = strchr(str, '@');
-+        struct netstrfns *nf;
-+        uint32_t             net;
-+        uint32_t             addr;
-+
-+        if (sep != NULL) {
-+                nf = libcfs_str2net_internal(sep + 1, &net);
-+                if (nf == NULL)
-+                        return LNET_NID_ANY;
-+        } else {
-+                sep = str + strlen(str);
-+                net = LNET_MKNET(SOCKLND, 0);
-+                nf = libcfs_lnd2netstrfns(SOCKLND);
-+                if (!nf)
-+                        return LNET_NID_ANY;
-+        }
-+
-+        if (!nf->nf_str2addr(str, sep - str, &addr))
-+                return LNET_NID_ANY;
-+
-+        return LNET_MKNID(net, addr);
-+}
-+
-+/****************************************
-+ * user mapping database handling       *
-+ * (very rudiment)                      *
-+ ****************************************/
-+
-+#define MAPPING_GROW_SIZE       512
-+#define MAX_LINE_LEN            256
-+
-+struct user_map_item {
-+        char        *principal; /* NULL means match all, will cause multi->single mapped, FORBID */
-+        lnet_nid_t   nid;
-+        uid_t        uid;
-+};
-+
-+struct user_mapping {
-+        int                   nitems;
-+        struct user_map_item *items;
-+};
-+
-+static struct user_mapping mapping = {0, NULL};
-+/* FIXME to be finished: monitor change of mapping database */
-+static int mapping_mtime = 0;
-+
-+void cleanup_mapping(void)
-+{
-+        if (mapping.items) {
-+                for (; mapping.nitems > 0; mapping.nitems--)
-+                        free(mapping.items[mapping.nitems - 1].principal);
-+                free(mapping.items);
-+                mapping.items = NULL;
-+        }
-+}
-+
-+static int grow_mapping(int nitems)
-+{
-+        struct user_map_item *new;
-+        int oldsize, newsize;
-+
-+        oldsize = (mapping.nitems * sizeof(struct user_map_item) +
-+                   MAPPING_GROW_SIZE - 1) / MAPPING_GROW_SIZE;
-+        newsize = (nitems * sizeof(struct user_map_item) +
-+                   MAPPING_GROW_SIZE - 1) / MAPPING_GROW_SIZE;
-+        while (newsize <= oldsize)
-+                return 0;
-+
-+        newsize *= MAPPING_GROW_SIZE;
-+        new = malloc(newsize);
-+        if (!new) {
-+                printerr(0, "can't alloc mapping size %d\n", newsize);
-+                return -1;
-+        }
-+
-+        if (mapping.items) {
-+                memcpy(new, mapping.items, mapping.nitems * sizeof(struct user_map_item));
-+                free(mapping.items);
-+        }
-+        mapping.items = new;
-+        return 0;
-+}
-+
-+uid_t parse_uid(char *uidstr)
-+{
-+        struct passwd *pw;
-+        char *p = NULL;
-+        long uid;
-+
-+        pw = getpwnam(uidstr);
-+        if (pw)
-+                return pw->pw_uid;
-+
-+        uid = strtol(uidstr, &p, 0);
-+        if (*p == '\0')
-+                return (uid_t) uid;
-+
-+        return -1;
-+}
-+
-+static int read_mapping_db(void)
-+{
-+        char princ[MAX_LINE_LEN];
-+        char nid_str[MAX_LINE_LEN];
-+        char dest[MAX_LINE_LEN];
-+        char linebuf[MAX_LINE_LEN];
-+        char *line;
-+        lnet_nid_t nid;
-+        uid_t dest_uid;
-+        FILE *f;
-+
-+        /* cleanup old mappings */
-+        cleanup_mapping();
-+
-+        f = fopen(MAPPING_DATABASE_FILE, "r");
-+        if (!f) {
-+                printerr(0, "can't open mapping database: %s\n",
-+                         MAPPING_DATABASE_FILE);
-+                return -1;
-+        }
-+
-+        while ((line = fgets(linebuf, MAX_LINE_LEN, f)) != NULL) {
-+                char *name;
-+
-+                if (strlen(line) >= MAX_LINE_LEN) {
-+                        printerr(0, "invalid mapping db: line too long (%d)\n",
-+                                 strlen(line));
-+                        continue;
-+                }
-+
-+                if (sscanf(line, "%s %s %s", princ, nid_str, dest) != 3) {
-+                        printerr(0, "mapping db: syntax error\n");
-+                        continue;
-+                }
-+
-+                if (!strcmp(princ, "*")) {
-+                        printerr(0, "NOT permit \"*\" princ, it will cause multi->single mapped\n");
-+                        continue;
-+                } else {
-+                        name = strdup(princ);
-+                        if (!name) {
-+                                printerr(0, "fail to dup str %s\n", princ);
-+                                continue;
-+                        }
-+                }
-+
-+                if (!strcmp(nid_str, "*")) {
-+                        nid = LNET_NID_ANY;
-+                } else {
-+                        nid = libcfs_str2nid(nid_str);
-+                        if (nid == LNET_NID_ANY) {
-+                                printerr(0, "fail to parse nid %s\n", nid_str);
-+                                free(name);
-+                                continue;
-+                        }
-+                }
-+
-+                dest_uid = parse_uid(dest);
-+                if (dest_uid == -1) {
-+                        printerr(0, "no valid user: %s\n", dest);
-+                        free(name);
-+                        continue;
-+                }
-+
-+                if (grow_mapping(mapping.nitems + 1)) {
-+                        printerr(0, "fail to grow mapping to %d\n",
-+                                 mapping.nitems + 1);
-+                        free(name);
-+                        fclose(f);
-+                        return -1;
-+                }
-+
-+                mapping.items[mapping.nitems].principal = name;
-+                mapping.items[mapping.nitems].nid = nid;
-+                mapping.items[mapping.nitems].uid = dest_uid;
-+                mapping.nitems++;
-+                printerr(1, "add mapping: %s(%s/0x%llx) ==> %d\n",
-+                         name, nid_str, nid, dest_uid);
-+        }
-+
-+        fclose(f);
-+        return 0;
-+}
-+
-+static inline int mapping_changed(void)
-+{
-+        struct stat st;
-+
-+        if (stat(MAPPING_DATABASE_FILE, &st) == -1) {
-+                /* stat failed, treat it like doesn't exist or be removed */
-+                if (mapping_mtime == 0) {
-+                        return 0;
-+                } else {
-+                        printerr(0, "Warning: stat %s failed: %s\n",
-+                                 MAPPING_DATABASE_FILE, strerror(errno));
-+
-+                        mapping_mtime = 0;
-+                        return 1;
-+                }
-+        }
-+
-+        if (st.st_mtime != mapping_mtime) {
-+                mapping_mtime = st.st_mtime;
-+                return 1;
-+        }
-+
-+        return 0;
-+}
-+
-+int lookup_mapping(char *princ, lnet_nid_t nid, uid_t *uid)
-+{
-+        int n;
-+
-+        *uid = -1;
-+
-+        /* FIXME race condition here */
-+        if (mapping_changed()) {
-+                if (read_mapping_db())
-+                        printerr(0, "all remote users will be denied\n");
-+        }
-+
-+        for (n = 0; n < mapping.nitems; n++) {
-+                struct user_map_item *entry = &mapping.items[n];
-+
-+                if (entry->nid != LNET_NID_ANY && entry->nid != nid)
-+                        continue;
-+                if (!strcasecmp(entry->principal, princ)) {
-+                        printerr(1, "found mapping: %s ==> %d\n",
-+                                 princ, entry->uid);
-+                        *uid = entry->uid;
-+                        return 0;
-+                }
-+        }
-+
-+        printerr(2, "no mapping for %s/%#Lx\n", princ, nid);
-+        return -1;
-+}
-diff -Nrup nfs-utils-1.0.11/utils/gssd/lsupport.h nfs-utils-1.0.11.lustre/utils/gssd/lsupport.h
---- nfs-utils-1.0.11/utils/gssd/lsupport.h     1969-12-31 17:00:00.000000000 -0700
-+++ nfs-utils-1.0.11.lustre/utils/gssd/lsupport.h      2007-06-29 12:32:43.000000000 -0600
-@@ -0,0 +1,89 @@
-+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
-+ * vim:expandtab:shiftwidth=8:tabstop=8:
-+ */
-+
-+#ifndef __LIBCFS_H__
-+#define __LIBCFS_H__
-+
-+#include <unistd.h>
-+#include <stdint.h>
-+
-+#define GSSD_CLI        (0)
-+#define GSSD_SVC        (1)
-+
-+void gssd_init_unique(int type);
-+void gssd_exit_unique(int type);
-+
-+/*
-+ * copied from lustre source
-+ */
-+
-+#define LUSTRE_GSS_SVC_MDS      0
-+#define LUSTRE_GSS_SVC_OSS      1
-+
-+struct lgssd_upcall_data {
-+        uint32_t        seq;
-+        uint32_t        uid;
-+        uint32_t        gid;
-+        uint32_t        svc;
-+        uint64_t        nid;
-+        char            obd[64];
-+};
-+
-+#define GSSD_INTERFACE_VERSION        (1)
-+
-+struct lgssd_ioctl_param {
-+        int             version;        /* in   */
-+        char           *uuid;           /* in   */
-+        int             lustre_svc;     /* in   */
-+        uid_t           uid;            /* in   */
-+        gid_t           gid;            /* in   */
-+        long            send_token_size;/* in   */
-+        char           *send_token;     /* in   */
-+        long            reply_buf_size; /* in   */
-+        char           *reply_buf;      /* in   */
-+        long            status;         /* out  */
-+        long            reply_length;   /* out  */
-+};
-+
-+#define GSSD_DEFAULT_GETHOSTNAME_EX     "/etc/lustre/nid2hostname"
-+#define MAPPING_DATABASE_FILE           "/etc/lustre/idmap.conf"
-+
-+typedef uint64_t lnet_nid_t;
-+typedef uint32_t lnet_netid_t;
-+
-+#define LNET_NID_ANY      ((lnet_nid_t) -1)
-+#define LNET_PID_ANY      ((lnet_pid_t) -1)
-+
-+enum {
-+        /* Only add to these values (i.e. don't ever change or redefine them):
-+         * network addresses depend on them... */
-+        QSWLND    = 1,
-+        SOCKLND   = 2,
-+        GMLND     = 3,
-+        PTLLND    = 4,
-+        O2IBLND   = 5,
-+        CIBLND    = 6,
-+        OPENIBLND = 7,
-+        IIBLND    = 8,
-+        LOLND     = 9,
-+        RALND     = 10,
-+        VIBLND    = 11,
-+        LND_ENUM_END_MARKER
-+};
-+
-+int lnet_nid2hostname(lnet_nid_t nid, char *buf, int buflen);
-+void cleanup_mapping(void);
-+int lookup_mapping(char *princ, uint64_t nid, uid_t *uid);
-+lnet_nid_t libcfs_str2nid(char *str);
-+
-+/* how an LNET NID encodes net:address */
-+#define LNET_NIDADDR(nid)      ((uint32_t)((nid) & 0xffffffff))
-+#define LNET_NIDNET(nid)       ((uint32_t)(((nid) >> 32)) & 0xffffffff)
-+#define LNET_MKNID(net,addr)   ((((uint64_t)(net))<<32)|((uint64_t)(addr)))
-+/* how net encodes type:number */
-+#define LNET_NETNUM(net)       ((net) & 0xffff)
-+#define LNET_NETTYP(net)       (((net) >> 16) & 0xffff)
-+#define LNET_MKNET(typ,num)    ((((uint32_t)(typ))<<16)|((uint32_t)(num)))
-+
-+#endif /* __LIBCFS_H__ */
-diff -Nrup nfs-utils-1.0.11/utils/gssd/Makefile.am nfs-utils-1.0.11.lustre/utils/gssd/Makefile.am
---- nfs-utils-1.0.11/utils/gssd/Makefile.am    2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11.lustre/utils/gssd/Makefile.am     2007-06-29 12:29:20.000000000 -0600
+diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/Makefile.am nfs-utils-1.0.11/utils/gssd/Makefile.am
+--- nfs-utils-1.0.11.lustre/utils/gssd/Makefile.am     2007-02-21 21:50:03.000000000 -0700
++++ nfs-utils-1.0.11/utils/gssd/Makefile.am    2008-01-02 18:10:29.000000000 -0700
 @@ -1,17 +1,11 @@
  ## Process this file with automake to produce Makefile.in
  
 @@ -1,17 +1,11 @@
  ## Process this file with automake to produce Makefile.in
  
@@ -3417,9 +2545,9 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/Makefile.am nfs-utils-1.0.11.lustre/utils
 -          rm -f $(RPCPREFIX)$$inst ; \
 -        done)
 -
 -          rm -f $(RPCPREFIX)$$inst ; \
 -        done)
 -
-diff -Nrup nfs-utils-1.0.11/utils/gssd/svcgssd.c nfs-utils-1.0.11.lustre/utils/gssd/svcgssd.c
---- nfs-utils-1.0.11/utils/gssd/svcgssd.c      2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11.lustre/utils/gssd/svcgssd.c       2007-06-29 12:32:44.000000000 -0600
+diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/svcgssd.c nfs-utils-1.0.11/utils/gssd/svcgssd.c
+--- nfs-utils-1.0.11.lustre/utils/gssd/svcgssd.c       2007-02-21 21:50:03.000000000 -0700
++++ nfs-utils-1.0.11/utils/gssd/svcgssd.c      2008-01-02 18:11:38.000000000 -0700
 @@ -43,7 +43,6 @@
  #include <sys/types.h>
  #include <sys/stat.h>
 @@ -43,7 +43,6 @@
  #include <sys/types.h>
  #include <sys/stat.h>
@@ -3583,9 +2711,9 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/svcgssd.c nfs-utils-1.0.11.lustre/utils/g
        printerr(0, "gssd_run returned!\n");
        abort();
  }
        printerr(0, "gssd_run returned!\n");
        abort();
  }
-diff -Nrup nfs-utils-1.0.11/utils/gssd/svcgssd.h nfs-utils-1.0.11.lustre/utils/gssd/svcgssd.h
---- nfs-utils-1.0.11/utils/gssd/svcgssd.h      2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11.lustre/utils/gssd/svcgssd.h       2007-06-29 12:32:45.000000000 -0600
+diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/svcgssd.h nfs-utils-1.0.11/utils/gssd/svcgssd.h
+--- nfs-utils-1.0.11.lustre/utils/gssd/svcgssd.h       2007-02-21 21:50:03.000000000 -0700
++++ nfs-utils-1.0.11/utils/gssd/svcgssd.h      2008-01-02 18:11:38.000000000 -0700
 @@ -35,9 +35,20 @@
  #include <sys/queue.h>
  #include <gssapi/gssapi.h>
 @@ -35,9 +35,20 @@
  #include <sys/queue.h>
  #include <gssapi/gssapi.h>
@@ -3610,10 +2738,16 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/svcgssd.h nfs-utils-1.0.11.lustre/utils/g
 +#define LUSTRE_ROOT_NAMELEN                   11
  
  #endif /* _RPC_SVCGSSD_H_ */
 +#define LUSTRE_ROOT_NAMELEN                   11
  
  #endif /* _RPC_SVCGSSD_H_ */
-diff -Nrup nfs-utils-1.0.11/utils/gssd/svcgssd_main_loop.c nfs-utils-1.0.11.lustre/utils/gssd/svcgssd_main_loop.c
---- nfs-utils-1.0.11/utils/gssd/svcgssd_main_loop.c    2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11.lustre/utils/gssd/svcgssd_main_loop.c     2007-06-29 12:32:45.000000000 -0600
-@@ -46,46 +46,66 @@
+diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/svcgssd_main_loop.c nfs-utils-1.0.11/utils/gssd/svcgssd_main_loop.c
+--- nfs-utils-1.0.11.lustre/utils/gssd/svcgssd_main_loop.c     2007-02-21 21:50:03.000000000 -0700
++++ nfs-utils-1.0.11/utils/gssd/svcgssd_main_loop.c    2008-01-02 18:11:38.000000000 -0700
+@@ -42,50 +42,72 @@
+ #include <fcntl.h>
+ #include <errno.h>
+ #include <unistd.h>
++/* For nanosleep() */
++#include <time.h>
  #include "svcgssd.h"
  #include "err_util.h"
  
  #include "svcgssd.h"
  #include "err_util.h"
  
@@ -3701,9 +2835,9 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/svcgssd_main_loop.c nfs-utils-1.0.11.lust
                }
        }
  }
                }
        }
  }
-diff -Nrup nfs-utils-1.0.11/utils/gssd/svcgssd_proc.c nfs-utils-1.0.11.lustre/utils/gssd/svcgssd_proc.c
---- nfs-utils-1.0.11/utils/gssd/svcgssd_proc.c 2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11.lustre/utils/gssd/svcgssd_proc.c  2007-06-29 12:32:46.000000000 -0600
+diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/svcgssd_proc.c nfs-utils-1.0.11/utils/gssd/svcgssd_proc.c
+--- nfs-utils-1.0.11.lustre/utils/gssd/svcgssd_proc.c  2007-02-21 21:50:03.000000000 -0700
++++ nfs-utils-1.0.11/utils/gssd/svcgssd_proc.c 2008-01-02 18:11:38.000000000 -0700
 @@ -35,7 +35,6 @@
  
  #include <sys/param.h>
 @@ -35,7 +35,6 @@
  
  #include <sys/param.h>
@@ -3814,7 +2948,7 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/svcgssd_proc.c nfs-utils-1.0.11.lustre/ut
  void
  print_hexl(int pri, unsigned char *cp, int length)
  {
  void
  print_hexl(int pri, unsigned char *cp, int length)
  {
-@@ -286,12 +293,121 @@ print_hexl(int pri, unsigned char *cp, i
+@@ -286,12 +293,149 @@ print_hexl(int pri, unsigned char *cp, i
                printerr(pri,"\n");
        }
  }
                printerr(pri,"\n");
        }
  }
@@ -3827,7 +2961,9 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/svcgssd_proc.c nfs-utils-1.0.11.lustre/ut
 +{
 +      u_int32_t       maj_stat, min_stat;
 +      gss_buffer_desc name;
 +{
 +      u_int32_t       maj_stat, min_stat;
 +      gss_buffer_desc name;
-+      char            *sname, *realm, *slash;
++      char            *sname, *host, *realm;
++      const int       namebuf_size = 512;
++      char            namebuf[namebuf_size];
 +      int             res = -1;
 +      gss_OID         name_type = GSS_C_NO_OID;
 +      struct passwd   *pw;
 +      int             res = -1;
 +      gss_OID         name_type = GSS_C_NO_OID;
 +      struct passwd   *pw;
@@ -3849,7 +2985,6 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/svcgssd_proc.c nfs-utils-1.0.11.lustre/ut
 +              return -1;
 +      }
 +      memcpy(sname, name.value, name.length);
 +              return -1;
 +      }
 +      memcpy(sname, name.value, name.length);
-+      printerr(1, "authenticated %s from %016llx\n", sname, nid);
 +      gss_release_buffer(&min_stat, &name);
 +
 +      if (lustre_svc == LUSTRE_GSS_SVC_MDS)
 +      gss_release_buffer(&min_stat, &name);
 +
 +      if (lustre_svc == LUSTRE_GSS_SVC_MDS)
@@ -3858,64 +2993,91 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/svcgssd_proc.c nfs-utils-1.0.11.lustre/ut
 +              cred->cr_mapped_uid = -1;
 +
 +        realm = strchr(sname, '@');
 +              cred->cr_mapped_uid = -1;
 +
 +        realm = strchr(sname, '@');
-+        if (!realm) {
-+                printerr(0, "WARNNING: principal %s contains no realm name\n",
-+                       sname);
-+                cred->cr_remote = (mds_local_realm != NULL);
-+        } else {
++      if (realm)
 +                *realm++ = '\0';
 +                *realm++ = '\0';
-+                if (!mds_local_realm)
-+                        cred->cr_remote = 1;
-+                else
-+                        cred->cr_remote =
-+                                (strcasecmp(mds_local_realm, realm) != 0);
-+        }
 +
 +
-+        if (cred->cr_remote) {
-+                if (cred->cr_mapped_uid != -1)
-+                        res = 0;
-+              else if (lustre_svc == LUSTRE_GSS_SVC_OSS &&
-+                       strcmp(sname, "lustre_root") == 0)
-+                        res = 0;
-+                else
-+                        printerr(0, "principal %s is remote without mapping\n",
-+                                 sname);
++        host = strchr(sname, '/');
++        if (host)
++                *host++ = '\0';
++
++      if (strcmp(sname, GSSD_SERVICE_OSS) == 0) {
++              printerr(0, "forbid "GSSD_SERVICE_OSS" as user name\n");
 +              goto out_free;
 +              goto out_free;
-+        }
++      }
++
++      /* 1. check host part */
++      if (host) {
++              if (lnet_nid2hostname(nid, namebuf, namebuf_size)) {
++                      printerr(0, "ERROR: failed to resolve hostname for "
++                               "%s/%s@%s from %016llx\n",
++                               sname, host, realm, nid);
++                      goto out_free;
++              }
++
++              if (strcasecmp(host, namebuf)) {
++                      printerr(0, "ERROR: %s/%s@s claimed hostname doesn't "
++                               "match %s, nid %016llx\n", sname, host, realm,
++                               namebuf, nid);
++                      goto out_free;
++              }
++      } else {
++              if (!strcmp(sname, GSSD_SERVICE_MDS)) {
++                      printerr(0, "ERROR: "GSSD_SERVICE_MDS"@%s from %016llx "
++                               "doesn't bind with hostname\n",
++                               realm ? realm : "", nid);
++                      goto out_free;
++              }
++      }
++
++      /* 2. check realm */
++      if (!realm) {
++              /* just deny it
++                cred->cr_remote = (mds_local_realm != NULL);
++              */
++                printerr(0, "ERROR: %s%s%s have no realm name\n",
++                       sname, host ? "/" : "", host ? "host" : "");
++              goto out_free;
++      }
++
++      if (!mds_local_realm || strcasecmp(mds_local_realm, realm)) {
++              cred->cr_remote = 1;
 +
 +
-+        slash = strchr(sname, '/');
-+        if (slash)
-+                *slash = '\0';
++              if (cred->cr_mapped_uid == -1)
++                        printerr(0, "ERROR: %s from %016llx is remote but "
++                               "without mapping\n", sname, nid);
++              /* mapped, skip user checking */
++              goto out_free;
++      }
 +
 +
++      /* 3. check user */
 +        if (!(pw = getpwnam(sname))) {
 +        if (!(pw = getpwnam(sname))) {
-+                /* If client use machine credential, we map it to root, which
-+                 * will subject to further mapping by root-squash in kernel.
-+                 *
-+                 * MDS service keytab is treated as special user, also mapped
-+                 * to root. OSS service keytab can't be used as a user.
-+                 */
++                /* map lustre_root/lustre_mds to root user, which is subject
++               * to further mapping by root-squash in kernel. */
 +                if (!strcmp(sname, LUSTRE_ROOT_NAME)) {
 +                if (!strcmp(sname, LUSTRE_ROOT_NAME)) {
-+                        printerr(2, "lustre_root principal, resolve to uid 0\n");
 +                        cred->cr_uid = 0;
 +                        cred->cr_usr_root = 1;
 +                } else if (!strcmp(sname, GSSD_SERVICE_MDS)) {
 +                        cred->cr_uid = 0;
 +                        cred->cr_usr_root = 1;
 +                } else if (!strcmp(sname, GSSD_SERVICE_MDS)) {
-+                        printerr(2, "mds service principal, resolve to uid 0\n");
 +                        cred->cr_uid = 0;
 +                        cred->cr_usr_mds = 1;
 +                } else {
 +                        cred->cr_uid = 0;
 +                        cred->cr_usr_mds = 1;
 +                } else {
-+                        cred->cr_uid = -1;
 +                        if (cred->cr_mapped_uid == -1) {
 +                        if (cred->cr_mapped_uid == -1) {
-+                                printerr(0, "invalid user %s\n", sname);
++                                printerr(0, "ERROR: invalid user, %s/%s@%s "
++                                       "from %016llx\n", sname, host,
++                                       realm, nid);
 +                                goto out_free;
 +                        }
 +                                goto out_free;
 +                        }
-+                        printerr(2, "user %s mapped to %u\n",
-+                                 sname, cred->cr_mapped_uid);
 +                }
 +                }
++              printerr(2, "user %s from %016llx is mapped to %u\n",
++                       sname, nid, cred->cr_mapped_uid);
 +        } else {
 +        } else {
++              /* note: a mapped local user will go to here too */
 +                cred->cr_uid = pw->pw_uid;
 +                printerr(2, "%s resolve to uid %u\n", sname, cred->cr_uid);
 +        }
 +
 +                cred->cr_uid = pw->pw_uid;
 +                printerr(2, "%s resolve to uid %u\n", sname, cred->cr_uid);
 +        }
 +
++      printerr(1, "%s: authenticated %s%s%s@%s from %016llx\n",
++               lustre_svc_name[lustre_svc], sname,
++               host ? "/" : "", host ? host : "", realm, nid);
 +        res = 0;
 +out_free:
 +        free(sname);
 +        res = 0;
 +out_free:
 +        free(sname);
@@ -3940,7 +3102,7 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/svcgssd_proc.c nfs-utils-1.0.11.lustre/ut
        char                    in_tok_buf[TOKEN_BUF_SIZE];
        char                    in_handle_buf[15];
        char                    out_handle_buf[15];
        char                    in_tok_buf[TOKEN_BUF_SIZE];
        char                    in_handle_buf[15];
        char                    out_handle_buf[15];
-@@ -303,10 +419,13 @@ handle_nullreq(FILE *f) {
+@@ -303,10 +447,13 @@ handle_nullreq(FILE *f) {
                                ignore_out_tok = {.value = NULL},
        /* XXX isn't there a define for this?: */
                                null_token = {.value = NULL};
                                ignore_out_tok = {.value = NULL},
        /* XXX isn't there a define for this?: */
                                null_token = {.value = NULL};
@@ -3954,7 +3116,7 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/svcgssd_proc.c nfs-utils-1.0.11.lustre/ut
        u_int32_t               maj_stat = GSS_S_FAILURE, min_stat = 0;
        u_int32_t               ignore_min_stat;
        struct svc_cred         cred;
        u_int32_t               maj_stat = GSS_S_FAILURE, min_stat = 0;
        u_int32_t               ignore_min_stat;
        struct svc_cred         cred;
-@@ -314,25 +433,31 @@ handle_nullreq(FILE *f) {
+@@ -314,25 +461,31 @@ handle_nullreq(FILE *f) {
        static int              lbuflen = 0;
        static char             *cp;
  
        static int              lbuflen = 0;
        static char             *cp;
  
@@ -3973,7 +3135,7 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/svcgssd_proc.c nfs-utils-1.0.11.lustre/ut
 +      qword_get(&cp, (char *) &lustre_svc, sizeof(lustre_svc));
 +      qword_get(&cp, (char *) &nid, sizeof(nid));
 +      qword_get(&cp, (char *) &handle_seq, sizeof(handle_seq));
 +      qword_get(&cp, (char *) &lustre_svc, sizeof(lustre_svc));
 +      qword_get(&cp, (char *) &nid, sizeof(nid));
 +      qword_get(&cp, (char *) &handle_seq, sizeof(handle_seq));
-+      printerr(1, "handling req: svc %u, nid %016llx, idx %llx\n",
++      printerr(2, "handling req: svc %u, nid %016llx, idx %llx\n",
 +               lustre_svc, nid, handle_seq);
 +
        in_handle.length = (size_t) qword_get(&cp, in_handle.value,
 +               lustre_svc, nid, handle_seq);
 +
        in_handle.length = (size_t) qword_get(&cp, in_handle.value,
@@ -3992,7 +3154,7 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/svcgssd_proc.c nfs-utils-1.0.11.lustre/ut
  
        if (in_tok.length < 0) {
                printerr(0, "WARNING: handle_nullreq: "
  
        if (in_tok.length < 0) {
                printerr(0, "WARNING: handle_nullreq: "
-@@ -352,7 +477,13 @@ handle_nullreq(FILE *f) {
+@@ -352,7 +505,13 @@ handle_nullreq(FILE *f) {
                memcpy(&ctx, in_handle.value, in_handle.length);
        }
  
                memcpy(&ctx, in_handle.value, in_handle.length);
        }
  
@@ -4007,7 +3169,7 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/svcgssd_proc.c nfs-utils-1.0.11.lustre/ut
                        &in_tok, GSS_C_NO_CHANNEL_BINDINGS, &client_name,
                        &mech, &out_tok, &ret_flags, NULL, NULL);
  
                        &in_tok, GSS_C_NO_CHANNEL_BINDINGS, &client_name,
                        &mech, &out_tok, &ret_flags, NULL, NULL);
  
-@@ -370,7 +501,8 @@ handle_nullreq(FILE *f) {
+@@ -370,7 +529,8 @@ handle_nullreq(FILE *f) {
                        maj_stat, min_stat, mech);
                goto out_err;
        }
                        maj_stat, min_stat, mech);
                goto out_err;
        }
@@ -4017,7 +3179,7 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/svcgssd_proc.c nfs-utils-1.0.11.lustre/ut
                /* get_ids() prints error msg */
                maj_stat = GSS_S_BAD_NAME; /* XXX ? */
                gss_release_name(&ignore_min_stat, &client_name);
                /* get_ids() prints error msg */
                maj_stat = GSS_S_BAD_NAME; /* XXX ? */
                gss_release_name(&ignore_min_stat, &client_name);
-@@ -378,10 +510,8 @@ handle_nullreq(FILE *f) {
+@@ -378,10 +538,8 @@ handle_nullreq(FILE *f) {
        }
        gss_release_name(&ignore_min_stat, &client_name);
  
        }
        gss_release_name(&ignore_min_stat, &client_name);
  
@@ -4028,7 +3190,7 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/svcgssd_proc.c nfs-utils-1.0.11.lustre/ut
        out_handle.length = sizeof(handle_seq);
        memcpy(out_handle.value, &handle_seq, sizeof(handle_seq));
  
        out_handle.length = sizeof(handle_seq);
        memcpy(out_handle.value, &handle_seq, sizeof(handle_seq));
  
-@@ -405,8 +535,7 @@ out:
+@@ -405,8 +563,7 @@ out:
                free(ctx_token.value);
        if (out_tok.value != NULL)
                gss_release_buffer(&ignore_min_stat, &out_tok);
                free(ctx_token.value);
        if (out_tok.value != NULL)
                gss_release_buffer(&ignore_min_stat, &out_tok);
@@ -4038,9 +3200,9 @@ diff -Nrup nfs-utils-1.0.11/utils/gssd/svcgssd_proc.c nfs-utils-1.0.11.lustre/ut
  
  out_err:
        if (ctx != GSS_C_NO_CONTEXT)
  
  out_err:
        if (ctx != GSS_C_NO_CONTEXT)
-diff -Nrup nfs-utils-1.0.11/utils/Makefile.am nfs-utils-1.0.11.lustre/utils/Makefile.am
---- nfs-utils-1.0.11/utils/Makefile.am 2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11.lustre/utils/Makefile.am  2007-06-29 12:29:20.000000000 -0600
+diff -Nrup nfs-utils-1.0.11.lustre/utils/Makefile.am nfs-utils-1.0.11/utils/Makefile.am
+--- nfs-utils-1.0.11.lustre/utils/Makefile.am  2007-02-21 21:50:03.000000000 -0700
++++ nfs-utils-1.0.11/utils/Makefile.am 2008-01-02 18:10:29.000000000 -0700
 @@ -2,30 +2,6 @@
  
  OPTDIRS =
 @@ -2,30 +2,6 @@
  
  OPTDIRS =
index 745268a..280aa2e 100644 (file)
@@ -301,7 +301,9 @@ get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred,
 {
        u_int32_t       maj_stat, min_stat;
        gss_buffer_desc name;
 {
        u_int32_t       maj_stat, min_stat;
        gss_buffer_desc name;
-       char            *sname, *realm, *slash;
+       char            *sname, *host, *realm;
+       const int       namebuf_size = 512;
+       char            namebuf[namebuf_size];
        int             res = -1;
        gss_OID         name_type = GSS_C_NO_OID;
        struct passwd   *pw;
        int             res = -1;
        gss_OID         name_type = GSS_C_NO_OID;
        struct passwd   *pw;
@@ -323,8 +325,6 @@ get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred,
                return -1;
        }
        memcpy(sname, name.value, name.length);
                return -1;
        }
        memcpy(sname, name.value, name.length);
-       printerr(1, "%s: authenticated %s from %016llx\n",
-                lustre_svc_name[lustre_svc], sname, nid);
        gss_release_buffer(&min_stat, &name);
 
        if (lustre_svc == LUSTRE_GSS_SVC_MDS)
        gss_release_buffer(&min_stat, &name);
 
        if (lustre_svc == LUSTRE_GSS_SVC_MDS)
@@ -333,64 +333,91 @@ get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred,
                cred->cr_mapped_uid = -1;
 
         realm = strchr(sname, '@');
                cred->cr_mapped_uid = -1;
 
         realm = strchr(sname, '@');
-        if (!realm) {
-                printerr(0, "WARNNING: principal %s contains no realm name\n",
-                        sname);
-                cred->cr_remote = (mds_local_realm != NULL);
-        } else {
+       if (realm)
                 *realm++ = '\0';
                 *realm++ = '\0';
-                if (!mds_local_realm)
-                        cred->cr_remote = 1;
-                else
-                        cred->cr_remote =
-                                (strcasecmp(mds_local_realm, realm) != 0);
-        }
 
 
-        if (cred->cr_remote) {
-                if (cred->cr_mapped_uid != -1)
-                        res = 0;
-               else if (lustre_svc == LUSTRE_GSS_SVC_OSS &&
-                        strcmp(sname, "lustre_root") == 0)
-                        res = 0;
-                else
-                        printerr(0, "principal %s is remote without mapping\n",
-                                 sname);
+        host = strchr(sname, '/');
+        if (host)
+                *host++ = '\0';
+
+       if (strcmp(sname, GSSD_SERVICE_OSS) == 0) {
+               printerr(0, "forbid "GSSD_SERVICE_OSS" as user name\n");
                goto out_free;
                goto out_free;
-        }
+       }
+
+       /* 1. check host part */
+       if (host) {
+               if (lnet_nid2hostname(nid, namebuf, namebuf_size)) {
+                       printerr(0, "ERROR: failed to resolve hostname for "
+                                "%s/%s@%s from %016llx\n",
+                                sname, host, realm, nid);
+                       goto out_free;
+               }
+
+               if (strcasecmp(host, namebuf)) {
+                       printerr(0, "ERROR: %s/%s@s claimed hostname doesn't "
+                                "match %s, nid %016llx\n", sname, host, realm,
+                                namebuf, nid);
+                       goto out_free;
+               }
+       } else {
+               if (!strcmp(sname, GSSD_SERVICE_MDS)) {
+                       printerr(0, "ERROR: "GSSD_SERVICE_MDS"@%s from %016llx "
+                                "doesn't bind with hostname\n",
+                                realm ? realm : "", nid);
+                       goto out_free;
+               }
+       }
 
 
-        slash = strchr(sname, '/');
-        if (slash)
-                *slash = '\0';
+       /* 2. check realm */
+       if (!realm) {
+               /* just deny it
+                cred->cr_remote = (mds_local_realm != NULL);
+               */
+                printerr(0, "ERROR: %s%s%s have no realm name\n",
+                        sname, host ? "/" : "", host ? "host" : "");
+               goto out_free;
+       }
+
+       if (!mds_local_realm || strcasecmp(mds_local_realm, realm)) {
+               cred->cr_remote = 1;
+
+               if (cred->cr_mapped_uid == -1)
+                        printerr(0, "ERROR: %s from %016llx is remote but "
+                                "without mapping\n", sname, nid);
+               /* mapped, skip user checking */
+               goto out_free;
+       }
 
 
+       /* 3. check user */
         if (!(pw = getpwnam(sname))) {
         if (!(pw = getpwnam(sname))) {
-                /* If client use machine credential, we map it to root, which
-                 * will subject to further mapping by root-squash in kernel.
-                 *
-                 * MDS service keytab is treated as special user, also mapped
-                 * to root. OSS service keytab can't be used as a user.
-                 */
+                /* map lustre_root/lustre_mds to root user, which is subject
+                * to further mapping by root-squash in kernel. */
                 if (!strcmp(sname, LUSTRE_ROOT_NAME)) {
                 if (!strcmp(sname, LUSTRE_ROOT_NAME)) {
-                        printerr(2, "lustre_root principal, resolve to uid 0\n");
                         cred->cr_uid = 0;
                         cred->cr_usr_root = 1;
                 } else if (!strcmp(sname, GSSD_SERVICE_MDS)) {
                         cred->cr_uid = 0;
                         cred->cr_usr_root = 1;
                 } else if (!strcmp(sname, GSSD_SERVICE_MDS)) {
-                        printerr(2, "mds service principal, resolve to uid 0\n");
                         cred->cr_uid = 0;
                         cred->cr_usr_mds = 1;
                 } else {
                         cred->cr_uid = 0;
                         cred->cr_usr_mds = 1;
                 } else {
-                        cred->cr_uid = -1;
                         if (cred->cr_mapped_uid == -1) {
                         if (cred->cr_mapped_uid == -1) {
-                                printerr(0, "invalid user %s\n", sname);
+                                printerr(0, "ERROR: invalid user, %s/%s@%s "
+                                        "from %016llx\n", sname, host,
+                                        realm, nid);
                                 goto out_free;
                         }
                                 goto out_free;
                         }
-                        printerr(2, "user %s mapped to %u\n",
-                                 sname, cred->cr_mapped_uid);
                 }
                 }
+               printerr(2, "user %s from %016llx is mapped to %u\n",
+                        sname, nid, cred->cr_mapped_uid);
         } else {
         } else {
+               /* note: a mapped local user will go to here too */
                 cred->cr_uid = pw->pw_uid;
                 printerr(2, "%s resolve to uid %u\n", sname, cred->cr_uid);
         }
 
                 cred->cr_uid = pw->pw_uid;
                 printerr(2, "%s resolve to uid %u\n", sname, cred->cr_uid);
         }
 
+       printerr(1, "%s: authenticated %s%s%s@%s from %016llx\n",
+                lustre_svc_name[lustre_svc], sname,
+                host ? "/" : "", host ? host : "", realm, nid);
         res = 0;
 out_free:
         free(sname);
         res = 0;
 out_free:
         free(sname);
diff --git a/lustre/utils/l_facl.c b/lustre/utils/l_facl.c
deleted file mode 100644 (file)
index d9eaa2c..0000000
+++ /dev/null
@@ -1,268 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- *  Copyright (C) 2004-2006 Cluster File Systems, Inc.
- *
- *   This file is part of Lustre, http://www.lustre.org.
- *
- *   Lustre is free software; you can redistribute it and/or
- *   modify it under the terms of version 2 of the GNU General Public
- *   License as published by the Free Software Foundation.
- *
- *   Lustre is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with Lustre; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <pwd.h>
-#include <grp.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <libgen.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <mntent.h>
-
-#include <lustre/liblustreapi.h>
-#include <lustre/lustre_user.h>
-
-#include "obdctl.h"
-
-static char *progname;
-
-static void usage(void)
-{
-        fprintf(stderr,
-                "\nusage: %s {uid} {gid} {mdtname} {key} {handle} {cmd}\n"
-                "Normally invoked as an upcall from Lustre, set via:\n"
-                "  /proc/fs/lustre/mdt/{mdtname}/rmtacl_upcall\n",
-                progname);
-}
-
-static inline void show_result(struct rmtacl_downcall_data *data)
-{
-        fprintf(stdout, "buflen %d\n\n%s\n", data->add_buflen, data->add_buf);
-}
-
-#define MDS_ERR "server processing error"
-
-static void errlog(char *buf, const char *fmt, ...)
-{
-        va_list args;
-
-        va_start(args, fmt);
-        vsprintf(buf, fmt, args);
-        va_end(args);
-}
-
-static char *get_lustre_mount(void)
-{
-        FILE *fp;
-        struct mntent *mnt;
-        static char mntpath[PATH_MAX] = "";
-
-        fp = setmntent(MOUNTED, "r");
-        if (fp == NULL) {
-                fprintf(stderr, "setmntent %s failed: %s\n",
-                        MOUNTED, strerror(errno));
-                return NULL;
-        }
-
-        while (1) {
-                mnt = getmntent(fp);
-                if (!mnt)
-                        break;
-
-                if (!llapi_is_lustre_mnttype(mnt->mnt_type))
-                        continue;
-
-                /*
-                 * XXX: The fsname can be configed by user, it should pass into as a parameter.
-                 *      Since we only need one client on mdt node for remote set{get}facl, it is
-                 *      unnecessary to do the accurate match for fsname, but match ":/" temporary.
-                 */
-                //if (strstr(mnt->mnt_fsname, ":/lustre")) {
-                        /* save the mountpoint dir part */
-                        strncpy(mntpath, mnt->mnt_dir, sizeof(mntpath));
-                        endmntent(fp);
-                        return mntpath;
-                //}
-        }
-        endmntent(fp);
-
-        return NULL;
-}
-
-int main(int argc, char **argv)
-{
-        struct rmtacl_downcall_data *data;
-        char procname[1024], *buf, *mntpath;
-        int out_pipe[2], err_pipe[2], pid, size, buflen, fd, rc;
-
-        progname = basename(argv[0]);
-
-        if (argc != 7) {
-                usage();
-                return 1;
-        }
-
-        size = offsetof(struct rmtacl_downcall_data, add_buf[RMTACL_SIZE_MAX]);
-        data = malloc(size);
-        if (!data) {
-                fprintf(stderr, "malloc %d failed\n", size);
-                return 1;
-        }
-        memset(data, 0, size);
-        data->add_magic = RMTACL_DOWNCALL_MAGIC;
-        data->add_key = strtoll(argv[4], NULL, 10);
-        data->add_handle = strtoul(argv[5], NULL, 10);
-        buf = data->add_buf;
-
-        mntpath = get_lustre_mount();
-        if (!mntpath) {
-                errlog(buf, MDS_ERR"(no lustre mounted on MDS)\n");
-                goto downcall;
-        }
-
-        /* create pipe */
-        if (pipe(out_pipe) < 0 || pipe(err_pipe) < 0) {
-                errlog(buf, MDS_ERR"(pipe failed): %s\n", strerror(errno));
-                goto downcall;
-        }
-
-        if ((pid = fork()) < 0) {
-                errlog(buf, MDS_ERR"(fork failed): %s\n", strerror(errno));
-                goto downcall;
-        } else if (pid == 0) {
-                uid_t uid;
-                gid_t gid;
-
-                close(out_pipe[0]);
-                if (out_pipe[1] != STDOUT_FILENO) {
-                        dup2(out_pipe[1], STDOUT_FILENO);
-                        close(out_pipe[1]);
-                }
-                close(err_pipe[0]);
-                if (err_pipe[1] != STDERR_FILENO) {
-                        dup2(err_pipe[1], STDERR_FILENO);
-                        close(err_pipe[1]);
-                }
-                close(STDIN_FILENO);
-
-                if (chdir(mntpath) < 0) {
-                        fprintf(stderr, "chdir %s failed: %s\n",
-                                mntpath, strerror(errno));
-                        return 1;
-                }
-
-                gid = (gid_t)atoi(argv[2]);
-                if (gid) {
-                        if (setgid(gid) == -1) {
-                                fprintf(stderr, "setgid %u failed: %s\n",
-                                        gid, strerror(errno));
-                                return 1;
-                        }
-                }
-
-                uid = (uid_t)atoi(argv[1]);
-                if (uid) {
-                        if (setuid(uid) == -1) {
-                                fprintf(stderr, "setuid %u failed: %s\n",
-                                        uid, strerror(errno));
-                                return 1;
-                        }
-                }
-
-                execl("/bin/sh", "sh", "-c", argv[6], NULL);
-                fprintf(stderr, "execl %s failed: %s\n",
-                        argv[6], strerror(errno));
-
-                return 1;
-        }
-
-        /* parent process handling */
-        close(out_pipe[1]);
-        close(err_pipe[1]);
-
-        buflen = 0;
-        while (1) {
-                rc = read(out_pipe[0], buf + buflen, RMTACL_SIZE_MAX - buflen);
-                if (rc < 0) {
-                        errlog(buf, MDS_ERR"(read failed): %s\n",
-                               strerror(errno));
-                        break;
-                }
-                if (rc == 0)
-                        break;
-                buflen += rc;
-                if (buflen >= RMTACL_SIZE_MAX)
-                        break;
-        }
-
-        if (buflen != 0) {
-                wait(&rc);
-                goto downcall;
-        }
-
-        while (1) {
-                rc = read(err_pipe[0], buf + buflen, RMTACL_SIZE_MAX - buflen);
-                if (rc < 0) {
-                        errlog(buf, MDS_ERR"(read failed): %s\n",
-                               strerror(errno));
-                        break;
-                }
-                if (rc == 0)
-                        break;
-                buflen += rc;
-                if (buflen >= RMTACL_SIZE_MAX)
-                        break;
-        }
-
-        wait(&rc);
-
-downcall:
-        buf[RMTACL_SIZE_MAX - 1] = 0;
-        data->add_buflen = strlen(buf) + 1;
-        if (getenv("L_FACL_TEST")) {
-                show_result(data);
-                free(data);
-                return 0;
-        }
-
-        snprintf(procname, sizeof(procname),
-                 "/proc/fs/lustre/mdt/%s/rmtacl_info", argv[3]);
-        fd = open(procname, O_WRONLY);
-        if (fd < 0) {
-                fprintf(stderr, "open %s failed: %s\n",
-                        procname, strerror(errno));
-                free(data);
-                return 1;
-        }
-
-        buflen = offsetof(struct rmtacl_downcall_data,
-                          add_buf[data->add_buflen]);
-        rc = write(fd, data, buflen);
-        close(fd);
-        if (rc != buflen) {
-                fprintf(stderr, "write %s len %d return %d: %s\n",
-                        procname, buflen, rc, strerror(errno));
-                free(data);
-                return 1;
-        }
-
-        free(data);
-        return 0;
-}
index c37057b..65e9f0b 100644 (file)
 #include <lustre/lustre_idl.h>
 #include <libcfs/kp30.h>
 
 #include <lustre/lustre_idl.h>
 #include <libcfs/kp30.h>
 
-#define SETXID_PATHNAME "/etc/lustre/setxid.conf"
+#define PERM_PATHNAME "/etc/lustre/perm.conf"
 
 /*
 
 /*
- * setxid permission file format is like this:
+ * permission file format is like this:
  * {nid} {uid} {perms}
  *
  * '*' nid means any nid
  * '*' uid means any uid
  * the valid values for perms are:
  * {nid} {uid} {perms}
  *
  * '*' nid means any nid
  * '*' uid means any uid
  * the valid values for perms are:
- * setuid/setgid/setgrp         -- enable corresponding perm
- * nosetuid/nosetgid/nosetgrp   -- disable corresponding perm
+ * setuid/setgid/setgrp/rmtacl           -- enable corresponding perm
+ * nosetuid/nosetgid/nosetgrp/normtacl   -- disable corresponding perm
  * they can be listed together, seperated by ',',
  * when perm and noperm are in the same line (item), noperm is preferential,
  * when they are in different lines (items), the latter is preferential,
  * they can be listed together, seperated by ',',
  * when perm and noperm are in the same line (item), noperm is preferential,
  * when they are in different lines (items), the latter is preferential,
@@ -174,27 +174,29 @@ static inline int match_uid(uid_t uid, const char *str)
 typedef struct {
         char   *name;
         __u32   bit;
 typedef struct {
         char   *name;
         __u32   bit;
-} setxid_perm_type_t;
+} perm_type_t;
 
 
-static setxid_perm_type_t setxid_perm_types[] = {
-        { "setuid", LUSTRE_SETUID_PERM },
-        { "setgid", LUSTRE_SETGID_PERM },
-        { "setgrp", LUSTRE_SETGRP_PERM },
+static perm_type_t perm_types[] = {
+        { "setuid", CFS_SETUID_PERM },
+        { "setgid", CFS_SETGID_PERM },
+        { "setgrp", CFS_SETGRP_PERM },
+        { "rmtacl", CFS_RMTACL_PERM },
         { 0 }
 };
 
         { 0 }
 };
 
-static setxid_perm_type_t setxid_noperm_types[] = {
-        { "nosetuid", LUSTRE_SETUID_PERM },
-        { "nosetgid", LUSTRE_SETGID_PERM },
-        { "nosetgrp", LUSTRE_SETGRP_PERM },
+static perm_type_t noperm_types[] = {
+        { "nosetuid", CFS_SETUID_PERM },
+        { "nosetgid", CFS_SETGID_PERM },
+        { "nosetgrp", CFS_SETGRP_PERM },
+        { "normtacl", CFS_RMTACL_PERM },
         { 0 }
 };
 
         { 0 }
 };
 
-int parse_setxid_perm(__u32 *perm, __u32 *noperm, char *str)
+int parse_perm(__u32 *perm, __u32 *noperm, char *str)
 {
         char *start, *end;
         char name[64];
 {
         char *start, *end;
         char name[64];
-        setxid_perm_type_t *pt;
+        perm_type_t *pt;
 
         *perm = 0;
         *noperm = 0;
 
         *perm = 0;
         *noperm = 0;
@@ -207,7 +209,7 @@ int parse_setxid_perm(__u32 *perm, __u32 *noperm, char *str)
                 if (start >= end)
                         break;
                 strncpy(name, start, end - start);
                 if (start >= end)
                         break;
                 strncpy(name, start, end - start);
-                for (pt = setxid_perm_types; pt->name; pt++) {
+                for (pt = perm_types; pt->name; pt++) {
                         if (!strcasecmp(name, pt->name)) {
                                 *perm |= pt->bit;
                                 break;
                         if (!strcasecmp(name, pt->name)) {
                                 *perm |= pt->bit;
                                 break;
@@ -215,7 +217,7 @@ int parse_setxid_perm(__u32 *perm, __u32 *noperm, char *str)
                 }
 
                 if (!pt->name) {
                 }
 
                 if (!pt->name) {
-                        for (pt = setxid_noperm_types; pt->name; pt++) {
+                        for (pt = noperm_types; pt->name; pt++) {
                                 if (!strcasecmp(name, pt->name)) {
                                         *noperm |= pt->bit;
                                         break;
                                 if (!strcasecmp(name, pt->name)) {
                                         *noperm |= pt->bit;
                                         break;
@@ -233,16 +235,16 @@ int parse_setxid_perm(__u32 *perm, __u32 *noperm, char *str)
         return 0;
 }
 
         return 0;
 }
 
-int parse_setxid_perm_line(struct identity_downcall_data *data, char *line)
+int parse_perm_line(struct identity_downcall_data *data, char *line)
 {
         char uid_str[256], nid_str[256], perm_str[256];
         lnet_nid_t nid;
         __u32 perm, noperm;
         int rc, i;
 
 {
         char uid_str[256], nid_str[256], perm_str[256];
         lnet_nid_t nid;
         __u32 perm, noperm;
         int rc, i;
 
-        if (data->idd_nperms >= N_SETXID_PERMS_MAX) {
-                errlog("setxid permission count %d > max %d\n",
-                        data->idd_nperms, N_SETXID_PERMS_MAX);
+        if (data->idd_nperms >= N_PERMS_MAX) {
+                errlog("permission count %d > max %d\n",
+                        data->idd_nperms, N_PERMS_MAX);
                 return -1;
         }
 
                 return -1;
         }
 
@@ -265,7 +267,7 @@ int parse_setxid_perm_line(struct identity_downcall_data *data, char *line)
                 }
         }
 
                 }
         }
 
-        if (parse_setxid_perm(&perm, &noperm, perm_str)) {
+        if (parse_perm(&perm, &noperm, perm_str)) {
                 errlog("invalid perm %s\n", perm_str);
                 return -1;
         }
                 errlog("invalid perm %s\n", perm_str);
                 return -1;
         }
@@ -324,7 +326,7 @@ int parse_setxid_perm_line(struct identity_downcall_data *data, char *line)
         return 0;
 }
 
         return 0;
 }
 
-int get_setxid_perms(FILE *fp, struct identity_downcall_data *data)
+int get_perms(FILE *fp, struct identity_downcall_data *data)
 {
         char line[1024];
 
 {
         char line[1024];
 
@@ -332,7 +334,7 @@ int get_setxid_perms(FILE *fp, struct identity_downcall_data *data)
                 if (comment_line(line))
                         continue;
 
                 if (comment_line(line))
                         continue;
 
-                if (parse_setxid_perm_line(data, line)) {
+                if (parse_perm_line(data, line)) {
                         errlog("parse line %s failed!\n", line);
                         return -1;
                 }
                         errlog("parse line %s failed!\n", line);
                         return -1;
                 }
@@ -355,10 +357,10 @@ static void show_result(struct identity_downcall_data *data)
         for (i = 0; i < data->idd_ngroups; i++)
                 printf("%s%u", i > 0 ? "," : "", data->idd_groups[i]);
         printf("\n");
         for (i = 0; i < data->idd_ngroups; i++)
                 printf("%s%u", i > 0 ? "," : "", data->idd_groups[i]);
         printf("\n");
-        printf("setxid permissions:\n"
+        printf("permissions:\n"
                "  nid\t\t\tperm\n");
         for (i = 0; i < data->idd_nperms; i++) {
                "  nid\t\t\tperm\n");
         for (i = 0; i < data->idd_nperms; i++) {
-                struct setxid_perm_downcall_data *pdd;
+                struct perm_downcall_data *pdd;
 
                 pdd = &data->idd_perms[i];
 
 
                 pdd = &data->idd_perms[i];
 
@@ -406,13 +408,13 @@ int main(int argc, char **argv)
                 goto downcall;
 
         /* read permission database */
                 goto downcall;
 
         /* read permission database */
-        perms_fp = fopen(SETXID_PATHNAME, "r");
+        perms_fp = fopen(PERM_PATHNAME, "r");
         if (perms_fp) {
         if (perms_fp) {
-                get_setxid_perms(perms_fp, data);
+                get_perms(perms_fp, data);
                 fclose(perms_fp);
         } else if (errno != ENOENT) {
                 errlog("open %s failed: %s\n",
                 fclose(perms_fp);
         } else if (errno != ENOENT) {
                 errlog("open %s failed: %s\n",
-                       SETXID_PATHNAME, strerror(errno));
+                       PERM_PATHNAME, strerror(errno));
         }
 
 downcall:
         }
 
 downcall:
index 4c7a99e..8d8d0d8 100644 (file)
@@ -71,8 +71,12 @@ static int lfs_quota(int argc, char **argv);
 #endif
 static int lfs_flushctx(int argc, char **argv);
 static int lfs_join(int argc, char **argv);
 #endif
 static int lfs_flushctx(int argc, char **argv);
 static int lfs_join(int argc, char **argv);
-static int lfs_getfacl(int argc, char **argv);
-static int lfs_setfacl(int argc, char **argv);
+static int lfs_lsetfacl(int argc, char **argv);
+static int lfs_lgetfacl(int argc, char **argv);
+static int lfs_rsetfacl(int argc, char **argv);
+static int lfs_rgetfacl(int argc, char **argv);
+static int lfs_cp(int argc, char **argv);
+static int lfs_ls(int argc, char **argv);
 
 /* all avaialable commands */
 command_t cmdlist[] = {
 
 /* all avaialable commands */
 command_t cmdlist[] = {
@@ -143,12 +147,24 @@ command_t cmdlist[] = {
 #endif
         {"flushctx", lfs_flushctx, 0, "Flush security context for current user.\n"
          "usage: flushctx [-k] [mountpoint...]"},
 #endif
         {"flushctx", lfs_flushctx, 0, "Flush security context for current user.\n"
          "usage: flushctx [-k] [mountpoint...]"},
-        {"getfacl", lfs_getfacl, 0,
-         "Get file access control list in remote client.\n"
-         "usage: getfacl [-dRLPvh] file"},
-        {"setfacl", lfs_setfacl, 0,
-         "Set file access control list in remote client.\n"
-         "usage: setfacl [-bkndRLPvh] [{-m|-x} acl_spec] [{-M|-X} acl_file] file"},
+        {"lsetfacl", lfs_lsetfacl, 0,
+         "Remote user setfacl for user/group on the same remote client.\n"
+         "usage: lsetfacl [-bkndRLPvh] [{-m|-x} acl_spec] [{-M|-X} acl_file] file ..."},
+        {"lgetfacl", lfs_lgetfacl, 0,
+         "Remote user getfacl for user/group on the same remote client.\n"
+         "usage: lgetfacl [-dRLPvh] file ..."},
+        {"rsetfacl", lfs_rsetfacl, 0,
+         "Remote user setfacl for user/group on other clients.\n"
+         "usage: rsetfacl [-bkndRLPvh] [{-m|-x} acl_spec] [{-M|-X} acl_file] file ..."},
+        {"rgetfacl", lfs_rgetfacl, 0,
+         "Remote user getfacl for user/group on other clients.\n"
+         "usage: rgetfacl [-dRLPvh] file ..."},
+        {"cp", lfs_cp, 0,
+         "Remote user copy files and directories.\n"
+         "usage: cp [OPTION]... [-T] SOURCE DEST\n\tcp [OPTION]... SOURCE... DIRECTORY\n\tcp [OPTION]... -t DIRECTORY SOURCE..."},
+        {"ls", lfs_ls, 0,
+         "Remote user list directory contents.\n"
+         "usage: ls [OPTION]... [FILE]..."},
         {"help", Parser_help, 0, "help"},
         {"exit", Parser_quit, 0, "quit"},
         {"quit", Parser_quit, 0, "quit"},
         {"help", Parser_help, 0, "help"},
         {"exit", Parser_quit, 0, "quit"},
         {"quit", Parser_quit, 0, "quit"},
@@ -1862,117 +1878,38 @@ static int lfs_flushctx(int argc, char **argv)
         return rc;
 }
 
         return rc;
 }
 
-/*
- * We assume one and only one filename is supplied as the
- * last parameter.
- */
-static int acl_cmd_parse(int argc, char **argv, char *fname, char *cmd)
+static int lfs_lsetfacl(int argc, char **argv)
 {
 {
-        char *dname, *rpath = NULL;
-        char path[PATH_MAX], cwd[PATH_MAX];
-        FILE *fp;
-        struct mntent *mnt;
-        int i;
-
-        if (argc < 2)
-                return -1;
-
-        /* FIXME the premise is there is no sub-mounted filesystems under this
-         * mounted lustre tree. */
-        strncpy(fname, argv[argc - 1], PATH_MAX);
-
-        /* get path prefix */
-        dname = dirname(fname);
-
-        /* try to resolve the pathname into relative to the root of the mounted
-         * lustre filesystem.
-         */
-        if (getcwd(cwd, sizeof(cwd)) == NULL) {
-                fprintf(stderr, "getcwd %s failed: %s\n", cwd, strerror(errno));
-                return -1;
-        }
-
-        if (chdir(dname) == -1) {
-                fprintf(stderr, "chdir to %s failed: %s\n",
-                        dname, strerror(errno));
-                return -1;
-        }
-
-        if (getcwd(path, sizeof(path)) == NULL) {
-                fprintf(stderr, "getcwd %s: %s\n", path, strerror(errno));
-                return -1;
-        }
-
-        if (chdir(cwd) == -1) {
-                fprintf(stderr, "chdir back to %s: %s\n",
-                        cwd, strerror(errno));
-                return -1;
-        }
-
-        strncat(path, "/", PATH_MAX);
-        strncpy(fname, argv[argc - 1], PATH_MAX);
-        strncat(path, basename(fname), PATH_MAX);
-
-        fp = setmntent(MOUNTED, "r");
-        if (fp == NULL) {
-                fprintf(stderr, "setmntent %s failed: %s\n",
-                        MOUNTED, strerror(errno));
-                return -1;
-        }
-
-        while (1) {
-                mnt = getmntent(fp);
-                if (!mnt)
-                        break;
-
-                if (!llapi_is_lustre_mnttype(mnt->mnt_type))
-                        continue;
-
-                if (!strncmp(mnt->mnt_dir, path, strlen(mnt->mnt_dir))) {
-                        rpath = path + strlen(mnt->mnt_dir);
-                        break;
-                }
-        }
-        endmntent(fp);
-
-        /* remove char '/' from rpath to be a relative path */
-        while (rpath && *rpath == '/') rpath++;
-
-        if (!rpath) {
-                fprintf(stderr,
-                        "%s: file %s doesn't belong to a lustre file system!\n",
-                        argv[0], argv[argc - 1]);
-                return -1;
-        }
-
-        for (i = 0; i < argc - 1; i++) {
-                strncat(cmd, argv[i], PATH_MAX);
-                strncat(cmd, " ", PATH_MAX);
-        }
-        strncat(cmd, *rpath ? rpath : ".", PATH_MAX);
-        strncpy(fname, argv[argc - 1], sizeof(fname));
-
-        return 0;
+        argv[0]++;
+        return(llapi_lsetfacl(argc, argv));
 }
 
 }
 
-static int lfs_getfacl(int argc, char **argv)
+static int lfs_lgetfacl(int argc, char **argv)
 {
 {
-        char fname[PATH_MAX] = "", cmd[PATH_MAX] = "";
-
-        if (acl_cmd_parse(argc, argv, fname, cmd))
-                return CMD_HELP;
+        argv[0]++;
+        return(llapi_lgetfacl(argc, argv));
+}
 
 
-        return llapi_getfacl(fname, cmd);
+static int lfs_rsetfacl(int argc, char **argv)
+{
+        argv[0]++;
+        return(llapi_rsetfacl(argc, argv));
 }
 
 }
 
-static int lfs_setfacl(int argc, char **argv)
+static int lfs_rgetfacl(int argc, char **argv)
 {
 {
-        char fname[PATH_MAX] = "", cmd[PATH_MAX] = "";
+        argv[0]++;
+        return(llapi_rgetfacl(argc, argv));
+}
 
 
-        if (acl_cmd_parse(argc, argv, fname, cmd))
-                return CMD_HELP;
+static int lfs_cp(int argc, char **argv)
+{
+        return(llapi_cp(argc, argv));
+}
 
 
-        return llapi_setfacl(fname, cmd);
+static int lfs_ls(int argc, char **argv)
+{
+        return(llapi_ls(argc, argv));
 }
 
 int main(int argc, char **argv)
 }
 
 int main(int argc, char **argv)
index 185be04..d43a7a2 100644 (file)
@@ -1697,67 +1697,293 @@ out:
         return ret;
 }
 
         return ret;
 }
 
-int llapi_getfacl(char *fname, char *cmd)
+#include <pwd.h>
+#include <grp.h>
+#include <mntent.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <ctype.h>
+
+static int rmtacl_notify(int ops)
 {
 {
-        struct rmtacl_ioctl_data data;
-        char out[RMTACL_SIZE_MAX] = "";
-        int fd, rc;
-
-        data.cmd = cmd;
-        data.cmd_len = strlen(cmd) + 1;
-        data.res = out;
-        data.res_len = sizeof(out);
-
-        fd = open(fname, 0);
-        if (fd == -1) {
-                llapi_err(LLAPI_MSG_ERROR,"open %s failed", fname);
+        FILE *fp;
+        struct mntent *mnt;
+        int found = 0, fd, rc;
+
+        fp = setmntent(MOUNTED, "r");
+        if (fp == NULL) {
+                perror("setmntent");
                 return -1;
         }
 
                 return -1;
         }
 
-        rc = ioctl(fd, LL_IOC_GETFACL, &data);
-        close(fd);
-        if (errno == EBADE) {
-                llapi_err(LLAPI_MSG_ERROR, "Please use getfacl directly!");
-                rc = 1;
-        } else if (rc) {
-                llapi_err(LLAPI_MSG_ERROR,"getfacl %s failed", fname);
+        while (1) {
+                mnt = getmntent(fp);
+                if (!mnt)
+                        break;
+
+                if (!llapi_is_lustre_mnt(mnt))
+                        continue;
+
+                fd = open(mnt->mnt_dir, O_RDONLY | O_DIRECTORY);
+                if (fd < 0) {
+                        perror("open");
+                        return -1;
+                }
+
+                rc = ioctl(fd, LL_IOC_RMTACL, ops);
+                if (rc < 0) {
+                        perror("ioctl");
+                return -1;
+        }
+
+                found++;
+        }
+        endmntent(fp);
+        return found;
+}
+
+static char *next_token(char *p, int div)
+{
+        if (p == NULL)
+                return NULL;
+
+        if (div)
+                while (*p && *p != ':' && !isspace(*p))
+                        p++;
+        else
+                while (*p == ':' || isspace(*p))
+                        p++;
+
+        return *p ? p : NULL;
+}
+
+static int rmtacl_name2id(char *name, int is_user)
+{
+        if (is_user) {
+                struct passwd *pw;
+
+                if ((pw = getpwnam(name)) == NULL)
+                        return INVALID_ID;
+                else
+                        return (int)(pw->pw_uid);
         } else {
         } else {
-                llapi_printf(LLAPI_MSG_NORMAL, "%s", out);
+                struct group *gr;
+
+                if ((gr = getgrnam(name)) == NULL)
+                        return INVALID_ID;
+                else
+                        return (int)(gr->gr_gid);
         }
         }
+}
 
 
-        return rc;
+static int isodigit(int c)
+{
+        return (c >= '0' && c <= '7') ? 1 : 0;
+}
+
+/*
+ * Whether the name is just digits string (uid/gid) already or not.
+ * Return value:
+ * 1: str is id
+ * 0: str is not id
+ */
+static int str_is_id(char *str)
+{
+        if (str == NULL)
+                return 0;
+
+        if (*str == '0') {
+                str++;
+                if (*str == 'x' || *str == 'X') { /* for Hex. */
+                        if (!isxdigit(*(++str)))
+                                return 0;
+
+                        while (isxdigit(*(++str)));
+                } else if (isodigit(*str)) { /* for Oct. */
+                        while (isodigit(*(++str)));
+                }
+        } else if (isdigit(*str)) { /* for Dec. */
+                while (isdigit(*(++str)));
+        }
+
+        return (*str == 0) ? 1 : 0;
 }
 
 }
 
-int llapi_setfacl(char *fname, char *cmd)
+typedef struct {
+        char *name;
+        int   length;
+        int   is_user;
+        int   next_token;
+} rmtacl_name_t;
+
+#define RMTACL_OPTNAME(name) name, sizeof(name) - 1
+
+static rmtacl_name_t rmtacl_namelist[] = {
+        { RMTACL_OPTNAME("user:"),            1,      0 },
+        { RMTACL_OPTNAME("group:"),           0,      0 },
+        { RMTACL_OPTNAME("default:user:"),    1,      0 },
+        { RMTACL_OPTNAME("default:group:"),   0,      0 },
+        /* for --tabular option */
+        { RMTACL_OPTNAME("user"),             1,      1 },
+        { RMTACL_OPTNAME("group"),            0,      1 },
+        { 0 }
+};
+
+static int rgetfacl_output(char *str)
 {
 {
-        struct rmtacl_ioctl_data data;
-        char out[RMTACL_SIZE_MAX] = "";
-        int fd, rc;
-
-        data.cmd = cmd;
-        data.cmd_len = strlen(cmd) + 1;
-        data.res = out;
-        data.res_len = sizeof(out);
-
-        fd = open(fname, 0);
-        if (fd == -1) {
-                llapi_err(LLAPI_MSG_ERROR,"open %s failed", fname);
+        char *start = NULL, *end = NULL;
+        int is_user = 0, n, id;
+        char c;
+        rmtacl_name_t *rn;
+
+        if (str == NULL)
                 return -1;
                 return -1;
+
+        for (rn = rmtacl_namelist; rn->name; rn++) {
+                if(strncmp(str, rn->name, rn->length) == 0) {
+                        if (!rn->next_token)
+                                start = str + rn->length;
+                        else
+                                start = next_token(str + rn->length, 0);
+                        is_user = rn->is_user;
+                        break;
+                }
         }
 
         }
 
-        rc = ioctl(fd, LL_IOC_SETFACL, &data);
-        close(fd);
-        if (errno == EBADE) {
-                llapi_err(LLAPI_MSG_ERROR, "Please use setfacl directly!");
-                rc = 1;
-        } else if (errno == EOPNOTSUPP) {
-                llapi_err(LLAPI_MSG_ERROR, "setfacl: %s: %s", fname);
-                rc = 1;
-        } else if (rc) {
-                llapi_err(LLAPI_MSG_ERROR,"setfacl %s failed", fname);
+        end = next_token(start, 1);
+        if (end == NULL || start == end) {
+                n = printf("%s", str);
+                return n;
+        }
+
+        c = *end;
+        *end = 0;
+        id = rmtacl_name2id(start, is_user);
+        if (id == INVALID_ID) {
+                if (str_is_id(start)) {
+                        *end = c;
+                        n = printf("%s", str);
+                } else
+                        return -1;
+        } else if ((id == NOBODY_UID && is_user) ||
+                   (id == NOBODY_GID && !is_user)) {
+                *end = c;
+                n = printf("%s", str);
         } else {
         } else {
-                llapi_printf(LLAPI_MSG_NORMAL, "%s", out);
+                *end = c;
+                *start = 0;
+                n = printf("%s%d%s", str, id, end);
         }
         }
+        return n;
+}
 
 
-        return rc;
+static int child_status(int status)
+{
+        return WIFEXITED(status) ? WEXITSTATUS(status) : -1;
+}
+
+static int do_rmtacl(int argc, char *argv[], int ops, int (output_func)(char *))
+{
+        pid_t pid = 0;
+        int fd[2], status;
+        FILE *fp;
+        char buf[PIPE_BUF];
+
+        if (output_func) {
+                if (pipe(fd) < 0) {
+                        perror("pipe");
+                        return -1;
+                }
+
+                if ((pid = fork()) < 0) {
+                        perror("pipe");
+                        close(fd[0]);
+                        close(fd[1]);
+                        return -1;
+                } else if (!pid) {
+                        /* child process redirects its output. */
+                        close(fd[0]);
+                        close(1);
+                        if (dup2(fd[1], 1) < 0) {
+                                perror("dup2");
+                                close(fd[1]);
+                                return -1;
+                        }
+                } else {
+                        close(fd[1]);
+                }
+        }
+
+        if (!pid) {
+                status = rmtacl_notify(ops);
+                if (status < 0)
+                        return -1;
+
+                exit(execvp(argv[0], argv));
+        }
+
+        /* the following is parent process */
+        if ((fp = fdopen(fd[0], "r")) == NULL) {
+                perror("fdopen");
+                kill(pid, SIGKILL);
+                close(fd[0]);
+                return -1;
+        }
+
+        while (fgets(buf, PIPE_BUF, fp) != NULL) {
+                if (output_func(buf) < 0)
+                        fprintf(stderr, "WARNING: unexpected error!\n[%s]\n",
+                                buf);
+        }
+        fclose(fp);
+        close(fd[0]);
+
+        if (waitpid(pid, &status, 0) < 0) {
+                perror("waitpid");
+                return -1;
+        }
+
+        return child_status(status);
+}
+
+int llapi_lsetfacl(int argc, char *argv[])
+{
+        return do_rmtacl(argc, argv, RMT_LSETFACL, NULL);
+}
+
+int llapi_lgetfacl(int argc, char *argv[])
+{
+        return do_rmtacl(argc, argv, RMT_LGETFACL, NULL);
+}
+
+int llapi_rsetfacl(int argc, char *argv[])
+{
+        return do_rmtacl(argc, argv, RMT_RSETFACL, NULL);
+}
+
+int llapi_rgetfacl(int argc, char *argv[])
+{
+        return do_rmtacl(argc, argv, RMT_RGETFACL, rgetfacl_output);
+}
+
+int llapi_cp(int argc, char *argv[])
+{
+        int rc;
+
+        rc = rmtacl_notify(RMT_RSETFACL);
+        if (rc < 0)
+                return -1;
+
+        exit(execvp(argv[0], argv));
+}
+
+int llapi_ls(int argc, char *argv[])
+{
+        int rc;
+
+        rc = rmtacl_notify(RMT_LGETFACL);
+        if (rc < 0)
+                return -1;
+
+        exit(execvp(argv[0], argv));
 }
 }
index 8597bcd..b0db190 100755 (executable)
@@ -63,7 +63,7 @@ depmod -A -e
 echo "Copying mount from local build dir to "$MDIR
 cp -u ../utils/mount.lustre /sbin/.
 cp -u ../utils/l_getidentity /usr/sbin/.
 echo "Copying mount from local build dir to "$MDIR
 cp -u ../utils/mount.lustre /sbin/.
 cp -u ../utils/l_getidentity /usr/sbin/.
-cp -u ../utils/l_facl /usr/sbin/.
+cp -u ../utils/lfs /usr/sbin/.
 
 MP="/sbin/modprobe"
 MPI="$MP --ignore-install"
 
 MP="/sbin/modprobe"
 MPI="$MP --ignore-install"