示例#1
0
/* 
** looks up the dentry of the parent directory for child.
** taken from ext2_get_parent
*/
struct dentry *reiserfs_get_parent(struct dentry *child)
{
    int retval;
    struct inode * inode = NULL;
    struct reiserfs_dir_entry de;
    INITIALIZE_PATH (path_to_entry);
    struct dentry *parent;
    struct inode *dir = child->d_inode ;


    if (dir->i_nlink == 0) {
	return ERR_PTR(-ENOENT);
    }
    de.de_gen_number_bit_string = NULL;

    reiserfs_write_lock(dir->i_sb);
    retval = reiserfs_find_entry (dir, "..", 2, &path_to_entry, &de);
    pathrelse (&path_to_entry);
    if (retval != NAME_FOUND) {
	reiserfs_write_unlock(dir->i_sb);
	return ERR_PTR(-ENOENT);
    }
    inode = reiserfs_iget (dir->i_sb, (struct cpu_key *)&(de.de_dir_id));
    reiserfs_write_unlock(dir->i_sb);

    if (!inode || IS_ERR(inode)) {
	return ERR_PTR(-EACCES);
    }
    parent = d_alloc_anon(inode);
    if (!parent) {
	iput(inode);
	parent = ERR_PTR(-ENOMEM);
    }
    return parent;
}
示例#2
0
static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj)
{
	struct gfs2_sbd *sdp = sb->s_fs_info;
	struct gfs2_inum_host *inum = inum_obj;
	struct inode *inode;
	struct dentry *dentry;

	inode = gfs2_ilookup(sb, inum->no_addr);
	if (inode) {
		if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) {
			iput(inode);
			return ERR_PTR(-ESTALE);
		}
	} else {
		inode = gfs2_lookup_by_inum(sdp, inum->no_addr,
					    &inum->no_formal_ino,
					    GFS2_BLKST_DINODE);
		if (inode == ERR_PTR(-ENOENT))
			inode = gfs2_ilookup(sb, inum->no_addr);
	}

	if (IS_ERR(inode))
		return ERR_CAST(inode);

	dentry = d_alloc_anon(inode);
	if (!dentry) {
		iput(inode);
		return ERR_PTR(-ENOMEM);
	}

	dentry->d_op = &gfs2_dops;
	return dentry;
}
示例#3
0
struct dentry *jfs_get_parent(struct dentry *dentry)
{
	struct super_block *sb = dentry->d_inode->i_sb;
	struct dentry *parent = ERR_PTR(-ENOENT);
	struct inode *inode;
	unsigned long parent_ino;

	parent_ino =
		le32_to_cpu(JFS_IP(dentry->d_inode)->i_dtroot.header.idotdot);
	inode = iget(sb, parent_ino);
	if (inode) {
		if (is_bad_inode(inode)) {
			iput(inode);
			parent = ERR_PTR(-EACCES);
		} else {
			parent = d_alloc_anon(inode);
			if (!parent) {
				parent = ERR_PTR(-ENOMEM);
				iput(inode);
			}
		}
	}

	return parent;
}
示例#4
0
STATIC struct dentry *
xfs_fs_fh_to_parent(struct super_block *sb, struct fid *fid,
		 int fh_len, int fileid_type)
{
	struct xfs_fid64	*fid64 = (struct xfs_fid64 *)fid;
	struct inode		*inode = NULL;
	struct dentry		*result;

	switch (fileid_type) {
	case FILEID_INO32_GEN_PARENT:
		inode = xfs_nfs_get_inode(sb, fid->i32.parent_ino,
					      fid->i32.parent_gen);
		break;
	case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG:
		inode = xfs_nfs_get_inode(sb, fid64->parent_ino,
					      fid64->parent_gen);
		break;
	}

	if (!inode)
		return NULL;
	if (IS_ERR(inode))
		return ERR_PTR(PTR_ERR(inode));
	result = d_alloc_anon(inode);
	if (!result) {
		iput(inode);
		return ERR_PTR(-ENOMEM);
	}
	return result;
}
示例#5
0
文件: export.c 项目: 274914765/C
static struct dentry *ocfs2_get_dentry(struct super_block *sb,
        struct ocfs2_inode_handle *handle)
{
    struct inode *inode;
    struct dentry *result;

    mlog_entry("(0x%p, 0x%p)\n", sb, handle);

    if (handle->ih_blkno == 0) {
        mlog_errno(-ESTALE);
        return ERR_PTR(-ESTALE);
    }

    inode = ocfs2_iget(OCFS2_SB(sb), handle->ih_blkno, 0, 0);

    if (IS_ERR(inode))
        return (void *)inode;

    if (handle->ih_generation != inode->i_generation) {
        iput(inode);
        return ERR_PTR(-ESTALE);
    }

    result = d_alloc_anon(inode);

    if (!result) {
        iput(inode);
        mlog_errno(-ENOMEM);
        return ERR_PTR(-ENOMEM);
    }
    result->d_op = &ocfs2_dentry_ops;

    mlog_exit_ptr(result);
    return result;
}
示例#6
0
struct dentry *efs_get_parent(struct dentry *child)
{
    struct dentry *parent;
    struct inode *inode;
    efs_ino_t ino;
    int error;

    lock_kernel();

    error = -ENOENT;
    ino = efs_find_entry(child->d_inode, "..", 2);
    if (!ino)
        goto fail;

