Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/unionfs/union_vfsops.c
Show First 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Mount unionfs layer. | * Mount unionfs layer. | ||||
*/ | */ | ||||
static int | static int | ||||
unionfs_domount(struct mount *mp) | unionfs_domount(struct mount *mp) | ||||
{ | { | ||||
int error; | int error; | ||||
struct mount *lowermp, *uppermp; | |||||
struct vnode *lowerrootvp; | struct vnode *lowerrootvp; | ||||
struct vnode *upperrootvp; | struct vnode *upperrootvp; | ||||
struct unionfs_mount *ump; | struct unionfs_mount *ump; | ||||
struct thread *td; | struct thread *td; | ||||
char *target; | char *target; | ||||
char *tmp; | char *tmp; | ||||
char *ep; | char *ep; | ||||
int len; | int len; | ||||
int below; | int below; | ||||
uid_t uid; | uid_t uid; | ||||
gid_t gid; | gid_t gid; | ||||
u_short udir; | u_short udir; | ||||
▲ Show 20 Lines • Show All 190 Lines • ▼ Show 20 Lines | unionfs_domount(struct mount *mp) | ||||
VOP_UNLOCK(ump->um_uppervp); | VOP_UNLOCK(ump->um_uppervp); | ||||
/* | /* | ||||
* Get the unionfs root vnode. | * Get the unionfs root vnode. | ||||
*/ | */ | ||||
error = unionfs_nodeget(mp, ump->um_uppervp, ump->um_lowervp, | error = unionfs_nodeget(mp, ump->um_uppervp, ump->um_lowervp, | ||||
NULLVP, &(ump->um_rootvp), NULL, td); | NULLVP, &(ump->um_rootvp), NULL, td); | ||||
vrele(upperrootvp); | vrele(upperrootvp); | ||||
if (error) { | if (error != 0) | ||||
free(ump, M_UNIONFSMNT); | goto unionfs_domount_cleanup; | ||||
mp->mnt_data = NULL; | |||||
return (error); | |||||
} | |||||
lowermp = unionfs_mount_trybusy(ump->um_lowervp); | |||||
uppermp = unionfs_mount_trybusy(ump->um_uppervp); | |||||
if (lowermp == NULL || uppermp == NULL) | |||||
error = ENOENT; | |||||
else { | |||||
MNT_ILOCK(mp); | MNT_ILOCK(mp); | ||||
if ((ump->um_lowervp->v_mount->mnt_flag & MNT_LOCAL) && | if ((lowermp->mnt_flag & MNT_LOCAL) != 0 && | ||||
kib: != 0 there and next line | |||||
(ump->um_uppervp->v_mount->mnt_flag & MNT_LOCAL)) | (uppermp->mnt_flag & MNT_LOCAL) != 0) | ||||
mp->mnt_flag |= MNT_LOCAL; | mp->mnt_flag |= MNT_LOCAL; | ||||
mp->mnt_kern_flag |= MNTK_NOMSYNC | MNTK_UNIONFS; | mp->mnt_kern_flag |= MNTK_NOMSYNC | MNTK_UNIONFS; | ||||
MNT_IUNLOCK(mp); | MNT_IUNLOCK(mp); | ||||
} | |||||
unionfs_mount_unbusy(uppermp); | |||||
unionfs_mount_unbusy(lowermp); | |||||
if (error != 0) | |||||
goto unionfs_domount_cleanup; | |||||
/* | /* | ||||
* Get new fsid | * Get new fsid | ||||
*/ | */ | ||||
vfs_getnewfsid(mp); | vfs_getnewfsid(mp); | ||||
snprintf(mp->mnt_stat.f_mntfromname, MNAMELEN, "<%s>:%s", | snprintf(mp->mnt_stat.f_mntfromname, MNAMELEN, "<%s>:%s", | ||||
below ? "below" : "above", target); | below ? "below" : "above", target); | ||||
UNIONFSDEBUG("unionfs_mount: from %s, on %s\n", | UNIONFSDEBUG("unionfs_mount: from %s, on %s\n", | ||||
mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname); | mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname); | ||||
return (0); | return (0); | ||||
unionfs_domount_cleanup: | |||||
free(ump, M_UNIONFSMNT); | |||||
mp->mnt_data = NULL; | |||||
return (error); | |||||
} | } | ||||
/* | /* | ||||
* Free reference to unionfs layer | * Free reference to unionfs layer | ||||
*/ | */ | ||||
static int | static int | ||||
unionfs_unmount(struct mount *mp, int mntflags) | unionfs_unmount(struct mount *mp, int mntflags) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | unionfs_root(struct mount *mp, int flags, struct vnode **vpp) | ||||
*vpp = vp; | *vpp = vp; | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
unionfs_quotactl(struct mount *mp, int cmd, uid_t uid, void *arg) | unionfs_quotactl(struct mount *mp, int cmd, uid_t uid, void *arg) | ||||
{ | { | ||||
struct mount *uppermp; | |||||
struct unionfs_mount *ump; | struct unionfs_mount *ump; | ||||
int error; | |||||
ump = MOUNTTOUNIONFSMOUNT(mp); | ump = MOUNTTOUNIONFSMOUNT(mp); | ||||
uppermp = unionfs_mount_trybusy(ump->um_uppervp); | |||||
/* | /* | ||||
* Writing is always performed to upper vnode. | * Writing is always performed to upper vnode. | ||||
*/ | */ | ||||
return (VFS_QUOTACTL(ump->um_uppervp->v_mount, cmd, uid, arg)); | if (uppermp == NULL) | ||||
error = ENOENT; | |||||
else | |||||
error = VFS_QUOTACTL(uppermp, cmd, uid, arg); | |||||
unionfs_mount_unbusy(uppermp); | |||||
markjUnsubmitted Not Done Inline ActionsLooking at ufs_quotactl(), there are some specific cases where it unbusies the mount point itself. See also sys_quotactl(). Don't we need similar special casing here? markj: Looking at ufs_quotactl(), there are some specific cases where it unbusies the mount point… | |||||
jahAuthorUnsubmitted Done Inline ActionsOh yeah, I suspect you're right. I made a mental note to dig into that and then promptly forgot; I'll figure out what I need to do here when I get some time tomorrow. jah: Oh yeah, I suspect you're right. I made a mental note to dig into that and then promptly… | |||||
return (error); | |||||
} | } | ||||
static int | static int | ||||
unionfs_statfs(struct mount *mp, struct statfs *sbp) | unionfs_statfs(struct mount *mp, struct statfs *sbp) | ||||
{ | { | ||||
struct mount *lowermp, *uppermp; | |||||
struct unionfs_mount *ump; | struct unionfs_mount *ump; | ||||
int error; | int error; | ||||
struct statfs *mstat; | struct statfs *mstat; | ||||
uint64_t lbsize; | uint64_t lbsize; | ||||
ump = MOUNTTOUNIONFSMOUNT(mp); | ump = MOUNTTOUNIONFSMOUNT(mp); | ||||
UNIONFSDEBUG("unionfs_statfs(mp = %p, lvp = %p, uvp = %p)\n", | UNIONFSDEBUG("unionfs_statfs(mp = %p, lvp = %p, uvp = %p)\n", | ||||
(void *)mp, (void *)ump->um_lowervp, (void *)ump->um_uppervp); | (void *)mp, (void *)ump->um_lowervp, (void *)ump->um_uppervp); | ||||
mstat = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK | M_ZERO); | mstat = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK | M_ZERO); | ||||
error = VFS_STATFS(ump->um_lowervp->v_mount, mstat); | lowermp = unionfs_mount_trybusy(ump->um_lowervp); | ||||
if (lowermp != NULL) | |||||
error = VFS_STATFS(lowermp, mstat); | |||||
else | |||||
error = ENOENT; | |||||
unionfs_mount_unbusy(lowermp); | |||||
if (error) { | if (error) { | ||||
free(mstat, M_STATFS); | free(mstat, M_STATFS); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* now copy across the "interesting" information and fake the rest */ | /* now copy across the "interesting" information and fake the rest */ | ||||
sbp->f_blocks = mstat->f_blocks; | sbp->f_blocks = mstat->f_blocks; | ||||
sbp->f_files = mstat->f_files; | sbp->f_files = mstat->f_files; | ||||
lbsize = mstat->f_bsize; | lbsize = mstat->f_bsize; | ||||
error = VFS_STATFS(ump->um_uppervp->v_mount, mstat); | uppermp = unionfs_mount_trybusy(ump->um_uppervp); | ||||
if (uppermp != NULL) | |||||
error = VFS_STATFS(uppermp, mstat); | |||||
else | |||||
error = ENOENT; | |||||
unionfs_mount_unbusy(uppermp); | |||||
if (error) { | if (error) { | ||||
free(mstat, M_STATFS); | free(mstat, M_STATFS); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* The FS type etc is copy from upper vfs. | * The FS type etc is copy from upper vfs. | ||||
* (write able vfs have priority) | * (write able vfs have priority) | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
return (EOPNOTSUPP); | return (EOPNOTSUPP); | ||||
} | } | ||||
static int | static int | ||||
unionfs_extattrctl(struct mount *mp, int cmd, struct vnode *filename_vp, | unionfs_extattrctl(struct mount *mp, int cmd, struct vnode *filename_vp, | ||||
int namespace, const char *attrname) | int namespace, const char *attrname) | ||||
{ | { | ||||
struct mount *cmp; | |||||
struct unionfs_mount *ump; | struct unionfs_mount *ump; | ||||
struct unionfs_node *unp; | struct unionfs_node *unp; | ||||
struct vnode *vp, *mvp; | |||||
int error; | |||||
ump = MOUNTTOUNIONFSMOUNT(mp); | ump = MOUNTTOUNIONFSMOUNT(mp); | ||||
unp = VTOUNIONFS(filename_vp); | unp = VTOUNIONFS(filename_vp); | ||||
if (unp->un_uppervp != NULLVP) { | if (unp->un_uppervp != NULLVP) { | ||||
return (VFS_EXTATTRCTL(ump->um_uppervp->v_mount, cmd, | vp = unp->un_uppervp; | ||||
unp->un_uppervp, namespace, attrname)); | mvp = ump->um_uppervp; | ||||
} else { | } else { | ||||
return (VFS_EXTATTRCTL(ump->um_lowervp->v_mount, cmd, | vp = unp->un_lowervp; | ||||
unp->un_lowervp, namespace, attrname)); | mvp = ump->um_lowervp; | ||||
} | } | ||||
cmp = unionfs_mount_trybusy(mvp); | |||||
if (cmp == NULL) | |||||
error = ENOENT; | |||||
else | |||||
error = VFS_EXTATTRCTL(cmp, cmd, vp, namespace, attrname); | |||||
unionfs_mount_unbusy(cmp); | |||||
return (error); | |||||
} | } | ||||
static struct vfsops unionfs_vfsops = { | static struct vfsops unionfs_vfsops = { | ||||
.vfs_checkexp = unionfs_checkexp, | .vfs_checkexp = unionfs_checkexp, | ||||
.vfs_extattrctl = unionfs_extattrctl, | .vfs_extattrctl = unionfs_extattrctl, | ||||
.vfs_fhtovp = unionfs_fhtovp, | .vfs_fhtovp = unionfs_fhtovp, | ||||
.vfs_init = unionfs_init, | .vfs_init = unionfs_init, | ||||
.vfs_mount = unionfs_domount, | .vfs_mount = unionfs_domount, | ||||
Show All 10 Lines |
!= 0 there and next line