diff options
author | Amir Goldstein <amir73il@gmail.com> | 2017-12-28 21:23:05 +0300 |
---|---|---|
committer | Miklos Szeredi <mszeredi@redhat.com> | 2018-01-24 13:25:56 +0300 |
commit | 91ffe7beb31e7e1e689a59f5ef56acea0811d81c (patch) | |
tree | 6a5528271ffbaf34650fd988a4f1660dcc70bbbb | |
parent | 24f0b17203691d22815e842051a014e3bde7c227 (diff) | |
download | linux-91ffe7beb31e7e1e689a59f5ef56acea0811d81c.tar.xz |
ovl: factor out ovl_get_index_fh() helper
The helper is needed to lookup an index by file handle for NFS export.
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
-rw-r--r-- | fs/overlayfs/namei.c | 59 | ||||
-rw-r--r-- | fs/overlayfs/overlayfs.h | 1 |
2 files changed, 50 insertions, 10 deletions
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c index 111a64f904c2..49984c9f3689 100644 --- a/fs/overlayfs/namei.c +++ b/fs/overlayfs/namei.c @@ -585,6 +585,21 @@ orphan: goto out; } +static int ovl_get_index_name_fh(struct ovl_fh *fh, struct qstr *name) +{ + char *n, *s; + + n = kzalloc(fh->len * 2, GFP_KERNEL); + if (!n) + return -ENOMEM; + + s = bin2hex(n, fh, fh->len); + *name = (struct qstr) QSTR_INIT(n, s - n); + + return 0; + +} + /* * Lookup in indexdir for the index entry of a lower real inode or a copy up * origin inode. The index entry name is the hex representation of the lower @@ -602,25 +617,49 @@ orphan: */ int ovl_get_index_name(struct dentry *origin, struct qstr *name) { - int err; struct ovl_fh *fh; - char *n, *s; + int err; fh = ovl_encode_fh(origin, false); if (IS_ERR(fh)) return PTR_ERR(fh); - err = -ENOMEM; - n = kzalloc(fh->len * 2, GFP_KERNEL); - if (n) { - s = bin2hex(n, fh, fh->len); - *name = (struct qstr) QSTR_INIT(n, s - n); - err = 0; - } - kfree(fh); + err = ovl_get_index_name_fh(fh, name); + kfree(fh); return err; +} + +/* Lookup index by file handle for NFS export */ +struct dentry *ovl_get_index_fh(struct ovl_fs *ofs, struct ovl_fh *fh) +{ + struct dentry *index; + struct qstr name; + int err; + + err = ovl_get_index_name_fh(fh, &name); + if (err) + return ERR_PTR(err); + + index = lookup_one_len_unlocked(name.name, ofs->indexdir, name.len); + kfree(name.name); + if (IS_ERR(index)) { + if (PTR_ERR(index) == -ENOENT) + index = NULL; + return index; + } + if (d_is_negative(index)) + err = 0; + else if (ovl_is_whiteout(index)) + err = -ESTALE; + else if (ovl_dentry_weird(index)) + err = -EIO; + else + return index; + + dput(index); + return ERR_PTR(err); } static struct dentry *ovl_lookup_index(struct dentry *dentry, diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 8f4313c6693b..4e784f6ff484 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -257,6 +257,7 @@ int ovl_verify_set_fh(struct dentry *dentry, const char *name, struct dentry *real, bool is_upper, bool set); int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index); int ovl_get_index_name(struct dentry *origin, struct qstr *name); +struct dentry *ovl_get_index_fh(struct ovl_fs *ofs, struct ovl_fh *fh); int ovl_path_next(int idx, struct dentry *dentry, struct path *path); struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags); |