diff --git a/lnet/autoconf/lustre-lnet.m4 b/lnet/autoconf/lustre-lnet.m4
index e368ff299640f00be2594c14f87212bd7cb65639..c5f1740e23cf9a5f1761d3b875baed3d5042d706 100644
--- a/lnet/autoconf/lustre-lnet.m4
+++ b/lnet/autoconf/lustre-lnet.m4
@@ -1066,7 +1066,7 @@ LB_LINUX_TRY_COMPILE([
 ])
 ])
 
-#2.6.19 API change
+# 2.6.19 API change
 #panic_notifier_list use atomic_notifier operations
 #
 AC_DEFUN([LN_ATOMIC_PANIC_NOTIFIER],
@@ -1085,6 +1085,42 @@ LB_LINUX_TRY_COMPILE([
 ])
 ])
 
+# 2.6.20 API change INIT_WORK use 2 args and not 
+# store data inside
+AC_DEFUN([LN_3ARGS_INIT_WORK],
+[AC_MSG_CHECKING([check INIT_WORK want 3 args])
+LB_LINUX_TRY_COMPILE([
+	#include <linux/workqueue.h>
+],[
+	struct work_struct work;
+
+	INIT_WORK(&work, NULL, NULL);
+],[
+        AC_MSG_RESULT(yes)
+        AC_DEFINE(HAVE_3ARGS_INIT_WORK, 1,
+                  [INIT_WORK use 3 args and store data inside])
+],[
+        AC_MSG_RESULT(NO)
+])
+])
+
+# 2.6.21 api change. 'register_sysctl_table' use only one argument,
+# instead of more old which need two.
+AC_DEFUN([LL_2ARGS_REGISTER_SYSCTL],
+[AC_MSG_CHECKING([check register_sysctl_table want 2 args])
+LB_LINUX_TRY_COMPILE([
+        #include <linux/sysctl.h>
+],[
+	return register_sysctl_table(NULL,0);
+],[
+        AC_MSG_RESULT(yes)
+        AC_DEFINE(HAVE_2ARGS_REGISTER_SYSCTL, 1,
+                  [register_sysctl_table want 2 args])
+],[
+        AC_MSG_RESULT(NO)
+])
+])
+
 #
 # LN_PROG_LINUX
 #
@@ -1117,6 +1153,10 @@ LN_TASKLIST_LOCK
 # 2.6.19
 LN_KMEM_CACHE_DESTROY_INT
 LN_ATOMIC_PANIC_NOTIFIER
+# 2.6.20
+LN_3ARGS_INIT_WORK
+# 2.6.21
+LL_2ARGS_REGISTER_SYSCTL
 ])
 
 #
diff --git a/lnet/include/libcfs/linux/kp30.h b/lnet/include/libcfs/linux/kp30.h
index a1e3b7c53f4e833b9fac4c038b989edf3f3e385c..9f84da4b11a1fd37a445458237b80a0a72616207 100644
--- a/lnet/include/libcfs/linux/kp30.h
+++ b/lnet/include/libcfs/linux/kp30.h
@@ -68,14 +68,30 @@ static inline void our_cond_resched(void)
         if (current->need_resched)
                schedule ();
 }
-#define work_struct_t       struct tq_struct
-
+#define work_struct_t                   struct tq_struct
+#define cfs_get_work_data(type,field,data)   (data)
 #else
 
+#ifdef HAVE_3ARGS_INIT_WORK
+
 #define prepare_work(wq,cb,cbdata)                                            \
 do {                                                                          \
         INIT_WORK((wq), (void *)(cb), (void *)(cbdata));                      \
 } while (0)
+
+#define cfs_get_work_data(type,field,data)   (data)
+
+#else
+
+#define prepare_work(wq,cb,cbdata)                                            \
+do {                                                                          \
+        INIT_WORK((wq), (void *)(cb));                                        \
+} while (0)
+
+#define cfs_get_work_data(type,field,data) container_of(data,type,field)
+
+#endif
+
 #define wait_on_page wait_on_page_locked
 #define our_recalc_sigpending(current) recalc_sigpending()
 #define strtok(a,b) strpbrk(a, b)
