summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2002-08-19 07:01:55 +0000
committerphk <phk@FreeBSD.org>2002-08-19 07:01:55 +0000
commitd1ede7ccd11cce49d364c5725e790b1f1c3b69b1 (patch)
tree0a2a86edb5b93c0beeb79414bd9f7da0f8a40b11
parentb08a6ac7b9d53d9c8af42dc1cd4b5c364004ef5b (diff)
downloadFreeBSD-src-d1ede7ccd11cce49d364c5725e790b1f1c3b69b1.zip
FreeBSD-src-d1ede7ccd11cce49d364c5725e790b1f1c3b69b1.tar.gz
First snapshot of UFS2 EA support.
Sponsored by: DARPA & NAI Labs.
-rw-r--r--sys/ufs/ffs/ffs_vnops.c235
1 files changed, 228 insertions, 7 deletions
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index 6de5b5a..7c9f9bb 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -78,7 +78,7 @@ int ffs_fsync(struct vop_fsync_args *);
static int ffs_getpages(struct vop_getpages_args *);
static int ffs_read(struct vop_read_args *);
static int ffs_write(struct vop_write_args *);
-static int ffs_extread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred);
+static int ffs_extread(struct vnode *vp, struct uio *uio, int ioflag);
static int ffs_extwrite(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred);
static int ffs_getextattr(struct vop_getextattr_args *);
static int ffs_setextattr(struct vop_setextattr_args *);
@@ -324,7 +324,11 @@ ffs_read(ap)
uio = ap->a_uio;
ioflag = ap->a_ioflag;
if (ap->a_ioflag & IO_EXT)
- return (ffs_extread(vp, uio, ioflag, ap->a_cred));
+#ifdef notyet
+ return (ffs_extread(vp, uio, ioflag));
+#else
+ panic("ffs_read+IO_EXT");
+#endif
GIANT_REQUIRED;
@@ -650,7 +654,11 @@ ffs_write(ap)
uio = ap->a_uio;
ioflag = ap->a_ioflag;
if (ap->a_ioflag & IO_EXT)
+#ifdef notyet
return (ffs_extwrite(vp, uio, ioflag, ap->a_cred));
+#else
+ panic("ffs_read+IO_EXT");
+#endif
GIANT_REQUIRED;
@@ -989,10 +997,10 @@ ffs_getpages(ap)
}
/*
- * Vnode op for extended attribute reading.
+ * Extended attribute reading.
*/
static int
-ffs_extread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
+ffs_extread(struct vnode *vp, struct uio *uio, int ioflag)
{
struct inode *ip;
struct ufs2_dinode *dp;
@@ -1156,7 +1164,7 @@ ffs_extread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
}
/*
- * Vnode op for external attribute writing.
+ * Extended attribute writing.
*/
static int
ffs_extwrite(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *ucred)
@@ -1282,6 +1290,93 @@ ffs_extwrite(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *ucred)
return (error);
}
+
+/*
+ * Vnode operating to retrieve a named extended attribute.
+ *
+ * Locate a particular EA (nspace:name) in the area (ptr:length), and return
+ * the length of the EA, and possibly the pointer to the entry and to the data.
+ */
+static int
+ffs_findextattr(u_char *ptr, uint length, int nspace, const char *name, u_char **eap, u_char **eac)
+{
+ u_char *p, *pe, *pn, *p0;
+ int eapad1, eapad2, ealength, ealen, nlen;
+ uint32_t ul;
+
+ pe = ptr + length;
+ nlen = strlen(name);
+
+ for (p = ptr; p < pe; p = pn) {
+ p0 = p;
+ bcopy(p, &ul, sizeof(ul));
+ pn = p + ul;
+ /* make sure this entry is complete */
+ if (pn > pe)
+ break;
+ p += sizeof(uint32_t);
+ if (*p != nspace)
+ continue;
+ p++;
+ eapad2 = *p++;
+ if (*p != nlen)
+ continue;
+ p++;
+ if (bcmp(p, name, nlen))
+ continue;
+ ealength = sizeof(uint32_t) + 3 + nlen;
+ eapad1 = 8 - (ealength % 8);
+ if (eapad1 == 8)
+ eapad1 = 0;
+ ealength += eapad1;
+ ealen = ul - ealength - eapad2;
+ p += nlen + eapad1;
+ if (eap != NULL)
+ *eap = p0;
+ if (eac != NULL)
+ *eac = p;
+ return (ealen);
+ }
+ return(0);
+}
+
+static int
+ffs_rdextattr(u_char **p, struct vnode *vp, struct thread *td, int extra)
+{
+ struct inode *ip;
+ struct fs *fs;
+ struct ufs2_dinode *dp;
+ struct uio luio;
+ struct iovec liovec;
+ int easize, error;
+ u_char *eae;
+
+ ip = VTOI(vp);
+ fs = ip->i_fs;
+ dp = ip->i_din2;
+ easize = dp->di_extsize;
+
+ eae = malloc(easize + extra, M_TEMP, M_WAITOK);
+
+ liovec.iov_base = eae;
+ liovec.iov_len = easize;
+ luio.uio_iov = &liovec;
+ luio.uio_iovcnt = 1;
+ luio.uio_offset = 0;
+ luio.uio_resid = easize;
+ luio.uio_segflg = UIO_SYSSPACE;
+ luio.uio_rw = UIO_READ;
+ luio.uio_td = td;
+
+ error = ffs_extread(vp, &luio, IO_EXT | IO_SYNC);
+ if (error) {
+ free(eae, M_TEMP);
+ return(error);
+ }
+ *p = eae;
+ return (0);
+}
+
/*
* Vnode operating to retrieve a named extended attribute.
*/
@@ -1299,8 +1394,36 @@ vop_getextattr {
};
*/
{
+ struct inode *ip;
+ struct fs *fs;
+ u_char *eae, *p;
+ struct ufs2_dinode *dp;
+ unsigned easize;
+ int error, ealen;
- return (ufs_vnoperate((struct vop_generic_args *)ap));
+ ip = VTOI(ap->a_vp);
+ fs = ip->i_fs;
+
+ if (fs->fs_magic == FS_UFS1_MAGIC)
+ return (ufs_vnoperate((struct vop_generic_args *)ap));
+
+ dp = ip->i_din2;
+ error = ffs_rdextattr(&eae, ap->a_vp, ap->a_td, 0);
+ if (error)
+ return (error);
+ easize = dp->di_extsize;
+ error = ENOATTR;
+ ealen = ffs_findextattr(eae, easize,
+ ap->a_attrnamespace, ap->a_name, NULL, &p);
+ if (ealen != 0) {
+ error = 0;
+ if (ap->a_size != NULL)
+ *ap->a_size = ealen;
+ else if (ap->a_uio != NULL)
+ error = uiomove(p, ealen, ap->a_uio);
+ }
+ free(eae, M_TEMP);
+ return(error);
}
/*
@@ -1319,6 +1442,104 @@ vop_setextattr {
};
*/
{
+ struct inode *ip;
+ struct fs *fs;
+ uint32_t ealength, ul;
+ int ealen, eacont, eapad1, eapad2, error, i, easize;
+ u_char *eae, *p;
+ struct uio luio;
+ struct iovec liovec;
+ struct ufs2_dinode *dp;
+ struct ucred *cred;
+
+ ip = VTOI(ap->a_vp);
+ fs = ip->i_fs;
+
+ if (fs->fs_magic == FS_UFS1_MAGIC)
+ return (ufs_vnoperate((struct vop_generic_args *)ap));
+
+ if (ap->a_cred != NOCRED)
+ cred = ap->a_cred;
+ else
+ cred = ap->a_vp->v_mount->mnt_cred;
+ dp = ip->i_din2;
+
+ /* Calculate the length of the EA entry */
+ if (ap->a_uio == NULL) {
+ /* delete */
+ ealength = eapad1 = ealen = eapad2 = eacont = 0;
+ } else {
+ ealen = ap->a_uio->uio_resid;
+ ealength = sizeof(uint32_t) + 3 + strlen(ap->a_name);
+ eapad1 = 8 - (ealength % 8);
+ if (eapad1 == 8)
+ eapad1 = 0;
+ eacont = ealength + eapad1;
+ eapad2 = 8 - (ealen % 8);
+ if (eapad2 == 8)
+ eapad2 = 0;
+ ealength += eapad1 + ealen + eapad2;
+ }
- return (ufs_vnoperate((struct vop_generic_args *)ap));
+ error = ffs_rdextattr(&eae, ap->a_vp, ap->a_td, ealength);
+ if (error)
+ return (error);
+
+ easize = dp->di_extsize;
+ ul = ffs_findextattr(eae, easize,
+ ap->a_attrnamespace, ap->a_name, &p, NULL);
+ if (ul == 0 && ealength == 0) {
+ /* delete but nonexistent */
+ free(eae, M_TEMP);
+ return(ENOATTR);
+ } else if (ul == 0) {
+ /* new, append at end */
+ p = eae + easize;
+ easize += ealength;
+ } else if (ul != ealength) {
+ bcopy(p, &ul, sizeof ul);
+ i = p - eae + ul;
+ bcopy(p + ul, p + ealength, easize - i);
+ easize -= ul;
+ easize += ealength;
+ }
+ if (easize > NXADDR * fs->fs_bsize) {
+ free(eae, M_TEMP);
+ return(ENOSPC);
+ }
+ if (ealength != 0) {
+ bcopy(&ealength, p, sizeof(ealength));
+ p += sizeof(ealength);
+ *p++ = ap->a_attrnamespace;
+ *p++ = eapad2;
+ *p++ = strlen(ap->a_name);
+ strcpy(p, ap->a_name);
+ p += strlen(ap->a_name);
+ bzero(p, eapad1);
+ p += eapad1;
+ error = uiomove(p, ealen, ap->a_uio);
+ if (error) {
+ free(eae, M_TEMP);
+ return(error);
+ }
+ p += ealen;
+ bzero(p, eapad2);
+ }
+ liovec.iov_base = eae;
+ liovec.iov_len = easize;
+ luio.uio_iov = &liovec;
+ luio.uio_iovcnt = 1;
+ luio.uio_offset = 0;
+ luio.uio_resid = easize;
+ luio.uio_segflg = UIO_SYSSPACE;
+ luio.uio_rw = UIO_WRITE;
+ luio.uio_td = ap->a_td;
+ /* XXX: I'm not happy about truncating to zero size */
+ if (easize < dp->di_extsize)
+ error = ffs_truncate(ap->a_vp, 0, IO_EXT, cred, ap->a_td);
+ error = ffs_extwrite(ap->a_vp, &luio, IO_EXT | IO_SYNC, cred);
+ free(eae, M_TEMP);
+ if (error)
+ return(error);
+ return(error);
}
OpenPOWER on IntegriCloud