    error = -EACCES;
    inode = iget(child->d_inode->i_sb, ino);
    if (!inode)
        goto fail;

    error = -ENOMEM;
    parent = d_alloc_anon(inode);
    if (!parent)
        goto fail_iput;

    unlock_kernel();
    return parent;

fail_iput:
    iput(inode);
fail:
    unlock_kernel();
    return ERR_PTR(error);
}
示例#7
0
static struct dentry *
isofs_export_iget(struct super_block *sb,
		  unsigned long block,
		  unsigned long offset,
		  __u32 generation)
{
	struct inode *inode;
	struct dentry *result;
	if (block == 0)
		return ERR_PTR(-ESTALE);
	inode = isofs_iget(sb, block, offset);
	if (inode == NULL)
		return ERR_PTR(-ENOMEM);
	if (is_bad_inode(inode)
	    || (generation && inode->i_generation != generation))
	{
		iput(inode);
		return ERR_PTR(-ESTALE);
	}
	result = d_alloc_anon(inode);
	if (!result) {
		iput(inode);
		return ERR_PTR(-ENOMEM);
	}
	return result;
}
示例#8
0
static struct dentry *fuse_get_dentry(struct super_block *sb, void *vobjp)
{
	__u32 *objp = vobjp;
	unsigned long nodeid = objp[0];
	__u32 generation = objp[1];
	struct inode *inode;
	struct dentry *entry;

	if (nodeid == 0)
		return ERR_PTR(-ESTALE);

	inode = ilookup5(sb, nodeid, fuse_inode_eq, &nodeid);
	if (!inode)
		return ERR_PTR(-ESTALE);
	if (inode->i_generation != generation) {
		iput(inode);
		return ERR_PTR(-ESTALE);
	}

	entry = d_alloc_anon(inode);
	if (!entry) {
		iput(inode);
		return ERR_PTR(-ENOMEM);
	}

	return entry;
}
示例#9
0
/**
 * ntfs_get_dentry - find a dentry for the inode from a file handle sub-fragment
 * @sb:		super block identifying the mounted ntfs volume
 * @fh:		the file handle sub-fragment
 *
 * Find a dentry for the inode given a file handle sub-fragment.  This function
 * is called from fs/exportfs/expfs.c::find_exported_dentry() which in turn is
 * called from the default ->decode_fh() which is export_decode_fh() in the
 * same file.  The code is closely based on the default ->get_dentry() helper
 * fs/exportfs/expfs.c::get_object().
 *
 * The @fh contains two 32-bit unsigned values, the first one is the inode
 * number and the second one is the inode generation.
 *
 * Return the dentry on success or the error code on error (IS_ERR() is true).
 */
static struct dentry *ntfs_get_dentry(struct super_block *sb, void *fh)
{
	struct inode *vi;
	struct dentry *dent;
	unsigned long ino = ((u32 *)fh)[0];
	u32 gen = ((u32 *)fh)[1];

	ntfs_debug("Entering for inode 0x%lx, generation 0x%x.", ino, gen);
	vi = ntfs_iget(sb, ino);
	if (IS_ERR(vi)) {
		ntfs_error(sb, "Failed to get inode 0x%lx.", ino);
		return (struct dentry *)vi;
	}
	if (unlikely(is_bad_inode(vi) || vi->i_generation != gen)) {
		/* We didn't find the right inode. */
		ntfs_error(sb, "Inode 0x%lx, bad count: %d %d or version 0x%x "
				"0x%x.", vi->i_ino, vi->i_nlink,
				atomic_read(&vi->i_count), vi->i_generation,
				gen);
		iput(vi);
		return ERR_PTR(-ESTALE);
	}
	/* Now find a dentry.  If possible, get a well-connected one. */
	dent = d_alloc_anon(vi);
	if (unlikely(!dent)) {
		iput(vi);
		return ERR_PTR(-ENOMEM);
	}
	ntfs_debug("Done for inode 0x%lx, generation 0x%x.", ino, gen);
	return dent;
}
示例#10
0
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;
}
示例#11
0
STATIC struct dentry *
linvfs_get_parent(
	struct dentry		*child)
{
	int			error;
	vnode_t			*vp, *cvp;
	struct dentry		*parent;
	struct inode		*ip = NULL;
	struct dentry		dotdot;

	dotdot.d_name.name = "..";
	dotdot.d_name.len = 2;
	dotdot.d_inode = 0;

	cvp = NULL;
	vp = LINVFS_GET_VP(child->d_inode);
	VOP_LOOKUP(vp, &dotdot, &cvp, 0, NULL, NULL, error);

	if (!error) {
		ASSERT(cvp);
		ip = LINVFS_GET_IP(cvp);
		if (!ip) {
			VN_RELE(cvp);
			return ERR_PTR(-EACCES);
		}
	}
	if (error)
		return ERR_PTR(-error);
	parent = d_alloc_anon(ip);
	if (!parent) {
		VN_RELE(cvp);
		parent = ERR_PTR(-ENOMEM);
	}
	return parent;
}
示例#12
0
static struct dentry *gfs2_get_parent(struct dentry *child)
{
	struct qstr dotdot;
	struct inode *inode;
	struct dentry *dentry;

	gfs2_str2qstr(&dotdot, "..");
	inode = gfs2_lookupi(child->d_inode, &dotdot, 1, NULL);

