/* * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * Further, this software is distributed without any warranty that it is * free of the rightful claim of any third person regarding infringement * or the like. Any license provided herein, whether implied or * otherwise, applies only to this software file. Patent licenses, if * any, provided herein do not apply to combinations of this program with * other software, or any other product whatsoever. * * You should have received a copy of the GNU General Public License along * with this program; if not, write the Free Software Foundation, Inc., 59 * Temple Place - Suite 330, Boston MA 02111-1307, USA. * * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, * Mountain View, CA 94043, or: * * http://www.sgi.com * * For further information regarding this notice, see: * * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ */ #include "xfs.h" STATIC struct dentry * linvfs_decode_fh( struct super_block *sb, __u32 *fh, int fh_len, int fileid_type, int (*acceptable)( void *context, struct dentry *de), void *context) { __u32 parent[2]; parent[0] = parent[1] = 0; if (fh_len < 2 || fileid_type > 2) return NULL; if (fileid_type == 2 && fh_len > 2) { if (fh_len == 3) { printk(KERN_WARNING "XFS: detected filehandle without " "parent inode generation information."); return ERR_PTR(-ESTALE); } parent[0] = fh[2]; parent[1] = fh[3]; } return find_exported_dentry(sb, fh, parent, acceptable, context); } STATIC struct dentry * linvfs_get_dentry( struct super_block *sb, void *data) { vnode_t *vp; struct inode *inode; struct dentry *result; xfs_fid2_t xfid; vfs_t *vfsp = LINVFS_GET_VFS(sb); int error; xfid.fid_len = sizeof(xfs_fid2_t) - sizeof(xfid.fid_len); xfid.fid_pad = 0; xfid.fid_gen = ((__u32 *)data)[1]; xfid.fid_ino = ((__u32 *)data)[0]; VFS_VGET(vfsp, &vp, (fid_t *)&xfid, error); if (error || vp == NULL) return ERR_PTR(-ESTALE) ; inode = LINVFS_GET_IP(vp); result = d_alloc_anon(inode); if (!result) { iput(inode); return ERR_PTR(-ENOMEM); } return result; } STATIC struct dentry * linvfs_get_parent( struct dentry *child) { int error; vnode_t *vp, *cvp; struct dentry *parent; struct dentry dotdot; dotdot.d_name.name = ".."; dotdot.d_name.len = 2; dotdot.d_inode = NULL; cvp = NULL; vp = LINVFS_GET_VP(child->d_inode); VOP_LOOKUP(vp, &dotdot, &cvp, 0, NULL, NULL, error); if (unlikely(error)) return ERR_PTR(-error); parent = d_alloc_anon(LINVFS_GET_IP(cvp)); if (unlikely(!parent)) { VN_RELE(cvp); return ERR_PTR(-ENOMEM); } return parent; } struct export_operations linvfs_export_ops = { .decode_fh = linvfs_decode_fh, .get_parent = linvfs_get_parent, .get_dentry = linvfs_get_dentry, };