diff --git a/lnet/include/libcfs/linux/linux-prim.h b/lnet/include/libcfs/linux/linux-prim.h
index 41eeb8adeb068c113db058cf76c8e54866a8d36b..4efeef41c508a5e9dcd2edd738e592dc2ad36713 100644
--- a/lnet/include/libcfs/linux/linux-prim.h
+++ b/lnet/include/libcfs/linux/linux-prim.h
@@ -59,8 +59,12 @@ typedef struct miscdevice		cfs_psdev_t;
 typedef struct ctl_table		cfs_sysctl_table_t;
 typedef struct ctl_table_header		cfs_sysctl_table_header_t;
 
+#ifdef HAVE_2ARGS_REGISTER_SYSCTL
 #define cfs_register_sysctl_table(t, a)	register_sysctl_table(t, a)
-#define cfs_unregister_sysctl_table(t)	unregister_sysctl_table(t, a)
+#else
+#define cfs_register_sysctl_table(t, a) register_sysctl_table(t)
+#endif
+#define cfs_unregister_sysctl_table(t)	unregister_sysctl_table(t)
 
 /*
  * Symbol register
diff --git a/lnet/include/libcfs/winnt/kp30.h b/lnet/include/libcfs/winnt/kp30.h
index e494a9fde5621253e220e7b01bea6c11c7a50fc7..779d8be68d7c00d298fd1b73e5b58c514852aabc 100644
--- a/lnet/include/libcfs/winnt/kp30.h
+++ b/lnet/include/libcfs/winnt/kp30.h
@@ -57,6 +57,7 @@ static inline void our_cond_resched()
 #define cfs_work_struct_t WORK_QUEUE_ITEM
 #define cfs_prepare_work(tq, routine, contex)
 #define cfs_schedule_work(tq)
+#define cfs_get_work_data(type,field,data)   (data)
 
 /* ------------------------------------------------------------------- */
 
diff --git a/lnet/klnds/gmlnd/gmlnd_module.c b/lnet/klnds/gmlnd/gmlnd_module.c
index 114a286a53307246a93ba840b334d0ca2c34ca01..1f7f96f0ea2a8fc2e8dc9a90a9fbf50bb2487a34 100644
--- a/lnet/klnds/gmlnd/gmlnd_module.c
+++ b/lnet/klnds/gmlnd/gmlnd_module.c
@@ -93,7 +93,7 @@ gmnal_load(void)
 
 #if CONFIG_SYSCTL && !CFS_SYSFS_MODULE_PARM
         gmnal_tunables.gm_sysctl =
-                register_sysctl_table(gmnal_top_ctl_table, 0);
+                cfs_register_sysctl_table(gmnal_top_ctl_table, 0);
         
         if (gmnal_tunables.gm_sysctl == NULL)
                 CWARN("Can't setup /proc tunables\n");
@@ -118,7 +118,7 @@ gmnal_unload(void)
 	gmnal_fini();
 #if CONFIG_SYSCTL && !CFS_SYSFS_MODULE_PARM
         if (gmnal_tunables.gm_sysctl != NULL)
-                unregister_sysctl_table(gmnal_tunables.gm_sysctl);
+                cfs_unregister_sysctl_table(gmnal_tunables.gm_sysctl);
 #endif
 }
 
