Implement new world order in VFS locking for extended attributes. This will

remove the unconditional acquisition of Giant for extended attribute related
operations. If the file system is set as being MP safe and debug.mpsafevfs is
1, do not pickup Giant.

Mark the following system calls as being MP safe so we no longer pickup Giant
in the system call handler:

o extattrctl
o extattr_set_file
o extattr_get_file
o extattr_delete_file
o extattr_set_fd
o extattr_get_fd
o extattr_delete_fd
o extattr_set_link
o extattr_get_link
o extattr_delete_link
o extattr_list_file
o extattr_list_link
o extattr_list_fd

-Pass MPSAFE flags to namei(9) lookup and introduce vfslocked variable which
 will keep track of any Giant acquisitions.
-Wrap any fd operations which manipulate vnodes in VFS_{UN}LOCK_GIANT
-Drop VFS_ASSERT_GIANT into function which operate on vnodes to ensure that
 we are sufficiently protected.

I've tested these changes with various TrustedBSD MAC policies which use
extended attribute a lot on SMP and UP systems (thanks to Scott Long for
making some SMP hardware available to me for testing).

Discussed with:	jeff
Requested by:	jhb, rwatson
This commit is contained in:
csjp 2005-09-24 23:47:04 +00:00
parent 3b94f1f114
commit 2c840e0d4e
3 changed files with 137 additions and 71 deletions

View File