	if (!inode)
		return ERR_PTR(-ENOENT);
	/*
	 * In case of an error, @inode carries the error value, and we
	 * have to return that as a(n invalid) pointer to dentry.
	 */
	if (IS_ERR(inode))
		return ERR_PTR(PTR_ERR(inode));

	dentry = d_alloc_anon(inode);
	if (!dentry) {
		iput(inode);
		return ERR_PTR(-ENOMEM);
	}

	dentry->d_op = &gfs2_dops;
	return dentry;
}
示例#13
0
static struct dentry *ocfs2_get_parent(struct dentry *child)
{
	int status;
	u64 blkno;
	struct dentry *parent;
	struct inode *inode;
	struct inode *dir = child->d_inode;
	struct buffer_head *dirent_bh = NULL;
	struct ocfs2_dir_entry *dirent;

	mlog_entry("(0x%p, '%.*s')\n", child,
		   child->d_name.len, child->d_name.name);

	mlog(0, "find parent of directory %llu\n",
	     (unsigned long long)OCFS2_I(dir)->ip_blkno);

	status = ocfs2_meta_lock(dir, NULL, 0);
	if (status < 0) {
		if (status != -ENOENT)
			mlog_errno(status);
		parent = ERR_PTR(status);
		goto bail;
	}

	status = ocfs2_find_files_on_disk("..", 2, &blkno, dir, &dirent_bh,
					  &dirent);
	if (status < 0) {
		parent = ERR_PTR(-ENOENT);
		goto bail_unlock;
	}

	inode = ocfs2_iget(OCFS2_SB(dir->i_sb), blkno, 0);
	if (IS_ERR(inode)) {
		mlog(ML_ERROR, "Unable to create inode %llu\n",
		     (unsigned long long)blkno);
		parent = ERR_PTR(-EACCES);
		goto bail_unlock;
	}

	parent = d_alloc_anon(inode);
	if (!parent) {
		iput(inode);
		parent = ERR_PTR(-ENOMEM);
	}

	parent->d_op = &ocfs2_dentry_ops;

bail_unlock:
	ocfs2_meta_unlock(dir, 0);

	if (dirent_bh)
		brelse(dirent_bh);

bail:
	mlog_exit_ptr(parent);

	return parent;
}
示例#14
0
文件: zpl_export.c 项目: Kream/zfs
static struct dentry *
zpl_dentry_obtain_alias(struct inode *ip)
{
	struct dentry *result;

#ifdef HAVE_D_OBTAIN_ALIAS
	result = d_obtain_alias(ip);
#else
	result = d_alloc_anon(ip);

	if (result == NULL) {
		iput(ip);
		result = ERR_PTR(-ENOMEM);
	}
#endif /* HAVE_D_OBTAIN_ALIAS */

	return result;
}
示例#15
0
static struct dentry *export_iget(struct super_block *sb, unsigned long ino, __u32 generation)
{

	/* iget isn't really right if the inode is currently unallocated!!
	 * This should really all be done inside each filesystem
	 *
	 * ext2fs' read_inode has been strengthed to return a bad_inode if
	 * the inode had been deleted.
	 *
	 * Currently we don't know the generation for parent directory, so
	 * a generation of 0 means "accept any"
	 */
	struct inode *inode;
	struct dentry *result;
	if (ino == 0)
		return ERR_PTR(-ESTALE);
	inode = iget(sb, ino);
	if (inode == NULL)
		return ERR_PTR(-ENOMEM);
	if (is_bad_inode(inode)
	    || (generation && inode->i_generation != generation)
		) {
		/* we didn't find the right inode.. */
		dprintk("fh_verify: Inode %lu, Bad count: %d %d or version  %u %u\n",
			inode->i_ino,
			inode->i_nlink, atomic_read(&inode->i_count),
			inode->i_generation,
			generation);

		iput(inode);
		return ERR_PTR(-ESTALE);
	}
	/* now to find a dentry.
	 * If possible, get a well-connected one
	 */
	result = d_alloc_anon(inode);
	if (!result) {
		iput(inode);
		return ERR_PTR(-ENOMEM);
	}
	return result;
}
示例#16
0
STATIC struct dentry *
xfs_fs_get_parent(
	struct dentry		*child)
{
	int			error;
	bhv_vnode_t		*cvp;
	struct dentry		*parent;

	cvp = NULL;
	error = xfs_lookup(XFS_I(child->d_inode), &dotdot, &cvp);
	if (unlikely(error))
		return ERR_PTR(-error);

	parent = d_alloc_anon(vn_to_inode(cvp));
	if (unlikely(!parent)) {
		VN_RELE(cvp);
		return ERR_PTR(-ENOMEM);
	}
	return parent;
}
示例#17
0
static struct dentry *ext2_get_dentry(struct super_block *sb, void *vobjp)
{
	__u32 *objp = vobjp;
	unsigned long ino = objp[0];
	__u32 generation = objp[1];
	struct inode *inode;
	struct dentry *result;

	if (ino < EXT2_FIRST_INO(sb) && ino != EXT2_ROOT_INO)
		return ERR_PTR(-ESTALE);
	if (ino > le32_to_cpu(EXT2_SB(sb)->s_es->s_inodes_count))
		return ERR_PTR(-ESTALE);