diff --git a/lnet/klnds/iiblnd/iiblnd_modparams.c b/lnet/klnds/iiblnd/iiblnd_modparams.c
index ceb6e5d2ae65fdfd46745232baf2ce990897af2f..94fb1af622b3c6189f23724a8d9546f8e590e95d 100644
--- a/lnet/klnds/iiblnd/iiblnd_modparams.c
+++ b/lnet/klnds/iiblnd/iiblnd_modparams.c
@@ -143,7 +143,7 @@ int
 kibnal_tunables_init ()
 {
 	kibnal_tunables.kib_sysctl =
-		register_sysctl_table(kibnal_top_ctl_table, 0);
+		cfs_register_sysctl_table(kibnal_top_ctl_table, 0);
 	
 	if (kibnal_tunables.kib_sysctl == NULL)
 		CWARN("Can't setup /proc tunables\n");
@@ -160,7 +160,7 @@ void
 kibnal_tunables_fini ()
 {
 	if (kibnal_tunables.kib_sysctl != NULL)
-		unregister_sysctl_table(kibnal_tunables.kib_sysctl);
+		cfs_unregister_sysctl_table(kibnal_tunables.kib_sysctl);
 }
 
 #else
diff --git a/lnet/klnds/o2iblnd/o2iblnd_modparams.c b/lnet/klnds/o2iblnd/o2iblnd_modparams.c
index ef42ffec40c22b96e945ee3bd3165445cf78943f..d09da473d2c5e509304f61f6e8f1e77822a27b5c 100644
--- a/lnet/klnds/o2iblnd/o2iblnd_modparams.c
+++ b/lnet/klnds/o2iblnd/o2iblnd_modparams.c
@@ -168,7 +168,7 @@ kiblnd_sysctl_init (void)
                               sizeof(ipif_basename_space));
 
 	kiblnd_tunables.kib_sysctl =
-		register_sysctl_table(kiblnd_top_ctl_table, 0);
+		cfs_register_sysctl_table(kiblnd_top_ctl_table, 0);
 
 	if (kiblnd_tunables.kib_sysctl == NULL)
 		CWARN("Can't setup /proc tunables\n");
@@ -178,7 +178,7 @@ void
 kiblnd_sysctl_fini (void)
 {
 	if (kiblnd_tunables.kib_sysctl != NULL)
-		unregister_sysctl_table(kiblnd_tunables.kib_sysctl);
+		cfs_unregister_sysctl_table(kiblnd_tunables.kib_sysctl);
 }
 
 #else
