aboutsummaryrefslogtreecommitdiffstats
path: root/fs/overlayfs
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@redhat.com>2016-06-30 02:53:27 -0400
committerMiklos Szeredi <mszeredi@redhat.com>2016-06-30 02:53:27 -0400
commit2d902671ce1cd98cdc88d78c481889a1b2996101 (patch)
tree48c4bc8f90ee3209b7fba9b70169e8528b781eaa /fs/overlayfs
parent4c2e07c6a29e0129e975727b9f57eede813eea85 (diff)
vfs: merge .d_select_inode() into .d_real()
The two methods essentially do the same: find the real dentry/inode belonging to an overlay dentry. The difference is in the usage: vfs_open() uses ->d_select_inode() and expects the function to perform copy-up if necessary based on the open flags argument. file_dentry() uses ->d_real() passing in the overlay dentry as well as the underlying inode. vfs_rename() uses ->d_select_inode() but passes zero flags. ->d_real() with a zero inode would have worked just as well here. This patch merges the functionality of ->d_select_inode() into ->d_real() by adding an 'open_flags' argument to the latter. [Al Viro] Make the signature of d_real() match that of ->d_real() again. And constify the inode argument, while we are at it. Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
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 1dbeab6cf96e..e08cd94d7b26 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -325,36 +325,25 @@ static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type,
325 return true; 325 return true;
326} 326}
327 327
328struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags) 328int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags)
329{ 329{
330 int err; 330 int err = 0;
331 struct path realpath; 331 struct path realpath;
332 enum ovl_path_type type; 332 enum ovl_path_type type;
333 333
334 if (d_is_dir(dentry))
335 return d_backing_inode(dentry);
336
337 type = ovl_path_real(dentry, &realpath); 334 type = ovl_path_real(dentry, &realpath);
338 if (ovl_open_need_copy_up(file_flags, type, realpath.dentry)) { 335 if (ovl_open_need_copy_up(file_flags, type, realpath.dentry)) {
339 err = ovl_want_write(dentry); 336 err = ovl_want_write(dentry);
340 if (err) 337 if (!err) {
341 return ERR_PTR(err); 338 if (file_flags & O_TRUNC)
342 339 err = ovl_copy_up_truncate(dentry);
343 if (file_flags & O_TRUNC) 340 else
344 err = ovl_copy_up_truncate(dentry); 341 err = ovl_copy_up(dentry);
345 else 342 ovl_drop_write(dentry);
346 err = ovl_copy_up(dentry); 343 }
347 ovl_drop_write(dentry);
348 if (err)
349 return ERR_PTR(err);
350
351 ovl_path_upper(dentry, &realpath);
352 } 344 }
353 345
354 if (realpath.dentry->d_flags & DCACHE_OP_SELECT_INODE) 346 return err;
355 return realpath.dentry->d_op->d_select_inode(realpath.dentry, file_flags);
356
357 return d_backing_inode(realpath.dentry);
358} 347}
359 348
360static const struct inode_operations ovl_file_inode_operations = { 349static const struct inode_operations ovl_file_inode_operations = {
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 4bd9b5ba8f42..6b9fd25c5ad4 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 ce02f46029da..035c176edf00 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,