	/* iget isn't really right if the inode is currently unallocated!!
	 * ext2_read_inode currently does appropriate checks, but
	 * it might be "neater" to call ext2_get_inode first and check
	 * if the inode is valid.....
	 */
	inode = iget(sb, ino);
	if (inode == NULL)
		return ERR_PTR(-ENOMEM);
	if (is_bad_inode(inode) ||
	    (generation && inode->i_generation != generation)) {
		/* we didn't find the right inode.. */
		iput(inode);
		return ERR_PTR(-ESTALE);
	}
	/* now to find a dentry.
	 * If possible, get a well-connected one
	 */
	result = d_alloc_anon(inode);
	if (!result) {
		iput(inode);
		return ERR_PTR(-ENOMEM);
	}
	return result;
}
示例#18
0
struct dentry *ext2_get_parent(struct dentry *child)
{
	unsigned long ino;
	struct dentry *parent;
	struct inode *inode;
	struct dentry dotdot;

	dotdot.d_name.name = "..";
	dotdot.d_name.len = 2;

	ino = ext2_inode_by_name(child->d_inode, &dotdot);
	if (!ino)
		return ERR_PTR(-ENOENT);
	inode = iget(child->d_inode->i_sb, ino);

	if (!inode)
		return ERR_PTR(-EACCES);
	parent = d_alloc_anon(inode);
	if (!parent) {
		iput(inode);
		parent = ERR_PTR(-ENOMEM);
	}
	return parent;
} 
示例#19
0
STATIC int
xfs_open_by_handle(
	xfs_mount_t		*mp,
	unsigned long		arg,
	struct file		*parfilp,
	struct inode		*parinode)
{
	int			error;
	int			new_fd;
	int			permflag;
	struct file		*filp;
	struct inode		*inode;
	struct dentry		*dentry;
	vnode_t			*vp;
	xfs_fsop_handlereq_t	hreq;

	error = xfs_vget_fsop_handlereq(mp, parinode, CAP_SYS_ADMIN, arg,
					sizeof(xfs_fsop_handlereq_t),
					&hreq, &vp, &inode);
	if (error)
		return -error;

	/* Restrict xfs_open_by_handle to directories & regular files. */
	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
		iput(inode);
		return -XFS_ERROR(EINVAL);
	}

#if BITS_PER_LONG != 32
	hreq.oflags |= O_LARGEFILE;
#endif
	/* Put open permission in namei format. */
	permflag = hreq.oflags;
	if ((permflag+1) & O_ACCMODE)
		permflag++;
	if (permflag & O_TRUNC)
		permflag |= 2;

	if ((!(permflag & O_APPEND) || (permflag & O_TRUNC)) &&
	    (permflag & FMODE_WRITE) && IS_APPEND(inode)) {
		iput(inode);
		return -XFS_ERROR(EPERM);
	}

	if ((permflag & FMODE_WRITE) && IS_IMMUTABLE(inode)) {
		iput(inode);
		return -XFS_ERROR(EACCES);
	}

	/* Can't write directories. */
	if ( S_ISDIR(inode->i_mode) && (permflag & FMODE_WRITE)) {
		iput(inode);
		return -XFS_ERROR(EISDIR);
	}

	if ((new_fd = get_unused_fd()) < 0) {
		iput(inode);
		return new_fd;
	}

	dentry = d_alloc_anon(inode);
	if (dentry == NULL) {
		iput(inode);
		put_unused_fd(new_fd);
		return -XFS_ERROR(ENOMEM);
	}

	/* Ensure umount returns EBUSY on umounts while this file is open. */
	mntget(parfilp->f_vfsmnt);

	/* Create file pointer. */
	filp = dentry_open(dentry, parfilp->f_vfsmnt, hreq.oflags);
	if (IS_ERR(filp)) {
		put_unused_fd(new_fd);
		return -XFS_ERROR(-PTR_ERR(filp));
	}
	if (inode->i_mode & S_IFREG)
		filp->f_op = &linvfs_invis_file_operations;

	fd_install(new_fd, filp);
	return new_fd;
}
示例#20
0
/*
 * get an NFS2/NFS3 root dentry from the root filehandle
 */
struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
{
	struct nfs_server *server = NFS_SB(sb);
	struct nfs_fsinfo fsinfo;
	struct nfs_fattr fattr;
	struct dentry *mntroot;
	struct inode *inode;
	int error;

	/* create a dummy root dentry with dummy inode for this superblock */
	if (!sb->s_root) {
		struct nfs_fh dummyfh;
		struct dentry *root;
		struct inode *iroot;

		memset(&dummyfh, 0, sizeof(dummyfh));
		memset(&fattr, 0, sizeof(fattr));
		nfs_fattr_init(&fattr);
		fattr.valid = NFS_ATTR_FATTR;
		fattr.type = NFDIR;
		fattr.mode = S_IFDIR | S_IRUSR | S_IWUSR;
		fattr.nlink = 2;

		iroot = nfs_fhget(sb, &dummyfh, &fattr);
		if (IS_ERR(iroot))
			return ERR_PTR(PTR_ERR(iroot));

		root = d_alloc_root(iroot);
		if (!root) {
			iput(iroot);
			return ERR_PTR(-ENOMEM);
		}

		sb->s_root = root;
	}

	/* get the actual root for this mount */
	fsinfo.fattr = &fattr;

	error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo);
	if (error < 0) {
		dprintk("nfs_get_root: getattr error = %d\n", -error);
		return ERR_PTR(error);
	}

	inode = nfs_fhget(sb, mntfh, fsinfo.fattr);
	if (IS_ERR(inode)) {
		dprintk("nfs_get_root: get root inode failed\n");
		return ERR_PTR(PTR_ERR(inode));
	}

	/* root dentries normally start off anonymous and get spliced in later
	 * if the dentry tree reaches them; however if the dentry already
	 * exists, we'll pick it up at this point and use it as the root
	 */
	mntroot = d_alloc_anon(inode);
	if (!mntroot) {
		iput(inode);
		dprintk("nfs_get_root: get root dentry failed\n");
		return ERR_PTR(-ENOMEM);
	}

	security_d_instantiate(mntroot, inode);

	if (!mntroot->d_op)
		mntroot->d_op = server->nfs_client->rpc_ops->dentry_ops;

	return mntroot;
}
示例#21
0
static int
#ifdef HAVE_ENCODE_FH_WITH_INODE
zpl_encode_fh(struct inode *ip, __u32 *fh, int *max_len, struct inode *parent)
{
#else
zpl_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len, int connectable)
{
	struct inode *ip = dentry->d_inode;
#endif /* HAVE_ENCODE_FH_WITH_INODE */
	fid_t *fid = (fid_t *)fh;
	int len_bytes, rc;

	len_bytes = *max_len * sizeof (__u32);

	if (len_bytes < offsetof(fid_t, fid_data))
		return (255);

	fid->fid_len = len_bytes - offsetof(fid_t, fid_data);

	if (zfsctl_is_node(ip))
		rc = zfsctl_fid(ip, fid);
	else
		rc = zfs_fid(ip, fid);

	len_bytes = offsetof(fid_t, fid_data) + fid->fid_len;
	*max_len = roundup(len_bytes, sizeof (__u32)) / sizeof (__u32);

	return (rc == 0 ? FILEID_INO32_GEN : 255);
}

static struct dentry *
zpl_dentry_obtain_alias(struct inode *ip)
{
	struct dentry *result;

#ifdef HAVE_D_OBTAIN_ALIAS
	result = d_obtain_alias(ip);
#else
	result = d_alloc_anon(ip);

	if (result == NULL) {
		VN_RELE(ip);
		result = ERR_PTR(-ENOMEM);
	}
#endif /* HAVE_D_OBTAIN_ALIAS */

	return (result);
}

static struct dentry *
zpl_fh_to_dentry(struct super_block *sb, struct fid *fh,
    int fh_len, int fh_type)
{
	fid_t *fid = (fid_t *)fh;
	struct inode *ip;
	int len_bytes, rc;

	len_bytes = fh_len * sizeof (__u32);

	if (fh_type != FILEID_INO32_GEN ||
	    len_bytes < offsetof(fid_t, fid_data) ||
	    len_bytes < offsetof(fid_t, fid_data) + fid->fid_len)
		return (ERR_PTR(-EINVAL));

	rc = zfs_vget(sb, &ip, fid);

	if (rc != 0)
		return (ERR_PTR(-rc));

	ASSERT((ip != NULL) && !IS_ERR(ip));

	return (zpl_dentry_obtain_alias(ip));
}
示例#22
0
static struct dentry *gfs2_get_dentry(struct super_block *sb,
		struct gfs2_inum_host *inum)
{
	struct gfs2_sbd *sdp = sb->s_fs_info;
	struct gfs2_fh_obj *fh_obj = (struct gfs2_fh_obj *)inum_obj;
	struct gfs2_holder i_gh, ri_gh, rgd_gh;
	struct gfs2_rgrpd *rgd;
	struct inode *inode;
	struct dentry *dentry;
	int error;

	/* System files? */

	inode = gfs2_ilookup(sb, inum);
	if (inode) {
		if (GFS2_I(inode)->i_num.no_formal_ino != inum->no_formal_ino) {
			iput(inode);
			return ERR_PTR(-ESTALE);
		}
		goto out_inode;
	}

	error = gfs2_glock_nq_num(sdp, inum->no_addr, &gfs2_inode_glops,
				  LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
	if (error)
		return ERR_PTR(error);

	error = gfs2_rindex_hold(sdp, &ri_gh);
	if (error)
		goto fail;

	error = -EINVAL;
	rgd = gfs2_blk2rgrpd(sdp, inum->no_addr);
	if (!rgd)
		goto fail_rindex;

	error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_SHARED, 0, &rgd_gh);
	if (error)
		goto fail_rindex;

	error = -ESTALE;
	if (gfs2_get_block_type(rgd, inum->no_addr) != GFS2_BLKST_DINODE)
		goto fail_rgd;

	gfs2_glock_dq_uninit(&rgd_gh);
	gfs2_glock_dq_uninit(&ri_gh);

	inode = gfs2_inode_lookup(sb, inum, fh_obj->imode);
	if (!inode)
		goto fail;
	if (IS_ERR(inode)) {
		error = PTR_ERR(inode);
		goto fail;
	}

	error = gfs2_inode_refresh(GFS2_I(inode));
	if (error) {
		iput(inode);
		goto fail;
	}

	error = -EIO;
	if (GFS2_I(inode)->i_di.di_flags & GFS2_DIF_SYSTEM) {
		iput(inode);
		goto fail;
	}

