From d10f010ab51f54e2e3d1dcf7b0b56e20a2354b72 Mon Sep 17 00:00:00 2001
From: Simon Wilkinson <sxw@your-file-system.com>
Date: Sun, 17 Apr 2011 23:43:51 +0100
Subject: [PATCH 1/6] Linux CM: Use kernel allocator directly

In another few locations within the Linux portion of the cache
manager, directly use the kernel allocator. We can do so here
because we can guarantee that the amount of memory being allocated
is less than the page size, and there is a kfree() in all of the
exit paths, so we don't need the magic freeing behaviour, either.

Reviewed-on: http://gerrit.openafs.org/4752
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Reviewed-by: Marc Dionne <marc.c.dionne@gmail.com>
Tested-by: Derrick Brashear <shadow@dementia.org>
(cherry picked from commit 7a70c2907b0435653098a611a140fea1ac0b2fac)

Change-Id: I72fd6a2109022af5e14d90ce147705da7ccec587
Reviewed-on: http://gerrit.openafs.org/11933
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Chas Williams <3chas3@gmail.com>
Reviewed-by: Perry Ruiter <pruiter@sinenomine.net>
Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
(cherry picked from commit 602130f1de65eefeb4e31e114070d544eb9edd40)
---
 src/afs/LINUX/osi_vfsops.c   |  4 ++--
 src/afs/LINUX/osi_vnodeops.c | 16 ++++++++--------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/afs/LINUX/osi_vfsops.c b/src/afs/LINUX/osi_vfsops.c
index d6504ae..934478d 100644
--- a/src/afs/LINUX/osi_vfsops.c
+++ b/src/afs/LINUX/osi_vfsops.c
@@ -112,7 +112,7 @@ afs_fill_super(struct super_block *sb, void *data, int silent)
 #endif
 
     /* used for inodes backing_dev_info field, also */
-    afs_backing_dev_info = osi_Alloc(sizeof(struct backing_dev_info));
+    afs_backing_dev_info = kmalloc(sizeof(struct backing_dev_info), GFP_NOFS);
     memset(afs_backing_dev_info, 0, sizeof(struct backing_dev_info));
 #if defined(HAVE_LINUX_BDI_INIT)
     bdi_init(afs_backing_dev_info);
@@ -338,7 +338,7 @@ afs_put_super(struct super_block *sbp)
 #if defined(HAVE_LINUX_BDI_INIT)
     bdi_destroy(afs_backing_dev_info);
 #endif
-    osi_Free(afs_backing_dev_info, sizeof(struct backing_dev_info));
+    kfree(afs_backing_dev_info);
     AFS_GUNLOCK();
 
     sbp->s_dev = 0;
diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
index 91c09ed..a8f0074 100644
--- a/src/afs/LINUX/osi_vnodeops.c
+++ b/src/afs/LINUX/osi_vnodeops.c
@@ -1893,7 +1893,7 @@ static int afs_linux_follow_link(struct dentry *dentry, struct nameidata *nd)
     int code;
     char *name;
 
-    name = osi_Alloc(PATH_MAX);
+    name = kmalloc(PATH_MAX, GFP_NOFS);
     if (!name) {
 	return -EIO;
     }
@@ -1915,9 +1915,9 @@ static void
 afs_linux_put_link(struct dentry *dentry, struct nameidata *nd)
 {
     char *name = nd_get_link(nd);
-    if (name && !IS_ERR(name)) {
-	osi_Free(name, PATH_MAX);
-    }
+
+    if (name && !IS_ERR(name))
+	kfree(name);
 }
 
 #endif /* USABLE_KERNEL_PAGE_SYMLINK_CACHE */
@@ -2174,8 +2174,8 @@ afs_linux_fillpage(struct file *fp, struct page *pp)
     address = kmap(pp);
     ClearPageError(pp);
 