@@ -199,7 +199,7 @@ int
 kiblnd_tunables_init (void)
 {
         kiblnd_sysctl_init();
-        
+
         if (*kiblnd_tunables.kib_concurrent_sends > IBLND_RX_MSGS)
                 *kiblnd_tunables.kib_concurrent_sends = IBLND_RX_MSGS;
         if (*kiblnd_tunables.kib_concurrent_sends < IBLND_MSG_QUEUE_SIZE)
diff --git a/lnet/klnds/openiblnd/openiblnd_modparams.c b/lnet/klnds/openiblnd/openiblnd_modparams.c
index f40004b322a2de1bff5bc67906730c4656ee882f..693d38ef5c71d42101fff4460c2b359e23b1e96b 100644
--- a/lnet/klnds/openiblnd/openiblnd_modparams.c
+++ b/lnet/klnds/openiblnd/openiblnd_modparams.c
@@ -118,7 +118,7 @@ int
 kibnal_tunables_init ()
 {
 	kibnal_tunables.kib_sysctl =
-		register_sysctl_table(kibnal_top_ctl_table, 0);
+		cfs_register_sysctl_table(kibnal_top_ctl_table, 0);
 	
 	if (kibnal_tunables.kib_sysctl == NULL)
 		CWARN("Can't setup /proc tunables\n");
@@ -130,7 +130,7 @@ void
 kibnal_tunables_fini ()
 {
 	if (kibnal_tunables.kib_sysctl != NULL)
-		unregister_sysctl_table(kibnal_tunables.kib_sysctl);
+		cfs_unregister_sysctl_table(kibnal_tunables.kib_sysctl);
 }
 
 #else
diff --git a/lnet/klnds/ptllnd/ptllnd_modparams.c b/lnet/klnds/ptllnd/ptllnd_modparams.c
index 03134138e9422bd32d235c33df20720d0ecef95b..044353ab979f407c0595737ae8c86daebd582be0 100644
--- a/lnet/klnds/ptllnd/ptllnd_modparams.c
+++ b/lnet/klnds/ptllnd/ptllnd_modparams.c
@@ -192,7 +192,7 @@ kptllnd_tunables_init ()
                                 sizeof(ptltrace_basename_space));
 #endif
 	kptllnd_tunables.kptl_sysctl =
-		register_sysctl_table(kptllnd_top_ctl_table, 0);
+		cfs_register_sysctl_table(kptllnd_top_ctl_table, 0);
 
 	if (kptllnd_tunables.kptl_sysctl == NULL)
 		CWARN("Can't setup /proc tunables\n");
@@ -204,7 +204,7 @@ void
 kptllnd_tunables_fini ()
 {
 	if (kptllnd_tunables.kptl_sysctl != NULL)
-		unregister_sysctl_table(kptllnd_tunables.kptl_sysctl);
+		cfs_unregister_sysctl_table(kptllnd_tunables.kptl_sysctl);
 }
 
 #else
diff --git a/lnet/klnds/qswlnd/qswlnd_modparams.c b/lnet/klnds/qswlnd/qswlnd_modparams.c
index 87f51654f36ce6c0c87a810fe0335e2b5dd746d2..45b8cecc57deb3e17afee97e92099d490e17834e 100644
--- a/lnet/klnds/qswlnd/qswlnd_modparams.c
+++ b/lnet/klnds/qswlnd/qswlnd_modparams.c
@@ -121,7 +121,7 @@ int
 kqswnal_tunables_init ()
 {
 	kqswnal_tunables.kqn_sysctl =
-		register_sysctl_table(kqswnal_top_ctl_table, 0);
+		cfs_register_sysctl_table(kqswnal_top_ctl_table, 0);
 	
 	if (kqswnal_tunables.kqn_sysctl == NULL)
 		CWARN("Can't setup /proc tunables\n");
@@ -133,7 +133,7 @@ void
 kqswnal_tunables_fini ()
 {
 	if (kqswnal_tunables.kqn_sysctl != NULL)
-		unregister_sysctl_table(kqswnal_tunables.kqn_sysctl);
+		cfs_unregister_sysctl_table(kqswnal_tunables.kqn_sysctl);
 }
 #else
 int 
diff --git a/lnet/klnds/ralnd/ralnd_modparams.c b/lnet/klnds/ralnd/ralnd_modparams.c
index 45f42e1327099417667a184215a3198e8b737684..42aaac4a5bf5b12c59df5465ccc26ee719702d02 100644
--- a/lnet/klnds/ralnd/ralnd_modparams.c
+++ b/lnet/klnds/ralnd/ralnd_modparams.c
@@ -103,11 +103,11 @@ int
 kranal_tunables_init ()
 {
 	kranal_tunables.kra_sysctl =
-		register_sysctl_table(kranal_top_ctl_table, 0);
-	
+		cfs_register_sysctl_table(kranal_top_ctl_table, 0);
+
 	if (kranal_tunables.kra_sysctl == NULL)
 		CWARN("Can't setup /proc tunables\n");
-	
+
 	return 0;
 }
 
@@ -115,7 +115,7 @@ void
 kranal_tunables_fini ()
 {
 	if (kranal_tunables.kra_sysctl != NULL)
-		unregister_sysctl_table(kranal_tunables.kra_sysctl);
+		cfs_unregister_sysctl_table(kranal_tunables.kra_sysctl);
 }
 
 #else
diff --git a/lnet/klnds/socklnd/socklnd_lib-linux.c b/lnet/klnds/socklnd/socklnd_lib-linux.c
index b7e2f49eb2c0f3d4efde9d6754191c65d79f85a4..955849cead2ede29e9c156d2d8aa09767cd99d52 100644
--- a/lnet/klnds/socklnd/socklnd_lib-linux.c
+++ b/lnet/klnds/socklnd/socklnd_lib-linux.c
@@ -84,7 +84,7 @@ ksocknal_lib_tunables_init ()
 	LASSERT (i < sizeof(ksocknal_ctl_table)/sizeof(ksocknal_ctl_table[0]));
 
         ksocknal_tunables.ksnd_sysctl =
-                register_sysctl_table(ksocknal_top_ctl_table, 0);
+                cfs_register_sysctl_table(ksocknal_top_ctl_table, 0);
 
         if (ksocknal_tunables.ksnd_sysctl == NULL)
 		CWARN("Can't setup /proc tunables\n");
@@ -96,7 +96,7 @@ void
 ksocknal_lib_tunables_fini ()
 {
         if (ksocknal_tunables.ksnd_sysctl != NULL)
-                unregister_sysctl_table(ksocknal_tunables.ksnd_sysctl);
+                cfs_unregister_sysctl_table(ksocknal_tunables.ksnd_sysctl);
 }
 #else
 int
diff --git a/lnet/klnds/viblnd/viblnd_modparams.c b/lnet/klnds/viblnd/viblnd_modparams.c
index 1179d72960eed0fa57a677e868495aa4a67c15c4..22cf75a00ca49c07d05bd9591439a1b38379b682 100644
--- a/lnet/klnds/viblnd/viblnd_modparams.c
+++ b/lnet/klnds/viblnd/viblnd_modparams.c
@@ -195,8 +195,8 @@ kibnal_tunables_init ()
                               sizeof(ipif_basename_space));
 
 	kibnal_tunables.kib_sysctl =
-		register_sysctl_table(kibnal_top_ctl_table, 0);
-	
+		cfs_register_sysctl_table(kibnal_top_ctl_table, 0);
+
 	if (kibnal_tunables.kib_sysctl == NULL)
 		CWARN("Can't setup /proc tunables\n");
 
@@ -212,7 +212,7 @@ void
 kibnal_tunables_fini ()
 {
 	if (kibnal_tunables.kib_sysctl != NULL)
-		unregister_sysctl_table(kibnal_tunables.kib_sysctl);
+		cfs_unregister_sysctl_table(kibnal_tunables.kib_sysctl);
 }
 
 #else
@@ -229,9 +229,3 @@ kibnal_tunables_fini ()
 }
 
 #endif
