Extend kobj compatibility KPI to support operating on files before and

after the root file system is mounted.
This is one of the changes that will allow to put root file system on ZFS.
This commit is contained in:
pjd 2007-04-08 23:57:08 +00:00
parent f0a2e6d38c
commit e47fb9eabd
4 changed files with 206 additions and 34 deletions

View File

@ -30,12 +30,13 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h> #include <sys/types.h>
#include <sys/systm.h> #include <sys/systm.h>
#include <sys/kernel.h> #include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/kthread.h> #include <sys/kthread.h>
#include <sys/namei.h> #include <sys/namei.h>
#include <sys/proc.h> #include <sys/proc.h>
#include <sys/filedesc.h> #include <sys/filedesc.h>
#include <sys/vnode.h>
#include <sys/fcntl.h> #include <sys/fcntl.h>
#include <sys/linker.h>
#include <sys/kobj.h> #include <sys/kobj.h>
void void
@ -62,8 +63,8 @@ kobj_zalloc(size_t size, int flag)
return (p); return (p);
} }
struct _buf * static void *
kobj_open_file(const char *file) kobj_open_file_vnode(const char *file)
{ {
struct thread *td = curthread; struct thread *td = curthread;
struct nameidata nd; struct nameidata nd;
@ -79,16 +80,45 @@ kobj_open_file(const char *file)
error = vn_open_cred(&nd, &flags, 0, td->td_ucred, -1); error = vn_open_cred(&nd, &flags, 0, td->td_ucred, -1);
NDFREE(&nd, NDF_ONLY_PNBUF); NDFREE(&nd, NDF_ONLY_PNBUF);
if (error != 0) if (error != 0)
return ((struct _buf *)-1); return (NULL);
/* We just unlock so we hold a reference. */ /* We just unlock so we hold a reference. */
VOP_UNLOCK(nd.ni_vp, 0, td); VOP_UNLOCK(nd.ni_vp, 0, td);
return ((struct _buf *)nd.ni_vp); return (nd.ni_vp);
} }
int static void *
kobj_get_filesize(struct _buf *file, uint64_t *size) kobj_open_file_loader(const char *file)
{ {
struct vnode *vp = (struct vnode *)file;
return (preload_search_by_name(file));
}
struct _buf *
kobj_open_file(const char *file)
{
struct _buf *out;
out = kmem_alloc(sizeof(*out), KM_SLEEP);
out->mounted = root_mounted();
/*
* If root is already mounted we read file using file system,
* if not, we use loader.
*/
if (out->mounted)
out->ptr = kobj_open_file_vnode(file);
else
out->ptr = kobj_open_file_loader(file);
if (out->ptr == NULL) {
kmem_free(out, sizeof(*out));
return ((struct _buf *)-1);
}
return (out);
}
static int
kobj_get_filesize_vnode(struct _buf *file, uint64_t *size)
{
struct vnode *vp = file->ptr;
struct thread *td = curthread; struct thread *td = curthread;
struct vattr va; struct vattr va;
int error; int error;
@ -101,10 +131,32 @@ kobj_get_filesize(struct _buf *file, uint64_t *size)
return (error); return (error);
} }
int static int
kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off) kobj_get_filesize_loader(struct _buf *file, uint64_t *size)
{ {
struct vnode *vp = (struct vnode *)file; void *ptr;
ptr = preload_search_info(file->ptr, MODINFO_SIZE);
if (ptr == NULL)
return (ENOENT);
*size = (uint64_t)*(size_t *)ptr;
return (0);
}
int
kobj_get_filesize(struct _buf *file, uint64_t *size)
{
if (file->mounted)
return (kobj_get_filesize_vnode(file, size));
else
return (kobj_get_filesize_loader(file, size));
}
int
kobj_read_file_vnode(struct _buf *file, char *buf, unsigned size, unsigned off)
{
struct vnode *vp = file->ptr;
struct thread *td = curthread; struct thread *td = curthread;
struct uio auio; struct uio auio;
struct iovec aiov; struct iovec aiov;
@ -130,13 +182,39 @@ kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
return (error != 0 ? -1 : size - auio.uio_resid); return (error != 0 ? -1 : size - auio.uio_resid);
} }
int
kobj_read_file_loader(struct _buf *file, char *buf, unsigned size, unsigned off)
{
char *ptr;
ptr = preload_search_info(file->ptr, MODINFO_ADDR);
if (ptr == NULL)
return (ENOENT);
ptr = *(void **)ptr;
bcopy(ptr + off, buf, size);
return (0);
}
int
kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
{
if (file->mounted)
return (kobj_read_file_vnode(file, buf, size, off));
else
return (kobj_read_file_loader(file, buf, size, off));
}
void void
kobj_close_file(struct _buf *file) kobj_close_file(struct _buf *file)
{ {
struct vnode *vp = (struct vnode *)file;
struct thread *td = curthread;
int flags;
flags = FREAD; if (file->mounted) {
vn_close(vp, flags, td->td_ucred, td); struct vnode *vp = file->ptr;
struct thread *td = curthread;
int flags = FREAD;
vn_close(vp, flags, td->td_ucred, td);
}
kmem_free(file, sizeof(*file));
} }

