summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2017-07-12 07:17:16 -0400
committerMiklos Szeredi <mszeredi@redhat.com>2018-01-24 05:25:59 -0500
commit8ed5eec9d6c4c013aa657ebefbd10a1a0d15893d (patch)
tree634ea6f80f9212f0d81c846145a8b260f2c6d34a
parenta01f64b5c06ca1130b0b72ceb5e2a25e4d37ab08 (diff)
ovl: encode pure upper file handles
Encode overlay file handles as struct ovl_fh containing the file handle encoding of the real upper inode. Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
-rw-r--r--fs/overlayfs/Makefile3
-rw-r--r--fs/overlayfs/export.c98
-rw-r--r--fs/overlayfs/overlayfs.h6
3 files changed, 106 insertions, 1 deletions
diff --git a/fs/overlayfs/Makefile b/fs/overlayfs/Makefile
index 99373bbc1478..30802347a020 100644
--- a/fs/overlayfs/Makefile
+++ b/fs/overlayfs/Makefile
@@ -4,4 +4,5 @@
4 4
5obj-$(CONFIG_OVERLAY_FS) += overlay.o 5obj-$(CONFIG_OVERLAY_FS) += overlay.o
6 6
7overlay-objs := super.o namei.o util.o inode.o dir.o readdir.o copy_up.o 7overlay-objs := super.o namei.o util.o inode.o dir.o readdir.o copy_up.o \
8 export.o
diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c
new file mode 100644
index 000000000000..67b907ca9cdc
--- /dev/null
+++ b/fs/overlayfs/export.c
@@ -0,0 +1,98 @@
1/*
2 * Overlayfs NFS export support.
3 *
4 * Amir Goldstein <amir73il@gmail.com>
5 *
6 * Copyright (C) 2017-2018 CTERA Networks. All Rights Reserved.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 */
12
13#include <linux/fs.h>
14#include <linux/cred.h>
15#include <linux/mount.h>
16#include <linux/namei.h>
17#include <linux/xattr.h>
18#include <linux/exportfs.h>
19#include <linux/ratelimit.h>
20#include "overlayfs.h"
21
22static int ovl_d_to_fh(struct dentry *dentry, char *buf, int buflen)
23{
24 struct dentry *upper = ovl_dentry_upper(dentry);
25 struct dentry *origin = ovl_dentry_lower(dentry);
26 struct ovl_fh *fh = NULL;
27 int err;
28
29 /*
30 * On overlay with an upper layer, overlay root inode is encoded as
31 * an upper file handle, because upper root dir is not indexed.
32 */
33 if (dentry == dentry->d_sb->s_root && upper)
34 origin = NULL;
35
36 err = -EACCES;
37 if (!upper || origin)
38 goto fail;
39
40 /* TODO: encode non pure-upper by origin */
41 fh = ovl_encode_fh(upper, true);
42
43 err = -EOVERFLOW;
44 if (fh->len > buflen)
45 goto fail;
46
47 memcpy(buf, (char *)fh, fh->len);
48 err = fh->len;
49
50out:
51 kfree(fh);
52 return err;
53
54fail:
55 pr_warn_ratelimited("overlayfs: failed to encode file handle (%pd2, err=%i, buflen=%d, len=%d, type=%d)\n",
56 dentry, err, buflen, fh ? (int)fh->len : 0,
57 fh ? fh->type : 0);
58 goto out;
59}
60
61static int ovl_dentry_to_fh(struct dentry *dentry, u32 *fid, int *max_len)
62{
63 int res, len = *max_len << 2;
64
65 res = ovl_d_to_fh(dentry, (char *)fid, len);
66 if (res <= 0)
67 return FILEID_INVALID;
68
69 len = res;
70
71 /* Round up to dwords */
72 *max_len = (len + 3) >> 2;
73 return OVL_FILEID;
74}
75
76static int ovl_encode_inode_fh(struct inode *inode, u32 *fid, int *max_len,
77 struct inode *parent)
78{
79 struct dentry *dentry;
80 int type;
81
82 /* TODO: encode connectable file handles */
83 if (parent)
84 return FILEID_INVALID;
85
86 dentry = d_find_any_alias(inode);
87 if (WARN_ON(!dentry))
88 return FILEID_INVALID;
89
90 type = ovl_dentry_to_fh(dentry, fid, max_len);
91
92 dput(dentry);
93 return type;
94}
95
96const struct export_operations ovl_export_operations = {
97 .encode_fh = ovl_encode_inode_fh,
98};
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 2dddcd257eb3..f2baa2ccaacd 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -68,6 +68,9 @@ enum ovl_entry_flag {
68#error Endianness not defined 68#error Endianness not defined
69#endif 69#endif
70 70
71/* The type returned by overlay exportfs ops when encoding an ovl_fh handle */
72#define OVL_FILEID 0xfb
73
71/* On-disk and in-memeory format for redirect by file handle */ 74/* On-disk and in-memeory format for redirect by file handle */
72struct ovl_fh { 75struct ovl_fh {
73 u8 version; /* 0 */ 76 u8 version; /* 0 */
@@ -351,3 +354,6 @@ int ovl_set_attr(struct dentry *upper, struct kstat *stat);
351struct ovl_fh *ovl_encode_fh(struct dentry *real, bool is_upper); 354struct ovl_fh *ovl_encode_fh(struct dentry *real, bool is_upper);
352int ovl_set_origin(struct dentry *dentry, struct dentry *lower, 355int ovl_set_origin(struct dentry *dentry, struct dentry *lower,
353 struct dentry *upper); 356 struct dentry *upper);
357
358/* export.c */
359extern const struct export_operations ovl_export_operations;