	gfs2_glock_dq_uninit(&i_gh);

out_inode:
	dentry = d_alloc_anon(inode);
	if (!dentry) {
		iput(inode);
		return ERR_PTR(-ENOMEM);
	}

	dentry->d_op = &gfs2_dops;
	return dentry;

fail_rgd:
	gfs2_glock_dq_uninit(&rgd_gh);

fail_rindex:
	gfs2_glock_dq_uninit(&ri_gh);

fail:
	gfs2_glock_dq_uninit(&i_gh);
	return ERR_PTR(error);
}
示例#23
0
static int
#ifdef HAVE_ENCODE_FH_WITH_INODE
zpl_encode_fh(struct inode *ip, __u32 *fh, int *max_len, struct inode *parent)
{
#else
zpl_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len, int connectable)
{
	struct inode *ip = dentry->d_inode;
#endif /* HAVE_ENCODE_FH_WITH_INODE */
	fstrans_cookie_t cookie;
	fid_t *fid = (fid_t *)fh;
	int len_bytes, rc;

	len_bytes = *max_len * sizeof (__u32);

	if (len_bytes < offsetof(fid_t, fid_data))
		return (255);

	fid->fid_len = len_bytes - offsetof(fid_t, fid_data);
	cookie = spl_fstrans_mark();

	if (zfsctl_is_node(ip))
		rc = zfsctl_fid(ip, fid);
	else
		rc = zfs_fid(ip, fid);

	spl_fstrans_unmark(cookie);
	len_bytes = offsetof(fid_t, fid_data) + fid->fid_len;
	*max_len = roundup(len_bytes, sizeof (__u32)) / sizeof (__u32);

	return (rc == 0 ? FILEID_INO32_GEN : 255);
}

static struct dentry *
zpl_dentry_obtain_alias(struct inode *ip)
{
	struct dentry *result;

#ifdef HAVE_D_OBTAIN_ALIAS
	result = d_obtain_alias(ip);
#else
	result = d_alloc_anon(ip);

	if (result == NULL) {
		VN_RELE(ip);
		result = ERR_PTR(-ENOMEM);
	}
#endif /* HAVE_D_OBTAIN_ALIAS */

	return (result);
}

static struct dentry *
zpl_fh_to_dentry(struct super_block *sb, struct fid *fh,
    int fh_len, int fh_type)
{
	fid_t *fid = (fid_t *)fh;
	fstrans_cookie_t cookie;
	struct inode *ip;
	int len_bytes, rc;

	len_bytes = fh_len * sizeof (__u32);

	if (fh_type != FILEID_INO32_GEN ||
	    len_bytes < offsetof(fid_t, fid_data) ||
	    len_bytes < offsetof(fid_t, fid_data) + fid->fid_len)
		return (ERR_PTR(-EINVAL));

	cookie = spl_fstrans_mark();
	rc = zfs_vget(sb, &ip, fid);
	spl_fstrans_unmark(cookie);

	if (rc) {
		/*
		 * If we see ENOENT it might mean that an NFSv4 * client
		 * is using a cached inode value in a file handle and
		 * that the sought after file has had its inode changed
		 * by a third party.  So change the error to ESTALE
		 * which will trigger a full lookup by the client and
		 * will find the new filename/inode pair if it still
		 * exists.
		 */
		if (rc == ENOENT)
			rc = ESTALE;

		return (ERR_PTR(-rc));
	}

	ASSERT((ip != NULL) && !IS_ERR(ip));

	return (zpl_dentry_obtain_alias(ip));
}
示例#24
0
osi_UFSOpen(afs_int32 ainode)
#endif
{
    register struct osi_file *afile = NULL;
    extern int cacheDiskType;
    struct inode *tip = NULL;
    struct dentry *dp = NULL;
    struct file *filp = NULL;
#if !defined(HAVE_IGET) || defined(LINUX_USE_FH)
    struct fid fid;
#endif
    AFS_STATCNT(osi_UFSOpen);
    if (cacheDiskType != AFS_FCACHE_TYPE_UFS) {
	osi_Panic("UFSOpen called for non-UFS cache\n");
    }
    if (!afs_osicred_initialized) {
	/* valid for alpha_osf, SunOS, Ultrix */
	memset((char *)&afs_osi_cred, 0, sizeof(struct AFS_UCRED));
	crhold(&afs_osi_cred);	/* don't let it evaporate, since it is static */
	afs_osicred_initialized = 1;
    }
    afile = (struct osi_file *)osi_AllocLargeSpace(sizeof(struct osi_file));
    AFS_GUNLOCK();
    if (!afile) {
	osi_Panic("osi_UFSOpen: Failed to allocate %d bytes for osi_file.\n",
		  sizeof(struct osi_file));
    }
    memset(afile, 0, sizeof(struct osi_file));
#if defined(HAVE_IGET)
    tip = iget(afs_cacheSBp, (u_long) ainode);
    if (!tip)
	osi_Panic("Can't get inode %d\n", ainode);

    dp = d_alloc_anon(tip);
#else
#if defined(LINUX_USE_FH)
    dp = afs_cacheSBp->s_export_op->fh_to_dentry(afs_cacheSBp, fh, sizeof(struct fid), fh_type);
#else
    fid.i32.ino = ainode;
    fid.i32.gen = 0;
    dp = afs_cacheSBp->s_export_op->fh_to_dentry(afs_cacheSBp, &fid, sizeof(fid), FILEID_INO32_GEN);
#endif
    if (!dp) 
           osi_Panic("Can't get dentry\n");          
    tip = dp->d_inode;
#endif
    tip->i_flags |= MS_NOATIME;	/* Disable updating access times. */

#if defined(STRUCT_TASK_HAS_CRED)
    filp = dentry_open(dp, mntget(afs_cacheMnt), O_RDWR, current_cred());
#else
    filp = dentry_open(dp, mntget(afs_cacheMnt), O_RDWR);
#endif
    if (IS_ERR(filp))
#if defined(LINUX_USE_FH)
	osi_Panic("Can't open file\n");
#else
	osi_Panic("Can't open inode %d\n", ainode);
#endif
    afile->filp = filp;
    afile->size = i_size_read(FILE_INODE(filp));
    AFS_GLOCK();
    afile->offset = 0;
    afile->proc = (int (*)())0;
#if defined(LINUX_USE_FH)
    afile->inum = tip->i_ino;	/* for hint validity checking */
#else
    afile->inum = ainode;	/* for hint validity checking */
#endif
    return (void *)afile;
}
示例#25
0
/* This function is surprisingly simple.  The trick is understanding
 * that "child" is always a directory. So, to find its parent, you
 * simply need to find its ".." entry, normalize its block and offset,
 * and return the underlying inode.  See the comments for
 * isofs_normalize_block_and_offset(). */