@ -384,10 +384,10 @@ struct sysent sysent[] = {
{ SYF_MPSAFE | AS(__acl_delete_fd_args), (sy_call_t *)__acl_delete_fd, AUE_NULL }, /* 352 = __acl_delete_fd */
{ SYF_MPSAFE | AS(__acl_aclcheck_file_args), (sy_call_t *)__acl_aclcheck_file, AUE_NULL }, /* 353 = __acl_aclcheck_file */
{ SYF_MPSAFE | AS(__acl_aclcheck_fd_args), (sy_call_t *)__acl_aclcheck_fd, AUE_NULL }, /* 354 = __acl_aclcheck_fd */
{ AS(extattrctl_args), (sy_call_t *)extattrctl, AUE_NULL }, /* 355 = extattrctl */
{ AS(extattr_set_file_args), (sy_call_t *)extattr_set_file, AUE_NULL }, /* 356 = extattr_set_file */
{ AS(extattr_get_file_args), (sy_call_t *)extattr_get_file, AUE_NULL }, /* 357 = extattr_get_file */
{ AS(extattr_delete_file_args), (sy_call_t *)extattr_delete_file, AUE_NULL }, /* 358 = extattr_delete_file */
{ SYF_MPSAFE | AS(extattrctl_args), (sy_call_t *)extattrctl, AUE_NULL }, /* 355 = extattrctl */
{ SYF_MPSAFE | AS(extattr_set_file_args), (sy_call_t *)extattr_set_file, AUE_NULL }, /* 356 = extattr_set_file */
{ SYF_MPSAFE | AS(extattr_get_file_args), (sy_call_t *)extattr_get_file, AUE_NULL }, /* 357 = extattr_get_file */
{ SYF_MPSAFE | AS(extattr_delete_file_args), (sy_call_t *)extattr_delete_file, AUE_NULL }, /* 358 = extattr_delete_file */
{ AS(aio_waitcomplete_args), (sy_call_t *)lkmressys, AUE_NULL }, /* 359 = aio_waitcomplete */
{ SYF_MPSAFE | AS(getresuid_args), (sy_call_t *)getresuid, AUE_NULL }, /* 360 = getresuid */
{ SYF_MPSAFE | AS(getresgid_args), (sy_call_t *)getresgid, AUE_NULL }, /* 361 = getresgid */
@ -400,9 +400,9 @@ struct sysent sysent[] = {
{ 0, (sy_call_t *)nosys, AUE_NULL }, /* 368 = __cap_set_fd */
{ 0, (sy_call_t *)nosys, AUE_NULL }, /* 369 = __cap_set_file */
{ AS(nosys_args), (sy_call_t *)lkmressys, AUE_NULL }, /* 370 = lkmressys */
{ AS(extattr_set_fd_args), (sy_call_t *)extattr_set_fd, AUE_NULL }, /* 371 = extattr_set_fd */
{ AS(extattr_get_fd_args), (sy_call_t *)extattr_get_fd, AUE_NULL }, /* 372 = extattr_get_fd */
{ AS(extattr_delete_fd_args), (sy_call_t *)extattr_delete_fd, AUE_NULL }, /* 373 = extattr_delete_fd */
{ SYF_MPSAFE | AS(extattr_set_fd_args), (sy_call_t *)extattr_set_fd, AUE_NULL }, /* 371 = extattr_set_fd */
{ SYF_MPSAFE | AS(extattr_get_fd_args), (sy_call_t *)extattr_get_fd, AUE_NULL }, /* 372 = extattr_get_fd */
{ SYF_MPSAFE | AS(extattr_delete_fd_args), (sy_call_t *)extattr_delete_fd, AUE_NULL }, /* 373 = extattr_delete_fd */
{ SYF_MPSAFE | AS(__setugid_args), (sy_call_t *)__setugid, AUE_NULL }, /* 374 = __setugid */
{ AS(nfsclnt_args), (sy_call_t *)nosys, AUE_NULL }, /* 375 = nfsclnt */
{ SYF_MPSAFE | AS(eaccess_args), (sy_call_t *)eaccess, AUE_NULL }, /* 376 = eaccess */
@ -441,9 +441,9 @@ struct sysent sysent[] = {
{ SYF_MPSAFE | AS(__mac_get_pid_args), (sy_call_t *)__mac_get_pid, AUE_NULL }, /* 409 = __mac_get_pid */
{ SYF_MPSAFE | AS(__mac_get_link_args), (sy_call_t *)__mac_get_link, AUE_NULL }, /* 410 = __mac_get_link */
{ SYF_MPSAFE | AS(__mac_set_link_args), (sy_call_t *)__mac_set_link, AUE_NULL }, /* 411 = __mac_set_link */
{ AS(extattr_set_link_args), (sy_call_t *)extattr_set_link, AUE_NULL }, /* 412 = extattr_set_link */
{ AS(extattr_get_link_args), (sy_call_t *)extattr_get_link, AUE_NULL }, /* 413 = extattr_get_link */
{ AS(extattr_delete_link_args), (sy_call_t *)extattr_delete_link, AUE_NULL }, /* 414 = extattr_delete_link */
{ SYF_MPSAFE | AS(extattr_set_link_args), (sy_call_t *)extattr_set_link, AUE_NULL }, /* 412 = extattr_set_link */
{ SYF_MPSAFE | AS(extattr_get_link_args), (sy_call_t *)extattr_get_link, AUE_NULL }, /* 413 = extattr_get_link */
{ SYF_MPSAFE | AS(extattr_delete_link_args), (sy_call_t *)extattr_delete_link, AUE_NULL }, /* 414 = extattr_delete_link */
{ SYF_MPSAFE | AS(__mac_execve_args), (sy_call_t *)__mac_execve, AUE_NULL }, /* 415 = __mac_execve */
{ SYF_MPSAFE | AS(sigaction_args), (sy_call_t *)sigaction, AUE_NULL }, /* 416 = sigaction */
{ SYF_MPSAFE | AS(sigreturn_args), (sy_call_t *)sigreturn, AUE_NULL }, /* 417 = sigreturn */
@ -466,9 +466,9 @@ struct sysent sysent[] = {
{ SYF_MPSAFE | AS(_umtx_lock_args), (sy_call_t *)_umtx_lock, AUE_NULL }, /* 434 = _umtx_lock */
{ SYF_MPSAFE | AS(_umtx_unlock_args), (sy_call_t *)_umtx_unlock, AUE_NULL }, /* 435 = _umtx_unlock */
{ SYF_MPSAFE | AS(jail_attach_args), (sy_call_t *)jail_attach, AUE_NULL }, /* 436 = jail_attach */
{ AS(extattr_list_fd_args), (sy_call_t *)extattr_list_fd, AUE_NULL }, /* 437 = extattr_list_fd */
{ AS(extattr_list_file_args), (sy_call_t *)extattr_list_file, AUE_NULL }, /* 438 = extattr_list_file */
{ AS(extattr_list_link_args), (sy_call_t *)extattr_list_link, AUE_NULL }, /* 439 = extattr_list_link */
{ SYF_MPSAFE | AS(extattr_list_fd_args), (sy_call_t *)extattr_list_fd, AUE_NULL }, /* 437 = extattr_list_fd */
{ SYF_MPSAFE | AS(extattr_list_file_args), (sy_call_t *)extattr_list_file, AUE_NULL }, /* 438 = extattr_list_file */
{ SYF_MPSAFE | AS(extattr_list_link_args), (sy_call_t *)extattr_list_link, AUE_NULL }, /* 439 = extattr_list_link */
{ SYF_MPSAFE | AS(kse_switchin_args), (sy_call_t *)kse_switchin, AUE_NULL }, /* 440 = kse_switchin */
{ SYF_MPSAFE | AS(ksem_timedwait_args), (sy_call_t *)lkmressys, AUE_NULL }, /* 441 = ksem_timedwait */
{ SYF_MPSAFE | AS(thr_suspend_args), (sy_call_t *)thr_suspend, AUE_NULL }, /* 442 = thr_suspend */

View File

@ -4278,7 +4278,7 @@ extattrctl(td, uap)
struct nameidata nd;
struct mount *mp, *mp_writable;
char attrname[EXTATTR_MAXNAMELEN];
int error;
int vfslocked, fnvfslocked, error;
/*
* uap->attrname is not always defined. We check again later when we
@ -4291,36 +4291,39 @@ extattrctl(td, uap)
return (error);
}
vfslocked = fnvfslocked = 0;
/*
* uap->filename is not always defined. If it is, grab a vnode lock,
* which VFS_EXTATTRCTL() will later release.
*/
filename_vp = NULL;
if (uap->filename != NULL) {
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
uap->filename, td);
NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | LOCKLEAF,
UIO_USERSPACE, uap->filename, td);
error = namei(&nd);
if (error)
return (error);
fnvfslocked = NDHASGIANT(&nd);
filename_vp = nd.ni_vp;
NDFREE(&nd, NDF_NO_VP_RELE | NDF_NO_VP_UNLOCK);
}
/* uap->path is always defined. */
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW, UIO_USERSPACE, uap->path, td);
error = namei(&nd);
if (error) {
if (filename_vp != NULL)
vput(filename_vp);
return (error);
goto out;
}
vfslocked = NDHASGIANT(&nd);
mp = nd.ni_vp->v_mount;
error = vn_start_write(nd.ni_vp, &mp_writable, V_WAIT | PCATCH);
NDFREE(&nd, 0);
if (error) {
if (filename_vp != NULL)
vput(filename_vp);
return (error);
goto out;
}
error = VFS_EXTATTRCTL(mp, uap->cmd, filename_vp, uap->attrnamespace,
@ -4333,6 +4336,9 @@ extattrctl(td, uap)
*/
if (filename_vp != NULL)
vrele(filename_vp);
out:
VFS_UNLOCK_GIANT(fnvfslocked);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@ -4356,6 +4362,7 @@ extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
ssize_t cnt;
int error;
VFS_ASSERT_GIANT(vp->v_mount);
error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
if (error)
return (error);
@ -4408,7 +4415,7 @@ extattr_set_fd(td, uap)
{
struct file *fp;
char attrname[EXTATTR_MAXNAMELEN];
int error;
int vfslocked, error;
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
if (error)
@ -4418,9 +4425,11 @@ extattr_set_fd(td, uap)
if (error)
return (error);
vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
error = extattr_set_vp(fp->f_vnode, uap->attrnamespace,
attrname, uap->data, uap->nbytes, td);
fdrop(fp, td);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@ -4438,22 +4447,24 @@ extattr_set_file(td, uap)
{
struct nameidata nd;
char attrname[EXTATTR_MAXNAMELEN];
int error;
int vfslocked, error;
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
if (error)
return (error);
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW, UIO_USERSPACE, uap->path, td);
error = namei(&nd);
if (error)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
vfslocked = NDHASGIANT(&nd);
error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
uap->data, uap->nbytes, td);
vrele(nd.ni_vp);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@ -4470,22 +4481,24 @@ extattr_set_link(td, uap)
{
struct nameidata nd;
char attrname[EXTATTR_MAXNAMELEN];
int error;
int vfslocked, error;
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
if (error)
return (error);
NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW, UIO_USERSPACE, uap->path, td);
error = namei(&nd);
if (error)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
vfslocked = NDHASGIANT(&nd);
error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
uap->data, uap->nbytes, td);
vrele(nd.ni_vp);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@ -4509,6 +4522,7 @@ extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
size_t size, *sizep;
int error;
VFS_ASSERT_GIANT(vp->v_mount);
VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
@ -4573,7 +4587,7 @@ extattr_get_fd(td, uap)
{
struct file *fp;
char attrname[EXTATTR_MAXNAMELEN];
int error;
int vfslocked, error;
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
if (error)
@ -4583,10 +4597,12 @@ extattr_get_fd(td, uap)
if (error)
return (error);
vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
error = extattr_get_vp(fp->f_vnode, uap->attrnamespace,
attrname, uap->data, uap->nbytes, td);
fdrop(fp, td);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@ -4603,22 +4619,24 @@ extattr_get_file(td, uap)
{
struct nameidata nd;
char attrname[EXTATTR_MAXNAMELEN];
int error;
int vfslocked, error;
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
if (error)
return (error);
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW, UIO_USERSPACE, uap->path, td);
error = namei(&nd);
if (error)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
vfslocked = NDHASGIANT(&nd);
error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
uap->data, uap->nbytes, td);
vrele(nd.ni_vp);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@ -4635,22 +4653,24 @@ extattr_get_link(td, uap)
{
struct nameidata nd;
char attrname[EXTATTR_MAXNAMELEN];
int error;
int vfslocked, error;
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
if (error)
return (error);
NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW, UIO_USERSPACE, uap->path, td);
error = namei(&nd);
if (error)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
vfslocked = NDHASGIANT(&nd);
error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
uap->data, uap->nbytes, td);
vrele(nd.ni_vp);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@ -4671,6 +4691,7 @@ extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
struct mount *mp;
int error;
VFS_ASSERT_GIANT(vp->v_mount);
error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
if (error)
return (error);
@ -4707,9 +4728,8 @@ extattr_delete_fd(td, uap)
} */ *uap;
{
struct file *fp;
struct vnode *vp;
char attrname[EXTATTR_MAXNAMELEN];
int error;
int vfslocked, error;
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
if (error)
@ -4718,10 +4738,12 @@ extattr_delete_fd(td, uap)
error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
if (error)
return (error);
vp = fp->f_vnode;
error = extattr_delete_vp(vp, uap->attrnamespace, attrname, td);
vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
error = extattr_delete_vp(fp->f_vnode, uap->attrnamespace,
attrname, td);
fdrop(fp, td);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@ -4736,20 +4758,22 @@ extattr_delete_file(td, uap)
{
struct nameidata nd;
char attrname[EXTATTR_MAXNAMELEN];
int error;
int vfslocked, error;
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
if (error)
return(error);
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW, UIO_USERSPACE, uap->path, td);
error = namei(&nd);
if (error)
return(error);
NDFREE(&nd, NDF_ONLY_PNBUF);
vfslocked = NDHASGIANT(&nd);
error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
vrele(nd.ni_vp);
VFS_UNLOCK_GIANT(vfslocked);
return(error);
}
@ -4764,20 +4788,22 @@ extattr_delete_link(td, uap)
{
struct nameidata nd;
char attrname[EXTATTR_MAXNAMELEN];
int error;
int vfslocked, error;
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
if (error)
return(error);
NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW, UIO_USERSPACE, uap->path, td);
error = namei(&nd);
if (error)
return(error);
NDFREE(&nd, NDF_ONLY_PNBUF);
vfslocked = NDHASGIANT(&nd);
error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
vrele(nd.ni_vp);
VFS_UNLOCK_GIANT(vfslocked);
return(error);
}
@ -4801,6 +4827,7 @@ extattr_list_vp(struct vnode *vp, int attrnamespace, void *data,
ssize_t cnt;
int error;
VFS_ASSERT_GIANT(vp->v_mount);
VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
@ -4858,16 +4885,18 @@ extattr_list_fd(td, uap)
} */ *uap;
{
struct file *fp;
int error;
int vfslocked, error;
error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
if (error)
return (error);
vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
error = extattr_list_vp(fp->f_vnode, uap->attrnamespace, uap->data,
uap->nbytes, td);
fdrop(fp, td);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@ -4882,18 +4911,20 @@ extattr_list_file(td, uap)
} */ *uap;
{
struct nameidata nd;
int error;
int vfslocked, error;
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW, UIO_USERSPACE, uap->path, td);
error = namei(&nd);
if (error)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
vfslocked = NDHASGIANT(&nd);
error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,
uap->nbytes, td);
vrele(nd.ni_vp);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@ -4908,17 +4939,19 @@ extattr_list_link(td, uap)
} */ *uap;
{
struct nameidata nd;
int error;
int vfslocked, error;
NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW, UIO_USERSPACE, uap->path, td);
error = namei(&nd);
if (error)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
vfslocked = NDHASGIANT(&nd);
error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,
uap->nbytes, td);
vrele(nd.ni_vp);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}

