1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2bbb1e54dSMiklos Szeredi /*
3bbb1e54dSMiklos Szeredi * Copyright (C) 2011 Novell Inc.
4bbb1e54dSMiklos Szeredi * Copyright (C) 2016 Red Hat, Inc.
5bbb1e54dSMiklos Szeredi */
6bbb1e54dSMiklos Szeredi
7bbb1e54dSMiklos Szeredi #include <linux/fs.h>
8bbb1e54dSMiklos Szeredi #include <linux/mount.h>
9bbb1e54dSMiklos Szeredi #include <linux/slab.h>
105b825c3aSIngo Molnar #include <linux/cred.h>
11bbb1e54dSMiklos Szeredi #include <linux/xattr.h>
1202bcd157SAmir Goldstein #include <linux/exportfs.h>
13184996e9SAlexander Larsson #include <linux/file.h>
14096a218aSAmir Goldstein #include <linux/fileattr.h>
1502bcd157SAmir Goldstein #include <linux/uuid.h>
16caf70cb2SAmir Goldstein #include <linux/namei.h>
17caf70cb2SAmir Goldstein #include <linux/ratelimit.h>
18bbb1e54dSMiklos Szeredi #include "overlayfs.h"
19bbb1e54dSMiklos Szeredi
ovl_want_write(struct dentry * dentry)20bbb1e54dSMiklos Szeredi int ovl_want_write(struct dentry *dentry)
21bbb1e54dSMiklos Szeredi {
22f01d0889SAndrea Righi struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
2308f4c7c8SMiklos Szeredi return mnt_want_write(ovl_upper_mnt(ofs));
24bbb1e54dSMiklos Szeredi }
25bbb1e54dSMiklos Szeredi
ovl_drop_write(struct dentry * dentry)26bbb1e54dSMiklos Szeredi void ovl_drop_write(struct dentry *dentry)
27bbb1e54dSMiklos Szeredi {
28f01d0889SAndrea Righi struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
2908f4c7c8SMiklos Szeredi mnt_drop_write(ovl_upper_mnt(ofs));
30bbb1e54dSMiklos Szeredi }
31bbb1e54dSMiklos Szeredi
ovl_workdir(struct dentry * dentry)32bbb1e54dSMiklos Szeredi struct dentry *ovl_workdir(struct dentry *dentry)
33bbb1e54dSMiklos Szeredi {
34f01d0889SAndrea Righi struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
35bbb1e54dSMiklos Szeredi return ofs->workdir;
36bbb1e54dSMiklos Szeredi }
37bbb1e54dSMiklos Szeredi
ovl_override_creds(struct super_block * sb)38bbb1e54dSMiklos Szeredi const struct cred *ovl_override_creds(struct super_block *sb)
39bbb1e54dSMiklos Szeredi {
40f01d0889SAndrea Righi struct ovl_fs *ofs = OVL_FS(sb);
41bbb1e54dSMiklos Szeredi
42bbb1e54dSMiklos Szeredi return override_creds(ofs->creator_cred);
43bbb1e54dSMiklos Szeredi }
44bbb1e54dSMiklos Szeredi
45e487d889SAmir Goldstein /*
46e487d889SAmir Goldstein * Check if underlying fs supports file handles and try to determine encoding
47e487d889SAmir Goldstein * type, in order to deduce maximum inode number used by fs.
48e487d889SAmir Goldstein *
49e487d889SAmir Goldstein * Return 0 if file handles are not supported.
50e487d889SAmir Goldstein * Return 1 (FILEID_INO32_GEN) if fs uses the default 32bit inode encoding.
51e487d889SAmir Goldstein * Return -1 if fs uses a non default encoding with unknown inode size.
52e487d889SAmir Goldstein */
ovl_can_decode_fh(struct super_block * sb)53e487d889SAmir Goldstein int ovl_can_decode_fh(struct super_block *sb)
5402bcd157SAmir Goldstein {
55c846af05SMiklos Szeredi if (!capable(CAP_DAC_READ_SEARCH))
56c846af05SMiklos Szeredi return 0;
57c846af05SMiklos Szeredi
589df085f3SAmir Goldstein if (!sb->s_export_op || !sb->s_export_op->fh_to_dentry)
59e487d889SAmir Goldstein return 0;
60e487d889SAmir Goldstein
61e487d889SAmir Goldstein return sb->s_export_op->encode_fh ? -1 : FILEID_INO32_GEN;
6202bcd157SAmir Goldstein }
6302bcd157SAmir Goldstein
ovl_indexdir(struct super_block * sb)6402bcd157SAmir Goldstein struct dentry *ovl_indexdir(struct super_block *sb)
6502bcd157SAmir Goldstein {
66f01d0889SAndrea Righi struct ovl_fs *ofs = OVL_FS(sb);
6702bcd157SAmir Goldstein
6802bcd157SAmir Goldstein return ofs->indexdir;
6902bcd157SAmir Goldstein }
7002bcd157SAmir Goldstein
71f168f109SAmir Goldstein /* Index all files on copy up. For now only enabled for NFS export */
ovl_index_all(struct super_block * sb)72f168f109SAmir Goldstein bool ovl_index_all(struct super_block *sb)
73f168f109SAmir Goldstein {
74f01d0889SAndrea Righi struct ovl_fs *ofs = OVL_FS(sb);
75f168f109SAmir Goldstein
76f168f109SAmir Goldstein return ofs->config.nfs_export && ofs->config.index;
77f168f109SAmir Goldstein }
78f168f109SAmir Goldstein
79f168f109SAmir Goldstein /* Verify lower origin on lookup. For now only enabled for NFS export */
ovl_verify_lower(struct super_block * sb)80f168f109SAmir Goldstein bool ovl_verify_lower(struct super_block *sb)
81f168f109SAmir Goldstein {
82f01d0889SAndrea Righi struct ovl_fs *ofs = OVL_FS(sb);
83f168f109SAmir Goldstein
84f168f109SAmir Goldstein return ofs->config.nfs_export && ofs->config.index;
85f168f109SAmir Goldstein }
86f168f109SAmir Goldstein
ovl_stack_alloc(unsigned int n)87163db0daSAmir Goldstein struct ovl_path *ovl_stack_alloc(unsigned int n)
88163db0daSAmir Goldstein {
89163db0daSAmir Goldstein return kcalloc(n, sizeof(struct ovl_path), GFP_KERNEL);
90163db0daSAmir Goldstein }
91163db0daSAmir Goldstein
ovl_stack_cpy(struct ovl_path * dst,struct ovl_path * src,unsigned int n)92163db0daSAmir Goldstein void ovl_stack_cpy(struct ovl_path *dst, struct ovl_path *src, unsigned int n)
93163db0daSAmir Goldstein {
94163db0daSAmir Goldstein unsigned int i;
95163db0daSAmir Goldstein
96163db0daSAmir Goldstein memcpy(dst, src, sizeof(struct ovl_path) * n);
97163db0daSAmir Goldstein for (i = 0; i < n; i++)
98163db0daSAmir Goldstein dget(src[i].dentry);
99163db0daSAmir Goldstein }
100163db0daSAmir Goldstein
ovl_stack_put(struct ovl_path * stack,unsigned int n)101163db0daSAmir Goldstein void ovl_stack_put(struct ovl_path *stack, unsigned int n)
102163db0daSAmir Goldstein {
103163db0daSAmir Goldstein unsigned int i;
104163db0daSAmir Goldstein
105163db0daSAmir Goldstein for (i = 0; stack && i < n; i++)
106163db0daSAmir Goldstein dput(stack[i].dentry);
107163db0daSAmir Goldstein }
108163db0daSAmir Goldstein
ovl_stack_free(struct ovl_path * stack,unsigned int n)109163db0daSAmir Goldstein void ovl_stack_free(struct ovl_path *stack, unsigned int n)
110163db0daSAmir Goldstein {
111163db0daSAmir Goldstein ovl_stack_put(stack, n);
112163db0daSAmir Goldstein kfree(stack);
113163db0daSAmir Goldstein }
114163db0daSAmir Goldstein
ovl_alloc_entry(unsigned int numlower)115bbb1e54dSMiklos Szeredi struct ovl_entry *ovl_alloc_entry(unsigned int numlower)
116bbb1e54dSMiklos Szeredi {
1175522c9c7SAmir Goldstein size_t size = offsetof(struct ovl_entry, __lowerstack[numlower]);
118bbb1e54dSMiklos Szeredi struct ovl_entry *oe = kzalloc(size, GFP_KERNEL);
119bbb1e54dSMiklos Szeredi
120bbb1e54dSMiklos Szeredi if (oe)
1215522c9c7SAmir Goldstein oe->__numlower = numlower;
122bbb1e54dSMiklos Szeredi
123bbb1e54dSMiklos Szeredi return oe;
124bbb1e54dSMiklos Szeredi }
125bbb1e54dSMiklos Szeredi
ovl_free_entry(struct ovl_entry * oe)126163db0daSAmir Goldstein void ovl_free_entry(struct ovl_entry *oe)
127163db0daSAmir Goldstein {
128163db0daSAmir Goldstein ovl_stack_put(ovl_lowerstack(oe), ovl_numlower(oe));
129163db0daSAmir Goldstein kfree(oe);
130163db0daSAmir Goldstein }
131163db0daSAmir Goldstein
132b07d5cc9SAmir Goldstein #define OVL_D_REVALIDATE (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE)
133b07d5cc9SAmir Goldstein
ovl_dentry_remote(struct dentry * dentry)134bbb1e54dSMiklos Szeredi bool ovl_dentry_remote(struct dentry *dentry)
135bbb1e54dSMiklos Szeredi {
136b07d5cc9SAmir Goldstein return dentry->d_flags & OVL_D_REVALIDATE;
137bbb1e54dSMiklos Szeredi }
138bbb1e54dSMiklos Szeredi
ovl_dentry_update_reval(struct dentry * dentry,struct dentry * realdentry)139b07d5cc9SAmir Goldstein void ovl_dentry_update_reval(struct dentry *dentry, struct dentry *realdentry)
140b07d5cc9SAmir Goldstein {
141b07d5cc9SAmir Goldstein if (!ovl_dentry_remote(realdentry))
142b07d5cc9SAmir Goldstein return;
143b07d5cc9SAmir Goldstein
144b07d5cc9SAmir Goldstein spin_lock(&dentry->d_lock);
145b07d5cc9SAmir Goldstein dentry->d_flags |= realdentry->d_flags & OVL_D_REVALIDATE;
146b07d5cc9SAmir Goldstein spin_unlock(&dentry->d_lock);
147b07d5cc9SAmir Goldstein }
148b07d5cc9SAmir Goldstein
ovl_dentry_init_reval(struct dentry * dentry,struct dentry * upperdentry,struct ovl_entry * oe)1490af950f5SAmir Goldstein void ovl_dentry_init_reval(struct dentry *dentry, struct dentry *upperdentry,
1500af950f5SAmir Goldstein struct ovl_entry *oe)
151b07d5cc9SAmir Goldstein {
1520af950f5SAmir Goldstein return ovl_dentry_init_flags(dentry, upperdentry, oe, OVL_D_REVALIDATE);
153b07d5cc9SAmir Goldstein }
154b07d5cc9SAmir Goldstein
ovl_dentry_init_flags(struct dentry * dentry,struct dentry * upperdentry,struct ovl_entry * oe,unsigned int mask)155b07d5cc9SAmir Goldstein void ovl_dentry_init_flags(struct dentry *dentry, struct dentry *upperdentry,
1560af950f5SAmir Goldstein struct ovl_entry *oe, unsigned int mask)
157f4288844SMiklos Szeredi {
1585522c9c7SAmir Goldstein struct ovl_path *lowerstack = ovl_lowerstack(oe);
159f4288844SMiklos Szeredi unsigned int i, flags = 0;
160f4288844SMiklos Szeredi
161bccece1eSMiklos Szeredi if (upperdentry)
162bccece1eSMiklos Szeredi flags |= upperdentry->d_flags;
16341665644SAmir Goldstein for (i = 0; i < ovl_numlower(oe) && lowerstack[i].dentry; i++)
1645522c9c7SAmir Goldstein flags |= lowerstack[i].dentry->d_flags;
165f4288844SMiklos Szeredi
166f4288844SMiklos Szeredi spin_lock(&dentry->d_lock);
167f4288844SMiklos Szeredi dentry->d_flags &= ~mask;
168f4288844SMiklos Szeredi dentry->d_flags |= flags & mask;
169f4288844SMiklos Szeredi spin_unlock(&dentry->d_lock);
170f4288844SMiklos Szeredi }
171f4288844SMiklos Szeredi
ovl_dentry_weird(struct dentry * dentry)172bbb1e54dSMiklos Szeredi bool ovl_dentry_weird(struct dentry *dentry)
173bbb1e54dSMiklos Szeredi {
174*065bf5ddSVasiliy Kovalev if (!d_can_lookup(dentry) && !d_is_file(dentry) && !d_is_symlink(dentry))
175*065bf5ddSVasiliy Kovalev return true;
176*065bf5ddSVasiliy Kovalev
177bbb1e54dSMiklos Szeredi return dentry->d_flags & (DCACHE_NEED_AUTOMOUNT |
178bbb1e54dSMiklos Szeredi DCACHE_MANAGE_TRANSIT |
179bbb1e54dSMiklos Szeredi DCACHE_OP_HASH |
180bbb1e54dSMiklos Szeredi DCACHE_OP_COMPARE);
181bbb1e54dSMiklos Szeredi }
182bbb1e54dSMiklos Szeredi
ovl_path_type(struct dentry * dentry)183bbb1e54dSMiklos Szeredi enum ovl_path_type ovl_path_type(struct dentry *dentry)
184bbb1e54dSMiklos Szeredi {
185a6ff2bc0SAmir Goldstein struct ovl_entry *oe = OVL_E(dentry);
186bbb1e54dSMiklos Szeredi enum ovl_path_type type = 0;
187bbb1e54dSMiklos Szeredi
18809d8b586SMiklos Szeredi if (ovl_dentry_upper(dentry)) {
189bbb1e54dSMiklos Szeredi type = __OVL_PATH_UPPER;
190bbb1e54dSMiklos Szeredi
191bbb1e54dSMiklos Szeredi /*
19259548503SAmir Goldstein * Non-dir dentry can hold lower dentry of its copy up origin.
193bbb1e54dSMiklos Szeredi */
1945522c9c7SAmir Goldstein if (ovl_numlower(oe)) {
19560124877SVivek Goyal if (ovl_test_flag(OVL_CONST_INO, d_inode(dentry)))
19659548503SAmir Goldstein type |= __OVL_PATH_ORIGIN;
1970b17c28aSVivek Goyal if (d_is_dir(dentry) ||
1980b17c28aSVivek Goyal !ovl_has_upperdata(d_inode(dentry)))
199bbb1e54dSMiklos Szeredi type |= __OVL_PATH_MERGE;
20059548503SAmir Goldstein }
201bbb1e54dSMiklos Szeredi } else {
2025522c9c7SAmir Goldstein if (ovl_numlower(oe) > 1)
203bbb1e54dSMiklos Szeredi type |= __OVL_PATH_MERGE;
204bbb1e54dSMiklos Szeredi }
205bbb1e54dSMiklos Szeredi return type;
206bbb1e54dSMiklos Szeredi }
207bbb1e54dSMiklos Szeredi
ovl_path_upper(struct dentry * dentry,struct path * path)208bbb1e54dSMiklos Szeredi void ovl_path_upper(struct dentry *dentry, struct path *path)
209bbb1e54dSMiklos Szeredi {
210f01d0889SAndrea Righi struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
211bbb1e54dSMiklos Szeredi
21208f4c7c8SMiklos Szeredi path->mnt = ovl_upper_mnt(ofs);
21309d8b586SMiklos Szeredi path->dentry = ovl_dentry_upper(dentry);
214bbb1e54dSMiklos Szeredi }
215bbb1e54dSMiklos Szeredi
ovl_path_lower(struct dentry * dentry,struct path * path)216bbb1e54dSMiklos Szeredi void ovl_path_lower(struct dentry *dentry, struct path *path)
217bbb1e54dSMiklos Szeredi {
218a6ff2bc0SAmir Goldstein struct ovl_entry *oe = OVL_E(dentry);
2195522c9c7SAmir Goldstein struct ovl_path *lowerpath = ovl_lowerstack(oe);
220bbb1e54dSMiklos Szeredi
2215522c9c7SAmir Goldstein if (ovl_numlower(oe)) {
2225522c9c7SAmir Goldstein path->mnt = lowerpath->layer->mnt;
2235522c9c7SAmir Goldstein path->dentry = lowerpath->dentry;
224b9343632SChandan Rajendra } else {
225b9343632SChandan Rajendra *path = (struct path) { };
226b9343632SChandan Rajendra }
227bbb1e54dSMiklos Szeredi }
228bbb1e54dSMiklos Szeredi
ovl_path_lowerdata(struct dentry * dentry,struct path * path)2294f93b426SVivek Goyal void ovl_path_lowerdata(struct dentry *dentry, struct path *path)
2304f93b426SVivek Goyal {
231a6ff2bc0SAmir Goldstein struct ovl_entry *oe = OVL_E(dentry);
232ab1eb5ffSAmir Goldstein struct ovl_path *lowerdata = ovl_lowerdata(oe);
2332b21da92SAmir Goldstein struct dentry *lowerdata_dentry = ovl_lowerdata_dentry(oe);
2344f93b426SVivek Goyal
2352b21da92SAmir Goldstein if (lowerdata_dentry) {
2362b21da92SAmir Goldstein path->dentry = lowerdata_dentry;
23742dd69aeSAmir Goldstein /*
23842dd69aeSAmir Goldstein * Pairs with smp_wmb() in ovl_dentry_set_lowerdata().
23942dd69aeSAmir Goldstein * Make sure that if lowerdata->dentry is visible, then
24042dd69aeSAmir Goldstein * datapath->layer is visible as well.
24142dd69aeSAmir Goldstein */
24242dd69aeSAmir Goldstein smp_rmb();
24342dd69aeSAmir Goldstein path->mnt = READ_ONCE(lowerdata->layer)->mnt;
2444f93b426SVivek Goyal } else {
2454f93b426SVivek Goyal *path = (struct path) { };
2464f93b426SVivek Goyal }
2474f93b426SVivek Goyal }
2484f93b426SVivek Goyal
ovl_path_real(struct dentry * dentry,struct path * path)249bbb1e54dSMiklos Szeredi enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path)
250bbb1e54dSMiklos Szeredi {
251bbb1e54dSMiklos Szeredi enum ovl_path_type type = ovl_path_type(dentry);
252bbb1e54dSMiklos Szeredi
253bbb1e54dSMiklos Szeredi if (!OVL_TYPE_UPPER(type))
254bbb1e54dSMiklos Szeredi ovl_path_lower(dentry, path);
255bbb1e54dSMiklos Szeredi else
256bbb1e54dSMiklos Szeredi ovl_path_upper(dentry, path);
257bbb1e54dSMiklos Szeredi
258bbb1e54dSMiklos Szeredi return type;
259bbb1e54dSMiklos Szeredi }
260bbb1e54dSMiklos Szeredi
ovl_path_realdata(struct dentry * dentry,struct path * path)2611248ea4bSAmir Goldstein enum ovl_path_type ovl_path_realdata(struct dentry *dentry, struct path *path)
2621248ea4bSAmir Goldstein {
2631248ea4bSAmir Goldstein enum ovl_path_type type = ovl_path_type(dentry);
2641248ea4bSAmir Goldstein
2651248ea4bSAmir Goldstein WARN_ON_ONCE(d_is_dir(dentry));
2661248ea4bSAmir Goldstein
2671248ea4bSAmir Goldstein if (!OVL_TYPE_UPPER(type) || OVL_TYPE_MERGE(type))
2681248ea4bSAmir Goldstein ovl_path_lowerdata(dentry, path);
2691248ea4bSAmir Goldstein else
2701248ea4bSAmir Goldstein ovl_path_upper(dentry, path);
2711248ea4bSAmir Goldstein
2721248ea4bSAmir Goldstein return type;
2731248ea4bSAmir Goldstein }
2741248ea4bSAmir Goldstein
ovl_dentry_upper(struct dentry * dentry)275bbb1e54dSMiklos Szeredi struct dentry *ovl_dentry_upper(struct dentry *dentry)
276bbb1e54dSMiklos Szeredi {
27709d8b586SMiklos Szeredi return ovl_upperdentry_dereference(OVL_I(d_inode(dentry)));
278bbb1e54dSMiklos Szeredi }
279bbb1e54dSMiklos Szeredi
ovl_dentry_lower(struct dentry * dentry)280bbb1e54dSMiklos Szeredi struct dentry *ovl_dentry_lower(struct dentry *dentry)
281bbb1e54dSMiklos Szeredi {
282a6ff2bc0SAmir Goldstein struct ovl_entry *oe = OVL_E(dentry);
283bbb1e54dSMiklos Szeredi
2845522c9c7SAmir Goldstein return ovl_numlower(oe) ? ovl_lowerstack(oe)->dentry : NULL;
285bbb1e54dSMiklos Szeredi }
286bbb1e54dSMiklos Szeredi
ovl_layer_lower(struct dentry * dentry)28713464165SMiklos Szeredi const struct ovl_layer *ovl_layer_lower(struct dentry *dentry)
288da309e8cSAmir Goldstein {
289a6ff2bc0SAmir Goldstein struct ovl_entry *oe = OVL_E(dentry);
290da309e8cSAmir Goldstein
2915522c9c7SAmir Goldstein return ovl_numlower(oe) ? ovl_lowerstack(oe)->layer : NULL;
292da309e8cSAmir Goldstein }
293da309e8cSAmir Goldstein
294647d253fSVivek Goyal /*
295647d253fSVivek Goyal * ovl_dentry_lower() could return either a data dentry or metacopy dentry
296597534e7SXiong Zhenwu * depending on what is stored in lowerstack[0]. At times we need to find
297647d253fSVivek Goyal * lower dentry which has data (and not metacopy dentry). This helper
298647d253fSVivek Goyal * returns the lower data dentry.
299647d253fSVivek Goyal */
ovl_dentry_lowerdata(struct dentry * dentry)300647d253fSVivek Goyal struct dentry *ovl_dentry_lowerdata(struct dentry *dentry)
301647d253fSVivek Goyal {
302ab1eb5ffSAmir Goldstein return ovl_lowerdata_dentry(OVL_E(dentry));
303647d253fSVivek Goyal }
304647d253fSVivek Goyal
ovl_dentry_set_lowerdata(struct dentry * dentry,struct ovl_path * datapath)30542dd69aeSAmir Goldstein int ovl_dentry_set_lowerdata(struct dentry *dentry, struct ovl_path *datapath)
30642dd69aeSAmir Goldstein {
30742dd69aeSAmir Goldstein struct ovl_entry *oe = OVL_E(dentry);
30842dd69aeSAmir Goldstein struct ovl_path *lowerdata = ovl_lowerdata(oe);
30942dd69aeSAmir Goldstein struct dentry *datadentry = datapath->dentry;
31042dd69aeSAmir Goldstein
31142dd69aeSAmir Goldstein if (WARN_ON_ONCE(ovl_numlower(oe) <= 1))
31242dd69aeSAmir Goldstein return -EIO;
31342dd69aeSAmir Goldstein
31442dd69aeSAmir Goldstein WRITE_ONCE(lowerdata->layer, datapath->layer);
31542dd69aeSAmir Goldstein /*
31642dd69aeSAmir Goldstein * Pairs with smp_rmb() in ovl_path_lowerdata().
31742dd69aeSAmir Goldstein * Make sure that if lowerdata->dentry is visible, then
31842dd69aeSAmir Goldstein * lowerdata->layer is visible as well.
31942dd69aeSAmir Goldstein */
32042dd69aeSAmir Goldstein smp_wmb();
32142dd69aeSAmir Goldstein WRITE_ONCE(lowerdata->dentry, dget(datadentry));
32242dd69aeSAmir Goldstein
32342dd69aeSAmir Goldstein ovl_dentry_update_reval(dentry, datadentry);
32442dd69aeSAmir Goldstein
32542dd69aeSAmir Goldstein return 0;
32642dd69aeSAmir Goldstein }
32742dd69aeSAmir Goldstein
ovl_dentry_real(struct dentry * dentry)328bbb1e54dSMiklos Szeredi struct dentry *ovl_dentry_real(struct dentry *dentry)
329bbb1e54dSMiklos Szeredi {
33009d8b586SMiklos Szeredi return ovl_dentry_upper(dentry) ?: ovl_dentry_lower(dentry);
331bbb1e54dSMiklos Szeredi }
332bbb1e54dSMiklos Szeredi
ovl_i_dentry_upper(struct inode * inode)3331d88f183SMiklos Szeredi struct dentry *ovl_i_dentry_upper(struct inode *inode)
3341d88f183SMiklos Szeredi {
3351d88f183SMiklos Szeredi return ovl_upperdentry_dereference(OVL_I(inode));
3361d88f183SMiklos Szeredi }
3371d88f183SMiklos Szeredi
ovl_i_path_real(struct inode * inode,struct path * path)338b2dd05f1SZhihao Cheng struct inode *ovl_i_path_real(struct inode *inode, struct path *path)
339ffa5723cSAmir Goldstein {
340ac900ed4SAmir Goldstein struct ovl_path *lowerpath = ovl_lowerpath(OVL_I_E(inode));
341ac900ed4SAmir Goldstein
342ffa5723cSAmir Goldstein path->dentry = ovl_i_dentry_upper(inode);
343ffa5723cSAmir Goldstein if (!path->dentry) {
344ac900ed4SAmir Goldstein path->dentry = lowerpath->dentry;
345ac900ed4SAmir Goldstein path->mnt = lowerpath->layer->mnt;
346ffa5723cSAmir Goldstein } else {
347ffa5723cSAmir Goldstein path->mnt = ovl_upper_mnt(OVL_FS(inode->i_sb));
348ffa5723cSAmir Goldstein }
349b2dd05f1SZhihao Cheng
350b2dd05f1SZhihao Cheng return path->dentry ? d_inode_rcu(path->dentry) : NULL;
351ffa5723cSAmir Goldstein }
352ffa5723cSAmir Goldstein
ovl_inode_upper(struct inode * inode)35309d8b586SMiklos Szeredi struct inode *ovl_inode_upper(struct inode *inode)
35425b7713aSMiklos Szeredi {
3551d88f183SMiklos Szeredi struct dentry *upperdentry = ovl_i_dentry_upper(inode);
35625b7713aSMiklos Szeredi
35709d8b586SMiklos Szeredi return upperdentry ? d_inode(upperdentry) : NULL;
35825b7713aSMiklos Szeredi }
35925b7713aSMiklos Szeredi
ovl_inode_lower(struct inode * inode)36009d8b586SMiklos Szeredi struct inode *ovl_inode_lower(struct inode *inode)
36109d8b586SMiklos Szeredi {
362ac900ed4SAmir Goldstein struct ovl_path *lowerpath = ovl_lowerpath(OVL_I_E(inode));
363ffa5723cSAmir Goldstein
364ac900ed4SAmir Goldstein return lowerpath ? d_inode(lowerpath->dentry) : NULL;
36509d8b586SMiklos Szeredi }
36609d8b586SMiklos Szeredi
ovl_inode_real(struct inode * inode)36709d8b586SMiklos Szeredi struct inode *ovl_inode_real(struct inode *inode)
36809d8b586SMiklos Szeredi {
36909d8b586SMiklos Szeredi return ovl_inode_upper(inode) ?: ovl_inode_lower(inode);
37009d8b586SMiklos Szeredi }
37109d8b586SMiklos Szeredi
3722664bd08SVivek Goyal /* Return inode which contains lower data. Do not return metacopy */
ovl_inode_lowerdata(struct inode * inode)3732664bd08SVivek Goyal struct inode *ovl_inode_lowerdata(struct inode *inode)
3742664bd08SVivek Goyal {
375ab1eb5ffSAmir Goldstein struct dentry *lowerdata = ovl_lowerdata_dentry(OVL_I_E(inode));
376ab1eb5ffSAmir Goldstein
3772664bd08SVivek Goyal if (WARN_ON(!S_ISREG(inode->i_mode)))
3782664bd08SVivek Goyal return NULL;
3792664bd08SVivek Goyal
380ab1eb5ffSAmir Goldstein return lowerdata ? d_inode(lowerdata) : NULL;
3812664bd08SVivek Goyal }
38209d8b586SMiklos Szeredi
3834823d49cSVivek Goyal /* Return real inode which contains data. Does not return metacopy inode */
ovl_inode_realdata(struct inode * inode)3844823d49cSVivek Goyal struct inode *ovl_inode_realdata(struct inode *inode)
3854823d49cSVivek Goyal {
3864823d49cSVivek Goyal struct inode *upperinode;
3874823d49cSVivek Goyal
3884823d49cSVivek Goyal upperinode = ovl_inode_upper(inode);
3894823d49cSVivek Goyal if (upperinode && ovl_has_upperdata(inode))
3904823d49cSVivek Goyal return upperinode;
3914823d49cSVivek Goyal
3924823d49cSVivek Goyal return ovl_inode_lowerdata(inode);
3934823d49cSVivek Goyal }
3944823d49cSVivek Goyal
ovl_lowerdata_redirect(struct inode * inode)3952b21da92SAmir Goldstein const char *ovl_lowerdata_redirect(struct inode *inode)
3962b21da92SAmir Goldstein {
3972b21da92SAmir Goldstein return inode && S_ISREG(inode->i_mode) ?
3982b21da92SAmir Goldstein OVL_I(inode)->lowerdata_redirect : NULL;
3992b21da92SAmir Goldstein }
4002b21da92SAmir Goldstein
ovl_dir_cache(struct inode * inode)4014edb83bbSMiklos Szeredi struct ovl_dir_cache *ovl_dir_cache(struct inode *inode)
402bbb1e54dSMiklos Szeredi {
4032b21da92SAmir Goldstein return inode && S_ISDIR(inode->i_mode) ? OVL_I(inode)->cache : NULL;
404bbb1e54dSMiklos Szeredi }
405bbb1e54dSMiklos Szeredi
ovl_set_dir_cache(struct inode * inode,struct ovl_dir_cache * cache)4064edb83bbSMiklos Szeredi void ovl_set_dir_cache(struct inode *inode, struct ovl_dir_cache *cache)
407bbb1e54dSMiklos Szeredi {
4084edb83bbSMiklos Szeredi OVL_I(inode)->cache = cache;
409bbb1e54dSMiklos Szeredi }
410bbb1e54dSMiklos Szeredi
ovl_dentry_set_flag(unsigned long flag,struct dentry * dentry)411c62520a8SAmir Goldstein void ovl_dentry_set_flag(unsigned long flag, struct dentry *dentry)
412c62520a8SAmir Goldstein {
413a6ff2bc0SAmir Goldstein set_bit(flag, OVL_E_FLAGS(dentry));
414c62520a8SAmir Goldstein }
415c62520a8SAmir Goldstein
ovl_dentry_clear_flag(unsigned long flag,struct dentry * dentry)416c62520a8SAmir Goldstein void ovl_dentry_clear_flag(unsigned long flag, struct dentry *dentry)
417c62520a8SAmir Goldstein {
418a6ff2bc0SAmir Goldstein clear_bit(flag, OVL_E_FLAGS(dentry));
419c62520a8SAmir Goldstein }
420c62520a8SAmir Goldstein
ovl_dentry_test_flag(unsigned long flag,struct dentry * dentry)421c62520a8SAmir Goldstein bool ovl_dentry_test_flag(unsigned long flag, struct dentry *dentry)
422c62520a8SAmir Goldstein {
423a6ff2bc0SAmir Goldstein return test_bit(flag, OVL_E_FLAGS(dentry));
424c62520a8SAmir Goldstein }
425c62520a8SAmir Goldstein
ovl_dentry_is_opaque(struct dentry * dentry)426bbb1e54dSMiklos Szeredi bool ovl_dentry_is_opaque(struct dentry *dentry)
427bbb1e54dSMiklos Szeredi {
428c62520a8SAmir Goldstein return ovl_dentry_test_flag(OVL_E_OPAQUE, dentry);
429bbb1e54dSMiklos Szeredi }
430bbb1e54dSMiklos Szeredi
ovl_dentry_is_whiteout(struct dentry * dentry)431bbb1e54dSMiklos Szeredi bool ovl_dentry_is_whiteout(struct dentry *dentry)
432bbb1e54dSMiklos Szeredi {
433bbb1e54dSMiklos Szeredi return !dentry->d_inode && ovl_dentry_is_opaque(dentry);
434bbb1e54dSMiklos Szeredi }
435bbb1e54dSMiklos Szeredi
ovl_dentry_set_opaque(struct dentry * dentry)4365cf5b477SMiklos Szeredi void ovl_dentry_set_opaque(struct dentry *dentry)
437bbb1e54dSMiklos Szeredi {
438c62520a8SAmir Goldstein ovl_dentry_set_flag(OVL_E_OPAQUE, dentry);
439bbb1e54dSMiklos Szeredi }
440bbb1e54dSMiklos Szeredi
44155acc661SMiklos Szeredi /*
442aa3ff3c1SAmir Goldstein * For hard links and decoded file handles, it's possible for ovl_dentry_upper()
443aa3ff3c1SAmir Goldstein * to return positive, while there's no actual upper alias for the inode.
444aa3ff3c1SAmir Goldstein * Copy up code needs to know about the existence of the upper alias, so it
445aa3ff3c1SAmir Goldstein * can't use ovl_dentry_upper().
44655acc661SMiklos Szeredi */
ovl_dentry_has_upper_alias(struct dentry * dentry)44755acc661SMiklos Szeredi bool ovl_dentry_has_upper_alias(struct dentry *dentry)
44855acc661SMiklos Szeredi {
449c62520a8SAmir Goldstein return ovl_dentry_test_flag(OVL_E_UPPER_ALIAS, dentry);
45055acc661SMiklos Szeredi }
45155acc661SMiklos Szeredi
ovl_dentry_set_upper_alias(struct dentry * dentry)45255acc661SMiklos Szeredi void ovl_dentry_set_upper_alias(struct dentry *dentry)
45355acc661SMiklos Szeredi {
454c62520a8SAmir Goldstein ovl_dentry_set_flag(OVL_E_UPPER_ALIAS, dentry);
45555acc661SMiklos Szeredi }
45655acc661SMiklos Szeredi
ovl_should_check_upperdata(struct inode * inode)4570c288874SVivek Goyal static bool ovl_should_check_upperdata(struct inode *inode)
4580c288874SVivek Goyal {
4590c288874SVivek Goyal if (!S_ISREG(inode->i_mode))
4600c288874SVivek Goyal return false;
4610c288874SVivek Goyal
4620c288874SVivek Goyal if (!ovl_inode_lower(inode))
4630c288874SVivek Goyal return false;
4640c288874SVivek Goyal
4650c288874SVivek Goyal return true;
4660c288874SVivek Goyal }
4670c288874SVivek Goyal
ovl_has_upperdata(struct inode * inode)4680c288874SVivek Goyal bool ovl_has_upperdata(struct inode *inode)
4690c288874SVivek Goyal {
4700c288874SVivek Goyal if (!ovl_should_check_upperdata(inode))
4710c288874SVivek Goyal return true;
4720c288874SVivek Goyal
4730c288874SVivek Goyal if (!ovl_test_flag(OVL_UPPERDATA, inode))
4740c288874SVivek Goyal return false;
4750c288874SVivek Goyal /*
4760c288874SVivek Goyal * Pairs with smp_wmb() in ovl_set_upperdata(). Main user of
4770c288874SVivek Goyal * ovl_has_upperdata() is ovl_copy_up_meta_inode_data(). Make sure
4780c288874SVivek Goyal * if setting of OVL_UPPERDATA is visible, then effects of writes
4790c288874SVivek Goyal * before that are visible too.
4800c288874SVivek Goyal */
4810c288874SVivek Goyal smp_rmb();
4820c288874SVivek Goyal return true;
4830c288874SVivek Goyal }
4840c288874SVivek Goyal
ovl_set_upperdata(struct inode * inode)4850c288874SVivek Goyal void ovl_set_upperdata(struct inode *inode)
4860c288874SVivek Goyal {
4870c288874SVivek Goyal /*
4880c288874SVivek Goyal * Pairs with smp_rmb() in ovl_has_upperdata(). Make sure
4890c288874SVivek Goyal * if OVL_UPPERDATA flag is visible, then effects of write operations
4900c288874SVivek Goyal * before it are visible as well.
4910c288874SVivek Goyal */
4920c288874SVivek Goyal smp_wmb();
4930c288874SVivek Goyal ovl_set_flag(OVL_UPPERDATA, inode);
4940c288874SVivek Goyal }
4950c288874SVivek Goyal
4960c288874SVivek Goyal /* Caller should hold ovl_inode->lock */
ovl_dentry_needs_data_copy_up_locked(struct dentry * dentry,int flags)4970c288874SVivek Goyal bool ovl_dentry_needs_data_copy_up_locked(struct dentry *dentry, int flags)
4980c288874SVivek Goyal {
4990c288874SVivek Goyal if (!ovl_open_flags_need_copy_up(flags))
5000c288874SVivek Goyal return false;
5010c288874SVivek Goyal
5020c288874SVivek Goyal return !ovl_test_flag(OVL_UPPERDATA, d_inode(dentry));
5030c288874SVivek Goyal }
5040c288874SVivek Goyal
ovl_dentry_needs_data_copy_up(struct dentry * dentry,int flags)5050c288874SVivek Goyal bool ovl_dentry_needs_data_copy_up(struct dentry *dentry, int flags)
5060c288874SVivek Goyal {
5070c288874SVivek Goyal if (!ovl_open_flags_need_copy_up(flags))
5080c288874SVivek Goyal return false;
5090c288874SVivek Goyal
5100c288874SVivek Goyal return !ovl_has_upperdata(d_inode(dentry));
5110c288874SVivek Goyal }
5120c288874SVivek Goyal
ovl_dentry_get_redirect(struct dentry * dentry)513a6c60655SMiklos Szeredi const char *ovl_dentry_get_redirect(struct dentry *dentry)
514a6c60655SMiklos Szeredi {
515cf31c463SMiklos Szeredi return OVL_I(d_inode(dentry))->redirect;
516a6c60655SMiklos Szeredi }
517a6c60655SMiklos Szeredi
ovl_dentry_set_redirect(struct dentry * dentry,const char * redirect)518a6c60655SMiklos Szeredi void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect)
519a6c60655SMiklos Szeredi {
520cf31c463SMiklos Szeredi struct ovl_inode *oi = OVL_I(d_inode(dentry));
521a6c60655SMiklos Szeredi
522cf31c463SMiklos Szeredi kfree(oi->redirect);
523cf31c463SMiklos Szeredi oi->redirect = redirect;
524a6c60655SMiklos Szeredi }
525a6c60655SMiklos Szeredi
ovl_inode_update(struct inode * inode,struct dentry * upperdentry)52609d8b586SMiklos Szeredi void ovl_inode_update(struct inode *inode, struct dentry *upperdentry)
527bbb1e54dSMiklos Szeredi {
52809d8b586SMiklos Szeredi struct inode *upperinode = d_inode(upperdentry);
529e6d2ebddSMiklos Szeredi
53009d8b586SMiklos Szeredi WARN_ON(OVL_I(inode)->__upperdentry);
53109d8b586SMiklos Szeredi
53225b7713aSMiklos Szeredi /*
53309d8b586SMiklos Szeredi * Make sure upperdentry is consistent before making it visible
53425b7713aSMiklos Szeredi */
53525b7713aSMiklos Szeredi smp_wmb();
53609d8b586SMiklos Szeredi OVL_I(inode)->__upperdentry = upperdentry;
53731747edaSAmir Goldstein if (inode_unhashed(inode)) {
53825b7713aSMiklos Szeredi inode->i_private = upperinode;
539bbb1e54dSMiklos Szeredi __insert_inode_hash(inode, (unsigned long) upperinode);
540bbb1e54dSMiklos Szeredi }
54125b7713aSMiklos Szeredi }
542bbb1e54dSMiklos Szeredi
ovl_dir_version_inc(struct dentry * dentry,bool impurity)54365cd913eSAmir Goldstein static void ovl_dir_version_inc(struct dentry *dentry, bool impurity)
544bbb1e54dSMiklos Szeredi {
54504a01ac7SMiklos Szeredi struct inode *inode = d_inode(dentry);
546bbb1e54dSMiklos Szeredi
54704a01ac7SMiklos Szeredi WARN_ON(!inode_is_locked(inode));
54865cd913eSAmir Goldstein WARN_ON(!d_is_dir(dentry));
5494edb83bbSMiklos Szeredi /*
55065cd913eSAmir Goldstein * Version is used by readdir code to keep cache consistent.
55165cd913eSAmir Goldstein * For merge dirs (or dirs with origin) all changes need to be noted.
55265cd913eSAmir Goldstein * For non-merge dirs, cache contains only impure entries (i.e. ones
55365cd913eSAmir Goldstein * which have been copied up and have origins), so only need to note
55465cd913eSAmir Goldstein * changes to impure entries.
5554edb83bbSMiklos Szeredi */
5561fa9c5c5SMiklos Szeredi if (!ovl_dir_is_real(inode) || impurity)
55704a01ac7SMiklos Szeredi OVL_I(inode)->version++;
558bbb1e54dSMiklos Szeredi }
559bbb1e54dSMiklos Szeredi
ovl_dir_modified(struct dentry * dentry,bool impurity)560d9854c87SMiklos Szeredi void ovl_dir_modified(struct dentry *dentry, bool impurity)
561d9854c87SMiklos Szeredi {
562d9854c87SMiklos Szeredi /* Copy mtime/ctime */
5632878dffcSChristian Brauner ovl_copyattr(d_inode(dentry));
564d9854c87SMiklos Szeredi
56565cd913eSAmir Goldstein ovl_dir_version_inc(dentry, impurity);
566d9854c87SMiklos Szeredi }
567d9854c87SMiklos Szeredi
ovl_inode_version_get(struct inode * inode)5681fa9c5c5SMiklos Szeredi u64 ovl_inode_version_get(struct inode *inode)
569bbb1e54dSMiklos Szeredi {
57004a01ac7SMiklos Szeredi WARN_ON(!inode_is_locked(inode));
57104a01ac7SMiklos Szeredi return OVL_I(inode)->version;
572bbb1e54dSMiklos Szeredi }
573bbb1e54dSMiklos Szeredi
ovl_is_whiteout(struct dentry * dentry)574bbb1e54dSMiklos Szeredi bool ovl_is_whiteout(struct dentry *dentry)
575bbb1e54dSMiklos Szeredi {
576bbb1e54dSMiklos Szeredi struct inode *inode = dentry->d_inode;
577bbb1e54dSMiklos Szeredi
578bbb1e54dSMiklos Szeredi return inode && IS_WHITEOUT(inode);
579bbb1e54dSMiklos Szeredi }
580bbb1e54dSMiklos Szeredi
ovl_path_open(const struct path * path,int flags)5812d343087SAl Viro struct file *ovl_path_open(const struct path *path, int flags)
582bbb1e54dSMiklos Szeredi {
58356230d95SMiklos Szeredi struct inode *inode = d_inode(path->dentry);
5844609e1f1SChristian Brauner struct mnt_idmap *real_idmap = mnt_idmap(path->mnt);
58556230d95SMiklos Szeredi int err, acc_mode;
58656230d95SMiklos Szeredi
58756230d95SMiklos Szeredi if (flags & ~(O_ACCMODE | O_LARGEFILE))
58856230d95SMiklos Szeredi BUG();
58956230d95SMiklos Szeredi
59056230d95SMiklos Szeredi switch (flags & O_ACCMODE) {
59156230d95SMiklos Szeredi case O_RDONLY:
59256230d95SMiklos Szeredi acc_mode = MAY_READ;
59356230d95SMiklos Szeredi break;
59456230d95SMiklos Szeredi case O_WRONLY:
59556230d95SMiklos Szeredi acc_mode = MAY_WRITE;
59656230d95SMiklos Szeredi break;
59756230d95SMiklos Szeredi default:
59856230d95SMiklos Szeredi BUG();
59956230d95SMiklos Szeredi }
60056230d95SMiklos Szeredi
6014609e1f1SChristian Brauner err = inode_permission(real_idmap, inode, acc_mode | MAY_OPEN);
60256230d95SMiklos Szeredi if (err)
60356230d95SMiklos Szeredi return ERR_PTR(err);
60456230d95SMiklos Szeredi
60556230d95SMiklos Szeredi /* O_NOATIME is an optimization, don't fail if not permitted */
60601beba79SChristian Brauner if (inode_owner_or_capable(real_idmap, inode))
60756230d95SMiklos Szeredi flags |= O_NOATIME;
60856230d95SMiklos Szeredi
60956230d95SMiklos Szeredi return dentry_open(path, flags, current_cred());
610bbb1e54dSMiklos Szeredi }
61139d3d60aSAmir Goldstein
6120c288874SVivek Goyal /* Caller should hold ovl_inode->lock */
ovl_already_copied_up_locked(struct dentry * dentry,int flags)6130c288874SVivek Goyal static bool ovl_already_copied_up_locked(struct dentry *dentry, int flags)
6140c288874SVivek Goyal {
6150c288874SVivek Goyal bool disconnected = dentry->d_flags & DCACHE_DISCONNECTED;
6160c288874SVivek Goyal
6170c288874SVivek Goyal if (ovl_dentry_upper(dentry) &&
6180c288874SVivek Goyal (ovl_dentry_has_upper_alias(dentry) || disconnected) &&
6190c288874SVivek Goyal !ovl_dentry_needs_data_copy_up_locked(dentry, flags))
6200c288874SVivek Goyal return true;
6210c288874SVivek Goyal
6220c288874SVivek Goyal return false;
6230c288874SVivek Goyal }
6240c288874SVivek Goyal
ovl_already_copied_up(struct dentry * dentry,int flags)6250c288874SVivek Goyal bool ovl_already_copied_up(struct dentry *dentry, int flags)
6262002df85SVivek Goyal {
6272002df85SVivek Goyal bool disconnected = dentry->d_flags & DCACHE_DISCONNECTED;
6282002df85SVivek Goyal
6292002df85SVivek Goyal /*
6302002df85SVivek Goyal * Check if copy-up has happened as well as for upper alias (in
6312002df85SVivek Goyal * case of hard links) is there.
6322002df85SVivek Goyal *
6332002df85SVivek Goyal * Both checks are lockless:
6342002df85SVivek Goyal * - false negatives: will recheck under oi->lock
6352002df85SVivek Goyal * - false positives:
6362002df85SVivek Goyal * + ovl_dentry_upper() uses memory barriers to ensure the
6372002df85SVivek Goyal * upper dentry is up-to-date
6382002df85SVivek Goyal * + ovl_dentry_has_upper_alias() relies on locking of
6392002df85SVivek Goyal * upper parent i_rwsem to prevent reordering copy-up
6402002df85SVivek Goyal * with rename.
6412002df85SVivek Goyal */
6422002df85SVivek Goyal if (ovl_dentry_upper(dentry) &&
6430c288874SVivek Goyal (ovl_dentry_has_upper_alias(dentry) || disconnected) &&
6440c288874SVivek Goyal !ovl_dentry_needs_data_copy_up(dentry, flags))
6452002df85SVivek Goyal return true;
6462002df85SVivek Goyal
6472002df85SVivek Goyal return false;
6482002df85SVivek Goyal }
6492002df85SVivek Goyal
ovl_copy_up_start(struct dentry * dentry,int flags)6500c288874SVivek Goyal int ovl_copy_up_start(struct dentry *dentry, int flags)
65139d3d60aSAmir Goldstein {
6521e92e307SAmir Goldstein struct inode *inode = d_inode(dentry);
65339d3d60aSAmir Goldstein int err;
65439d3d60aSAmir Goldstein
655531d3040SAmir Goldstein err = ovl_inode_lock_interruptible(inode);
6560c288874SVivek Goyal if (!err && ovl_already_copied_up_locked(dentry, flags)) {
65739d3d60aSAmir Goldstein err = 1; /* Already copied up */
6581e92e307SAmir Goldstein ovl_inode_unlock(inode);
65939d3d60aSAmir Goldstein }
66039d3d60aSAmir Goldstein
66139d3d60aSAmir Goldstein return err;
66239d3d60aSAmir Goldstein }
66339d3d60aSAmir Goldstein
ovl_copy_up_end(struct dentry * dentry)66439d3d60aSAmir Goldstein void ovl_copy_up_end(struct dentry *dentry)
66539d3d60aSAmir Goldstein {
6661e92e307SAmir Goldstein ovl_inode_unlock(d_inode(dentry));
66739d3d60aSAmir Goldstein }
66882b749b2SAmir Goldstein
ovl_path_check_origin_xattr(struct ovl_fs * ofs,const struct path * path)6692d343087SAl Viro bool ovl_path_check_origin_xattr(struct ovl_fs *ofs, const struct path *path)
670b79e05aaSAmir Goldstein {
671b79e05aaSAmir Goldstein int res;
672b79e05aaSAmir Goldstein
673dad7017aSChristian Brauner res = ovl_path_getxattr(ofs, path, OVL_XATTR_ORIGIN, NULL, 0);
674b79e05aaSAmir Goldstein
675b79e05aaSAmir Goldstein /* Zero size value means "copied up but origin unknown" */
676b79e05aaSAmir Goldstein if (res >= 0)
677b79e05aaSAmir Goldstein return true;
678b79e05aaSAmir Goldstein
679b79e05aaSAmir Goldstein return false;
680b79e05aaSAmir Goldstein }
681b79e05aaSAmir Goldstein
682d9544c1bSAmir Goldstein /*
683d9544c1bSAmir Goldstein * Load persistent uuid from xattr into s_uuid if found, or store a new
684d9544c1bSAmir Goldstein * random generated value in s_uuid and in xattr.
685d9544c1bSAmir Goldstein */
ovl_init_uuid_xattr(struct super_block * sb,struct ovl_fs * ofs,const struct path * upperpath)686d9544c1bSAmir Goldstein bool ovl_init_uuid_xattr(struct super_block *sb, struct ovl_fs *ofs,
687d9544c1bSAmir Goldstein const struct path *upperpath)
688d9544c1bSAmir Goldstein {
689d9544c1bSAmir Goldstein bool set = false;
690d9544c1bSAmir Goldstein int res;
691d9544c1bSAmir Goldstein
692d9544c1bSAmir Goldstein /* Try to load existing persistent uuid */
693d9544c1bSAmir Goldstein res = ovl_path_getxattr(ofs, upperpath, OVL_XATTR_UUID, sb->s_uuid.b,
694d9544c1bSAmir Goldstein UUID_SIZE);
695d9544c1bSAmir Goldstein if (res == UUID_SIZE)
696d9544c1bSAmir Goldstein return true;
697d9544c1bSAmir Goldstein
698d9544c1bSAmir Goldstein if (res != -ENODATA)
699d9544c1bSAmir Goldstein goto fail;
700d9544c1bSAmir Goldstein
701cbb44f09SAmir Goldstein /*
702cbb44f09SAmir Goldstein * With uuid=auto, if uuid xattr is found, it will be used.
703cbb44f09SAmir Goldstein * If uuid xattrs is not found, generate a persistent uuid only on mount
704cbb44f09SAmir Goldstein * of new overlays where upper root dir is not yet marked as impure.
705cbb44f09SAmir Goldstein * An upper dir is marked as impure on copy up or lookup of its subdirs.
706cbb44f09SAmir Goldstein */
707cbb44f09SAmir Goldstein if (ofs->config.uuid == OVL_UUID_AUTO) {
708cbb44f09SAmir Goldstein res = ovl_path_getxattr(ofs, upperpath, OVL_XATTR_IMPURE, NULL,
709cbb44f09SAmir Goldstein 0);
710cbb44f09SAmir Goldstein if (res > 0) {
711cbb44f09SAmir Goldstein /* Any mount of old overlay - downgrade to uuid=null */
712cbb44f09SAmir Goldstein ofs->config.uuid = OVL_UUID_NULL;
713cbb44f09SAmir Goldstein return true;
714cbb44f09SAmir Goldstein } else if (res == -ENODATA) {
715cbb44f09SAmir Goldstein /* First mount of new overlay - upgrade to uuid=on */
716cbb44f09SAmir Goldstein ofs->config.uuid = OVL_UUID_ON;
717cbb44f09SAmir Goldstein } else if (res < 0) {
718cbb44f09SAmir Goldstein goto fail;
719cbb44f09SAmir Goldstein }
720cbb44f09SAmir Goldstein
721cbb44f09SAmir Goldstein }
722cbb44f09SAmir Goldstein
723d9544c1bSAmir Goldstein /* Generate overlay instance uuid */
724d9544c1bSAmir Goldstein uuid_gen(&sb->s_uuid);
725d9544c1bSAmir Goldstein
726d9544c1bSAmir Goldstein /* Try to store persistent uuid */
727d9544c1bSAmir Goldstein set = true;
728d9544c1bSAmir Goldstein res = ovl_setxattr(ofs, upperpath->dentry, OVL_XATTR_UUID, sb->s_uuid.b,
729d9544c1bSAmir Goldstein UUID_SIZE);
730d9544c1bSAmir Goldstein if (res == 0)
731d9544c1bSAmir Goldstein return true;
732d9544c1bSAmir Goldstein
733d9544c1bSAmir Goldstein fail:
734d9544c1bSAmir Goldstein memset(sb->s_uuid.b, 0, UUID_SIZE);
735d9544c1bSAmir Goldstein ofs->config.uuid = OVL_UUID_NULL;
736d9544c1bSAmir Goldstein pr_warn("failed to %s uuid (%pd2, err=%i); falling back to uuid=null.\n",
737d9544c1bSAmir Goldstein set ? "set" : "get", upperpath->dentry, res);
738d9544c1bSAmir Goldstein return false;
739d9544c1bSAmir Goldstein }
740d9544c1bSAmir Goldstein
ovl_path_check_dir_xattr(struct ovl_fs * ofs,const struct path * path,enum ovl_xattr ox)7412d343087SAl Viro bool ovl_path_check_dir_xattr(struct ovl_fs *ofs, const struct path *path,
74243d193f8SMiklos Szeredi enum ovl_xattr ox)
743f3a15685SAmir Goldstein {
744f3a15685SAmir Goldstein int res;
745f3a15685SAmir Goldstein char val;
746f3a15685SAmir Goldstein
747dad7017aSChristian Brauner if (!d_is_dir(path->dentry))
748f3a15685SAmir Goldstein return false;
749f3a15685SAmir Goldstein
750dad7017aSChristian Brauner res = ovl_path_getxattr(ofs, path, ox, &val, 1);
751f3a15685SAmir Goldstein if (res == 1 && val == 'y')
752f3a15685SAmir Goldstein return true;
753f3a15685SAmir Goldstein
754f3a15685SAmir Goldstein return false;
755f3a15685SAmir Goldstein }
756f3a15685SAmir Goldstein
75743d193f8SMiklos Szeredi #define OVL_XATTR_OPAQUE_POSTFIX "opaque"
75843d193f8SMiklos Szeredi #define OVL_XATTR_REDIRECT_POSTFIX "redirect"
75943d193f8SMiklos Szeredi #define OVL_XATTR_ORIGIN_POSTFIX "origin"
76043d193f8SMiklos Szeredi #define OVL_XATTR_IMPURE_POSTFIX "impure"
76143d193f8SMiklos Szeredi #define OVL_XATTR_NLINK_POSTFIX "nlink"
76243d193f8SMiklos Szeredi #define OVL_XATTR_UPPER_POSTFIX "upper"
763d9544c1bSAmir Goldstein #define OVL_XATTR_UUID_POSTFIX "uuid"
76443d193f8SMiklos Szeredi #define OVL_XATTR_METACOPY_POSTFIX "metacopy"
765096a218aSAmir Goldstein #define OVL_XATTR_PROTATTR_POSTFIX "protattr"
76643d193f8SMiklos Szeredi
76743d193f8SMiklos Szeredi #define OVL_XATTR_TAB_ENTRY(x) \
7682d2f2d73SMiklos Szeredi [x] = { [false] = OVL_XATTR_TRUSTED_PREFIX x ## _POSTFIX, \
7692d2f2d73SMiklos Szeredi [true] = OVL_XATTR_USER_PREFIX x ## _POSTFIX }
77043d193f8SMiklos Szeredi
7712d2f2d73SMiklos Szeredi const char *const ovl_xattr_table[][2] = {
77243d193f8SMiklos Szeredi OVL_XATTR_TAB_ENTRY(OVL_XATTR_OPAQUE),
77343d193f8SMiklos Szeredi OVL_XATTR_TAB_ENTRY(OVL_XATTR_REDIRECT),
77443d193f8SMiklos Szeredi OVL_XATTR_TAB_ENTRY(OVL_XATTR_ORIGIN),
77543d193f8SMiklos Szeredi OVL_XATTR_TAB_ENTRY(OVL_XATTR_IMPURE),
77643d193f8SMiklos Szeredi OVL_XATTR_TAB_ENTRY(OVL_XATTR_NLINK),
77743d193f8SMiklos Szeredi OVL_XATTR_TAB_ENTRY(OVL_XATTR_UPPER),
778d9544c1bSAmir Goldstein OVL_XATTR_TAB_ENTRY(OVL_XATTR_UUID),
77943d193f8SMiklos Szeredi OVL_XATTR_TAB_ENTRY(OVL_XATTR_METACOPY),
780096a218aSAmir Goldstein OVL_XATTR_TAB_ENTRY(OVL_XATTR_PROTATTR),
78143d193f8SMiklos Szeredi };
78243d193f8SMiklos Szeredi
ovl_check_setxattr(struct ovl_fs * ofs,struct dentry * upperdentry,enum ovl_xattr ox,const void * value,size_t size,int xerr)783a0c236b1SAmir Goldstein int ovl_check_setxattr(struct ovl_fs *ofs, struct dentry *upperdentry,
78443d193f8SMiklos Szeredi enum ovl_xattr ox, const void *value, size_t size,
78582b749b2SAmir Goldstein int xerr)
78682b749b2SAmir Goldstein {
78782b749b2SAmir Goldstein int err;
78882b749b2SAmir Goldstein
78982b749b2SAmir Goldstein if (ofs->noxattr)
79082b749b2SAmir Goldstein return xerr;
79182b749b2SAmir Goldstein
792c914c0e2SAmir Goldstein err = ovl_setxattr(ofs, upperdentry, ox, value, size);
79382b749b2SAmir Goldstein
79482b749b2SAmir Goldstein if (err == -EOPNOTSUPP) {
79543d193f8SMiklos Szeredi pr_warn("cannot set %s xattr on upper\n", ovl_xattr(ofs, ox));
79682b749b2SAmir Goldstein ofs->noxattr = true;
79782b749b2SAmir Goldstein return xerr;
79882b749b2SAmir Goldstein }
79982b749b2SAmir Goldstein
80082b749b2SAmir Goldstein return err;
80182b749b2SAmir Goldstein }
802f3a15685SAmir Goldstein
ovl_set_impure(struct dentry * dentry,struct dentry * upperdentry)803f3a15685SAmir Goldstein int ovl_set_impure(struct dentry *dentry, struct dentry *upperdentry)
804f3a15685SAmir Goldstein {
805a0c236b1SAmir Goldstein struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
806f3a15685SAmir Goldstein int err;
807f3a15685SAmir Goldstein
80813c72075SMiklos Szeredi if (ovl_test_flag(OVL_IMPURE, d_inode(dentry)))
809f3a15685SAmir Goldstein return 0;
810f3a15685SAmir Goldstein
811f3a15685SAmir Goldstein /*
812f3a15685SAmir Goldstein * Do not fail when upper doesn't support xattrs.
813f3a15685SAmir Goldstein * Upper inodes won't have origin nor redirect xattr anyway.
814f3a15685SAmir Goldstein */
815a0c236b1SAmir Goldstein err = ovl_check_setxattr(ofs, upperdentry, OVL_XATTR_IMPURE, "y", 1, 0);
816f3a15685SAmir Goldstein if (!err)
81713c72075SMiklos Szeredi ovl_set_flag(OVL_IMPURE, d_inode(dentry));
818f3a15685SAmir Goldstein
819f3a15685SAmir Goldstein return err;
820f3a15685SAmir Goldstein }
82113c72075SMiklos Szeredi
822096a218aSAmir Goldstein
823096a218aSAmir Goldstein #define OVL_PROTATTR_MAX 32 /* Reserved for future flags */
824096a218aSAmir Goldstein
ovl_check_protattr(struct inode * inode,struct dentry * upper)825096a218aSAmir Goldstein void ovl_check_protattr(struct inode *inode, struct dentry *upper)
826096a218aSAmir Goldstein {
827096a218aSAmir Goldstein struct ovl_fs *ofs = OVL_FS(inode->i_sb);
828096a218aSAmir Goldstein u32 iflags = inode->i_flags & OVL_PROT_I_FLAGS_MASK;
829096a218aSAmir Goldstein char buf[OVL_PROTATTR_MAX+1];
830096a218aSAmir Goldstein int res, n;
831096a218aSAmir Goldstein
832dad7017aSChristian Brauner res = ovl_getxattr_upper(ofs, upper, OVL_XATTR_PROTATTR, buf,
833096a218aSAmir Goldstein OVL_PROTATTR_MAX);
834096a218aSAmir Goldstein if (res < 0)
835096a218aSAmir Goldstein return;
836096a218aSAmir Goldstein
837096a218aSAmir Goldstein /*
838096a218aSAmir Goldstein * Initialize inode flags from overlay.protattr xattr and upper inode
839096a218aSAmir Goldstein * flags. If upper inode has those fileattr flags set (i.e. from old
840096a218aSAmir Goldstein * kernel), we do not clear them on ovl_get_inode(), but we will clear
841096a218aSAmir Goldstein * them on next fileattr_set().
842096a218aSAmir Goldstein */
843096a218aSAmir Goldstein for (n = 0; n < res; n++) {
844096a218aSAmir Goldstein if (buf[n] == 'a')
845096a218aSAmir Goldstein iflags |= S_APPEND;
846096a218aSAmir Goldstein else if (buf[n] == 'i')
847096a218aSAmir Goldstein iflags |= S_IMMUTABLE;
848096a218aSAmir Goldstein else
849096a218aSAmir Goldstein break;
850096a218aSAmir Goldstein }
851096a218aSAmir Goldstein
852096a218aSAmir Goldstein if (!res || n < res) {
853096a218aSAmir Goldstein pr_warn_ratelimited("incompatible overlay.protattr format (%pd2, len=%d)\n",
854096a218aSAmir Goldstein upper, res);
855096a218aSAmir Goldstein } else {
856096a218aSAmir Goldstein inode_set_flags(inode, iflags, OVL_PROT_I_FLAGS_MASK);
857096a218aSAmir Goldstein }
858096a218aSAmir Goldstein }
859096a218aSAmir Goldstein
ovl_set_protattr(struct inode * inode,struct dentry * upper,struct fileattr * fa)860096a218aSAmir Goldstein int ovl_set_protattr(struct inode *inode, struct dentry *upper,
861096a218aSAmir Goldstein struct fileattr *fa)
862096a218aSAmir Goldstein {
863096a218aSAmir Goldstein struct ovl_fs *ofs = OVL_FS(inode->i_sb);
864096a218aSAmir Goldstein char buf[OVL_PROTATTR_MAX];
865096a218aSAmir Goldstein int len = 0, err = 0;
866096a218aSAmir Goldstein u32 iflags = 0;
867096a218aSAmir Goldstein
868096a218aSAmir Goldstein BUILD_BUG_ON(HWEIGHT32(OVL_PROT_FS_FLAGS_MASK) > OVL_PROTATTR_MAX);
869096a218aSAmir Goldstein
870096a218aSAmir Goldstein if (fa->flags & FS_APPEND_FL) {
871096a218aSAmir Goldstein buf[len++] = 'a';
872096a218aSAmir Goldstein iflags |= S_APPEND;
873096a218aSAmir Goldstein }
874096a218aSAmir Goldstein if (fa->flags & FS_IMMUTABLE_FL) {
875096a218aSAmir Goldstein buf[len++] = 'i';
876096a218aSAmir Goldstein iflags |= S_IMMUTABLE;
877096a218aSAmir Goldstein }
878096a218aSAmir Goldstein
879096a218aSAmir Goldstein /*
880096a218aSAmir Goldstein * Do not allow to set protection flags when upper doesn't support
881096a218aSAmir Goldstein * xattrs, because we do not set those fileattr flags on upper inode.
882096a218aSAmir Goldstein * Remove xattr if it exist and all protection flags are cleared.
883096a218aSAmir Goldstein */
884096a218aSAmir Goldstein if (len) {
885096a218aSAmir Goldstein err = ovl_check_setxattr(ofs, upper, OVL_XATTR_PROTATTR,
886096a218aSAmir Goldstein buf, len, -EPERM);
887096a218aSAmir Goldstein } else if (inode->i_flags & OVL_PROT_I_FLAGS_MASK) {
888c914c0e2SAmir Goldstein err = ovl_removexattr(ofs, upper, OVL_XATTR_PROTATTR);
889096a218aSAmir Goldstein if (err == -EOPNOTSUPP || err == -ENODATA)
890096a218aSAmir Goldstein err = 0;
891096a218aSAmir Goldstein }
892096a218aSAmir Goldstein if (err)
893096a218aSAmir Goldstein return err;
894096a218aSAmir Goldstein
895096a218aSAmir Goldstein inode_set_flags(inode, iflags, OVL_PROT_I_FLAGS_MASK);
896096a218aSAmir Goldstein
897096a218aSAmir Goldstein /* Mask out the fileattr flags that should not be set in upper inode */
898096a218aSAmir Goldstein fa->flags &= ~OVL_PROT_FS_FLAGS_MASK;
899096a218aSAmir Goldstein fa->fsx_xflags &= ~OVL_PROT_FSX_FLAGS_MASK;
900096a218aSAmir Goldstein
901096a218aSAmir Goldstein return 0;
902096a218aSAmir Goldstein }
903096a218aSAmir Goldstein
904ad0af710SAmir Goldstein /**
905ad0af710SAmir Goldstein * Caller must hold a reference to inode to prevent it from being freed while
906ad0af710SAmir Goldstein * it is marked inuse.
907ad0af710SAmir Goldstein */
ovl_inuse_trylock(struct dentry * dentry)908ad0af710SAmir Goldstein bool ovl_inuse_trylock(struct dentry *dentry)
909ad0af710SAmir Goldstein {
910ad0af710SAmir Goldstein struct inode *inode = d_inode(dentry);
911ad0af710SAmir Goldstein bool locked = false;
912ad0af710SAmir Goldstein
913ad0af710SAmir Goldstein spin_lock(&inode->i_lock);
914ad0af710SAmir Goldstein if (!(inode->i_state & I_OVL_INUSE)) {
915ad0af710SAmir Goldstein inode->i_state |= I_OVL_INUSE;
916ad0af710SAmir Goldstein locked = true;
917ad0af710SAmir Goldstein }
918ad0af710SAmir Goldstein spin_unlock(&inode->i_lock);
919ad0af710SAmir Goldstein
920ad0af710SAmir Goldstein return locked;
921ad0af710SAmir Goldstein }
922ad0af710SAmir Goldstein
ovl_inuse_unlock(struct dentry * dentry)923ad0af710SAmir Goldstein void ovl_inuse_unlock(struct dentry *dentry)
924ad0af710SAmir Goldstein {
925ad0af710SAmir Goldstein if (dentry) {
926ad0af710SAmir Goldstein struct inode *inode = d_inode(dentry);
927ad0af710SAmir Goldstein
928ad0af710SAmir Goldstein spin_lock(&inode->i_lock);
929ad0af710SAmir Goldstein WARN_ON(!(inode->i_state & I_OVL_INUSE));
930ad0af710SAmir Goldstein inode->i_state &= ~I_OVL_INUSE;
931ad0af710SAmir Goldstein spin_unlock(&inode->i_lock);
932ad0af710SAmir Goldstein }
933ad0af710SAmir Goldstein }
9345f8415d6SAmir Goldstein
ovl_is_inuse(struct dentry * dentry)935146d62e5SAmir Goldstein bool ovl_is_inuse(struct dentry *dentry)
936146d62e5SAmir Goldstein {
937146d62e5SAmir Goldstein struct inode *inode = d_inode(dentry);
938146d62e5SAmir Goldstein bool inuse;
939146d62e5SAmir Goldstein
940146d62e5SAmir Goldstein spin_lock(&inode->i_lock);
941146d62e5SAmir Goldstein inuse = (inode->i_state & I_OVL_INUSE);
942146d62e5SAmir Goldstein spin_unlock(&inode->i_lock);
943146d62e5SAmir Goldstein
944146d62e5SAmir Goldstein return inuse;
945146d62e5SAmir Goldstein }
946146d62e5SAmir Goldstein
94724b33ee1SAmir Goldstein /*
94824b33ee1SAmir Goldstein * Does this overlay dentry need to be indexed on copy up?
94924b33ee1SAmir Goldstein */
ovl_need_index(struct dentry * dentry)95024b33ee1SAmir Goldstein bool ovl_need_index(struct dentry *dentry)
95124b33ee1SAmir Goldstein {
95224b33ee1SAmir Goldstein struct dentry *lower = ovl_dentry_lower(dentry);
95324b33ee1SAmir Goldstein
95424b33ee1SAmir Goldstein if (!lower || !ovl_indexdir(dentry->d_sb))
95524b33ee1SAmir Goldstein return false;
95624b33ee1SAmir Goldstein
957fbd2d207SAmir Goldstein /* Index all files for NFS export and consistency verification */
958016b720fSAmir Goldstein if (ovl_index_all(dentry->d_sb))
959fbd2d207SAmir Goldstein return true;
960fbd2d207SAmir Goldstein
96124b33ee1SAmir Goldstein /* Index only lower hardlinks on copy up */
96224b33ee1SAmir Goldstein if (!d_is_dir(lower) && d_inode(lower)->i_nlink > 1)
96324b33ee1SAmir Goldstein return true;
96424b33ee1SAmir Goldstein
96524b33ee1SAmir Goldstein return false;
96624b33ee1SAmir Goldstein }
96724b33ee1SAmir Goldstein
9689f4ec904SAmir Goldstein /* Caller must hold OVL_I(inode)->lock */
ovl_cleanup_index(struct dentry * dentry)969caf70cb2SAmir Goldstein static void ovl_cleanup_index(struct dentry *dentry)
970caf70cb2SAmir Goldstein {
9711cdb0cb6SPavel Tikhomirov struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
972e7dd0e71SAmir Goldstein struct dentry *indexdir = ovl_indexdir(dentry->d_sb);
973e7dd0e71SAmir Goldstein struct inode *dir = indexdir->d_inode;
974caf70cb2SAmir Goldstein struct dentry *lowerdentry = ovl_dentry_lower(dentry);
975caf70cb2SAmir Goldstein struct dentry *upperdentry = ovl_dentry_upper(dentry);
976caf70cb2SAmir Goldstein struct dentry *index = NULL;
977caf70cb2SAmir Goldstein struct inode *inode;
97863e13252SAmir Goldstein struct qstr name = { };
979caf70cb2SAmir Goldstein int err;
980caf70cb2SAmir Goldstein
9811cdb0cb6SPavel Tikhomirov err = ovl_get_index_name(ofs, lowerdentry, &name);
982caf70cb2SAmir Goldstein if (err)
983caf70cb2SAmir Goldstein goto fail;
984caf70cb2SAmir Goldstein
985caf70cb2SAmir Goldstein inode = d_inode(upperdentry);
98689a17556SAmir Goldstein if (!S_ISDIR(inode->i_mode) && inode->i_nlink != 1) {
9871bd0a3aeSlijiazi pr_warn_ratelimited("cleanup linked index (%pd2, ino=%lu, nlink=%u)\n",
988caf70cb2SAmir Goldstein upperdentry, inode->i_ino, inode->i_nlink);
989caf70cb2SAmir Goldstein /*
990caf70cb2SAmir Goldstein * We either have a bug with persistent union nlink or a lower
991caf70cb2SAmir Goldstein * hardlink was added while overlay is mounted. Adding a lower
992caf70cb2SAmir Goldstein * hardlink and then unlinking all overlay hardlinks would drop
993caf70cb2SAmir Goldstein * overlay nlink to zero before all upper inodes are unlinked.
994caf70cb2SAmir Goldstein * As a safety measure, when that situation is detected, set
995caf70cb2SAmir Goldstein * the overlay nlink to the index inode nlink minus one for the
996caf70cb2SAmir Goldstein * index entry itself.
997caf70cb2SAmir Goldstein */
998caf70cb2SAmir Goldstein set_nlink(d_inode(dentry), inode->i_nlink - 1);
999caf70cb2SAmir Goldstein ovl_set_nlink_upper(dentry);
1000caf70cb2SAmir Goldstein goto out;
1001caf70cb2SAmir Goldstein }
1002caf70cb2SAmir Goldstein
1003caf70cb2SAmir Goldstein inode_lock_nested(dir, I_MUTEX_PARENT);
100422f289ceSChristian Brauner index = ovl_lookup_upper(ofs, name.name, indexdir, name.len);
1005caf70cb2SAmir Goldstein err = PTR_ERR(index);
1006e7dd0e71SAmir Goldstein if (IS_ERR(index)) {
10079f4ec904SAmir Goldstein index = NULL;
1008e7dd0e71SAmir Goldstein } else if (ovl_index_all(dentry->d_sb)) {
1009e7dd0e71SAmir Goldstein /* Whiteout orphan index to block future open by handle */
1010c21c839bSChengguang Xu err = ovl_cleanup_and_whiteout(OVL_FS(dentry->d_sb),
1011c21c839bSChengguang Xu dir, index);
1012e7dd0e71SAmir Goldstein } else {
1013e7dd0e71SAmir Goldstein /* Cleanup orphan index entries */
1014576bb263SChristian Brauner err = ovl_cleanup(ofs, dir, index);
1015e7dd0e71SAmir Goldstein }
10169f4ec904SAmir Goldstein
1017caf70cb2SAmir Goldstein inode_unlock(dir);
1018caf70cb2SAmir Goldstein if (err)
1019caf70cb2SAmir Goldstein goto fail;
1020caf70cb2SAmir Goldstein
1021caf70cb2SAmir Goldstein out:
102263e13252SAmir Goldstein kfree(name.name);
1023caf70cb2SAmir Goldstein dput(index);
1024caf70cb2SAmir Goldstein return;
1025caf70cb2SAmir Goldstein
1026caf70cb2SAmir Goldstein fail:
10271bd0a3aeSlijiazi pr_err("cleanup index of '%pd2' failed (%i)\n", dentry, err);
1028caf70cb2SAmir Goldstein goto out;
1029caf70cb2SAmir Goldstein }
1030caf70cb2SAmir Goldstein
10315f8415d6SAmir Goldstein /*
10325f8415d6SAmir Goldstein * Operations that change overlay inode and upper inode nlink need to be
10335f8415d6SAmir Goldstein * synchronized with copy up for persistent nlink accounting.
10345f8415d6SAmir Goldstein */
ovl_nlink_start(struct dentry * dentry)10350e32992fSAmir Goldstein int ovl_nlink_start(struct dentry *dentry)
10365f8415d6SAmir Goldstein {
10371e92e307SAmir Goldstein struct inode *inode = d_inode(dentry);
10385f8415d6SAmir Goldstein const struct cred *old_cred;
10395f8415d6SAmir Goldstein int err;
10405f8415d6SAmir Goldstein
10411e92e307SAmir Goldstein if (WARN_ON(!inode))
10420e32992fSAmir Goldstein return -ENOENT;
10435f8415d6SAmir Goldstein
10445f8415d6SAmir Goldstein /*
10455f8415d6SAmir Goldstein * With inodes index is enabled, we store the union overlay nlink
104624b33ee1SAmir Goldstein * in an xattr on the index inode. When whiting out an indexed lower,
10475f8415d6SAmir Goldstein * we need to decrement the overlay persistent nlink, but before the
10485f8415d6SAmir Goldstein * first copy up, we have no upper index inode to store the xattr.
10495f8415d6SAmir Goldstein *
105024b33ee1SAmir Goldstein * As a workaround, before whiteout/rename over an indexed lower,
10515f8415d6SAmir Goldstein * copy up to create the upper index. Creating the upper index will
10525f8415d6SAmir Goldstein * initialize the overlay nlink, so it could be dropped if unlink
10535f8415d6SAmir Goldstein * or rename succeeds.
10545f8415d6SAmir Goldstein *
10555f8415d6SAmir Goldstein * TODO: implement metadata only index copy up when called with
10565f8415d6SAmir Goldstein * ovl_copy_up_flags(dentry, O_PATH).
10575f8415d6SAmir Goldstein */
105824b33ee1SAmir Goldstein if (ovl_need_index(dentry) && !ovl_dentry_has_upper_alias(dentry)) {
10595f8415d6SAmir Goldstein err = ovl_copy_up(dentry);
10605f8415d6SAmir Goldstein if (err)
10615f8415d6SAmir Goldstein return err;
10625f8415d6SAmir Goldstein }
10635f8415d6SAmir Goldstein
1064531d3040SAmir Goldstein err = ovl_inode_lock_interruptible(inode);
10655f8415d6SAmir Goldstein if (err)
10665f8415d6SAmir Goldstein return err;
10675f8415d6SAmir Goldstein
10681e92e307SAmir Goldstein if (d_is_dir(dentry) || !ovl_test_flag(OVL_INDEX, inode))
10695f8415d6SAmir Goldstein goto out;
10705f8415d6SAmir Goldstein
10715f8415d6SAmir Goldstein old_cred = ovl_override_creds(dentry->d_sb);
10725f8415d6SAmir Goldstein /*
10735f8415d6SAmir Goldstein * The overlay inode nlink should be incremented/decremented IFF the
10745f8415d6SAmir Goldstein * upper operation succeeds, along with nlink change of upper inode.
10755f8415d6SAmir Goldstein * Therefore, before link/unlink/rename, we store the union nlink
10765f8415d6SAmir Goldstein * value relative to the upper inode nlink in an upper inode xattr.
10775f8415d6SAmir Goldstein */
10785f8415d6SAmir Goldstein err = ovl_set_nlink_upper(dentry);
10795f8415d6SAmir Goldstein revert_creds(old_cred);
10805f8415d6SAmir Goldstein
10815f8415d6SAmir Goldstein out:
10825f8415d6SAmir Goldstein if (err)
10831e92e307SAmir Goldstein ovl_inode_unlock(inode);
10845f8415d6SAmir Goldstein
10855f8415d6SAmir Goldstein return err;
10865f8415d6SAmir Goldstein }
10875f8415d6SAmir Goldstein
ovl_nlink_end(struct dentry * dentry)10880e32992fSAmir Goldstein void ovl_nlink_end(struct dentry *dentry)
10895f8415d6SAmir Goldstein {
10901e92e307SAmir Goldstein struct inode *inode = d_inode(dentry);
10911e92e307SAmir Goldstein
10921e92e307SAmir Goldstein if (ovl_test_flag(OVL_INDEX, inode) && inode->i_nlink == 0) {
1093caf70cb2SAmir Goldstein const struct cred *old_cred;
1094caf70cb2SAmir Goldstein
1095caf70cb2SAmir Goldstein old_cred = ovl_override_creds(dentry->d_sb);
1096caf70cb2SAmir Goldstein ovl_cleanup_index(dentry);
1097caf70cb2SAmir Goldstein revert_creds(old_cred);
1098caf70cb2SAmir Goldstein }
1099caf70cb2SAmir Goldstein
11001e92e307SAmir Goldstein ovl_inode_unlock(inode);
11015f8415d6SAmir Goldstein }
11025820dc08SAmir Goldstein
ovl_lock_rename_workdir(struct dentry * workdir,struct dentry * upperdir)11035820dc08SAmir Goldstein int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir)
11045820dc08SAmir Goldstein {
11055820dc08SAmir Goldstein /* Workdir should not be the same as upperdir */
11065820dc08SAmir Goldstein if (workdir == upperdir)
11075820dc08SAmir Goldstein goto err;
11085820dc08SAmir Goldstein
11095820dc08SAmir Goldstein /* Workdir should not be subdir of upperdir and vice versa */
11105820dc08SAmir Goldstein if (lock_rename(workdir, upperdir) != NULL)
11115820dc08SAmir Goldstein goto err_unlock;
11125820dc08SAmir Goldstein
11135820dc08SAmir Goldstein return 0;
11145820dc08SAmir Goldstein
11155820dc08SAmir Goldstein err_unlock:
11165820dc08SAmir Goldstein unlock_rename(workdir, upperdir);
11175820dc08SAmir Goldstein err:
11181bd0a3aeSlijiazi pr_err("failed to lock workdir+upperdir\n");
11195820dc08SAmir Goldstein return -EIO;
11205820dc08SAmir Goldstein }
11219d3dfea3SVivek Goyal
1122bf070890SAlexander Larsson /*
1123bf070890SAlexander Larsson * err < 0, 0 if no metacopy xattr, metacopy data size if xattr found.
1124bf070890SAlexander Larsson * an empty xattr returns OVL_METACOPY_MIN_SIZE to distinguish from no xattr value.
1125bf070890SAlexander Larsson */
ovl_check_metacopy_xattr(struct ovl_fs * ofs,const struct path * path,struct ovl_metacopy * data)1126bf070890SAlexander Larsson int ovl_check_metacopy_xattr(struct ovl_fs *ofs, const struct path *path,
1127bf070890SAlexander Larsson struct ovl_metacopy *data)
11289d3dfea3SVivek Goyal {
11299d3dfea3SVivek Goyal int res;
11309d3dfea3SVivek Goyal
11319d3dfea3SVivek Goyal /* Only regular files can have metacopy xattr */
1132dad7017aSChristian Brauner if (!S_ISREG(d_inode(path->dentry)->i_mode))
11339d3dfea3SVivek Goyal return 0;
11349d3dfea3SVivek Goyal
1135bf070890SAlexander Larsson res = ovl_path_getxattr(ofs, path, OVL_XATTR_METACOPY,
1136bf070890SAlexander Larsson data, data ? OVL_METACOPY_MAX_SIZE : 0);
11379d3dfea3SVivek Goyal if (res < 0) {
11389d3dfea3SVivek Goyal if (res == -ENODATA || res == -EOPNOTSUPP)
11399d3dfea3SVivek Goyal return 0;
114087b2c60cSMiklos Szeredi /*
114187b2c60cSMiklos Szeredi * getxattr on user.* may fail with EACCES in case there's no
114287b2c60cSMiklos Szeredi * read permission on the inode. Not much we can do, other than
114387b2c60cSMiklos Szeredi * tell the caller that this is not a metacopy inode.
114487b2c60cSMiklos Szeredi */
114587b2c60cSMiklos Szeredi if (ofs->config.userxattr && res == -EACCES)
114687b2c60cSMiklos Szeredi return 0;
11479d3dfea3SVivek Goyal goto out;
11489d3dfea3SVivek Goyal }
11499d3dfea3SVivek Goyal
1150bf070890SAlexander Larsson if (res == 0) {
1151bf070890SAlexander Larsson /* Emulate empty data for zero size metacopy xattr */
1152bf070890SAlexander Larsson res = OVL_METACOPY_MIN_SIZE;
1153bf070890SAlexander Larsson if (data) {
1154bf070890SAlexander Larsson memset(data, 0, res);
1155bf070890SAlexander Larsson data->len = res;
1156bf070890SAlexander Larsson }
1157bf070890SAlexander Larsson } else if (res < OVL_METACOPY_MIN_SIZE) {
1158bf070890SAlexander Larsson pr_warn_ratelimited("metacopy file '%pd' has too small xattr\n",
1159bf070890SAlexander Larsson path->dentry);
1160bf070890SAlexander Larsson return -EIO;
1161bf070890SAlexander Larsson } else if (data) {
1162bf070890SAlexander Larsson if (data->version != 0) {
1163bf070890SAlexander Larsson pr_warn_ratelimited("metacopy file '%pd' has unsupported version\n",
1164bf070890SAlexander Larsson path->dentry);
1165bf070890SAlexander Larsson return -EIO;
1166bf070890SAlexander Larsson }
1167bf070890SAlexander Larsson if (res != data->len) {
1168bf070890SAlexander Larsson pr_warn_ratelimited("metacopy file '%pd' has invalid xattr size\n",
1169bf070890SAlexander Larsson path->dentry);
1170bf070890SAlexander Larsson return -EIO;
1171bf070890SAlexander Larsson }
1172bf070890SAlexander Larsson }
1173bf070890SAlexander Larsson
1174bf070890SAlexander Larsson return res;
11759d3dfea3SVivek Goyal out:
11761bd0a3aeSlijiazi pr_warn_ratelimited("failed to get metacopy (%i)\n", res);
11779d3dfea3SVivek Goyal return res;
11789d3dfea3SVivek Goyal }
117967d756c2SVivek Goyal
ovl_set_metacopy_xattr(struct ovl_fs * ofs,struct dentry * d,struct ovl_metacopy * metacopy)1180184996e9SAlexander Larsson int ovl_set_metacopy_xattr(struct ovl_fs *ofs, struct dentry *d, struct ovl_metacopy *metacopy)
1181184996e9SAlexander Larsson {
1182184996e9SAlexander Larsson size_t len = metacopy->len;
1183184996e9SAlexander Larsson
1184184996e9SAlexander Larsson /* If no flags or digest fall back to empty metacopy file */
1185184996e9SAlexander Larsson if (metacopy->version == 0 && metacopy->flags == 0 && metacopy->digest_algo == 0)
1186184996e9SAlexander Larsson len = 0;
1187184996e9SAlexander Larsson
1188184996e9SAlexander Larsson return ovl_check_setxattr(ofs, d, OVL_XATTR_METACOPY,
1189184996e9SAlexander Larsson metacopy, len, -EOPNOTSUPP);
1190184996e9SAlexander Larsson }
1191184996e9SAlexander Larsson
ovl_is_metacopy_dentry(struct dentry * dentry)119267d756c2SVivek Goyal bool ovl_is_metacopy_dentry(struct dentry *dentry)
119367d756c2SVivek Goyal {
1194a6ff2bc0SAmir Goldstein struct ovl_entry *oe = OVL_E(dentry);
119567d756c2SVivek Goyal
119667d756c2SVivek Goyal if (!d_is_reg(dentry))
119767d756c2SVivek Goyal return false;
119867d756c2SVivek Goyal
119967d756c2SVivek Goyal if (ovl_dentry_upper(dentry)) {
120067d756c2SVivek Goyal if (!ovl_has_upperdata(d_inode(dentry)))
120167d756c2SVivek Goyal return true;
120267d756c2SVivek Goyal return false;
120367d756c2SVivek Goyal }
120467d756c2SVivek Goyal
12055522c9c7SAmir Goldstein return (ovl_numlower(oe) > 1);
120667d756c2SVivek Goyal }
12070a2d0d3fSVivek Goyal
ovl_get_redirect_xattr(struct ovl_fs * ofs,const struct path * path,int padding)12082d343087SAl Viro char *ovl_get_redirect_xattr(struct ovl_fs *ofs, const struct path *path, int padding)
12090a2d0d3fSVivek Goyal {
12100a2d0d3fSVivek Goyal int res;
12110a2d0d3fSVivek Goyal char *s, *next, *buf = NULL;
12120a2d0d3fSVivek Goyal
1213dad7017aSChristian Brauner res = ovl_path_getxattr(ofs, path, OVL_XATTR_REDIRECT, NULL, 0);
121492f0d6c9SMiklos Szeredi if (res == -ENODATA || res == -EOPNOTSUPP)
12150a2d0d3fSVivek Goyal return NULL;
12160a2d0d3fSVivek Goyal if (res < 0)
121792f0d6c9SMiklos Szeredi goto fail;
121892f0d6c9SMiklos Szeredi if (res == 0)
121992f0d6c9SMiklos Szeredi goto invalid;
122092f0d6c9SMiklos Szeredi
122192f0d6c9SMiklos Szeredi buf = kzalloc(res + padding + 1, GFP_KERNEL);
122292f0d6c9SMiklos Szeredi if (!buf)
122392f0d6c9SMiklos Szeredi return ERR_PTR(-ENOMEM);
122492f0d6c9SMiklos Szeredi
1225dad7017aSChristian Brauner res = ovl_path_getxattr(ofs, path, OVL_XATTR_REDIRECT, buf, res);
122692f0d6c9SMiklos Szeredi if (res < 0)
122792f0d6c9SMiklos Szeredi goto fail;
12280a2d0d3fSVivek Goyal if (res == 0)
12290a2d0d3fSVivek Goyal goto invalid;
12300a2d0d3fSVivek Goyal
12310a2d0d3fSVivek Goyal if (buf[0] == '/') {
12320a2d0d3fSVivek Goyal for (s = buf; *s++ == '/'; s = next) {
12330a2d0d3fSVivek Goyal next = strchrnul(s, '/');
12340a2d0d3fSVivek Goyal if (s == next)
12350a2d0d3fSVivek Goyal goto invalid;
12360a2d0d3fSVivek Goyal }
12370a2d0d3fSVivek Goyal } else {
12380a2d0d3fSVivek Goyal if (strchr(buf, '/') != NULL)
12390a2d0d3fSVivek Goyal goto invalid;
12400a2d0d3fSVivek Goyal }
12410a2d0d3fSVivek Goyal
12420a2d0d3fSVivek Goyal return buf;
12430a2d0d3fSVivek Goyal invalid:
12441bd0a3aeSlijiazi pr_warn_ratelimited("invalid redirect (%s)\n", buf);
12450a2d0d3fSVivek Goyal res = -EINVAL;
124692f0d6c9SMiklos Szeredi goto err_free;
124792f0d6c9SMiklos Szeredi fail:
124892f0d6c9SMiklos Szeredi pr_warn_ratelimited("failed to get redirect (%i)\n", res);
124992f0d6c9SMiklos Szeredi err_free:
1250993a0b2aSVivek Goyal kfree(buf);
1251993a0b2aSVivek Goyal return ERR_PTR(res);
12520a2d0d3fSVivek Goyal }
1253335d3fc5SSargun Dhillon
1254184996e9SAlexander Larsson /* Call with mounter creds as it may open the file */
ovl_ensure_verity_loaded(struct path * datapath)12550c71faf5SAlexander Larsson int ovl_ensure_verity_loaded(struct path *datapath)
1256184996e9SAlexander Larsson {
1257184996e9SAlexander Larsson struct inode *inode = d_inode(datapath->dentry);
1258184996e9SAlexander Larsson struct file *filp;
1259184996e9SAlexander Larsson
1260184996e9SAlexander Larsson if (!fsverity_active(inode) && IS_VERITY(inode)) {
1261184996e9SAlexander Larsson /*
1262184996e9SAlexander Larsson * If this inode was not yet opened, the verity info hasn't been
1263184996e9SAlexander Larsson * loaded yet, so we need to do that here to force it into memory.
1264184996e9SAlexander Larsson */
1265184996e9SAlexander Larsson filp = kernel_file_open(datapath, O_RDONLY, inode, current_cred());
1266184996e9SAlexander Larsson if (IS_ERR(filp))
1267184996e9SAlexander Larsson return PTR_ERR(filp);
1268184996e9SAlexander Larsson fput(filp);
1269184996e9SAlexander Larsson }
1270184996e9SAlexander Larsson
1271184996e9SAlexander Larsson return 0;
1272184996e9SAlexander Larsson }
1273184996e9SAlexander Larsson
ovl_validate_verity(struct ovl_fs * ofs,struct path * metapath,struct path * datapath)1274184996e9SAlexander Larsson int ovl_validate_verity(struct ovl_fs *ofs,
1275184996e9SAlexander Larsson struct path *metapath,
1276184996e9SAlexander Larsson struct path *datapath)
1277184996e9SAlexander Larsson {
1278184996e9SAlexander Larsson struct ovl_metacopy metacopy_data;
1279184996e9SAlexander Larsson u8 actual_digest[FS_VERITY_MAX_DIGEST_SIZE];
1280184996e9SAlexander Larsson int xattr_digest_size, digest_size;
1281184996e9SAlexander Larsson int xattr_size, err;
1282184996e9SAlexander Larsson u8 verity_algo;
1283184996e9SAlexander Larsson
1284184996e9SAlexander Larsson if (!ofs->config.verity_mode ||
1285184996e9SAlexander Larsson /* Verity only works on regular files */
1286184996e9SAlexander Larsson !S_ISREG(d_inode(metapath->dentry)->i_mode))
1287184996e9SAlexander Larsson return 0;
1288184996e9SAlexander Larsson
1289184996e9SAlexander Larsson xattr_size = ovl_check_metacopy_xattr(ofs, metapath, &metacopy_data);
1290184996e9SAlexander Larsson if (xattr_size < 0)
1291184996e9SAlexander Larsson return xattr_size;
1292184996e9SAlexander Larsson
1293184996e9SAlexander Larsson if (!xattr_size || !metacopy_data.digest_algo) {
1294184996e9SAlexander Larsson if (ofs->config.verity_mode == OVL_VERITY_REQUIRE) {
1295184996e9SAlexander Larsson pr_warn_ratelimited("metacopy file '%pd' has no digest specified\n",
1296184996e9SAlexander Larsson metapath->dentry);
1297184996e9SAlexander Larsson return -EIO;
1298184996e9SAlexander Larsson }
1299184996e9SAlexander Larsson return 0;
1300184996e9SAlexander Larsson }
1301184996e9SAlexander Larsson
1302184996e9SAlexander Larsson xattr_digest_size = ovl_metadata_digest_size(&metacopy_data);
1303184996e9SAlexander Larsson
1304184996e9SAlexander Larsson err = ovl_ensure_verity_loaded(datapath);
1305184996e9SAlexander Larsson if (err < 0) {
1306184996e9SAlexander Larsson pr_warn_ratelimited("lower file '%pd' failed to load fs-verity info\n",
1307184996e9SAlexander Larsson datapath->dentry);
1308184996e9SAlexander Larsson return -EIO;
1309184996e9SAlexander Larsson }
1310184996e9SAlexander Larsson
1311184996e9SAlexander Larsson digest_size = fsverity_get_digest(d_inode(datapath->dentry), actual_digest,
1312184996e9SAlexander Larsson &verity_algo, NULL);
1313184996e9SAlexander Larsson if (digest_size == 0) {
1314184996e9SAlexander Larsson pr_warn_ratelimited("lower file '%pd' has no fs-verity digest\n", datapath->dentry);
1315184996e9SAlexander Larsson return -EIO;
1316184996e9SAlexander Larsson }
1317184996e9SAlexander Larsson
1318184996e9SAlexander Larsson if (xattr_digest_size != digest_size ||
1319184996e9SAlexander Larsson metacopy_data.digest_algo != verity_algo ||
1320184996e9SAlexander Larsson memcmp(metacopy_data.digest, actual_digest, xattr_digest_size) != 0) {
1321184996e9SAlexander Larsson pr_warn_ratelimited("lower file '%pd' has the wrong fs-verity digest\n",
1322184996e9SAlexander Larsson datapath->dentry);
1323184996e9SAlexander Larsson return -EIO;
1324184996e9SAlexander Larsson }
1325184996e9SAlexander Larsson
1326184996e9SAlexander Larsson return 0;
1327184996e9SAlexander Larsson }
1328184996e9SAlexander Larsson
ovl_get_verity_digest(struct ovl_fs * ofs,struct path * src,struct ovl_metacopy * metacopy)13290c71faf5SAlexander Larsson int ovl_get_verity_digest(struct ovl_fs *ofs, struct path *src,
13300c71faf5SAlexander Larsson struct ovl_metacopy *metacopy)
13310c71faf5SAlexander Larsson {
13320c71faf5SAlexander Larsson int err, digest_size;
13330c71faf5SAlexander Larsson
13340c71faf5SAlexander Larsson if (!ofs->config.verity_mode || !S_ISREG(d_inode(src->dentry)->i_mode))
13350c71faf5SAlexander Larsson return 0;
13360c71faf5SAlexander Larsson
13370c71faf5SAlexander Larsson err = ovl_ensure_verity_loaded(src);
13380c71faf5SAlexander Larsson if (err < 0) {
13390c71faf5SAlexander Larsson pr_warn_ratelimited("lower file '%pd' failed to load fs-verity info\n",
13400c71faf5SAlexander Larsson src->dentry);
13410c71faf5SAlexander Larsson return -EIO;
13420c71faf5SAlexander Larsson }
13430c71faf5SAlexander Larsson
13440c71faf5SAlexander Larsson digest_size = fsverity_get_digest(d_inode(src->dentry),
13450c71faf5SAlexander Larsson metacopy->digest, &metacopy->digest_algo, NULL);
13460c71faf5SAlexander Larsson if (digest_size == 0 ||
13470c71faf5SAlexander Larsson WARN_ON_ONCE(digest_size > FS_VERITY_MAX_DIGEST_SIZE)) {
13480c71faf5SAlexander Larsson if (ofs->config.verity_mode == OVL_VERITY_REQUIRE) {
13490c71faf5SAlexander Larsson pr_warn_ratelimited("lower file '%pd' has no fs-verity digest\n",
13500c71faf5SAlexander Larsson src->dentry);
13510c71faf5SAlexander Larsson return -EIO;
13520c71faf5SAlexander Larsson }
13530c71faf5SAlexander Larsson return 0;
13540c71faf5SAlexander Larsson }
13550c71faf5SAlexander Larsson
13560c71faf5SAlexander Larsson metacopy->len += digest_size;
13570c71faf5SAlexander Larsson return 0;
13580c71faf5SAlexander Larsson }
13590c71faf5SAlexander Larsson
1360335d3fc5SSargun Dhillon /*
1361335d3fc5SSargun Dhillon * ovl_sync_status() - Check fs sync status for volatile mounts
1362335d3fc5SSargun Dhillon *
1363335d3fc5SSargun Dhillon * Returns 1 if this is not a volatile mount and a real sync is required.
1364335d3fc5SSargun Dhillon *
1365335d3fc5SSargun Dhillon * Returns 0 if syncing can be skipped because mount is volatile, and no errors
1366335d3fc5SSargun Dhillon * have occurred on the upperdir since the mount.
1367335d3fc5SSargun Dhillon *
1368335d3fc5SSargun Dhillon * Returns -errno if it is a volatile mount, and the error that occurred since
1369335d3fc5SSargun Dhillon * the last mount. If the error code changes, it'll return the latest error
1370335d3fc5SSargun Dhillon * code.
1371335d3fc5SSargun Dhillon */
1372335d3fc5SSargun Dhillon
ovl_sync_status(struct ovl_fs * ofs)1373335d3fc5SSargun Dhillon int ovl_sync_status(struct ovl_fs *ofs)
1374335d3fc5SSargun Dhillon {
1375335d3fc5SSargun Dhillon struct vfsmount *mnt;
1376335d3fc5SSargun Dhillon
1377335d3fc5SSargun Dhillon if (ovl_should_sync(ofs))
1378335d3fc5SSargun Dhillon return 1;
1379335d3fc5SSargun Dhillon
1380335d3fc5SSargun Dhillon mnt = ovl_upper_mnt(ofs);
1381335d3fc5SSargun Dhillon if (!mnt)
1382335d3fc5SSargun Dhillon return 0;
1383335d3fc5SSargun Dhillon
1384335d3fc5SSargun Dhillon return errseq_check(&mnt->mnt_sb->s_wb_err, ofs->errseq);
1385335d3fc5SSargun Dhillon }
13862878dffcSChristian Brauner
13872878dffcSChristian Brauner /*
13882878dffcSChristian Brauner * ovl_copyattr() - copy inode attributes from layer to ovl inode
13892878dffcSChristian Brauner *
13902878dffcSChristian Brauner * When overlay copies inode information from an upper or lower layer to the
13912878dffcSChristian Brauner * relevant overlay inode it will apply the idmapping of the upper or lower
13922878dffcSChristian Brauner * layer when doing so ensuring that the ovl inode ownership will correctly
13932878dffcSChristian Brauner * reflect the ownership of the idmapped upper or lower layer. For example, an
13942878dffcSChristian Brauner * idmapped upper or lower layer mapping id 1001 to id 1000 will take care to
13952878dffcSChristian Brauner * map any lower or upper inode owned by id 1001 to id 1000. These mapping
13962878dffcSChristian Brauner * helpers are nops when the relevant layer isn't idmapped.
13972878dffcSChristian Brauner */
ovl_copyattr(struct inode * inode)13982878dffcSChristian Brauner void ovl_copyattr(struct inode *inode)
13992878dffcSChristian Brauner {
14002878dffcSChristian Brauner struct path realpath;
14012878dffcSChristian Brauner struct inode *realinode;
1402e67fe633SChristian Brauner struct mnt_idmap *real_idmap;
140373db6a06SChristian Brauner vfsuid_t vfsuid;
140473db6a06SChristian Brauner vfsgid_t vfsgid;
14052878dffcSChristian Brauner
1406b2dd05f1SZhihao Cheng realinode = ovl_i_path_real(inode, &realpath);
1407e67fe633SChristian Brauner real_idmap = mnt_idmap(realpath.mnt);
14082878dffcSChristian Brauner
1409e67fe633SChristian Brauner vfsuid = i_uid_into_vfsuid(real_idmap, realinode);
1410e67fe633SChristian Brauner vfsgid = i_gid_into_vfsgid(real_idmap, realinode);
141173db6a06SChristian Brauner
141273db6a06SChristian Brauner inode->i_uid = vfsuid_into_kuid(vfsuid);
141373db6a06SChristian Brauner inode->i_gid = vfsgid_into_kgid(vfsgid);
14142878dffcSChristian Brauner inode->i_mode = realinode->i_mode;
14152878dffcSChristian Brauner inode->i_atime = realinode->i_atime;
14162878dffcSChristian Brauner inode->i_mtime = realinode->i_mtime;
14179aa71115SJeff Layton inode_set_ctime_to_ts(inode, inode_get_ctime(realinode));
14182878dffcSChristian Brauner i_size_write(inode, i_size_read(realinode));
14192878dffcSChristian Brauner }
1420