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:
Pawel Jakub Dawidek
2024-05-19 01:08:41 +00:00
parent d76ef58d56
commit 56a8aca83a
6 changed files with 51 additions and 18 deletions
+1 -1
View File
@@ -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);
}
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
View File
@@ -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;
+7
View File
@@ -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
View File
@@ -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)
{