aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/overlayfs/export.c53
-rw-r--r--fs/overlayfs/namei.c7
-rw-r--r--fs/overlayfs/overlayfs.h2
3 files changed, 47 insertions, 15 deletions
diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c
index 8e37a07b9eff..8c0172d9b922 100644
--- a/fs/overlayfs/export.c
+++ b/fs/overlayfs/export.c
@@ -169,16 +169,16 @@ static struct dentry *ovl_obtain_alias(struct super_block *sb,
169 struct dentry *upper, 169 struct dentry *upper,
170 struct ovl_path *lowerpath) 170 struct ovl_path *lowerpath)
171{ 171{
172 struct inode *inode; 172 struct dentry *lower = lowerpath ? lowerpath->dentry : NULL;
173 struct dentry *dentry; 173 struct dentry *dentry;
174 struct inode *inode;
174 struct ovl_entry *oe; 175 struct ovl_entry *oe;
175 void *fsdata = &oe;
176 176
177 /* TODO: obtain non pure-upper */ 177 /* TODO: obtain an indexed non-dir upper with origin */
178 if (lowerpath) 178 if (lower && (upper || d_is_dir(lower)))
179 return ERR_PTR(-EIO); 179 return ERR_PTR(-EIO);
180 180
181 inode = ovl_get_inode(sb, dget(upper), NULL, NULL, 0); 181 inode = ovl_get_inode(sb, dget(upper), lower, NULL, !!lower);
182 if (IS_ERR(inode)) { 182 if (IS_ERR(inode)) {
183 dput(upper); 183 dput(upper);
184 return ERR_CAST(inode); 184 return ERR_CAST(inode);
@@ -189,12 +189,17 @@ static struct dentry *ovl_obtain_alias(struct super_block *sb,
189 dentry = d_alloc_anon(inode->i_sb); 189 dentry = d_alloc_anon(inode->i_sb);
190 if (!dentry) 190 if (!dentry)
191 goto nomem; 191 goto nomem;
192 oe = ovl_alloc_entry(0); 192 oe = ovl_alloc_entry(lower ? 1 : 0);
193 if (!oe) 193 if (!oe)
194 goto nomem; 194 goto nomem;
195 195
196 if (lower) {
197 oe->lowerstack->dentry = dget(lower);
198 oe->lowerstack->layer = lowerpath->layer;
199 }
196 dentry->d_fsdata = oe; 200 dentry->d_fsdata = oe;
197 ovl_dentry_set_upper_alias(dentry); 201 if (upper)
202 ovl_dentry_set_upper_alias(dentry);
198 } 203 }
199 204
200 return d_instantiate_anon(dentry, inode); 205 return d_instantiate_anon(dentry, inode);
@@ -381,7 +386,14 @@ static struct dentry *ovl_get_dentry(struct super_block *sb,
381 struct ovl_fs *ofs = sb->s_fs_info; 386 struct ovl_fs *ofs = sb->s_fs_info;
382 struct ovl_layer upper_layer = { .mnt = ofs->upper_mnt }; 387 struct ovl_layer upper_layer = { .mnt = ofs->upper_mnt };
383 388
384 /* TODO: get non-upper dentry */ 389 /*
390 * Obtain a disconnected overlay dentry from a disconnected non-dir
391 * real lower dentry.
392 */
393 if (!upper && !d_is_dir(lowerpath->dentry))
394 return ovl_obtain_alias(sb, NULL, lowerpath);
395
396 /* TODO: lookup connected dir from real lower dir */
385 if (!upper) 397 if (!upper)
386 return ERR_PTR(-EACCES); 398 return ERR_PTR(-EACCES);
387 399
@@ -423,6 +435,25 @@ static struct dentry *ovl_upper_fh_to_d(struct super_block *sb,
423 return dentry; 435 return dentry;
424} 436}
425 437
438static struct dentry *ovl_lower_fh_to_d(struct super_block *sb,
439 struct ovl_fh *fh)
440{
441 struct ovl_fs *ofs = sb->s_fs_info;
442 struct ovl_path origin = { };
443 struct ovl_path *stack = &origin;
444 struct dentry *dentry = NULL;
445 int err;
446
447 err = ovl_check_origin_fh(ofs, fh, NULL, &stack);
448 if (err)
449 return ERR_PTR(err);
450
451 dentry = ovl_get_dentry(sb, NULL, &origin);
452 dput(origin.dentry);
453
454 return dentry;
455}
456
426static struct dentry *ovl_fh_to_dentry(struct super_block *sb, struct fid *fid, 457static struct dentry *ovl_fh_to_dentry(struct super_block *sb, struct fid *fid,
427 int fh_len, int fh_type) 458 int fh_len, int fh_type)
428{ 459{
@@ -440,10 +471,10 @@ static struct dentry *ovl_fh_to_dentry(struct super_block *sb, struct fid *fid,
440 if (err) 471 if (err)
441 goto out_err; 472 goto out_err;
442 473
443 /* TODO: decode non-upper */
444 flags = fh->flags; 474 flags = fh->flags;
445 if (flags & OVL_FH_FLAG_PATH_UPPER) 475 dentry = (flags & OVL_FH_FLAG_PATH_UPPER) ?
446 dentry = ovl_upper_fh_to_d(sb, fh); 476 ovl_upper_fh_to_d(sb, fh) :
477 ovl_lower_fh_to_d(sb, fh);
447 err = PTR_ERR(dentry); 478 err = PTR_ERR(dentry);
448 if (IS_ERR(dentry) && err != -ESTALE) 479 if (IS_ERR(dentry) && err != -ESTALE)
449 goto out_err; 480 goto out_err;
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
index a35c5eaa2c01..741a42d974a3 100644
--- a/fs/overlayfs/namei.c
+++ b/fs/overlayfs/namei.c
@@ -310,9 +310,8 @@ static int ovl_lookup_layer(struct dentry *base, struct ovl_lookup_data *d,
310} 310}
311 311
312 312
313static int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, 313int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh,
314 struct dentry *upperdentry, 314 struct dentry *upperdentry, struct ovl_path **stackp)
315 struct ovl_path **stackp)
316{ 315{
317 struct dentry *origin = NULL; 316 struct dentry *origin = NULL;
318 int i; 317 int i;
@@ -328,7 +327,7 @@ static int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh,
328 else if (IS_ERR(origin)) 327 else if (IS_ERR(origin))
329 return PTR_ERR(origin); 328 return PTR_ERR(origin);
330 329
331 if (!ovl_is_whiteout(upperdentry) && 330 if (upperdentry && !ovl_is_whiteout(upperdentry) &&
332 ((d_inode(origin)->i_mode ^ d_inode(upperdentry)->i_mode) & S_IFMT)) 331 ((d_inode(origin)->i_mode ^ d_inode(upperdentry)->i_mode) & S_IFMT))
333 goto invalid; 332 goto invalid;
334 333
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 401113a2e9c7..40ba11e412b1 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -266,6 +266,8 @@ static inline bool ovl_is_impuredir(struct dentry *dentry)
266/* namei.c */ 266/* namei.c */
267int ovl_check_fh_len(struct ovl_fh *fh, int fh_len); 267int ovl_check_fh_len(struct ovl_fh *fh, int fh_len);
268struct dentry *ovl_decode_fh(struct ovl_fh *fh, struct vfsmount *mnt); 268struct dentry *ovl_decode_fh(struct ovl_fh *fh, struct vfsmount *mnt);
269int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh,
270 struct dentry *upperdentry, struct ovl_path **stackp);
269int ovl_verify_set_fh(struct dentry *dentry, const char *name, 271int ovl_verify_set_fh(struct dentry *dentry, const char *name,
270 struct dentry *real, bool is_upper, bool set); 272 struct dentry *real, bool is_upper, bool set);
271int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index); 273int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index);