diff options
author | Miklos Szeredi <mszeredi@redhat.com> | 2016-06-30 02:53:27 -0400 |
---|---|---|
committer | Miklos Szeredi <mszeredi@redhat.com> | 2016-06-30 02:53:27 -0400 |
commit | 2d902671ce1cd98cdc88d78c481889a1b2996101 (patch) | |
tree | 48c4bc8f90ee3209b7fba9b70169e8528b781eaa /fs/overlayfs | |
parent | 4c2e07c6a29e0129e975727b9f57eede813eea85 (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.c | 31 | ||||
-rw-r--r-- | fs/overlayfs/overlayfs.h | 2 | ||||
-rw-r--r-- | fs/overlayfs/super.c | 20 |
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 | ||
328 | struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags) | 328 | int 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 | ||
360 | static const struct inode_operations ovl_file_inode_operations = { | 349 | static 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); |
180 | ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size); | 180 | ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size); |
181 | int ovl_removexattr(struct dentry *dentry, const char *name); | 181 | int ovl_removexattr(struct dentry *dentry, const char *name); |
182 | struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags); | 182 | int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags); |
183 | 183 | ||
184 | struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, | 184 | struct 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 | ||
307 | static struct dentry *ovl_d_real(struct dentry *dentry, struct inode *inode) | 307 | static 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 | |||
332 | bug: | 342 | bug: |
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 | ||
379 | static const struct dentry_operations ovl_dentry_operations = { | 389 | static 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 | ||
385 | static const struct dentry_operations ovl_reval_dentry_operations = { | 394 | static 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, |