aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNed A. Bass <[email protected]>2011-05-09 12:31:56 -0700
committerNed A. Bass <[email protected]>2011-05-09 13:35:07 -0700
commitaa6d8c10864dd532b1577a84a22da2eaee10fcfd (patch)
tree3f07ed9010213d4184c0ce21b92e9c1098059f3c
parent3117dd0b9005eb76e483b9772c493883b82998bb (diff)
Don't store rdev in SA for FIFOs and sockets
Update the handling of named pipes and sockets to be consistent with other platforms with regard to the rdev attribute. While all ZFS ipmlementations store the rdev for device files in a system attribute (SA), this is not the case for FIFOs and sockets. Indeed, Linux always passes rdev=0 to mknod() for FIFOs and sockets, so the value is not needed. Add an ASSERT that rdev==0 for FIFOs and sockets to detect if the expected behavior ever changes. Closes #216
-rw-r--r--module/zfs/zfs_znode.c16
-rw-r--r--module/zfs/zpl_inode.c7
2 files changed, 16 insertions, 7 deletions
diff --git a/module/zfs/zfs_znode.c b/module/zfs/zfs_znode.c
index 936b950f3..faf1161c9 100644
--- a/module/zfs/zfs_znode.c
+++ b/module/zfs/zfs_znode.c
@@ -278,7 +278,7 @@ zfs_inode_destroy(struct inode *ip)
static void
zfs_inode_set_ops(zfs_sb_t *zsb, struct inode *ip)
{
- uint64_t rdev;
+ uint64_t rdev = 0;
switch (ip->i_mode & S_IFMT) {
case S_IFREG:
@@ -297,12 +297,16 @@ zfs_inode_set_ops(zfs_sb_t *zsb, struct inode *ip)
ip->i_op = &zpl_symlink_inode_operations;
break;
+ /*
+ * rdev is only stored in a SA only for device files.
+ */
case S_IFCHR:
case S_IFBLK:
- case S_IFIFO:
- case S_IFSOCK:
VERIFY(sa_lookup(ITOZ(ip)->z_sa_hdl, SA_ZPL_RDEV(zsb),
&rdev, sizeof (rdev)) == 0);
+ /*FALLTHROUGH*/
+ case S_IFIFO:
+ case S_IFSOCK:
init_special_inode(ip, ip->i_mode, rdev);
ip->i_op = &zpl_special_inode_operations;
break;
@@ -556,8 +560,7 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
size = links = 0;
}
- if (S_ISBLK(vap->va_mode) || S_ISCHR(vap->va_mode) ||
- S_ISFIFO(vap->va_mode) || S_ISSOCK(vap->va_mode))
+ if (S_ISBLK(vap->va_mode) || S_ISCHR(vap->va_mode))
rdev = vap->va_rdev;
parent = dzp->z_id;
@@ -648,8 +651,7 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
&empty_xattr, 8);
}
if (obj_type == DMU_OT_ZNODE ||
- (S_ISBLK(vap->va_mode) || S_ISCHR(vap->va_mode) ||
- S_ISFIFO(vap->va_mode) || S_ISSOCK(vap->va_mode))) {
+ (S_ISBLK(vap->va_mode) || S_ISCHR(vap->va_mode))) {
SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_RDEV(zsb),
NULL, &rdev, 8);
}
diff --git a/module/zfs/zpl_inode.c b/module/zfs/zpl_inode.c
index 029a4038b..8376673f1 100644
--- a/module/zfs/zpl_inode.c
+++ b/module/zfs/zpl_inode.c
@@ -85,6 +85,13 @@ zpl_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
vattr_t *vap;
int error;
+ /*
+ * We currently expect Linux to supply rdev=0 for all sockets
+ * and fifos, but we want to know if this behavior ever changes.
+ */
+ if (S_ISSOCK(mode) || S_ISFIFO(mode))
+ ASSERT(rdev == 0);
+
crhold(cr);
vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP);
vap->va_mode = mode;