View File

@ -31,6 +31,13 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/kmem.h> #include <sys/kmem.h>
#include_next <sys/kobj.h>
#ifdef AT_UID
#undef AT_UID
#endif
#ifdef AT_GID
#undef AT_GID
#endif
#include <sys/vnode.h> #include <sys/vnode.h>
#define KM_NOWAIT 0x01 #define KM_NOWAIT 0x01
@ -41,7 +48,8 @@ void *kobj_alloc(size_t size, int flag);
void *kobj_zalloc(size_t size, int flag); void *kobj_zalloc(size_t size, int flag);
struct _buf { struct _buf {
void *dummy; void *ptr;
int mounted;
}; };
struct _buf *kobj_open_file(const char *path); struct _buf *kobj_open_file(const char *path);

View File

@ -30,12 +30,13 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h> #include <sys/types.h>
#include <sys/systm.h> #include <sys/systm.h>
#include <sys/kernel.h> #include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/kthread.h> #include <sys/kthread.h>
#include <sys/namei.h> #include <sys/namei.h>
#include <sys/proc.h> #include <sys/proc.h>
#include <sys/filedesc.h> #include <sys/filedesc.h>
#include <sys/vnode.h>
#include <sys/fcntl.h> #include <sys/fcntl.h>
#include <sys/linker.h>
#include <sys/kobj.h> #include <sys/kobj.h>
void void
@ -62,8 +63,8 @@ kobj_zalloc(size_t size, int flag)
return (p); return (p);
} }
struct _buf * static void *
kobj_open_file(const char *file) kobj_open_file_vnode(const char *file)
{ {
struct thread *td = curthread; struct thread *td = curthread;
struct nameidata nd; struct nameidata nd;
@ -79,16 +80,45 @@ kobj_open_file(const char *file)
error = vn_open_cred(&nd, &flags, 0, td->td_ucred, -1); error = vn_open_cred(&nd, &flags, 0, td->td_ucred, -1);
NDFREE(&nd, NDF_ONLY_PNBUF); NDFREE(&nd, NDF_ONLY_PNBUF);
if (error != 0) if (error != 0)
return ((struct _buf *)-1); return (NULL);
/* We just unlock so we hold a reference. */ /* We just unlock so we hold a reference. */
VOP_UNLOCK(nd.ni_vp, 0, td); VOP_UNLOCK(nd.ni_vp, 0, td);
return ((struct _buf *)nd.ni_vp); return (nd.ni_vp);
} }
int static void *
kobj_get_filesize(struct _buf *file, uint64_t *size) kobj_open_file_loader(const char *file)
{ {
struct vnode *vp = (struct vnode *)file;
return (preload_search_by_name(file));
}
struct _buf *
kobj_open_file(const char *file)
{
struct _buf *out;
out = kmem_alloc(sizeof(*out), KM_SLEEP);
out->mounted = root_mounted();
/*
* If root is already mounted we read file using file system,
* if not, we use loader.
*/
if (out->mounted)
out->ptr = kobj_open_file_vnode(file);
else
out->ptr = kobj_open_file_loader(file);
if (out->ptr == NULL) {
kmem_free(out, sizeof(*out));
return ((struct _buf *)-1);
}
return (out);
}
static int
kobj_get_filesize_vnode(struct _buf *file, uint64_t *size)
{
struct vnode *vp = file->ptr;
struct thread *td = curthread; struct thread *td = curthread;
struct vattr va; struct vattr va;
int error; int error;
@ -101,10 +131,32 @@ kobj_get_filesize(struct _buf *file, uint64_t *size)
return (error); return (error);
} }
int static int
kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off) kobj_get_filesize_loader(struct _buf *file, uint64_t *size)
{ {
struct vnode *vp = (struct vnode *)file; void *ptr;
ptr = preload_search_info(file->ptr, MODINFO_SIZE);
if (ptr == NULL)
return (ENOENT);
*size = (uint64_t)*(size_t *)ptr;
return (0);
}
int
kobj_get_filesize(struct _buf *file, uint64_t *size)
{
if (file->mounted)
return (kobj_get_filesize_vnode(file, size));
else
return (kobj_get_filesize_loader(file, size));
}
int
kobj_read_file_vnode(struct _buf *file, char *buf, unsigned size, unsigned off)
{
struct vnode *vp = file->ptr;
struct thread *td = curthread; struct thread *td = curthread;
struct uio auio; struct uio auio;
struct iovec aiov; struct iovec aiov;
@ -130,13 +182,39 @@ kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
return (error != 0 ? -1 : size - auio.uio_resid); return (error != 0 ? -1 : size - auio.uio_resid);
} }
int
kobj_read_file_loader(struct _buf *file, char *buf, unsigned size, unsigned off)
{
char *ptr;
ptr = preload_search_info(file->ptr, MODINFO_ADDR);
if (ptr == NULL)
return (ENOENT);
ptr = *(void **)ptr;
bcopy(ptr + off, buf, size);
return (0);
}
int
kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
{
if (file->mounted)
return (kobj_read_file_vnode(file, buf, size, off));
else
return (kobj_read_file_loader(file, buf, size, off));
}
void void
kobj_close_file(struct _buf *file) kobj_close_file(struct _buf *file)
{ {
struct vnode *vp = (struct vnode *)file;
struct thread *td = curthread;
int flags;
flags = FREAD; if (file->mounted) {
vn_close(vp, flags, td->td_ucred, td); struct vnode *vp = file->ptr;
struct thread *td = curthread;
int flags = FREAD;
vn_close(vp, flags, td->td_ucred, td);
}
kmem_free(file, sizeof(*file));
} }

View File

@ -31,6 +31,13 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/kmem.h> #include <sys/kmem.h>
#include_next <sys/kobj.h>
#ifdef AT_UID
#undef AT_UID
#endif
#ifdef AT_GID
#undef AT_GID
#endif
#include <sys/vnode.h> #include <sys/vnode.h>
#define KM_NOWAIT 0x01 #define KM_NOWAIT 0x01
@ -41,7 +48,8 @@ void *kobj_alloc(size_t size, int flag);
void *kobj_zalloc(size_t size, int flag); void *kobj_zalloc(size_t size, int flag);
struct _buf { struct _buf {
void *dummy; void *ptr;
int mounted;
}; };
struct _buf *kobj_open_file(const char *path); struct _buf *kobj_open_file(const char *path);