SHA256
1
0
forked from pool/openafs
openafs/linux-kmp.patch

1574 lines
55 KiB
Diff

commit d7fc5bf9bf031089d80703c48daf30d5b15a80ca
Author: Cheyenne Wills <cwills@sinenomine.net>
Date: Fri Jul 3 10:33:51 2020 -0600
LINUX 5.8: Replace kernel_setsockopt with new funcs
Linux 5.8-rc1 commit 'net: remove kernel_setsockopt' (5a892ff2facb)
retires the kernel_setsockopt function. In prior kernel commits new
functions (ip_sock_set_*) were added to replace the specific functions
performed by kernel_setsockopt.
Define new config test 'HAVE_IP_SOCK_SET' if the 'ip_sock_set' functions
are available. The config define 'HAVE_KERNEL_SETSOCKOPT' is no longer
set in Linux 5.8.
Create wrapper functions that replace the kernel_setsockopt calls with
calls to the appropriate Linux kernel function(s) (depending on what
functions the kernel supports).
Remove the unused 'kernel_getsockopt' function (used for building with
pre 2.6.19 kernels).
For reference
Linux 2.6.19 introduced kernel_setsockopt
Linux 5.8 removed kernel_setsockopt and replaced the functionality
with a set of new functions (ip_sock_set_*)
Reviewed-on: https://gerrit.openafs.org/14247
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
(cherry picked from commit c48072b9800759ef1682b91ff1e962f6904a2594)
Change-Id: I2724fad06b1882149d2066d13eced55eff5ee695
Reviewed-on: https://gerrit.openafs.org/14267
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Michael Laß <lass@mail.uni-paderborn.de>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
diff --git a/src/afs/LINUX/osi_compat.h b/src/afs/LINUX/osi_compat.h
index 4999b89b9..620b3730c 100644
--- a/src/afs/LINUX/osi_compat.h
+++ b/src/afs/LINUX/osi_compat.h
@@ -314,9 +314,22 @@ zero_user_segment(struct page *pp, unsigned int from1, unsigned int to1)
}
#endif
-#ifndef HAVE_LINUX_KERNEL_SETSOCKOPT
+#if defined(HAVE_LINUX_IP_SOCK_SET)
+# include <net/ip.h>
+/* ip_sock_set_* introduced in linux 5.8 */
+static inline void
+afs_linux_sock_set_mtu_discover(struct socket *sockp, int pmtu)
+{
+ ip_sock_set_mtu_discover(sockp->sk, pmtu);
+}
+static inline void
+afs_linux_sock_set_recverr(struct socket *sockp)
+{
+ ip_sock_set_recverr(sockp->sk);
+}
+#else
+# if !defined(HAVE_LINUX_KERNEL_SETSOCKOPT)
/* Available from 2.6.19 */
-
static inline int
kernel_setsockopt(struct socket *sockp, int level, int name, char *val,
unsigned int len) {
@@ -329,20 +342,22 @@ kernel_setsockopt(struct socket *sockp, int level, int name, char *val,
return ret;
}
+# endif /* !HAVE_LINUX_KERNEL_SETSOCKOPT */
-static inline int
-kernel_getsockopt(struct socket *sockp, int level, int name, char *val,
- int *len) {
- mm_segment_t old_fs = get_fs();
- int ret;
-
- set_fs(get_ds());
- ret = sockp->ops->getsockopt(sockp, level, name, val, len);
- set_fs(old_fs);
-
- return ret;
+static inline void
+afs_linux_sock_set_mtu_discover(struct socket *sockp, int pmtu)
+{
+ kernel_setsockopt(sockp, SOL_IP, IP_MTU_DISCOVER, (char *)&pmtu,
+ sizeof(pmtu));
}
-#endif
+static inline void
+afs_linux_sock_set_recverr(struct socket *sockp)
+{
+ int recverr = 1;
+ kernel_setsockopt(sockp, SOL_IP, IP_RECVERR, (char *)&recverr,
+ sizeof(recverr));
+}
+#endif /* !HAVE_LINUX_IP_SOCK_SET */
#ifdef HAVE_TRY_TO_FREEZE
static inline int
diff --git a/src/cf/linux-kernel-func.m4 b/src/cf/linux-kernel-func.m4
index 07627db52..78ff48294 100644
--- a/src/cf/linux-kernel-func.m4
+++ b/src/cf/linux-kernel-func.m4
@@ -151,6 +151,12 @@ AC_CHECK_LINUX_FUNC([lru_cache_add_file],
[#include <linux/swap.h>],
[lru_cache_add_file(NULL);])
+dnl Linux 5.8 replaced kernel_setsockopt with helper functions
+dnl e.g. ip_sock_set_mtu_discover, ip_sock_set_recverr
+AC_CHECK_LINUX_FUNC([ip_sock_set],
+ [#include <net/ip.h>],
+ [ip_sock_set_mtu_discover(NULL, 0);])
+
dnl Consequences - things which get set as a result of the
dnl above tests
AS_IF([test "x$ac_cv_linux_func_d_alloc_anon" = "xno"],
diff --git a/src/rx/LINUX/rx_knet.c b/src/rx/LINUX/rx_knet.c
index 9fbb563f3..50607c8f5 100644
--- a/src/rx/LINUX/rx_knet.c
+++ b/src/rx/LINUX/rx_knet.c
@@ -34,7 +34,6 @@
#include <linux/errqueue.h>
#include <linux/icmp.h>
#endif
-
#include "osi_compat.h"
/* rxk_NewSocket
@@ -76,14 +75,10 @@ rxk_NewSocketHost(afs_uint32 ahost, short aport)
return NULL;
}
- kernel_setsockopt(sockp, SOL_IP, IP_MTU_DISCOVER, (char *)&pmtu,
- sizeof(pmtu));
+ afs_linux_sock_set_mtu_discover(sockp, pmtu);
+
#ifdef AFS_RXERRQ_ENV
- {
- int recverr = 1;
- kernel_setsockopt(sockp, SOL_IP, IP_RECVERR, (char *)&recverr,
- sizeof(recverr));
- }
+ afs_linux_sock_set_recverr(sockp);
#endif
return (osi_socket *)sockp;
}
commit 335f37be13d2ff954e4aeea617ee66502170805e
Author: Cheyenne Wills <cwills@sinenomine.net>
Date: Fri Jul 3 10:34:42 2020 -0600
LINUX 5.8: do not set name field in backing_dev_info
Linux-5.8-rc1 commit 'bdi: remove the name field in struct
backing_dev_info' (1cd925d5838)
Do not set the name field in the backing_dev_info structure if it is
not available. Uses an existing config test
'STRUCT_BACKING_DEV_INFO_HAS_NAME'
Note the name field in the backing_dev_info structure was added in
Linux-2.6.32
Reviewed-on: https://gerrit.openafs.org/14248
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
(cherry picked from commit d8ec294534fcdee77a2ccd297b4b167dc4d5573d)
Change-Id: I3d9e18092db998a4c4f26bd63ee3b75383a53d4c
Reviewed-on: https://gerrit.openafs.org/14268
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Michael Laß <lass@mail.uni-paderborn.de>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
diff --git a/src/afs/LINUX/osi_vfsops.c b/src/afs/LINUX/osi_vfsops.c
index 8bbb5f225..ca1d5c83b 100644
--- a/src/afs/LINUX/osi_vfsops.c
+++ b/src/afs/LINUX/osi_vfsops.c
@@ -121,7 +121,9 @@ afs_fill_super(struct super_block *sb, void *data, int silent)
code = super_setup_bdi(sb);
if (code)
goto out;
+# if defined(STRUCT_BACKING_DEV_INFO_HAS_NAME)
sb->s_bdi->name = "openafs";
+# endif
sb->s_bdi->ra_pages = 32;
#else
/* used for inodes backing_dev_info field, also */
commit facff58b840a47853592510617ba7a1da2e3eaa9
Author: Cheyenne Wills <cwills@sinenomine.net>
Date: Fri Jul 3 10:35:06 2020 -0600
LINUX 5.8: use lru_cache_add
With Linux-5.8-rc1 commit 'mm: fold and remove lru_cache_add_anon() and
lru_cache_add_file()' (6058eaec), the lru_cache_add_file function is
removed since it was functionally equivalent to lru_cache_add.
Replace lru_cache_add_file with lru_cache_add.
Introduce a new autoconf test to determine if lru_cache_add is present
For reference, the Linux changes associated with the lru caches:
__pagevec_lru_add introduced before v2.6.12-rc2
lru_cache_add_file introduced in v2.6.28-rc1
__pagevec_lru_add_file replaces __pagevec_lru_add in v2.6.28-rc1
vmscan: split LRU lists into anon & file sets (4f98a2fee)
__pagevec_lru_add removed in v5.7 with a note to use lru_cache_add_file
mm/swap.c: not necessary to export __pagevec_lru_add() (bde07cfc6)
lru_cache_add_file removed in v5.8
mm: fold and remove lru_cache_add_anon() and lru_cache_add_file()
(6058eaec)
lru_cache_add exported
mm: fold and remove lru_cache_add_anon() and lru_cache_add_file()
(6058eaec)
Openafs will use:
lru_cache_add on 5.8 kernels
lru_cache_add_file from 2.6.28 through 5.7 kernels
__pagevec_lru_add/__pagevec_lru_add_file on pre 2.6.28 kernels
Reviewed-on: https://gerrit.openafs.org/14249
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Yadavendra Yadav <yadayada@in.ibm.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
(cherry picked from commit 7d85ce221d6ccc19cf76ce7680c74311e4ed2632)
Change-Id: Iba6ef4441687dbf60d227a708e2a032c2c0dc79f
Reviewed-on: https://gerrit.openafs.org/14269
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Michael Laß <lass@mail.uni-paderborn.de>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
index 00995b27a..36a4f685e 100644
--- a/src/afs/LINUX/osi_vnodeops.c
+++ b/src/afs/LINUX/osi_vnodeops.c
@@ -71,7 +71,7 @@ extern struct vcache *afs_globalVp;
/* Handle interfacing with Linux's pagevec/lru facilities */
-#if defined(HAVE_LINUX_LRU_CACHE_ADD_FILE)
+#if defined(HAVE_LINUX_LRU_CACHE_ADD_FILE) || defined(HAVE_LINUX_LRU_CACHE_ADD)
/*
* Linux's lru_cache_add_file provides a simplified LRU interface without
@@ -90,7 +90,13 @@ afs_lru_cache_init(struct afs_lru_pages *alrupages)
static inline void
afs_lru_cache_add(struct afs_lru_pages *alrupages, struct page *page)
{
+# if defined(HAVE_LINUX_LRU_CACHE_ADD)
+ lru_cache_add(page);
+# elif defined(HAVE_LINUX_LRU_CACHE_ADD_FILE)
lru_cache_add_file(page);
+# else
+# error need a kernel function to add a page to the kernel lru cache
+# endif
}
static inline void
diff --git a/src/cf/linux-kernel-func.m4 b/src/cf/linux-kernel-func.m4
index 78ff48294..11d071806 100644
--- a/src/cf/linux-kernel-func.m4
+++ b/src/cf/linux-kernel-func.m4
@@ -147,10 +147,17 @@ AC_CHECK_LINUX_FUNC([inode_lock],
[inode_lock(NULL);])
dnl lru_cache_add_file added to Linux 2.6.28.
+dnl removed in Linux 5.8
AC_CHECK_LINUX_FUNC([lru_cache_add_file],
[#include <linux/swap.h>],
[lru_cache_add_file(NULL);])
+dnl lru_cache_add exported in Linux 5.8
+dnl replaces lru_cache_add_file
+AC_CHECK_LINUX_FUNC([lru_cache_add],
+ [#include <linux/swap.h>],
+ [lru_cache_add(NULL);])
+
dnl Linux 5.8 replaced kernel_setsockopt with helper functions
dnl e.g. ip_sock_set_mtu_discover, ip_sock_set_recverr
AC_CHECK_LINUX_FUNC([ip_sock_set],
commit e7902252f15acfc28453c531f6fa3b29c9c91b92
Author: Cheyenne Wills <cwills@sinenomine.net>
Date: Fri Aug 21 10:37:51 2020 -0600
LINUX 5.9: Remove HAVE_UNLOCKED_IOCTL/COMPAT_IOCTL
Linux-5.9-rc1 commit 'fs: remove the HAVE_UNLOCKED_IOCTL and
HAVE_COMPAT_IOCTL defines' (4e24566a) removed the two referenced macros
from the kernel.
The support for unlocked_ioctl and compat_ioctl were introduced in
Linux 2.6.11.
Remove references to HAVE_UNLOCKED_IOCTL and HAVE_COMPAT_IOCTL using
the assumption that they were always defined.
Notes:
With this change, building against kernels 2.6.10 and older will fail.
RHEL4 (EOL in March 2017) used a 2.6.9 kernel. RHEL5 uses a 2.6.18
kernel.
In linux-2.6.33-rc1 the commit messages for "staging: comedi:
Remove check for HAVE_UNLOCKED_IOCTL" (00a1855c) and "Staging: comedi:
remove check for HAVE_COMPAT_IOCTL" (5d7ae225) both state that all new
kernels have support for unlocked_ioctl/compat_ioctl so the checks can
be removed along with removing support for older kernels.
Reviewed-on: https://gerrit.openafs.org/14300
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Tested-by: Benjamin Kaduk <kaduk@mit.edu>
(cherry picked from commit 13a49aaf0d5c43bce08135edaabb65587e1a8031)
Change-Id: I6dc5ae5b32031641f4a021a31630390a91d834fe
Reviewed-on: https://gerrit.openafs.org/14315
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
diff --git a/src/afs/LINUX/osi_ioctl.c b/src/afs/LINUX/osi_ioctl.c
index 1646a1518..9ba076a1b 100644
--- a/src/afs/LINUX/osi_ioctl.c
+++ b/src/afs/LINUX/osi_ioctl.c
@@ -25,10 +25,6 @@
#include <asm/ia32_unistd.h>
#endif
-#if defined(AFS_SPARC64_LINUX26_ENV) && defined(NEED_IOCTL32) && !defined(HAVE_COMPAT_IOCTL)
-#include <linux/ioctl32.h>
-#endif
-
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/sched.h>
@@ -37,9 +33,6 @@
#include "osi_compat.h"
extern struct proc_dir_entry *openafs_procfs;
-#if defined(NEED_IOCTL32) && !defined(HAVE_COMPAT_IOCTL)
-static int ioctl32_done;
-#endif
extern asmlinkage long
afs_syscall(long syscall, long parm1, long parm2, long parm3, long parm4);
@@ -85,12 +78,11 @@ afs_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
}
}
-#if defined(HAVE_UNLOCKED_IOCTL) || defined(HAVE_COMPAT_IOCTL)
static long afs_unlocked_ioctl(struct file *file, unsigned int cmd,
unsigned long arg) {
return afs_ioctl(FILE_INODE(file), file, cmd, arg);
}
-#endif
+
#if defined(HAVE_LINUX_STRUCT_PROC_OPS)
static struct proc_ops afs_syscall_ops = {
.proc_ioctl = afs_unlocked_ioctl,
@@ -100,16 +92,11 @@ static struct proc_ops afs_syscall_ops = {
};
#else
static struct file_operations afs_syscall_ops = {
-# ifdef HAVE_UNLOCKED_IOCTL
.unlocked_ioctl = afs_unlocked_ioctl,
-# else
- .ioctl = afs_ioctl,
-# endif
-# ifdef HAVE_COMPAT_IOCTL
.compat_ioctl = afs_unlocked_ioctl,
-# endif
};
#endif /* HAVE_LINUX_STRUCT_PROC_OPS */
+
void
osi_ioctl_init(void)
{
@@ -121,18 +108,10 @@ osi_ioctl_init(void)
entry->owner = THIS_MODULE;
#endif
-#if defined(NEED_IOCTL32) && !defined(HAVE_COMPAT_IOCTL)
- if (register_ioctl32_conversion(VIOC_SYSCALL32, NULL) == 0)
- ioctl32_done = 1;
-#endif
}
void
osi_ioctl_clean(void)
{
remove_proc_entry(PROC_SYSCALL_NAME, openafs_procfs);
-#if defined(NEED_IOCTL32) && !defined(HAVE_COMPAT_IOCTL)
- if (ioctl32_done)
- unregister_ioctl32_conversion(VIOC_SYSCALL32);
-#endif
}
diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
index 36a4f685e..ba4f1e6af 100644
--- a/src/afs/LINUX/osi_vnodeops.c
+++ b/src/afs/LINUX/osi_vnodeops.c
@@ -589,13 +589,11 @@ out1:
extern int afs_xioctl(struct inode *ip, struct file *fp, unsigned int com,
unsigned long arg);
-#if defined(HAVE_UNLOCKED_IOCTL) || defined(HAVE_COMPAT_IOCTL)
static long afs_unlocked_xioctl(struct file *fp, unsigned int com,
unsigned long arg) {
return afs_xioctl(FILE_INODE(fp), fp, com, arg);
}
-#endif
static int
@@ -891,14 +889,8 @@ struct file_operations afs_dir_fops = {
#else
.readdir = afs_linux_readdir,
#endif
-#ifdef HAVE_UNLOCKED_IOCTL
.unlocked_ioctl = afs_unlocked_xioctl,
-#else
- .ioctl = afs_xioctl,
-#endif
-#ifdef HAVE_COMPAT_IOCTL
.compat_ioctl = afs_unlocked_xioctl,
-#endif
.open = afs_linux_open,
.release = afs_linux_release,
.llseek = default_llseek,
@@ -926,14 +918,8 @@ struct file_operations afs_file_fops = {
.read = afs_linux_read,
.write = afs_linux_write,
#endif
-#ifdef HAVE_UNLOCKED_IOCTL
.unlocked_ioctl = afs_unlocked_xioctl,
-#else
- .ioctl = afs_xioctl,
-#endif
-#ifdef HAVE_COMPAT_IOCTL
.compat_ioctl = afs_unlocked_xioctl,
-#endif
.mmap = afs_linux_mmap,
.open = afs_linux_open,
.flush = afs_linux_flush,
commit 5c476b91fd2259e9c34070be8ba201dd471ad974
Author: Andrew Deason <adeason@sinenomine.net>
Date: Thu Jul 13 17:40:21 2017 -0500
afs: Change VerifyVCache2 calls to VerifyVCache
afs_VerifyVCache is a macro that (on most platforms) effectively
expands to:
if ((avc->f.states & CStatd)) {
return 0;
} else {
return afs_VerifyVCache2(...);
}
Some callers call afs_VerifyVCache2 directly, since they already check
for CStatd for other reasons. A few callers currently call
afs_VerifyVCache2, but without guaranteeing that CStatd is not set.
Specifically, in afs_getattr and afs_linux_VerifyVCache, CStatd could
be set while afs_CreateReq drops GLOCK. And in afs_linux_readdir,
CStatd could be cleared at multiple different points before the
VerifyVCache call.
This can result in afs_VerifyVCache2 acquiring a write-lock on the
vcache, even when CStatd is already set, which is an unnecessary
performance hit.
To avoid this, change these call sites to use afs_VerifyVCache instead
of calling afs_VerifyVCache2 directly, which skips the write lock when
CStatd is already set.
Reviewed-on: https://gerrit.openafs.org/12655
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
(cherry picked from commit a05d5b7503e466e18f5157006c1de2a2f7d019f7)
Change-Id: I05bdcb7f10930ed465c24a8d7e51077a027b1a4b
Reviewed-on: https://gerrit.openafs.org/14395
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Cheyenne Wills <cwills@sinenomine.net>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
index ba4f1e6af..d2a994389 100644
--- a/src/afs/LINUX/osi_vnodeops.c
+++ b/src/afs/LINUX/osi_vnodeops.c
@@ -177,7 +177,7 @@ afs_linux_VerifyVCache(struct vcache *avc, cred_t **retcred) {
code = afs_CreateReq(&treq, credp);
if (code == 0) {
- code = afs_VerifyVCache2(avc, treq);
+ code = afs_VerifyVCache(avc, treq);
afs_DestroyReq(treq);
}
@@ -419,7 +419,7 @@ afs_linux_readdir(struct file *fp, void *dirbuf, filldir_t filldir)
/* update the cache entry */
tagain:
- code = afs_convert_code(afs_VerifyVCache2(avc, treq));
+ code = afs_convert_code(afs_VerifyVCache(avc, treq));
if (code)
goto out;
diff --git a/src/afs/VNOPS/afs_vnop_attrs.c b/src/afs/VNOPS/afs_vnop_attrs.c
index a22331a5b..7166bf3c3 100644
--- a/src/afs/VNOPS/afs_vnop_attrs.c
+++ b/src/afs/VNOPS/afs_vnop_attrs.c
@@ -248,7 +248,7 @@ afs_getattr(OSI_VC_DECL(avc), struct vattr *attrs, afs_ucred_t *acred)
if (!(avc->f.states & CStatd)) {
if (!(code = afs_CreateReq(&treq, acred))) {
- code = afs_VerifyVCache2(avc, treq);
+ code = afs_VerifyVCache(avc, treq);
inited = 1;
}
} else
commit b7ddd1262117332871e7cd537aa6065b78a41bb2
Author: Andrew Deason <adeason@sinenomine.net>
Date: Thu Jun 18 21:16:09 2020 -0500
LINUX: Close cacheFp if no ->readpage in fastpath
In afs_linux_readpage_fastpath, if we discover that our disk cache fs
has no ->readpage function, we'll 'goto out', but we never close our
cacheFp. To make sure we close it, add a filp_close() call to the
'goto out' cleanup code.
Reviewed-on: https://gerrit.openafs.org/14252
Reviewed-by: Cheyenne Wills <cwills@sinenomine.net>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
(cherry picked from commit f9d20c631d7280ce00125a1208331931a6e3f31c)
Change-Id: If409c50e5515cd80f77171a90fd96e2d3fb575a8
Reviewed-on: https://gerrit.openafs.org/14421
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Michael Meffie <mmeffie@sinenomine.net>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
index d2a994389..ae406df61 100644
--- a/src/afs/LINUX/osi_vnodeops.c
+++ b/src/afs/LINUX/osi_vnodeops.c
@@ -2357,6 +2357,9 @@ afs_linux_readpage_fastpath(struct file *fp, struct page *pp, int *codep)
return 1;
out:
+ if (cacheFp != NULL) {
+ filp_close(cacheFp, NULL);
+ }
ReleaseWriteLock(&avc->lock);
ReleaseReadLock(&tdc->lock);
afs_PutDCache(tdc);
commit c55607d732a65f8acb1dfc6bf93aee0f4409cecf
Author: Andrew Deason <adeason@sinenomine.net>
Date: Mon Oct 26 12:35:32 2020 -0500
LINUX: Return errors in our d_revalidate
In our d_revalidate callback (afs_linux_dentry_revalidate), we
currently 'goto bad_dentry' when we encounter any error. This can
happen if we can't allocate memory or some other internal errors, or
if the relevant afs_lookup call fails just due to plain network
errors.
For any of these cases, we'll treat the dentry as if it's no longer
valid, so we'll return '0' and call d_invalidate() on the dentry.
However, the behavior of d_invalidate changed, as mentioned in commit
afbc199f1 (LINUX: Avoid d_invalidate() during
afs_ShakeLooseVCaches()). After a certain point in the Linux kernel,
d_invalidate() will also effectively d_drop() the given dentry,
unhashing it. This can cause getcwd() calls to fail with ENOENT for
those directories (as mentioned in afbc199f1), and can cause
bind-mount calls to fail similarly during a small window.
To avoid all of this, when we encounter an error that prevents us from
checking if the dentry is valid or not, we need to return an error,
instead of saying 'yes' or 'no'. So, change
afs_linux_dentry_revalidate to jump to the 'done' label when we
encounter such errors, and avoid calling d_drop/d_invalidate in such
cases. This also lets us remove the 'lookup_good' variable and
consolidate some of the related logic.
Important note: in older Linux kernels, d_revalidate cannot return
errors; callers just interpreted its return value as either 'valid'
(non-zero) or 'not valid' (zero). The treatment of negative values as
errors was introduced in Linux commit
bcdc5e019d9f525a9f181a7de642d3a9c27c7610, which was included in
2.6.19. This is very old, but technically still above our stated
requirements for the Linux kernel, so try to handle this case, by
jumping to 'bad_dentry' still for those old kernels. Just do this with
a version check, since no configure check can detect this (no function
signatures changed), and the only Linux versions that are a concern
are quite old.
Reviewed-on: https://gerrit.openafs.org/14417
Reviewed-by: Mark Vitale <mvitale@sinenomine.net>
Reviewed-by: Cheyenne Wills <cwills@sinenomine.net>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
(cherry picked from commit 78e5e1b0e54b31bb08b7578e86a6a2a95770d94c)
Change-Id: I9f9e2cd3a10cc8fa30a770cabd6ae9757f412ce5
Reviewed-on: https://gerrit.openafs.org/14451
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Cheyenne Wills <cwills@sinenomine.net>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
index ae406df61..c2a4278bf 100644
--- a/src/afs/LINUX/osi_vnodeops.c
+++ b/src/afs/LINUX/osi_vnodeops.c
@@ -63,6 +63,12 @@
#undef USE_FOP_ITERATE
#endif
+/* Kernels from before 2.6.19 may not be able to return errors from
+ * d_revalidate. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
+# define ERRORS_FROM_D_REVALIDATE
+#endif
+
int cachefs_noreadpage = 0;
extern struct backing_dev_info *afs_backing_dev_info;
@@ -1291,6 +1297,7 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
struct afs_fakestat_state fakestate;
int force_drop = 0;
afs_uint32 parent_dv;
+ int code = 0;
#ifdef LOOKUP_RCU
/* We don't support RCU path walking */
@@ -1321,14 +1328,13 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
if (vcp->mvstat == AFS_MVSTAT_MTPT) {
if (vcp->mvid.target_root && (vcp->f.states & CMValid)) {
int tryEvalOnly = 0;
- int code = 0;
struct vrequest *treq = NULL;
credp = crref();
code = afs_CreateReq(&treq, credp);
if (code) {
- goto bad_dentry;
+ goto error;
}
if ((strcmp(dp->d_name.name, ".directory") == 0)) {
tryEvalOnly = 1;
@@ -1338,7 +1344,10 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
else
code = afs_EvalFakeStat(&vcp, &fakestate, treq);
afs_DestroyReq(treq);
- if ((tryEvalOnly && vcp->mvstat == AFS_MVSTAT_MTPT) || code) {
+ if (code != 0) {
+ goto error;
+ }
+ if (tryEvalOnly && vcp->mvstat == AFS_MVSTAT_MTPT) {
/* a mount point, not yet replaced by its directory */
goto bad_dentry;
}
@@ -1372,22 +1381,27 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
if (parent_dv > dp->d_time || !(vcp->f.states & CStatd)) {
struct vattr *vattr = NULL;
- int code;
- int lookup_good;
if (credp == NULL) {
credp = crref();
}
code = afs_lookup(pvcp, (char *)dp->d_name.name, &tvc, credp);
code = filter_enoent(code);
+ if (code == ENOENT) {
+ /* ENOENT is not an error here. */
+ code = 0;
+ osi_Assert(tvc == NULL);
+ }
if (code) {
- /* We couldn't perform the lookup, so we're not okay. */
- lookup_good = 0;
+ /* We couldn't perform the lookup, so we don't know if the
+ * dentry is valid or not. */
+ dput(parent);
+ goto error;
+ }
- } else if (tvc == vcp) {
+ if (tvc == vcp) {
/* We got back the same vcache, so we're good. */
- lookup_good = 1;
} else if (tvc == VTOAFS(dp->d_inode)) {
/* We got back the same vcache, so we're good. This is
@@ -1398,37 +1412,29 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
* versa, so the previous case will not succeed. But this is
* still 'correct', so make sure not to mark the dentry as
* invalid; it still points to the same thing! */
- lookup_good = 1;
} else {
- /* We got back a different file, so we're definitely not
- * okay. */
- lookup_good = 0;
- }
-
- if (!lookup_good) {
+ /*
+ * We got back a different file, so we know this dentry is
+ * _not_ okay. Force it to be unhashed, since the given name
+ * doesn't point to this file anymore.
+ */
dput(parent);
- /* Force unhash; the name doesn't point to this file
- * anymore. */
force_drop = 1;
- if (code && code != ENOENT) {
- /* ...except if we couldn't perform the actual lookup,
- * we don't know if the name points to this file or not. */
- force_drop = 0;
- }
goto bad_dentry;
}
code = afs_CreateAttr(&vattr);
if (code) {
dput(parent);
- goto bad_dentry;
+ goto error;
}
if (afs_getattr(vcp, vattr, credp)) {
dput(parent);
afs_DestroyAttr(vattr);
- goto bad_dentry;
+ code = EIO;
+ goto error;
}
vattr2inode(AFSTOV(vcp), vattr);
@@ -1460,10 +1466,12 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
}
good_dentry:
+ code = 0;
valid = 1;
goto done;
bad_dentry:
+ code = 0;
valid = 0;
#ifndef D_INVALIDATE_IS_VOID
/* When (v3.18) d_invalidate was converted to void, it also started
@@ -1489,6 +1497,18 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
if (credp)
crfree(credp);
+#ifdef ERRORS_FROM_D_REVALIDATE
+ if (code != 0) {
+ /*
+ * If code is nonzero, we don't know whether this dentry is valid or
+ * not; we couldn't successfully perform the relevant lookup in order
+ * to tell. So we must not return 'valid' (1) or 'not valid' (0); we
+ * need to return an error (e.g. -EIO).
+ */
+ return -code;
+ }
+#endif
+
#ifndef D_INVALIDATE_IS_VOID
if (!valid) {
/*
@@ -1505,6 +1525,17 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
#endif
return valid;
+ error:
+ if (code <= 0) {
+ code = EIO;
+ }
+#ifdef ERRORS_FROM_D_REVALIDATE
+ valid = 0;
+ goto done;
+#else
+ /* We can't return an error, so default to saying the dentry is invalid. */
+ goto bad_dentry;
+#endif
}
static void
commit aaa7043a154d35838e65bc28473355c452339bcc
Author: Andrew Deason <adeason@sinenomine.net>
Date: Thu Jan 28 16:59:47 2021 -0600
LINUX: Fix includes for fatal_signal_pending test
Commit 8b6ae289 (LINUX: Avoid lookup ENOENT on fatal signals) added a
configure test for fatal_signal_pending(). However, this check fails
incorrectly ever since Linux 4.11, because fatal_signal_pending() was moved
from linux/sched.h to linux/sched/signal.h in Linux commit 2a1f062a
(sched/headers: Move signal wakeup [...]). Fix this by including
linux/sched/signal.h if we have it during the configure test.
A false negative on this configure test doesn't break the build, but
it disables one of our safeguards preventing incorrect negative
dentries at runtime. The function fatal_signal_pending() hasn't
changed in quite some time (except for what header it lives in); it
was introduced in Linux 2.6.25 via Linux commit f776d12d (Add
fatal_signal_pending). So to try to avoid this mistake again in the
future, make it so a missing fatal_signal_pending() breaks the build
if we're on Linux 2.6.25+.
Reviewed-on: https://gerrit.openafs.org/14508
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
(cherry picked from commit 0c1465e4f3310daa54f1e799f76237604222666d)
Change-Id: I1334c060f8ab5733461ebf7c191dffa7be830021
Reviewed-on: https://gerrit.openafs.org/14509
Reviewed-by: Cheyenne Wills <cwills@sinenomine.net>
Reviewed-by: Michael Meffie <mmeffie@sinenomine.net>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
index 593086d1e..1564f8986 100644
--- a/src/afs/LINUX/osi_vnodeops.c
+++ b/src/afs/LINUX/osi_vnodeops.c
@@ -1212,6 +1212,8 @@ filter_enoent(int code)
if (code == ENOENT && fatal_signal_pending(current)) {
return EINTR;
}
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
+# error fatal_signal_pending not available, but it should be
#endif
return code;
}
diff --git a/src/cf/linux-kernel-func.m4 b/src/cf/linux-kernel-func.m4
index 10b7c97dd..4651b5b1a 100644
--- a/src/cf/linux-kernel-func.m4
+++ b/src/cf/linux-kernel-func.m4
@@ -42,8 +42,13 @@ AC_CHECK_LINUX_FUNC([d_make_root],
AC_CHECK_LINUX_FUNC([do_sync_read],
[#include <linux/fs.h>],
[do_sync_read(NULL, NULL, 0, NULL);])
+dnl - fatal_signal_pending introduced in 2.6.25
+dnl - moved from linux/sched.h to linux/sched/signal.h in 4.11
AC_CHECK_LINUX_FUNC([fatal_signal_pending],
- [#include <linux/sched.h>],
+ [#include <linux/sched.h>
+ #ifdef HAVE_LINUX_SCHED_SIGNAL_H
+ # include <linux/sched/signal.h>
+ #endif],
[fatal_signal_pending(NULL);])
AC_CHECK_LINUX_FUNC([file_dentry],
[#include <linux/fs.h>],
commit 4ad1057ab8fd206c9fa8d5e3bdde4f1a8417afdb
Author: Cheyenne Wills <cwills@sinenomine.net>
Date: Fri Jan 29 11:32:36 2021 -0700
Linux: Refactor test for 32bit compat
Refactor the preprocessor checks for determining the method to test for
32bit compatibility (64bit kernel performing work for a 32bit task) into
a common inline function, 'afs_in_compat_syscall' that is defined in
LINUX/osi_machdep.h. Update osi_ioctl.c and afs_syscall.c to use
afs_in_compat_syscall.
Add include afs/sysincludes into osi_machdep.h to ensure linux/compat.h
is pulled for the functions called in afs_in_compat_syscall.
Reviewed-on: https://gerrit.openafs.org/14500
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
(cherry picked from commit 32cc6b0796495e596262d84c428172a511f757c4)
Change-Id: I746e5777737d49381c4a74627b79d2a61cbd4f8e
Reviewed-on: https://gerrit.openafs.org/14510
Reviewed-by: Cheyenne Wills <cwills@sinenomine.net>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
diff --git a/src/afs/LINUX/osi_ioctl.c b/src/afs/LINUX/osi_ioctl.c
index 9ba076a1b..7d355674d 100644
--- a/src/afs/LINUX/osi_ioctl.c
+++ b/src/afs/LINUX/osi_ioctl.c
@@ -43,21 +43,13 @@ afs_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
{
struct afsprocdata sysargs;
-#ifdef NEED_IOCTL32
- struct afsprocdata32 sysargs32;
-#endif
if (cmd != VIOC_SYSCALL && cmd != VIOC_SYSCALL32) return -EINVAL;
#ifdef NEED_IOCTL32
-# if defined(AFS_S390X_LINUX26_ENV)
- if (test_thread_flag(TIF_31BIT))
-# elif defined(AFS_AMD64_LINUX20_ENV)
- if (test_thread_flag(TIF_IA32))
-# else
- if (test_thread_flag(TIF_32BIT))
-# endif /* AFS_S390X_LINUX26_ENV */
- {
+ if (afs_in_compat_syscall()) {
+ struct afsprocdata32 sysargs32;
+
if (copy_from_user(&sysargs32, (void *)arg,
sizeof(struct afsprocdata32)))
return -EFAULT;
diff --git a/src/afs/LINUX/osi_machdep.h b/src/afs/LINUX/osi_machdep.h
index 784829627..9ecdaf0bf 100644
--- a/src/afs/LINUX/osi_machdep.h
+++ b/src/afs/LINUX/osi_machdep.h
@@ -76,6 +76,8 @@
#include "h/cred.h"
#endif
+#include "afs/sysincludes.h"
+
#if !defined(HAVE_LINUX_TIME_T)
typedef time64_t time_t;
#endif
@@ -157,6 +159,44 @@ static inline long copyinstr(char *from, char *to, int count, int *length) {
}
#define copyout(F, T, C) (copy_to_user ((char*)(T), (char*)(F), (C)) > 0 ? EFAULT : 0)
+/*
+ * Test to see for 64/32bit compatibility mode
+ * Return non-zero if in a 64bit kernel and handing a 32bit syscall
+ */
+#if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV)
+static inline int
+afs_in_compat_syscall(void)
+{
+# if defined(AFS_SPARC64_LINUX26_ENV)
+ return test_thread_flag(TIF_32BIT);
+# elif defined(AFS_SPARC64_LINUX24_ENV)
+ return (current->thread.flags & SPARC_FLAG_32BIT) != 0;
+# elif defined(AFS_SPARC64_LINUX20_ENV)
+ return (current->tss.flags & SPARC_FLAG_32BIT) != 0;
+# elif defined(AFS_AMD64_LINUX26_ENV)
+ return test_thread_flag(TIF_IA32);
+# elif defined(AFS_AMD64_LINUX20_ENV)
+ return (current->thread.flags & THREAD_IA32) != 0;
+# elif defined(AFS_PPC64_LINUX26_ENV)
+# if defined(STRUCT_TASK_STRUCT_HAS_THREAD_INFO)
+ return (current->thread_info->flags & _TIF_32BIT) != 0;
+# else
+ return (task_thread_info(current)->flags & _TIF_32BIT) != 0;
+# endif
+# elif defined(AFS_PPC64_LINUX20_ENV)
+ return (current->thread.flags & PPC_FLAG_32BIT) != 0;
+# elif defined(AFS_S390X_LINUX26_ENV)
+ return test_thread_flag(TIF_31BIT);
+# elif defined(AFS_S390X_LINUX20_ENV)
+ return (current->thread.flags & S390_FLAG_31BIT) != 0;
+# elif defined(AFS_ARM64_LINUX26_ENV)
+ return is_compat_task();
+# else
+# error afs_in_compat_syscall not done for this linux
+# endif
+}
+#endif /* AFS_LINUX_64BIT_KERNEL */
+
/* kernel print statements */
#define printf(args...) printk(args)
#define uprintf(args...) printk(args)
diff --git a/src/afs/afs_syscall.c b/src/afs/afs_syscall.c
index ce6afdf9a..9414f38b8 100644
--- a/src/afs/afs_syscall.c
+++ b/src/afs/afs_syscall.c
@@ -114,40 +114,9 @@ copyin_afs_ioctl(caddr_t cmarg, struct afs_ioctl *dst)
#endif /* defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64) */
#if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV)
- struct afs_ioctl32 dst32;
-
-#ifdef AFS_SPARC64_LINUX26_ENV
- if (test_thread_flag(TIF_32BIT))
-#elif defined(AFS_SPARC64_LINUX24_ENV)
- if (current->thread.flags & SPARC_FLAG_32BIT)
-#elif defined(AFS_SPARC64_LINUX20_ENV)
- if (current->tss.flags & SPARC_FLAG_32BIT)
-
-#elif defined(AFS_AMD64_LINUX26_ENV)
- if (test_thread_flag(TIF_IA32))
-#elif defined(AFS_AMD64_LINUX20_ENV)
- if (current->thread.flags & THREAD_IA32)
-
-#elif defined(AFS_PPC64_LINUX26_ENV)
-#if defined(STRUCT_TASK_STRUCT_HAS_THREAD_INFO)
- if (current->thread_info->flags & _TIF_32BIT)
-#else
- if (task_thread_info(current)->flags & _TIF_32BIT)
-#endif
-#elif defined(AFS_PPC64_LINUX20_ENV)
- if (current->thread.flags & PPC_FLAG_32BIT)
-
-#elif defined(AFS_S390X_LINUX26_ENV)
- if (test_thread_flag(TIF_31BIT))
-#elif defined(AFS_S390X_LINUX20_ENV)
- if (current->thread.flags & S390_FLAG_31BIT)
-#elif defined(AFS_ARM64_LINUX26_ENV)
- if (is_compat_task())
+ if (afs_in_compat_syscall()) {
+ struct afs_ioctl32 dst32;
-#else
-#error pioctl32 not done for this linux
-#endif
- {
AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
if (!code)
afs_ioctl32_to_afs_ioctl(&dst32, dst);
@@ -391,40 +360,9 @@ copyin_iparam(caddr_t cmarg, struct iparam *dst)
#endif /* AFS_SUN5_64BIT_ENV */
#if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV)
- struct iparam32 dst32;
-
-#ifdef AFS_SPARC64_LINUX26_ENV
- if (test_thread_flag(TIF_32BIT))
-#elif defined(AFS_SPARC64_LINUX24_ENV)
- if (current->thread.flags & SPARC_FLAG_32BIT)
-#elif defined(AFS_SPARC64_LINUX20_ENV)
- if (current->tss.flags & SPARC_FLAG_32BIT)
-
-#elif defined(AFS_AMD64_LINUX26_ENV)
- if (test_thread_flag(TIF_IA32))
-#elif defined(AFS_AMD64_LINUX20_ENV)
- if (current->thread.flags & THREAD_IA32)
-
-#elif defined(AFS_PPC64_LINUX26_ENV)
-#if defined(STRUCT_TASK_STRUCT_HAS_THREAD_INFO)
- if (current->thread_info->flags & _TIF_32BIT)
-#else
- if (task_thread_info(current)->flags & _TIF_32BIT)
-#endif
-#elif defined(AFS_PPC64_LINUX20_ENV)
- if (current->thread.flags & PPC_FLAG_32BIT)
-
-#elif defined(AFS_S390X_LINUX26_ENV)
- if (test_thread_flag(TIF_31BIT))
-#elif defined(AFS_S390X_LINUX20_ENV)
- if (current->thread.flags & S390_FLAG_31BIT)
-#elif defined(AFS_ARM64_LINUX26_ENV)
- if (is_compat_task())
+ if (afs_in_compat_syscall()) {
+ struct iparam32 dst32;
-#else
-#error iparam32 not done for this linux platform
-#endif
- {
AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
if (!code)
iparam32_to_iparam(&dst32, dst);
commit ee53dd3bc087a05e22fc4111297a51ddb30013f0
Author: Cheyenne Wills <cwills@sinenomine.net>
Date: Fri Jan 22 07:57:55 2021 -0700
Linux 5.11: Test 32bit compat with in_compat_syscall
Linux 5.11 removed the TIF_IA32 thread flag with commit:
x86: Reclaim TIF_IA32 and TIF_X32 (8d71d2bf6efec)
The flag TIF_IA32 was being used by openafs to determine if the task was
handling a syscall request from a 32 bit process. Building against a
Linux 5.11 kernel results in a build failure as TIF_IA32 is undefined.
The function 'in_compat_syscall' was introduced in Linux 4.6 as
the preferred method to determine if a syscall needed to handle a
compatible call (e.g. 32bit application).
To resolve the build problem, use 'in_compat_syscall' if present (Linux
4.6 and later) to determine if the syscall needs to handle a
compatibility mode call.
Add autoconf check for in_compat_syscall.
Notes about in_compat_syscall:
In Linux 4.6 'in_compat_syscall' was defined for all architectures with
a generic return of 'is_compat_task', but allows architecture specific
overriding implementations (x86 and sparc).
At 4.6 (and later), the function 'is_compat_task' is defined only for
the following architectures to return:
Arch Returns
======= ==============================
arm64 test_thread_flag(TIF_32BIT);
mips test_thread_flag(TIF_32BIT_ADDR)
parisc test_ti_thread_flag(task_thread_info(t), TIF_32BIT)
powerpc is_32bit_task()
s390 test_thread_flag(TIF_31BIT)
sparc test_thread_flag(TIF_32BIT)
If the Linux kernel is not built with compat mode, is_compat_task and
in_compat_syscall is set to always return 0
Linux commit that introduced in_compat_syscall:
compat: add in_compat_syscall to ask whether we're in a compat syscall
(5180e3e24fd3e8e7)
Reviewed-on: https://gerrit.openafs.org/14499
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
(cherry picked from commit 78ef922612bef5f5fd6904896e84b9d2ea802404)
Change-Id: I4eca62f19ae58fd830915feff5098cec2825f099
Reviewed-on: https://gerrit.openafs.org/14511
Reviewed-by: Cheyenne Wills <cwills@sinenomine.net>
Tested-by: Cheyenne Wills <cwills@sinenomine.net>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
diff --git a/src/afs/LINUX/osi_machdep.h b/src/afs/LINUX/osi_machdep.h
index 9ecdaf0bf..066c1885f 100644
--- a/src/afs/LINUX/osi_machdep.h
+++ b/src/afs/LINUX/osi_machdep.h
@@ -167,7 +167,9 @@ static inline long copyinstr(char *from, char *to, int count, int *length) {
static inline int
afs_in_compat_syscall(void)
{
-# if defined(AFS_SPARC64_LINUX26_ENV)
+# if defined(HAVE_LINUX_IN_COMPAT_SYSCALL)
+ return in_compat_syscall();
+# elif defined(AFS_SPARC64_LINUX26_ENV)
return test_thread_flag(TIF_32BIT);
# elif defined(AFS_SPARC64_LINUX24_ENV)
return (current->thread.flags & SPARC_FLAG_32BIT) != 0;
diff --git a/src/cf/linux-kernel-func.m4 b/src/cf/linux-kernel-func.m4
index 4651b5b1a..0ca3e4463 100644
--- a/src/cf/linux-kernel-func.m4
+++ b/src/cf/linux-kernel-func.m4
@@ -160,6 +160,12 @@ AC_CHECK_LINUX_FUNC([lru_cache_add_file],
[#include <linux/swap.h>],
[lru_cache_add_file(NULL);])
+dnl Linux 4.6 introduced in_compat_syscall as replacement for is_compat_task
+dnl for certain platforms.
+AC_CHECK_LINUX_FUNC([in_compat_syscall],
+ [#include <linux/compat.h>],
+ [in_compat_syscall();])
+
dnl lru_cache_add exported in Linux 5.8
dnl replaces lru_cache_add_file
AC_CHECK_LINUX_FUNC([lru_cache_add],
From cdec210405afb47ee338bfde9280710b64d7abc6 Mon Sep 17 00:00:00 2001
From: Andrew Deason <adeason@sinenomine.net>
Date: Tue, 23 Jul 2019 13:50:31 -0500
Subject: [PATCH] LINUX: Introduce afs_d_path
Move our preprocessor logic around d_path into an osi_compat.h
wrapper, called afs_d_path. This just makes it a little easier to use
d_path, and moves a tiny bit of #ifdef cruft away from real code.
Reviewed-on: https://gerrit.openafs.org/13721
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
(cherry picked from commit 4c4fb6e36634e5663c8be25acd4a1ac872e4738c)
Change-Id: I08763c71006e4ac6f2bf88d8ac71941fc44e6ab8
Reviewed-on: https://gerrit.openafs.org/14563
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Cheyenne Wills <cwills@sinenomine.net>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
---
diff --git a/src/afs/LINUX/osi_compat.h b/src/afs/LINUX/osi_compat.h
index 620b373..a1e7f21 100644
--- a/src/afs/LINUX/osi_compat.h
+++ b/src/afs/LINUX/osi_compat.h
@@ -737,4 +737,15 @@
#endif
}
+static inline char*
+afs_d_path(struct dentry *dp, struct vfsmount *mnt, char *buf, int buflen)
+{
+#ifdef D_PATH_TAKES_STRUCT_PATH
+ afs_linux_path_t p = { .mnt = mnt, .dentry = dp };
+ return d_path(&p, buf, buflen);
+#else
+ return d_path(dp, mnt, buf, buflen);
+#endif
+}
+
#endif /* AFS_LINUX_OSI_COMPAT_H */
diff --git a/src/afs/LINUX/osi_misc.c b/src/afs/LINUX/osi_misc.c
index 0e9336d..aa5d5fc 100644
--- a/src/afs/LINUX/osi_misc.c
+++ b/src/afs/LINUX/osi_misc.c
@@ -138,13 +138,7 @@
return -PTR_ERR(name);
code = osi_lookupname_internal(name, followlink, &mnt, &dp);
if (!code) {
-#if defined(D_PATH_TAKES_STRUCT_PATH)
- afs_linux_path_t p = { .mnt = mnt, .dentry = dp };
- path = d_path(&p, buf, buflen);
-#else
- path = d_path(dp, mnt, buf, buflen);
-#endif
-
+ path = afs_d_path(dp, mnt, buf, buflen);
if (IS_ERR(path)) {
code = -PTR_ERR(path);
} else {
From 5a5d358b02b88d6d2c7a27a75149e35b1de7db38 Mon Sep 17 00:00:00 2001
From: Cheyenne Wills <cwills@sinenomine.net>
Date: Mon, 08 Mar 2021 09:22:04 -0700
Subject: [PATCH] Linux: Create wrapper for setattr_prepare
Move call to setattr_prepare/inode_change_ok into an osi_compat.h
wrapper called 'afs_setattr_prepare'. This moves some of the #if logic
out of the mainline code.
Reviewed-on: https://gerrit.openafs.org/14548
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
(cherry picked from commit 12ae2beeeb172cebdfa24d5ea149f73fd85541f8)
Change-Id: I1c7806893daf2404a8b3ac1b5c88ca04e6409226
Reviewed-on: https://gerrit.openafs.org/14564
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Cheyenne Wills <cwills@sinenomine.net>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
---
diff --git a/src/afs/LINUX/osi_compat.h b/src/afs/LINUX/osi_compat.h
index a1e7f21..3ac4d79 100644
--- a/src/afs/LINUX/osi_compat.h
+++ b/src/afs/LINUX/osi_compat.h
@@ -748,4 +748,14 @@
#endif
}
+static inline int
+afs_setattr_prepare(struct dentry *dp, struct iattr *newattrs)
+{
+#if defined(HAVE_LINUX_SETATTR_PREPARE)
+ return setattr_prepare(dp, newattrs);
+#else
+ return inode_change_ok(dp->d_inode, newattrs);
+#endif
+}
+
#endif /* AFS_LINUX_OSI_COMPAT_H */
diff --git a/src/afs/LINUX/osi_file.c b/src/afs/LINUX/osi_file.c
index 0afb875..03777f5 100644
--- a/src/afs/LINUX/osi_file.c
+++ b/src/afs/LINUX/osi_file.c
@@ -230,11 +230,7 @@
AFS_CURRENT_TIME(&newattrs.ia_ctime);
/* avoid notify_change() since it wants to update dentry->d_parent */
-#ifdef HAVE_LINUX_SETATTR_PREPARE
- code = setattr_prepare(file_dentry(afile->filp), &newattrs);
-#else
- code = inode_change_ok(inode, &newattrs);
-#endif
+ code = afs_setattr_prepare(file_dentry(afile->filp), &newattrs);
if (!code)
code = afs_inode_setattr(afile, &newattrs);
if (!code)
From c747b15dd2877e6d17e3e6b940ae78c1e1ccd3ea Mon Sep 17 00:00:00 2001
From: Cheyenne Wills <cwills@sinenomine.net>
Date: Fri, 05 Mar 2021 16:31:03 -0700
Subject: [PATCH] Linux 5.12: Add user_namespace param to inode ops
The Linux commits:
"fs: make helpers idmap mount aware" (549c72977) and
"attr: handle idmapped mounts" (2f221d6f7) that were merged into
Linux-5.12-rc1 cause a build failure when creating the kernel module.
Several functions within the inode_operations structure had their
signature updated to include a user_namespace parameter. This allows
a filesystem to support idmapped mounts.
OpenAFS only implements some of the changed functions.
LINUX/vnodeops function inode_operation
===================== ===============
afs_notify_change setattr
afs_linux_getattr getattr
afs_linux_create create
afs_linux_symlink symlink
afs_linux_mkdir mkdir
afs_linux_rename rename
afs_linux_permission permission
Update the autoconf tests to determine if the Linux kernel requires
the user_namespace structure for inode_operations functions. If so,
define a generic "IOP_TAKES_USER_NAMESPACE" macro.
Update the above vnodeops functions to accept a 'struct user_namespace'
parameter.
When using the 'setattr_prepare' function a user namespace must be
now provided. In order to provide compatibility as a non-idmapped mount
filesystem the initial user namespace can be used. With OpenAFS, the
initial user namespace obtained at kernel module load time is stored in
a global variable 'afs_ns'.
Update the call to setattr_prepare to pass the user namespace pointed
to by the 'afs_ns' global variable.
Update calls to setattr to pass the user namespace pointed to by
the 'afs_ns' global variable.
Notes:
The changes introduced with Linux 5.12 allow a filesystem to support
idmapped mounts if desired. This commit does not implement support for
idmapped mounts, but will continue to use the same initial user
namespace as prior to Linux 5.12.
With Linux 5.12 the following autoconf checks fail:
HAVE_LINUX_INODE_OPERATIONS_RENAME_TAKES_FLAGS
HAVE_LINUX_SETATTR_PREPARE
IOP_CREATE_TAKES_BOOL
IOP_GETATTR_TAKES_PATH_STRUCT
IOP_MKDIR_TAKES_UMODE_T
The new macro 'IOP_TAKES_USER_NAMESPACE' covers the cases where these
macros where used.
Reviewed-on: https://gerrit.openafs.org/14549
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
(cherry picked from commit 1bd68506be3243c5670aaf53798b2e4e715d4c8b)
Change-Id: I8cd54042da4e0295f3cf8417c84138bb0458f881
Reviewed-on: https://gerrit.openafs.org/14565
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Cheyenne Wills <cwills@sinenomine.net>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
---
diff --git a/src/afs/LINUX/osi_compat.h b/src/afs/LINUX/osi_compat.h
index 3ac4d79..726b655 100644
--- a/src/afs/LINUX/osi_compat.h
+++ b/src/afs/LINUX/osi_compat.h
@@ -524,7 +524,9 @@
int code = 0;
struct inode *inode = OSIFILE_INODE(afile);
-#if !defined(HAVE_LINUX_INODE_SETATTR)
+#if defined(IOP_TAKES_USER_NAMESPACE)
+ code = inode->i_op->setattr(afs_ns, afile->filp->f_dentry, newattrs);
+#elif !defined(HAVE_LINUX_INODE_SETATTR)
code = inode->i_op->setattr(afile->filp->f_dentry, newattrs);
#elif defined(INODE_SETATTR_NOT_VOID)
if (inode->i_op && inode->i_op->setattr)
@@ -751,7 +753,9 @@
static inline int
afs_setattr_prepare(struct dentry *dp, struct iattr *newattrs)
{
-#if defined(HAVE_LINUX_SETATTR_PREPARE)
+#if defined(IOP_TAKES_USER_NAMESPACE)
+ return setattr_prepare(afs_ns, dp, newattrs);
+#elif defined(HAVE_LINUX_SETATTR_PREPARE)
return setattr_prepare(dp, newattrs);
#else
return inode_change_ok(dp->d_inode, newattrs);
diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
index 1564f89..f4bedae 100644
--- a/src/afs/LINUX/osi_vnodeops.c
+++ b/src/afs/LINUX/osi_vnodeops.c
@@ -1124,8 +1124,13 @@
* Linux version of setattr call. What to change is in the iattr struct.
* We need to set bits in both the Linux inode as well as the vcache.
*/
+#if defined(IOP_TAKES_USER_NAMESPACE)
+static int
+afs_notify_change(struct user_namespace *mnt_userns, struct dentry *dp, struct iattr *iattrp)
+#else
static int
afs_notify_change(struct dentry *dp, struct iattr *iattrp)
+#endif
{
struct vattr *vattr = NULL;
cred_t *credp = crref();
@@ -1153,7 +1158,18 @@
return afs_convert_code(code);
}
-#if defined(IOP_GETATTR_TAKES_PATH_STRUCT)
+#if defined(IOP_TAKES_USER_NAMESPACE)
+static int
+afs_linux_getattr(struct user_namespace *mnt_userns, const struct path *path, struct kstat *stat,
+ u32 request_mask, unsigned int sync_mode)
+{
+ int err = afs_linux_revalidate(path->dentry);
+ if (!err) {
+ generic_fillattr(afs_ns, path->dentry->d_inode, stat);
+ }
+ return err;
+}
+#elif defined(IOP_GETATTR_TAKES_PATH_STRUCT)
static int
afs_linux_getattr(const struct path *path, struct kstat *stat, u32 request_mask, unsigned int sync_mode)
{
@@ -1622,17 +1638,25 @@
*
* name is in kernel space at this point.
*/
+
+#if defined(IOP_TAKES_USER_NAMESPACE)
static int
-#if defined(IOP_CREATE_TAKES_BOOL)
+afs_linux_create(struct user_namespace *mnt_userns, struct inode *dip,
+ struct dentry *dp, umode_t mode, bool excl)
+#elif defined(IOP_CREATE_TAKES_BOOL)
+static int
afs_linux_create(struct inode *dip, struct dentry *dp, umode_t mode,
bool excl)
#elif defined(IOP_CREATE_TAKES_UMODE_T)
+static int
afs_linux_create(struct inode *dip, struct dentry *dp, umode_t mode,
struct nameidata *nd)
#elif defined(IOP_CREATE_TAKES_NAMEIDATA)
+static int
afs_linux_create(struct inode *dip, struct dentry *dp, int mode,
struct nameidata *nd)
#else
+static int
afs_linux_create(struct inode *dip, struct dentry *dp, int mode)
#endif
{
@@ -1907,8 +1931,14 @@
}
+#if defined(IOP_TAKES_USER_NAMESPACE)
+static int
+afs_linux_symlink(struct user_namespace *mnt_userns, struct inode *dip,
+ struct dentry *dp, const char *target)
+#else
static int
afs_linux_symlink(struct inode *dip, struct dentry *dp, const char *target)
+#endif
{
int code;
cred_t *credp = crref();
@@ -1936,10 +1966,15 @@
return afs_convert_code(code);
}
+#if defined(IOP_TAKES_USER_NAMESPACE)
static int
-#if defined(IOP_MKDIR_TAKES_UMODE_T)
+afs_linux_mkdir(struct user_namespace *mnt_userns, struct inode *dip,
+ struct dentry *dp, umode_t mode)
+#elif defined(IOP_MKDIR_TAKES_UMODE_T)
+static int
afs_linux_mkdir(struct inode *dip, struct dentry *dp, umode_t mode)
#else
+static int
afs_linux_mkdir(struct inode *dip, struct dentry *dp, int mode)
#endif
{
@@ -2011,13 +2046,22 @@
}
+#if defined(IOP_TAKES_USER_NAMESPACE)
+static int
+afs_linux_rename(struct user_namespace *mnt_userns,
+ struct inode *oldip, struct dentry *olddp,
+ struct inode *newip, struct dentry *newdp,
+ unsigned int flags)
+#elif defined(HAVE_LINUX_INODE_OPERATIONS_RENAME_TAKES_FLAGS)
static int
afs_linux_rename(struct inode *oldip, struct dentry *olddp,
- struct inode *newip, struct dentry *newdp
-#ifdef HAVE_LINUX_INODE_OPERATIONS_RENAME_TAKES_FLAGS
- , unsigned int flags
+ struct inode *newip, struct dentry *newdp,
+ unsigned int flags)
+#else
+static int
+afs_linux_rename(struct inode *oldip, struct dentry *olddp,
+ struct inode *newip, struct dentry *newdp)
#endif
- )
{
int code;
cred_t *credp = crref();
@@ -2025,7 +2069,8 @@
const char *newname = newdp->d_name.name;
struct dentry *rehash = NULL;
-#ifdef HAVE_LINUX_INODE_OPERATIONS_RENAME_TAKES_FLAGS
+#if defined(HAVE_LINUX_INODE_OPERATIONS_RENAME_TAKES_FLAGS) || \
+ defined(IOP_TAKES_USER_NAMESPACE)
if (flags)
return -EINVAL; /* no support for new flags yet */
#endif
@@ -3050,12 +3095,18 @@
/* afs_linux_permission
* Check access rights - returns error if can't check or permission denied.
*/
+
+#if defined(IOP_TAKES_USER_NAMESPACE)
static int
-#if defined(IOP_PERMISSION_TAKES_FLAGS)
+afs_linux_permission(struct user_namespace *mnt_userns, struct inode *ip, int mode)
+#elif defined(IOP_PERMISSION_TAKES_FLAGS)
+static int
afs_linux_permission(struct inode *ip, int mode, unsigned int flags)
#elif defined(IOP_PERMISSION_TAKES_NAMEIDATA)
+static int
afs_linux_permission(struct inode *ip, int mode, struct nameidata *nd)
#else
+static int
afs_linux_permission(struct inode *ip, int mode)
#endif
{
diff --git a/src/cf/linux-kernel-sig.m4 b/src/cf/linux-kernel-sig.m4
index 3d3aff9..e0cc9a2 100644
--- a/src/cf/linux-kernel-sig.m4
+++ b/src/cf/linux-kernel-sig.m4
@@ -14,4 +14,18 @@
[struct inode *oinode, struct dentry *odentry,
struct inode *ninode, struct dentry *ndentry,
unsigned int flags])
-])
+dnl Linux 5.12 added the user_namespace parameter to the several
+dnl inode operations functions.
+dnl Perform a generic test using the inode_op create to test for this change.
+AC_CHECK_LINUX_OPERATION([inode_operations], [create], [user_namespace],
+ [#include <linux/fs.h>],
+ [int],
+ [struct user_namespace *mnt_userns,
+ struct inode *inode, struct dentry *dentry,
+ umode_t umode, bool flag])
+dnl if HAVE_LINUX_INODE_OPERATIONS_CREATE_USER_NAMESPACE, create a more generic
+dnl define.
+AS_IF([test AS_VAR_GET([ac_cv_linux_operation_inode_operations_create_user_namespace]) = yes],
+ [AC_DEFINE([IOP_TAKES_USER_NAMESPACE], 1,
+ [define if inodeops require struct user_namespace])])
+])
\ No newline at end of file