Skip to content

Commit 11b3f8a

Browse files
amir73ilbrauner
authored andcommitted
fs: remove the inode argument to ->d_real() method
The only remaining user of ->d_real() method is d_real_inode(), which passed NULL inode argument to get the real data dentry. There are no longer any users that call ->d_real() with a non-NULL inode argument for getting a detry from a specific underlying layer. Remove the inode argument of the method and replace it with an integer 'type' argument, to allow callers to request the real metadata dentry instead of the real data dentry. All the current users of d_real_inode() (e.g. uprobe) continue to get the real data inode. Caller that need to get the real metadata inode (e.g. IMA/EVM) can use d_inode(d_real(dentry, D_REAL_METADATA)). Signed-off-by: Amir Goldstein <amir73il@gmail.com> Link: https://lore.kernel.org/r/20240202110132.1584111-3-amir73il@gmail.com Tested-by: Stefan Berger <stefanb@linux.ibm.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent 3058fca commit 11b3f8a

4 files changed

Lines changed: 41 additions & 47 deletions

File tree

Documentation/filesystems/locking.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ prototypes::
2929
char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen);
3030
struct vfsmount *(*d_automount)(struct path *path);
3131
int (*d_manage)(const struct path *, bool);
32-
struct dentry *(*d_real)(struct dentry *, const struct inode *);
32+
struct dentry *(*d_real)(struct dentry *, enum d_real_type type);
3333

3434
locking rules:
3535

Documentation/filesystems/vfs.rst

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,7 +1264,7 @@ defined:
12641264
char *(*d_dname)(struct dentry *, char *, int);
12651265
struct vfsmount *(*d_automount)(struct path *);
12661266
int (*d_manage)(const struct path *, bool);
1267-
struct dentry *(*d_real)(struct dentry *, const struct inode *);
1267+
struct dentry *(*d_real)(struct dentry *, enum d_real_type type);
12681268
};
12691269
12701270
``d_revalidate``
@@ -1419,16 +1419,14 @@ defined:
14191419
the dentry being transited from.
14201420

14211421
``d_real``
1422-
overlay/union type filesystems implement this method to return
1423-
one of the underlying dentries hidden by the overlay. It is
1424-
used in two different modes:
1422+
overlay/union type filesystems implement this method to return one
1423+
of the underlying dentries of a regular file hidden by the overlay.
14251424

1426-
Called from file_dentry() it returns the real dentry matching
1427-
the inode argument. The real dentry may be from a lower layer
1428-
already copied up, but still referenced from the file. This
1429-
mode is selected with a non-NULL inode argument.
1425+
The 'type' argument takes the values D_REAL_DATA or D_REAL_METADATA
1426+
for returning the real underlying dentry that refers to the inode
1427+
hosting the file's data or metadata respectively.
14301428

1431-
With NULL inode the topmost real underlying dentry is returned.
1429+
For non-regular files, the 'dentry' argument is returned.
14321430

14331431
Each dentry has a pointer to its parent dentry, as well as a hash list
14341432
of child dentries. Child dentries are basically like files in a

fs/overlayfs/super.c

Lines changed: 22 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -28,41 +28,38 @@ MODULE_LICENSE("GPL");
2828

2929
struct ovl_dir_cache;
3030