static struct dentry *isofs_export_get_parent(struct dentry *child)
{
	unsigned long parent_block = 0;
	unsigned long parent_offset = 0;
	struct inode *child_inode = child->d_inode;
	struct iso_inode_info *e_child_inode = ISOFS_I(child_inode);
	struct inode *parent_inode = NULL;
	struct iso_directory_record *de = NULL;
	struct buffer_head * bh = NULL;
	struct dentry *rv = NULL;

	/* "child" must always be a directory. */
	if (!S_ISDIR(child_inode->i_mode)) {
		printk(KERN_ERR "isofs: isofs_export_get_parent(): "
		       "child is not a directory!\n");
		rv = ERR_PTR(-EACCES);
		goto out;
	}

	/* It is an invariant that the directory offset is zero.  If
	 * it is not zero, it means the directory failed to be
	 * normalized for some reason. */
	if (e_child_inode->i_iget5_offset != 0) {
		printk(KERN_ERR "isofs: isofs_export_get_parent(): "
		       "child directory not normalized!\n");
		rv = ERR_PTR(-EACCES);
		goto out;
	}

	/* The child inode has been normalized such that its
	 * i_iget5_block value points to the "." entry.  Fortunately,
	 * the ".." entry is located in the same block. */
	parent_block = e_child_inode->i_iget5_block;

	/* Get the block in question. */
	bh = sb_bread(child_inode->i_sb, parent_block);
	if (bh == NULL) {
		rv = ERR_PTR(-EACCES);
		goto out;
	}

	/* This is the "." entry. */
	de = (struct iso_directory_record*)bh->b_data;

	/* The ".." entry is always the second entry. */
	parent_offset = (unsigned long)isonum_711(de->length);
	de = (struct iso_directory_record*)(bh->b_data + parent_offset);

	/* Verify it is in fact the ".." entry. */
	if ((isonum_711(de->name_len) != 1) || (de->name[0] != 1)) {
		printk(KERN_ERR "isofs: Unable to find the \"..\" "
		       "directory for NFS.\n");
		rv = ERR_PTR(-EACCES);
		goto out;
	}

	/* Normalize */
	isofs_normalize_block_and_offset(de, &parent_block, &parent_offset);

	/* Get the inode. */
	parent_inode = isofs_iget(child_inode->i_sb,
				  parent_block,
				  parent_offset);
	if (IS_ERR(parent_inode)) {
		rv = ERR_CAST(parent_inode);
		if (rv != ERR_PTR(-ENOMEM))
			rv = ERR_PTR(-EACCES);
		goto out;
	}

	/* Allocate the dentry. */
	rv = d_alloc_anon(parent_inode);
	if (rv == NULL) {
		rv = ERR_PTR(-ENOMEM);
		goto out;
	}

 out:
	if (bh) {
		brelse(bh);
	}
	return rv;
}
示例#26
0
/* 
 * Given a FID, obtain or construct a dentry, or return an error.
 * This should be called with the BKL and AFS_GLOCK held.
 */
static struct dentry *get_dentry_from_fid(cred_t *credp, struct VenusFid *afid)
{
    struct vrequest treq;
    struct vcache *vcp;
    struct vattr vattr;
    struct inode *ip;
    struct dentry *dp;
    afs_int32 code;

    code = afs_InitReq(&treq, credp);
    if (code) {
#ifdef OSI_EXPORT_DEBUG
	printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): afs_InitReq: %d\n",
	       afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique,
	       code);
#endif
	return ERR_PTR(-afs_CheckCode(code, &treq, 101));
    }
    vcp = afs_GetVCache(afid, &treq, NULL, NULL);
    if (vcp == NULL) {
#ifdef OSI_EXPORT_DEBUG
	printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): no vcache\n",
	       afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique);
