Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fe15ce44 authored by Nick Piggin's avatar Nick Piggin
Browse files

fs: change d_delete semantics



Change d_delete from a dentry deletion notification to a dentry caching
advise, more like ->drop_inode. Require it to be constant and idempotent,
and not take d_lock. This is how all existing filesystems use the callback
anyway.

This makes fine grained dentry locking of dput and dentry lru scanning
much simpler.

Signed-off-by: default avatarNick Piggin <npiggin@kernel.dk>
parent 5eef7fa9
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -318,3 +318,11 @@ if it's zero is not *and* *never* *had* *been* enough. Final unlink() and iput(
may happen while the inode is in the middle of ->write_inode(); e.g. if you blindly
free the on-disk inode, you may end up doing that while ->write_inode() is writing
to it.

---
[mandatory]

	.d_delete() now only advises the dcache as to whether or not to cache
unreferenced dentries, and is now only called when the dentry refcount goes to
0. Even on 0 refcount transition, it must be able to tolerate being called 0,
1, or more times (eg. constant, idempotent).
+13 −14
Original line number Diff line number Diff line
@@ -849,7 +849,7 @@ struct dentry_operations {
	int (*d_revalidate)(struct dentry *, struct nameidata *);
	int (*d_hash)(struct dentry *, struct qstr *);
	int (*d_compare)(struct dentry *, struct qstr *, struct qstr *);
	int (*d_delete)(struct dentry *);
	int (*d_delete)(const struct dentry *);
	void (*d_release)(struct dentry *);
	void (*d_iput)(struct dentry *, struct inode *);
	char *(*d_dname)(struct dentry *, char *, int);
@@ -864,9 +864,11 @@ struct dentry_operations {

  d_compare: called when a dentry should be compared with another

  d_delete: called when the last reference to a dentry is
	deleted. This means no-one is using the dentry, however it is
	still valid and in the dcache
  d_delete: called when the last reference to a dentry is dropped and the
	dcache is deciding whether or not to cache it. Return 1 to delete
	immediately, or 0 to cache the dentry. Default is NULL which means to
	always cache a reachable dentry. d_delete must be constant and
	idempotent.

  d_release: called when a dentry is really deallocated

@@ -910,14 +912,11 @@ manipulate dentries:
	the usage count)

  dput: close a handle for a dentry (decrements the usage count). If
	the usage count drops to 0, the "d_delete" method is called
	and the dentry is placed on the unused list if the dentry is
	still in its parents hash list. Putting the dentry on the
	unused list just means that if the system needs some RAM, it
	goes through the unused list of dentries and deallocates them.
	If the dentry has already been unhashed and the usage count
	drops to 0, in this case the dentry is deallocated after the
	"d_delete" method is called
	the usage count drops to 0, and the dentry is still in its
	parent's hash, the "d_delete" method is called to check whether
	it should be cached. If it should not be cached, or if the dentry
	is not hashed, it is deleted. Otherwise cached dentries are put
	into an LRU list to be reclaimed on memory shortage.

  d_drop: this unhashes a dentry from its parents hash list. A
	subsequent call to dput() will deallocate the dentry if its
+1 −1
Original line number Diff line number Diff line
@@ -2185,7 +2185,7 @@ static const struct file_operations pfm_file_ops = {
};

static int
pfmfs_delete_dentry(struct dentry *dentry)
pfmfs_delete_dentry(const struct dentry *dentry)
{
	return 1;
}
+2 −2
Original line number Diff line number Diff line
@@ -276,7 +276,7 @@ smb_dir_open(struct inode *dir, struct file *file)
static int smb_lookup_validate(struct dentry *, struct nameidata *);
static int smb_hash_dentry(struct dentry *, struct qstr *);
static int smb_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
static int smb_delete_dentry(struct dentry *);
static int smb_delete_dentry(const struct dentry *);

static const struct dentry_operations smbfs_dentry_operations =
{
@@ -367,7 +367,7 @@ smb_compare_dentry(struct dentry *dir, struct qstr *a, struct qstr *b)
 * We use this to unhash dentries with bad inodes.
 */
static int
smb_delete_dentry(struct dentry * dentry)
smb_delete_dentry(const struct dentry *dentry)
{
	if (dentry->d_inode) {
		if (is_bad_inode(dentry->d_inode)) {
+2 −2
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@
 *
 */

static int v9fs_dentry_delete(struct dentry *dentry)
static int v9fs_dentry_delete(const struct dentry *dentry)
{
	P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_name.name,
									dentry);
@@ -68,7 +68,7 @@ static int v9fs_dentry_delete(struct dentry *dentry)
 *
 */

static int v9fs_cached_dentry_delete(struct dentry *dentry)
static int v9fs_cached_dentry_delete(const struct dentry *dentry)
{
	struct inode *inode = dentry->d_inode;
	P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_name.name,
Loading