Set stat->st_dev and statfs->f_fsid
[zfs.git] / module / zfs / zpl_inode.c
index e866dcd..c4ff14f 100644 (file)
@@ -171,10 +171,33 @@ static int
 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);
 
@@ -182,21 +205,34 @@ zpl_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 }
 
 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
@@ -245,8 +281,33 @@ out:
 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
@@ -256,7 +317,7 @@ zpl_put_link(struct dentry *dentry, struct nameidata *nd, void *ptr)
 
        link = nd_get_link(nd);
        if (!IS_ERR(link))
-               kmem_free(link, MAXPATHLEN + 1);
+               kmem_free(link, MAXPATHLEN);
 }
 
 static int
@@ -288,7 +349,6 @@ out:
 }
 
 const struct inode_operations zpl_inode_operations = {
-       .check_acl      = NULL,
        .create         = zpl_create,
        .link           = zpl_link,
        .unlink         = zpl_unlink,
@@ -306,7 +366,6 @@ const struct inode_operations zpl_inode_operations = {
 };
 
 const struct inode_operations zpl_dir_inode_operations = {
-       .check_acl      = NULL,
        .create         = zpl_create,
        .lookup         = zpl_lookup,
        .link           = zpl_link,
@@ -317,15 +376,24 @@ const struct inode_operations zpl_dir_inode_operations = {
        .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,
 };