-    auio = osi_Alloc(sizeof(struct uio));
-    iovecp = osi_Alloc(sizeof(struct iovec));
+    auio = kmalloc(sizeof(struct uio), GFP_NOFS);
+    iovecp = kmalloc(sizeof(struct iovec), GFP_NOFS);
 
     setup_uio(auio, iovecp, (char *)address, offset, PAGE_SIZE, UIO_READ,
               AFS_UIOSYS);
@@ -2206,8 +2206,8 @@ afs_linux_fillpage(struct file *fp, struct page *pp)
 
     kunmap(pp);
 
-    osi_Free(auio, sizeof(struct uio));
-    osi_Free(iovecp, sizeof(struct iovec));
+    kfree(auio);
+    kfree(iovecp);
 
     crfree(credp);
     return afs_convert_code(code);
-- 
2.5.1

From 35259d83d7e2e445c20ddc2f603c2fc74cf5164c Mon Sep 17 00:00:00 2001
From: Marc Dionne <marc.dionne@your-file-system.com>
Date: Wed, 8 Jul 2015 14:32:31 -0300
Subject: [PATCH 2/6] Linux 4.2: Pass namespace to sock_create_kern

sock_create_kern gains an additional network namespace
argument.

Pass in the default system namesapce.

Reviewed-on: http://gerrit.openafs.org/11925
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Perry Ruiter <pruiter@sinenomine.net>
Reviewed-by: Chas Williams <3chas3@gmail.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>
(cherry picked from commit e597b879677d023165298adadfb88db031883ff4)

Change-Id: I8e4341a6b4c33c5226b9307827932f577e08d5b2
Reviewed-on: http://gerrit.openafs.org/11948
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
(cherry picked from commit 8d1e5a497635bf453c73525b9df2bcf9c13a5faf)
---
 acinclude.m4           | 3 +++
 src/rx/LINUX/rx_knet.c | 4 +++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/acinclude.m4 b/acinclude.m4
