summaryrefslogtreecommitdiff
path: root/net-fs/openafs/files/0018-openafs-1.8.15-linux-6.17.patch
blob: 3e224856a51c4c9453e675ed5a359b21345f05b8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
From c87b1e31f62b827e2f421a57362923d78afc2279 Mon Sep 17 00:00:00 2001
From: Cheyenne Wills <cwills@sinenomine.net>
Date: Tue, 10 Mar 2026 14:24:54 -0600
Subject: [PATCH] Linux: Use set_default_d_op() to set dentry ops

The Linux 6.17 commit:
    'new helper: set_default_d_op()' (05fb0e666495c)
replaced the way that the default dentry_operations is set on a
super_block. The s_d_op member was renamed to __s_d_op and a new helper
function set_default_d_op() is now used to set the default
dentry_operations.

The OpenAFS commit 'linux: 2.6.38: New d_op handling' (08bb83d950) added
an autoconf test for using the s_d_op member in the super_block struct.
With the above Linux commit, the test for STRUCT_SUPER_BLOCK_HAS_S_D_OP
fails, and the __s_d_op member in the super_block is not set during
afs_fill_super(), but instead dp->d_op is set during various vfs
operations. Doing so sets the dentry ops for the dentry, but does not
set the flag DCACHE_OP_REVALIDATE on the dentry, and so Linux never
calls our d_revalidate function, causing dentries to not get properly
revalidated.

To fix this, add a new autoconf test for set_default_d_op(), and use
that function when available. Add a comment for the autoconf test for
the super_block member s_d_op to note the change.  Add an additional
build time check to ensure that we don't accidentally revert to the
pre-2.6.38 behavior after Linux 2.6.38

In afs_fill_super(), use set_default_d_op() to initialize the
super_block with the afs_dentry_operations.

The dentry->d_op member only needs to be updated when set_default_d_op()
is not available and the super_block does not have the s_d_op member.

Note: This commit fixes a reported problem with stale dentries that was
discovered on a Linux 6.17 system.

Reviewed-on: https://gerrit.openafs.org/16700
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Tested-by: Michael Meffie <mmeffie@sinenomine.net>
Reviewed-by: Michael Meffie <mmeffie@sinenomine.net>
(cherry picked from commit a99b2ff4c04a9b1a4ba3ab5fac1b37bfd5d43568)

Change-Id: Ic454c52ca88c82a9efa62a486ec05300a95c6cb0
(cherry picked from commit 6d0a2107fcab28fc4ba64d365133d171b75bd3dc)
---
 src/afs/LINUX/osi_vfsops.c    |  8 ++++++--
 src/afs/LINUX/osi_vnodeops.c  |  6 +++---
 src/cf/linux-kernel-func.m4   | 10 ++++++++++
 src/cf/linux-kernel-struct.m4 |  4 ++++
 4 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/src/afs/LINUX/osi_vfsops.c b/src/afs/LINUX/osi_vfsops.c
index 18506474ee48..f1e59074760c 100644
--- a/src/afs/LINUX/osi_vfsops.c
+++ b/src/afs/LINUX/osi_vfsops.c
@@ -117,8 +117,12 @@ afs_fill_super(struct super_block *sb, void *data, int silent)
     sb->s_magic = AFS_VFSMAGIC;
     sb->s_op = &afs_sops;	/* Super block (vfs) ops */
 
-#if defined(STRUCT_SUPER_BLOCK_HAS_S_D_OP)
+#if defined(HAVE_LINUX_SET_DEFAULT_D_OP)
+    set_default_d_op(sb, &afs_dentry_operations);
+#elif defined(STRUCT_SUPER_BLOCK_HAS_S_D_OP)
     sb->s_d_op = &afs_dentry_operations;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
+# error "Missing method to set the super_block's dentry operations member"
 #endif
 #if defined(HAVE_LINUX_SUPER_SETUP_BDI)
     code = super_setup_bdi(sb);
@@ -221,7 +225,7 @@ afs_root(struct super_block *afsp)
 #else
 		    afsp->s_root = d_alloc_root(ip);
 #endif
-#if !defined(STRUCT_SUPER_BLOCK_HAS_S_D_OP)
+#if !defined(HAVE_LINUX_SET_DEFAULT_D_OP) && !defined(STRUCT_SUPER_BLOCK_HAS_S_D_OP)
 		    afsp->s_root->d_op = &afs_dentry_operations;
 #endif
 		    afs_DestroyAttr(vattr);
diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
index b525126c20a1..432643fe5583 100644
--- a/src/afs/LINUX/osi_vnodeops.c
+++ b/src/afs/LINUX/osi_vnodeops.c
@@ -1844,7 +1844,7 @@ afs_linux_create(struct inode *dip, struct dentry *dp, int mode)
 	afs_getattr(vcp, vattr, credp);
 	afs_fill_inode(ip, vattr);
 	insert_inode_hash(ip);
-#if !defined(STRUCT_SUPER_BLOCK_HAS_S_D_OP)
+#if !defined(HAVE_LINUX_SET_DEFAULT_D_OP) && !defined(STRUCT_SUPER_BLOCK_HAS_S_D_OP)
 	dp->d_op = &afs_dentry_operations;
 #endif
 	dp->d_time = parent_vcache_dv(dip, credp);
@@ -1925,7 +1925,7 @@ afs_linux_lookup(struct inode *dip, struct dentry *dp)
 
 	afs_DestroyAttr(vattr);
     }
-#if !defined(STRUCT_SUPER_BLOCK_HAS_S_D_OP)
+#if !defined(HAVE_LINUX_SET_DEFAULT_D_OP) && !defined(STRUCT_SUPER_BLOCK_HAS_S_D_OP)
     dp->d_op = &afs_dentry_operations;
 #endif
     dp->d_time = parent_vcache_dv(dip, credp);
@@ -2171,7 +2171,7 @@ afs_linux_mkdir(struct inode *dip, struct dentry *dp, int mode)
 	afs_getattr(tvcp, vattr, credp);
 	afs_fill_inode(ip, vattr);
 
-#if !defined(STRUCT_SUPER_BLOCK_HAS_S_D_OP)
+#if !defined(HAVE_LINUX_SET_DEFAULT_D_OP) && !defined(STRUCT_SUPER_BLOCK_HAS_S_D_OP)
 	dp->d_op = &afs_dentry_operations;
 #endif
 	dp->d_time = parent_vcache_dv(dip, credp);
diff --git a/src/cf/linux-kernel-func.m4 b/src/cf/linux-kernel-func.m4
index 0784262d70b9..6845c9918ad1 100644
--- a/src/cf/linux-kernel-func.m4
+++ b/src/cf/linux-kernel-func.m4
@@ -379,6 +379,16 @@ AC_CHECK_LINUX_FUNC([write_begin_end_kiocb],
 		    [[aops->write_begin(kiocb, mapping, 0, 0, &foliop, fsdata);
 		      aops->write_end(kiocb, mapping, 0, 0, 0, foliop, fsdata);]])
 
+dnl Linux 6.17 added a helper function set_default_d_op() to set the default
+dnl dentry_operations for a super_block.  The super_block member s_d_op is now
+dnl a private member of the super_block.
+AC_CHECK_LINUX_FUNC([set_default_d_op],
+		    [#include <linux/kernel.h>
+		     #include <linux/dcache.h>],
+		    [[static struct super_block sb;
+		      static struct dentry_operations d_op;
+		      set_default_d_op(&sb, &d_op);]])
+
 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/cf/linux-kernel-struct.m4 b/src/cf/linux-kernel-struct.m4
index 24841e9f3245..46c23a25fbb8 100644
--- a/src/cf/linux-kernel-struct.m4
+++ b/src/cf/linux-kernel-struct.m4
@@ -44,6 +44,10 @@ AC_CHECK_LINUX_STRUCT([nameidata], [path], [namei.h])
 AC_CHECK_LINUX_STRUCT([proc_dir_entry], [owner], [proc_fs.h])
 AC_CHECK_LINUX_STRUCT([proc_ops], [proc_compat_ioctl], [proc_fs.h])
 AC_CHECK_LINUX_STRUCT([super_block], [s_bdi], [fs.h])
+dnl Linux 2.6.38 added the s_d_op field to hold the default dentry ops.
+dnl Linux 6.17 renamed s_d_op to a private member, requiring users to instead
+dnl call set_default_d_op() to initialize the super_block with the default
+dnl dentry ops.
 AC_CHECK_LINUX_STRUCT([super_block], [s_d_op], [fs.h])
 AC_CHECK_LINUX_STRUCT([super_operations], [alloc_inode],
                       [fs.h])
-- 
2.52.0