| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * |
|---|
| 3 | 4 | * Copyright (C) 2011 Novell Inc. |
|---|
| 4 | | - * |
|---|
| 5 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 6 | | - * under the terms of the GNU General Public License version 2 as published by |
|---|
| 7 | | - * the Free Software Foundation. |
|---|
| 8 | 5 | */ |
|---|
| 9 | 6 | |
|---|
| 10 | 7 | #include <uapi/linux/magic.h> |
|---|
| .. | .. |
|---|
| 23 | 20 | MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); |
|---|
| 24 | 21 | MODULE_DESCRIPTION("Overlay filesystem"); |
|---|
| 25 | 22 | MODULE_LICENSE("GPL"); |
|---|
| 23 | +MODULE_IMPORT_NS(ANDROID_GKI_VFS_EXPORT_ONLY); |
|---|
| 26 | 24 | |
|---|
| 27 | 25 | |
|---|
| 28 | 26 | struct ovl_dir_cache; |
|---|
| .. | .. |
|---|
| 31 | 29 | |
|---|
| 32 | 30 | static bool ovl_redirect_dir_def = IS_ENABLED(CONFIG_OVERLAY_FS_REDIRECT_DIR); |
|---|
| 33 | 31 | module_param_named(redirect_dir, ovl_redirect_dir_def, bool, 0644); |
|---|
| 34 | | -MODULE_PARM_DESC(ovl_redirect_dir_def, |
|---|
| 32 | +MODULE_PARM_DESC(redirect_dir, |
|---|
| 35 | 33 | "Default to on or off for the redirect_dir feature"); |
|---|
| 36 | 34 | |
|---|
| 37 | 35 | static bool ovl_redirect_always_follow = |
|---|
| 38 | 36 | IS_ENABLED(CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW); |
|---|
| 39 | 37 | module_param_named(redirect_always_follow, ovl_redirect_always_follow, |
|---|
| 40 | 38 | bool, 0644); |
|---|
| 41 | | -MODULE_PARM_DESC(ovl_redirect_always_follow, |
|---|
| 39 | +MODULE_PARM_DESC(redirect_always_follow, |
|---|
| 42 | 40 | "Follow redirects even if redirect_dir feature is turned off"); |
|---|
| 43 | 41 | |
|---|
| 44 | 42 | static bool ovl_index_def = IS_ENABLED(CONFIG_OVERLAY_FS_INDEX); |
|---|
| 45 | 43 | module_param_named(index, ovl_index_def, bool, 0644); |
|---|
| 46 | | -MODULE_PARM_DESC(ovl_index_def, |
|---|
| 44 | +MODULE_PARM_DESC(index, |
|---|
| 47 | 45 | "Default to on or off for the inodes index feature"); |
|---|
| 48 | 46 | |
|---|
| 49 | 47 | static bool ovl_nfs_export_def = IS_ENABLED(CONFIG_OVERLAY_FS_NFS_EXPORT); |
|---|
| 50 | 48 | module_param_named(nfs_export, ovl_nfs_export_def, bool, 0644); |
|---|
| 51 | | -MODULE_PARM_DESC(ovl_nfs_export_def, |
|---|
| 49 | +MODULE_PARM_DESC(nfs_export, |
|---|
| 52 | 50 | "Default to on or off for the NFS export feature"); |
|---|
| 53 | 51 | |
|---|
| 54 | 52 | static bool ovl_xino_auto_def = IS_ENABLED(CONFIG_OVERLAY_FS_XINO_AUTO); |
|---|
| 55 | 53 | module_param_named(xino_auto, ovl_xino_auto_def, bool, 0644); |
|---|
| 56 | | -MODULE_PARM_DESC(ovl_xino_auto_def, |
|---|
| 54 | +MODULE_PARM_DESC(xino_auto, |
|---|
| 57 | 55 | "Auto enable xino feature"); |
|---|
| 58 | 56 | |
|---|
| 59 | 57 | static bool __read_mostly ovl_override_creds_def = true; |
|---|
| .. | .. |
|---|
| 71 | 69 | |
|---|
| 72 | 70 | static bool ovl_metacopy_def = IS_ENABLED(CONFIG_OVERLAY_FS_METACOPY); |
|---|
| 73 | 71 | module_param_named(metacopy, ovl_metacopy_def, bool, 0644); |
|---|
| 74 | | -MODULE_PARM_DESC(ovl_metacopy_def, |
|---|
| 72 | +MODULE_PARM_DESC(metacopy, |
|---|
| 75 | 73 | "Default to on or off for the metadata only copy up feature"); |
|---|
| 76 | 74 | |
|---|
| 77 | 75 | static void ovl_dentry_release(struct dentry *dentry) |
|---|
| .. | .. |
|---|
| 124 | 122 | return dentry; |
|---|
| 125 | 123 | } |
|---|
| 126 | 124 | |
|---|
| 127 | | -static int ovl_dentry_revalidate(struct dentry *dentry, unsigned int flags) |
|---|
| 125 | +static int ovl_revalidate_real(struct dentry *d, unsigned int flags, bool weak) |
|---|
| 128 | 126 | { |
|---|
| 129 | | - struct ovl_entry *oe = dentry->d_fsdata; |
|---|
| 130 | | - unsigned int i; |
|---|
| 131 | 127 | int ret = 1; |
|---|
| 132 | 128 | |
|---|
| 133 | | - for (i = 0; i < oe->numlower; i++) { |
|---|
| 134 | | - struct dentry *d = oe->lowerstack[i].dentry; |
|---|
| 135 | | - |
|---|
| 136 | | - if (d->d_flags & DCACHE_OP_REVALIDATE) { |
|---|
| 137 | | - ret = d->d_op->d_revalidate(d, flags); |
|---|
| 138 | | - if (ret < 0) |
|---|
| 139 | | - return ret; |
|---|
| 140 | | - if (!ret) { |
|---|
| 141 | | - if (!(flags & LOOKUP_RCU)) |
|---|
| 142 | | - d_invalidate(d); |
|---|
| 143 | | - return -ESTALE; |
|---|
| 144 | | - } |
|---|
| 145 | | - } |
|---|
| 146 | | - } |
|---|
| 147 | | - return 1; |
|---|
| 148 | | -} |
|---|
| 149 | | - |
|---|
| 150 | | -static int ovl_dentry_weak_revalidate(struct dentry *dentry, unsigned int flags) |
|---|
| 151 | | -{ |
|---|
| 152 | | - struct ovl_entry *oe = dentry->d_fsdata; |
|---|
| 153 | | - unsigned int i; |
|---|
| 154 | | - int ret = 1; |
|---|
| 155 | | - |
|---|
| 156 | | - for (i = 0; i < oe->numlower; i++) { |
|---|
| 157 | | - struct dentry *d = oe->lowerstack[i].dentry; |
|---|
| 158 | | - |
|---|
| 159 | | - if (d->d_flags & DCACHE_OP_WEAK_REVALIDATE) { |
|---|
| 160 | | - ret = d->d_op->d_weak_revalidate(d, flags); |
|---|
| 161 | | - if (ret <= 0) |
|---|
| 162 | | - break; |
|---|
| 129 | + if (weak) { |
|---|
| 130 | + if (d->d_flags & DCACHE_OP_WEAK_REVALIDATE) |
|---|
| 131 | + ret = d->d_op->d_weak_revalidate(d, flags); |
|---|
| 132 | + } else if (d->d_flags & DCACHE_OP_REVALIDATE) { |
|---|
| 133 | + ret = d->d_op->d_revalidate(d, flags); |
|---|
| 134 | + if (!ret) { |
|---|
| 135 | + if (!(flags & LOOKUP_RCU)) |
|---|
| 136 | + d_invalidate(d); |
|---|
| 137 | + ret = -ESTALE; |
|---|
| 163 | 138 | } |
|---|
| 164 | 139 | } |
|---|
| 165 | 140 | return ret; |
|---|
| 166 | 141 | } |
|---|
| 167 | 142 | |
|---|
| 168 | | -static const struct dentry_operations ovl_dentry_operations = { |
|---|
| 169 | | - .d_release = ovl_dentry_release, |
|---|
| 170 | | - .d_real = ovl_d_real, |
|---|
| 171 | | -}; |
|---|
| 143 | +static int ovl_dentry_revalidate_common(struct dentry *dentry, |
|---|
| 144 | + unsigned int flags, bool weak) |
|---|
| 145 | +{ |
|---|
| 146 | + struct ovl_entry *oe = dentry->d_fsdata; |
|---|
| 147 | + struct inode *inode = d_inode_rcu(dentry); |
|---|
| 148 | + struct dentry *upper; |
|---|
| 149 | + unsigned int i; |
|---|
| 150 | + int ret = 1; |
|---|
| 172 | 151 | |
|---|
| 173 | | -static const struct dentry_operations ovl_reval_dentry_operations = { |
|---|
| 152 | + /* Careful in RCU mode */ |
|---|
| 153 | + if (!inode) |
|---|
| 154 | + return -ECHILD; |
|---|
| 155 | + |
|---|
| 156 | + upper = ovl_i_dentry_upper(inode); |
|---|
| 157 | + if (upper) |
|---|
| 158 | + ret = ovl_revalidate_real(upper, flags, weak); |
|---|
| 159 | + |
|---|
| 160 | + for (i = 0; ret > 0 && i < oe->numlower; i++) { |
|---|
| 161 | + ret = ovl_revalidate_real(oe->lowerstack[i].dentry, flags, |
|---|
| 162 | + weak); |
|---|
| 163 | + } |
|---|
| 164 | + return ret; |
|---|
| 165 | +} |
|---|
| 166 | + |
|---|
| 167 | +static int ovl_dentry_revalidate(struct dentry *dentry, unsigned int flags) |
|---|
| 168 | +{ |
|---|
| 169 | + return ovl_dentry_revalidate_common(dentry, flags, false); |
|---|
| 170 | +} |
|---|
| 171 | + |
|---|
| 172 | +static int ovl_dentry_weak_revalidate(struct dentry *dentry, unsigned int flags) |
|---|
| 173 | +{ |
|---|
| 174 | + return ovl_dentry_revalidate_common(dentry, flags, true); |
|---|
| 175 | +} |
|---|
| 176 | + |
|---|
| 177 | +static const struct dentry_operations ovl_dentry_operations = { |
|---|
| 174 | 178 | .d_release = ovl_dentry_release, |
|---|
| 175 | 179 | .d_real = ovl_d_real, |
|---|
| 176 | 180 | .d_revalidate = ovl_dentry_revalidate, |
|---|
| .. | .. |
|---|
| 198 | 202 | return &oi->vfs_inode; |
|---|
| 199 | 203 | } |
|---|
| 200 | 204 | |
|---|
| 201 | | -static void ovl_i_callback(struct rcu_head *head) |
|---|
| 205 | +static void ovl_free_inode(struct inode *inode) |
|---|
| 202 | 206 | { |
|---|
| 203 | | - struct inode *inode = container_of(head, struct inode, i_rcu); |
|---|
| 207 | + struct ovl_inode *oi = OVL_I(inode); |
|---|
| 204 | 208 | |
|---|
| 205 | | - kmem_cache_free(ovl_inode_cachep, OVL_I(inode)); |
|---|
| 209 | + kfree(oi->redirect); |
|---|
| 210 | + mutex_destroy(&oi->lock); |
|---|
| 211 | + kmem_cache_free(ovl_inode_cachep, oi); |
|---|
| 206 | 212 | } |
|---|
| 207 | 213 | |
|---|
| 208 | 214 | static void ovl_destroy_inode(struct inode *inode) |
|---|
| .. | .. |
|---|
| 215 | 221 | ovl_dir_cache_free(inode); |
|---|
| 216 | 222 | else |
|---|
| 217 | 223 | iput(oi->lowerdata); |
|---|
| 218 | | - kfree(oi->redirect); |
|---|
| 219 | | - mutex_destroy(&oi->lock); |
|---|
| 220 | | - |
|---|
| 221 | | - call_rcu(&inode->i_rcu, ovl_i_callback); |
|---|
| 222 | 224 | } |
|---|
| 223 | 225 | |
|---|
| 224 | 226 | static void ovl_free_fs(struct ovl_fs *ofs) |
|---|
| 225 | 227 | { |
|---|
| 228 | + struct vfsmount **mounts; |
|---|
| 226 | 229 | unsigned i; |
|---|
| 227 | 230 | |
|---|
| 228 | 231 | iput(ofs->workbasedir_trap); |
|---|
| 229 | 232 | iput(ofs->indexdir_trap); |
|---|
| 230 | 233 | iput(ofs->workdir_trap); |
|---|
| 231 | | - iput(ofs->upperdir_trap); |
|---|
| 234 | + dput(ofs->whiteout); |
|---|
| 232 | 235 | dput(ofs->indexdir); |
|---|
| 233 | 236 | dput(ofs->workdir); |
|---|
| 234 | 237 | if (ofs->workdir_locked) |
|---|
| 235 | 238 | ovl_inuse_unlock(ofs->workbasedir); |
|---|
| 236 | 239 | dput(ofs->workbasedir); |
|---|
| 237 | 240 | if (ofs->upperdir_locked) |
|---|
| 238 | | - ovl_inuse_unlock(ofs->upper_mnt->mnt_root); |
|---|
| 239 | | - mntput(ofs->upper_mnt); |
|---|
| 240 | | - for (i = 0; i < ofs->numlower; i++) { |
|---|
| 241 | | - iput(ofs->lower_layers[i].trap); |
|---|
| 242 | | - mntput(ofs->lower_layers[i].mnt); |
|---|
| 241 | + ovl_inuse_unlock(ovl_upper_mnt(ofs)->mnt_root); |
|---|
| 242 | + |
|---|
| 243 | + /* Hack! Reuse ofs->layers as a vfsmount array before freeing it */ |
|---|
| 244 | + mounts = (struct vfsmount **) ofs->layers; |
|---|
| 245 | + for (i = 0; i < ofs->numlayer; i++) { |
|---|
| 246 | + iput(ofs->layers[i].trap); |
|---|
| 247 | + mounts[i] = ofs->layers[i].mnt; |
|---|
| 243 | 248 | } |
|---|
| 244 | | - for (i = 0; i < ofs->numlowerfs; i++) |
|---|
| 245 | | - free_anon_bdev(ofs->lower_fs[i].pseudo_dev); |
|---|
| 246 | | - kfree(ofs->lower_layers); |
|---|
| 247 | | - kfree(ofs->lower_fs); |
|---|
| 249 | + kern_unmount_array(mounts, ofs->numlayer); |
|---|
| 250 | + kfree(ofs->layers); |
|---|
| 251 | + for (i = 0; i < ofs->numfs; i++) |
|---|
| 252 | + free_anon_bdev(ofs->fs[i].pseudo_dev); |
|---|
| 253 | + kfree(ofs->fs); |
|---|
| 248 | 254 | |
|---|
| 249 | 255 | kfree(ofs->config.lowerdir); |
|---|
| 250 | 256 | kfree(ofs->config.upperdir); |
|---|
| .. | .. |
|---|
| 269 | 275 | struct super_block *upper_sb; |
|---|
| 270 | 276 | int ret; |
|---|
| 271 | 277 | |
|---|
| 272 | | - if (!ofs->upper_mnt) |
|---|
| 273 | | - return 0; |
|---|
| 278 | + ret = ovl_sync_status(ofs); |
|---|
| 279 | + /* |
|---|
| 280 | + * We have to always set the err, because the return value isn't |
|---|
| 281 | + * checked in syncfs, and instead indirectly return an error via |
|---|
| 282 | + * the sb's writeback errseq, which VFS inspects after this call. |
|---|
| 283 | + */ |
|---|
| 284 | + if (ret < 0) { |
|---|
| 285 | + errseq_set(&sb->s_wb_err, -EIO); |
|---|
| 286 | + return -EIO; |
|---|
| 287 | + } |
|---|
| 288 | + |
|---|
| 289 | + if (!ret) |
|---|
| 290 | + return ret; |
|---|
| 274 | 291 | |
|---|
| 275 | 292 | /* |
|---|
| 276 | | - * If this is a sync(2) call or an emergency sync, all the super blocks |
|---|
| 277 | | - * will be iterated, including upper_sb, so no need to do anything. |
|---|
| 293 | + * Not called for sync(2) call or an emergency sync (SB_I_SKIP_SYNC). |
|---|
| 294 | + * All the super blocks will be iterated, including upper_sb. |
|---|
| 278 | 295 | * |
|---|
| 279 | 296 | * If this is a syncfs(2) call, then we do need to call |
|---|
| 280 | 297 | * sync_filesystem() on upper_sb, but enough if we do it when being |
|---|
| .. | .. |
|---|
| 283 | 300 | if (!wait) |
|---|
| 284 | 301 | return 0; |
|---|
| 285 | 302 | |
|---|
| 286 | | - upper_sb = ofs->upper_mnt->mnt_sb; |
|---|
| 303 | + upper_sb = ovl_upper_mnt(ofs)->mnt_sb; |
|---|
| 287 | 304 | |
|---|
| 288 | 305 | down_read(&upper_sb->s_umount); |
|---|
| 289 | 306 | ret = sync_filesystem(upper_sb); |
|---|
| .. | .. |
|---|
| 321 | 338 | /* Will this overlay be forced to mount/remount ro? */ |
|---|
| 322 | 339 | static bool ovl_force_readonly(struct ovl_fs *ofs) |
|---|
| 323 | 340 | { |
|---|
| 324 | | - return (!ofs->upper_mnt || !ofs->workdir); |
|---|
| 341 | + return (!ovl_upper_mnt(ofs) || !ofs->workdir); |
|---|
| 325 | 342 | } |
|---|
| 326 | 343 | |
|---|
| 327 | 344 | static const char *ovl_redirect_mode_def(void) |
|---|
| 328 | 345 | { |
|---|
| 329 | 346 | return ovl_redirect_dir_def ? "on" : "off"; |
|---|
| 330 | 347 | } |
|---|
| 331 | | - |
|---|
| 332 | | -enum { |
|---|
| 333 | | - OVL_XINO_OFF, |
|---|
| 334 | | - OVL_XINO_AUTO, |
|---|
| 335 | | - OVL_XINO_ON, |
|---|
| 336 | | -}; |
|---|
| 337 | 348 | |
|---|
| 338 | 349 | static const char * const ovl_xino_str[] = { |
|---|
| 339 | 350 | "off", |
|---|
| .. | .. |
|---|
| 371 | 382 | if (ofs->config.nfs_export != ovl_nfs_export_def) |
|---|
| 372 | 383 | seq_printf(m, ",nfs_export=%s", ofs->config.nfs_export ? |
|---|
| 373 | 384 | "on" : "off"); |
|---|
| 374 | | - if (ofs->config.xino != ovl_xino_def()) |
|---|
| 385 | + if (ofs->config.xino != ovl_xino_def() && !ovl_same_fs(sb)) |
|---|
| 375 | 386 | seq_printf(m, ",xino=%s", ovl_xino_str[ofs->config.xino]); |
|---|
| 376 | 387 | if (ofs->config.metacopy != ovl_metacopy_def) |
|---|
| 377 | 388 | seq_printf(m, ",metacopy=%s", |
|---|
| 378 | 389 | ofs->config.metacopy ? "on" : "off"); |
|---|
| 390 | + if (ofs->config.ovl_volatile) |
|---|
| 391 | + seq_puts(m, ",volatile"); |
|---|
| 379 | 392 | if (ofs->config.override_creds != ovl_override_creds_def) |
|---|
| 380 | 393 | seq_show_option(m, "override_creds", |
|---|
| 381 | 394 | ofs->config.override_creds ? "on" : "off"); |
|---|
| .. | .. |
|---|
| 385 | 398 | static int ovl_remount(struct super_block *sb, int *flags, char *data) |
|---|
| 386 | 399 | { |
|---|
| 387 | 400 | struct ovl_fs *ofs = sb->s_fs_info; |
|---|
| 401 | + struct super_block *upper_sb; |
|---|
| 402 | + int ret = 0; |
|---|
| 388 | 403 | |
|---|
| 389 | 404 | if (!(*flags & SB_RDONLY) && ovl_force_readonly(ofs)) |
|---|
| 390 | 405 | return -EROFS; |
|---|
| 391 | 406 | |
|---|
| 392 | | - return 0; |
|---|
| 407 | + if (*flags & SB_RDONLY && !sb_rdonly(sb)) { |
|---|
| 408 | + upper_sb = ovl_upper_mnt(ofs)->mnt_sb; |
|---|
| 409 | + if (ovl_should_sync(ofs)) { |
|---|
| 410 | + down_read(&upper_sb->s_umount); |
|---|
| 411 | + ret = sync_filesystem(upper_sb); |
|---|
| 412 | + up_read(&upper_sb->s_umount); |
|---|
| 413 | + } |
|---|
| 414 | + } |
|---|
| 415 | + |
|---|
| 416 | + return ret; |
|---|
| 393 | 417 | } |
|---|
| 394 | 418 | |
|---|
| 395 | 419 | static const struct super_operations ovl_super_operations = { |
|---|
| 396 | 420 | .alloc_inode = ovl_alloc_inode, |
|---|
| 421 | + .free_inode = ovl_free_inode, |
|---|
| 397 | 422 | .destroy_inode = ovl_destroy_inode, |
|---|
| 398 | 423 | .drop_inode = generic_delete_inode, |
|---|
| 399 | 424 | .put_super = ovl_put_super, |
|---|
| .. | .. |
|---|
| 418 | 443 | OPT_XINO_AUTO, |
|---|
| 419 | 444 | OPT_METACOPY_ON, |
|---|
| 420 | 445 | OPT_METACOPY_OFF, |
|---|
| 446 | + OPT_VOLATILE, |
|---|
| 421 | 447 | OPT_OVERRIDE_CREDS_ON, |
|---|
| 422 | 448 | OPT_OVERRIDE_CREDS_OFF, |
|---|
| 423 | 449 | OPT_ERR, |
|---|
| .. | .. |
|---|
| 438 | 464 | {OPT_XINO_AUTO, "xino=auto"}, |
|---|
| 439 | 465 | {OPT_METACOPY_ON, "metacopy=on"}, |
|---|
| 440 | 466 | {OPT_METACOPY_OFF, "metacopy=off"}, |
|---|
| 467 | + {OPT_VOLATILE, "volatile"}, |
|---|
| 441 | 468 | {OPT_OVERRIDE_CREDS_ON, "override_creds=on"}, |
|---|
| 442 | 469 | {OPT_OVERRIDE_CREDS_OFF, "override_creds=off"}, |
|---|
| 443 | 470 | {OPT_ERR, NULL} |
|---|
| .. | .. |
|---|
| 481 | 508 | if (ovl_redirect_always_follow) |
|---|
| 482 | 509 | config->redirect_follow = true; |
|---|
| 483 | 510 | } else if (strcmp(mode, "nofollow") != 0) { |
|---|
| 484 | | - pr_err("overlayfs: bad mount option \"redirect_dir=%s\"\n", |
|---|
| 511 | + pr_err("bad mount option \"redirect_dir=%s\"\n", |
|---|
| 485 | 512 | mode); |
|---|
| 486 | 513 | return -EINVAL; |
|---|
| 487 | 514 | } |
|---|
| .. | .. |
|---|
| 494 | 521 | char *p; |
|---|
| 495 | 522 | int err; |
|---|
| 496 | 523 | bool metacopy_opt = false, redirect_opt = false; |
|---|
| 524 | + bool nfs_export_opt = false, index_opt = false; |
|---|
| 497 | 525 | |
|---|
| 498 | 526 | config->redirect_mode = kstrdup(ovl_redirect_mode_def(), GFP_KERNEL); |
|---|
| 499 | 527 | if (!config->redirect_mode) |
|---|
| .. | .. |
|---|
| 544 | 572 | |
|---|
| 545 | 573 | case OPT_INDEX_ON: |
|---|
| 546 | 574 | config->index = true; |
|---|
| 575 | + index_opt = true; |
|---|
| 547 | 576 | break; |
|---|
| 548 | 577 | |
|---|
| 549 | 578 | case OPT_INDEX_OFF: |
|---|
| 550 | 579 | config->index = false; |
|---|
| 580 | + index_opt = true; |
|---|
| 551 | 581 | break; |
|---|
| 552 | 582 | |
|---|
| 553 | 583 | case OPT_NFS_EXPORT_ON: |
|---|
| 554 | 584 | config->nfs_export = true; |
|---|
| 585 | + nfs_export_opt = true; |
|---|
| 555 | 586 | break; |
|---|
| 556 | 587 | |
|---|
| 557 | 588 | case OPT_NFS_EXPORT_OFF: |
|---|
| 558 | 589 | config->nfs_export = false; |
|---|
| 590 | + nfs_export_opt = true; |
|---|
| 559 | 591 | break; |
|---|
| 560 | 592 | |
|---|
| 561 | 593 | case OPT_XINO_ON: |
|---|
| .. | .. |
|---|
| 577 | 609 | |
|---|
| 578 | 610 | case OPT_METACOPY_OFF: |
|---|
| 579 | 611 | config->metacopy = false; |
|---|
| 612 | + metacopy_opt = true; |
|---|
| 613 | + break; |
|---|
| 614 | + |
|---|
| 615 | + case OPT_VOLATILE: |
|---|
| 616 | + config->ovl_volatile = true; |
|---|
| 580 | 617 | break; |
|---|
| 581 | 618 | |
|---|
| 582 | 619 | case OPT_OVERRIDE_CREDS_ON: |
|---|
| .. | .. |
|---|
| 588 | 625 | break; |
|---|
| 589 | 626 | |
|---|
| 590 | 627 | default: |
|---|
| 591 | | - pr_err("overlayfs: unrecognized mount option \"%s\" or missing value\n", p); |
|---|
| 628 | + pr_err("unrecognized mount option \"%s\" or missing value\n", |
|---|
| 629 | + p); |
|---|
| 592 | 630 | return -EINVAL; |
|---|
| 593 | 631 | } |
|---|
| 594 | 632 | } |
|---|
| 595 | 633 | |
|---|
| 596 | | - /* Workdir is useless in non-upper mount */ |
|---|
| 597 | | - if (!config->upperdir && config->workdir) { |
|---|
| 598 | | - pr_info("overlayfs: option \"workdir=%s\" is useless in a non-upper mount, ignore\n", |
|---|
| 599 | | - config->workdir); |
|---|
| 600 | | - kfree(config->workdir); |
|---|
| 601 | | - config->workdir = NULL; |
|---|
| 634 | + /* Workdir/index are useless in non-upper mount */ |
|---|
| 635 | + if (!config->upperdir) { |
|---|
| 636 | + if (config->workdir) { |
|---|
| 637 | + pr_info("option \"workdir=%s\" is useless in a non-upper mount, ignore\n", |
|---|
| 638 | + config->workdir); |
|---|
| 639 | + kfree(config->workdir); |
|---|
| 640 | + config->workdir = NULL; |
|---|
| 641 | + } |
|---|
| 642 | + if (config->index && index_opt) { |
|---|
| 643 | + pr_info("option \"index=on\" is useless in a non-upper mount, ignore\n"); |
|---|
| 644 | + index_opt = false; |
|---|
| 645 | + } |
|---|
| 646 | + config->index = false; |
|---|
| 647 | + } |
|---|
| 648 | + |
|---|
| 649 | + if (!config->upperdir && config->ovl_volatile) { |
|---|
| 650 | + pr_info("option \"volatile\" is meaningless in a non-upper mount, ignoring it.\n"); |
|---|
| 651 | + config->ovl_volatile = false; |
|---|
| 602 | 652 | } |
|---|
| 603 | 653 | |
|---|
| 604 | 654 | err = ovl_parse_redirect_mode(config, config->redirect_mode); |
|---|
| .. | .. |
|---|
| 615 | 665 | /* Resolve metacopy -> redirect_dir dependency */ |
|---|
| 616 | 666 | if (config->metacopy && !config->redirect_dir) { |
|---|
| 617 | 667 | if (metacopy_opt && redirect_opt) { |
|---|
| 618 | | - pr_err("overlayfs: conflicting options: metacopy=on,redirect_dir=%s\n", |
|---|
| 668 | + pr_err("conflicting options: metacopy=on,redirect_dir=%s\n", |
|---|
| 619 | 669 | config->redirect_mode); |
|---|
| 620 | 670 | return -EINVAL; |
|---|
| 621 | 671 | } |
|---|
| .. | .. |
|---|
| 624 | 674 | * There was an explicit redirect_dir=... that resulted |
|---|
| 625 | 675 | * in this conflict. |
|---|
| 626 | 676 | */ |
|---|
| 627 | | - pr_info("overlayfs: disabling metacopy due to redirect_dir=%s\n", |
|---|
| 677 | + pr_info("disabling metacopy due to redirect_dir=%s\n", |
|---|
| 628 | 678 | config->redirect_mode); |
|---|
| 629 | 679 | config->metacopy = false; |
|---|
| 630 | 680 | } else { |
|---|
| 631 | 681 | /* Automatically enable redirect otherwise. */ |
|---|
| 632 | 682 | config->redirect_follow = config->redirect_dir = true; |
|---|
| 683 | + } |
|---|
| 684 | + } |
|---|
| 685 | + |
|---|
| 686 | + /* Resolve nfs_export -> index dependency */ |
|---|
| 687 | + if (config->nfs_export && !config->index) { |
|---|
| 688 | + if (!config->upperdir && config->redirect_follow) { |
|---|
| 689 | + pr_info("NFS export requires \"redirect_dir=nofollow\" on non-upper mount, falling back to nfs_export=off.\n"); |
|---|
| 690 | + config->nfs_export = false; |
|---|
| 691 | + } else if (nfs_export_opt && index_opt) { |
|---|
| 692 | + pr_err("conflicting options: nfs_export=on,index=off\n"); |
|---|
| 693 | + return -EINVAL; |
|---|
| 694 | + } else if (index_opt) { |
|---|
| 695 | + /* |
|---|
| 696 | + * There was an explicit index=off that resulted |
|---|
| 697 | + * in this conflict. |
|---|
| 698 | + */ |
|---|
| 699 | + pr_info("disabling nfs_export due to index=off\n"); |
|---|
| 700 | + config->nfs_export = false; |
|---|
| 701 | + } else { |
|---|
| 702 | + /* Automatically enable index otherwise. */ |
|---|
| 703 | + config->index = true; |
|---|
| 704 | + } |
|---|
| 705 | + } |
|---|
| 706 | + |
|---|
| 707 | + /* Resolve nfs_export -> !metacopy dependency */ |
|---|
| 708 | + if (config->nfs_export && config->metacopy) { |
|---|
| 709 | + if (nfs_export_opt && metacopy_opt) { |
|---|
| 710 | + pr_err("conflicting options: nfs_export=on,metacopy=on\n"); |
|---|
| 711 | + return -EINVAL; |
|---|
| 712 | + } |
|---|
| 713 | + if (metacopy_opt) { |
|---|
| 714 | + /* |
|---|
| 715 | + * There was an explicit metacopy=on that resulted |
|---|
| 716 | + * in this conflict. |
|---|
| 717 | + */ |
|---|
| 718 | + pr_info("disabling nfs_export due to metacopy=on\n"); |
|---|
| 719 | + config->nfs_export = false; |
|---|
| 720 | + } else { |
|---|
| 721 | + /* |
|---|
| 722 | + * There was an explicit nfs_export=on that resulted |
|---|
| 723 | + * in this conflict. |
|---|
| 724 | + */ |
|---|
| 725 | + pr_info("disabling metacopy due to nfs_export=on\n"); |
|---|
| 726 | + config->metacopy = false; |
|---|
| 633 | 727 | } |
|---|
| 634 | 728 | } |
|---|
| 635 | 729 | |
|---|
| .. | .. |
|---|
| 643 | 737 | const char *name, bool persist) |
|---|
| 644 | 738 | { |
|---|
| 645 | 739 | struct inode *dir = ofs->workbasedir->d_inode; |
|---|
| 646 | | - struct vfsmount *mnt = ofs->upper_mnt; |
|---|
| 740 | + struct vfsmount *mnt = ovl_upper_mnt(ofs); |
|---|
| 647 | 741 | struct dentry *work; |
|---|
| 648 | 742 | int err; |
|---|
| 649 | 743 | bool retried = false; |
|---|
| 650 | | - bool locked = false; |
|---|
| 651 | 744 | |
|---|
| 652 | 745 | inode_lock_nested(dir, I_MUTEX_PARENT); |
|---|
| 653 | | - locked = true; |
|---|
| 654 | | - |
|---|
| 655 | 746 | retry: |
|---|
| 656 | 747 | work = lookup_one_len(name, ofs->workbasedir, strlen(name)); |
|---|
| 657 | 748 | |
|---|
| .. | .. |
|---|
| 670 | 761 | goto out_unlock; |
|---|
| 671 | 762 | |
|---|
| 672 | 763 | retried = true; |
|---|
| 673 | | - ovl_workdir_cleanup(dir, mnt, work, 0); |
|---|
| 764 | + err = ovl_workdir_cleanup(dir, mnt, work, 0); |
|---|
| 674 | 765 | dput(work); |
|---|
| 766 | + if (err == -EINVAL) { |
|---|
| 767 | + work = ERR_PTR(err); |
|---|
| 768 | + goto out_unlock; |
|---|
| 769 | + } |
|---|
| 675 | 770 | goto retry; |
|---|
| 676 | 771 | } |
|---|
| 677 | 772 | |
|---|
| .. | .. |
|---|
| 716 | 811 | goto out_err; |
|---|
| 717 | 812 | } |
|---|
| 718 | 813 | out_unlock: |
|---|
| 719 | | - if (locked) |
|---|
| 720 | | - inode_unlock(dir); |
|---|
| 721 | | - |
|---|
| 814 | + inode_unlock(dir); |
|---|
| 722 | 815 | return work; |
|---|
| 723 | 816 | |
|---|
| 724 | 817 | out_dput: |
|---|
| 725 | 818 | dput(work); |
|---|
| 726 | 819 | out_err: |
|---|
| 727 | | - pr_warn("overlayfs: failed to create directory %s/%s (errno: %i); mounting read-only\n", |
|---|
| 820 | + pr_warn("failed to create directory %s/%s (errno: %i); mounting read-only\n", |
|---|
| 728 | 821 | ofs->config.workdir, name, -err); |
|---|
| 729 | 822 | work = NULL; |
|---|
| 730 | 823 | goto out_unlock; |
|---|
| .. | .. |
|---|
| 748 | 841 | int err = -EINVAL; |
|---|
| 749 | 842 | |
|---|
| 750 | 843 | if (!*name) { |
|---|
| 751 | | - pr_err("overlayfs: empty lowerdir\n"); |
|---|
| 844 | + pr_err("empty lowerdir\n"); |
|---|
| 752 | 845 | goto out; |
|---|
| 753 | 846 | } |
|---|
| 754 | 847 | err = kern_path(name, LOOKUP_FOLLOW, path); |
|---|
| 755 | 848 | if (err) { |
|---|
| 756 | | - pr_err("overlayfs: failed to resolve '%s': %i\n", name, err); |
|---|
| 849 | + pr_err("failed to resolve '%s': %i\n", name, err); |
|---|
| 757 | 850 | goto out; |
|---|
| 758 | 851 | } |
|---|
| 759 | 852 | err = -EINVAL; |
|---|
| 760 | 853 | if (ovl_dentry_weird(path->dentry)) { |
|---|
| 761 | | - pr_err("overlayfs: filesystem on '%s' not supported\n", name); |
|---|
| 854 | + pr_err("filesystem on '%s' not supported\n", name); |
|---|
| 762 | 855 | goto out_put; |
|---|
| 763 | 856 | } |
|---|
| 764 | 857 | if (!d_is_dir(path->dentry)) { |
|---|
| 765 | | - pr_err("overlayfs: '%s' not a directory\n", name); |
|---|
| 858 | + pr_err("'%s' not a directory\n", name); |
|---|
| 766 | 859 | goto out_put; |
|---|
| 767 | 860 | } |
|---|
| 768 | 861 | return 0; |
|---|
| .. | .. |
|---|
| 782 | 875 | ovl_unescape(tmp); |
|---|
| 783 | 876 | err = ovl_mount_dir_noesc(tmp, path); |
|---|
| 784 | 877 | |
|---|
| 785 | | - if (!err) |
|---|
| 786 | | - if (ovl_dentry_remote(path->dentry)) { |
|---|
| 787 | | - pr_err("overlayfs: filesystem on '%s' not supported as upperdir\n", |
|---|
| 788 | | - tmp); |
|---|
| 789 | | - path_put_init(path); |
|---|
| 790 | | - err = -EINVAL; |
|---|
| 791 | | - } |
|---|
| 878 | + if (!err && path->dentry->d_flags & DCACHE_OP_REAL) { |
|---|
| 879 | + pr_err("filesystem on '%s' not supported as upperdir\n", |
|---|
| 880 | + tmp); |
|---|
| 881 | + path_put_init(path); |
|---|
| 882 | + err = -EINVAL; |
|---|
| 883 | + } |
|---|
| 792 | 884 | kfree(tmp); |
|---|
| 793 | 885 | } |
|---|
| 794 | 886 | return err; |
|---|
| .. | .. |
|---|
| 801 | 893 | int err = vfs_statfs(path, &statfs); |
|---|
| 802 | 894 | |
|---|
| 803 | 895 | if (err) |
|---|
| 804 | | - pr_err("overlayfs: statfs failed on '%s'\n", name); |
|---|
| 896 | + pr_err("statfs failed on '%s'\n", name); |
|---|
| 805 | 897 | else |
|---|
| 806 | 898 | ofs->namelen = max(ofs->namelen, statfs.f_namelen); |
|---|
| 807 | 899 | |
|---|
| .. | .. |
|---|
| 809 | 901 | } |
|---|
| 810 | 902 | |
|---|
| 811 | 903 | static int ovl_lower_dir(const char *name, struct path *path, |
|---|
| 812 | | - struct ovl_fs *ofs, int *stack_depth, bool *remote) |
|---|
| 904 | + struct ovl_fs *ofs, int *stack_depth) |
|---|
| 813 | 905 | { |
|---|
| 814 | 906 | int fh_type; |
|---|
| 815 | 907 | int err; |
|---|
| 816 | 908 | |
|---|
| 817 | 909 | err = ovl_mount_dir_noesc(name, path); |
|---|
| 818 | 910 | if (err) |
|---|
| 819 | | - goto out; |
|---|
| 911 | + return err; |
|---|
| 820 | 912 | |
|---|
| 821 | 913 | err = ovl_check_namelen(path, ofs, name); |
|---|
| 822 | 914 | if (err) |
|---|
| 823 | | - goto out_put; |
|---|
| 915 | + return err; |
|---|
| 824 | 916 | |
|---|
| 825 | 917 | *stack_depth = max(*stack_depth, path->mnt->mnt_sb->s_stack_depth); |
|---|
| 826 | | - |
|---|
| 827 | | - if (ovl_dentry_remote(path->dentry)) |
|---|
| 828 | | - *remote = true; |
|---|
| 829 | 918 | |
|---|
| 830 | 919 | /* |
|---|
| 831 | 920 | * The inodes index feature and NFS export need to encode and decode |
|---|
| .. | .. |
|---|
| 836 | 925 | (ofs->config.index && ofs->config.upperdir)) && !fh_type) { |
|---|
| 837 | 926 | ofs->config.index = false; |
|---|
| 838 | 927 | ofs->config.nfs_export = false; |
|---|
| 839 | | - pr_warn("overlayfs: fs on '%s' does not support file handles, falling back to index=off,nfs_export=off.\n", |
|---|
| 928 | + pr_warn("fs on '%s' does not support file handles, falling back to index=off,nfs_export=off.\n", |
|---|
| 840 | 929 | name); |
|---|
| 841 | 930 | } |
|---|
| 842 | 931 | |
|---|
| 843 | 932 | /* Check if lower fs has 32bit inode numbers */ |
|---|
| 844 | 933 | if (fh_type != FILEID_INO32_GEN) |
|---|
| 845 | | - ofs->xino_bits = 0; |
|---|
| 934 | + ofs->xino_mode = -1; |
|---|
| 846 | 935 | |
|---|
| 847 | 936 | return 0; |
|---|
| 848 | | - |
|---|
| 849 | | -out_put: |
|---|
| 850 | | - path_put_init(path); |
|---|
| 851 | | -out: |
|---|
| 852 | | - return err; |
|---|
| 853 | 937 | } |
|---|
| 854 | 938 | |
|---|
| 855 | 939 | /* Workdir should not be subdir of upperdir and vice versa */ |
|---|
| .. | .. |
|---|
| 887 | 971 | static int __maybe_unused |
|---|
| 888 | 972 | ovl_posix_acl_xattr_get(const struct xattr_handler *handler, |
|---|
| 889 | 973 | struct dentry *dentry, struct inode *inode, |
|---|
| 890 | | - const char *name, void *buffer, size_t size) |
|---|
| 974 | + const char *name, void *buffer, size_t size, int flags) |
|---|
| 891 | 975 | { |
|---|
| 892 | | - return ovl_xattr_get(dentry, inode, handler->name, buffer, size); |
|---|
| 893 | | -} |
|---|
| 894 | | - |
|---|
| 895 | | -static int __maybe_unused |
|---|
| 896 | | -__ovl_posix_acl_xattr_get(const struct xattr_handler *handler, |
|---|
| 897 | | - struct dentry *dentry, struct inode *inode, |
|---|
| 898 | | - const char *name, void *buffer, size_t size) |
|---|
| 899 | | -{ |
|---|
| 900 | | - return __ovl_xattr_get(dentry, inode, handler->name, buffer, size); |
|---|
| 976 | + return ovl_xattr_get(dentry, inode, handler->name, buffer, size, flags); |
|---|
| 901 | 977 | } |
|---|
| 902 | 978 | |
|---|
| 903 | 979 | static int __maybe_unused |
|---|
| .. | .. |
|---|
| 960 | 1036 | |
|---|
| 961 | 1037 | static int ovl_own_xattr_get(const struct xattr_handler *handler, |
|---|
| 962 | 1038 | struct dentry *dentry, struct inode *inode, |
|---|
| 963 | | - const char *name, void *buffer, size_t size) |
|---|
| 1039 | + const char *name, void *buffer, size_t size, |
|---|
| 1040 | + int flags) |
|---|
| 964 | 1041 | { |
|---|
| 965 | 1042 | return -EOPNOTSUPP; |
|---|
| 966 | 1043 | } |
|---|
| .. | .. |
|---|
| 975 | 1052 | |
|---|
| 976 | 1053 | static int ovl_other_xattr_get(const struct xattr_handler *handler, |
|---|
| 977 | 1054 | struct dentry *dentry, struct inode *inode, |
|---|
| 978 | | - const char *name, void *buffer, size_t size) |
|---|
| 1055 | + const char *name, void *buffer, size_t size, |
|---|
| 1056 | + int flags) |
|---|
| 979 | 1057 | { |
|---|
| 980 | | - return ovl_xattr_get(dentry, inode, name, buffer, size); |
|---|
| 981 | | -} |
|---|
| 982 | | - |
|---|
| 983 | | -static int __ovl_other_xattr_get(const struct xattr_handler *handler, |
|---|
| 984 | | - struct dentry *dentry, struct inode *inode, |
|---|
| 985 | | - const char *name, void *buffer, size_t size) |
|---|
| 986 | | -{ |
|---|
| 987 | | - return __ovl_xattr_get(dentry, inode, name, buffer, size); |
|---|
| 1058 | + return ovl_xattr_get(dentry, inode, name, buffer, size, flags); |
|---|
| 988 | 1059 | } |
|---|
| 989 | 1060 | |
|---|
| 990 | 1061 | static int ovl_other_xattr_set(const struct xattr_handler *handler, |
|---|
| .. | .. |
|---|
| 1000 | 1071 | .name = XATTR_NAME_POSIX_ACL_ACCESS, |
|---|
| 1001 | 1072 | .flags = ACL_TYPE_ACCESS, |
|---|
| 1002 | 1073 | .get = ovl_posix_acl_xattr_get, |
|---|
| 1003 | | - .__get = __ovl_posix_acl_xattr_get, |
|---|
| 1004 | 1074 | .set = ovl_posix_acl_xattr_set, |
|---|
| 1005 | 1075 | }; |
|---|
| 1006 | 1076 | |
|---|
| .. | .. |
|---|
| 1009 | 1079 | .name = XATTR_NAME_POSIX_ACL_DEFAULT, |
|---|
| 1010 | 1080 | .flags = ACL_TYPE_DEFAULT, |
|---|
| 1011 | 1081 | .get = ovl_posix_acl_xattr_get, |
|---|
| 1012 | | - .__get = __ovl_posix_acl_xattr_get, |
|---|
| 1013 | 1082 | .set = ovl_posix_acl_xattr_set, |
|---|
| 1014 | 1083 | }; |
|---|
| 1015 | 1084 | |
|---|
| .. | .. |
|---|
| 1022 | 1091 | static const struct xattr_handler ovl_other_xattr_handler = { |
|---|
| 1023 | 1092 | .prefix = "", /* catch all */ |
|---|
| 1024 | 1093 | .get = ovl_other_xattr_get, |
|---|
| 1025 | | - .__get = __ovl_other_xattr_get, |
|---|
| 1026 | 1094 | .set = ovl_other_xattr_set, |
|---|
| 1027 | 1095 | }; |
|---|
| 1028 | 1096 | |
|---|
| .. | .. |
|---|
| 1046 | 1114 | err = PTR_ERR_OR_ZERO(trap); |
|---|
| 1047 | 1115 | if (err) { |
|---|
| 1048 | 1116 | if (err == -ELOOP) |
|---|
| 1049 | | - pr_err("overlayfs: conflicting %s path\n", name); |
|---|
| 1117 | + pr_err("conflicting %s path\n", name); |
|---|
| 1050 | 1118 | return err; |
|---|
| 1051 | 1119 | } |
|---|
| 1052 | 1120 | |
|---|
| .. | .. |
|---|
| 1063 | 1131 | static int ovl_report_in_use(struct ovl_fs *ofs, const char *name) |
|---|
| 1064 | 1132 | { |
|---|
| 1065 | 1133 | if (ofs->config.index) { |
|---|
| 1066 | | - pr_err("overlayfs: %s is in-use as upperdir/workdir of another mount, mount with '-o index=off' to override exclusive upperdir protection.\n", |
|---|
| 1134 | + pr_err("%s is in-use as upperdir/workdir of another mount, mount with '-o index=off' to override exclusive upperdir protection.\n", |
|---|
| 1067 | 1135 | name); |
|---|
| 1068 | 1136 | return -EBUSY; |
|---|
| 1069 | 1137 | } else { |
|---|
| 1070 | | - pr_warn("overlayfs: %s is in-use as upperdir/workdir of another mount, accessing files from both mounts will result in undefined behavior.\n", |
|---|
| 1138 | + pr_warn("%s is in-use as upperdir/workdir of another mount, accessing files from both mounts will result in undefined behavior.\n", |
|---|
| 1071 | 1139 | name); |
|---|
| 1072 | 1140 | return 0; |
|---|
| 1073 | 1141 | } |
|---|
| 1074 | 1142 | } |
|---|
| 1075 | 1143 | |
|---|
| 1076 | 1144 | static int ovl_get_upper(struct super_block *sb, struct ovl_fs *ofs, |
|---|
| 1077 | | - struct path *upperpath) |
|---|
| 1145 | + struct ovl_layer *upper_layer, struct path *upperpath) |
|---|
| 1078 | 1146 | { |
|---|
| 1079 | 1147 | struct vfsmount *upper_mnt; |
|---|
| 1080 | 1148 | int err; |
|---|
| .. | .. |
|---|
| 1085 | 1153 | |
|---|
| 1086 | 1154 | /* Upper fs should not be r/o */ |
|---|
| 1087 | 1155 | if (sb_rdonly(upperpath->mnt->mnt_sb)) { |
|---|
| 1088 | | - pr_err("overlayfs: upper fs is r/o, try multi-lower layers mount\n"); |
|---|
| 1156 | + pr_err("upper fs is r/o, try multi-lower layers mount\n"); |
|---|
| 1089 | 1157 | err = -EINVAL; |
|---|
| 1090 | 1158 | goto out; |
|---|
| 1091 | 1159 | } |
|---|
| .. | .. |
|---|
| 1094 | 1162 | if (err) |
|---|
| 1095 | 1163 | goto out; |
|---|
| 1096 | 1164 | |
|---|
| 1097 | | - err = ovl_setup_trap(sb, upperpath->dentry, &ofs->upperdir_trap, |
|---|
| 1165 | + err = ovl_setup_trap(sb, upperpath->dentry, &upper_layer->trap, |
|---|
| 1098 | 1166 | "upperdir"); |
|---|
| 1099 | 1167 | if (err) |
|---|
| 1100 | 1168 | goto out; |
|---|
| .. | .. |
|---|
| 1102 | 1170 | upper_mnt = clone_private_mount(upperpath); |
|---|
| 1103 | 1171 | err = PTR_ERR(upper_mnt); |
|---|
| 1104 | 1172 | if (IS_ERR(upper_mnt)) { |
|---|
| 1105 | | - pr_err("overlayfs: failed to clone upperpath\n"); |
|---|
| 1173 | + pr_err("failed to clone upperpath\n"); |
|---|
| 1106 | 1174 | goto out; |
|---|
| 1107 | 1175 | } |
|---|
| 1108 | 1176 | |
|---|
| 1109 | 1177 | /* Don't inherit atime flags */ |
|---|
| 1110 | 1178 | upper_mnt->mnt_flags &= ~(MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME); |
|---|
| 1111 | | - ofs->upper_mnt = upper_mnt; |
|---|
| 1179 | + upper_layer->mnt = upper_mnt; |
|---|
| 1180 | + upper_layer->idx = 0; |
|---|
| 1181 | + upper_layer->fsid = 0; |
|---|
| 1112 | 1182 | |
|---|
| 1113 | | - if (ovl_inuse_trylock(ofs->upper_mnt->mnt_root)) { |
|---|
| 1183 | + /* |
|---|
| 1184 | + * Inherit SB_NOSEC flag from upperdir. |
|---|
| 1185 | + * |
|---|
| 1186 | + * This optimization changes behavior when a security related attribute |
|---|
| 1187 | + * (suid/sgid/security.*) is changed on an underlying layer. This is |
|---|
| 1188 | + * okay because we don't yet have guarantees in that case, but it will |
|---|
| 1189 | + * need careful treatment once we want to honour changes to underlying |
|---|
| 1190 | + * filesystems. |
|---|
| 1191 | + */ |
|---|
| 1192 | + if (upper_mnt->mnt_sb->s_flags & SB_NOSEC) |
|---|
| 1193 | + sb->s_flags |= SB_NOSEC; |
|---|
| 1194 | + |
|---|
| 1195 | + if (ovl_inuse_trylock(ovl_upper_mnt(ofs)->mnt_root)) { |
|---|
| 1114 | 1196 | ofs->upperdir_locked = true; |
|---|
| 1115 | 1197 | } else { |
|---|
| 1116 | 1198 | err = ovl_report_in_use(ofs, "upperdir"); |
|---|
| .. | .. |
|---|
| 1123 | 1205 | return err; |
|---|
| 1124 | 1206 | } |
|---|
| 1125 | 1207 | |
|---|
| 1208 | +/* |
|---|
| 1209 | + * Returns 1 if RENAME_WHITEOUT is supported, 0 if not supported and |
|---|
| 1210 | + * negative values if error is encountered. |
|---|
| 1211 | + */ |
|---|
| 1212 | +static int ovl_check_rename_whiteout(struct dentry *workdir) |
|---|
| 1213 | +{ |
|---|
| 1214 | + struct inode *dir = d_inode(workdir); |
|---|
| 1215 | + struct dentry *temp; |
|---|
| 1216 | + struct dentry *dest; |
|---|
| 1217 | + struct dentry *whiteout; |
|---|
| 1218 | + struct name_snapshot name; |
|---|
| 1219 | + int err; |
|---|
| 1220 | + |
|---|
| 1221 | + inode_lock_nested(dir, I_MUTEX_PARENT); |
|---|
| 1222 | + |
|---|
| 1223 | + temp = ovl_create_temp(workdir, OVL_CATTR(S_IFREG | 0)); |
|---|
| 1224 | + err = PTR_ERR(temp); |
|---|
| 1225 | + if (IS_ERR(temp)) |
|---|
| 1226 | + goto out_unlock; |
|---|
| 1227 | + |
|---|
| 1228 | + dest = ovl_lookup_temp(workdir); |
|---|
| 1229 | + err = PTR_ERR(dest); |
|---|
| 1230 | + if (IS_ERR(dest)) { |
|---|
| 1231 | + dput(temp); |
|---|
| 1232 | + goto out_unlock; |
|---|
| 1233 | + } |
|---|
| 1234 | + |
|---|
| 1235 | + /* Name is inline and stable - using snapshot as a copy helper */ |
|---|
| 1236 | + take_dentry_name_snapshot(&name, temp); |
|---|
| 1237 | + err = ovl_do_rename(dir, temp, dir, dest, RENAME_WHITEOUT); |
|---|
| 1238 | + if (err) { |
|---|
| 1239 | + if (err == -EINVAL) |
|---|
| 1240 | + err = 0; |
|---|
| 1241 | + goto cleanup_temp; |
|---|
| 1242 | + } |
|---|
| 1243 | + |
|---|
| 1244 | + whiteout = lookup_one_len(name.name.name, workdir, name.name.len); |
|---|
| 1245 | + err = PTR_ERR(whiteout); |
|---|
| 1246 | + if (IS_ERR(whiteout)) |
|---|
| 1247 | + goto cleanup_temp; |
|---|
| 1248 | + |
|---|
| 1249 | + err = ovl_is_whiteout(whiteout); |
|---|
| 1250 | + |
|---|
| 1251 | + /* Best effort cleanup of whiteout and temp file */ |
|---|
| 1252 | + if (err) |
|---|
| 1253 | + ovl_cleanup(dir, whiteout); |
|---|
| 1254 | + dput(whiteout); |
|---|
| 1255 | + |
|---|
| 1256 | +cleanup_temp: |
|---|
| 1257 | + ovl_cleanup(dir, temp); |
|---|
| 1258 | + release_dentry_name_snapshot(&name); |
|---|
| 1259 | + dput(temp); |
|---|
| 1260 | + dput(dest); |
|---|
| 1261 | + |
|---|
| 1262 | +out_unlock: |
|---|
| 1263 | + inode_unlock(dir); |
|---|
| 1264 | + |
|---|
| 1265 | + return err; |
|---|
| 1266 | +} |
|---|
| 1267 | + |
|---|
| 1268 | +static struct dentry *ovl_lookup_or_create(struct dentry *parent, |
|---|
| 1269 | + const char *name, umode_t mode) |
|---|
| 1270 | +{ |
|---|
| 1271 | + size_t len = strlen(name); |
|---|
| 1272 | + struct dentry *child; |
|---|
| 1273 | + |
|---|
| 1274 | + inode_lock_nested(parent->d_inode, I_MUTEX_PARENT); |
|---|
| 1275 | + child = lookup_one_len(name, parent, len); |
|---|
| 1276 | + if (!IS_ERR(child) && !child->d_inode) |
|---|
| 1277 | + child = ovl_create_real(parent->d_inode, child, |
|---|
| 1278 | + OVL_CATTR(mode)); |
|---|
| 1279 | + inode_unlock(parent->d_inode); |
|---|
| 1280 | + dput(parent); |
|---|
| 1281 | + |
|---|
| 1282 | + return child; |
|---|
| 1283 | +} |
|---|
| 1284 | + |
|---|
| 1285 | +/* |
|---|
| 1286 | + * Creates $workdir/work/incompat/volatile/dirty file if it is not already |
|---|
| 1287 | + * present. |
|---|
| 1288 | + */ |
|---|
| 1289 | +static int ovl_create_volatile_dirty(struct ovl_fs *ofs) |
|---|
| 1290 | +{ |
|---|
| 1291 | + unsigned int ctr; |
|---|
| 1292 | + struct dentry *d = dget(ofs->workbasedir); |
|---|
| 1293 | + static const char *const volatile_path[] = { |
|---|
| 1294 | + OVL_WORKDIR_NAME, "incompat", "volatile", "dirty" |
|---|
| 1295 | + }; |
|---|
| 1296 | + const char *const *name = volatile_path; |
|---|
| 1297 | + |
|---|
| 1298 | + for (ctr = ARRAY_SIZE(volatile_path); ctr; ctr--, name++) { |
|---|
| 1299 | + d = ovl_lookup_or_create(d, *name, ctr > 1 ? S_IFDIR : S_IFREG); |
|---|
| 1300 | + if (IS_ERR(d)) |
|---|
| 1301 | + return PTR_ERR(d); |
|---|
| 1302 | + } |
|---|
| 1303 | + dput(d); |
|---|
| 1304 | + return 0; |
|---|
| 1305 | +} |
|---|
| 1306 | + |
|---|
| 1126 | 1307 | static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs, |
|---|
| 1127 | 1308 | struct path *workpath) |
|---|
| 1128 | 1309 | { |
|---|
| 1129 | | - struct vfsmount *mnt = ofs->upper_mnt; |
|---|
| 1130 | | - struct dentry *temp; |
|---|
| 1310 | + struct vfsmount *mnt = ovl_upper_mnt(ofs); |
|---|
| 1311 | + struct dentry *temp, *workdir; |
|---|
| 1312 | + bool rename_whiteout; |
|---|
| 1313 | + bool d_type; |
|---|
| 1131 | 1314 | int fh_type; |
|---|
| 1132 | 1315 | int err; |
|---|
| 1133 | 1316 | |
|---|
| .. | .. |
|---|
| 1135 | 1318 | if (err) |
|---|
| 1136 | 1319 | return err; |
|---|
| 1137 | 1320 | |
|---|
| 1138 | | - ofs->workdir = ovl_workdir_create(ofs, OVL_WORKDIR_NAME, false); |
|---|
| 1139 | | - if (!ofs->workdir) |
|---|
| 1321 | + workdir = ovl_workdir_create(ofs, OVL_WORKDIR_NAME, false); |
|---|
| 1322 | + err = PTR_ERR(workdir); |
|---|
| 1323 | + if (IS_ERR_OR_NULL(workdir)) |
|---|
| 1140 | 1324 | goto out; |
|---|
| 1325 | + |
|---|
| 1326 | + ofs->workdir = workdir; |
|---|
| 1141 | 1327 | |
|---|
| 1142 | 1328 | err = ovl_setup_trap(sb, ofs->workdir, &ofs->workdir_trap, "workdir"); |
|---|
| 1143 | 1329 | if (err) |
|---|
| .. | .. |
|---|
| 1153 | 1339 | if (err < 0) |
|---|
| 1154 | 1340 | goto out; |
|---|
| 1155 | 1341 | |
|---|
| 1156 | | - /* |
|---|
| 1157 | | - * We allowed this configuration and don't want to break users over |
|---|
| 1158 | | - * kernel upgrade. So warn instead of erroring out. |
|---|
| 1159 | | - */ |
|---|
| 1160 | | - if (!err) |
|---|
| 1161 | | - pr_warn("overlayfs: upper fs needs to support d_type.\n"); |
|---|
| 1342 | + d_type = err; |
|---|
| 1343 | + if (!d_type) |
|---|
| 1344 | + pr_warn("upper fs needs to support d_type.\n"); |
|---|
| 1162 | 1345 | |
|---|
| 1163 | 1346 | /* Check if upper/work fs supports O_TMPFILE */ |
|---|
| 1164 | 1347 | temp = ovl_do_tmpfile(ofs->workdir, S_IFREG | 0); |
|---|
| .. | .. |
|---|
| 1166 | 1349 | if (ofs->tmpfile) |
|---|
| 1167 | 1350 | dput(temp); |
|---|
| 1168 | 1351 | else |
|---|
| 1169 | | - pr_warn("overlayfs: upper fs does not support tmpfile.\n"); |
|---|
| 1352 | + pr_warn("upper fs does not support tmpfile.\n"); |
|---|
| 1353 | + |
|---|
| 1354 | + |
|---|
| 1355 | + /* Check if upper/work fs supports RENAME_WHITEOUT */ |
|---|
| 1356 | + err = ovl_check_rename_whiteout(ofs->workdir); |
|---|
| 1357 | + if (err < 0) |
|---|
| 1358 | + goto out; |
|---|
| 1359 | + |
|---|
| 1360 | + rename_whiteout = err; |
|---|
| 1361 | + if (!rename_whiteout) |
|---|
| 1362 | + pr_warn("upper fs does not support RENAME_WHITEOUT.\n"); |
|---|
| 1170 | 1363 | |
|---|
| 1171 | 1364 | /* |
|---|
| 1172 | 1365 | * Check if upper/work fs supports trusted.overlay.* xattr |
|---|
| 1173 | 1366 | */ |
|---|
| 1174 | | - err = ovl_do_setxattr(ofs->workdir, OVL_XATTR_OPAQUE, "0", 1, 0); |
|---|
| 1367 | + err = ovl_do_setxattr(ofs, ofs->workdir, OVL_XATTR_OPAQUE, "0", 1); |
|---|
| 1175 | 1368 | if (err) { |
|---|
| 1176 | 1369 | ofs->noxattr = true; |
|---|
| 1177 | 1370 | ofs->config.index = false; |
|---|
| 1178 | 1371 | ofs->config.metacopy = false; |
|---|
| 1179 | | - pr_warn("overlayfs: upper fs does not support xattr, falling back to index=off and metacopy=off.\n"); |
|---|
| 1372 | + pr_warn("upper fs does not support xattr, falling back to index=off and metacopy=off.\n"); |
|---|
| 1180 | 1373 | err = 0; |
|---|
| 1181 | 1374 | } else { |
|---|
| 1182 | | - vfs_removexattr(ofs->workdir, OVL_XATTR_OPAQUE); |
|---|
| 1375 | + ovl_do_removexattr(ofs, ofs->workdir, OVL_XATTR_OPAQUE); |
|---|
| 1376 | + } |
|---|
| 1377 | + |
|---|
| 1378 | + /* |
|---|
| 1379 | + * We allowed sub-optimal upper fs configuration and don't want to break |
|---|
| 1380 | + * users over kernel upgrade, but we never allowed remote upper fs, so |
|---|
| 1381 | + * we can enforce strict requirements for remote upper fs. |
|---|
| 1382 | + */ |
|---|
| 1383 | + if (ovl_dentry_remote(ofs->workdir) && |
|---|
| 1384 | + (!d_type || !rename_whiteout || ofs->noxattr)) { |
|---|
| 1385 | + pr_err("upper fs missing required features.\n"); |
|---|
| 1386 | + err = -EINVAL; |
|---|
| 1387 | + goto out; |
|---|
| 1388 | + } |
|---|
| 1389 | + |
|---|
| 1390 | + /* |
|---|
| 1391 | + * For volatile mount, create a incompat/volatile/dirty file to keep |
|---|
| 1392 | + * track of it. |
|---|
| 1393 | + */ |
|---|
| 1394 | + if (ofs->config.ovl_volatile) { |
|---|
| 1395 | + err = ovl_create_volatile_dirty(ofs); |
|---|
| 1396 | + if (err < 0) { |
|---|
| 1397 | + pr_err("Failed to create volatile/dirty file.\n"); |
|---|
| 1398 | + goto out; |
|---|
| 1399 | + } |
|---|
| 1183 | 1400 | } |
|---|
| 1184 | 1401 | |
|---|
| 1185 | 1402 | /* Check if upper/work fs supports file handles */ |
|---|
| 1186 | 1403 | fh_type = ovl_can_decode_fh(ofs->workdir->d_sb); |
|---|
| 1187 | 1404 | if (ofs->config.index && !fh_type) { |
|---|
| 1188 | 1405 | ofs->config.index = false; |
|---|
| 1189 | | - pr_warn("overlayfs: upper fs does not support file handles, falling back to index=off.\n"); |
|---|
| 1406 | + pr_warn("upper fs does not support file handles, falling back to index=off.\n"); |
|---|
| 1190 | 1407 | } |
|---|
| 1191 | 1408 | |
|---|
| 1192 | 1409 | /* Check if upper fs has 32bit inode numbers */ |
|---|
| 1193 | 1410 | if (fh_type != FILEID_INO32_GEN) |
|---|
| 1194 | | - ofs->xino_bits = 0; |
|---|
| 1411 | + ofs->xino_mode = -1; |
|---|
| 1195 | 1412 | |
|---|
| 1196 | 1413 | /* NFS export of r/w mount depends on index */ |
|---|
| 1197 | 1414 | if (ofs->config.nfs_export && !ofs->config.index) { |
|---|
| 1198 | | - pr_warn("overlayfs: NFS export requires \"index=on\", falling back to nfs_export=off.\n"); |
|---|
| 1415 | + pr_warn("NFS export requires \"index=on\", falling back to nfs_export=off.\n"); |
|---|
| 1199 | 1416 | ofs->config.nfs_export = false; |
|---|
| 1200 | 1417 | } |
|---|
| 1201 | 1418 | out: |
|---|
| .. | .. |
|---|
| 1215 | 1432 | |
|---|
| 1216 | 1433 | err = -EINVAL; |
|---|
| 1217 | 1434 | if (upperpath->mnt != workpath.mnt) { |
|---|
| 1218 | | - pr_err("overlayfs: workdir and upperdir must reside under the same mount\n"); |
|---|
| 1435 | + pr_err("workdir and upperdir must reside under the same mount\n"); |
|---|
| 1219 | 1436 | goto out; |
|---|
| 1220 | 1437 | } |
|---|
| 1221 | 1438 | if (!ovl_workdir_ok(workpath.dentry, upperpath->dentry)) { |
|---|
| 1222 | | - pr_err("overlayfs: workdir and upperdir must be separate subtrees\n"); |
|---|
| 1439 | + pr_err("workdir and upperdir must be separate subtrees\n"); |
|---|
| 1223 | 1440 | goto out; |
|---|
| 1224 | 1441 | } |
|---|
| 1225 | 1442 | |
|---|
| .. | .. |
|---|
| 1249 | 1466 | static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ofs, |
|---|
| 1250 | 1467 | struct ovl_entry *oe, struct path *upperpath) |
|---|
| 1251 | 1468 | { |
|---|
| 1252 | | - struct vfsmount *mnt = ofs->upper_mnt; |
|---|
| 1469 | + struct vfsmount *mnt = ovl_upper_mnt(ofs); |
|---|
| 1470 | + struct dentry *indexdir; |
|---|
| 1253 | 1471 | int err; |
|---|
| 1254 | 1472 | |
|---|
| 1255 | 1473 | err = mnt_want_write(mnt); |
|---|
| .. | .. |
|---|
| 1257 | 1475 | return err; |
|---|
| 1258 | 1476 | |
|---|
| 1259 | 1477 | /* Verify lower root is upper root origin */ |
|---|
| 1260 | | - err = ovl_verify_origin(upperpath->dentry, oe->lowerstack[0].dentry, |
|---|
| 1261 | | - true); |
|---|
| 1478 | + err = ovl_verify_origin(ofs, upperpath->dentry, |
|---|
| 1479 | + oe->lowerstack[0].dentry, true); |
|---|
| 1262 | 1480 | if (err) { |
|---|
| 1263 | | - pr_err("overlayfs: failed to verify upper root origin\n"); |
|---|
| 1481 | + pr_err("failed to verify upper root origin\n"); |
|---|
| 1264 | 1482 | goto out; |
|---|
| 1265 | 1483 | } |
|---|
| 1266 | 1484 | |
|---|
| 1267 | | - ofs->indexdir = ovl_workdir_create(ofs, OVL_INDEXDIR_NAME, true); |
|---|
| 1268 | | - if (ofs->indexdir) { |
|---|
| 1485 | + /* index dir will act also as workdir */ |
|---|
| 1486 | + iput(ofs->workdir_trap); |
|---|
| 1487 | + ofs->workdir_trap = NULL; |
|---|
| 1488 | + dput(ofs->workdir); |
|---|
| 1489 | + ofs->workdir = NULL; |
|---|
| 1490 | + indexdir = ovl_workdir_create(ofs, OVL_INDEXDIR_NAME, true); |
|---|
| 1491 | + if (IS_ERR(indexdir)) { |
|---|
| 1492 | + err = PTR_ERR(indexdir); |
|---|
| 1493 | + } else if (indexdir) { |
|---|
| 1494 | + ofs->indexdir = indexdir; |
|---|
| 1495 | + ofs->workdir = dget(indexdir); |
|---|
| 1496 | + |
|---|
| 1269 | 1497 | err = ovl_setup_trap(sb, ofs->indexdir, &ofs->indexdir_trap, |
|---|
| 1270 | 1498 | "indexdir"); |
|---|
| 1271 | 1499 | if (err) |
|---|
| .. | .. |
|---|
| 1279 | 1507 | * "trusted.overlay.upper" to indicate that index may have |
|---|
| 1280 | 1508 | * directory entries. |
|---|
| 1281 | 1509 | */ |
|---|
| 1282 | | - if (ovl_check_origin_xattr(ofs->indexdir)) { |
|---|
| 1283 | | - err = ovl_verify_set_fh(ofs->indexdir, OVL_XATTR_ORIGIN, |
|---|
| 1510 | + if (ovl_check_origin_xattr(ofs, ofs->indexdir)) { |
|---|
| 1511 | + err = ovl_verify_set_fh(ofs, ofs->indexdir, |
|---|
| 1512 | + OVL_XATTR_ORIGIN, |
|---|
| 1284 | 1513 | upperpath->dentry, true, false); |
|---|
| 1285 | 1514 | if (err) |
|---|
| 1286 | | - pr_err("overlayfs: failed to verify index dir 'origin' xattr\n"); |
|---|
| 1515 | + pr_err("failed to verify index dir 'origin' xattr\n"); |
|---|
| 1287 | 1516 | } |
|---|
| 1288 | | - err = ovl_verify_upper(ofs->indexdir, upperpath->dentry, true); |
|---|
| 1517 | + err = ovl_verify_upper(ofs, ofs->indexdir, upperpath->dentry, |
|---|
| 1518 | + true); |
|---|
| 1289 | 1519 | if (err) |
|---|
| 1290 | | - pr_err("overlayfs: failed to verify index dir 'upper' xattr\n"); |
|---|
| 1520 | + pr_err("failed to verify index dir 'upper' xattr\n"); |
|---|
| 1291 | 1521 | |
|---|
| 1292 | 1522 | /* Cleanup bad/stale/orphan index entries */ |
|---|
| 1293 | 1523 | if (!err) |
|---|
| 1294 | 1524 | err = ovl_indexdir_cleanup(ofs); |
|---|
| 1295 | 1525 | } |
|---|
| 1296 | 1526 | if (err || !ofs->indexdir) |
|---|
| 1297 | | - pr_warn("overlayfs: try deleting index dir or mounting with '-o index=off' to disable inodes index.\n"); |
|---|
| 1527 | + pr_warn("try deleting index dir or mounting with '-o index=off' to disable inodes index.\n"); |
|---|
| 1298 | 1528 | |
|---|
| 1299 | 1529 | out: |
|---|
| 1300 | 1530 | mnt_drop_write(mnt); |
|---|
| 1301 | 1531 | return err; |
|---|
| 1302 | 1532 | } |
|---|
| 1303 | 1533 | |
|---|
| 1304 | | -/* Get a unique fsid for the layer */ |
|---|
| 1305 | | -static int ovl_get_fsid(struct ovl_fs *ofs, struct super_block *sb) |
|---|
| 1534 | +static bool ovl_lower_uuid_ok(struct ovl_fs *ofs, const uuid_t *uuid) |
|---|
| 1306 | 1535 | { |
|---|
| 1536 | + unsigned int i; |
|---|
| 1537 | + |
|---|
| 1538 | + if (!ofs->config.nfs_export && !ovl_upper_mnt(ofs)) |
|---|
| 1539 | + return true; |
|---|
| 1540 | + |
|---|
| 1541 | + /* |
|---|
| 1542 | + * We allow using single lower with null uuid for index and nfs_export |
|---|
| 1543 | + * for example to support those features with single lower squashfs. |
|---|
| 1544 | + * To avoid regressions in setups of overlay with re-formatted lower |
|---|
| 1545 | + * squashfs, do not allow decoding origin with lower null uuid unless |
|---|
| 1546 | + * user opted-in to one of the new features that require following the |
|---|
| 1547 | + * lower inode of non-dir upper. |
|---|
| 1548 | + */ |
|---|
| 1549 | + if (!ofs->config.index && !ofs->config.metacopy && !ofs->config.xino && |
|---|
| 1550 | + uuid_is_null(uuid)) |
|---|
| 1551 | + return false; |
|---|
| 1552 | + |
|---|
| 1553 | + for (i = 0; i < ofs->numfs; i++) { |
|---|
| 1554 | + /* |
|---|
| 1555 | + * We use uuid to associate an overlay lower file handle with a |
|---|
| 1556 | + * lower layer, so we can accept lower fs with null uuid as long |
|---|
| 1557 | + * as all lower layers with null uuid are on the same fs. |
|---|
| 1558 | + * if we detect multiple lower fs with the same uuid, we |
|---|
| 1559 | + * disable lower file handle decoding on all of them. |
|---|
| 1560 | + */ |
|---|
| 1561 | + if (ofs->fs[i].is_lower && |
|---|
| 1562 | + uuid_equal(&ofs->fs[i].sb->s_uuid, uuid)) { |
|---|
| 1563 | + ofs->fs[i].bad_uuid = true; |
|---|
| 1564 | + return false; |
|---|
| 1565 | + } |
|---|
| 1566 | + } |
|---|
| 1567 | + return true; |
|---|
| 1568 | +} |
|---|
| 1569 | + |
|---|
| 1570 | +/* Get a unique fsid for the layer */ |
|---|
| 1571 | +static int ovl_get_fsid(struct ovl_fs *ofs, const struct path *path) |
|---|
| 1572 | +{ |
|---|
| 1573 | + struct super_block *sb = path->mnt->mnt_sb; |
|---|
| 1307 | 1574 | unsigned int i; |
|---|
| 1308 | 1575 | dev_t dev; |
|---|
| 1309 | 1576 | int err; |
|---|
| 1577 | + bool bad_uuid = false; |
|---|
| 1310 | 1578 | |
|---|
| 1311 | | - /* fsid 0 is reserved for upper fs even with non upper overlay */ |
|---|
| 1312 | | - if (ofs->upper_mnt && ofs->upper_mnt->mnt_sb == sb) |
|---|
| 1313 | | - return 0; |
|---|
| 1579 | + for (i = 0; i < ofs->numfs; i++) { |
|---|
| 1580 | + if (ofs->fs[i].sb == sb) |
|---|
| 1581 | + return i; |
|---|
| 1582 | + } |
|---|
| 1314 | 1583 | |
|---|
| 1315 | | - for (i = 0; i < ofs->numlowerfs; i++) { |
|---|
| 1316 | | - if (ofs->lower_fs[i].sb == sb) |
|---|
| 1317 | | - return i + 1; |
|---|
| 1584 | + if (!ovl_lower_uuid_ok(ofs, &sb->s_uuid)) { |
|---|
| 1585 | + bad_uuid = true; |
|---|
| 1586 | + if (ofs->config.index || ofs->config.nfs_export) { |
|---|
| 1587 | + ofs->config.index = false; |
|---|
| 1588 | + ofs->config.nfs_export = false; |
|---|
| 1589 | + pr_warn("%s uuid detected in lower fs '%pd2', falling back to index=off,nfs_export=off.\n", |
|---|
| 1590 | + uuid_is_null(&sb->s_uuid) ? "null" : |
|---|
| 1591 | + "conflicting", |
|---|
| 1592 | + path->dentry); |
|---|
| 1593 | + } |
|---|
| 1318 | 1594 | } |
|---|
| 1319 | 1595 | |
|---|
| 1320 | 1596 | err = get_anon_bdev(&dev); |
|---|
| 1321 | 1597 | if (err) { |
|---|
| 1322 | | - pr_err("overlayfs: failed to get anonymous bdev for lowerpath\n"); |
|---|
| 1598 | + pr_err("failed to get anonymous bdev for lowerpath\n"); |
|---|
| 1323 | 1599 | return err; |
|---|
| 1324 | 1600 | } |
|---|
| 1325 | 1601 | |
|---|
| 1326 | | - ofs->lower_fs[ofs->numlowerfs].sb = sb; |
|---|
| 1327 | | - ofs->lower_fs[ofs->numlowerfs].pseudo_dev = dev; |
|---|
| 1328 | | - ofs->numlowerfs++; |
|---|
| 1602 | + ofs->fs[ofs->numfs].sb = sb; |
|---|
| 1603 | + ofs->fs[ofs->numfs].pseudo_dev = dev; |
|---|
| 1604 | + ofs->fs[ofs->numfs].bad_uuid = bad_uuid; |
|---|
| 1329 | 1605 | |
|---|
| 1330 | | - return ofs->numlowerfs; |
|---|
| 1606 | + return ofs->numfs++; |
|---|
| 1331 | 1607 | } |
|---|
| 1332 | 1608 | |
|---|
| 1333 | | -static int ovl_get_lower_layers(struct super_block *sb, struct ovl_fs *ofs, |
|---|
| 1334 | | - struct path *stack, unsigned int numlower) |
|---|
| 1609 | +static int ovl_get_layers(struct super_block *sb, struct ovl_fs *ofs, |
|---|
| 1610 | + struct path *stack, unsigned int numlower, |
|---|
| 1611 | + struct ovl_layer *layers) |
|---|
| 1335 | 1612 | { |
|---|
| 1336 | 1613 | int err; |
|---|
| 1337 | 1614 | unsigned int i; |
|---|
| 1338 | 1615 | |
|---|
| 1339 | 1616 | err = -ENOMEM; |
|---|
| 1340 | | - ofs->lower_layers = kcalloc(numlower, sizeof(struct ovl_layer), |
|---|
| 1341 | | - GFP_KERNEL); |
|---|
| 1342 | | - if (ofs->lower_layers == NULL) |
|---|
| 1617 | + ofs->fs = kcalloc(numlower + 1, sizeof(struct ovl_sb), GFP_KERNEL); |
|---|
| 1618 | + if (ofs->fs == NULL) |
|---|
| 1343 | 1619 | goto out; |
|---|
| 1344 | 1620 | |
|---|
| 1345 | | - ofs->lower_fs = kcalloc(numlower, sizeof(struct ovl_sb), |
|---|
| 1346 | | - GFP_KERNEL); |
|---|
| 1347 | | - if (ofs->lower_fs == NULL) |
|---|
| 1621 | + /* idx/fsid 0 are reserved for upper fs even with lower only overlay */ |
|---|
| 1622 | + ofs->numfs++; |
|---|
| 1623 | + |
|---|
| 1624 | + /* |
|---|
| 1625 | + * All lower layers that share the same fs as upper layer, use the same |
|---|
| 1626 | + * pseudo_dev as upper layer. Allocate fs[0].pseudo_dev even for lower |
|---|
| 1627 | + * only overlay to simplify ovl_fs_free(). |
|---|
| 1628 | + * is_lower will be set if upper fs is shared with a lower layer. |
|---|
| 1629 | + */ |
|---|
| 1630 | + err = get_anon_bdev(&ofs->fs[0].pseudo_dev); |
|---|
| 1631 | + if (err) { |
|---|
| 1632 | + pr_err("failed to get anonymous bdev for upper fs\n"); |
|---|
| 1348 | 1633 | goto out; |
|---|
| 1634 | + } |
|---|
| 1635 | + |
|---|
| 1636 | + if (ovl_upper_mnt(ofs)) { |
|---|
| 1637 | + ofs->fs[0].sb = ovl_upper_mnt(ofs)->mnt_sb; |
|---|
| 1638 | + ofs->fs[0].is_lower = false; |
|---|
| 1639 | + } |
|---|
| 1349 | 1640 | |
|---|
| 1350 | 1641 | for (i = 0; i < numlower; i++) { |
|---|
| 1351 | 1642 | struct vfsmount *mnt; |
|---|
| 1352 | 1643 | struct inode *trap; |
|---|
| 1353 | 1644 | int fsid; |
|---|
| 1354 | 1645 | |
|---|
| 1355 | | - err = fsid = ovl_get_fsid(ofs, stack[i].mnt->mnt_sb); |
|---|
| 1646 | + err = fsid = ovl_get_fsid(ofs, &stack[i]); |
|---|
| 1356 | 1647 | if (err < 0) |
|---|
| 1357 | 1648 | goto out; |
|---|
| 1358 | 1649 | |
|---|
| .. | .. |
|---|
| 1378 | 1669 | mnt = clone_private_mount(&stack[i]); |
|---|
| 1379 | 1670 | err = PTR_ERR(mnt); |
|---|
| 1380 | 1671 | if (IS_ERR(mnt)) { |
|---|
| 1381 | | - pr_err("overlayfs: failed to clone lowerpath\n"); |
|---|
| 1672 | + pr_err("failed to clone lowerpath\n"); |
|---|
| 1382 | 1673 | iput(trap); |
|---|
| 1383 | 1674 | goto out; |
|---|
| 1384 | 1675 | } |
|---|
| .. | .. |
|---|
| 1389 | 1680 | */ |
|---|
| 1390 | 1681 | mnt->mnt_flags |= MNT_READONLY | MNT_NOATIME; |
|---|
| 1391 | 1682 | |
|---|
| 1392 | | - ofs->lower_layers[ofs->numlower].trap = trap; |
|---|
| 1393 | | - ofs->lower_layers[ofs->numlower].mnt = mnt; |
|---|
| 1394 | | - ofs->lower_layers[ofs->numlower].idx = i + 1; |
|---|
| 1395 | | - ofs->lower_layers[ofs->numlower].fsid = fsid; |
|---|
| 1396 | | - if (fsid) { |
|---|
| 1397 | | - ofs->lower_layers[ofs->numlower].fs = |
|---|
| 1398 | | - &ofs->lower_fs[fsid - 1]; |
|---|
| 1399 | | - } |
|---|
| 1400 | | - ofs->numlower++; |
|---|
| 1683 | + layers[ofs->numlayer].trap = trap; |
|---|
| 1684 | + layers[ofs->numlayer].mnt = mnt; |
|---|
| 1685 | + layers[ofs->numlayer].idx = ofs->numlayer; |
|---|
| 1686 | + layers[ofs->numlayer].fsid = fsid; |
|---|
| 1687 | + layers[ofs->numlayer].fs = &ofs->fs[fsid]; |
|---|
| 1688 | + ofs->numlayer++; |
|---|
| 1689 | + ofs->fs[fsid].is_lower = true; |
|---|
| 1401 | 1690 | } |
|---|
| 1402 | 1691 | |
|---|
| 1403 | 1692 | /* |
|---|
| 1404 | 1693 | * When all layers on same fs, overlay can use real inode numbers. |
|---|
| 1405 | | - * With mount option "xino=on", mounter declares that there are enough |
|---|
| 1406 | | - * free high bits in underlying fs to hold the unique fsid. |
|---|
| 1694 | + * With mount option "xino=<on|auto>", mounter declares that there are |
|---|
| 1695 | + * enough free high bits in underlying fs to hold the unique fsid. |
|---|
| 1407 | 1696 | * If overlayfs does encounter underlying inodes using the high xino |
|---|
| 1408 | 1697 | * bits reserved for fsid, it emits a warning and uses the original |
|---|
| 1409 | | - * inode number. |
|---|
| 1698 | + * inode number or a non persistent inode number allocated from a |
|---|
| 1699 | + * dedicated range. |
|---|
| 1410 | 1700 | */ |
|---|
| 1411 | | - if (!ofs->numlowerfs || (ofs->numlowerfs == 1 && !ofs->upper_mnt)) { |
|---|
| 1412 | | - ofs->xino_bits = 0; |
|---|
| 1413 | | - ofs->config.xino = OVL_XINO_OFF; |
|---|
| 1414 | | - } else if (ofs->config.xino == OVL_XINO_ON && !ofs->xino_bits) { |
|---|
| 1701 | + if (ofs->numfs - !ovl_upper_mnt(ofs) == 1) { |
|---|
| 1702 | + if (ofs->config.xino == OVL_XINO_ON) |
|---|
| 1703 | + pr_info("\"xino=on\" is useless with all layers on same fs, ignore.\n"); |
|---|
| 1704 | + ofs->xino_mode = 0; |
|---|
| 1705 | + } else if (ofs->config.xino == OVL_XINO_OFF) { |
|---|
| 1706 | + ofs->xino_mode = -1; |
|---|
| 1707 | + } else if (ofs->xino_mode < 0) { |
|---|
| 1415 | 1708 | /* |
|---|
| 1416 | | - * This is a roundup of number of bits needed for numlowerfs+1 |
|---|
| 1417 | | - * (i.e. ilog2(numlowerfs+1 - 1) + 1). fsid 0 is reserved for |
|---|
| 1418 | | - * upper fs even with non upper overlay. |
|---|
| 1709 | + * This is a roundup of number of bits needed for encoding |
|---|
| 1710 | + * fsid, where fsid 0 is reserved for upper fs (even with |
|---|
| 1711 | + * lower only overlay) +1 extra bit is reserved for the non |
|---|
| 1712 | + * persistent inode number range that is used for resolving |
|---|
| 1713 | + * xino lower bits overflow. |
|---|
| 1419 | 1714 | */ |
|---|
| 1420 | | - BUILD_BUG_ON(ilog2(OVL_MAX_STACK) > 31); |
|---|
| 1421 | | - ofs->xino_bits = ilog2(ofs->numlowerfs) + 1; |
|---|
| 1715 | + BUILD_BUG_ON(ilog2(OVL_MAX_STACK) > 30); |
|---|
| 1716 | + ofs->xino_mode = ilog2(ofs->numfs - 1) + 2; |
|---|
| 1422 | 1717 | } |
|---|
| 1423 | 1718 | |
|---|
| 1424 | | - if (ofs->xino_bits) { |
|---|
| 1425 | | - pr_info("overlayfs: \"xino\" feature enabled using %d upper inode bits.\n", |
|---|
| 1426 | | - ofs->xino_bits); |
|---|
| 1719 | + if (ofs->xino_mode > 0) { |
|---|
| 1720 | + pr_info("\"xino\" feature enabled using %d upper inode bits.\n", |
|---|
| 1721 | + ofs->xino_mode); |
|---|
| 1427 | 1722 | } |
|---|
| 1428 | 1723 | |
|---|
| 1429 | 1724 | err = 0; |
|---|
| .. | .. |
|---|
| 1432 | 1727 | } |
|---|
| 1433 | 1728 | |
|---|
| 1434 | 1729 | static struct ovl_entry *ovl_get_lowerstack(struct super_block *sb, |
|---|
| 1435 | | - struct ovl_fs *ofs) |
|---|
| 1730 | + const char *lower, unsigned int numlower, |
|---|
| 1731 | + struct ovl_fs *ofs, struct ovl_layer *layers) |
|---|
| 1436 | 1732 | { |
|---|
| 1437 | 1733 | int err; |
|---|
| 1438 | | - char *lowertmp, *lower; |
|---|
| 1439 | 1734 | struct path *stack = NULL; |
|---|
| 1440 | | - unsigned int stacklen, numlower = 0, i; |
|---|
| 1441 | | - bool remote = false; |
|---|
| 1735 | + unsigned int i; |
|---|
| 1442 | 1736 | struct ovl_entry *oe; |
|---|
| 1443 | 1737 | |
|---|
| 1444 | | - err = -ENOMEM; |
|---|
| 1445 | | - lowertmp = kstrdup(ofs->config.lowerdir, GFP_KERNEL); |
|---|
| 1446 | | - if (!lowertmp) |
|---|
| 1447 | | - goto out_err; |
|---|
| 1448 | | - |
|---|
| 1449 | | - err = -EINVAL; |
|---|
| 1450 | | - stacklen = ovl_split_lowerdirs(lowertmp); |
|---|
| 1451 | | - if (stacklen > OVL_MAX_STACK) { |
|---|
| 1452 | | - pr_err("overlayfs: too many lower directories, limit is %d\n", |
|---|
| 1453 | | - OVL_MAX_STACK); |
|---|
| 1454 | | - goto out_err; |
|---|
| 1455 | | - } else if (!ofs->config.upperdir && stacklen == 1) { |
|---|
| 1456 | | - pr_err("overlayfs: at least 2 lowerdir are needed while upperdir nonexistent\n"); |
|---|
| 1457 | | - goto out_err; |
|---|
| 1458 | | - } else if (!ofs->config.upperdir && ofs->config.nfs_export && |
|---|
| 1459 | | - ofs->config.redirect_follow) { |
|---|
| 1460 | | - pr_warn("overlayfs: NFS export requires \"redirect_dir=nofollow\" on non-upper mount, falling back to nfs_export=off.\n"); |
|---|
| 1461 | | - ofs->config.nfs_export = false; |
|---|
| 1738 | + if (!ofs->config.upperdir && numlower == 1) { |
|---|
| 1739 | + pr_err("at least 2 lowerdir are needed while upperdir nonexistent\n"); |
|---|
| 1740 | + return ERR_PTR(-EINVAL); |
|---|
| 1462 | 1741 | } |
|---|
| 1463 | 1742 | |
|---|
| 1464 | | - err = -ENOMEM; |
|---|
| 1465 | | - stack = kcalloc(stacklen, sizeof(struct path), GFP_KERNEL); |
|---|
| 1743 | + stack = kcalloc(numlower, sizeof(struct path), GFP_KERNEL); |
|---|
| 1466 | 1744 | if (!stack) |
|---|
| 1467 | | - goto out_err; |
|---|
| 1745 | + return ERR_PTR(-ENOMEM); |
|---|
| 1468 | 1746 | |
|---|
| 1469 | 1747 | err = -EINVAL; |
|---|
| 1470 | | - lower = lowertmp; |
|---|
| 1471 | | - for (numlower = 0; numlower < stacklen; numlower++) { |
|---|
| 1472 | | - err = ovl_lower_dir(lower, &stack[numlower], ofs, |
|---|
| 1473 | | - &sb->s_stack_depth, &remote); |
|---|
| 1748 | + for (i = 0; i < numlower; i++) { |
|---|
| 1749 | + err = ovl_lower_dir(lower, &stack[i], ofs, &sb->s_stack_depth); |
|---|
| 1474 | 1750 | if (err) |
|---|
| 1475 | 1751 | goto out_err; |
|---|
| 1476 | 1752 | |
|---|
| .. | .. |
|---|
| 1480 | 1756 | err = -EINVAL; |
|---|
| 1481 | 1757 | sb->s_stack_depth++; |
|---|
| 1482 | 1758 | if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) { |
|---|
| 1483 | | - pr_err("overlayfs: maximum fs stacking depth exceeded\n"); |
|---|
| 1759 | + pr_err("maximum fs stacking depth exceeded\n"); |
|---|
| 1484 | 1760 | goto out_err; |
|---|
| 1485 | 1761 | } |
|---|
| 1486 | 1762 | |
|---|
| 1487 | | - err = ovl_get_lower_layers(sb, ofs, stack, numlower); |
|---|
| 1763 | + err = ovl_get_layers(sb, ofs, stack, numlower, layers); |
|---|
| 1488 | 1764 | if (err) |
|---|
| 1489 | 1765 | goto out_err; |
|---|
| 1490 | 1766 | |
|---|
| .. | .. |
|---|
| 1495 | 1771 | |
|---|
| 1496 | 1772 | for (i = 0; i < numlower; i++) { |
|---|
| 1497 | 1773 | oe->lowerstack[i].dentry = dget(stack[i].dentry); |
|---|
| 1498 | | - oe->lowerstack[i].layer = &ofs->lower_layers[i]; |
|---|
| 1774 | + oe->lowerstack[i].layer = &ofs->layers[i+1]; |
|---|
| 1499 | 1775 | } |
|---|
| 1500 | | - |
|---|
| 1501 | | - if (remote) |
|---|
| 1502 | | - sb->s_d_op = &ovl_reval_dentry_operations; |
|---|
| 1503 | | - else |
|---|
| 1504 | | - sb->s_d_op = &ovl_dentry_operations; |
|---|
| 1505 | 1776 | |
|---|
| 1506 | 1777 | out: |
|---|
| 1507 | 1778 | for (i = 0; i < numlower; i++) |
|---|
| 1508 | 1779 | path_put(&stack[i]); |
|---|
| 1509 | 1780 | kfree(stack); |
|---|
| 1510 | | - kfree(lowertmp); |
|---|
| 1511 | 1781 | |
|---|
| 1512 | 1782 | return oe; |
|---|
| 1513 | 1783 | |
|---|
| .. | .. |
|---|
| 1537 | 1807 | while (!err && parent != next) { |
|---|
| 1538 | 1808 | if (is_lower && ovl_lookup_trap_inode(sb, parent)) { |
|---|
| 1539 | 1809 | err = -ELOOP; |
|---|
| 1540 | | - pr_err("overlayfs: overlapping %s path\n", name); |
|---|
| 1810 | + pr_err("overlapping %s path\n", name); |
|---|
| 1541 | 1811 | } else if (ovl_is_inuse(parent)) { |
|---|
| 1542 | 1812 | err = ovl_report_in_use(ofs, name); |
|---|
| 1543 | 1813 | } |
|---|
| .. | .. |
|---|
| 1559 | 1829 | { |
|---|
| 1560 | 1830 | int i, err; |
|---|
| 1561 | 1831 | |
|---|
| 1562 | | - if (ofs->upper_mnt) { |
|---|
| 1563 | | - err = ovl_check_layer(sb, ofs, ofs->upper_mnt->mnt_root, |
|---|
| 1832 | + if (ovl_upper_mnt(ofs)) { |
|---|
| 1833 | + err = ovl_check_layer(sb, ofs, ovl_upper_mnt(ofs)->mnt_root, |
|---|
| 1564 | 1834 | "upperdir", false); |
|---|
| 1565 | 1835 | if (err) |
|---|
| 1566 | 1836 | return err; |
|---|
| .. | .. |
|---|
| 1578 | 1848 | return err; |
|---|
| 1579 | 1849 | } |
|---|
| 1580 | 1850 | |
|---|
| 1581 | | - for (i = 0; i < ofs->numlower; i++) { |
|---|
| 1851 | + for (i = 1; i < ofs->numlayer; i++) { |
|---|
| 1582 | 1852 | err = ovl_check_layer(sb, ofs, |
|---|
| 1583 | | - ofs->lower_layers[i].mnt->mnt_root, |
|---|
| 1853 | + ofs->layers[i].mnt->mnt_root, |
|---|
| 1584 | 1854 | "lowerdir", true); |
|---|
| 1585 | 1855 | if (err) |
|---|
| 1586 | 1856 | return err; |
|---|
| .. | .. |
|---|
| 1589 | 1859 | return 0; |
|---|
| 1590 | 1860 | } |
|---|
| 1591 | 1861 | |
|---|
| 1862 | +static struct dentry *ovl_get_root(struct super_block *sb, |
|---|
| 1863 | + struct dentry *upperdentry, |
|---|
| 1864 | + struct ovl_entry *oe) |
|---|
| 1865 | +{ |
|---|
| 1866 | + struct dentry *root; |
|---|
| 1867 | + struct ovl_path *lowerpath = &oe->lowerstack[0]; |
|---|
| 1868 | + unsigned long ino = d_inode(lowerpath->dentry)->i_ino; |
|---|
| 1869 | + int fsid = lowerpath->layer->fsid; |
|---|
| 1870 | + struct ovl_inode_params oip = { |
|---|
| 1871 | + .upperdentry = upperdentry, |
|---|
| 1872 | + .lowerpath = lowerpath, |
|---|
| 1873 | + }; |
|---|
| 1874 | + |
|---|
| 1875 | + root = d_make_root(ovl_new_inode(sb, S_IFDIR, 0)); |
|---|
| 1876 | + if (!root) |
|---|
| 1877 | + return NULL; |
|---|
| 1878 | + |
|---|
| 1879 | + root->d_fsdata = oe; |
|---|
| 1880 | + |
|---|
| 1881 | + if (upperdentry) { |
|---|
| 1882 | + /* Root inode uses upper st_ino/i_ino */ |
|---|
| 1883 | + ino = d_inode(upperdentry)->i_ino; |
|---|
| 1884 | + fsid = 0; |
|---|
| 1885 | + ovl_dentry_set_upper_alias(root); |
|---|
| 1886 | + if (ovl_is_impuredir(sb, upperdentry)) |
|---|
| 1887 | + ovl_set_flag(OVL_IMPURE, d_inode(root)); |
|---|
| 1888 | + } |
|---|
| 1889 | + |
|---|
| 1890 | + /* Root is always merge -> can have whiteouts */ |
|---|
| 1891 | + ovl_set_flag(OVL_WHITEOUTS, d_inode(root)); |
|---|
| 1892 | + ovl_dentry_set_flag(OVL_E_CONNECTED, root); |
|---|
| 1893 | + ovl_set_upperdata(d_inode(root)); |
|---|
| 1894 | + ovl_inode_init(d_inode(root), &oip, ino, fsid); |
|---|
| 1895 | + ovl_dentry_init_flags(root, upperdentry, DCACHE_OP_WEAK_REVALIDATE); |
|---|
| 1896 | + |
|---|
| 1897 | + return root; |
|---|
| 1898 | +} |
|---|
| 1899 | + |
|---|
| 1592 | 1900 | static int ovl_fill_super(struct super_block *sb, void *data, int silent) |
|---|
| 1593 | 1901 | { |
|---|
| 1594 | 1902 | struct path upperpath = { }; |
|---|
| 1595 | 1903 | struct dentry *root_dentry; |
|---|
| 1596 | 1904 | struct ovl_entry *oe; |
|---|
| 1597 | 1905 | struct ovl_fs *ofs; |
|---|
| 1906 | + struct ovl_layer *layers; |
|---|
| 1598 | 1907 | struct cred *cred; |
|---|
| 1908 | + char *splitlower = NULL; |
|---|
| 1909 | + unsigned int numlower; |
|---|
| 1599 | 1910 | int err; |
|---|
| 1911 | + |
|---|
| 1912 | + sb->s_d_op = &ovl_dentry_operations; |
|---|
| 1600 | 1913 | |
|---|
| 1601 | 1914 | err = -ENOMEM; |
|---|
| 1602 | 1915 | ofs = kzalloc(sizeof(struct ovl_fs), GFP_KERNEL); |
|---|
| .. | .. |
|---|
| 1606 | 1919 | ofs->creator_cred = cred = prepare_creds(); |
|---|
| 1607 | 1920 | if (!cred) |
|---|
| 1608 | 1921 | goto out_err; |
|---|
| 1922 | + |
|---|
| 1923 | + /* Is there a reason anyone would want not to share whiteouts? */ |
|---|
| 1924 | + ofs->share_whiteout = true; |
|---|
| 1609 | 1925 | |
|---|
| 1610 | 1926 | ofs->config.index = ovl_index_def; |
|---|
| 1611 | 1927 | ofs->config.nfs_export = ovl_nfs_export_def; |
|---|
| .. | .. |
|---|
| 1618 | 1934 | err = -EINVAL; |
|---|
| 1619 | 1935 | if (!ofs->config.lowerdir) { |
|---|
| 1620 | 1936 | if (!silent) |
|---|
| 1621 | | - pr_err("overlayfs: missing 'lowerdir'\n"); |
|---|
| 1937 | + pr_err("missing 'lowerdir'\n"); |
|---|
| 1622 | 1938 | goto out_err; |
|---|
| 1623 | 1939 | } |
|---|
| 1624 | 1940 | |
|---|
| 1941 | + err = -ENOMEM; |
|---|
| 1942 | + splitlower = kstrdup(ofs->config.lowerdir, GFP_KERNEL); |
|---|
| 1943 | + if (!splitlower) |
|---|
| 1944 | + goto out_err; |
|---|
| 1945 | + |
|---|
| 1946 | + numlower = ovl_split_lowerdirs(splitlower); |
|---|
| 1947 | + if (numlower > OVL_MAX_STACK) { |
|---|
| 1948 | + pr_err("too many lower directories, limit is %d\n", |
|---|
| 1949 | + OVL_MAX_STACK); |
|---|
| 1950 | + goto out_err; |
|---|
| 1951 | + } |
|---|
| 1952 | + |
|---|
| 1953 | + layers = kcalloc(numlower + 1, sizeof(struct ovl_layer), GFP_KERNEL); |
|---|
| 1954 | + if (!layers) |
|---|
| 1955 | + goto out_err; |
|---|
| 1956 | + |
|---|
| 1957 | + ofs->layers = layers; |
|---|
| 1958 | + /* Layer 0 is reserved for upper even if there's no upper */ |
|---|
| 1959 | + ofs->numlayer = 1; |
|---|
| 1960 | + |
|---|
| 1625 | 1961 | sb->s_stack_depth = 0; |
|---|
| 1626 | 1962 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
|---|
| 1963 | + atomic_long_set(&ofs->last_ino, 1); |
|---|
| 1627 | 1964 | /* Assume underlaying fs uses 32bit inodes unless proven otherwise */ |
|---|
| 1628 | | - if (ofs->config.xino != OVL_XINO_OFF) |
|---|
| 1629 | | - ofs->xino_bits = BITS_PER_LONG - 32; |
|---|
| 1965 | + if (ofs->config.xino != OVL_XINO_OFF) { |
|---|
| 1966 | + ofs->xino_mode = BITS_PER_LONG - 32; |
|---|
| 1967 | + if (!ofs->xino_mode) { |
|---|
| 1968 | + pr_warn("xino not supported on 32bit kernel, falling back to xino=off.\n"); |
|---|
| 1969 | + ofs->config.xino = OVL_XINO_OFF; |
|---|
| 1970 | + } |
|---|
| 1971 | + } |
|---|
| 1630 | 1972 | |
|---|
| 1631 | 1973 | /* alloc/destroy_inode needed for setting up traps in inode cache */ |
|---|
| 1632 | 1974 | sb->s_op = &ovl_super_operations; |
|---|
| 1633 | 1975 | |
|---|
| 1634 | 1976 | if (ofs->config.upperdir) { |
|---|
| 1977 | + struct super_block *upper_sb; |
|---|
| 1978 | + |
|---|
| 1635 | 1979 | if (!ofs->config.workdir) { |
|---|
| 1636 | | - pr_err("overlayfs: missing 'workdir'\n"); |
|---|
| 1980 | + pr_err("missing 'workdir'\n"); |
|---|
| 1637 | 1981 | goto out_err; |
|---|
| 1638 | 1982 | } |
|---|
| 1639 | 1983 | |
|---|
| 1640 | | - err = ovl_get_upper(sb, ofs, &upperpath); |
|---|
| 1984 | + err = ovl_get_upper(sb, ofs, &layers[0], &upperpath); |
|---|
| 1641 | 1985 | if (err) |
|---|
| 1642 | 1986 | goto out_err; |
|---|
| 1987 | + |
|---|
| 1988 | + upper_sb = ovl_upper_mnt(ofs)->mnt_sb; |
|---|
| 1989 | + if (!ovl_should_sync(ofs)) { |
|---|
| 1990 | + ofs->errseq = errseq_sample(&upper_sb->s_wb_err); |
|---|
| 1991 | + if (errseq_check(&upper_sb->s_wb_err, ofs->errseq)) { |
|---|
| 1992 | + err = -EIO; |
|---|
| 1993 | + pr_err("Cannot mount volatile when upperdir has an unseen error. Sync upperdir fs to clear state.\n"); |
|---|
| 1994 | + goto out_err; |
|---|
| 1995 | + } |
|---|
| 1996 | + } |
|---|
| 1643 | 1997 | |
|---|
| 1644 | 1998 | err = ovl_get_workdir(sb, ofs, &upperpath); |
|---|
| 1645 | 1999 | if (err) |
|---|
| .. | .. |
|---|
| 1648 | 2002 | if (!ofs->workdir) |
|---|
| 1649 | 2003 | sb->s_flags |= SB_RDONLY; |
|---|
| 1650 | 2004 | |
|---|
| 1651 | | - sb->s_stack_depth = ofs->upper_mnt->mnt_sb->s_stack_depth; |
|---|
| 1652 | | - sb->s_time_gran = ofs->upper_mnt->mnt_sb->s_time_gran; |
|---|
| 1653 | | - |
|---|
| 2005 | + sb->s_stack_depth = upper_sb->s_stack_depth; |
|---|
| 2006 | + sb->s_time_gran = upper_sb->s_time_gran; |
|---|
| 1654 | 2007 | } |
|---|
| 1655 | | - oe = ovl_get_lowerstack(sb, ofs); |
|---|
| 2008 | + oe = ovl_get_lowerstack(sb, splitlower, numlower, ofs, layers); |
|---|
| 1656 | 2009 | err = PTR_ERR(oe); |
|---|
| 1657 | 2010 | if (IS_ERR(oe)) |
|---|
| 1658 | 2011 | goto out_err; |
|---|
| 1659 | 2012 | |
|---|
| 1660 | 2013 | /* If the upper fs is nonexistent, we mark overlayfs r/o too */ |
|---|
| 1661 | | - if (!ofs->upper_mnt) |
|---|
| 2014 | + if (!ovl_upper_mnt(ofs)) |
|---|
| 1662 | 2015 | sb->s_flags |= SB_RDONLY; |
|---|
| 1663 | 2016 | |
|---|
| 1664 | | - if (!(ovl_force_readonly(ofs)) && ofs->config.index) { |
|---|
| 2017 | + if (!ovl_force_readonly(ofs) && ofs->config.index) { |
|---|
| 1665 | 2018 | err = ovl_get_indexdir(sb, ofs, oe, &upperpath); |
|---|
| 1666 | 2019 | if (err) |
|---|
| 1667 | 2020 | goto out_free_oe; |
|---|
| 1668 | 2021 | |
|---|
| 1669 | 2022 | /* Force r/o mount with no index dir */ |
|---|
| 1670 | | - if (!ofs->indexdir) { |
|---|
| 1671 | | - dput(ofs->workdir); |
|---|
| 1672 | | - ofs->workdir = NULL; |
|---|
| 2023 | + if (!ofs->indexdir) |
|---|
| 1673 | 2024 | sb->s_flags |= SB_RDONLY; |
|---|
| 1674 | | - } |
|---|
| 1675 | | - |
|---|
| 1676 | 2025 | } |
|---|
| 1677 | 2026 | |
|---|
| 1678 | 2027 | err = ovl_check_overlapping_layers(sb, ofs); |
|---|
| .. | .. |
|---|
| 1682 | 2031 | /* Show index=off in /proc/mounts for forced r/o mount */ |
|---|
| 1683 | 2032 | if (!ofs->indexdir) { |
|---|
| 1684 | 2033 | ofs->config.index = false; |
|---|
| 1685 | | - if (ofs->upper_mnt && ofs->config.nfs_export) { |
|---|
| 1686 | | - pr_warn("overlayfs: NFS export requires an index dir, falling back to nfs_export=off.\n"); |
|---|
| 2034 | + if (ovl_upper_mnt(ofs) && ofs->config.nfs_export) { |
|---|
| 2035 | + pr_warn("NFS export requires an index dir, falling back to nfs_export=off.\n"); |
|---|
| 1687 | 2036 | ofs->config.nfs_export = false; |
|---|
| 1688 | 2037 | } |
|---|
| 1689 | 2038 | } |
|---|
| 1690 | 2039 | |
|---|
| 1691 | 2040 | if (ofs->config.metacopy && ofs->config.nfs_export) { |
|---|
| 1692 | | - pr_warn("overlayfs: NFS export is not supported with metadata only copy up, falling back to nfs_export=off.\n"); |
|---|
| 2041 | + pr_warn("NFS export is not supported with metadata only copy up, falling back to nfs_export=off.\n"); |
|---|
| 1693 | 2042 | ofs->config.nfs_export = false; |
|---|
| 1694 | 2043 | } |
|---|
| 1695 | 2044 | |
|---|
| .. | .. |
|---|
| 1703 | 2052 | sb->s_xattr = ovl_xattr_handlers; |
|---|
| 1704 | 2053 | sb->s_fs_info = ofs; |
|---|
| 1705 | 2054 | sb->s_flags |= SB_POSIXACL; |
|---|
| 2055 | + sb->s_iflags |= SB_I_SKIP_SYNC | SB_I_IMA_UNVERIFIABLE_SIGNATURE; |
|---|
| 1706 | 2056 | |
|---|
| 1707 | 2057 | err = -ENOMEM; |
|---|
| 1708 | | - root_dentry = d_make_root(ovl_new_inode(sb, S_IFDIR, 0)); |
|---|
| 2058 | + root_dentry = ovl_get_root(sb, upperpath.dentry, oe); |
|---|
| 1709 | 2059 | if (!root_dentry) |
|---|
| 1710 | 2060 | goto out_free_oe; |
|---|
| 1711 | 2061 | |
|---|
| 1712 | | - root_dentry->d_fsdata = oe; |
|---|
| 1713 | | - |
|---|
| 1714 | 2062 | mntput(upperpath.mnt); |
|---|
| 1715 | | - if (upperpath.dentry) { |
|---|
| 1716 | | - ovl_dentry_set_upper_alias(root_dentry); |
|---|
| 1717 | | - if (ovl_is_impuredir(upperpath.dentry)) |
|---|
| 1718 | | - ovl_set_flag(OVL_IMPURE, d_inode(root_dentry)); |
|---|
| 1719 | | - } |
|---|
| 1720 | | - |
|---|
| 1721 | | - /* Root is always merge -> can have whiteouts */ |
|---|
| 1722 | | - ovl_set_flag(OVL_WHITEOUTS, d_inode(root_dentry)); |
|---|
| 1723 | | - ovl_dentry_set_flag(OVL_E_CONNECTED, root_dentry); |
|---|
| 1724 | | - ovl_set_upperdata(d_inode(root_dentry)); |
|---|
| 1725 | | - ovl_inode_init(d_inode(root_dentry), upperpath.dentry, |
|---|
| 1726 | | - ovl_dentry_lower(root_dentry), NULL); |
|---|
| 2063 | + kfree(splitlower); |
|---|
| 1727 | 2064 | |
|---|
| 1728 | 2065 | sb->s_root = root_dentry; |
|---|
| 1729 | 2066 | return 0; |
|---|
| .. | .. |
|---|
| 1732 | 2069 | ovl_entry_stack_free(oe); |
|---|
| 1733 | 2070 | kfree(oe); |
|---|
| 1734 | 2071 | out_err: |
|---|
| 2072 | + kfree(splitlower); |
|---|
| 1735 | 2073 | path_put(&upperpath); |
|---|
| 1736 | 2074 | ovl_free_fs(ofs); |
|---|
| 1737 | 2075 | out: |
|---|
| .. | .. |
|---|
| 1771 | 2109 | if (ovl_inode_cachep == NULL) |
|---|
| 1772 | 2110 | return -ENOMEM; |
|---|
| 1773 | 2111 | |
|---|
| 1774 | | - err = register_filesystem(&ovl_fs_type); |
|---|
| 1775 | | - if (err) |
|---|
| 1776 | | - kmem_cache_destroy(ovl_inode_cachep); |
|---|
| 2112 | + err = ovl_aio_request_cache_init(); |
|---|
| 2113 | + if (!err) { |
|---|
| 2114 | + err = register_filesystem(&ovl_fs_type); |
|---|
| 2115 | + if (!err) |
|---|
| 2116 | + return 0; |
|---|
| 2117 | + |
|---|
| 2118 | + ovl_aio_request_cache_destroy(); |
|---|
| 2119 | + } |
|---|
| 2120 | + kmem_cache_destroy(ovl_inode_cachep); |
|---|
| 1777 | 2121 | |
|---|
| 1778 | 2122 | return err; |
|---|
| 1779 | 2123 | } |
|---|
| .. | .. |
|---|
| 1788 | 2132 | */ |
|---|
| 1789 | 2133 | rcu_barrier(); |
|---|
| 1790 | 2134 | kmem_cache_destroy(ovl_inode_cachep); |
|---|
| 1791 | | - |
|---|
| 2135 | + ovl_aio_request_cache_destroy(); |
|---|
| 1792 | 2136 | } |
|---|
| 1793 | 2137 | |
|---|
| 1794 | 2138 | module_init(ovl_init); |
|---|