diff options
-rw-r--r-- | fs/overlayfs/copy_up.c | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index 01e332725e94..6e39e90b5605 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/fdtable.h> | 20 | #include <linux/fdtable.h> |
21 | #include <linux/ratelimit.h> | 21 | #include <linux/ratelimit.h> |
22 | #include "overlayfs.h" | 22 | #include "overlayfs.h" |
23 | #include "ovl_entry.h" | ||
23 | 24 | ||
24 | #define OVL_COPY_UP_CHUNK_SIZE (1 << 20) | 25 | #define OVL_COPY_UP_CHUNK_SIZE (1 << 20) |
25 | 26 | ||
@@ -233,7 +234,7 @@ int ovl_set_attr(struct dentry *upperdentry, struct kstat *stat) | |||
233 | static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, | 234 | static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, |
234 | struct dentry *dentry, struct path *lowerpath, | 235 | struct dentry *dentry, struct path *lowerpath, |
235 | struct kstat *stat, const char *link, | 236 | struct kstat *stat, const char *link, |
236 | struct kstat *pstat) | 237 | struct kstat *pstat, bool tmpfile) |
237 | { | 238 | { |
238 | struct inode *wdir = workdir->d_inode; | 239 | struct inode *wdir = workdir->d_inode; |
239 | struct inode *udir = upperdir->d_inode; | 240 | struct inode *udir = upperdir->d_inode; |
@@ -263,12 +264,17 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, | |||
263 | if (new_creds) | 264 | if (new_creds) |
264 | old_creds = override_creds(new_creds); | 265 | old_creds = override_creds(new_creds); |
265 | 266 | ||
266 | temp = ovl_lookup_temp(workdir, dentry); | 267 | if (tmpfile) |
268 | temp = ovl_do_tmpfile(upperdir, stat->mode); | ||
269 | else | ||
270 | temp = ovl_lookup_temp(workdir, dentry); | ||
267 | err = PTR_ERR(temp); | 271 | err = PTR_ERR(temp); |
268 | if (IS_ERR(temp)) | 272 | if (IS_ERR(temp)) |
269 | goto out1; | 273 | goto out1; |
270 | 274 | ||
271 | err = ovl_create_real(wdir, temp, &cattr, NULL, true); | 275 | err = 0; |
276 | if (!tmpfile) | ||
277 | err = ovl_create_real(wdir, temp, &cattr, NULL, true); | ||
272 | 278 | ||
273 | if (new_creds) { | 279 | if (new_creds) { |
274 | revert_creds(old_creds); | 280 | revert_creds(old_creds); |
@@ -300,11 +306,14 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, | |||
300 | if (err) | 306 | if (err) |
301 | goto out_cleanup; | 307 | goto out_cleanup; |
302 | 308 | ||
303 | err = ovl_do_rename(wdir, temp, udir, upper, 0); | 309 | if (tmpfile) |
310 | err = ovl_do_link(temp, udir, upper, true); | ||
311 | else | ||
312 | err = ovl_do_rename(wdir, temp, udir, upper, 0); | ||
304 | if (err) | 313 | if (err) |
305 | goto out_cleanup; | 314 | goto out_cleanup; |
306 | 315 | ||
307 | newdentry = dget(temp); | 316 | newdentry = dget(tmpfile ? upper : temp); |
308 | ovl_dentry_update(dentry, newdentry); | 317 | ovl_dentry_update(dentry, newdentry); |
309 | ovl_inode_update(d_inode(dentry), d_inode(newdentry)); | 318 | ovl_inode_update(d_inode(dentry), d_inode(newdentry)); |
310 | 319 | ||
@@ -318,7 +327,8 @@ out: | |||
318 | return err; | 327 | return err; |
319 | 328 | ||
320 | out_cleanup: | 329 | out_cleanup: |
321 | ovl_cleanup(wdir, temp); | 330 | if (!tmpfile) |
331 | ovl_cleanup(wdir, temp); | ||
322 | goto out2; | 332 | goto out2; |
323 | } | 333 | } |
324 | 334 | ||
@@ -342,6 +352,9 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, | |||
342 | struct dentry *lowerdentry = lowerpath->dentry; | 352 | struct dentry *lowerdentry = lowerpath->dentry; |
343 | struct dentry *upperdir; | 353 | struct dentry *upperdir; |
344 | const char *link = NULL; | 354 | const char *link = NULL; |
355 | struct ovl_fs *ofs = dentry->d_sb->s_fs_info; | ||
356 | /* Should we copyup with O_TMPFILE or with workdir? */ | ||
357 | bool tmpfile = S_ISREG(stat->mode) && ofs->tmpfile; | ||
345 | 358 | ||
346 | if (WARN_ON(!workdir)) | 359 | if (WARN_ON(!workdir)) |
347 | return -EROFS; | 360 | return -EROFS; |
@@ -373,7 +386,7 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, | |||
373 | } | 386 | } |
374 | 387 | ||
375 | err = ovl_copy_up_locked(workdir, upperdir, dentry, lowerpath, | 388 | err = ovl_copy_up_locked(workdir, upperdir, dentry, lowerpath, |
376 | stat, link, &pstat); | 389 | stat, link, &pstat, tmpfile); |
377 | out_unlock: | 390 | out_unlock: |
378 | unlock_rename(workdir, upperdir); | 391 | unlock_rename(workdir, upperdir); |
379 | do_delayed_call(&done); | 392 | do_delayed_call(&done); |