Stop treating size 0 as unknown size in vnode_create_vobject().
Whenever file is created, the vnode_create_vobject() function will try to determine its size by calling vn_getsize_locked() as size 0 is ambigious: it means either the file size is 0 or the file size is unknown. Introduce special value for the size argument: VNODE_NO_SIZE. Only when it is given, the vnode_create_vobject() will try to obtain file's size on its own. Introduce dedicated vnode_disk_create_vobject() for use by g_vfs_open(), so we don't have to call vn_isdisk() in the common case (for regular files). Handle the case of mediasize==0 in g_vfs_open(). Reviewed by: alc, kib, markj, olce Approved by: oshogbo (mentor), allanjude (mentor) Differential Revision: https://reviews.freebsd.org/D45244
This commit is contained in:
@@ -1345,7 +1345,7 @@ ext2_fhtovp(struct mount *mp, struct fid *fhp, int flags, struct vnode **vpp)
|
||||
return (ESTALE);
|
||||
}
|
||||
*vpp = nvp;
|
||||
vnode_create_vobject(*vpp, 0, curthread);
|
||||
vnode_create_vobject(*vpp, ip->i_size, curthread);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
@@ -354,7 +354,7 @@ void
|
||||
fuse_vnode_open(struct vnode *vp, int32_t fuse_open_flags, struct thread *td)
|
||||
{
|
||||
if (vnode_vtype(vp) == VREG)
|
||||
vnode_create_vobject(vp, 0, td);
|
||||
vnode_create_vobject(vp, VNODE_NO_SIZE, td);
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -286,7 +286,7 @@ fuse_vfsop_fhtovp(struct mount *mp, struct fid *fhp, int flags,
|
||||
return (ESTALE);
|
||||
}
|
||||
*vpp = nvp;
|
||||
vnode_create_vobject(*vpp, 0, curthread);
|
||||
vnode_create_vobject(*vpp, VNODE_NO_SIZE, curthread);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
+10
-1
@@ -292,7 +292,16 @@ g_vfs_open(struct vnode *vp, struct g_consumer **cpp, const char *fsname, int wr
|
||||
g_wither_geom(gp, ENXIO);
|
||||
return (error);
|
||||
}
|
||||
vnode_create_vobject(vp, pp->mediasize, curthread);
|
||||
/*
|
||||
* Mediasize might not be set until first access (see g_disk_access()),
|
||||
* That's why we check it here and not earlier.
|
||||
*/
|
||||
if (pp->mediasize == 0) {
|
||||
(void)g_access(cp, -1, -wr, -wr);
|
||||
g_wither_geom(gp, ENXIO);
|
||||
return (ENXIO);
|
||||
}
|
||||
vnode_create_disk_vobject(vp, pp->mediasize, curthread);
|
||||
*cpp = cp;
|
||||
cp->private = vp;
|
||||
cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE;
|
||||
|
||||
@@ -1081,7 +1081,14 @@ vrefcnt(struct vnode *vp)
|
||||
vref(vp); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* The caller doesn't know the file size and vnode_create_vobject() should
|
||||
* determine the size on its own.
|
||||
*/
|
||||
#define VNODE_NO_SIZE ((off_t)-1)
|
||||
|
||||
int vnode_create_vobject(struct vnode *vp, off_t size, struct thread *td);
|
||||
int vnode_create_disk_vobject(struct vnode *vp, off_t size, struct thread *td);
|
||||
void vnode_destroy_vobject(struct vnode *vp);
|
||||
|
||||
extern struct vop_vector fifo_specops;
|
||||
|
||||
+31
-14
@@ -146,27 +146,22 @@ vnode_pager_init(void *dummy)
|
||||
SYSINIT(vnode_pager, SI_SUB_CPU, SI_ORDER_ANY, vnode_pager_init, NULL);
|
||||
|
||||
/* Create the VM system backing object for this vnode */
|
||||
int
|
||||
vnode_create_vobject(struct vnode *vp, off_t isize, struct thread *td)
|
||||
static int
|
||||
vnode_create_vobject_any(struct vnode *vp, off_t isize, struct thread *td)
|
||||
{
|
||||
vm_object_t object;
|
||||
vm_ooffset_t size = isize;
|
||||
vm_ooffset_t size;
|
||||
bool last;
|
||||
|
||||
if (!vn_isdisk(vp) && vn_canvmio(vp) == FALSE)
|
||||
return (0);
|
||||
|
||||
object = vp->v_object;
|
||||
if (object != NULL)
|
||||
return (0);
|
||||
|
||||
if (size == 0) {
|
||||
if (vn_isdisk(vp)) {
|
||||
size = IDX_TO_OFF(INT_MAX);
|
||||
} else {
|
||||
if (vn_getsize_locked(vp, &size, td->td_ucred) != 0)
|
||||
return (0);
|
||||
}
|
||||
if (isize == VNODE_NO_SIZE) {
|
||||
if (vn_getsize_locked(vp, &size, td->td_ucred) != 0)
|
||||
return (0);
|
||||
} else {
|
||||
size = isize;
|
||||
}
|
||||
|
||||
object = vnode_pager_alloc(vp, size, 0, 0, td->td_ucred);
|
||||
@@ -182,11 +177,33 @@ vnode_create_vobject(struct vnode *vp, off_t isize, struct thread *td)
|
||||
if (last)
|
||||
vrele(vp);
|
||||
|
||||
KASSERT(vp->v_object != NULL, ("vnode_create_vobject: NULL object"));
|
||||
VNASSERT(vp->v_object != NULL, vp, ("%s: NULL object", __func__));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
vnode_create_vobject(struct vnode *vp, off_t isize, struct thread *td)
|
||||
{
|
||||
VNASSERT(!vn_isdisk(vp), vp, ("%s: disk vnode", __func__));
|
||||
VNASSERT(isize == VNODE_NO_SIZE || isize >= 0, vp,
|
||||
("%s: invalid size (%jd)", __func__, (intmax_t)isize));
|
||||
|
||||
if (!vn_canvmio(vp))
|
||||
return (0);
|
||||
|
||||
return (vnode_create_vobject_any(vp, isize, td));
|
||||
}
|
||||
|
||||
int
|
||||
vnode_create_disk_vobject(struct vnode *vp, off_t isize, struct thread *td)
|
||||
{
|
||||
VNASSERT(isize > 0, vp, ("%s: invalid size (%jd)", __func__,
|
||||
(intmax_t)isize));
|
||||
|
||||
return (vnode_create_vobject_any(vp, isize, td));
|
||||
}
|
||||
|
||||
void
|
||||
vnode_destroy_vobject(struct vnode *vp)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user