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