aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--fs/dcache.c3
-rw-r--r--fs/namei.c2
-rw-r--r--fs/open.c8
-rw-r--r--fs/overlayfs/inode.c31
-rw-r--r--fs/overlayfs/overlayfs.h2
-rw-r--r--fs/overlayfs/super.c20
-rw-r--r--include/linux/dcache.h28
-rw-r--r--include/linux/fs.h7
8 files changed, 39 insertions, 62 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index d6847d7b123d..5405b89fe8ec 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1729,7 +1729,6 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
1729 DCACHE_OP_REVALIDATE | 1729 DCACHE_OP_REVALIDATE |
1730 DCACHE_OP_WEAK_REVALIDATE | 1730 DCACHE_OP_WEAK_REVALIDATE |
1731 DCACHE_OP_DELETE | 1731 DCACHE_OP_DELETE |
1732 DCACHE_OP_SELECT_INODE |
1733 DCACHE_OP_REAL)); 1732 DCACHE_OP_REAL));
1734 dentry->d_op = op; 1733 dentry->d_op = op;
1735 if (!op) 1734 if (!op)
@@ -1746,8 +1745,6 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
1746 dentry->d_flags |= DCACHE_OP_DELETE; 1745 dentry->d_flags |= DCACHE_OP_DELETE;
1747 if (op->d_prune) 1746 if (op->d_prune)
1748 dentry->d_flags |= DCACHE_OP_PRUNE; 1747 dentry->d_flags |= DCACHE_OP_PRUNE;
1749 if (op->d_select_inode)
1750 dentry->d_flags |= DCACHE_OP_SELECT_INODE;
1751 if (op->d_real) 1748 if (op->d_real)
1752 dentry->d_flags |= DCACHE_OP_REAL; 1749 dentry->d_flags |= DCACHE_OP_REAL;
1753 1750
diff --git a/fs/namei.c b/fs/namei.c
index 70580ab1445c..bb7a2e0b959c 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -4328,7 +4328,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
4328 * Check source == target. 4328 * Check source == target.
4329 * On overlayfs need to look at underlying inodes. 4329 * On overlayfs need to look at underlying inodes.
4330 */ 4330 */
4331 if (vfs_select_inode(old_dentry, 0) == vfs_select_inode(new_dentry, 0)) 4331 if (d_real_inode(old_dentry) == d_real_inode(new_dentry))
4332 return 0; 4332 return 0;
4333 4333
4334 error = may_delete(old_dir, old_dentry, is_dir); 4334 error = may_delete(old_dir, old_dentry, is_dir);
diff --git a/fs/open.c b/fs/open.c
index 93ae3cdee4ab..bf66cf1a9f5c 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -840,13 +840,13 @@ EXPORT_SYMBOL(file_path);
840int vfs_open(const struct path *path, struct file *file, 840int vfs_open(const struct path *path, struct file *file,
841 const struct cred *cred) 841 const struct cred *cred)
842{ 842{
843 struct inode *inode = vfs_select_inode(path->dentry, file->f_flags); 843 struct dentry *dentry = d_real(path->dentry, NULL, file->f_flags);
844 844
845 if (IS_ERR(inode)) 845 if (IS_ERR(dentry))
846 return PTR_ERR(inode); 846 return PTR_ERR(dentry);
847 847
848 file->f_path = *path; 848 file->f_path = *path;
849 return do_dentry_open(file, inode, NULL, cred); 849 return do_dentry_open(file, d_backing_inode(dentry), NULL, cred);
850} 850}
851 851
852struct file *dentry_open(const struct path *path, int flags, 852struct file *dentry_open(const struct path *path, int flags,
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,
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index f53fa055021a..45b22de15ede 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -139,8 +139,7 @@ struct dentry_operations {
139 char *(*d_dname)(struct dentry *, char *, int); 139 char *(*d_dname)(struct dentry *, char *, int);
140 struct vfsmount *(*d_automount)(struct path *); 140 struct vfsmount *(*d_automount)(struct path *);
141 int (*d_manage)(struct dentry *, bool); 141 int (*d_manage)(struct dentry *, bool);
142 struct inode *(*d_select_inode)(struct dentry *, unsigned); 142 struct dentry *(*d_real)(struct dentry *, const struct inode *, unsigned int);
143 struct dentry *(*d_real)(struct dentry *, struct inode *);
144} ____cacheline_aligned; 143} ____cacheline_aligned;
145 144
146/* 145/*
@@ -206,10 +205,8 @@ struct dentry_operations {
206 205
207#define DCACHE_MAY_FREE 0x00800000 206#define DCACHE_MAY_FREE 0x00800000
208#define DCACHE_FALLTHRU 0x01000000 /* Fall through to lower layer */ 207#define DCACHE_FALLTHRU 0x01000000 /* Fall through to lower layer */
209#define DCACHE_OP_SELECT_INODE 0x02000000 /* Unioned entry: dcache op selects inode */ 208#define DCACHE_ENCRYPTED_WITH_KEY 0x02000000 /* dir is encrypted with a valid key */
210 209#define DCACHE_OP_REAL 0x04000000
211#define DCACHE_ENCRYPTED_WITH_KEY 0x04000000 /* dir is encrypted with a valid key */
212#define DCACHE_OP_REAL 0x08000000
213 210
214#define DCACHE_PAR_LOOKUP 0x10000000 /* being looked up (with parent locked shared) */ 211#define DCACHE_PAR_LOOKUP 0x10000000 /* being looked up (with parent locked shared) */
215#define DCACHE_DENTRY_CURSOR 0x20000000 212#define DCACHE_DENTRY_CURSOR 0x20000000
@@ -557,25 +554,16 @@ static inline struct dentry *d_backing_dentry(struct dentry *upper)
557 return upper; 554 return upper;
558} 555}
559 556
560static inline struct dentry *d_real(struct dentry *dentry) 557static inline struct dentry *d_real(struct dentry *dentry,
558 const struct inode *inode,
559 unsigned int flags)
561{ 560{
562 if (unlikely(dentry->d_flags & DCACHE_OP_REAL)) 561 if (unlikely(dentry->d_flags & DCACHE_OP_REAL))
563 return dentry->d_op->d_real(dentry, NULL); 562 return dentry->d_op->d_real(dentry, inode, flags);
564 else 563 else
565 return dentry; 564 return dentry;
566} 565}
567 566
568static inline struct inode *vfs_select_inode(struct dentry *dentry,
569 unsigned open_flags)
570{
571 struct inode *inode = d_inode(dentry);
572
573 if (inode && unlikely(dentry->d_flags & DCACHE_OP_SELECT_INODE))
574 inode = dentry->d_op->d_select_inode(dentry, open_flags);
575
576 return inode;
577}
578
579/** 567/**
580 * d_real_inode - Return the real inode 568 * d_real_inode - Return the real inode
581 * @dentry: The dentry to query 569 * @dentry: The dentry to query
@@ -585,7 +573,7 @@ static inline struct inode *vfs_select_inode(struct dentry *dentry,
585 */ 573 */
586static inline struct inode *d_real_inode(struct dentry *dentry) 574static inline struct inode *d_real_inode(struct dentry *dentry)
587{ 575{
588 return d_backing_inode(d_real(dentry)); 576 return d_backing_inode(d_real(dentry, NULL, 0));
589} 577}
590 578
591 579
diff --git a/include/linux/fs.h b/include/linux/fs.h
index dd288148a6b1..bacc0733663c 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1272,12 +1272,7 @@ static inline struct inode *file_inode(const struct file *f)
1272 1272
1273static inline struct dentry *file_dentry(const struct file *file) 1273static inline struct dentry *file_dentry(const struct file *file)
1274{ 1274{
1275 struct dentry *dentry = file->f_path.dentry; 1275 return d_real(file->f_path.dentry, file_inode(file), 0);
1276
1277 if (unlikely(dentry->d_flags & DCACHE_OP_REAL))
1278 return dentry->d_op->d_real(dentry, file_inode(file));
1279 else
1280 return dentry;
1281} 1276}
1282 1277
1283static inline int locks_lock_file_wait(struct file *filp, struct file_lock *fl) 1278static inline int locks_lock_file_wait(struct file *filp, struct file_lock *fl)