21
21
#include <linux/fdtable.h>
22
22
#include <linux/ratelimit.h>
23
23
#include "overlayfs.h"
24
+ #include "ovl_entry.h"
24
25
25
26
#define OVL_COPY_UP_CHUNK_SIZE (1 << 20)
26
27
@@ -233,12 +234,14 @@ int ovl_set_attr(struct dentry *upperdentry, struct kstat *stat)
233
234
234
235
static int ovl_copy_up_locked (struct dentry * workdir , struct dentry * upperdir ,
235
236
struct dentry * dentry , struct path * lowerpath ,
236
- struct kstat * stat , const char * link )
237
+ struct kstat * stat , const char * link ,
238
+ struct kstat * pstat , bool tmpfile )
237
239
{
238
240
struct inode * wdir = workdir -> d_inode ;
239
241
struct inode * udir = upperdir -> d_inode ;
240
242
struct dentry * newdentry = NULL ;
241
243
struct dentry * upper = NULL ;
244
+ struct dentry * temp = NULL ;
242
245
int err ;
243
246
const struct cred * old_creds = NULL ;
244
247
struct cred * new_creds = NULL ;
@@ -249,25 +252,30 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,
249
252
.link = link
250
253
};
251
254
252
- newdentry = ovl_lookup_temp (workdir , dentry );
253
- err = PTR_ERR (newdentry );
254
- if (IS_ERR (newdentry ))
255
- goto out ;
256
-
257
255
upper = lookup_one_len (dentry -> d_name .name , upperdir ,
258
256
dentry -> d_name .len );
259
257
err = PTR_ERR (upper );
260
258
if (IS_ERR (upper ))
261
- goto out1 ;
259
+ goto out ;
262
260
263
261
err = security_inode_copy_up (dentry , & new_creds );
264
262
if (err < 0 )
265
- goto out2 ;
263
+ goto out1 ;
266
264
267
265
if (new_creds )
268
266
old_creds = override_creds (new_creds );
269
267
270
- err = ovl_create_real (wdir , newdentry , & cattr , NULL , true);
268
+ if (tmpfile )
269
+ temp = ovl_do_tmpfile (upperdir , stat -> mode );
270
+ else
271
+ temp = ovl_lookup_temp (workdir , dentry );
272
+ err = PTR_ERR (temp );
273
+ if (IS_ERR (temp ))
274
+ goto out1 ;
275
+
276
+ err = 0 ;
277
+ if (!tmpfile )
278
+ err = ovl_create_real (wdir , temp , & cattr , NULL , true);
271
279
272
280
if (new_creds ) {
273
281
revert_creds (old_creds );
@@ -282,39 +290,55 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,
282
290
283
291
ovl_path_upper (dentry , & upperpath );
284
292
BUG_ON (upperpath .dentry != NULL );
285
- upperpath .dentry = newdentry ;
293
+ upperpath .dentry = temp ;
294
+
295
+ if (tmpfile ) {
296
+ inode_unlock (udir );
297
+ err = ovl_copy_up_data (lowerpath , & upperpath ,
298
+ stat -> size );
299
+ inode_lock_nested (udir , I_MUTEX_PARENT );
300
+ } else {
301
+ err = ovl_copy_up_data (lowerpath , & upperpath ,
302
+ stat -> size );
303
+ }
286
304
287
- err = ovl_copy_up_data (lowerpath , & upperpath , stat -> size );
288
305
if (err )
289
306
goto out_cleanup ;
290
307
}
291
308
292
- err = ovl_copy_xattr (lowerpath -> dentry , newdentry );
309
+ err = ovl_copy_xattr (lowerpath -> dentry , temp );
293
310
if (err )
294
311
goto out_cleanup ;
295
312
296
- inode_lock (newdentry -> d_inode );
297
- err = ovl_set_attr (newdentry , stat );
298
- inode_unlock (newdentry -> d_inode );
313
+ inode_lock (temp -> d_inode );
314
+ err = ovl_set_attr (temp , stat );
315
+ inode_unlock (temp -> d_inode );
299
316
if (err )
300
317
goto out_cleanup ;
301
318
302
- err = ovl_do_rename (wdir , newdentry , udir , upper , 0 );
319
+ if (tmpfile )
320
+ err = ovl_do_link (temp , udir , upper , true);
321
+ else
322
+ err = ovl_do_rename (wdir , temp , udir , upper , 0 );
303
323
if (err )
304
324
goto out_cleanup ;
305
325
326
+ newdentry = dget (tmpfile ? upper : temp );
306
327
ovl_dentry_update (dentry , newdentry );
307
328
ovl_inode_update (d_inode (dentry ), d_inode (newdentry ));
308
- newdentry = NULL ;
329
+
330
+ /* Restore timestamps on parent (best effort) */
331
+ ovl_set_timestamps (upperdir , pstat );
309
332
out2 :
310
- dput (upper );
333
+ dput (temp );
311
334
out1 :
312
- dput (newdentry );
335
+ dput (upper );
313
336
out :
314
337
return err ;
315
338
316
339
out_cleanup :
317
- ovl_cleanup (wdir , newdentry );
340
+ if (!tmpfile )
341
+ ovl_cleanup (wdir , temp );
318
342
goto out2 ;
319
343
}
320
344
@@ -338,6 +362,7 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
338
362
struct dentry * lowerdentry = lowerpath -> dentry ;
339
363
struct dentry * upperdir ;
340
364
const char * link = NULL ;
365
+ struct ovl_fs * ofs = dentry -> d_sb -> s_fs_info ;
341
366
342
367
if (WARN_ON (!workdir ))
343
368
return - EROFS ;
@@ -358,6 +383,25 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
358
383
return PTR_ERR (link );
359
384
}
360
385
386
+ /* Should we copyup with O_TMPFILE or with workdir? */
387
+ if (S_ISREG (stat -> mode ) && ofs -> tmpfile ) {
388
+ err = ovl_copy_up_start (dentry );
389
+ /* err < 0: interrupted, err > 0: raced with another copy-up */
390
+ if (unlikely (err )) {
391
+ pr_debug ("ovl_copy_up_start(%pd2) = %i\n" , dentry , err );
392
+ if (err > 0 )
393
+ err = 0 ;
394
+ goto out_done ;
395
+ }
396
+
397
+ inode_lock_nested (upperdir -> d_inode , I_MUTEX_PARENT );
398
+ err = ovl_copy_up_locked (workdir , upperdir , dentry , lowerpath ,
399
+ stat , link , & pstat , true);
400
+ inode_unlock (upperdir -> d_inode );
401
+ ovl_copy_up_end (dentry );
402
+ goto out_done ;
403
+ }
404
+
361
405
err = - EIO ;
362
406
if (lock_rename (workdir , upperdir ) != NULL ) {
363
407
pr_err ("overlayfs: failed to lock workdir+upperdir\n" );
@@ -370,13 +414,10 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
370
414
}
371
415
372
416
err = ovl_copy_up_locked (workdir , upperdir , dentry , lowerpath ,
373
- stat , link );
374
- if (!err ) {
375
- /* Restore timestamps on parent (best effort) */
376
- ovl_set_timestamps (upperdir , & pstat );
377
- }
417
+ stat , link , & pstat , false);
378
418
out_unlock :
379
419
unlock_rename (workdir , upperdir );
420
+ out_done :
380
421
do_delayed_call (& done );
381
422
382
423
return err ;
0 commit comments