index dda9798..a99592a 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -997,6 +997,9 @@ case $AFS_SYSNAME in *_linux* | *_umlinux*)
 		 AC_CHECK_LINUX_FUNC([sock_create_kern],
 				     [#include <linux/net.h>],
 				     [sock_create_kern(0, 0, 0, NULL);])
+		 AC_CHECK_LINUX_FUNC([sock_create_kern_ns],
+				     [#include <linux/net.h>],
+				     [sock_create_kern(NULL, 0, 0, 0, NULL);])
 		 AC_CHECK_LINUX_FUNC([splice_direct_to_actor],
 				     [#include <linux/splice.h>],
 				     [splice_direct_to_actor(NULL,NULL,NULL);])
diff --git a/src/rx/LINUX/rx_knet.c b/src/rx/LINUX/rx_knet.c
index 3f7f2bc..1a5cfde 100644
--- a/src/rx/LINUX/rx_knet.c
+++ b/src/rx/LINUX/rx_knet.c
@@ -42,7 +42,9 @@ rxk_NewSocketHost(afs_uint32 ahost, short aport)
     int pmtu = IP_PMTUDISC_DONT;
 #endif
 
-#ifdef HAVE_LINUX_SOCK_CREATE_KERN
+#ifdef HAVE_LINUX_SOCK_CREATE_KERN_NS
+    code = sock_create_kern(&init_net, AF_INET, SOCK_DGRAM, IPPROTO_UDP, &sockp);
+#elif defined(HAVE_LINUX_SOCK_CREATE_KERN)
     code = sock_create_kern(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &sockp);
 #elif defined(LINUX_KERNEL_SOCK_CREATE_V)
     code = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &sockp, 0);
-- 
2.5.1

From e123ace58e2c574cd2eb50ec28f8fe616f9ca69d Mon Sep 17 00:00:00 2001
From: Marc Dionne <marc.dionne@your-file-system.com>
Date: Mon, 6 Jul 2015 11:00:13 -0300
Subject: [PATCH 3/6] Linux 4.2: total_link_count is no longer accessible

The value is now stored in the nameidata structure which
is private to fs/namei.c, so we can't modify it here.

The effect is that using a path that contains 40+ directories
may fail with ELOOP, depending on which directories in the
path were previously used.  After a directory is accessed once
its D_AUTOMOUNT flag is reset and it will no longer count
against the symlink limit in later path lookups.

Reviewed-on: http://gerrit.openafs.org/11926
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>
(cherry picked from commit 89aeb71a3e23c944f58cfa9572e9eae4d2130d37)

Change-Id: Ib6282f3029c4112c510217eacf270a56d679fccd
Reviewed-on: http://gerrit.openafs.org/11949
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
(cherry picked from commit 2e5ba7e16c6797a39323173ce17a1db698526c2c)
---
 acinclude.m4                 |  1 +
 src/afs/LINUX/osi_vnodeops.c | 12 ++++++++++--
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/acinclude.m4 b/acinclude.m4
index a99592a..c924d90 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -902,6 +902,7 @@ case $AFS_SYSNAME in *_linux* | *_umlinux*)
 		 AC_CHECK_LINUX_STRUCT([task_struct], [sigmask_lock], [sched.h])
 		 AC_CHECK_LINUX_STRUCT([task_struct], [tgid], [sched.h])
 		 AC_CHECK_LINUX_STRUCT([task_struct], [thread_info], [sched.h])
+		 AC_CHECK_LINUX_STRUCT([task_struct], [total_link_count], [sched.h])
 		 LINUX_SCHED_STRUCT_TASK_STRUCT_HAS_SIGNAL_RLIM
 
 		 dnl Check for typed structure elements
diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
index a8f0074..a878eb4 100644
--- a/src/afs/LINUX/osi_vnodeops.c
+++ b/src/afs/LINUX/osi_vnodeops.c
@@ -1385,9 +1385,17 @@ afs_dentry_automount(afs_linux_path_t *path)
 {
     struct dentry *target;
 
-    /* avoid symlink resolution limits when resolving; we cannot contribute to
-     * an infinite symlink loop */
+    /* 
+     * Avoid symlink resolution limits when resolving; we cannot contribute to
+     * an infinite symlink loop.
+     *
+     * On newer kernels the field has moved to the private nameidata structure
+     * so we can't adjust it here.  This may cause ELOOP when using a path with
+     * 40 or more directories that are not already in the dentry cache.
+     */
+#if defined(STRUCT_TASK_STRUCT_HAS_TOTAL_LINK_COUNT)
     current->total_link_count--;
+#endif
 
     target = canonical_dentry(path->dentry->d_inode);
 
-- 
2.5.1

From ec8c1a258c18a07171f5316f5150da9b15ad53c3 Mon Sep 17 00:00:00 2001
From: Marc Dionne <marc.dionne@your-file-system.com>
Date: Mon, 6 Jul 2015 12:00:10 -0300
Subject: [PATCH 4/6] Linux: Add AC_CHECK_LINUX_OPERATION configure macro

Add a new macro to check the signature of a particular
operation against a provided typed argument list.
One of the arguments is an arbitrary label that is used
to construct the pre-processor define name.  This will
allow for testing of different forms for the same
operation.

This can be used to replace many of the remaining odd
checks in src/cf/linux_test4.m4.

Reviewed-on: http://gerrit.openafs.org/11927
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>
(cherry picked from commit c2c0b6bc86c6d67814d0f7fe14fa8eefc445b4a4)

Change-Id: Id929412d87bb9fc38b2b599abbe3fddca3cda4b1
Reviewed-on: http://gerrit.openafs.org/11950
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
(cherry picked from commit dfcf0b348886b4a97d2c8a8b90eae98ad9e25834)
---
 src/cf/linux-test1.m4 | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/src/cf/linux-test1.m4 b/src/cf/linux-test1.m4
index f7176d2..fd5bfd8 100644
--- a/src/cf/linux-test1.m4
+++ b/src/cf/linux-test1.m4
@@ -150,3 +150,18 @@ AC_DEFUN([AC_CHECK_LINUX_TYPED_STRUCT],
 		       [Define if kernel typedef'd $1 has the $2 element])
  ])
 
+dnl AC_CHECK_LINUX_OPERATION([structure], [operation], [label], [includes], [return_type], [args])
+AC_DEFUN([AC_CHECK_LINUX_OPERATION],
+ [AS_VAR_PUSHDEF([ac_linux_operation], [ac_cv_linux_operation_$1_$2_$3])
+  AC_CACHE_CHECK([operation $2 in $1], [ac_linux_operation],
+    [save_CPPFLAGS="$CPPFLAGS"
+     CPPFLAGS="$CPPFLAGS -Werror"
+     AC_TRY_KBUILD([$4], [struct $1 ops; $5 op($6) { return ($5)0; }; ops.$2 = op;],
+		   AS_VAR_SET([ac_linux_operation], [yes]),
+		   AS_VAR_SET([ac_linux_operation], [no]))
+     CPPFLAGS="$save_CPPFLAGS"
+    ])
+  AS_IF([test AS_VAR_GET([ac_linux_operation]) = yes],
+	[AC_DEFINE(AS_TR_CPP(HAVE_LINUX_$1_$2_$3), 1,
+		   [Define if $1 has $2 operation of form $6])])
+ ])
-- 
2.5.1

From 1c8e07a6e09d25d1f3dc63b4af8f7267eabe34ee Mon Sep 17 00:00:00 2001
From: Marc Dionne <marc.dionne@your-file-system.com>
Date: Mon, 6 Jul 2015 13:01:38 -0300
Subject: [PATCH 5/6] Linux 4.2: Changes in link operation APIs

The follow_link and put_link operations are revised.
Test for the new signature and adapt the code.

Reviewed-on: http://gerrit.openafs.org/11928
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>
(cherry picked from commit 6c3ac6dc1ea865153a65b5c5c4f288617a3e6d0f)

Change-Id: I779fe8a29ec75a5db545b5d370927b810c1165c9
Reviewed-on: http://gerrit.openafs.org/11951
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
(cherry picked from commit b93da6f3e99735ef2584fb172d028284bb581011)
---
 acinclude.m4                 | 10 ++++++++++
 src/afs/LINUX/osi_vnodeops.c | 27 +++++++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/acinclude.m4 b/acinclude.m4
index c924d90..e9e84a7f 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -845,6 +845,16 @@ case $AFS_SYSNAME in *_linux* | *_umlinux*)
 		 LINUX_KBUILD_USES_EXTRA_CFLAGS
 		 LINUX_KERNEL_COMPILE_WORKS
 
+		 dnl Operation signature checks
+		 AC_CHECK_LINUX_OPERATION([inode_operations], [follow_link], [no_nameidata],
+					  [#include <linux/fs.h>],
+					  [const char *],
+					  [struct dentry *dentry, void **link_data])
+		 AC_CHECK_LINUX_OPERATION([inode_operations], [put_link], [no_nameidata],
+					  [#include <linux/fs.h>],
+					  [void],
+					  [struct inode *inode, void *link_data])
+
 		 dnl Check for header files
 		 AC_CHECK_LINUX_HEADER([config.h])
 		 AC_CHECK_LINUX_HEADER([completion.h])
diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
index a878eb4..3c0cb33 100644
--- a/src/afs/LINUX/osi_vnodeops.c
+++ b/src/afs/LINUX/osi_vnodeops.c
@@ -1896,14 +1896,22 @@ afs_linux_readlink(struct dentry *dp, char *target, int maxlen)
 /* afs_linux_follow_link
  * a file system dependent link following routine.
  */
+#if defined(HAVE_LINUX_INODE_OPERATIONS_FOLLOW_LINK_NO_NAMEIDATA)
+static const char *afs_linux_follow_link(struct dentry *dentry, void **link_data)
+#else
 static int afs_linux_follow_link(struct dentry *dentry, struct nameidata *nd)
+#endif
 {
     int code;
     char *name;
 
     name = kmalloc(PATH_MAX, GFP_NOFS);
     if (!name) {
+#if defined(HAVE_LINUX_INODE_OPERATIONS_FOLLOW_LINK_NO_NAMEIDATA)
+	return ERR_PTR(-EIO);
+#else
 	return -EIO;
+#endif
     }
 
     AFS_GLOCK();
@@ -1911,14 +1919,32 @@ static int afs_linux_follow_link(struct dentry *dentry, struct nameidata *nd)
     AFS_GUNLOCK();
 
     if (code < 0) {
+#if defined(HAVE_LINUX_INODE_OPERATIONS_FOLLOW_LINK_NO_NAMEIDATA)
+	return ERR_PTR(code);
+#else
 	return code;
+#endif
     }
 
     name[code] = '\0';
+#if defined(HAVE_LINUX_INODE_OPERATIONS_FOLLOW_LINK_NO_NAMEIDATA)
+    return *link_data = name;
+#else
     nd_set_link(nd, name);
     return 0;
+#endif
 }
 
+#if defined(HAVE_LINUX_INODE_OPERATIONS_PUT_LINK_NO_NAMEIDATA)
+static void
+afs_linux_put_link(struct inode *inode, void *link_data)
+{
+    char *name = link_data;
+
+    if (name && !IS_ERR(name))
+	kfree(name);
+}
+#else
 static void
 afs_linux_put_link(struct dentry *dentry, struct nameidata *nd)
 {
@@ -1927,6 +1953,7 @@ afs_linux_put_link(struct dentry *dentry, struct nameidata *nd)
     if (name && !IS_ERR(name))
 	kfree(name);
 }
+#endif /* HAVE_LINUX_INODE_OPERATIONS_PUT_LINK_NO_NAMEIDATA */
 
 #endif /* USABLE_KERNEL_PAGE_SYMLINK_CACHE */
 
-- 
2.5.1

From 81d05d6fb3b79e572064f57e1f8185d3b16149dc Mon Sep 17 00:00:00 2001
From: Marc Dionne <marc.dionne@your-file-system.com>
Date: Wed, 29 Jul 2015 09:03:14 -0300
Subject: [PATCH 6/6] Linux: Only use automount for volume roots

As long as we avoid using directory aliases when crossing
a mount point (at the volume root), we should always get
to a given non root directory with the same dentry.
The mechanism added by commit de381aa0 ("Linux: Make dir
dentry aliases act like symlinks") is therefore only really
necessary for a volume root.

With kernel 4.2 it is not possible to tweak the "total link
count", resulting in ELOOP errors when looking up a path
with 40 or more directories that are being looked up for
the first time.  With this change, only mountpoints will
count against the limit.

Reviewed-on: http://gerrit.openafs.org/11945
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Reviewed-by: Daria Brashear <shadow@your-file-system.com>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
(cherry picked from commit 05f64de7d723a8d5430d9b5928c2025838a6fa52)

Change-Id: I16e855c8322174604288b7d440b342951dd3a015
---
 src/afs/LINUX/osi_vnodeops.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
index 3c0cb33..ae0513c 100644
--- a/src/afs/LINUX/osi_vnodeops.c
+++ b/src/afs/LINUX/osi_vnodeops.c
@@ -1555,7 +1555,9 @@ afs_linux_lookup(struct inode *dip, struct dentry *dp)
 	d_prune_aliases(ip);
 
 #ifdef STRUCT_DENTRY_OPERATIONS_HAS_D_AUTOMOUNT
-	ip->i_flags |= S_AUTOMOUNT;
+	/* Only needed if this is a volume root */
+	if (vcp->mvstat == 2)
+	    ip->i_flags |= S_AUTOMOUNT;
 #endif
     }
     /*
-- 
2.5.1

