Page MenuHomeFreeBSD

D13267.id36236.diff
No OneTemporary

D13267.id36236.diff

Index: kern/vfs_extattr.c
===================================================================
--- kern/vfs_extattr.c
+++ kern/vfs_extattr.c
@@ -150,16 +150,18 @@
/*-
* Set a named extended attribute on a file or directory
*
- * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
- * kernelspace string pointer "attrname", userspace buffer
- * pointer "data", buffer length "nbytes", thread "td".
+ * Arguments: vnode "vp", attribute namespace "attrnamespace",
+ * "ioflag" for vnode locking control,
+ * kernelspace string pointer "attrname",
+ * buffer pointer "data", buffer length "nbytes",
+ * buffer uio adress-space control - "segflg", thread "td".
* Returns: 0 on success, an error number otherwise
- * Locks: none
* References: vp must be a valid reference for the duration of the call
*/
-static int
-extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
- void *data, size_t nbytes, struct thread *td)
+int
+extattr_set_vp(struct vnode *vp, int ioflg, int attrnamespace,
+ const char *attrname, void *data, size_t nbytes, enum uio_seg segflg,
+ struct thread *td)
{
struct mount *mp;
struct uio auio;
@@ -167,26 +169,29 @@
ssize_t cnt;
int error;
- error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
- if (error)
- return (error);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ if (nbytes > IOSIZE_MAX)
+ return (EINVAL);
aiov.iov_base = data;
aiov.iov_len = nbytes;
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_offset = 0;
- if (nbytes > IOSIZE_MAX) {
- error = EINVAL;
- goto done;
- }
auio.uio_resid = nbytes;
auio.uio_rw = UIO_WRITE;
- auio.uio_segflg = UIO_USERSPACE;
+ auio.uio_segflg = segflg;
auio.uio_td = td;
cnt = nbytes;
+ if ((ioflg & IO_NODELOCKED) == 0) {
+ error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
+ if (error)
+ return (error);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ }
+
+ ASSERT_VOP_LOCKED(vp, "IO_NODELOCKED with no vp lock held");
+
#ifdef MAC
error = mac_vnode_check_setextattr(td->td_ucred, vp, attrnamespace,
attrname);
@@ -200,8 +205,11 @@
td->td_retval[0] = cnt;
done:
- VOP_UNLOCK(vp, 0);
- vn_finished_write(mp);
+ if ((ioflg & IO_NODELOCKED) == 0) {
+ vn_finished_write(mp);
+ VOP_UNLOCK(vp, 0);
+ }
+
return (error);
}
@@ -233,8 +241,8 @@
if (error)
return (error);
- error = extattr_set_vp(fp->f_vnode, uap->attrnamespace,
- attrname, uap->data, uap->nbytes, td);
+ error = extattr_set_vp(fp->f_vnode, 0, uap->attrnamespace,
+ attrname, uap->data, uap->nbytes, UIO_USERSPACE, td);
fdrop(fp, td);
return (error);
@@ -268,8 +276,8 @@
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
- error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
- uap->data, uap->nbytes, td);
+ error = extattr_set_vp(nd.ni_vp, 0, uap->attrnamespace, attrname,
+ uap->data, uap->nbytes, UIO_USERSPACE, td);
vrele(nd.ni_vp);
return (error);
@@ -303,8 +311,8 @@
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
- error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
- uap->data, uap->nbytes, td);
+ error = extattr_set_vp(nd.ni_vp, 0, uap->attrnamespace, attrname,
+ uap->data, uap->nbytes, UIO_USERSPACE, td);
vrele(nd.ni_vp);
return (error);
@@ -313,16 +321,19 @@
/*-
* Get a named extended attribute on a file or directory
*
- * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
- * kernelspace string pointer "attrname", userspace buffer
- * pointer "data", buffer length "nbytes", thread "td".
+ * Arguments: vnode "vp", "ioflag" for vnode locking control,
+ * attribute namespace "attrnamespace",
+ * kernelspace string pointer "attrname",
+ * buffer pointer "data", buffer length "nbytes",
+ * buffer uio adress-space control - "segflg", thread "td".
* Returns: 0 on success, an error number otherwise
* Locks: none
* References: vp must be a valid reference for the duration of the call
*/
-static int
-extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
- void *data, size_t nbytes, struct thread *td)
+int
+extattr_get_vp(struct vnode *vp, int ioflg, int attrnamespace,
+ const char *attrname, void *data, size_t nbytes, enum uio_seg segflg,
+ struct thread *td)
{
struct uio auio, *auiop;
struct iovec aiov;
@@ -330,7 +341,8 @@
size_t size, *sizep;
int error;
- vn_lock(vp, LK_SHARED | LK_RETRY);
+ if (nbytes > IOSIZE_MAX)
+ return (EINVAL);
/*
* Slightly unusual semantics: if the user provides a NULL data
@@ -346,19 +358,20 @@
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_offset = 0;
- if (nbytes > IOSIZE_MAX) {
- error = EINVAL;
- goto done;
- }
auio.uio_resid = nbytes;
auio.uio_rw = UIO_READ;
- auio.uio_segflg = UIO_USERSPACE;
+ auio.uio_segflg = segflg;
auio.uio_td = td;
auiop = &auio;
cnt = nbytes;
} else
sizep = &size;
+ if ((ioflg & IO_NODELOCKED) == 0)
+ vn_lock(vp, LK_SHARED | LK_RETRY);
+
+ ASSERT_VOP_LOCKED(vp, "IO_NODELOCKED with no vp lock held");
+
#ifdef MAC
error = mac_vnode_check_getextattr(td->td_ucred, vp, attrnamespace,
attrname);
@@ -376,7 +389,9 @@
td->td_retval[0] = size;
done:
- VOP_UNLOCK(vp, 0);
+ if ((ioflg & IO_NODELOCKED) == 0)
+ VOP_UNLOCK(vp, 0);
+
return (error);
}
@@ -408,8 +423,8 @@
if (error)
return (error);
- error = extattr_get_vp(fp->f_vnode, uap->attrnamespace,
- attrname, uap->data, uap->nbytes, td);
+ error = extattr_get_vp(fp->f_vnode, 0, uap->attrnamespace,
+ attrname, uap->data, uap->nbytes, UIO_USERSPACE, td);
fdrop(fp, td);
return (error);
@@ -442,8 +457,8 @@
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
- error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
- uap->data, uap->nbytes, td);
+ error = extattr_get_vp(nd.ni_vp, 0, uap->attrnamespace, attrname,
+ uap->data, uap->nbytes, UIO_USERSPACE, td);
vrele(nd.ni_vp);
return (error);
@@ -477,8 +492,8 @@
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
- error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
- uap->data, uap->nbytes, td);
+ error = extattr_get_vp(nd.ni_vp, 0, uap->attrnamespace, attrname,
+ uap->data, uap->nbytes, UIO_USERSPACE, td);
vrele(nd.ni_vp);
return (error);
@@ -488,23 +503,27 @@
* extattr_delete_vp(): Delete a named extended attribute on a file or
* directory
*
- * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
- * kernelspace string pointer "attrname", proc "p"
+ * Arguments: vnode "vp", "ioflag" for vnode locking control,
+ * attribute namespace "attrnamespace",
+ * kernelspace string pointer "attrname", thread "td".
* Returns: 0 on success, an error number otherwise
- * Locks: none
* References: vp must be a valid reference for the duration of the call
*/
-static int
-extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
- struct thread *td)
+int
+extattr_delete_vp(struct vnode *vp, int ioflg, int attrnamespace,
+ const char *attrname, struct thread *td)
{
struct mount *mp;
int error;
- error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
- if (error)
- return (error);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ if ((ioflg & IO_NODELOCKED) == 0) {
+ error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
+ if (error)
+ return (error);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ }
+
+ ASSERT_VOP_LOCKED(vp, "IO_NODELOCKED with no vp lock held");
#ifdef MAC
error = mac_vnode_check_deleteextattr(td->td_ucred, vp, attrnamespace,
@@ -521,8 +540,11 @@
#ifdef MAC
done:
#endif
- VOP_UNLOCK(vp, 0);
- vn_finished_write(mp);
+ if ((ioflg & IO_NODELOCKED) == 0) {
+ vn_finished_write(mp);
+ VOP_UNLOCK(vp, 0);
+ }
+
return (error);
}
@@ -552,7 +574,7 @@
if (error)
return (error);
- error = extattr_delete_vp(fp->f_vnode, uap->attrnamespace,
+ error = extattr_delete_vp(fp->f_vnode, 0, uap->attrnamespace,
attrname, td);
fdrop(fp, td);
return (error);
@@ -583,7 +605,7 @@
return(error);
NDFREE(&nd, NDF_ONLY_PNBUF);
- error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
+ error = extattr_delete_vp(nd.ni_vp, 0, uap->attrnamespace, attrname, td);
vrele(nd.ni_vp);
return(error);
}
@@ -613,7 +635,7 @@
return(error);
NDFREE(&nd, NDF_ONLY_PNBUF);
- error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
+ error = extattr_delete_vp(nd.ni_vp, 0, uap->attrnamespace, attrname, td);
vrele(nd.ni_vp);
return(error);
}
@@ -621,16 +643,17 @@
/*-
* Retrieve a list of extended attributes on a file or directory.
*
- * Arguments: unlocked vnode "vp", attribute namespace 'attrnamespace",
- * userspace buffer pointer "data", buffer length "nbytes",
- * thread "td".
+ * Arguments: vnode "vp", "ioflag" for vnode locking control,
+ * attribute namespace 'attrnamespace",
+ * buffer pointer "data", buffer length "nbytes",
+ * buffer uio adress-space control - "segflg", thread "td".
* Returns: 0 on success, an error number otherwise
* Locks: none
* References: vp must be a valid reference for the duration of the call
*/
-static int
-extattr_list_vp(struct vnode *vp, int attrnamespace, void *data,
- size_t nbytes, struct thread *td)
+int
+extattr_list_vp(struct vnode *vp, int ioflg, int attrnamespace, void *data,
+ size_t nbytes, enum uio_seg segflg, struct thread *td)
{
struct uio auio, *auiop;
size_t size, *sizep;
@@ -638,7 +661,8 @@
ssize_t cnt;
int error;
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ if (nbytes > IOSIZE_MAX)
+ return (EINVAL);
auiop = NULL;
sizep = NULL;
@@ -649,19 +673,20 @@
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_offset = 0;
- if (nbytes > IOSIZE_MAX) {
- error = EINVAL;
- goto done;
- }
auio.uio_resid = nbytes;
auio.uio_rw = UIO_READ;
- auio.uio_segflg = UIO_USERSPACE;
+ auio.uio_segflg = segflg;
auio.uio_td = td;
auiop = &auio;
cnt = nbytes;
} else
sizep = &size;
+ if ((ioflg & IO_NODELOCKED) == 0)
+ vn_lock(vp, LK_SHARED | LK_RETRY);
+
+ ASSERT_VOP_LOCKED(vp, "IO_NODELOCKED with no vp lock held");
+
#ifdef MAC
error = mac_vnode_check_listextattr(td->td_ucred, vp, attrnamespace);
if (error)
@@ -678,11 +703,12 @@
td->td_retval[0] = size;
done:
- VOP_UNLOCK(vp, 0);
+ if ((ioflg & IO_NODELOCKED) == 0)
+ VOP_UNLOCK(vp, 0);
+
return (error);
}
-
int
sys_extattr_list_fd(td, uap)
struct thread *td;
@@ -704,8 +730,8 @@
if (error)
return (error);
- error = extattr_list_vp(fp->f_vnode, uap->attrnamespace, uap->data,
- uap->nbytes, td);
+ error = extattr_list_vp(fp->f_vnode, 0, uap->attrnamespace, uap->data,
+ uap->nbytes, UIO_USERSPACE, td);
fdrop(fp, td);
return (error);
@@ -731,8 +757,8 @@
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
- error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,
- uap->nbytes, td);
+ error = extattr_list_vp(nd.ni_vp, 0, uap->attrnamespace, uap->data,
+ uap->nbytes, UIO_USERSPACE, td);
vrele(nd.ni_vp);
return (error);
@@ -759,8 +785,8 @@
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
- error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,
- uap->nbytes, td);
+ error = extattr_list_vp(nd.ni_vp, 0, uap->attrnamespace, uap->data,
+ uap->nbytes, UIO_USERSPACE, td);
vrele(nd.ni_vp);
return (error);
Index: sys/extattr.h
===================================================================
--- sys/extattr.h
+++ sys/extattr.h
@@ -63,12 +63,23 @@
#ifdef _KERNEL
#include <sys/types.h>
+#include <sys/uio.h>
struct thread;
struct ucred;
struct vnode;
int extattr_check_cred(struct vnode *vp, int attrnamespace,
struct ucred *cred, struct thread *td, accmode_t accmode);
+int extattr_delete_vp(struct vnode *vp, int ioflg, int attrnamespace,
+ const char *attrname, struct thread *td);
+int extattr_get_vp(struct vnode *vp, int ioflg, int attrnamespace,
+ const char *attrname, void *data, size_t nbytes,
+ enum uio_seg segflg, struct thread *td);
+int extattr_list_vp(struct vnode *vp, int ioflg, int attrnamespace,
+ void *data, size_t nbytes, enum uio_seg segflg, struct thread *td);
+int extattr_set_vp(struct vnode *vp, int ioflg, int attrnamespace,
+ const char *attrname, void *data, size_t nbytes,
+ enum uio_seg segflg, struct thread *td);
#else
#include <sys/cdefs.h>

File Metadata

Mime Type
text/plain
Expires
Sun, Feb 8, 8:41 PM (13 h, 15 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28496053
Default Alt Text
D13267.id36236.diff (12 KB)

Event Timeline