aboutsummaryrefslogtreecommitdiffstats
path: root/fs/overlayfs
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@redhat.com>2016-07-27 05:36:03 -0400
committerMiklos Szeredi <mszeredi@redhat.com>2016-07-27 05:36:03 -0400
commit1b91dbdd2938a0102fea2d8853073159f2b08deb (patch)
tree6c1c54e4b15a1efbcd15a4d68d6366c71abf9979 /fs/overlayfs
parent523d939ef98fd712632d93a5a2b588e477a7565e (diff)
parent0cac643c102c0632dc2cc81e2490b0fec1cac0af (diff)
Merge branch 'd_real' into overlayfs-next
Diffstat (limited to 'fs/overlayfs')
-rw-r--r--fs/overlayfs/inode.c31
-rw-r--r--fs/overlayfs/overlayfs.h2
-rw-r--r--fs/overlayfs/super.c20
3 files changed, 25 insertions, 28 deletions
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index d1cdc60dd68f..d554e86abbe3 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -351,36 +351,25 @@ static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type,
351 return true; 351 return true;
352} 352}
353 353
354struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags) 354int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags)
355{ 355{
356 int err; 356 int err = 0;
357 struct path realpath; 357 struct path realpath;
358 enum ovl_path_type type; 358 enum ovl_path_type type;
359 359
360 if (d_is_dir(dentry))
361 return d_backing_inode(dentry);
362
363 type = ovl_path_real(dentry, &realpath); 360 type = ovl_path_real(dentry, &realpath);
364 if (ovl_open_need_copy_up(file_flags, type, realpath.dentry)) { 361 if (ovl_open_need_copy_up(file_flags, type, realpath.dentry)) {
365 err = ovl_want_write(dentry); 362 err = ovl_want_write(dentry);
366 if (err) 363 if (!err) {
367 return ERR_PTR(err); 364 if (file_flags & O_TRUNC)
368 365 err = ovl_copy_up_truncate(dentry);
369 if (file_flags & O_TRUNC) 366 else
370 err = ovl_copy_up_truncate(dentry); 367 err = ovl_copy_up(dentry);
371 else 368 ovl_drop_write(dentry);
372 err = ovl_copy_up(dentry); 369 }
373 ovl_drop_write(dentry);
374 if (err)
375 return ERR_PTR(err);
376
377 ovl_path_upper(dentry, &realpath);
378 } 370 }
379 371
380 if (realpath.dentry->d_flags & DCACHE_OP_SELECT_INODE) 372 return err;
381 return realpath.dentry->d_op->d_select_inode(realpath.dentry, file_flags);
382
383 return d_backing_inode(realpath.dentry);
384} 373}
385 374
386static const struct inode_operations ovl_file_inode_operations = { 375static const struct inode_operations ovl_file_inode_operations = {
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index cfbca53590d0..0d3f2ad45708 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -179,7 +179,7 @@ ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode,
179 const char *name, void *value, size_t size); 179 const char *name, void *value, size_t size);
180ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size); 180ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size);
181int ovl_removexattr(struct dentry *dentry, const char *name); 181int ovl_removexattr(struct dentry *dentry, const char *name);
182struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags); 182int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags);
183 183
184struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, 184struct inode *ovl_new_inode(struct super_block *sb, umode_t mode,
185 struct ovl_entry *oe); 185 struct ovl_entry *oe);
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 9a7693d5f8ff..5e254b3a8c56 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -304,7 +304,9 @@ static void ovl_dentry_release(struct dentry *dentry)
304 } 304 }
305} 305}
306 306
307static struct dentry *ovl_d_real(struct dentry *dentry, struct inode *inode) 307static struct dentry *ovl_d_real(struct dentry *dentry,
308 const struct inode *inode,
309 unsigned int open_flags)
308{ 310{
309 struct dentry *real; 311 struct dentry *real;
310 312
@@ -314,6 +316,16 @@ static struct dentry *ovl_d_real(struct dentry *dentry, struct inode *inode)
314 goto bug; 316 goto bug;
315 } 317 }
316 318
319 if (d_is_negative(dentry))
320 return dentry;
321
322 if (open_flags) {
323 int err = ovl_open_maybe_copy_up(dentry, open_flags);
324
325 if (err)
326 return ERR_PTR(err);
327 }
328
317 real = ovl_dentry_upper(dentry); 329 real = ovl_dentry_upper(dentry);
318 if (real && (!inode || inode == d_inode(real))) 330 if (real && (!inode || inode == d_inode(real)))
319 return real; 331 return real;
@@ -326,9 +338,7 @@ static struct dentry *ovl_d_real(struct dentry *dentry, struct inode *inode)
326 return real; 338 return real;
327 339
328 /* Handle recursion */ 340 /* Handle recursion */
329 if (real->d_flags & DCACHE_OP_REAL) 341 return d_real(real, inode, open_flags);
330 return real->d_op->d_real(real, inode);
331
332bug: 342bug:
333 WARN(1, "ovl_d_real(%pd4, %s:%lu\n): real dentry not found\n", dentry, 343 WARN(1, "ovl_d_real(%pd4, %s:%lu\n): real dentry not found\n", dentry,
334 inode ? inode->i_sb->s_id : "NULL", inode ? inode->i_ino : 0); 344 inode ? inode->i_sb->s_id : "NULL", inode ? inode->i_ino : 0);
@@ -378,13 +388,11 @@ static int ovl_dentry_weak_revalidate(struct dentry *dentry, unsigned int flags)
378 388
379static const struct dentry_operations ovl_dentry_operations = { 389static const struct dentry_operations ovl_dentry_operations = {
380 .d_release = ovl_dentry_release, 390 .d_release = ovl_dentry_release,
381 .d_select_inode = ovl_d_select_inode,
382 .d_real = ovl_d_real, 391 .d_real = ovl_d_real,
383}; 392};
384 393
385static const struct dentry_operations ovl_reval_dentry_operations = { 394static const struct dentry_operations ovl_reval_dentry_operations = {
386 .d_release = ovl_dentry_release, 395 .d_release = ovl_dentry_release,
387 .d_select_inode = ovl_d_select_inode,
388 .d_real = ovl_d_real, 396 .d_real = ovl_d_real,
389 .d_revalidate = ovl_dentry_revalidate, 397 .d_revalidate = ovl_dentry_revalidate,
390 .d_weak_revalidate = ovl_dentry_weak_revalidate, 398 .d_weak_revalidate = ovl_dentry_weak_revalidate,