ovl: merge getattr for dir and nondir
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
parent
72b608f085
commit
5b712091a3
|
@ -138,65 +138,6 @@ static int ovl_set_opaque(struct dentry *dentry, struct dentry *upperdentry)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ovl_dir_getattr(const struct path *path, struct kstat *stat,
|
|
||||||
u32 request_mask, unsigned int flags)
|
|
||||||
{
|
|
||||||
struct dentry *dentry = path->dentry;
|
|
||||||
int err;
|
|
||||||
enum ovl_path_type type;
|
|
||||||
struct path realpath;
|
|
||||||
const struct cred *old_cred;
|
|
||||||
|
|
||||||
type = ovl_path_real(dentry, &realpath);
|
|
||||||
old_cred = ovl_override_creds(dentry->d_sb);
|
|
||||||
err = vfs_getattr(&realpath, stat, request_mask, flags);
|
|
||||||
if (err)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When all layers are on the same fs, use the copy-up-origin st_ino,
|
|
||||||
* which is persistent, unique and constant across copy up.
|
|
||||||
*
|
|
||||||
* Otherwise the pair {real st_ino; overlay st_dev} is not unique, so
|
|
||||||
* use the non persistent overlay st_ino.
|
|
||||||
*/
|
|
||||||
if (ovl_same_sb(dentry->d_sb)) {
|
|
||||||
if (OVL_TYPE_ORIGIN(type)) {
|
|
||||||
struct kstat lowerstat;
|
|
||||||
|
|
||||||
ovl_path_lower(dentry, &realpath);
|
|
||||||
err = vfs_getattr(&realpath, &lowerstat,
|
|
||||||
STATX_INO, flags);
|
|
||||||
if (err)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
WARN_ON_ONCE(stat->dev != lowerstat.dev);
|
|
||||||
stat->ino = lowerstat.ino;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
stat->ino = dentry->d_inode->i_ino;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
stat->dev = dentry->d_sb->s_dev;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* It's probably not worth it to count subdirs to get the
|
|
||||||
* correct link count. nlink=1 seems to pacify 'find' and
|
|
||||||
* other utilities.
|
|
||||||
*/
|
|
||||||
if (OVL_TYPE_MERGE(type))
|
|
||||||
stat->nlink = 1;
|
|
||||||
out:
|
|
||||||
revert_creds(old_cred);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Common operations required to be done after creation of file on upper */
|
/* Common operations required to be done after creation of file on upper */
|
||||||
static void ovl_instantiate(struct dentry *dentry, struct inode *inode,
|
static void ovl_instantiate(struct dentry *dentry, struct inode *inode,
|
||||||
struct dentry *newdentry, bool hardlink)
|
struct dentry *newdentry, bool hardlink)
|
||||||
|
@ -1099,7 +1040,7 @@ const struct inode_operations ovl_dir_inode_operations = {
|
||||||
.create = ovl_create,
|
.create = ovl_create,
|
||||||
.mknod = ovl_mknod,
|
.mknod = ovl_mknod,
|
||||||
.permission = ovl_permission,
|
.permission = ovl_permission,
|
||||||
.getattr = ovl_dir_getattr,
|
.getattr = ovl_getattr,
|
||||||
.listxattr = ovl_listxattr,
|
.listxattr = ovl_listxattr,
|
||||||
.get_acl = ovl_get_acl,
|
.get_acl = ovl_get_acl,
|
||||||
.update_time = ovl_update_time,
|
.update_time = ovl_update_time,
|
||||||
|
|
|
@ -57,13 +57,14 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ovl_getattr(const struct path *path, struct kstat *stat,
|
int ovl_getattr(const struct path *path, struct kstat *stat,
|
||||||
u32 request_mask, unsigned int flags)
|
u32 request_mask, unsigned int flags)
|
||||||
{
|
{
|
||||||
struct dentry *dentry = path->dentry;
|
struct dentry *dentry = path->dentry;
|
||||||
enum ovl_path_type type;
|
enum ovl_path_type type;
|
||||||
struct path realpath;
|
struct path realpath;
|
||||||
const struct cred *old_cred;
|
const struct cred *old_cred;
|
||||||
|
bool is_dir = S_ISDIR(dentry->d_inode->i_mode);
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
type = ovl_path_real(dentry, &realpath);
|
type = ovl_path_real(dentry, &realpath);
|
||||||
|
@ -85,10 +86,11 @@ static int ovl_getattr(const struct path *path, struct kstat *stat,
|
||||||
if (ovl_same_sb(dentry->d_sb)) {
|
if (ovl_same_sb(dentry->d_sb)) {
|
||||||
if (OVL_TYPE_ORIGIN(type)) {
|
if (OVL_TYPE_ORIGIN(type)) {
|
||||||
struct kstat lowerstat;
|
struct kstat lowerstat;
|
||||||
|
u32 lowermask = STATX_INO | (!is_dir ? STATX_NLINK : 0);
|
||||||
|
|
||||||
ovl_path_lower(dentry, &realpath);
|
ovl_path_lower(dentry, &realpath);
|
||||||
err = vfs_getattr(&realpath, &lowerstat,
|
err = vfs_getattr(&realpath, &lowerstat,
|
||||||
STATX_INO | STATX_NLINK, flags);
|
lowermask, flags);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -98,11 +100,32 @@ static int ovl_getattr(const struct path *path, struct kstat *stat,
|
||||||
* upper files, so we cannot use the lower origin st_ino
|
* upper files, so we cannot use the lower origin st_ino
|
||||||
* for those different files, even for the same fs case.
|
* for those different files, even for the same fs case.
|
||||||
*/
|
*/
|
||||||
if (lowerstat.nlink == 1)
|
if (is_dir || lowerstat.nlink == 1)
|
||||||
stat->ino = lowerstat.ino;
|
stat->ino = lowerstat.ino;
|
||||||
}
|
}
|
||||||
stat->dev = dentry->d_sb->s_dev;
|
stat->dev = dentry->d_sb->s_dev;
|
||||||
|
} else if (is_dir) {
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
stat->dev = dentry->d_sb->s_dev;
|
||||||
|
stat->ino = dentry->d_inode->i_ino;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It's probably not worth it to count subdirs to get the
|
||||||
|
* correct link count. nlink=1 seems to pacify 'find' and
|
||||||
|
* other utilities.
|
||||||
|
*/
|
||||||
|
if (is_dir && OVL_TYPE_MERGE(type))
|
||||||
|
stat->nlink = 1;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
revert_creds(old_cred);
|
revert_creds(old_cred);
|
||||||
|
|
||||||
|
|
|
@ -236,6 +236,8 @@ void ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt,
|
||||||
|
|
||||||
/* inode.c */
|
/* inode.c */
|
||||||
int ovl_setattr(struct dentry *dentry, struct iattr *attr);
|
int ovl_setattr(struct dentry *dentry, struct iattr *attr);
|
||||||
|
int ovl_getattr(const struct path *path, struct kstat *stat,
|
||||||
|
u32 request_mask, unsigned int flags);
|
||||||
int ovl_permission(struct inode *inode, int mask);
|
int ovl_permission(struct inode *inode, int mask);
|
||||||
int ovl_xattr_set(struct dentry *dentry, const char *name, const void *value,
|
int ovl_xattr_set(struct dentry *dentry, const char *name, const void *value,
|
||||||
size_t size, int flags);
|
size_t size, int flags);
|
||||||
|
|
Loading…
Reference in New Issue