.. | .. |
---|
| 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 <linux/module.h> |
---|
.. | .. |
---|
27 | 24 | |
---|
28 | 25 | static int ovl_ccup_set(const char *buf, const struct kernel_param *param) |
---|
29 | 26 | { |
---|
30 | | - pr_warn("overlayfs: \"check_copy_up\" module option is obsolete\n"); |
---|
| 27 | + pr_warn("\"check_copy_up\" module option is obsolete\n"); |
---|
31 | 28 | return 0; |
---|
32 | 29 | } |
---|
33 | 30 | |
---|
.. | .. |
---|
37 | 34 | } |
---|
38 | 35 | |
---|
39 | 36 | module_param_call(check_copy_up, ovl_ccup_set, ovl_ccup_get, NULL, 0644); |
---|
40 | | -MODULE_PARM_DESC(ovl_check_copy_up, "Obsolete; does nothing"); |
---|
| 37 | +MODULE_PARM_DESC(check_copy_up, "Obsolete; does nothing"); |
---|
41 | 38 | |
---|
42 | | -int ovl_copy_xattr(struct dentry *old, struct dentry *new) |
---|
| 39 | +static bool ovl_must_copy_xattr(const char *name) |
---|
| 40 | +{ |
---|
| 41 | + return !strcmp(name, XATTR_POSIX_ACL_ACCESS) || |
---|
| 42 | + !strcmp(name, XATTR_POSIX_ACL_DEFAULT) || |
---|
| 43 | + !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN); |
---|
| 44 | +} |
---|
| 45 | + |
---|
| 46 | +int ovl_copy_xattr(struct super_block *sb, struct dentry *old, |
---|
| 47 | + struct dentry *new) |
---|
43 | 48 | { |
---|
44 | 49 | ssize_t list_size, size, value_size = 0; |
---|
45 | 50 | char *buf, *name, *value = NULL; |
---|
.. | .. |
---|
77 | 82 | } |
---|
78 | 83 | list_size -= slen; |
---|
79 | 84 | |
---|
80 | | - if (ovl_is_private_xattr(name)) |
---|
| 85 | + if (ovl_is_private_xattr(sb, name)) |
---|
81 | 86 | continue; |
---|
82 | 87 | |
---|
83 | 88 | error = security_inode_copy_up_xattr(name); |
---|
.. | .. |
---|
111 | 116 | } |
---|
112 | 117 | |
---|
113 | 118 | error = vfs_setxattr(new, name, value, size, 0); |
---|
114 | | - if (error) |
---|
115 | | - break; |
---|
| 119 | + if (error) { |
---|
| 120 | + if (error != -EOPNOTSUPP || ovl_must_copy_xattr(name)) |
---|
| 121 | + break; |
---|
| 122 | + |
---|
| 123 | + /* Ignore failure to copy unknown xattrs */ |
---|
| 124 | + error = 0; |
---|
| 125 | + } |
---|
116 | 126 | } |
---|
117 | 127 | kfree(value); |
---|
118 | 128 | out: |
---|
.. | .. |
---|
120 | 130 | return error; |
---|
121 | 131 | } |
---|
122 | 132 | |
---|
123 | | -static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len) |
---|
| 133 | +static int ovl_copy_up_data(struct ovl_fs *ofs, struct path *old, |
---|
| 134 | + struct path *new, loff_t len) |
---|
124 | 135 | { |
---|
125 | 136 | struct file *old_file; |
---|
126 | 137 | struct file *new_file; |
---|
127 | 138 | loff_t old_pos = 0; |
---|
128 | 139 | loff_t new_pos = 0; |
---|
| 140 | + loff_t cloned; |
---|
| 141 | + loff_t data_pos = -1; |
---|
| 142 | + loff_t hole_len; |
---|
| 143 | + bool skip_hole = false; |
---|
129 | 144 | int error = 0; |
---|
130 | 145 | |
---|
131 | 146 | if (len == 0) |
---|
.. | .. |
---|
142 | 157 | } |
---|
143 | 158 | |
---|
144 | 159 | /* Try to use clone_file_range to clone up within the same fs */ |
---|
145 | | - error = do_clone_file_range(old_file, 0, new_file, 0, len); |
---|
146 | | - if (!error) |
---|
| 160 | + cloned = do_clone_file_range(old_file, 0, new_file, 0, len, 0); |
---|
| 161 | + if (cloned == len) |
---|
147 | 162 | goto out; |
---|
148 | 163 | /* Couldn't clone, so now we try to copy the data */ |
---|
149 | | - error = 0; |
---|
150 | 164 | |
---|
151 | | - /* FIXME: copy up sparse files efficiently */ |
---|
| 165 | + /* Check if lower fs supports seek operation */ |
---|
| 166 | + if (old_file->f_mode & FMODE_LSEEK && |
---|
| 167 | + old_file->f_op->llseek) |
---|
| 168 | + skip_hole = true; |
---|
| 169 | + |
---|
152 | 170 | while (len) { |
---|
153 | 171 | size_t this_len = OVL_COPY_UP_CHUNK_SIZE; |
---|
154 | 172 | long bytes; |
---|
.. | .. |
---|
159 | 177 | if (signal_pending_state(TASK_KILLABLE, current)) { |
---|
160 | 178 | error = -EINTR; |
---|
161 | 179 | break; |
---|
| 180 | + } |
---|
| 181 | + |
---|
| 182 | + /* |
---|
| 183 | + * Fill zero for hole will cost unnecessary disk space |
---|
| 184 | + * and meanwhile slow down the copy-up speed, so we do |
---|
| 185 | + * an optimization for hole during copy-up, it relies |
---|
| 186 | + * on SEEK_DATA implementation in lower fs so if lower |
---|
| 187 | + * fs does not support it, copy-up will behave as before. |
---|
| 188 | + * |
---|
| 189 | + * Detail logic of hole detection as below: |
---|
| 190 | + * When we detect next data position is larger than current |
---|
| 191 | + * position we will skip that hole, otherwise we copy |
---|
| 192 | + * data in the size of OVL_COPY_UP_CHUNK_SIZE. Actually, |
---|
| 193 | + * it may not recognize all kind of holes and sometimes |
---|
| 194 | + * only skips partial of hole area. However, it will be |
---|
| 195 | + * enough for most of the use cases. |
---|
| 196 | + */ |
---|
| 197 | + |
---|
| 198 | + if (skip_hole && data_pos < old_pos) { |
---|
| 199 | + data_pos = vfs_llseek(old_file, old_pos, SEEK_DATA); |
---|
| 200 | + if (data_pos > old_pos) { |
---|
| 201 | + hole_len = data_pos - old_pos; |
---|
| 202 | + len -= hole_len; |
---|
| 203 | + old_pos = new_pos = data_pos; |
---|
| 204 | + continue; |
---|
| 205 | + } else if (data_pos == -ENXIO) { |
---|
| 206 | + break; |
---|
| 207 | + } else if (data_pos < 0) { |
---|
| 208 | + skip_hole = false; |
---|
| 209 | + } |
---|
162 | 210 | } |
---|
163 | 211 | |
---|
164 | 212 | bytes = do_splice_direct(old_file, &old_pos, |
---|
.. | .. |
---|
173 | 221 | len -= bytes; |
---|
174 | 222 | } |
---|
175 | 223 | out: |
---|
176 | | - if (!error) |
---|
| 224 | + if (!error && ovl_should_sync(ofs)) |
---|
177 | 225 | error = vfs_fsync(new_file, 0); |
---|
178 | 226 | fput(new_file); |
---|
179 | 227 | out_fput: |
---|
.. | .. |
---|
231 | 279 | struct ovl_fh *ovl_encode_real_fh(struct dentry *real, bool is_upper) |
---|
232 | 280 | { |
---|
233 | 281 | struct ovl_fh *fh; |
---|
234 | | - int fh_type, fh_len, dwords; |
---|
235 | | - void *buf; |
---|
| 282 | + int fh_type, dwords; |
---|
236 | 283 | int buflen = MAX_HANDLE_SZ; |
---|
237 | 284 | uuid_t *uuid = &real->d_sb->s_uuid; |
---|
| 285 | + int err; |
---|
238 | 286 | |
---|
239 | | - buf = kmalloc(buflen, GFP_KERNEL); |
---|
240 | | - if (!buf) |
---|
| 287 | + /* Make sure the real fid stays 32bit aligned */ |
---|
| 288 | + BUILD_BUG_ON(OVL_FH_FID_OFFSET % 4); |
---|
| 289 | + BUILD_BUG_ON(MAX_HANDLE_SZ + OVL_FH_FID_OFFSET > 255); |
---|
| 290 | + |
---|
| 291 | + fh = kzalloc(buflen + OVL_FH_FID_OFFSET, GFP_KERNEL); |
---|
| 292 | + if (!fh) |
---|
241 | 293 | return ERR_PTR(-ENOMEM); |
---|
242 | 294 | |
---|
243 | 295 | /* |
---|
.. | .. |
---|
246 | 298 | * the price or reconnecting the dentry. |
---|
247 | 299 | */ |
---|
248 | 300 | dwords = buflen >> 2; |
---|
249 | | - fh_type = exportfs_encode_fh(real, buf, &dwords, 0); |
---|
| 301 | + fh_type = exportfs_encode_fh(real, (void *)fh->fb.fid, &dwords, 0); |
---|
250 | 302 | buflen = (dwords << 2); |
---|
251 | 303 | |
---|
252 | | - fh = ERR_PTR(-EIO); |
---|
| 304 | + err = -EIO; |
---|
253 | 305 | if (WARN_ON(fh_type < 0) || |
---|
254 | 306 | WARN_ON(buflen > MAX_HANDLE_SZ) || |
---|
255 | 307 | WARN_ON(fh_type == FILEID_INVALID)) |
---|
256 | | - goto out; |
---|
| 308 | + goto out_err; |
---|
257 | 309 | |
---|
258 | | - BUILD_BUG_ON(MAX_HANDLE_SZ + offsetof(struct ovl_fh, fid) > 255); |
---|
259 | | - fh_len = offsetof(struct ovl_fh, fid) + buflen; |
---|
260 | | - fh = kmalloc(fh_len, GFP_KERNEL); |
---|
261 | | - if (!fh) { |
---|
262 | | - fh = ERR_PTR(-ENOMEM); |
---|
263 | | - goto out; |
---|
264 | | - } |
---|
265 | | - |
---|
266 | | - fh->version = OVL_FH_VERSION; |
---|
267 | | - fh->magic = OVL_FH_MAGIC; |
---|
268 | | - fh->type = fh_type; |
---|
269 | | - fh->flags = OVL_FH_FLAG_CPU_ENDIAN; |
---|
| 310 | + fh->fb.version = OVL_FH_VERSION; |
---|
| 311 | + fh->fb.magic = OVL_FH_MAGIC; |
---|
| 312 | + fh->fb.type = fh_type; |
---|
| 313 | + fh->fb.flags = OVL_FH_FLAG_CPU_ENDIAN; |
---|
270 | 314 | /* |
---|
271 | 315 | * When we will want to decode an overlay dentry from this handle |
---|
272 | 316 | * and all layers are on the same fs, if we get a disconncted real |
---|
.. | .. |
---|
274 | 318 | * it to upperdentry or to lowerstack is by checking this flag. |
---|
275 | 319 | */ |
---|
276 | 320 | if (is_upper) |
---|
277 | | - fh->flags |= OVL_FH_FLAG_PATH_UPPER; |
---|
278 | | - fh->len = fh_len; |
---|
279 | | - fh->uuid = *uuid; |
---|
280 | | - memcpy(fh->fid, buf, buflen); |
---|
| 321 | + fh->fb.flags |= OVL_FH_FLAG_PATH_UPPER; |
---|
| 322 | + fh->fb.len = sizeof(fh->fb) + buflen; |
---|
| 323 | + fh->fb.uuid = *uuid; |
---|
281 | 324 | |
---|
282 | | -out: |
---|
283 | | - kfree(buf); |
---|
284 | 325 | return fh; |
---|
| 326 | + |
---|
| 327 | +out_err: |
---|
| 328 | + kfree(fh); |
---|
| 329 | + return ERR_PTR(err); |
---|
285 | 330 | } |
---|
286 | 331 | |
---|
287 | 332 | int ovl_set_origin(struct dentry *dentry, struct dentry *lower, |
---|
.. | .. |
---|
304 | 349 | /* |
---|
305 | 350 | * Do not fail when upper doesn't support xattrs. |
---|
306 | 351 | */ |
---|
307 | | - err = ovl_check_setxattr(dentry, upper, OVL_XATTR_ORIGIN, fh, |
---|
308 | | - fh ? fh->len : 0, 0); |
---|
| 352 | + err = ovl_check_setxattr(dentry, upper, OVL_XATTR_ORIGIN, fh->buf, |
---|
| 353 | + fh ? fh->fb.len : 0, 0); |
---|
309 | 354 | kfree(fh); |
---|
310 | 355 | |
---|
311 | 356 | return err; |
---|
312 | 357 | } |
---|
313 | 358 | |
---|
314 | 359 | /* Store file handle of @upper dir in @index dir entry */ |
---|
315 | | -static int ovl_set_upper_fh(struct dentry *upper, struct dentry *index) |
---|
| 360 | +static int ovl_set_upper_fh(struct ovl_fs *ofs, struct dentry *upper, |
---|
| 361 | + struct dentry *index) |
---|
316 | 362 | { |
---|
317 | 363 | const struct ovl_fh *fh; |
---|
318 | 364 | int err; |
---|
.. | .. |
---|
321 | 367 | if (IS_ERR(fh)) |
---|
322 | 368 | return PTR_ERR(fh); |
---|
323 | 369 | |
---|
324 | | - err = ovl_do_setxattr(index, OVL_XATTR_UPPER, fh, fh->len, 0); |
---|
| 370 | + err = ovl_do_setxattr(ofs, index, OVL_XATTR_UPPER, fh->buf, fh->fb.len); |
---|
325 | 371 | |
---|
326 | 372 | kfree(fh); |
---|
327 | 373 | return err; |
---|
.. | .. |
---|
366 | 412 | if (IS_ERR(temp)) |
---|
367 | 413 | goto free_name; |
---|
368 | 414 | |
---|
369 | | - err = ovl_set_upper_fh(upper, temp); |
---|
| 415 | + err = ovl_set_upper_fh(OVL_FS(dentry->d_sb), upper, temp); |
---|
370 | 416 | if (err) |
---|
371 | 417 | goto out; |
---|
372 | 418 | |
---|
.. | .. |
---|
396 | 442 | struct dentry *destdir; |
---|
397 | 443 | struct qstr destname; |
---|
398 | 444 | struct dentry *workdir; |
---|
399 | | - bool tmpfile; |
---|
400 | 445 | bool origin; |
---|
401 | 446 | bool indexed; |
---|
402 | 447 | bool metacopy; |
---|
.. | .. |
---|
430 | 475 | /* Restore timestamps on parent (best effort) */ |
---|
431 | 476 | ovl_set_timestamps(upperdir, &c->pstat); |
---|
432 | 477 | ovl_dentry_set_upper_alias(c->dentry); |
---|
| 478 | + ovl_dentry_update_reval(c->dentry, upper); |
---|
433 | 479 | } |
---|
434 | 480 | } |
---|
435 | 481 | inode_unlock(udir); |
---|
.. | .. |
---|
441 | 487 | return err; |
---|
442 | 488 | } |
---|
443 | 489 | |
---|
444 | | -static int ovl_install_temp(struct ovl_copy_up_ctx *c, struct dentry *temp, |
---|
445 | | - struct dentry **newdentry) |
---|
446 | | -{ |
---|
447 | | - int err; |
---|
448 | | - struct dentry *upper; |
---|
449 | | - struct inode *udir = d_inode(c->destdir); |
---|
450 | | - |
---|
451 | | - upper = lookup_one_len(c->destname.name, c->destdir, c->destname.len); |
---|
452 | | - if (IS_ERR(upper)) |
---|
453 | | - return PTR_ERR(upper); |
---|
454 | | - |
---|
455 | | - if (c->tmpfile) |
---|
456 | | - err = ovl_do_link(temp, udir, upper); |
---|
457 | | - else |
---|
458 | | - err = ovl_do_rename(d_inode(c->workdir), temp, udir, upper, 0); |
---|
459 | | - |
---|
460 | | - if (!err) |
---|
461 | | - *newdentry = dget(c->tmpfile ? upper : temp); |
---|
462 | | - dput(upper); |
---|
463 | | - |
---|
464 | | - return err; |
---|
465 | | -} |
---|
466 | | - |
---|
467 | | -static struct dentry *ovl_get_tmpfile(struct ovl_copy_up_ctx *c) |
---|
468 | | -{ |
---|
469 | | - int err; |
---|
470 | | - struct dentry *temp; |
---|
471 | | - const struct cred *old_creds = NULL; |
---|
472 | | - struct cred *new_creds = NULL; |
---|
473 | | - struct ovl_cattr cattr = { |
---|
474 | | - /* Can't properly set mode on creation because of the umask */ |
---|
475 | | - .mode = c->stat.mode & S_IFMT, |
---|
476 | | - .rdev = c->stat.rdev, |
---|
477 | | - .link = c->link |
---|
478 | | - }; |
---|
479 | | - |
---|
480 | | - err = security_inode_copy_up(c->dentry, &new_creds); |
---|
481 | | - temp = ERR_PTR(err); |
---|
482 | | - if (err < 0) |
---|
483 | | - goto out; |
---|
484 | | - |
---|
485 | | - if (new_creds) |
---|
486 | | - old_creds = override_creds(new_creds); |
---|
487 | | - |
---|
488 | | - if (c->tmpfile) |
---|
489 | | - temp = ovl_do_tmpfile(c->workdir, c->stat.mode); |
---|
490 | | - else |
---|
491 | | - temp = ovl_create_temp(c->workdir, &cattr); |
---|
492 | | -out: |
---|
493 | | - if (new_creds) { |
---|
494 | | - revert_creds(old_creds); |
---|
495 | | - put_cred(new_creds); |
---|
496 | | - } |
---|
497 | | - |
---|
498 | | - return temp; |
---|
499 | | -} |
---|
500 | | - |
---|
501 | 490 | static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp) |
---|
502 | 491 | { |
---|
| 492 | + struct ovl_fs *ofs = OVL_FS(c->dentry->d_sb); |
---|
503 | 493 | int err; |
---|
504 | 494 | |
---|
505 | 495 | /* |
---|
.. | .. |
---|
515 | 505 | upperpath.dentry = temp; |
---|
516 | 506 | |
---|
517 | 507 | ovl_path_lowerdata(c->dentry, &datapath); |
---|
518 | | - err = ovl_copy_up_data(&datapath, &upperpath, c->stat.size); |
---|
| 508 | + err = ovl_copy_up_data(ofs, &datapath, &upperpath, |
---|
| 509 | + c->stat.size); |
---|
519 | 510 | if (err) |
---|
520 | 511 | return err; |
---|
521 | 512 | } |
---|
522 | 513 | |
---|
523 | | - err = ovl_copy_xattr(c->lowerpath.dentry, temp); |
---|
| 514 | + err = ovl_copy_xattr(c->dentry->d_sb, c->lowerpath.dentry, temp); |
---|
524 | 515 | if (err) |
---|
525 | 516 | return err; |
---|
526 | 517 | |
---|
.. | .. |
---|
545 | 536 | } |
---|
546 | 537 | |
---|
547 | 538 | inode_lock(temp->d_inode); |
---|
548 | | - if (c->metacopy) |
---|
| 539 | + if (S_ISREG(c->stat.mode)) |
---|
549 | 540 | err = ovl_set_size(temp, &c->stat); |
---|
550 | 541 | if (!err) |
---|
551 | 542 | err = ovl_set_attr(temp, &c->stat); |
---|
.. | .. |
---|
554 | 545 | return err; |
---|
555 | 546 | } |
---|
556 | 547 | |
---|
557 | | -static int ovl_copy_up_locked(struct ovl_copy_up_ctx *c) |
---|
| 548 | +struct ovl_cu_creds { |
---|
| 549 | + const struct cred *old; |
---|
| 550 | + struct cred *new; |
---|
| 551 | +}; |
---|
| 552 | + |
---|
| 553 | +static int ovl_prep_cu_creds(struct dentry *dentry, struct ovl_cu_creds *cc) |
---|
558 | 554 | { |
---|
559 | | - struct inode *udir = c->destdir->d_inode; |
---|
560 | | - struct inode *inode; |
---|
561 | | - struct dentry *newdentry = NULL; |
---|
562 | | - struct dentry *temp; |
---|
563 | 555 | int err; |
---|
564 | 556 | |
---|
565 | | - temp = ovl_get_tmpfile(c); |
---|
| 557 | + cc->old = cc->new = NULL; |
---|
| 558 | + err = security_inode_copy_up(dentry, &cc->new); |
---|
| 559 | + if (err < 0) |
---|
| 560 | + return err; |
---|
| 561 | + |
---|
| 562 | + if (cc->new) |
---|
| 563 | + cc->old = override_creds(cc->new); |
---|
| 564 | + |
---|
| 565 | + return 0; |
---|
| 566 | +} |
---|
| 567 | + |
---|
| 568 | +static void ovl_revert_cu_creds(struct ovl_cu_creds *cc) |
---|
| 569 | +{ |
---|
| 570 | + if (cc->new) { |
---|
| 571 | + revert_creds(cc->old); |
---|
| 572 | + put_cred(cc->new); |
---|
| 573 | + } |
---|
| 574 | +} |
---|
| 575 | + |
---|
| 576 | +/* |
---|
| 577 | + * Copyup using workdir to prepare temp file. Used when copying up directories, |
---|
| 578 | + * special files or when upper fs doesn't support O_TMPFILE. |
---|
| 579 | + */ |
---|
| 580 | +static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c) |
---|
| 581 | +{ |
---|
| 582 | + struct inode *inode; |
---|
| 583 | + struct inode *udir = d_inode(c->destdir), *wdir = d_inode(c->workdir); |
---|
| 584 | + struct dentry *temp, *upper; |
---|
| 585 | + struct ovl_cu_creds cc; |
---|
| 586 | + int err; |
---|
| 587 | + struct ovl_cattr cattr = { |
---|
| 588 | + /* Can't properly set mode on creation because of the umask */ |
---|
| 589 | + .mode = c->stat.mode & S_IFMT, |
---|
| 590 | + .rdev = c->stat.rdev, |
---|
| 591 | + .link = c->link |
---|
| 592 | + }; |
---|
| 593 | + |
---|
| 594 | + /* workdir and destdir could be the same when copying up to indexdir */ |
---|
| 595 | + err = -EIO; |
---|
| 596 | + if (lock_rename(c->workdir, c->destdir) != NULL) |
---|
| 597 | + goto unlock; |
---|
| 598 | + |
---|
| 599 | + err = ovl_prep_cu_creds(c->dentry, &cc); |
---|
| 600 | + if (err) |
---|
| 601 | + goto unlock; |
---|
| 602 | + |
---|
| 603 | + temp = ovl_create_temp(c->workdir, &cattr); |
---|
| 604 | + ovl_revert_cu_creds(&cc); |
---|
| 605 | + |
---|
| 606 | + err = PTR_ERR(temp); |
---|
| 607 | + if (IS_ERR(temp)) |
---|
| 608 | + goto unlock; |
---|
| 609 | + |
---|
| 610 | + err = ovl_copy_up_inode(c, temp); |
---|
| 611 | + if (err) |
---|
| 612 | + goto cleanup; |
---|
| 613 | + |
---|
| 614 | + if (S_ISDIR(c->stat.mode) && c->indexed) { |
---|
| 615 | + err = ovl_create_index(c->dentry, c->lowerpath.dentry, temp); |
---|
| 616 | + if (err) |
---|
| 617 | + goto cleanup; |
---|
| 618 | + } |
---|
| 619 | + |
---|
| 620 | + upper = lookup_one_len(c->destname.name, c->destdir, c->destname.len); |
---|
| 621 | + err = PTR_ERR(upper); |
---|
| 622 | + if (IS_ERR(upper)) |
---|
| 623 | + goto cleanup; |
---|
| 624 | + |
---|
| 625 | + err = ovl_do_rename(wdir, temp, udir, upper, 0); |
---|
| 626 | + dput(upper); |
---|
| 627 | + if (err) |
---|
| 628 | + goto cleanup; |
---|
| 629 | + |
---|
| 630 | + if (!c->metacopy) |
---|
| 631 | + ovl_set_upperdata(d_inode(c->dentry)); |
---|
| 632 | + inode = d_inode(c->dentry); |
---|
| 633 | + ovl_inode_update(inode, temp); |
---|
| 634 | + if (S_ISDIR(inode->i_mode)) |
---|
| 635 | + ovl_set_flag(OVL_WHITEOUTS, inode); |
---|
| 636 | +unlock: |
---|
| 637 | + unlock_rename(c->workdir, c->destdir); |
---|
| 638 | + |
---|
| 639 | + return err; |
---|
| 640 | + |
---|
| 641 | +cleanup: |
---|
| 642 | + ovl_cleanup(wdir, temp); |
---|
| 643 | + dput(temp); |
---|
| 644 | + goto unlock; |
---|
| 645 | +} |
---|
| 646 | + |
---|
| 647 | +/* Copyup using O_TMPFILE which does not require cross dir locking */ |
---|
| 648 | +static int ovl_copy_up_tmpfile(struct ovl_copy_up_ctx *c) |
---|
| 649 | +{ |
---|
| 650 | + struct inode *udir = d_inode(c->destdir); |
---|
| 651 | + struct dentry *temp, *upper; |
---|
| 652 | + struct ovl_cu_creds cc; |
---|
| 653 | + int err; |
---|
| 654 | + |
---|
| 655 | + err = ovl_prep_cu_creds(c->dentry, &cc); |
---|
| 656 | + if (err) |
---|
| 657 | + return err; |
---|
| 658 | + |
---|
| 659 | + temp = ovl_do_tmpfile(c->workdir, c->stat.mode); |
---|
| 660 | + ovl_revert_cu_creds(&cc); |
---|
| 661 | + |
---|
566 | 662 | if (IS_ERR(temp)) |
---|
567 | 663 | return PTR_ERR(temp); |
---|
568 | 664 | |
---|
569 | 665 | err = ovl_copy_up_inode(c, temp); |
---|
570 | 666 | if (err) |
---|
571 | | - goto out; |
---|
| 667 | + goto out_dput; |
---|
572 | 668 | |
---|
573 | | - if (S_ISDIR(c->stat.mode) && c->indexed) { |
---|
574 | | - err = ovl_create_index(c->dentry, c->lowerpath.dentry, temp); |
---|
575 | | - if (err) |
---|
576 | | - goto out; |
---|
577 | | - } |
---|
| 669 | + inode_lock_nested(udir, I_MUTEX_PARENT); |
---|
578 | 670 | |
---|
579 | | - if (c->tmpfile) { |
---|
580 | | - inode_lock_nested(udir, I_MUTEX_PARENT); |
---|
581 | | - err = ovl_install_temp(c, temp, &newdentry); |
---|
582 | | - inode_unlock(udir); |
---|
583 | | - } else { |
---|
584 | | - err = ovl_install_temp(c, temp, &newdentry); |
---|
| 671 | + upper = lookup_one_len(c->destname.name, c->destdir, c->destname.len); |
---|
| 672 | + err = PTR_ERR(upper); |
---|
| 673 | + if (!IS_ERR(upper)) { |
---|
| 674 | + err = ovl_do_link(temp, udir, upper); |
---|
| 675 | + dput(upper); |
---|
585 | 676 | } |
---|
| 677 | + inode_unlock(udir); |
---|
| 678 | + |
---|
586 | 679 | if (err) |
---|
587 | | - goto out; |
---|
| 680 | + goto out_dput; |
---|
588 | 681 | |
---|
589 | 682 | if (!c->metacopy) |
---|
590 | 683 | ovl_set_upperdata(d_inode(c->dentry)); |
---|
591 | | - inode = d_inode(c->dentry); |
---|
592 | | - ovl_inode_update(inode, newdentry); |
---|
593 | | - if (S_ISDIR(inode->i_mode)) |
---|
594 | | - ovl_set_flag(OVL_WHITEOUTS, inode); |
---|
| 684 | + ovl_inode_update(d_inode(c->dentry), temp); |
---|
595 | 685 | |
---|
596 | | -out: |
---|
597 | | - if (err && !c->tmpfile) |
---|
598 | | - ovl_cleanup(d_inode(c->workdir), temp); |
---|
| 686 | + return 0; |
---|
| 687 | + |
---|
| 688 | +out_dput: |
---|
599 | 689 | dput(temp); |
---|
600 | 690 | return err; |
---|
601 | | - |
---|
602 | 691 | } |
---|
603 | 692 | |
---|
604 | 693 | /* |
---|
.. | .. |
---|
652 | 741 | } |
---|
653 | 742 | |
---|
654 | 743 | /* Should we copyup with O_TMPFILE or with workdir? */ |
---|
655 | | - if (S_ISREG(c->stat.mode) && ofs->tmpfile) { |
---|
656 | | - c->tmpfile = true; |
---|
657 | | - err = ovl_copy_up_locked(c); |
---|
658 | | - } else { |
---|
659 | | - err = ovl_lock_rename_workdir(c->workdir, c->destdir); |
---|
660 | | - if (!err) { |
---|
661 | | - err = ovl_copy_up_locked(c); |
---|
662 | | - unlock_rename(c->workdir, c->destdir); |
---|
663 | | - } |
---|
664 | | - } |
---|
665 | | - |
---|
666 | | - |
---|
| 744 | + if (S_ISREG(c->stat.mode) && ofs->tmpfile) |
---|
| 745 | + err = ovl_copy_up_tmpfile(c); |
---|
| 746 | + else |
---|
| 747 | + err = ovl_copy_up_workdir(c); |
---|
667 | 748 | if (err) |
---|
668 | 749 | goto out; |
---|
669 | 750 | |
---|
.. | .. |
---|
682 | 763 | inode_unlock(udir); |
---|
683 | 764 | |
---|
684 | 765 | ovl_dentry_set_upper_alias(c->dentry); |
---|
| 766 | + ovl_dentry_update_reval(c->dentry, ovl_dentry_upper(c->dentry)); |
---|
685 | 767 | } |
---|
686 | 768 | |
---|
687 | 769 | out: |
---|
.. | .. |
---|
707 | 789 | return true; |
---|
708 | 790 | } |
---|
709 | 791 | |
---|
| 792 | +static ssize_t ovl_getxattr(struct dentry *dentry, char *name, char **value) |
---|
| 793 | +{ |
---|
| 794 | + ssize_t res; |
---|
| 795 | + char *buf; |
---|
| 796 | + |
---|
| 797 | + res = vfs_getxattr(dentry, name, NULL, 0); |
---|
| 798 | + if (res == -ENODATA || res == -EOPNOTSUPP) |
---|
| 799 | + res = 0; |
---|
| 800 | + |
---|
| 801 | + if (res > 0) { |
---|
| 802 | + buf = kzalloc(res, GFP_KERNEL); |
---|
| 803 | + if (!buf) |
---|
| 804 | + return -ENOMEM; |
---|
| 805 | + |
---|
| 806 | + res = vfs_getxattr(dentry, name, buf, res); |
---|
| 807 | + if (res < 0) |
---|
| 808 | + kfree(buf); |
---|
| 809 | + else |
---|
| 810 | + *value = buf; |
---|
| 811 | + } |
---|
| 812 | + return res; |
---|
| 813 | +} |
---|
| 814 | + |
---|
710 | 815 | /* Copy up data of an inode which was copied up metadata only in the past. */ |
---|
711 | 816 | static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c) |
---|
712 | 817 | { |
---|
| 818 | + struct ovl_fs *ofs = OVL_FS(c->dentry->d_sb); |
---|
713 | 819 | struct path upperpath, datapath; |
---|
714 | 820 | int err; |
---|
715 | 821 | char *capability = NULL; |
---|
716 | | - ssize_t uninitialized_var(cap_size); |
---|
| 822 | + ssize_t cap_size; |
---|
717 | 823 | |
---|
718 | 824 | ovl_path_upper(c->dentry, &upperpath); |
---|
719 | 825 | if (WARN_ON(upperpath.dentry == NULL)) |
---|
.. | .. |
---|
725 | 831 | |
---|
726 | 832 | if (c->stat.size) { |
---|
727 | 833 | err = cap_size = ovl_getxattr(upperpath.dentry, XATTR_NAME_CAPS, |
---|
728 | | - &capability, 0); |
---|
729 | | - if (err < 0 && err != -ENODATA) |
---|
| 834 | + &capability); |
---|
| 835 | + if (cap_size < 0) |
---|
730 | 836 | goto out; |
---|
731 | 837 | } |
---|
732 | 838 | |
---|
733 | | - err = ovl_copy_up_data(&datapath, &upperpath, c->stat.size); |
---|
| 839 | + err = ovl_copy_up_data(ofs, &datapath, &upperpath, c->stat.size); |
---|
734 | 840 | if (err) |
---|
735 | 841 | goto out_free; |
---|
736 | 842 | |
---|
.. | .. |
---|
739 | 845 | * don't want that to happen for normal copy-up operation. |
---|
740 | 846 | */ |
---|
741 | 847 | if (capability) { |
---|
742 | | - err = ovl_do_setxattr(upperpath.dentry, XATTR_NAME_CAPS, |
---|
743 | | - capability, cap_size, 0); |
---|
| 848 | + err = vfs_setxattr(upperpath.dentry, XATTR_NAME_CAPS, |
---|
| 849 | + capability, cap_size, 0); |
---|
744 | 850 | if (err) |
---|
745 | 851 | goto out_free; |
---|
746 | 852 | } |
---|
747 | 853 | |
---|
748 | 854 | |
---|
749 | | - err = vfs_removexattr(upperpath.dentry, OVL_XATTR_METACOPY); |
---|
| 855 | + err = ovl_do_removexattr(ofs, upperpath.dentry, OVL_XATTR_METACOPY); |
---|
750 | 856 | if (err) |
---|
751 | 857 | goto out_free; |
---|
752 | 858 | |
---|
.. | .. |
---|
821 | 927 | return err; |
---|
822 | 928 | } |
---|
823 | 929 | |
---|
824 | | -int ovl_copy_up_flags(struct dentry *dentry, int flags) |
---|
| 930 | +static int ovl_copy_up_flags(struct dentry *dentry, int flags) |
---|
825 | 931 | { |
---|
826 | 932 | int err = 0; |
---|
827 | 933 | const struct cred *old_cred; |
---|
.. | .. |
---|
860 | 966 | dput(parent); |
---|
861 | 967 | dput(next); |
---|
862 | 968 | } |
---|
863 | | - ovl_revert_creds(old_cred); |
---|
| 969 | + ovl_revert_creds(dentry->d_sb, old_cred); |
---|
864 | 970 | |
---|
865 | 971 | return err; |
---|
866 | 972 | } |
---|