-	
-		
-		
-
-	
-		
diff --git a/lnet/libcfs/linux/linux-proc.c b/lnet/libcfs/linux/linux-proc.c
index 3efdd467391fbb1d4ea1ff944176f12f8bd3af57..b090d1d4cf25d772e526a1ab4801861edee6f01d 100644
--- a/lnet/libcfs/linux/linux-proc.c
+++ b/lnet/libcfs/linux/linux-proc.c
@@ -78,28 +78,86 @@ enum {
 int LL_PROC_PROTO(proc_dobitmasks);
 
 static struct ctl_table lnet_table[] = {
-        {PSDEV_DEBUG, "debug", &libcfs_debug, sizeof(int), 0644, NULL,
-         &proc_dobitmasks},
-        {PSDEV_SUBSYSTEM_DEBUG, "subsystem_debug", &libcfs_subsystem_debug,
-         sizeof(int), 0644, NULL, &proc_dobitmasks},
-        {PSDEV_PRINTK, "printk", &libcfs_printk, sizeof(int), 0644, NULL,
-         &proc_dobitmasks},
-        {PSDEV_CONSOLE_RATELIMIT, "console_ratelimit",&libcfs_console_ratelimit,
-         sizeof(int), 0644, NULL, &proc_dointvec},
-        {PSDEV_DEBUG_PATH, "debug_path", debug_file_path,
-         sizeof(debug_file_path), 0644, NULL, &proc_dostring, &sysctl_string},
-        {PSDEV_LNET_UPCALL, "upcall", lnet_upcall,
-         sizeof(lnet_upcall), 0644, NULL, &proc_dostring,
-         &sysctl_string},
-        {PSDEV_LNET_MEMUSED, "memused", (int *)&libcfs_kmemory.counter,
-         sizeof(int), 0444, NULL, &proc_dointvec},
-        {PSDEV_LNET_CATASTROPHE, "catastrophe", &libcfs_catastrophe,
-         sizeof(int), 0444, NULL, &proc_dointvec},
+        {
+                .ctl_name = PSDEV_DEBUG,
+                .procname = "debug",
+                .data     = &libcfs_debug,
+                .maxlen   = sizeof(int),
+                .mode     = 0644,
+                .proc_handler = &proc_dobitmasks
+        },
+        {
+                .ctl_name = PSDEV_SUBSYSTEM_DEBUG,
+                .procname = "subsystem_debug",
+                .data     = &libcfs_subsystem_debug,
+                .maxlen   = sizeof(int),
+                .mode     = 0644,
+                .proc_handler = &proc_dobitmasks
+        },
+        {
+                .ctl_name = PSDEV_PRINTK,
+                .procname = "printk",
+                .data     = &libcfs_printk,
+                .maxlen   = sizeof(int),
+                .mode     = 0644,
+                .proc_handler = &proc_dobitmasks
+        },
+        {
+                .ctl_name = PSDEV_CONSOLE_RATELIMIT,
+                .procname = "console_ratelimit",
+                .data     = &libcfs_console_ratelimit,
+                .maxlen   = sizeof(int),
+                .mode     = 0644,
+                .proc_handler = &proc_dointvec
+        },
+
+        {
+                .ctl_name = PSDEV_DEBUG_PATH,
+                .procname = "debug_path",
+                .data     = debug_file_path,
+                .maxlen   = sizeof(debug_file_path),
+                .mode     = 0644,
+                .proc_handler = &proc_dostring,
+                .strategy =  &sysctl_string
+        },
+
+        {
+                .ctl_name = PSDEV_LNET_UPCALL,
+                .procname = "upcall",
+                .data     = lnet_upcall,
+                .maxlen   = sizeof(lnet_upcall),
+                .mode     = 0644,
+                .proc_handler = &proc_dostring,
+                .strategy =  &sysctl_string
+        },
+        {
+                .ctl_name = PSDEV_LNET_MEMUSED,
+                .procname = "memused",
+                .data     = (int *)&libcfs_kmemory.counter,
+                .maxlen   = sizeof(int),
+                .mode     = 0444,
+                .proc_handler = &proc_dointvec
+        },
+        {
+                .ctl_name = PSDEV_LNET_CATASTROPHE,
+                .procname = "catastrophe",
+                .data     = &libcfs_catastrophe,
+                .maxlen   = sizeof(int),
+                .mode     = 0444,
+                .proc_handler = &proc_dointvec
+        },
         {0}
 };
 
 static struct ctl_table top_table[2] = {
-        {PSDEV_LNET, "lnet", NULL, 0, 0555, lnet_table},
+        {
+                .ctl_name = PSDEV_LNET,
+                .procname = "lnet",
+                .data     = NULL,
+                .maxlen   = 0,
+                .mode     = 0555,
+                .child    = lnet_table
+        },
         {0}
 };
 
@@ -174,7 +232,7 @@ int insert_proc(void)
 
 #ifdef CONFIG_SYSCTL
         if (!lnet_table_header)
-                lnet_table_header = register_sysctl_table(top_table, 0);
+                lnet_table_header = cfs_register_sysctl_table(top_table, 0);
 #endif
 
         ent = create_proc_entry("sys/lnet/dump_kernel", 0, NULL);
@@ -211,7 +269,7 @@ void remove_proc(void)
 
 #ifdef CONFIG_SYSCTL
         if (lnet_table_header)
-                unregister_sysctl_table(lnet_table_header);
+                cfs_unregister_sysctl_table(lnet_table_header);
         lnet_table_header = NULL;
 #endif
 }