Changeset View
Changeset View
Standalone View
Standalone View
fuse_vnops.c
Context not available. | |||||
#include <sys/bio.h> | #include <sys/bio.h> | ||||
#include <sys/buf.h> | #include <sys/buf.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/extattr.h> | |||||
#include <vm/vm.h> | #include <vm/vm.h> | ||||
#include <vm/vm_extern.h> | #include <vm/vm_extern.h> | ||||
Context not available. | |||||
static vop_getpages_t fuse_vnop_getpages; | static vop_getpages_t fuse_vnop_getpages; | ||||
static vop_putpages_t fuse_vnop_putpages; | static vop_putpages_t fuse_vnop_putpages; | ||||
static vop_print_t fuse_vnop_print; | static vop_print_t fuse_vnop_print; | ||||
static vop_getextattr_t fuse_vnop_getextattr; | |||||
static vop_setextattr_t fuse_vnop_setextattr; | |||||
static vop_listextattr_t fuse_vnop_listextattr; | |||||
static vop_deleteextattr_t fuse_vnop_deleteextattr; | |||||
struct vop_vector fuse_vnops = { | struct vop_vector fuse_vnops = { | ||||
.vop_default = &default_vnodeops, | .vop_default = &default_vnodeops, | ||||
Context not available. | |||||
.vop_getpages = fuse_vnop_getpages, | .vop_getpages = fuse_vnop_getpages, | ||||
.vop_putpages = fuse_vnop_putpages, | .vop_putpages = fuse_vnop_putpages, | ||||
.vop_print = fuse_vnop_print, | .vop_print = fuse_vnop_print, | ||||
.vop_getextattr = fuse_vnop_getextattr, | |||||
.vop_setextattr = fuse_vnop_setextattr, | |||||
.vop_listextattr = fuse_vnop_listextattr, | |||||
.vop_deleteextattr = fuse_vnop_deleteextattr, | |||||
}; | }; | ||||
static u_long fuse_lookup_cache_hits = 0; | static u_long fuse_lookup_cache_hits = 0; | ||||
Context not available. | |||||
return 0; | return 0; | ||||
} | } | ||||
/* | |||||
struct vop_getextattr_args { | |||||
struct vnode *a_vp; | |||||
int a_attrnamespace; | |||||
const char *a_name; | |||||
struct uio *a_uio; | |||||
size_t *a_size; | |||||
struct ucred *a_cred; | |||||
struct thread *a_td; | |||||
}; | |||||
*/ | |||||
static int | |||||
fuse_vnop_getextattr(struct vop_getextattr_args *ap) | |||||
{ | |||||
struct vnode *vp = ap->a_vp; | |||||
struct uio *uio = ap->a_uio; | |||||
struct fuse_dispatcher fdi; | |||||
struct fuse_getxattr_in *fgin; | |||||
struct fuse_getxattr_out *fgout; | |||||
int err = 0; | |||||
size_t len; | |||||
FS_DEBUG2G("inode=%ju\n", (uintmax_t)VTOI(vp)); | |||||
/* Fuse only supports one attribute name space, so make it "user". */ | |||||
if (ap->a_attrnamespace != EXTATTR_NAMESPACE_USER) | |||||
return (ENOATTR); | |||||
if (fuse_isdeadfs(vp) != 0) | |||||
return (ENXIO); | |||||
len = strlen(ap->a_name); | |||||
fdisp_init(&fdi, sizeof(struct fuse_getxattr_in) + len + 1); | |||||
fdisp_make_vp(&fdi, FUSE_GETXATTR, vp, curthread, ap->a_cred); | |||||
fgin = (struct fuse_getxattr_in *)fdi.indata; | |||||
if (uio != NULL) | |||||
fgin->size = uio->uio_resid; | |||||
else if (ap->a_size != NULL) | |||||
fgin->size = 0; | |||||
else { | |||||
err = EPERM; | |||||
goto out; | |||||
} | |||||
fgin++; | |||||
memcpy(fgin, ap->a_name, len + 1); | |||||
err = fdisp_wait_answ(&fdi); | |||||
if (err != 0) | |||||
goto out; | |||||
if (uio != NULL) { | |||||
if (ap->a_size != NULL) | |||||
*ap->a_size = fdi.iosize; | |||||
if (fdi.iosize > 0) | |||||
err = uiomove(fdi.answ, fdi.iosize, uio); | |||||
} else if (ap->a_size != NULL) { | |||||
/* When size is set to 0, it returns the size. */ | |||||
fgout = (struct fuse_getxattr_out *)fdi.answ; | |||||
*ap->a_size = fgout->size; | |||||
} | |||||
out: | |||||
fdisp_destroy(&fdi); | |||||
return (err); | |||||
} | |||||
/* | |||||
struct vop_setextattr_args { | |||||
struct vop_generic_args a_gen; | |||||
struct vnode *a_vp; | |||||
int a_attrnamespace; | |||||
const char *a_name; | |||||
struct uio *a_uio; | |||||
struct ucred *a_cred; | |||||
struct thread *a_td; | |||||
}; | |||||
*/ | |||||
static int | |||||
fuse_vnop_setextattr(struct vop_setextattr_args *ap) | |||||
{ | |||||
struct vnode *vp = ap->a_vp; | |||||
struct uio *uio = ap->a_uio; | |||||
struct fuse_dispatcher fdi; | |||||
struct fuse_setxattr_in *fsin; | |||||
int err = 0; | |||||
size_t len; | |||||
char *cp; | |||||
FS_DEBUG2G("inode=%ju\n", (uintmax_t)VTOI(vp)); | |||||
/* Fuse only supports one attribute name space, so make it "user". */ | |||||
if (ap->a_attrnamespace != EXTATTR_NAMESPACE_USER) | |||||
return (ENOATTR); | |||||
if (fuse_isdeadfs(vp) != 0) | |||||
return (ENXIO); | |||||
len = strlen(ap->a_name); | |||||
fdisp_init(&fdi, sizeof(struct fuse_setxattr_in) + len + 1 + | |||||
uio->uio_resid); | |||||
fdisp_make_vp(&fdi, FUSE_SETXATTR, vp, curthread, ap->a_cred); | |||||
fsin = (struct fuse_setxattr_in *)fdi.indata; | |||||
fsin->size = uio->uio_resid; | |||||
fsin->flags = 0; | |||||
fsin++; | |||||
cp = (char *)fsin; | |||||
memcpy(cp, ap->a_name, len + 1); | |||||
cp += len + 1; | |||||
err = uiomove(cp, uio->uio_resid, uio); | |||||
if (err != 0) | |||||
goto out; | |||||
err = fdisp_wait_answ(&fdi); | |||||
out: | |||||
fdisp_destroy(&fdi); | |||||
return (err); | |||||
} | |||||
/* | |||||
struct vop_listextattr_args { | |||||
struct vop_generic_args a_gen; | |||||
struct vnode *a_vp; | |||||
int a_attrnamespace; | |||||
struct uio *a_uio; | |||||
size_t *a_size; | |||||
struct ucred *a_cred; | |||||
struct thread *a_td; | |||||
}; | |||||
*/ | |||||
static int | |||||
fuse_vnop_listextattr(struct vop_listextattr_args *ap) | |||||
{ | |||||
struct vnode *vp = ap->a_vp; | |||||
struct uio *uio = ap->a_uio; | |||||
struct fuse_dispatcher fdi; | |||||
struct fuse_getxattr_in *fgin; | |||||
struct fuse_getxattr_out *fgout; | |||||
int err = 0; | |||||
FS_DEBUG2G("inode=%ju\n", (uintmax_t)VTOI(vp)); | |||||
/* Fuse only supports one attribute name space, so make it "user". */ | |||||
if (ap->a_attrnamespace != EXTATTR_NAMESPACE_USER) | |||||
return (ENOATTR); | |||||
if (fuse_isdeadfs(vp) != 0) | |||||
return (ENXIO); | |||||
fdisp_init(&fdi, sizeof(struct fuse_getxattr_in)); | |||||
fdisp_make_vp(&fdi, FUSE_LISTXATTR, vp, curthread, ap->a_cred); | |||||
fgin = (struct fuse_getxattr_in *)fdi.indata; | |||||
if (uio != NULL) | |||||
fgin->size = uio->uio_resid; | |||||
else if (ap->a_size != NULL) | |||||
fgin->size = 0; | |||||
else { | |||||
err = EPERM; | |||||
goto out; | |||||
} | |||||
err = fdisp_wait_answ(&fdi); | |||||
if (err != 0) | |||||
goto out; | |||||
if (uio != NULL) { | |||||
if (ap->a_size != NULL) | |||||
*ap->a_size = fdi.iosize; | |||||
if (fdi.iosize > 0) | |||||
err = uiomove(fdi.answ, fdi.iosize, uio); | |||||
} else if (ap->a_size != NULL) { | |||||
/* When size is set to 0, it returns the size. */ | |||||
fgout = (struct fuse_getxattr_out *)fdi.answ; | |||||
*ap->a_size = fgout->size; | |||||
} | |||||
out: | |||||
fdisp_destroy(&fdi); | |||||
return (err); | |||||
} | |||||
/* | |||||
struct vop_deleteextattr_args { | |||||
struct vop_generic_args a_gen; | |||||
struct vnode *a_vp; | |||||
int a_attrnamespace; | |||||
const char *a_name; | |||||
struct ucred *a_cred; | |||||
struct thread *a_td; | |||||
}; | |||||
*/ | |||||
static int | |||||
fuse_vnop_deleteextattr(struct vop_deleteextattr_args *ap) | |||||
{ | |||||
struct vnode *vp = ap->a_vp; | |||||
struct fuse_dispatcher fdi; | |||||
int err = 0; | |||||
size_t len; | |||||
char *cp; | |||||
FS_DEBUG2G("inode=%ju\n", (uintmax_t)VTOI(vp)); | |||||
/* Fuse only supports one attribute name space, so make it "user". */ | |||||
if (ap->a_attrnamespace != EXTATTR_NAMESPACE_USER) | |||||
return (ENOATTR); | |||||
if (fuse_isdeadfs(vp) != 0) | |||||
return (ENXIO); | |||||
len = strlen(ap->a_name); | |||||
fdisp_init(&fdi, len + 1); | |||||
fdisp_make_vp(&fdi, FUSE_REMOVEXATTR, vp, curthread, ap->a_cred); | |||||
cp = (char *)fdi.indata; | |||||
memcpy(cp, ap->a_name, len + 1); | |||||
err = fdisp_wait_answ(&fdi); | |||||
fdisp_destroy(&fdi); | |||||
return (err); | |||||
} | |||||
Context not available. |