1e9be9d5eSMiklos Szeredi /* 2e9be9d5eSMiklos Szeredi * 3e9be9d5eSMiklos Szeredi * Copyright (C) 2011 Novell Inc. 4e9be9d5eSMiklos Szeredi * 5e9be9d5eSMiklos Szeredi * This program is free software; you can redistribute it and/or modify it 6e9be9d5eSMiklos Szeredi * under the terms of the GNU General Public License version 2 as published by 7e9be9d5eSMiklos Szeredi * the Free Software Foundation. 8e9be9d5eSMiklos Szeredi */ 9e9be9d5eSMiklos Szeredi 10e9be9d5eSMiklos Szeredi #include <linux/fs.h> 11e9be9d5eSMiklos Szeredi #include <linux/slab.h> 12e9be9d5eSMiklos Szeredi #include <linux/file.h> 13e9be9d5eSMiklos Szeredi #include <linux/splice.h> 14e9be9d5eSMiklos Szeredi #include <linux/xattr.h> 15e9be9d5eSMiklos Szeredi #include <linux/security.h> 16e9be9d5eSMiklos Szeredi #include <linux/uaccess.h> 17e9be9d5eSMiklos Szeredi #include <linux/sched.h> 18e9be9d5eSMiklos Szeredi #include <linux/namei.h> 19e9be9d5eSMiklos Szeredi #include "overlayfs.h" 20e9be9d5eSMiklos Szeredi 21e9be9d5eSMiklos Szeredi #define OVL_COPY_UP_CHUNK_SIZE (1 << 20) 22e9be9d5eSMiklos Szeredi 23e9be9d5eSMiklos Szeredi int ovl_copy_xattr(struct dentry *old, struct dentry *new) 24e9be9d5eSMiklos Szeredi { 25e9be9d5eSMiklos Szeredi ssize_t list_size, size; 26e9be9d5eSMiklos Szeredi char *buf, *name, *value; 27e9be9d5eSMiklos Szeredi int error; 28e9be9d5eSMiklos Szeredi 29e9be9d5eSMiklos Szeredi if (!old->d_inode->i_op->getxattr || 30e9be9d5eSMiklos Szeredi !new->d_inode->i_op->getxattr) 31e9be9d5eSMiklos Szeredi return 0; 32e9be9d5eSMiklos Szeredi 33e9be9d5eSMiklos Szeredi list_size = vfs_listxattr(old, NULL, 0); 34e9be9d5eSMiklos Szeredi if (list_size <= 0) { 35e9be9d5eSMiklos Szeredi if (list_size == -EOPNOTSUPP) 36e9be9d5eSMiklos Szeredi return 0; 37e9be9d5eSMiklos Szeredi return list_size; 38e9be9d5eSMiklos Szeredi } 39e9be9d5eSMiklos Szeredi 40e9be9d5eSMiklos Szeredi buf = kzalloc(list_size, GFP_KERNEL); 41e9be9d5eSMiklos Szeredi if (!buf) 42e9be9d5eSMiklos Szeredi return -ENOMEM; 43e9be9d5eSMiklos Szeredi 44e9be9d5eSMiklos Szeredi error = -ENOMEM; 45e9be9d5eSMiklos Szeredi value = kmalloc(XATTR_SIZE_MAX, GFP_KERNEL); 46e9be9d5eSMiklos Szeredi if (!value) 47e9be9d5eSMiklos Szeredi goto out; 48e9be9d5eSMiklos Szeredi 49e9be9d5eSMiklos Szeredi list_size = vfs_listxattr(old, buf, list_size); 50e9be9d5eSMiklos Szeredi if (list_size <= 0) { 51e9be9d5eSMiklos Szeredi error = list_size; 52e9be9d5eSMiklos Szeredi goto out_free_value; 53e9be9d5eSMiklos Szeredi } 54e9be9d5eSMiklos Szeredi 55e9be9d5eSMiklos Szeredi for (name = buf; name < (buf + list_size); name += strlen(name) + 1) { 56e9be9d5eSMiklos Szeredi size = vfs_getxattr(old, name, value, XATTR_SIZE_MAX); 57e9be9d5eSMiklos Szeredi if (size <= 0) { 58e9be9d5eSMiklos Szeredi error = size; 59e9be9d5eSMiklos Szeredi goto out_free_value; 60e9be9d5eSMiklos Szeredi } 61e9be9d5eSMiklos Szeredi error = vfs_setxattr(new, name, value, size, 0); 62e9be9d5eSMiklos Szeredi if (error) 63e9be9d5eSMiklos Szeredi goto out_free_value; 64e9be9d5eSMiklos Szeredi } 65e9be9d5eSMiklos Szeredi 66e9be9d5eSMiklos Szeredi out_free_value: 67e9be9d5eSMiklos Szeredi kfree(value); 68e9be9d5eSMiklos Szeredi out: 69e9be9d5eSMiklos Szeredi kfree(buf); 70e9be9d5eSMiklos Szeredi return error; 71e9be9d5eSMiklos Szeredi } 72e9be9d5eSMiklos Szeredi 73e9be9d5eSMiklos Szeredi static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len) 74e9be9d5eSMiklos Szeredi { 75e9be9d5eSMiklos Szeredi struct file *old_file; 76e9be9d5eSMiklos Szeredi struct file *new_file; 77e9be9d5eSMiklos Szeredi loff_t old_pos = 0; 78e9be9d5eSMiklos Szeredi loff_t new_pos = 0; 79e9be9d5eSMiklos Szeredi int error = 0; 80e9be9d5eSMiklos Szeredi 81e9be9d5eSMiklos Szeredi if (len == 0) 82e9be9d5eSMiklos Szeredi return 0; 83e9be9d5eSMiklos Szeredi 84e9be9d5eSMiklos Szeredi old_file = ovl_path_open(old, O_RDONLY); 85e9be9d5eSMiklos Szeredi if (IS_ERR(old_file)) 86e9be9d5eSMiklos Szeredi return PTR_ERR(old_file); 87e9be9d5eSMiklos Szeredi 88e9be9d5eSMiklos Szeredi new_file = ovl_path_open(new, O_WRONLY); 89e9be9d5eSMiklos Szeredi if (IS_ERR(new_file)) { 90e9be9d5eSMiklos Szeredi error = PTR_ERR(new_file); 91e9be9d5eSMiklos Szeredi goto out_fput; 92e9be9d5eSMiklos Szeredi } 93e9be9d5eSMiklos Szeredi 94e9be9d5eSMiklos Szeredi /* FIXME: copy up sparse files efficiently */ 95e9be9d5eSMiklos Szeredi while (len) { 96e9be9d5eSMiklos Szeredi size_t this_len = OVL_COPY_UP_CHUNK_SIZE; 97e9be9d5eSMiklos Szeredi long bytes; 98e9be9d5eSMiklos Szeredi 99e9be9d5eSMiklos Szeredi if (len < this_len) 100e9be9d5eSMiklos Szeredi this_len = len; 101e9be9d5eSMiklos Szeredi 102e9be9d5eSMiklos Szeredi if (signal_pending_state(TASK_KILLABLE, current)) { 103e9be9d5eSMiklos Szeredi error = -EINTR; 104e9be9d5eSMiklos Szeredi break; 105e9be9d5eSMiklos Szeredi } 106e9be9d5eSMiklos Szeredi 107e9be9d5eSMiklos Szeredi bytes = do_splice_direct(old_file, &old_pos, 108e9be9d5eSMiklos Szeredi new_file, &new_pos, 109e9be9d5eSMiklos Szeredi this_len, SPLICE_F_MOVE); 110e9be9d5eSMiklos Szeredi if (bytes <= 0) { 111e9be9d5eSMiklos Szeredi error = bytes; 112e9be9d5eSMiklos Szeredi break; 113e9be9d5eSMiklos Szeredi } 114e9be9d5eSMiklos Szeredi WARN_ON(old_pos != new_pos); 115e9be9d5eSMiklos Szeredi 116e9be9d5eSMiklos Szeredi len -= bytes; 117e9be9d5eSMiklos Szeredi } 118e9be9d5eSMiklos Szeredi 119e9be9d5eSMiklos Szeredi fput(new_file); 120e9be9d5eSMiklos Szeredi out_fput: 121e9be9d5eSMiklos Szeredi fput(old_file); 122e9be9d5eSMiklos Szeredi return error; 123e9be9d5eSMiklos Szeredi } 124e9be9d5eSMiklos Szeredi 125e9be9d5eSMiklos Szeredi static char *ovl_read_symlink(struct dentry *realdentry) 126e9be9d5eSMiklos Szeredi { 127e9be9d5eSMiklos Szeredi int res; 128e9be9d5eSMiklos Szeredi char *buf; 129e9be9d5eSMiklos Szeredi struct inode *inode = realdentry->d_inode; 130e9be9d5eSMiklos Szeredi mm_segment_t old_fs; 131e9be9d5eSMiklos Szeredi 132e9be9d5eSMiklos Szeredi res = -EINVAL; 133e9be9d5eSMiklos Szeredi if (!inode->i_op->readlink) 134e9be9d5eSMiklos Szeredi goto err; 135e9be9d5eSMiklos Szeredi 136e9be9d5eSMiklos Szeredi res = -ENOMEM; 137e9be9d5eSMiklos Szeredi buf = (char *) __get_free_page(GFP_KERNEL); 138e9be9d5eSMiklos Szeredi if (!buf) 139e9be9d5eSMiklos Szeredi goto err; 140e9be9d5eSMiklos Szeredi 141e9be9d5eSMiklos Szeredi old_fs = get_fs(); 142e9be9d5eSMiklos Szeredi set_fs(get_ds()); 143e9be9d5eSMiklos Szeredi /* The cast to a user pointer is valid due to the set_fs() */ 144e9be9d5eSMiklos Szeredi res = inode->i_op->readlink(realdentry, 145e9be9d5eSMiklos Szeredi (char __user *)buf, PAGE_SIZE - 1); 146e9be9d5eSMiklos Szeredi set_fs(old_fs); 147e9be9d5eSMiklos Szeredi if (res < 0) { 148e9be9d5eSMiklos Szeredi free_page((unsigned long) buf); 149e9be9d5eSMiklos Szeredi goto err; 150e9be9d5eSMiklos Szeredi } 151e9be9d5eSMiklos Szeredi buf[res] = '\0'; 152e9be9d5eSMiklos Szeredi 153e9be9d5eSMiklos Szeredi return buf; 154e9be9d5eSMiklos Szeredi 155e9be9d5eSMiklos Szeredi err: 156e9be9d5eSMiklos Szeredi return ERR_PTR(res); 157e9be9d5eSMiklos Szeredi } 158e9be9d5eSMiklos Szeredi 159e9be9d5eSMiklos Szeredi static int ovl_set_timestamps(struct dentry *upperdentry, struct kstat *stat) 160e9be9d5eSMiklos Szeredi { 161e9be9d5eSMiklos Szeredi struct iattr attr = { 162e9be9d5eSMiklos Szeredi .ia_valid = 163e9be9d5eSMiklos Szeredi ATTR_ATIME | ATTR_MTIME | ATTR_ATIME_SET | ATTR_MTIME_SET, 164e9be9d5eSMiklos Szeredi .ia_atime = stat->atime, 165e9be9d5eSMiklos Szeredi .ia_mtime = stat->mtime, 166e9be9d5eSMiklos Szeredi }; 167e9be9d5eSMiklos Szeredi 168e9be9d5eSMiklos Szeredi return notify_change(upperdentry, &attr, NULL); 169e9be9d5eSMiklos Szeredi } 170e9be9d5eSMiklos Szeredi 171e9be9d5eSMiklos Szeredi int ovl_set_attr(struct dentry *upperdentry, struct kstat *stat) 172e9be9d5eSMiklos Szeredi { 173e9be9d5eSMiklos Szeredi int err = 0; 174e9be9d5eSMiklos Szeredi 175e9be9d5eSMiklos Szeredi if (!S_ISLNK(stat->mode)) { 176e9be9d5eSMiklos Szeredi struct iattr attr = { 177e9be9d5eSMiklos Szeredi .ia_valid = ATTR_MODE, 178e9be9d5eSMiklos Szeredi .ia_mode = stat->mode, 179e9be9d5eSMiklos Szeredi }; 180e9be9d5eSMiklos Szeredi err = notify_change(upperdentry, &attr, NULL); 181e9be9d5eSMiklos Szeredi } 182e9be9d5eSMiklos Szeredi if (!err) { 183e9be9d5eSMiklos Szeredi struct iattr attr = { 184e9be9d5eSMiklos Szeredi .ia_valid = ATTR_UID | ATTR_GID, 185e9be9d5eSMiklos Szeredi .ia_uid = stat->uid, 186e9be9d5eSMiklos Szeredi .ia_gid = stat->gid, 187e9be9d5eSMiklos Szeredi }; 188e9be9d5eSMiklos Szeredi err = notify_change(upperdentry, &attr, NULL); 189e9be9d5eSMiklos Szeredi } 190e9be9d5eSMiklos Szeredi if (!err) 191e9be9d5eSMiklos Szeredi ovl_set_timestamps(upperdentry, stat); 192e9be9d5eSMiklos Szeredi 193e9be9d5eSMiklos Szeredi return err; 194e9be9d5eSMiklos Szeredi 195e9be9d5eSMiklos Szeredi } 196e9be9d5eSMiklos Szeredi 197e9be9d5eSMiklos Szeredi static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, 198e9be9d5eSMiklos Szeredi struct dentry *dentry, struct path *lowerpath, 199e9be9d5eSMiklos Szeredi struct kstat *stat, struct iattr *attr, 200e9be9d5eSMiklos Szeredi const char *link) 201e9be9d5eSMiklos Szeredi { 202e9be9d5eSMiklos Szeredi struct inode *wdir = workdir->d_inode; 203e9be9d5eSMiklos Szeredi struct inode *udir = upperdir->d_inode; 204e9be9d5eSMiklos Szeredi struct dentry *newdentry = NULL; 205e9be9d5eSMiklos Szeredi struct dentry *upper = NULL; 206e9be9d5eSMiklos Szeredi umode_t mode = stat->mode; 207e9be9d5eSMiklos Szeredi int err; 208e9be9d5eSMiklos Szeredi 209e9be9d5eSMiklos Szeredi newdentry = ovl_lookup_temp(workdir, dentry); 210e9be9d5eSMiklos Szeredi err = PTR_ERR(newdentry); 211e9be9d5eSMiklos Szeredi if (IS_ERR(newdentry)) 212e9be9d5eSMiklos Szeredi goto out; 213e9be9d5eSMiklos Szeredi 214e9be9d5eSMiklos Szeredi upper = lookup_one_len(dentry->d_name.name, upperdir, 215e9be9d5eSMiklos Szeredi dentry->d_name.len); 216e9be9d5eSMiklos Szeredi err = PTR_ERR(upper); 217e9be9d5eSMiklos Szeredi if (IS_ERR(upper)) 218e9be9d5eSMiklos Szeredi goto out1; 219e9be9d5eSMiklos Szeredi 220e9be9d5eSMiklos Szeredi /* Can't properly set mode on creation because of the umask */ 221e9be9d5eSMiklos Szeredi stat->mode &= S_IFMT; 222e9be9d5eSMiklos Szeredi err = ovl_create_real(wdir, newdentry, stat, link, NULL, true); 223e9be9d5eSMiklos Szeredi stat->mode = mode; 224e9be9d5eSMiklos Szeredi if (err) 225e9be9d5eSMiklos Szeredi goto out2; 226e9be9d5eSMiklos Szeredi 227e9be9d5eSMiklos Szeredi if (S_ISREG(stat->mode)) { 228e9be9d5eSMiklos Szeredi struct path upperpath; 229e9be9d5eSMiklos Szeredi ovl_path_upper(dentry, &upperpath); 230e9be9d5eSMiklos Szeredi BUG_ON(upperpath.dentry != NULL); 231e9be9d5eSMiklos Szeredi upperpath.dentry = newdentry; 232e9be9d5eSMiklos Szeredi 233e9be9d5eSMiklos Szeredi err = ovl_copy_up_data(lowerpath, &upperpath, stat->size); 234e9be9d5eSMiklos Szeredi if (err) 235e9be9d5eSMiklos Szeredi goto out_cleanup; 236e9be9d5eSMiklos Szeredi } 237e9be9d5eSMiklos Szeredi 238e9be9d5eSMiklos Szeredi err = ovl_copy_xattr(lowerpath->dentry, newdentry); 239e9be9d5eSMiklos Szeredi if (err) 240e9be9d5eSMiklos Szeredi goto out_cleanup; 241e9be9d5eSMiklos Szeredi 242e9be9d5eSMiklos Szeredi mutex_lock(&newdentry->d_inode->i_mutex); 243e9be9d5eSMiklos Szeredi err = ovl_set_attr(newdentry, stat); 244e9be9d5eSMiklos Szeredi if (!err && attr) 245e9be9d5eSMiklos Szeredi err = notify_change(newdentry, attr, NULL); 246e9be9d5eSMiklos Szeredi mutex_unlock(&newdentry->d_inode->i_mutex); 247e9be9d5eSMiklos Szeredi if (err) 248e9be9d5eSMiklos Szeredi goto out_cleanup; 249e9be9d5eSMiklos Szeredi 250e9be9d5eSMiklos Szeredi err = ovl_do_rename(wdir, newdentry, udir, upper, 0); 251e9be9d5eSMiklos Szeredi if (err) 252e9be9d5eSMiklos Szeredi goto out_cleanup; 253e9be9d5eSMiklos Szeredi 254e9be9d5eSMiklos Szeredi ovl_dentry_update(dentry, newdentry); 255e9be9d5eSMiklos Szeredi newdentry = NULL; 256e9be9d5eSMiklos Szeredi 257e9be9d5eSMiklos Szeredi /* 258e9be9d5eSMiklos Szeredi * Non-directores become opaque when copied up. 259e9be9d5eSMiklos Szeredi */ 260e9be9d5eSMiklos Szeredi if (!S_ISDIR(stat->mode)) 261e9be9d5eSMiklos Szeredi ovl_dentry_set_opaque(dentry, true); 262e9be9d5eSMiklos Szeredi out2: 263e9be9d5eSMiklos Szeredi dput(upper); 264e9be9d5eSMiklos Szeredi out1: 265e9be9d5eSMiklos Szeredi dput(newdentry); 266e9be9d5eSMiklos Szeredi out: 267e9be9d5eSMiklos Szeredi return err; 268e9be9d5eSMiklos Szeredi 269e9be9d5eSMiklos Szeredi out_cleanup: 270e9be9d5eSMiklos Szeredi ovl_cleanup(wdir, newdentry); 271e9be9d5eSMiklos Szeredi goto out; 272e9be9d5eSMiklos Szeredi } 273e9be9d5eSMiklos Szeredi 274e9be9d5eSMiklos Szeredi /* 275e9be9d5eSMiklos Szeredi * Copy up a single dentry 276e9be9d5eSMiklos Szeredi * 277e9be9d5eSMiklos Szeredi * Directory renames only allowed on "pure upper" (already created on 278e9be9d5eSMiklos Szeredi * upper filesystem, never copied up). Directories which are on lower or 279e9be9d5eSMiklos Szeredi * are merged may not be renamed. For these -EXDEV is returned and 280e9be9d5eSMiklos Szeredi * userspace has to deal with it. This means, when copying up a 281e9be9d5eSMiklos Szeredi * directory we can rely on it and ancestors being stable. 282e9be9d5eSMiklos Szeredi * 283e9be9d5eSMiklos Szeredi * Non-directory renames start with copy up of source if necessary. The 284e9be9d5eSMiklos Szeredi * actual rename will only proceed once the copy up was successful. Copy 285e9be9d5eSMiklos Szeredi * up uses upper parent i_mutex for exclusion. Since rename can change 286e9be9d5eSMiklos Szeredi * d_parent it is possible that the copy up will lock the old parent. At 287e9be9d5eSMiklos Szeredi * that point the file will have already been copied up anyway. 288e9be9d5eSMiklos Szeredi */ 289e9be9d5eSMiklos Szeredi int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, 290e9be9d5eSMiklos Szeredi struct path *lowerpath, struct kstat *stat, 291e9be9d5eSMiklos Szeredi struct iattr *attr) 292e9be9d5eSMiklos Szeredi { 293e9be9d5eSMiklos Szeredi struct dentry *workdir = ovl_workdir(dentry); 294e9be9d5eSMiklos Szeredi int err; 295e9be9d5eSMiklos Szeredi struct kstat pstat; 296e9be9d5eSMiklos Szeredi struct path parentpath; 297e9be9d5eSMiklos Szeredi struct dentry *upperdir; 298e9be9d5eSMiklos Szeredi struct dentry *upperdentry; 299e9be9d5eSMiklos Szeredi const struct cred *old_cred; 300e9be9d5eSMiklos Szeredi struct cred *override_cred; 301e9be9d5eSMiklos Szeredi char *link = NULL; 302e9be9d5eSMiklos Szeredi 303e9be9d5eSMiklos Szeredi ovl_path_upper(parent, &parentpath); 304e9be9d5eSMiklos Szeredi upperdir = parentpath.dentry; 305e9be9d5eSMiklos Szeredi 306e9be9d5eSMiklos Szeredi err = vfs_getattr(&parentpath, &pstat); 307e9be9d5eSMiklos Szeredi if (err) 308e9be9d5eSMiklos Szeredi return err; 309e9be9d5eSMiklos Szeredi 310e9be9d5eSMiklos Szeredi if (S_ISLNK(stat->mode)) { 311e9be9d5eSMiklos Szeredi link = ovl_read_symlink(lowerpath->dentry); 312e9be9d5eSMiklos Szeredi if (IS_ERR(link)) 313e9be9d5eSMiklos Szeredi return PTR_ERR(link); 314e9be9d5eSMiklos Szeredi } 315e9be9d5eSMiklos Szeredi 316e9be9d5eSMiklos Szeredi err = -ENOMEM; 317e9be9d5eSMiklos Szeredi override_cred = prepare_creds(); 318e9be9d5eSMiklos Szeredi if (!override_cred) 319e9be9d5eSMiklos Szeredi goto out_free_link; 320e9be9d5eSMiklos Szeredi 321e9be9d5eSMiklos Szeredi override_cred->fsuid = stat->uid; 322e9be9d5eSMiklos Szeredi override_cred->fsgid = stat->gid; 323e9be9d5eSMiklos Szeredi /* 324e9be9d5eSMiklos Szeredi * CAP_SYS_ADMIN for copying up extended attributes 325e9be9d5eSMiklos Szeredi * CAP_DAC_OVERRIDE for create 326e9be9d5eSMiklos Szeredi * CAP_FOWNER for chmod, timestamp update 327e9be9d5eSMiklos Szeredi * CAP_FSETID for chmod 328e9be9d5eSMiklos Szeredi * CAP_CHOWN for chown 329e9be9d5eSMiklos Szeredi * CAP_MKNOD for mknod 330e9be9d5eSMiklos Szeredi */ 331e9be9d5eSMiklos Szeredi cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); 332e9be9d5eSMiklos Szeredi cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE); 333e9be9d5eSMiklos Szeredi cap_raise(override_cred->cap_effective, CAP_FOWNER); 334e9be9d5eSMiklos Szeredi cap_raise(override_cred->cap_effective, CAP_FSETID); 335e9be9d5eSMiklos Szeredi cap_raise(override_cred->cap_effective, CAP_CHOWN); 336e9be9d5eSMiklos Szeredi cap_raise(override_cred->cap_effective, CAP_MKNOD); 337e9be9d5eSMiklos Szeredi old_cred = override_creds(override_cred); 338e9be9d5eSMiklos Szeredi 339e9be9d5eSMiklos Szeredi err = -EIO; 340e9be9d5eSMiklos Szeredi if (lock_rename(workdir, upperdir) != NULL) { 341e9be9d5eSMiklos Szeredi pr_err("overlayfs: failed to lock workdir+upperdir\n"); 342e9be9d5eSMiklos Szeredi goto out_unlock; 343e9be9d5eSMiklos Szeredi } 344e9be9d5eSMiklos Szeredi upperdentry = ovl_dentry_upper(dentry); 345e9be9d5eSMiklos Szeredi if (upperdentry) { 346e9be9d5eSMiklos Szeredi unlock_rename(workdir, upperdir); 347e9be9d5eSMiklos Szeredi err = 0; 348e9be9d5eSMiklos Szeredi /* Raced with another copy-up? Do the setattr here */ 349e9be9d5eSMiklos Szeredi if (attr) { 350e9be9d5eSMiklos Szeredi mutex_lock(&upperdentry->d_inode->i_mutex); 351e9be9d5eSMiklos Szeredi err = notify_change(upperdentry, attr, NULL); 352e9be9d5eSMiklos Szeredi mutex_unlock(&upperdentry->d_inode->i_mutex); 353e9be9d5eSMiklos Szeredi } 354e9be9d5eSMiklos Szeredi goto out_put_cred; 355e9be9d5eSMiklos Szeredi } 356e9be9d5eSMiklos Szeredi 357e9be9d5eSMiklos Szeredi err = ovl_copy_up_locked(workdir, upperdir, dentry, lowerpath, 358e9be9d5eSMiklos Szeredi stat, attr, link); 359e9be9d5eSMiklos Szeredi if (!err) { 360e9be9d5eSMiklos Szeredi /* Restore timestamps on parent (best effort) */ 361e9be9d5eSMiklos Szeredi ovl_set_timestamps(upperdir, &pstat); 362e9be9d5eSMiklos Szeredi } 363e9be9d5eSMiklos Szeredi out_unlock: 364e9be9d5eSMiklos Szeredi unlock_rename(workdir, upperdir); 365e9be9d5eSMiklos Szeredi out_put_cred: 366e9be9d5eSMiklos Szeredi revert_creds(old_cred); 367e9be9d5eSMiklos Szeredi put_cred(override_cred); 368e9be9d5eSMiklos Szeredi 369e9be9d5eSMiklos Szeredi out_free_link: 370e9be9d5eSMiklos Szeredi if (link) 371e9be9d5eSMiklos Szeredi free_page((unsigned long) link); 372e9be9d5eSMiklos Szeredi 373e9be9d5eSMiklos Szeredi return err; 374e9be9d5eSMiklos Szeredi } 375e9be9d5eSMiklos Szeredi 376e9be9d5eSMiklos Szeredi int ovl_copy_up(struct dentry *dentry) 377e9be9d5eSMiklos Szeredi { 378e9be9d5eSMiklos Szeredi int err; 379e9be9d5eSMiklos Szeredi 380e9be9d5eSMiklos Szeredi err = 0; 381e9be9d5eSMiklos Szeredi while (!err) { 382e9be9d5eSMiklos Szeredi struct dentry *next; 383e9be9d5eSMiklos Szeredi struct dentry *parent; 384e9be9d5eSMiklos Szeredi struct path lowerpath; 385e9be9d5eSMiklos Szeredi struct kstat stat; 386e9be9d5eSMiklos Szeredi enum ovl_path_type type = ovl_path_type(dentry); 387e9be9d5eSMiklos Szeredi 388e9be9d5eSMiklos Szeredi if (type != OVL_PATH_LOWER) 389e9be9d5eSMiklos Szeredi break; 390e9be9d5eSMiklos Szeredi 391e9be9d5eSMiklos Szeredi next = dget(dentry); 392e9be9d5eSMiklos Szeredi /* find the topmost dentry not yet copied up */ 393e9be9d5eSMiklos Szeredi for (;;) { 394e9be9d5eSMiklos Szeredi parent = dget_parent(next); 395e9be9d5eSMiklos Szeredi 396e9be9d5eSMiklos Szeredi type = ovl_path_type(parent); 397e9be9d5eSMiklos Szeredi if (type != OVL_PATH_LOWER) 398e9be9d5eSMiklos Szeredi break; 399e9be9d5eSMiklos Szeredi 400e9be9d5eSMiklos Szeredi dput(next); 401e9be9d5eSMiklos Szeredi next = parent; 402e9be9d5eSMiklos Szeredi } 403e9be9d5eSMiklos Szeredi 404e9be9d5eSMiklos Szeredi ovl_path_lower(next, &lowerpath); 405e9be9d5eSMiklos Szeredi err = vfs_getattr(&lowerpath, &stat); 406e9be9d5eSMiklos Szeredi if (!err) 407e9be9d5eSMiklos Szeredi err = ovl_copy_up_one(parent, next, &lowerpath, &stat, NULL); 408e9be9d5eSMiklos Szeredi 409e9be9d5eSMiklos Szeredi dput(parent); 410e9be9d5eSMiklos Szeredi dput(next); 411e9be9d5eSMiklos Szeredi } 412e9be9d5eSMiklos Szeredi 413e9be9d5eSMiklos Szeredi return err; 414e9be9d5eSMiklos Szeredi } 415