View File

@ -4278,7 +4278,7 @@ extattrctl(td, uap)
struct nameidata nd;
struct mount *mp, *mp_writable;
char attrname[EXTATTR_MAXNAMELEN];
int error;
int vfslocked, fnvfslocked, error;
/*
* uap->attrname is not always defined. We check again later when we
@ -4291,36 +4291,39 @@ extattrctl(td, uap)
return (error);
}
vfslocked = fnvfslocked = 0;
/*
* uap->filename is not always defined. If it is, grab a vnode lock,
* which VFS_EXTATTRCTL() will later release.
*/
filename_vp = NULL;
if (uap->filename != NULL) {
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
uap->filename, td);
NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | LOCKLEAF,
UIO_USERSPACE, uap->filename, td);
error = namei(&nd);
if (error)
return (error);
fnvfslocked = NDHASGIANT(&nd);
filename_vp = nd.ni_vp;
NDFREE(&nd, NDF_NO_VP_RELE | NDF_NO_VP_UNLOCK);
}
/* uap->path is always defined. */
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW, UIO_USERSPACE, uap->path, td);
error = namei(&nd);
if (error) {
if (filename_vp != NULL)
vput(filename_vp);
return (error);
goto out;
}
vfslocked = NDHASGIANT(&nd);
mp = nd.ni_vp->v_mount;
error = vn_start_write(nd.ni_vp, &mp_writable, V_WAIT | PCATCH);
NDFREE(&nd, 0);
if (error) {
if (filename_vp != NULL)
vput(filename_vp);
return (error);
goto out;
}
error = VFS_EXTATTRCTL(mp, uap->cmd, filename_vp, uap->attrnamespace,
@ -4333,6 +4336,9 @@ extattrctl(td, uap)
*/
if (filename_vp != NULL)
vrele(filename_vp);
out:
VFS_UNLOCK_GIANT(fnvfslocked);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@ -4356,6 +4362,7 @@ extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
ssize_t cnt;
int error;
VFS_ASSERT_GIANT(vp->v_mount);
error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
if (error)
return (error);
@ -4408,7 +4415,7 @@ extattr_set_fd(td, uap)
{
struct file *fp;
char attrname[EXTATTR_MAXNAMELEN];
int error;
int vfslocked, error;
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
if (error)
@ -4418,9 +4425,11 @@ extattr_set_fd(td, uap)
if (error)
return (error);
vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
error = extattr_set_vp(fp->f_vnode, uap->attrnamespace,
attrname, uap->data, uap->nbytes, td);
fdrop(fp, td);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@ -4438,22 +4447,24 @@ extattr_set_file(td, uap)
{
struct nameidata nd;
char attrname[EXTATTR_MAXNAMELEN];
int error;
int vfslocked, error;
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
if (error)
return (error);
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW, UIO_USERSPACE, uap->path, td);
error = namei(&nd);
if (error)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
vfslocked = NDHASGIANT(&nd);
error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
uap->data, uap->nbytes, td);
vrele(nd.ni_vp);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@ -4470,22 +4481,24 @@ extattr_set_link(td, uap)
{
struct nameidata nd;
char attrname[EXTATTR_MAXNAMELEN];
int error;
int vfslocked, error;
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
if (error)
return (error);
NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW, UIO_USERSPACE, uap->path, td);
error = namei(&nd);
if (error)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
vfslocked = NDHASGIANT(&nd);
error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
uap->data, uap->nbytes, td);
vrele(nd.ni_vp);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@ -4509,6 +4522,7 @@ extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
size_t size, *sizep;
int error;
VFS_ASSERT_GIANT(vp->v_mount);
VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
@ -4573,7 +4587,7 @@ extattr_get_fd(td, uap)
{
struct file *fp;
char attrname[EXTATTR_MAXNAMELEN];
int error;
int vfslocked, error;
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
if (error)
@ -4583,10 +4597,12 @@ extattr_get_fd(td, uap)
if (error)
return (error);
vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
error = extattr_get_vp(fp->f_vnode, uap->attrnamespace,
attrname, uap->data, uap->nbytes, td);
fdrop(fp, td);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@ -4603,22 +4619,24 @@ extattr_get_file(td, uap)
{
struct nameidata nd;
char attrname[EXTATTR_MAXNAMELEN];
int error;
int vfslocked, error;
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
if (error)
return (error);
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW, UIO_USERSPACE, uap->path, td);
error = namei(&nd);
if (error)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
vfslocked = NDHASGIANT(&nd);
error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
uap->data, uap->nbytes, td);
vrele(nd.ni_vp);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@ -4635,22 +4653,24 @@ extattr_get_link(td, uap)
{
struct nameidata nd;
char attrname[EXTATTR_MAXNAMELEN];
int error;
int vfslocked, error;
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
if (error)
return (error);
NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW, UIO_USERSPACE, uap->path, td);
error = namei(&nd);
if (error)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
vfslocked = NDHASGIANT(&nd);
error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
uap->data, uap->nbytes, td);
vrele(nd.ni_vp);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@ -4671,6 +4691,7 @@ extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
struct mount *mp;
int error;
VFS_ASSERT_GIANT(vp->v_mount);
error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
if (error)
return (error);
@ -4707,9 +4728,8 @@ extattr_delete_fd(td, uap)
} */ *uap;
{
struct file *fp;
struct vnode *vp;
char attrname[EXTATTR_MAXNAMELEN];
int error;
int vfslocked, error;
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
if (error)
@ -4718,10 +4738,12 @@ extattr_delete_fd(td, uap)
error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
if (error)
return (error);
vp = fp->f_vnode;
error = extattr_delete_vp(vp, uap->attrnamespace, attrname, td);
vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
error = extattr_delete_vp(fp->f_vnode, uap->attrnamespace,
attrname, td);
fdrop(fp, td);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@ -4736,20 +4758,22 @@ extattr_delete_file(td, uap)
{
struct nameidata nd;
char attrname[EXTATTR_MAXNAMELEN];
int error;
int vfslocked, error;
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
if (error)
return(error);
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW, UIO_USERSPACE, uap->path, td);
error = namei(&nd);
if (error)
return(error);
NDFREE(&nd, NDF_ONLY_PNBUF);
vfslocked = NDHASGIANT(&nd);
error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
vrele(nd.ni_vp);
VFS_UNLOCK_GIANT(vfslocked);
return(error);
}
@ -4764,20 +4788,22 @@ extattr_delete_link(td, uap)
{
struct nameidata nd;
char attrname[EXTATTR_MAXNAMELEN];
int error;
int vfslocked, error;
error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
if (error)
return(error);
NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW, UIO_USERSPACE, uap->path, td);
error = namei(&nd);
if (error)
return(error);
NDFREE(&nd, NDF_ONLY_PNBUF);
vfslocked = NDHASGIANT(&nd);
error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
vrele(nd.ni_vp);
VFS_UNLOCK_GIANT(vfslocked);
return(error);
}
@ -4801,6 +4827,7 @@ extattr_list_vp(struct vnode *vp, int attrnamespace, void *data,
ssize_t cnt;
int error;
VFS_ASSERT_GIANT(vp->v_mount);
VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
@ -4858,16 +4885,18 @@ extattr_list_fd(td, uap)
} */ *uap;
{
struct file *fp;
int error;
int vfslocked, error;
error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
if (error)
return (error);
vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
error = extattr_list_vp(fp->f_vnode, uap->attrnamespace, uap->data,
uap->nbytes, td);
fdrop(fp, td);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@ -4882,18 +4911,20 @@ extattr_list_file(td, uap)
} */ *uap;
{
struct nameidata nd;
int error;
int vfslocked, error;
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW, UIO_USERSPACE, uap->path, td);
error = namei(&nd);
if (error)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
vfslocked = NDHASGIANT(&nd);
error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,
uap->nbytes, td);
vrele(nd.ni_vp);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@ -4908,17 +4939,19 @@ extattr_list_link(td, uap)
} */ *uap;
{
struct nameidata nd;
int error;
int vfslocked, error;
NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW, UIO_USERSPACE, uap->path, td);
error = namei(&nd);
if (error)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
vfslocked = NDHASGIANT(&nd);
error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,
uap->nbytes, td);
vrele(nd.ni_vp);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}