/*
* 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,
};