#endif
	return NULL;
    }

    /* 
     * Now, it might be that we just caused a directory vnode to
     * spring into existence, in which case its parent FID is unset.
     * We need to do something about that, but only because we care
     * in our own get_parent(), below -- the common code never looks
     * at parentVnode on directories, except for VIOCGETVCXSTATUS.
     * So, if this fails, we don't really care very much.
     */
    if (vType(vcp) == VDIR && vcp->mvstat != 2 && !vcp->f.parent.vnode)
	update_dir_parent(&treq, vcp);

    /*
     * If this is a volume root directory and fakestat is enabled,
     * we might need to replace the directory by a mount point.
     */
    code = UnEvalFakeStat(&treq, &vcp);
    if (code) {
#ifdef OSI_EXPORT_DEBUG
	printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): UnEvalFakeStat: %d\n",
	       afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique,
	       code);
#endif
	afs_PutVCache(vcp);
	return ERR_PTR(-afs_CheckCode(code, &treq, 101));
    }

    ip = AFSTOV(vcp);
    afs_getattr(vcp, &vattr, credp);
    afs_fill_inode(ip, &vattr);

    /* d_alloc_anon might block, so we shouldn't hold the glock */
    AFS_GUNLOCK();
    dp = d_alloc_anon(ip);
    AFS_GLOCK();

    if (!dp) {
	iput(ip);
#ifdef OSI_EXPORT_DEBUG
	printk("afs: get_dentry_from_fid(0x%08x/%d/%d.%d): out of memory\n",
	       afid->Cell, afid->Fid.Volume, afid->Fid.Vnode, afid->Fid.Unique);
#endif
	return ERR_PTR(-ENOMEM);
    }

    dp->d_op = &afs_dentry_operations;
    return dp;
}
示例#27
0
/**
 * ntfs_get_parent - find the dentry of the parent of a given directory dentry
 * @child_dent:		dentry of the directory whose parent directory to find
 *
 * Find the dentry for the parent directory of the directory specified by the
 * dentry @child_dent.  This function is called from
 * fs/exportfs/expfs.c::find_exported_dentry() which in turn is called from the
 * default ->decode_fh() which is export_decode_fh() in the same file.
 *
 * The code is based on the ext3 ->get_parent() implementation found in
 * fs/ext3/namei.c::ext3_get_parent().
 *
 * Note: ntfs_get_parent() is called with @child_dent->d_inode->i_mutex down.
 *
 * Return the dentry of the parent directory on success or the error code on
 * error (IS_ERR() is true).
 */
static struct dentry *ntfs_get_parent(struct dentry *child_dent)
{
	struct inode *vi = child_dent->d_inode;
	ntfs_inode *ni = NTFS_I(vi);
	MFT_RECORD *mrec;
	ntfs_attr_search_ctx *ctx;
	ATTR_RECORD *attr;
	FILE_NAME_ATTR *fn;
	struct inode *parent_vi;
	struct dentry *parent_dent;
	unsigned long parent_ino;
	int err;

	ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
	/* Get the mft record of the inode belonging to the child dentry. */
	mrec = map_mft_record(ni);
	if (IS_ERR(mrec))
		return (struct dentry *)mrec;
	/* Find the first file name attribute in the mft record. */
	ctx = ntfs_attr_get_search_ctx(ni, mrec);
	if (unlikely(!ctx)) {
		unmap_mft_record(ni);
		return ERR_PTR(-ENOMEM);
	}
try_next:
	err = ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, CASE_SENSITIVE, 0, NULL,
			0, ctx);
	if (unlikely(err)) {
		ntfs_attr_put_search_ctx(ctx);
		unmap_mft_record(ni);
		if (err == -ENOENT)
			ntfs_error(vi->i_sb, "Inode 0x%lx does not have a "
					"file name attribute.  Run chkdsk.",
					vi->i_ino);
		return ERR_PTR(err);
	}
	attr = ctx->attr;
	if (unlikely(attr->non_resident))
		goto try_next;
	fn = (FILE_NAME_ATTR *)((u8 *)attr +
			le16_to_cpu(attr->data.resident.value_offset));
	if (unlikely((u8 *)fn + le32_to_cpu(attr->data.resident.value_length) >
			(u8*)attr + le32_to_cpu(attr->length)))
		goto try_next;
	/* Get the inode number of the parent directory. */
	parent_ino = MREF_LE(fn->parent_directory);
	/* Release the search context and the mft record of the child. */
	ntfs_attr_put_search_ctx(ctx);
	unmap_mft_record(ni);
	/* Get the inode of the parent directory. */
	parent_vi = ntfs_iget(vi->i_sb, parent_ino);
	if (IS_ERR(parent_vi) || unlikely(is_bad_inode(parent_vi))) {
		if (!IS_ERR(parent_vi))
			iput(parent_vi);
		ntfs_error(vi->i_sb, "Failed to get parent directory inode "
				"0x%lx of child inode 0x%lx.", parent_ino,
				vi->i_ino);
		return ERR_PTR(-EACCES);
	}
	/* Finally get a dentry for the parent directory and return it. */
	parent_dent = d_alloc_anon(parent_vi);
	if (unlikely(!parent_dent)) {
		iput(parent_vi);
		return ERR_PTR(-ENOMEM);
	}
	ntfs_debug("Done for inode 0x%lx.", vi->i_ino);
	return parent_dent;
}