int udf_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp) { struct buf *bp; struct vnode *devvp; struct udf_mnt *udfmp; struct thread *td; struct vnode *vp; struct udf_node *unode; struct file_entry *fe; int error, sector, size; error = vfs_hash_get(mp, ino, flags, curthread, vpp, NULL, NULL); if (error || *vpp != NULL) return (error); /* * We must promote to an exclusive lock for vnode creation. This * can happen if lookup is passed LOCKSHARED. */ if ((flags & LK_TYPE_MASK) == LK_SHARED) { flags &= ~LK_TYPE_MASK; flags |= LK_EXCLUSIVE; } /* * We do not lock vnode creation as it is believed to be too * expensive for such rare case as simultaneous creation of vnode * for same ino by different processes. We just allow them to race * and check later to decide who wins. Let the race begin! */ td = curthread; udfmp = VFSTOUDFFS(mp); unode = uma_zalloc(udf_zone_node, M_WAITOK | M_ZERO); if ((error = udf_allocv(mp, &vp, td))) { printf("Error from udf_allocv\n"); uma_zfree(udf_zone_node, unode); return (error); } unode->i_vnode = vp; unode->hash_id = ino; unode->udfmp = udfmp; vp->v_data = unode; lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL); error = insmntque(vp, mp); if (error != 0) { uma_zfree(udf_zone_node, unode); return (error); } error = vfs_hash_insert(vp, ino, flags, td, vpp, NULL, NULL); if (error || *vpp != NULL) return (error); /* * Copy in the file entry. Per the spec, the size can only be 1 block. */ sector = ino + udfmp->part_start; devvp = udfmp->im_devvp; if ((error = RDSECTOR(devvp, sector, udfmp->bsize, &bp)) != 0) { printf("Cannot read sector %d\n", sector); vgone(vp); vput(vp); brelse(bp); *vpp = NULL; return (error); } fe = (struct file_entry *)bp->b_data; if (udf_checktag(&fe->tag, TAGID_FENTRY)) { printf("Invalid file entry!\n"); vgone(vp); vput(vp); brelse(bp); *vpp = NULL; return (ENOMEM); } size = UDF_FENTRY_SIZE + le32toh(fe->l_ea) + le32toh(fe->l_ad); unode->fentry = malloc(size, M_UDFFENTRY, M_NOWAIT | M_ZERO); if (unode->fentry == NULL) { printf("Cannot allocate file entry block\n"); vgone(vp); vput(vp); brelse(bp); *vpp = NULL; return (ENOMEM); } bcopy(bp->b_data, unode->fentry, size); brelse(bp); bp = NULL; switch (unode->fentry->icbtag.file_type) { default: vp->v_type = VBAD; break; case 4: vp->v_type = VDIR; break; case 5: vp->v_type = VREG; break; case 6: vp->v_type = VBLK; break; case 7: vp->v_type = VCHR; break; case 9: vp->v_type = VFIFO; vp->v_op = &udf_fifoops; break; case 10: vp->v_type = VSOCK; break; case 12: vp->v_type = VLNK; break; } if (vp->v_type != VFIFO) VN_LOCK_ASHARE(vp); if (ino == udf_getid(&udfmp->root_icb)) vp->v_vflag |= VV_ROOT; *vpp = vp; return (0); }
int udf_vget(struct mount *mp, ino_t ino, struct vnode **vpp) { struct buf *bp; struct vnode *devvp; struct umount *ump; struct proc *p; struct vnode *vp, *nvp; struct unode *up; struct extfile_entry *xfe; struct file_entry *fe; int error, sector, size; p = curproc; bp = NULL; *vpp = NULL; ump = VFSTOUDFFS(mp); /* See if we already have this in the cache */ if ((error = udf_hashlookup(ump, ino, LK_EXCLUSIVE, vpp)) != 0) return (error); if (*vpp != NULL) return (0); /* * Allocate memory and check the tag id's before grabbing a new * vnode, since it's hard to roll back if there is a problem. */ up = pool_get(&unode_pool, PR_WAITOK | PR_ZERO); /* * Copy in the file entry. Per the spec, the size can only be 1 block. */ sector = ino; devvp = ump->um_devvp; udf_vat_map(ump, §or); if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) { printf("Cannot read sector %d\n", sector); pool_put(&unode_pool, up); if (bp != NULL) brelse(bp); return (error); } xfe = (struct extfile_entry *)bp->b_data; fe = (struct file_entry *)bp->b_data; error = udf_checktag(&xfe->tag, TAGID_EXTFENTRY); if (error == 0) { size = letoh32(xfe->l_ea) + letoh32(xfe->l_ad); } else { error = udf_checktag(&fe->tag, TAGID_FENTRY); if (error) { printf("Invalid file entry!\n"); pool_put(&unode_pool, up); if (bp != NULL) brelse(bp); return (ENOMEM); } else size = letoh32(fe->l_ea) + letoh32(fe->l_ad); } /* Allocate max size of FE/XFE. */ up->u_fentry = malloc(size + UDF_EXTFENTRY_SIZE, M_UDFFENTRY, M_NOWAIT | M_ZERO); if (up->u_fentry == NULL) { pool_put(&unode_pool, up); if (bp != NULL) brelse(bp); return (ENOMEM); /* Cannot allocate file entry block */ } if (udf_checktag(&xfe->tag, TAGID_EXTFENTRY) == 0) bcopy(bp->b_data, up->u_fentry, size + UDF_EXTFENTRY_SIZE); else bcopy(bp->b_data, up->u_fentry, size + UDF_FENTRY_SIZE); brelse(bp); bp = NULL; if ((error = udf_allocv(mp, &vp, p))) { free(up->u_fentry, M_UDFFENTRY); pool_put(&unode_pool, up); return (error); /* Error from udf_allocv() */ } up->u_vnode = vp; up->u_ino = ino; up->u_devvp = ump->um_devvp; up->u_dev = ump->um_dev; up->u_ump = ump; vp->v_data = up; vref(ump->um_devvp); lockinit(&up->u_lock, PINOD, "unode", 0, 0); /* * udf_hashins() will lock the vnode for us. */ udf_hashins(up); switch (up->u_fentry->icbtag.file_type) { default: printf("Unrecognized file type (%d)\n", vp->v_type); vp->v_type = VREG; break; case UDF_ICB_FILETYPE_DIRECTORY: vp->v_type = VDIR; break; case UDF_ICB_FILETYPE_BLOCKDEVICE: vp->v_type = VBLK; break; case UDF_ICB_FILETYPE_CHARDEVICE: vp->v_type = VCHR; break; case UDF_ICB_FILETYPE_FIFO: vp->v_type = VFIFO; break; case UDF_ICB_FILETYPE_SOCKET: vp->v_type = VSOCK; break; case UDF_ICB_FILETYPE_SYMLINK: vp->v_type = VLNK; break; case UDF_ICB_FILETYPE_RANDOMACCESS: case UDF_ICB_FILETYPE_REALTIME: case UDF_ICB_FILETYPE_UNKNOWN: vp->v_type = VREG; break; } /* check if this is a vnode alias */ if ((nvp = checkalias(vp, up->u_dev, ump->um_mountp)) != NULL) { printf("found a vnode alias\n"); /* * Discard unneeded vnode, but save its udf_node. * Note that the lock is carried over in the udf_node */ nvp->v_data = vp->v_data; vp->v_data = NULL; vp->v_op = spec_vnodeop_p; vrele(vp); vgone(vp); /* * Reinitialize aliased inode. */ vp = nvp; ump->um_devvp = vp; } *vpp = vp; return (0); }
int udf_vget(struct mount *mp, ino_t ino, struct vnode **vpp) { struct buf *bp; struct vnode *devvp; struct umount *ump; struct proc *p; struct vnode *vp; struct unode *up; struct file_entry *fe; int error, sector, size; p = curproc; bp = NULL; *vpp = NULL; ump = VFSTOUDFFS(mp); /* See if we already have this in the cache */ if ((error = udf_hashlookup(ump, ino, LK_EXCLUSIVE, vpp)) != 0) return (error); if (*vpp != NULL) return (0); /* * Allocate memory and check the tag id's before grabbing a new * vnode, since it's hard to roll back if there is a problem. */ up = pool_get(&unode_pool, PR_WAITOK); bzero(up, sizeof(struct unode)); /* * Copy in the file entry. Per the spec, the size can only be 1 block. */ sector = ino; devvp = ump->um_devvp; udf_vat_map(ump, §or); if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) { printf("Cannot read sector %d\n", sector); pool_put(&unode_pool, up); if (bp != NULL) brelse(bp); return (error); } fe = (struct file_entry *)bp->b_data; if (udf_checktag(&fe->tag, TAGID_FENTRY)) { printf("Invalid file entry!\n"); pool_put(&unode_pool, up); brelse(bp); return (ENOMEM); } size = UDF_FENTRY_SIZE + letoh32(fe->l_ea) + letoh32(fe->l_ad); up->u_fentry = malloc(size, M_UDFFENTRY, M_NOWAIT); if (up->u_fentry == NULL) { pool_put(&unode_pool, up); brelse(bp); return (ENOMEM); /* Cannot allocate file entry block */ } bcopy(bp->b_data, up->u_fentry, size); brelse(bp); bp = NULL; if ((error = udf_allocv(mp, &vp, p))) { free(up->u_fentry, M_UDFFENTRY); pool_put(&unode_pool, up); return (error); /* Error from udf_allocv() */ } up->u_vnode = vp; up->u_ino = ino; up->u_devvp = ump->um_devvp; up->u_dev = ump->um_dev; up->u_ump = ump; vp->v_data = up; VREF(ump->um_devvp); lockinit(&up->u_lock, PINOD, "unode", 0, 0); /* * udf_hashins() will lock the vnode for us. */ udf_hashins(up); switch (up->u_fentry->icbtag.file_type) { default: vp->v_type = VBAD; break; case UDF_ICB_TYPE_DIR: vp->v_type = VDIR; break; case UDF_ICB_TYPE_FILE: vp->v_type = VREG; break; case UDF_ICB_TYPE_BLKDEV: vp->v_type = VBLK; break; case UDF_ICB_TYPE_CHRDEV: vp->v_type = VCHR; break; case UDF_ICB_TYPE_FIFO: vp->v_type = VFIFO; break; case UDF_ICB_TYPE_SOCKET: vp->v_type = VSOCK; break; case UDF_ICB_TYPE_SYMLINK: vp->v_type = VLNK; break; case UDF_ICB_TYPE_VAT_150: vp->v_type = VREG; break; } *vpp = vp; return (0); }