18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * linux/fs/9p/vfs_dentry.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This file contians vfs dentry ops for the 9P2000 protocol. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 88c2ecf20Sopenharmony_ci * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/module.h> 128c2ecf20Sopenharmony_ci#include <linux/errno.h> 138c2ecf20Sopenharmony_ci#include <linux/fs.h> 148c2ecf20Sopenharmony_ci#include <linux/file.h> 158c2ecf20Sopenharmony_ci#include <linux/pagemap.h> 168c2ecf20Sopenharmony_ci#include <linux/stat.h> 178c2ecf20Sopenharmony_ci#include <linux/string.h> 188c2ecf20Sopenharmony_ci#include <linux/inet.h> 198c2ecf20Sopenharmony_ci#include <linux/namei.h> 208c2ecf20Sopenharmony_ci#include <linux/idr.h> 218c2ecf20Sopenharmony_ci#include <linux/sched.h> 228c2ecf20Sopenharmony_ci#include <linux/slab.h> 238c2ecf20Sopenharmony_ci#include <net/9p/9p.h> 248c2ecf20Sopenharmony_ci#include <net/9p/client.h> 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#include "v9fs.h" 278c2ecf20Sopenharmony_ci#include "v9fs_vfs.h" 288c2ecf20Sopenharmony_ci#include "fid.h" 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci/** 318c2ecf20Sopenharmony_ci * v9fs_cached_dentry_delete - called when dentry refcount equals 0 328c2ecf20Sopenharmony_ci * @dentry: dentry in question 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci */ 358c2ecf20Sopenharmony_cistatic int v9fs_cached_dentry_delete(const struct dentry *dentry) 368c2ecf20Sopenharmony_ci{ 378c2ecf20Sopenharmony_ci p9_debug(P9_DEBUG_VFS, " dentry: %pd (%p)\n", 388c2ecf20Sopenharmony_ci dentry, dentry); 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci /* Don't cache negative dentries */ 418c2ecf20Sopenharmony_ci if (d_really_is_negative(dentry)) 428c2ecf20Sopenharmony_ci return 1; 438c2ecf20Sopenharmony_ci return 0; 448c2ecf20Sopenharmony_ci} 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci/** 478c2ecf20Sopenharmony_ci * v9fs_dentry_release - called when dentry is going to be freed 488c2ecf20Sopenharmony_ci * @dentry: dentry that is being release 498c2ecf20Sopenharmony_ci * 508c2ecf20Sopenharmony_ci */ 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistatic void v9fs_dentry_release(struct dentry *dentry) 538c2ecf20Sopenharmony_ci{ 548c2ecf20Sopenharmony_ci struct hlist_node *p, *n; 558c2ecf20Sopenharmony_ci p9_debug(P9_DEBUG_VFS, " dentry: %pd (%p)\n", 568c2ecf20Sopenharmony_ci dentry, dentry); 578c2ecf20Sopenharmony_ci hlist_for_each_safe(p, n, (struct hlist_head *)&dentry->d_fsdata) 588c2ecf20Sopenharmony_ci p9_client_clunk(hlist_entry(p, struct p9_fid, dlist)); 598c2ecf20Sopenharmony_ci dentry->d_fsdata = NULL; 608c2ecf20Sopenharmony_ci} 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_cistatic int v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci struct p9_fid *fid; 658c2ecf20Sopenharmony_ci struct inode *inode; 668c2ecf20Sopenharmony_ci struct v9fs_inode *v9inode; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci if (flags & LOOKUP_RCU) 698c2ecf20Sopenharmony_ci return -ECHILD; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci inode = d_inode(dentry); 728c2ecf20Sopenharmony_ci if (!inode) 738c2ecf20Sopenharmony_ci goto out_valid; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci v9inode = V9FS_I(inode); 768c2ecf20Sopenharmony_ci if (v9inode->cache_validity & V9FS_INO_INVALID_ATTR) { 778c2ecf20Sopenharmony_ci int retval; 788c2ecf20Sopenharmony_ci struct v9fs_session_info *v9ses; 798c2ecf20Sopenharmony_ci fid = v9fs_fid_lookup(dentry); 808c2ecf20Sopenharmony_ci if (IS_ERR(fid)) 818c2ecf20Sopenharmony_ci return PTR_ERR(fid); 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci v9ses = v9fs_inode2v9ses(inode); 848c2ecf20Sopenharmony_ci if (v9fs_proto_dotl(v9ses)) 858c2ecf20Sopenharmony_ci retval = v9fs_refresh_inode_dotl(fid, inode); 868c2ecf20Sopenharmony_ci else 878c2ecf20Sopenharmony_ci retval = v9fs_refresh_inode(fid, inode); 888c2ecf20Sopenharmony_ci if (retval == -ENOENT) 898c2ecf20Sopenharmony_ci return 0; 908c2ecf20Sopenharmony_ci if (retval < 0) 918c2ecf20Sopenharmony_ci return retval; 928c2ecf20Sopenharmony_ci } 938c2ecf20Sopenharmony_ciout_valid: 948c2ecf20Sopenharmony_ci return 1; 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ciconst struct dentry_operations v9fs_cached_dentry_operations = { 988c2ecf20Sopenharmony_ci .d_revalidate = v9fs_lookup_revalidate, 998c2ecf20Sopenharmony_ci .d_weak_revalidate = v9fs_lookup_revalidate, 1008c2ecf20Sopenharmony_ci .d_delete = v9fs_cached_dentry_delete, 1018c2ecf20Sopenharmony_ci .d_release = v9fs_dentry_release, 1028c2ecf20Sopenharmony_ci}; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ciconst struct dentry_operations v9fs_dentry_operations = { 1058c2ecf20Sopenharmony_ci .d_delete = always_delete_dentry, 1068c2ecf20Sopenharmony_ci .d_release = v9fs_dentry_release, 1078c2ecf20Sopenharmony_ci}; 108