Thomas Gleixner | 7336d0e | 2019-05-31 01:09:56 -0700 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0-only |
David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 2 | /* |
| 3 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
Steven Whitehouse | 3a8a9a1 | 2006-05-18 15:09:15 -0400 | [diff] [blame] | 4 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. |
David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 5 | */ |
| 6 | |
David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 7 | #include <linux/spinlock.h> |
| 8 | #include <linux/completion.h> |
| 9 | #include <linux/buffer_head.h> |
Steven Whitehouse | 5c676f6 | 2006-02-27 17:23:27 -0500 | [diff] [blame] | 10 | #include <linux/gfs2_ondisk.h> |
Nick Piggin | 34286d6 | 2011-01-07 17:49:57 +1100 | [diff] [blame] | 11 | #include <linux/namei.h> |
Steven Whitehouse | 71b86f5 | 2006-03-28 14:14:04 -0500 | [diff] [blame] | 12 | #include <linux/crc32.h> |
David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 13 | |
| 14 | #include "gfs2.h" |
Steven Whitehouse | 5c676f6 | 2006-02-27 17:23:27 -0500 | [diff] [blame] | 15 | #include "incore.h" |
David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 16 | #include "dir.h" |
| 17 | #include "glock.h" |
Steven Whitehouse | b276058 | 2008-10-14 16:05:55 +0100 | [diff] [blame] | 18 | #include "super.h" |
Steven Whitehouse | 5c676f6 | 2006-02-27 17:23:27 -0500 | [diff] [blame] | 19 | #include "util.h" |
Steven Whitehouse | dbb7cae | 2007-05-15 15:37:50 +0100 | [diff] [blame] | 20 | #include "inode.h" |
David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 21 | |
| 22 | /** |
| 23 | * gfs2_drevalidate - Check directory lookup consistency |
| 24 | * @dentry: the mapping to check |
Al Viro | 0b728e1 | 2012-06-10 16:03:43 -0400 | [diff] [blame] | 25 | * @flags: lookup flags |
David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 26 | * |
| 27 | * Check to make sure the lookup necessary to arrive at this inode from its |
| 28 | * parent is still good. |
| 29 | * |
| 30 | * Returns: 1 if the dentry is ok, 0 if it isn't |
| 31 | */ |
| 32 | |
Al Viro | 0b728e1 | 2012-06-10 16:03:43 -0400 | [diff] [blame] | 33 | static int gfs2_drevalidate(struct dentry *dentry, unsigned int flags) |
David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 34 | { |
Nick Piggin | 34286d6 | 2011-01-07 17:49:57 +1100 | [diff] [blame] | 35 | struct dentry *parent; |
| 36 | struct gfs2_sbd *sdp; |
| 37 | struct gfs2_inode *dip; |
| 38 | struct inode *inode; |
David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 39 | struct gfs2_holder d_gh; |
Steven Whitehouse | dbb7cae | 2007-05-15 15:37:50 +0100 | [diff] [blame] | 40 | struct gfs2_inode *ip = NULL; |
Bob Peterson | 8c5ca11 | 2019-08-06 13:52:21 -0400 | [diff] [blame] | 41 | int error, valid = 0; |
Steven Whitehouse | 7afd88d | 2008-02-22 16:07:18 +0000 | [diff] [blame] | 42 | int had_lock = 0; |
David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 43 | |
Al Viro | 0b728e1 | 2012-06-10 16:03:43 -0400 | [diff] [blame] | 44 | if (flags & LOOKUP_RCU) |
Nick Piggin | 34286d6 | 2011-01-07 17:49:57 +1100 | [diff] [blame] | 45 | return -ECHILD; |
| 46 | |
| 47 | parent = dget_parent(dentry); |
David Howells | 2b0143b | 2015-03-17 22:25:59 +0000 | [diff] [blame] | 48 | sdp = GFS2_SB(d_inode(parent)); |
| 49 | dip = GFS2_I(d_inode(parent)); |
| 50 | inode = d_inode(dentry); |
Nick Piggin | 34286d6 | 2011-01-07 17:49:57 +1100 | [diff] [blame] | 51 | |
Steven Whitehouse | dbb7cae | 2007-05-15 15:37:50 +0100 | [diff] [blame] | 52 | if (inode) { |
| 53 | if (is_bad_inode(inode)) |
Bob Peterson | 8c5ca11 | 2019-08-06 13:52:21 -0400 | [diff] [blame] | 54 | goto out; |
Steven Whitehouse | dbb7cae | 2007-05-15 15:37:50 +0100 | [diff] [blame] | 55 | ip = GFS2_I(inode); |
| 56 | } |
David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 57 | |
Bob Peterson | 8c5ca11 | 2019-08-06 13:52:21 -0400 | [diff] [blame] | 58 | if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL) { |
| 59 | valid = 1; |
| 60 | goto out; |
| 61 | } |
Steven Whitehouse | c752666 | 2006-03-20 12:30:04 -0500 | [diff] [blame] | 62 | |
Steven Whitehouse | 7afd88d | 2008-02-22 16:07:18 +0000 | [diff] [blame] | 63 | had_lock = (gfs2_glock_is_locked_by_me(dip->i_gl) != NULL); |
Wendy Cheng | 549ae0a | 2007-02-06 03:52:16 -0500 | [diff] [blame] | 64 | if (!had_lock) { |
| 65 | error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); |
| 66 | if (error) |
Bob Peterson | 8c5ca11 | 2019-08-06 13:52:21 -0400 | [diff] [blame] | 67 | goto out; |
David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 68 | } |
| 69 | |
Bob Peterson | 8c5ca11 | 2019-08-06 13:52:21 -0400 | [diff] [blame] | 70 | error = gfs2_dir_check(d_inode(parent), &dentry->d_name, ip); |
| 71 | valid = inode ? !error : (error == -ENOENT); |
| 72 | |
Wendy Cheng | 549ae0a | 2007-02-06 03:52:16 -0500 | [diff] [blame] | 73 | if (!had_lock) |
| 74 | gfs2_glock_dq_uninit(&d_gh); |
Bob Peterson | 8c5ca11 | 2019-08-06 13:52:21 -0400 | [diff] [blame] | 75 | out: |
David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 76 | dput(parent); |
Bob Peterson | 8c5ca11 | 2019-08-06 13:52:21 -0400 | [diff] [blame] | 77 | return valid; |
David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 78 | } |
| 79 | |
Linus Torvalds | da53be1 | 2013-05-21 15:22:44 -0700 | [diff] [blame] | 80 | static int gfs2_dhash(const struct dentry *dentry, struct qstr *str) |
Steven Whitehouse | c752666 | 2006-03-20 12:30:04 -0500 | [diff] [blame] | 81 | { |
| 82 | str->hash = gfs2_disk_hash(str->name, str->len); |
| 83 | return 0; |
| 84 | } |
| 85 | |
Nick Piggin | fe15ce4 | 2011-01-07 17:49:23 +1100 | [diff] [blame] | 86 | static int gfs2_dentry_delete(const struct dentry *dentry) |
Wengang Wang | 970343c | 2009-08-18 14:25:03 +0800 | [diff] [blame] | 87 | { |
| 88 | struct gfs2_inode *ginode; |
| 89 | |
David Howells | 2b0143b | 2015-03-17 22:25:59 +0000 | [diff] [blame] | 90 | if (d_really_is_negative(dentry)) |
Wengang Wang | 970343c | 2009-08-18 14:25:03 +0800 | [diff] [blame] | 91 | return 0; |
| 92 | |
David Howells | 2b0143b | 2015-03-17 22:25:59 +0000 | [diff] [blame] | 93 | ginode = GFS2_I(d_inode(dentry)); |
Andreas Gruenbacher | 6df9f9a | 2016-06-17 07:31:27 -0500 | [diff] [blame] | 94 | if (!gfs2_holder_initialized(&ginode->i_iopen_gh)) |
Wengang Wang | 970343c | 2009-08-18 14:25:03 +0800 | [diff] [blame] | 95 | return 0; |
| 96 | |
| 97 | if (test_bit(GLF_DEMOTE, &ginode->i_iopen_gh.gh_gl->gl_flags)) |
| 98 | return 1; |
| 99 | |
| 100 | return 0; |
| 101 | } |
| 102 | |
Al Viro | 92cecbb | 2009-02-20 06:00:05 +0000 | [diff] [blame] | 103 | const struct dentry_operations gfs2_dops = { |
David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 104 | .d_revalidate = gfs2_drevalidate, |
Steven Whitehouse | c752666 | 2006-03-20 12:30:04 -0500 | [diff] [blame] | 105 | .d_hash = gfs2_dhash, |
Wengang Wang | 970343c | 2009-08-18 14:25:03 +0800 | [diff] [blame] | 106 | .d_delete = gfs2_dentry_delete, |
David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 107 | }; |
| 108 | |