mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-29 07:04:10 +08:00
ovl: factor out ovl_map_dev_ino() helper
A helper for ovl_getattr() to map the values of st_dev and st_ino according to constant st_ino rules. Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
parent
8f35cf51cd
commit
da309e8c05
@ -16,13 +16,6 @@
|
||||
#include "overlayfs.h"
|
||||
|
||||
|
||||
static dev_t ovl_get_pseudo_dev(struct dentry *dentry)
|
||||
{
|
||||
struct ovl_entry *oe = dentry->d_fsdata;
|
||||
|
||||
return oe->lowerstack[0].layer->pseudo_dev;
|
||||
}
|
||||
|
||||
int ovl_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
{
|
||||
int err;
|
||||
@ -66,6 +59,43 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ovl_map_dev_ino(struct dentry *dentry, struct kstat *stat,
|
||||
struct ovl_layer *lower_layer)
|
||||
{
|
||||
bool samefs = ovl_same_sb(dentry->d_sb);
|
||||
|
||||
if (samefs) {
|
||||
/*
|
||||
* When all layers are on the same fs, all real inode
|
||||
* number are unique, so we use the overlay st_dev,
|
||||
* which is friendly to du -x.
|
||||
*/
|
||||
stat->dev = dentry->d_sb->s_dev;
|
||||
} else if (S_ISDIR(dentry->d_inode->i_mode)) {
|
||||
/*
|
||||
* Always use the overlay st_dev for directories, so 'find
|
||||
* -xdev' will scan the entire overlay mount and won't cross the
|
||||
* overlay mount boundaries.
|
||||
*
|
||||
* If not all layers are on the same fs the pair {real st_ino;
|
||||
* overlay st_dev} is not unique, so use the non persistent
|
||||
* overlay st_ino for directories.
|
||||
*/
|
||||
stat->dev = dentry->d_sb->s_dev;
|
||||
stat->ino = dentry->d_inode->i_ino;
|
||||
} else if (lower_layer) {
|
||||
/*
|
||||
* For non-samefs setup, if we cannot map all layers st_ino
|
||||
* to a unified address space, we need to make sure that st_dev
|
||||
* is unique per layer. Upper layer uses real st_dev and lower
|
||||
* layers use the unique anonymous bdev.
|
||||
*/
|
||||
stat->dev = lower_layer->pseudo_dev;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ovl_getattr(const struct path *path, struct kstat *stat,
|
||||
u32 request_mask, unsigned int flags)
|
||||
{
|
||||
@ -75,6 +105,7 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
|
||||
const struct cred *old_cred;
|
||||
bool is_dir = S_ISDIR(dentry->d_inode->i_mode);
|
||||
bool samefs = ovl_same_sb(dentry->d_sb);
|
||||
struct ovl_layer *lower_layer = NULL;
|
||||
int err;
|
||||
|
||||
type = ovl_path_real(dentry, &realpath);
|
||||
@ -84,14 +115,16 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* For non-dir or same fs, we use st_ino of the copy up origin, if we
|
||||
* know it. This guaranties constant st_dev/st_ino across copy up.
|
||||
* For non-dir or same fs, we use st_ino of the copy up origin.
|
||||
* This guaranties constant st_dev/st_ino across copy up.
|
||||
*
|
||||
* If filesystem supports NFS export ops, this also guaranties
|
||||
* If lower filesystem supports NFS file handles, this also guaranties
|
||||
* persistent st_ino across mount cycle.
|
||||
*/
|
||||
if (!is_dir || samefs) {
|
||||
if (OVL_TYPE_ORIGIN(type)) {
|
||||
if (!OVL_TYPE_UPPER(type)) {
|
||||
lower_layer = ovl_layer_lower(dentry);
|
||||
} else if (OVL_TYPE_ORIGIN(type)) {
|
||||
struct kstat lowerstat;
|
||||
u32 lowermask = STATX_INO | (!is_dir ? STATX_NLINK : 0);
|
||||
|
||||
@ -120,38 +153,15 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
|
||||
(!ovl_verify_lower(dentry->d_sb) &&
|
||||
(is_dir || lowerstat.nlink == 1))) {
|
||||
stat->ino = lowerstat.ino;
|
||||
stat->dev = ovl_get_pseudo_dev(dentry);
|
||||
lower_layer = ovl_layer_lower(dentry);
|
||||
}
|
||||
}
|
||||
if (samefs) {
|
||||
/*
|
||||
* When all layers are on the same fs, all real inode
|
||||
* number are unique, so we use the overlay st_dev,
|
||||
* which is friendly to du -x.
|
||||
*/
|
||||
stat->dev = dentry->d_sb->s_dev;
|
||||
} else if (!OVL_TYPE_UPPER(type)) {
|
||||
/*
|
||||
* For non-samefs setup, to make sure that st_dev/st_ino
|
||||
* pair is unique across the system, we use a unique
|
||||
* anonymous st_dev for lower layer inode.
|
||||
*/
|
||||
stat->dev = ovl_get_pseudo_dev(dentry);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Always use the overlay st_dev for directories, so 'find
|
||||
* -xdev' will scan the entire overlay mount and won't cross the
|
||||
* overlay mount boundaries.
|
||||
*
|
||||
* If not all layers are on the same fs the pair {real st_ino;
|
||||
* overlay st_dev} is not unique, so use the non persistent
|
||||
* overlay st_ino for directories.
|
||||
*/
|
||||
stat->dev = dentry->d_sb->s_dev;
|
||||
stat->ino = dentry->d_inode->i_ino;
|
||||
}
|
||||
|
||||
err = ovl_map_dev_ino(dentry, stat, lower_layer);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* It's probably not worth it to count subdirs to get the
|
||||
* correct link count. nlink=1 seems to pacify 'find' and
|
||||
|
@ -215,6 +215,7 @@ void ovl_path_lower(struct dentry *dentry, struct path *path);
|
||||
enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path);
|
||||
struct dentry *ovl_dentry_upper(struct dentry *dentry);
|
||||
struct dentry *ovl_dentry_lower(struct dentry *dentry);
|
||||
struct ovl_layer *ovl_layer_lower(struct dentry *dentry);
|
||||
struct dentry *ovl_dentry_real(struct dentry *dentry);
|
||||
struct dentry *ovl_i_dentry_upper(struct inode *inode);
|
||||
struct inode *ovl_inode_upper(struct inode *inode);
|
||||
|
@ -172,6 +172,13 @@ struct dentry *ovl_dentry_lower(struct dentry *dentry)
|
||||
return oe->numlower ? oe->lowerstack[0].dentry : NULL;
|
||||
}
|
||||
|
||||
struct ovl_layer *ovl_layer_lower(struct dentry *dentry)
|
||||
{
|
||||
struct ovl_entry *oe = dentry->d_fsdata;
|
||||
|
||||
return oe->numlower ? oe->lowerstack[0].layer : NULL;
|
||||
}
|
||||
|
||||
struct dentry *ovl_dentry_real(struct dentry *dentry)
|
||||
{
|
||||
return ovl_dentry_upper(dentry) ?: ovl_dentry_lower(dentry);
|
||||
|
Loading…
Reference in New Issue
Block a user