31-
static struct dentry *ovl_d_real(struct dentry *dentry,
32-
const struct inode *inode)
31+
static struct dentry *ovl_d_real(struct dentry *dentry, enum d_real_type type)
3332
{
34-
struct dentry *real = NULL, *lower;
33+
struct dentry *upper, *lower;
3534
int err;
3635

37-
/*
38-
* vfs is only expected to call d_real() with NULL from d_real_inode()
39-
* and with overlay inode from file_dentry() on an overlay file.
40-
*
41-
* TODO: remove @inode argument from d_real() API, remove code in this
42-
* function that deals with non-NULL @inode and remove d_real() call
43-
* from file_dentry().
44-
*/
45-
if (inode && d_inode(dentry) == inode)
46-
return dentry;
47-
else if (inode)
36+
switch (type) {
37+
case D_REAL_DATA:
38+
case D_REAL_METADATA:
39+
break;
40+
default:
4841
goto bug;
42+
}
4943

5044
if (!d_is_reg(dentry)) {
5145
/* d_real_inode() is only relevant for regular files */
5246
return dentry;
5347
}
5448

55-
real = ovl_dentry_upper(dentry);
56-
if (real && (inode == d_inode(real)))
57-
return real;
49+
upper = ovl_dentry_upper(dentry);
50+
if (upper && (type == D_REAL_METADATA ||
51+
ovl_has_upperdata(d_inode(dentry))))
52+
return upper;
5853

59-
if (real && !inode && ovl_has_upperdata(d_inode(dentry)))
60-
return real;
54+
if (type == D_REAL_METADATA) {
55+
lower = ovl_dentry_lower(dentry);
56+
goto real_lower;
57+
}
6158

6259
/*
63-
* Best effort lazy lookup of lowerdata for !inode case to return
60+
* Best effort lazy lookup of lowerdata for D_REAL_DATA case to return
6461
* the real lowerdata dentry. The only current caller of d_real() with
65-
* NULL inode is d_real_inode() from trace_uprobe and this caller is
62+
* D_REAL_DATA is d_real_inode() from trace_uprobe and this caller is
6663
* likely going to be followed reading from the file, before placing
6764
* uprobes on offset within the file, so lowerdata should be available
6865
* when setting the uprobe.
@@ -73,18 +70,13 @@ static struct dentry *ovl_d_real(struct dentry *dentry,
7370
lower = ovl_dentry_lowerdata(dentry);
7471
if (!lower)
7572
goto bug;
76-
real = lower;
7773

78-
/* Handle recursion */
79-
real = d_real(real, inode);
74+
real_lower:
75+
/* Handle recursion into stacked lower fs */
76+
return d_real(lower, type);
8077

81-
if (!inode || inode == d_inode(real))
82-
return real;
8378
bug:
84-
WARN(1, "%s(%pd4, %s:%lu): real dentry (%p/%lu) not found\n",
85-
__func__, dentry, inode ? inode->i_sb->s_id : "NULL",
86-
inode ? inode->i_ino : 0, real,
87-
real && d_inode(real) ? d_inode(real)->i_ino : 0);
79+
WARN(1, "%s(%pd4, %d): real dentry not found\n", __func__, dentry, type);
8880
return dentry;
8981
}
9082

include/linux/dcache.h

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,11 @@ enum dentry_d_lock_class
125125
DENTRY_D_LOCK_NESTED
126126
};
127127

128+
enum d_real_type {
129+
D_REAL_DATA,
130+
D_REAL_METADATA,
131+
};
132+
128133
struct dentry_operations {
129134
int (*d_revalidate)(struct dentry *, unsigned int);
130135
int (*d_weak_revalidate)(struct dentry *, unsigned int);
@@ -139,7 +144,7 @@ struct dentry_operations {
139144
char *(*d_dname)(struct dentry *, char *, int);
140145
struct vfsmount *(*d_automount)(struct path *);
141146
int (*d_manage)(const struct path *, bool);
142-
struct dentry *(*d_real)(struct dentry *, const struct inode *);
147+
struct dentry *(*d_real)(struct dentry *, enum d_real_type type);
143148
} ____cacheline_aligned;
144149

145150
/*
@@ -546,24 +551,23 @@ static inline struct inode *d_backing_inode(const struct dentry *upper)
546551
/**
547552
* d_real - Return the real dentry
548553
* @dentry: the dentry to query
549-
* @inode: inode to select the dentry from multiple layers (can be NULL)
554+
* @type: the type of real dentry (data or metadata)
550555
*
551556
* If dentry is on a union/overlay, then return the underlying, real dentry.
552557
* Otherwise return the dentry itself.
553558
*
554559
* See also: Documentation/filesystems/vfs.rst
555560
*/
556-
static inline struct dentry *d_real(struct dentry *dentry,
557-
const struct inode *inode)
561+
static inline struct dentry *d_real(struct dentry *dentry, enum d_real_type type)
558562
{
559563
if (unlikely(dentry->d_flags & DCACHE_OP_REAL))
560-
return dentry->d_op->d_real(dentry, inode);
564+
return dentry->d_op->d_real(dentry, type);
561565
else
562566
return dentry;
563567
}
564568

565569
/**
566-
* d_real_inode - Return the real inode
570+
* d_real_inode - Return the real inode hosting the data
567571
* @dentry: The dentry to query
568572
*
569573
* If dentry is on a union/overlay, then return the underlying, real inode.
@@ -572,7 +576,7 @@ static inline struct dentry *d_real(struct dentry *dentry,
572576
static inline struct inode *d_real_inode(const struct dentry *dentry)
573577
{
574578
/* This usage of d_real() results in const dentry */
575-
return d_backing_inode(d_real((struct dentry *) dentry, NULL));
579+
return d_inode(d_real((struct dentry *) dentry, D_REAL_DATA));
576580
}
577581

578582
struct name_snapshot {

0 commit comments

Comments
 (0)