zpl_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
{
cred_t *cr;
+ vattr_t *vap;
+ struct inode *ip;
int error;
+ ip = dentry->d_inode;
cr = (cred_t *)get_current_cred();
- error = -zfs_getattr(dentry->d_inode, stat, 0, cr);
+ vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP);
+
+ error = -zfs_getattr(ip, vap, 0, cr);
+ if (error)
+ goto out;
+
+ stat->ino = ip->i_ino;
+ stat->dev = ip->i_sb->s_dev;
+ stat->mode = vap->va_mode;
+ stat->nlink = vap->va_nlink;
+ stat->uid = vap->va_uid;
+ stat->gid = vap->va_gid;
+ stat->rdev = vap->va_rdev;
+ stat->size = vap->va_size;
+ stat->atime = vap->va_atime;
+ stat->mtime = vap->va_mtime;
+ stat->ctime = vap->va_ctime;
+ stat->blksize = vap->va_blksize;
+ stat->blocks = vap->va_nblocks;
+out:
+ kmem_free(vap, sizeof(vattr_t));
put_cred(cr);
ASSERT3S(error, <=, 0);
}
static int
-zpl_setattr(struct dentry *dentry, struct iattr *attr)
+zpl_setattr(struct dentry *dentry, struct iattr *ia)
{
cred_t *cr;
+ vattr_t *vap;
int error;
- error = inode_change_ok(dentry->d_inode, attr);
+ error = inode_change_ok(dentry->d_inode, ia);
if (error)
return (error);
cr = (cred_t *)get_current_cred();
- error = -zfs_setattr(dentry->d_inode, attr, 0, cr);
+ vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP);
+ vap->va_mask = ia->ia_valid & ATTR_IATTR_MASK;
+ vap->va_mode = ia->ia_mode;
+ vap->va_uid = ia->ia_uid;
+ vap->va_gid = ia->ia_gid;
+ vap->va_size = ia->ia_size;
+ vap->va_atime = ia->ia_atime;
+ vap->va_mtime = ia->ia_mtime;
+ vap->va_ctime = ia->ia_ctime;
+
+ error = -zfs_setattr(dentry->d_inode, vap, 0, cr);
+
+ kmem_free(vap, sizeof(vattr_t));
put_cred(cr);
ASSERT3S(error, <=, 0);
- return (-error);
+ return (error);
}
static int
static void *
zpl_follow_link(struct dentry *dentry, struct nameidata *nd)
{
- (void) zfs_follow_link(dentry, nd);
- return NULL;
+ struct inode *ip = dentry->d_inode;
+ struct iovec iov;
+ uio_t uio;
+ char *link;
+ cred_t *cr;
+ int error;
+
+ cr = (cred_t *)get_current_cred();
+
+ iov.iov_len = MAXPATHLEN;
+ iov.iov_base = link = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
+
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_resid = (MAXPATHLEN - 1);
+ uio.uio_segflg = UIO_SYSSPACE;
+
+ error = -zfs_readlink(ip, &uio, cr);
+ if (error) {
+ kmem_free(link, MAXPATHLEN);
+ nd_set_link(nd, ERR_PTR(error));
+ } else {
+ nd_set_link(nd, link);
+ }
+
+ put_cred(cr);
+ return (NULL);
}
static void
link = nd_get_link(nd);
if (!IS_ERR(link))
- kmem_free(link, MAXPATHLEN + 1);
+ kmem_free(link, MAXPATHLEN);
}
static int
}
const struct inode_operations zpl_inode_operations = {
- .check_acl = NULL,
.create = zpl_create,
.link = zpl_link,
.unlink = zpl_unlink,
};
const struct inode_operations zpl_dir_inode_operations = {
- .check_acl = NULL,
.create = zpl_create,
.lookup = zpl_lookup,
.link = zpl_link,
.mknod = zpl_mknod,
.rename = zpl_rename,
.setattr = zpl_setattr,
+ .getattr = zpl_getattr,
+ .setxattr = generic_setxattr,
+ .getxattr = generic_getxattr,
+ .removexattr = generic_removexattr,
+ .listxattr = zpl_xattr_list,
};
const struct inode_operations zpl_symlink_inode_operations = {
- .check_acl = NULL,
.readlink = generic_readlink,
.follow_link = zpl_follow_link,
.put_link = zpl_put_link,
};
const struct inode_operations zpl_special_inode_operations = {
- .check_acl = NULL,
+ .setattr = zpl_setattr,
+ .getattr = zpl_getattr,
+ .setxattr = generic_setxattr,
+ .getxattr = generic_getxattr,
+ .removexattr = generic_removexattr,
+ .listxattr = zpl_xattr_list,
};