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
This commit is contained in:
Ned A. Bass 2011-05-09 12:31:56 -07:00
parent 3117dd0b90
commit aa6d8c1086
2 changed files with 16 additions and 7 deletions

View File

@ -278,7 +278,7 @@ zfs_inode_destroy(struct inode *ip)
static void static void
zfs_inode_set_ops(zfs_sb_t *zsb, struct inode *ip) zfs_inode_set_ops(zfs_sb_t *zsb, struct inode *ip)
{ {
uint64_t rdev; uint64_t rdev = 0;
switch (ip->i_mode & S_IFMT) { switch (ip->i_mode & S_IFMT) {
case S_IFREG: 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; ip->i_op = &zpl_symlink_inode_operations;
break; break;
/*
* rdev is only stored in a SA only for device files.
*/
case S_IFCHR: case S_IFCHR:
case S_IFBLK: case S_IFBLK:
case S_IFIFO:
case S_IFSOCK:
VERIFY(sa_lookup(ITOZ(ip)->z_sa_hdl, SA_ZPL_RDEV(zsb), VERIFY(sa_lookup(ITOZ(ip)->z_sa_hdl, SA_ZPL_RDEV(zsb),
&rdev, sizeof (rdev)) == 0); &rdev, sizeof (rdev)) == 0);
/*FALLTHROUGH*/
case S_IFIFO:
case S_IFSOCK:
init_special_inode(ip, ip->i_mode, rdev); init_special_inode(ip, ip->i_mode, rdev);
ip->i_op = &zpl_special_inode_operations; ip->i_op = &zpl_special_inode_operations;
break; break;
@ -556,8 +560,7 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
size = links = 0; size = links = 0;
} }
if (S_ISBLK(vap->va_mode) || S_ISCHR(vap->va_mode) || if (S_ISBLK(vap->va_mode) || S_ISCHR(vap->va_mode))
S_ISFIFO(vap->va_mode) || S_ISSOCK(vap->va_mode))
rdev = vap->va_rdev; rdev = vap->va_rdev;
parent = dzp->z_id; 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); &empty_xattr, 8);
} }
if (obj_type == DMU_OT_ZNODE || if (obj_type == DMU_OT_ZNODE ||
(S_ISBLK(vap->va_mode) || S_ISCHR(vap->va_mode) || (S_ISBLK(vap->va_mode) || S_ISCHR(vap->va_mode))) {
S_ISFIFO(vap->va_mode) || S_ISSOCK(vap->va_mode))) {
SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_RDEV(zsb), SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_RDEV(zsb),
NULL, &rdev, 8); NULL, &rdev, 8);
} }

View File

@ -85,6 +85,13 @@ zpl_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
vattr_t *vap; vattr_t *vap;
int error; 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); crhold(cr);
vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP); vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP);
vap->va_mode = mode; vap->va_mode = mode;