#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
+#include "xfs_dir2.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
#include "xfs_export.h"
#include "xfs_inode.h"
#include "xfs_vfsops.h"
-static struct dentry dotdot = { .d_name.name = "..", .d_name.len = 2, };
-
/*
* Note that we only accept fileids which are long enough rather than allow
* the parent generation number to default to zero. XFS considers zero a
int len;
/* Directories don't need their parent encoded, they have ".." */
- if (S_ISDIR(inode->i_mode))
+ if (S_ISDIR(inode->i_mode) || !connectable)
fileid_type = FILEID_INO32_GEN;
else
fileid_type = FILEID_INO32_GEN_PARENT;
u64 ino,
u32 generation)
{
- xfs_fid_t xfid;
- bhv_vnode_t *vp;
+ xfs_mount_t *mp = XFS_M(sb);
+ xfs_inode_t *ip;
int error;
- xfid.fid_len = sizeof(xfs_fid_t) - sizeof(xfid.fid_len);
- xfid.fid_pad = 0;
- xfid.fid_ino = ino;
- xfid.fid_gen = generation;
+ /*
+ * NFS can sometimes send requests for ino 0. Fail them gracefully.
+ */
+ if (ino == 0)
+ return ERR_PTR(-ESTALE);
- error = xfs_vget(XFS_M(sb), &vp, &xfid);
+ error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, 0);
if (error)
return ERR_PTR(-error);
+ if (!ip)
+ return ERR_PTR(-EIO);
+
+ if (!ip->i_d.di_mode || ip->i_d.di_gen != generation) {
+ xfs_iput_new(ip, XFS_ILOCK_SHARED);
+ return ERR_PTR(-ENOENT);
+ }
- return vp ? vn_to_inode(vp) : NULL;
+ xfs_iunlock(ip, XFS_ILOCK_SHARED);
+ return ip->i_vnode;
}
STATIC struct dentry *
struct dentry *child)
{
int error;
- bhv_vnode_t *cvp;
+ struct xfs_inode *cip;
struct dentry *parent;
- cvp = NULL;
- error = xfs_lookup(XFS_I(child->d_inode), &dotdot, &cvp);
+ error = xfs_lookup(XFS_I(child->d_inode), &xfs_name_dotdot, &cip);
if (unlikely(error))
return ERR_PTR(-error);
- parent = d_alloc_anon(vn_to_inode(cvp));
+ parent = d_alloc_anon(cip->i_vnode);
if (unlikely(!parent)) {
- VN_RELE(cvp);
+ iput(cip->i_vnode);
return ERR_PTR(-ENOMEM);
}
return parent;