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); 5797daf8b9SMiklos 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 840480334fSDavid Howells old_file = ovl_path_open(old, O_LARGEFILE | O_RDONLY); 85e9be9d5eSMiklos Szeredi if (IS_ERR(old_file)) 86e9be9d5eSMiklos Szeredi return PTR_ERR(old_file); 87e9be9d5eSMiklos Szeredi 880480334fSDavid Howells new_file = ovl_path_open(new, O_LARGEFILE | 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 static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, 197e9be9d5eSMiklos Szeredi struct dentry *dentry, struct path *lowerpath, 198e9be9d5eSMiklos Szeredi struct kstat *stat, struct iattr *attr, 199e9be9d5eSMiklos Szeredi const char *link) 200e9be9d5eSMiklos Szeredi { 201e9be9d5eSMiklos Szeredi struct inode *wdir = workdir->d_inode; 202e9be9d5eSMiklos Szeredi struct inode *udir = upperdir->d_inode; 203e9be9d5eSMiklos Szeredi struct dentry *newdentry = NULL; 204e9be9d5eSMiklos Szeredi struct dentry *upper = NULL; 205e9be9d5eSMiklos Szeredi umode_t mode = stat->mode; 206e9be9d5eSMiklos Szeredi int err; 207e9be9d5eSMiklos Szeredi 208e9be9d5eSMiklos Szeredi newdentry = ovl_lookup_temp(workdir, dentry); 209e9be9d5eSMiklos Szeredi err = PTR_ERR(newdentry); 210e9be9d5eSMiklos Szeredi if (IS_ERR(newdentry)) 211e9be9d5eSMiklos Szeredi goto out; 212e9be9d5eSMiklos Szeredi 213e9be9d5eSMiklos Szeredi upper = lookup_one_len(dentry->d_name.name, upperdir, 214e9be9d5eSMiklos Szeredi dentry->d_name.len); 215e9be9d5eSMiklos Szeredi err = PTR_ERR(upper); 216e9be9d5eSMiklos Szeredi if (IS_ERR(upper)) 217e9be9d5eSMiklos Szeredi goto out1; 218e9be9d5eSMiklos Szeredi 219e9be9d5eSMiklos Szeredi /* Can't properly set mode on creation because of the umask */ 220e9be9d5eSMiklos Szeredi stat->mode &= S_IFMT; 221e9be9d5eSMiklos Szeredi err = ovl_create_real(wdir, newdentry, stat, link, NULL, true); 222e9be9d5eSMiklos Szeredi stat->mode = mode; 223e9be9d5eSMiklos Szeredi if (err) 224e9be9d5eSMiklos Szeredi goto out2; 225e9be9d5eSMiklos Szeredi 226e9be9d5eSMiklos Szeredi if (S_ISREG(stat->mode)) { 227e9be9d5eSMiklos Szeredi struct path upperpath; 228e9be9d5eSMiklos Szeredi ovl_path_upper(dentry, &upperpath); 229e9be9d5eSMiklos Szeredi BUG_ON(upperpath.dentry != NULL); 230e9be9d5eSMiklos Szeredi upperpath.dentry = newdentry; 231e9be9d5eSMiklos Szeredi 232e9be9d5eSMiklos Szeredi err = ovl_copy_up_data(lowerpath, &upperpath, stat->size); 233e9be9d5eSMiklos Szeredi if (err) 234e9be9d5eSMiklos Szeredi goto out_cleanup; 235e9be9d5eSMiklos Szeredi } 236e9be9d5eSMiklos Szeredi 237e9be9d5eSMiklos Szeredi err = ovl_copy_xattr(lowerpath->dentry, newdentry); 238e9be9d5eSMiklos Szeredi if (err) 239e9be9d5eSMiklos Szeredi goto out_cleanup; 240e9be9d5eSMiklos Szeredi 241e9be9d5eSMiklos Szeredi mutex_lock(&newdentry->d_inode->i_mutex); 242e9be9d5eSMiklos Szeredi err = ovl_set_attr(newdentry, stat); 243e9be9d5eSMiklos Szeredi if (!err && attr) 244e9be9d5eSMiklos Szeredi err = notify_change(newdentry, attr, NULL); 245e9be9d5eSMiklos Szeredi mutex_unlock(&newdentry->d_inode->i_mutex); 246e9be9d5eSMiklos Szeredi if (err) 247e9be9d5eSMiklos Szeredi goto out_cleanup; 248e9be9d5eSMiklos Szeredi 249e9be9d5eSMiklos Szeredi err = ovl_do_rename(wdir, newdentry, udir, upper, 0); 250e9be9d5eSMiklos Szeredi if (err) 251e9be9d5eSMiklos Szeredi goto out_cleanup; 252e9be9d5eSMiklos Szeredi 253e9be9d5eSMiklos Szeredi ovl_dentry_update(dentry, newdentry); 254e9be9d5eSMiklos Szeredi newdentry = NULL; 255e9be9d5eSMiklos Szeredi 256e9be9d5eSMiklos Szeredi /* 257e9be9d5eSMiklos Szeredi * Non-directores become opaque when copied up. 258e9be9d5eSMiklos Szeredi */ 259e9be9d5eSMiklos Szeredi if (!S_ISDIR(stat->mode)) 260e9be9d5eSMiklos Szeredi ovl_dentry_set_opaque(dentry, true); 261e9be9d5eSMiklos Szeredi out2: 262e9be9d5eSMiklos Szeredi dput(upper); 263e9be9d5eSMiklos Szeredi out1: 264e9be9d5eSMiklos Szeredi dput(newdentry); 265e9be9d5eSMiklos Szeredi out: 266e9be9d5eSMiklos Szeredi return err; 267e9be9d5eSMiklos Szeredi 268e9be9d5eSMiklos Szeredi out_cleanup: 269e9be9d5eSMiklos Szeredi ovl_cleanup(wdir, newdentry); 270ab79efabSDavid Howells goto out2; 271e9be9d5eSMiklos Szeredi } 272e9be9d5eSMiklos Szeredi 273e9be9d5eSMiklos Szeredi /* 274e9be9d5eSMiklos Szeredi * Copy up a single dentry 275e9be9d5eSMiklos Szeredi * 276e9be9d5eSMiklos Szeredi * Directory renames only allowed on "pure upper" (already created on 277e9be9d5eSMiklos Szeredi * upper filesystem, never copied up). Directories which are on lower or 278e9be9d5eSMiklos Szeredi * are merged may not be renamed. For these -EXDEV is returned and 279e9be9d5eSMiklos Szeredi * userspace has to deal with it. This means, when copying up a 280e9be9d5eSMiklos Szeredi * directory we can rely on it and ancestors being stable. 281e9be9d5eSMiklos Szeredi * 282e9be9d5eSMiklos Szeredi * Non-directory renames start with copy up of source if necessary. The 283e9be9d5eSMiklos Szeredi * actual rename will only proceed once the copy up was successful. Copy 284e9be9d5eSMiklos Szeredi * up uses upper parent i_mutex for exclusion. Since rename can change 285e9be9d5eSMiklos Szeredi * d_parent it is possible that the copy up will lock the old parent. At 286e9be9d5eSMiklos Szeredi * that point the file will have already been copied up anyway. 287e9be9d5eSMiklos Szeredi */ 288e9be9d5eSMiklos Szeredi int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, 289e9be9d5eSMiklos Szeredi struct path *lowerpath, struct kstat *stat, 290e9be9d5eSMiklos Szeredi struct iattr *attr) 291e9be9d5eSMiklos Szeredi { 292e9be9d5eSMiklos Szeredi struct dentry *workdir = ovl_workdir(dentry); 293e9be9d5eSMiklos Szeredi int err; 294e9be9d5eSMiklos Szeredi struct kstat pstat; 295e9be9d5eSMiklos Szeredi struct path parentpath; 296e9be9d5eSMiklos Szeredi struct dentry *upperdir; 297e9be9d5eSMiklos Szeredi struct dentry *upperdentry; 298e9be9d5eSMiklos Szeredi const struct cred *old_cred; 299e9be9d5eSMiklos Szeredi struct cred *override_cred; 300e9be9d5eSMiklos Szeredi char *link = NULL; 301e9be9d5eSMiklos Szeredi 302cc6f67bcSMiklos Szeredi if (WARN_ON(!workdir)) 303cc6f67bcSMiklos Szeredi return -EROFS; 304cc6f67bcSMiklos Szeredi 305e9be9d5eSMiklos Szeredi ovl_path_upper(parent, &parentpath); 306e9be9d5eSMiklos Szeredi upperdir = parentpath.dentry; 307e9be9d5eSMiklos Szeredi 308e9be9d5eSMiklos Szeredi err = vfs_getattr(&parentpath, &pstat); 309e9be9d5eSMiklos Szeredi if (err) 310e9be9d5eSMiklos Szeredi return err; 311e9be9d5eSMiklos Szeredi 312e9be9d5eSMiklos Szeredi if (S_ISLNK(stat->mode)) { 313e9be9d5eSMiklos Szeredi link = ovl_read_symlink(lowerpath->dentry); 314e9be9d5eSMiklos Szeredi if (IS_ERR(link)) 315e9be9d5eSMiklos Szeredi return PTR_ERR(link); 316e9be9d5eSMiklos Szeredi } 317e9be9d5eSMiklos Szeredi 318e9be9d5eSMiklos Szeredi err = -ENOMEM; 319e9be9d5eSMiklos Szeredi override_cred = prepare_creds(); 320e9be9d5eSMiklos Szeredi if (!override_cred) 321e9be9d5eSMiklos Szeredi goto out_free_link; 322e9be9d5eSMiklos Szeredi 323e9be9d5eSMiklos Szeredi override_cred->fsuid = stat->uid; 324e9be9d5eSMiklos Szeredi override_cred->fsgid = stat->gid; 325e9be9d5eSMiklos Szeredi /* 326e9be9d5eSMiklos Szeredi * CAP_SYS_ADMIN for copying up extended attributes 327e9be9d5eSMiklos Szeredi * CAP_DAC_OVERRIDE for create 328e9be9d5eSMiklos Szeredi * CAP_FOWNER for chmod, timestamp update 329e9be9d5eSMiklos Szeredi * CAP_FSETID for chmod 330e9be9d5eSMiklos Szeredi * CAP_CHOWN for chown 331e9be9d5eSMiklos Szeredi * CAP_MKNOD for mknod 332e9be9d5eSMiklos Szeredi */ 333e9be9d5eSMiklos Szeredi cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); 334e9be9d5eSMiklos Szeredi cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE); 335e9be9d5eSMiklos Szeredi cap_raise(override_cred->cap_effective, CAP_FOWNER); 336e9be9d5eSMiklos Szeredi cap_raise(override_cred->cap_effective, CAP_FSETID); 337e9be9d5eSMiklos Szeredi cap_raise(override_cred->cap_effective, CAP_CHOWN); 338e9be9d5eSMiklos Szeredi cap_raise(override_cred->cap_effective, CAP_MKNOD); 339e9be9d5eSMiklos Szeredi old_cred = override_creds(override_cred); 340e9be9d5eSMiklos Szeredi 341e9be9d5eSMiklos Szeredi err = -EIO; 342e9be9d5eSMiklos Szeredi if (lock_rename(workdir, upperdir) != NULL) { 343e9be9d5eSMiklos Szeredi pr_err("overlayfs: failed to lock workdir+upperdir\n"); 344e9be9d5eSMiklos Szeredi goto out_unlock; 345e9be9d5eSMiklos Szeredi } 346e9be9d5eSMiklos Szeredi upperdentry = ovl_dentry_upper(dentry); 347e9be9d5eSMiklos Szeredi if (upperdentry) { 348e9be9d5eSMiklos Szeredi unlock_rename(workdir, upperdir); 349e9be9d5eSMiklos Szeredi err = 0; 350e9be9d5eSMiklos Szeredi /* Raced with another copy-up? Do the setattr here */ 351e9be9d5eSMiklos Szeredi if (attr) { 352e9be9d5eSMiklos Szeredi mutex_lock(&upperdentry->d_inode->i_mutex); 353e9be9d5eSMiklos Szeredi err = notify_change(upperdentry, attr, NULL); 354e9be9d5eSMiklos Szeredi mutex_unlock(&upperdentry->d_inode->i_mutex); 355e9be9d5eSMiklos Szeredi } 356e9be9d5eSMiklos Szeredi goto out_put_cred; 357e9be9d5eSMiklos Szeredi } 358e9be9d5eSMiklos Szeredi 359e9be9d5eSMiklos Szeredi err = ovl_copy_up_locked(workdir, upperdir, dentry, lowerpath, 360e9be9d5eSMiklos Szeredi stat, attr, link); 361e9be9d5eSMiklos Szeredi if (!err) { 362e9be9d5eSMiklos Szeredi /* Restore timestamps on parent (best effort) */ 363e9be9d5eSMiklos Szeredi ovl_set_timestamps(upperdir, &pstat); 364e9be9d5eSMiklos Szeredi } 365e9be9d5eSMiklos Szeredi out_unlock: 366e9be9d5eSMiklos Szeredi unlock_rename(workdir, upperdir); 367e9be9d5eSMiklos Szeredi out_put_cred: 368e9be9d5eSMiklos Szeredi revert_creds(old_cred); 369e9be9d5eSMiklos Szeredi put_cred(override_cred); 370e9be9d5eSMiklos Szeredi 371e9be9d5eSMiklos Szeredi out_free_link: 372e9be9d5eSMiklos Szeredi if (link) 373e9be9d5eSMiklos Szeredi free_page((unsigned long) link); 374e9be9d5eSMiklos Szeredi 375e9be9d5eSMiklos Szeredi return err; 376e9be9d5eSMiklos Szeredi } 377e9be9d5eSMiklos Szeredi 378e9be9d5eSMiklos Szeredi int ovl_copy_up(struct dentry *dentry) 379e9be9d5eSMiklos Szeredi { 380e9be9d5eSMiklos Szeredi int err; 381e9be9d5eSMiklos Szeredi 382e9be9d5eSMiklos Szeredi err = 0; 383e9be9d5eSMiklos Szeredi while (!err) { 384e9be9d5eSMiklos Szeredi struct dentry *next; 385e9be9d5eSMiklos Szeredi struct dentry *parent; 386e9be9d5eSMiklos Szeredi struct path lowerpath; 387e9be9d5eSMiklos Szeredi struct kstat stat; 388e9be9d5eSMiklos Szeredi enum ovl_path_type type = ovl_path_type(dentry); 389e9be9d5eSMiklos Szeredi 3901afaba1eSMiklos Szeredi if (OVL_TYPE_UPPER(type)) 391e9be9d5eSMiklos Szeredi break; 392e9be9d5eSMiklos Szeredi 393e9be9d5eSMiklos Szeredi next = dget(dentry); 394e9be9d5eSMiklos Szeredi /* find the topmost dentry not yet copied up */ 395e9be9d5eSMiklos Szeredi for (;;) { 396e9be9d5eSMiklos Szeredi parent = dget_parent(next); 397e9be9d5eSMiklos Szeredi 398e9be9d5eSMiklos Szeredi type = ovl_path_type(parent); 3991afaba1eSMiklos Szeredi if (OVL_TYPE_UPPER(type)) 400e9be9d5eSMiklos Szeredi break; 401e9be9d5eSMiklos Szeredi 402e9be9d5eSMiklos Szeredi dput(next); 403e9be9d5eSMiklos Szeredi next = parent; 404e9be9d5eSMiklos Szeredi } 405e9be9d5eSMiklos Szeredi 406e9be9d5eSMiklos Szeredi ovl_path_lower(next, &lowerpath); 407e9be9d5eSMiklos Szeredi err = vfs_getattr(&lowerpath, &stat); 408e9be9d5eSMiklos Szeredi if (!err) 409e9be9d5eSMiklos Szeredi err = ovl_copy_up_one(parent, next, &lowerpath, &stat, NULL); 410e9be9d5eSMiklos Szeredi 411e9be9d5eSMiklos Szeredi dput(parent); 412e9be9d5eSMiklos Szeredi dput(next); 413e9be9d5eSMiklos Szeredi } 414e9be9d5eSMiklos Szeredi 415e9be9d5eSMiklos Szeredi return err; 416e9be9d5eSMiklos Szeredi } 417