#include "xfs_utils.h"
#include <linux/xattr.h>
+#include <linux/namei.h>
/*
*/
teardown.d_inode = ip = LINVFS_GET_IP(vp);
teardown.d_name = dentry->d_name;
- remove_inode_hash(ip);
- make_bad_inode(ip);
+
+ vn_mark_bad(vp);
+
if (S_ISDIR(mode))
VOP_RMDIR(dvp, &teardown, NULL, err2);
else
struct dentry *dentry,
struct nameidata *nd)
{
- struct inode *ip = NULL;
- vnode_t *vp, *cvp = NULL;
+ struct vnode *vp = LINVFS_GET_VP(dir), *cvp;
int error;
if (dentry->d_name.len >= MAXNAMELEN)
return ERR_PTR(-ENAMETOOLONG);
- vp = LINVFS_GET_VP(dir);
VOP_LOOKUP(vp, dentry, &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) {
+ if (unlikely(error != ENOENT))
+ return ERR_PTR(-error);
+ d_add(dentry, NULL);
+ return NULL;
}
- if (error && (error != ENOENT))
- return ERR_PTR(-error);
- return d_splice_alias(ip, dentry);
+
+ return d_splice_alias(LINVFS_GET_IP(cvp), dentry);
}
STATIC int
{
struct inode *ip;
vattr_t va;
- vnode_t *dvp; /* directory containing name to remove */
+ vnode_t *dvp; /* directory containing name of symlink */
vnode_t *cvp; /* used to lookup symlink to put in dentry */
int error;
return 0;
}
-STATIC int
-linvfs_readlink(
- struct dentry *dentry,
- char *buf,
- int size)
-{
- vnode_t *vp = LINVFS_GET_VP(dentry->d_inode);
- uio_t uio;
- iovec_t iov;
- int error;
-
- iov.iov_base = buf;
- iov.iov_len = size;
-
- uio.uio_iov = &iov;
- uio.uio_offset = 0;
- uio.uio_segflg = UIO_USERSPACE;
- uio.uio_resid = size;
- uio.uio_iovcnt = 1;
-
- VOP_READLINK(vp, &uio, 0, NULL, error);
- if (error)
- return -error;
-
- return (size - uio.uio_resid);
-}
-
/*
* careful here - this function can get called recursively, so
* we need to be very careful about how much stack we use.
ASSERT(nd);
link = (char *)kmalloc(MAXNAMELEN+1, GFP_KERNEL);
- if (!link)
- return -ENOMEM;
+ if (!link) {
+ nd_set_link(nd, ERR_PTR(-ENOMEM));
+ return 0;
+ }
uio = (uio_t *)kmalloc(sizeof(uio_t), GFP_KERNEL);
if (!uio) {
kfree(link);
- return -ENOMEM;
+ nd_set_link(nd, ERR_PTR(-ENOMEM));
+ return 0;
}
vp = LINVFS_GET_VP(dentry->d_inode);
VOP_READLINK(vp, uio, 0, NULL, error);
if (error) {
- kfree(uio);
kfree(link);
- return -error;
+ link = ERR_PTR(-error);
+ } else {
+ link[MAXNAMELEN - uio->uio_resid] = '\0';
}
-
- link[MAXNAMELEN - uio->uio_resid] = '\0';
kfree(uio);
- /* vfs_follow_link returns (-) errors */
- error = vfs_follow_link(nd, link);
- kfree(link);
- return error;
+ nd_set_link(nd, link);
+ return 0;
+}
+
+static void linvfs_put_link(struct dentry *dentry, struct nameidata *nd)
+{
+ char *s = nd_get_link(nd);
+ if (!IS_ERR(s))
+ kfree(s);
}
#ifdef CONFIG_XFS_POSIX_ACL
int flags = 0;
int error;
+ error = inode_change_ok(inode, attr);
+ if (error)
+ return error;
+
memset(&vattr, 0, sizeof(vattr_t));
if (ia_valid & ATTR_UID) {
vattr.va_mask |= XFS_AT_UID;
vattr.va_mask |= XFS_AT_GID;
vattr.va_gid = attr->ia_gid;
}
+ if (ia_valid & ATTR_XID) {
+ vattr.va_mask |= XFS_AT_XID;
+ vattr.va_xid = attr->ia_xid;
+ }
if (ia_valid & ATTR_SIZE) {
vattr.va_mask |= XFS_AT_SIZE;
vattr.va_size = attr->ia_size;
};
struct inode_operations linvfs_symlink_inode_operations = {
- .readlink = linvfs_readlink,
+ .readlink = generic_readlink,
.follow_link = linvfs_follow_link,
+ .put_link = linvfs_put_link,
.permission = linvfs_permission,
.getattr = linvfs_getattr,
.setattr = linvfs_setattr,