162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * This file contians vfs dentry ops for the 9P2000 protocol. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 662306a36Sopenharmony_ci * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/module.h> 1062306a36Sopenharmony_ci#include <linux/errno.h> 1162306a36Sopenharmony_ci#include <linux/fs.h> 1262306a36Sopenharmony_ci#include <linux/file.h> 1362306a36Sopenharmony_ci#include <linux/pagemap.h> 1462306a36Sopenharmony_ci#include <linux/stat.h> 1562306a36Sopenharmony_ci#include <linux/string.h> 1662306a36Sopenharmony_ci#include <linux/namei.h> 1762306a36Sopenharmony_ci#include <linux/sched.h> 1862306a36Sopenharmony_ci#include <linux/slab.h> 1962306a36Sopenharmony_ci#include <net/9p/9p.h> 2062306a36Sopenharmony_ci#include <net/9p/client.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include "v9fs.h" 2362306a36Sopenharmony_ci#include "v9fs_vfs.h" 2462306a36Sopenharmony_ci#include "fid.h" 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci/** 2762306a36Sopenharmony_ci * v9fs_cached_dentry_delete - called when dentry refcount equals 0 2862306a36Sopenharmony_ci * @dentry: dentry in question 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci */ 3162306a36Sopenharmony_cistatic int v9fs_cached_dentry_delete(const struct dentry *dentry) 3262306a36Sopenharmony_ci{ 3362306a36Sopenharmony_ci p9_debug(P9_DEBUG_VFS, " dentry: %pd (%p)\n", 3462306a36Sopenharmony_ci dentry, dentry); 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci /* Don't cache negative dentries */ 3762306a36Sopenharmony_ci if (d_really_is_negative(dentry)) 3862306a36Sopenharmony_ci return 1; 3962306a36Sopenharmony_ci return 0; 4062306a36Sopenharmony_ci} 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/** 4362306a36Sopenharmony_ci * v9fs_dentry_release - called when dentry is going to be freed 4462306a36Sopenharmony_ci * @dentry: dentry that is being release 4562306a36Sopenharmony_ci * 4662306a36Sopenharmony_ci */ 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistatic void v9fs_dentry_release(struct dentry *dentry) 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci struct hlist_node *p, *n; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci p9_debug(P9_DEBUG_VFS, " dentry: %pd (%p)\n", 5362306a36Sopenharmony_ci dentry, dentry); 5462306a36Sopenharmony_ci hlist_for_each_safe(p, n, (struct hlist_head *)&dentry->d_fsdata) 5562306a36Sopenharmony_ci p9_fid_put(hlist_entry(p, struct p9_fid, dlist)); 5662306a36Sopenharmony_ci dentry->d_fsdata = NULL; 5762306a36Sopenharmony_ci} 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cistatic int v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci struct p9_fid *fid; 6262306a36Sopenharmony_ci struct inode *inode; 6362306a36Sopenharmony_ci struct v9fs_inode *v9inode; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci if (flags & LOOKUP_RCU) 6662306a36Sopenharmony_ci return -ECHILD; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci inode = d_inode(dentry); 6962306a36Sopenharmony_ci if (!inode) 7062306a36Sopenharmony_ci goto out_valid; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci v9inode = V9FS_I(inode); 7362306a36Sopenharmony_ci if (v9inode->cache_validity & V9FS_INO_INVALID_ATTR) { 7462306a36Sopenharmony_ci int retval; 7562306a36Sopenharmony_ci struct v9fs_session_info *v9ses; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci fid = v9fs_fid_lookup(dentry); 7862306a36Sopenharmony_ci if (IS_ERR(fid)) 7962306a36Sopenharmony_ci return PTR_ERR(fid); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci v9ses = v9fs_inode2v9ses(inode); 8262306a36Sopenharmony_ci if (v9fs_proto_dotl(v9ses)) 8362306a36Sopenharmony_ci retval = v9fs_refresh_inode_dotl(fid, inode); 8462306a36Sopenharmony_ci else 8562306a36Sopenharmony_ci retval = v9fs_refresh_inode(fid, inode); 8662306a36Sopenharmony_ci p9_fid_put(fid); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci if (retval == -ENOENT) 8962306a36Sopenharmony_ci return 0; 9062306a36Sopenharmony_ci if (retval < 0) 9162306a36Sopenharmony_ci return retval; 9262306a36Sopenharmony_ci } 9362306a36Sopenharmony_ciout_valid: 9462306a36Sopenharmony_ci return 1; 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ciconst struct dentry_operations v9fs_cached_dentry_operations = { 9862306a36Sopenharmony_ci .d_revalidate = v9fs_lookup_revalidate, 9962306a36Sopenharmony_ci .d_weak_revalidate = v9fs_lookup_revalidate, 10062306a36Sopenharmony_ci .d_delete = v9fs_cached_dentry_delete, 10162306a36Sopenharmony_ci .d_release = v9fs_dentry_release, 10262306a36Sopenharmony_ci}; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ciconst struct dentry_operations v9fs_dentry_operations = { 10562306a36Sopenharmony_ci .d_delete = always_delete_dentry, 10662306a36Sopenharmony_ci .d_release = v9fs_dentry_release, 10762306a36Sopenharmony_ci}; 108