ASSERT(nd);
link = (char *)kmalloc(MAXNAMELEN+1, GFP_KERNEL);
- if (!link) {
- nd_set_link(nd, ERR_PTR(-ENOMEM));
- return 0;
- }
+ if (!link)
+ return -ENOMEM;
uio = (uio_t *)kmalloc(sizeof(uio_t), GFP_KERNEL);
if (!uio) {
kfree(link);
- nd_set_link(nd, ERR_PTR(-ENOMEM));
- return 0;
+ return -ENOMEM;
}
vp = LINVFS_GET_VP(dentry->d_inode);
VOP_READLINK(vp, uio, 0, NULL, error);
if (error) {
+ kfree(uio);
kfree(link);
- link = ERR_PTR(-error);
- } else {
- link[MAXNAMELEN - uio->uio_resid] = '\0';
+ return -error;
}
- kfree(uio);
- nd_set_link(nd, link);
- return 0;
-}
+ link[MAXNAMELEN - uio->uio_resid] = '\0';
+ kfree(uio);
-static void linvfs_put_link(struct dentry *dentry, struct nameidata *nd)
-{
- char *s = nd_get_link(nd);
- if (!IS_ERR(s))
- kfree(s);
+ /* vfs_follow_link returns (-) errors */
+ error = vfs_follow_link(nd, link);
+ kfree(link);
+ return error;
}
#ifdef CONFIG_XFS_POSIX_ACL
return 0;
}
+STATIC int
+linvfs_setattr_flags(
+ vattr_t *vap,
+ unsigned int flags)
+{
+ unsigned int oldflags, newflags;
+
+ oldflags = vap->va_xflags;
+ newflags = oldflags & ~(XFS_XFLAG_IMMUTABLE |
+ XFS_XFLAG_IUNLINK | XFS_XFLAG_BARRIER);
+ if (flags & ATTR_FLAG_IMMUTABLE)
+ newflags |= XFS_XFLAG_IMMUTABLE;
+ if (flags & ATTR_FLAG_IUNLINK)
+ newflags |= XFS_XFLAG_IUNLINK;
+ if (flags & ATTR_FLAG_BARRIER)
+ newflags |= XFS_XFLAG_BARRIER;
+
+ if (oldflags ^ newflags)
+ vap->va_xflags = newflags;
+ return 0;
+}
+
STATIC int
linvfs_setattr(
struct dentry *dentry,
flags |= ATTR_NONBLOCK;
#endif
+ if (ia_valid & ATTR_ATTR_FLAG) {
+ vattr.va_mask |= XFS_AT_XFLAGS;
+ linvfs_setattr_flags(&vattr, attr->ia_attr_flags);
+ }
+
VOP_SETATTR(vp, &vattr, flags, NULL, error);
if (error)
return -error;
struct inode_operations linvfs_symlink_inode_operations = {
.readlink = linvfs_readlink,
.follow_link = linvfs_follow_link,
- .put_link = linvfs_put_link,
.permission = linvfs_permission,
.getattr = linvfs_getattr,
.setattr = linvfs_setattr,