Hello, this patch recodes ovl_copy_up and ovl_copy_up_truncate as a recursive routine, there is less code and less number of instructions to execute, therefore maybe faster and easy to mantain, I have tested it, that works, Thanks, Jordi Pujol Live never ending Tale GNU/Linux Live forever! http://livenet.selfip.com
--- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -315,69 +315,46 @@ out_free_link: return err; } -int ovl_copy_up(struct dentry *dentry) +/* Optimize by not copying up the file first and truncating later */ +int ovl_copy_up_truncate(struct dentry *dentry, loff_t size) { int err; + struct dentry *actual; + struct dentry *parent; + struct path lowerpath; + struct kstat stat; + enum ovl_path_type type; err = 0; - while (!err) { - struct dentry *next; - struct dentry *parent; - struct path lowerpath; - struct kstat stat; - enum ovl_path_type type = ovl_path_type(dentry); - - if (type != OVL_PATH_LOWER) - break; - - next = dget(dentry); - /* find the topmost dentry not yet copied up */ - for (;;) { - parent = dget_parent(next); - - type = ovl_path_type(parent); - if (type != OVL_PATH_LOWER) - break; - dput(next); - next = parent; - } + actual = dget(dentry); + type = ovl_path_type(actual); + if (type != OVL_PATH_LOWER) + goto out; + + /* if the parent is not yet copied up, copy it now recursively */ + err = ovl_copy_up_truncate(actual->d_parent, -1LL); + if (!err) { + parent = dget_parent(actual); - ovl_path_lower(next, &lowerpath); + ovl_path_lower(actual, &lowerpath); err = vfs_getattr(lowerpath.mnt, lowerpath.dentry, &stat); - if (!err) - err = ovl_copy_up_one(parent, next, &lowerpath, &stat); + if (!err) { + if (size >= 0 && size < stat.size) + stat.size = size; + err = ovl_copy_up_one(parent, actual, &lowerpath, &stat); + } dput(parent); - dput(next); } +out: + dput(actual); + return err; } -/* Optimize by not copying up the file first and truncating later */ -int ovl_copy_up_truncate(struct dentry *dentry, loff_t size) +int ovl_copy_up(struct dentry *dentry) { - int err; - struct kstat stat; - struct path lowerpath; - struct dentry *parent = dget_parent(dentry); - - err = ovl_copy_up(parent); - if (err) - goto out_dput_parent; - - ovl_path_lower(dentry, &lowerpath); - err = vfs_getattr(lowerpath.mnt, lowerpath.dentry, &stat); - if (err) - goto out_dput_parent; - - if (size < stat.size) - stat.size = size; - - err = ovl_copy_up_one(parent, dentry, &lowerpath, &stat); - -out_dput_parent: - dput(parent); - return err; + return ovl_copy_up_truncate(dentry, -1LL); }