From: Matthew Dillon Date: Wed, 16 May 2012 03:04:15 +0000 (-0700) Subject: hammer2 - hookup getattr, setattr X-Git-Tag: v3.4.0rc~1106 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/b2b78aaa870ae0fb07df142a8c7c05f7ff2e804d hammer2 - hookup getattr, setattr * Hook up most remaining fields for getattr and setattr, and also initial ownership and so forth for create. * initialize and update the time on create, setattr, and write. * kqueue handling for write. --- diff --git a/sys/vfs/hammer2/hammer2.h b/sys/vfs/hammer2/hammer2.h index 789be110da..b14e7899e6 100644 --- a/sys/vfs/hammer2/hammer2.h +++ b/sys/vfs/hammer2/hammer2.h @@ -344,13 +344,16 @@ int hammer2_get_dtype(hammer2_inode_t *ip); int hammer2_get_vtype(hammer2_inode_t *ip); u_int8_t hammer2_get_obj_type(enum vtype vtype); void hammer2_time_to_timespec(u_int64_t xtime, struct timespec *ts); +u_int64_t hammer2_timespec_to_time(struct timespec *ts); u_int32_t hammer2_to_unix_xid(uuid_t *uuid); +void hammer2_guid_to_uuid(uuid_t *uuid, u_int32_t guid); hammer2_key_t hammer2_dirhash(const unsigned char *name, size_t len); int hammer2_bytes_to_radix(size_t bytes); int hammer2_calc_logical(hammer2_inode_t *ip, hammer2_off_t uoff, hammer2_key_t *lbasep, hammer2_key_t *leofp); +void hammer2_update_time(uint64_t *timep); /* * hammer2_inode.c diff --git a/sys/vfs/hammer2/hammer2_inode.c b/sys/vfs/hammer2/hammer2_inode.c index 3a4b18d163..a1c682cbce 100644 --- a/sys/vfs/hammer2/hammer2_inode.c +++ b/sys/vfs/hammer2/hammer2_inode.c @@ -213,6 +213,7 @@ hammer2_inode_create(hammer2_inode_t *dip, hammer2_inode_t *nip; hammer2_key_t lhc; int error; + uid_t xuid; lhc = hammer2_dirhash(name, name_len); @@ -270,12 +271,36 @@ hammer2_inode_create(hammer2_inode_t *dip, } hammer2_voldata_unlock(hmp); nip->ip_data.version = HAMMER2_INODE_VERSION_ONE; - nip->ip_data.ctime = 0; - nip->ip_data.mtime = 0; + hammer2_update_time(&nip->ip_data.ctime); + nip->ip_data.mtime = nip->ip_data.ctime; if (vap) nip->ip_data.mode = vap->va_mode; nip->ip_data.nlinks = 1; - /* uid, gid, etc */ + if (vap) { + if (dip) { + xuid = hammer2_to_unix_xid(&dip->ip_data.uid); + xuid = vop_helper_create_uid(dip->pmp->mp, + dip->ip_data.mode, + xuid, + cred, + &vap->va_mode); + } else { + xuid = 0; + } + if (vap->va_vaflags & VA_UID_UUID_VALID) + nip->ip_data.uid = vap->va_uid_uuid; + else if (vap->va_uid != (uid_t)VNOVAL) + hammer2_guid_to_uuid(&nip->ip_data.uid, vap->va_uid); + else + hammer2_guid_to_uuid(&nip->ip_data.uid, xuid); + + if (vap->va_vaflags & VA_GID_UUID_VALID) + nip->ip_data.gid = vap->va_gid_uuid; + else if (vap->va_gid != (gid_t)VNOVAL) + hammer2_guid_to_uuid(&nip->ip_data.gid, vap->va_gid); + else if (dip) + nip->ip_data.gid = dip->ip_data.gid; + } /* * Regular files and softlinks allow a small amount of data to be diff --git a/sys/vfs/hammer2/hammer2_subr.c b/sys/vfs/hammer2/hammer2_subr.c index 03c8270bd9..ffe75bcfe1 100644 --- a/sys/vfs/hammer2/hammer2_subr.c +++ b/sys/vfs/hammer2/hammer2_subr.c @@ -240,6 +240,16 @@ hammer2_time_to_timespec(u_int64_t xtime, struct timespec *ts) ts->tv_nsec = (unsigned int)(xtime % 1000000) * 1000L; } +u_int64_t +hammer2_timespec_to_time(struct timespec *ts) +{ + u_int64_t xtime; + + xtime = (unsigned)(ts->tv_nsec / 1000) + + (unsigned long)ts->tv_sec * 1000000ULL; + return(xtime); +} + /* * Convert a uuid to a unix uid or gid */ @@ -249,6 +259,13 @@ hammer2_to_unix_xid(uuid_t *uuid) return(*(u_int32_t *)&uuid->node[2]); } +void +hammer2_guid_to_uuid(uuid_t *uuid, u_int32_t guid) +{ + bzero(uuid, sizeof(*uuid)); + *(u_int32_t *)&uuid->node[2] = guid; +} + /* * Borrow HAMMER1's directory hash algorithm #1 with a few modifications. * The filename is split into fields which are hashed separately and then @@ -360,3 +377,12 @@ hammer2_calc_logical(hammer2_inode_t *ip, hammer2_off_t uoff, return (HAMMER2_PBUFSIZE); } } + +void +hammer2_update_time(uint64_t *timep) +{ + struct timeval tv; + + getmicrotime(&tv); + *timep = (unsigned long)tv.tv_sec * 1000000 + tv.tv_usec; +} diff --git a/sys/vfs/hammer2/hammer2_vnops.c b/sys/vfs/hammer2/hammer2_vnops.c index 93f9c83251..8c959c0779 100644 --- a/sys/vfs/hammer2/hammer2_vnops.c +++ b/sys/vfs/hammer2/hammer2_vnops.c @@ -58,6 +58,14 @@ static hammer2_off_t hammer2_assign_physical(hammer2_inode_t *ip, static void hammer2_extend_file(hammer2_inode_t *ip, hammer2_key_t nsize); static void hammer2_truncate_file(hammer2_inode_t *ip, hammer2_key_t nsize); +static __inline +void +hammer2_knote(struct vnode *vp, int flags) +{ + if (flags) + KNOTE(&vp->v_pollinfo.vpi_kqinfo.ki_note, flags); +} + /* * Last reference to a vnode is going away but it is still cached. */ @@ -222,8 +230,8 @@ hammer2_vop_getattr(struct vop_getattr_args *ap) vap->va_fileid = ip->ip_data.inum; vap->va_mode = ip->ip_data.mode; vap->va_nlink = ip->ip_data.nlinks; - vap->va_uid = 0; - vap->va_gid = 0; + vap->va_uid = hammer2_to_unix_xid(&ip->ip_data.uid); + vap->va_gid = hammer2_to_unix_xid(&ip->ip_data.gid); vap->va_rmajor = 0; vap->va_rminor = 0; vap->va_size = ip->ip_data.size; @@ -256,11 +264,12 @@ hammer2_vop_setattr(struct vop_setattr_args *ap) struct vattr *vap; int error; int kflags = 0; - int doctime = 0; int domtime = 0; + uint64_t ctime; vp = ap->a_vp; vap = ap->a_vap; + hammer2_update_time(&ctime); ip = VTOI(vp); hmp = ip->hmp; @@ -282,7 +291,7 @@ hammer2_vop_setattr(struct vop_setattr_args *ap) if (ip->ip_data.uflags != flags) { hammer2_chain_modify(hmp, &ip->chain, 0); ip->ip_data.uflags = flags; - doctime = 1; + ip->ip_data.ctime = ctime; kflags |= NOTE_ATTRIB; } if (ip->ip_data.uflags & (IMMUTABLE | APPEND)) { @@ -290,13 +299,40 @@ hammer2_vop_setattr(struct vop_setattr_args *ap) goto done; } } + goto done; } - if (ip->ip_data.uflags & (IMMUTABLE | APPEND)) { error = EPERM; goto done; } - /* uid, gid */ + if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) { + mode_t cur_mode = ip->ip_data.mode; + uid_t cur_uid = hammer2_to_unix_xid(&ip->ip_data.uid); + gid_t cur_gid = hammer2_to_unix_xid(&ip->ip_data.gid); + uuid_t uuid_uid; + uuid_t uuid_gid; + + error = vop_helper_chown(ap->a_vp, vap->va_uid, vap->va_gid, + ap->a_cred, + &cur_uid, &cur_gid, &cur_mode); + if (error == 0) { + hammer2_guid_to_uuid(&uuid_uid, cur_uid); + hammer2_guid_to_uuid(&uuid_gid, cur_gid); + if (bcmp(&uuid_uid, &ip->ip_data.uid, + sizeof(uuid_uid)) || + bcmp(&uuid_gid, &ip->ip_data.gid, + sizeof(uuid_gid)) || + ip->ip_data.mode != cur_mode + ) { + hammer2_chain_modify(hmp, &ip->chain, 0); + ip->ip_data.uid = uuid_uid; + ip->ip_data.gid = uuid_gid; + ip->ip_data.mode = cur_mode; + ip->ip_data.ctime = ctime; + } + kflags |= NOTE_ATTRIB; + } + } /* * Resize the file @@ -318,6 +354,32 @@ hammer2_vop_setattr(struct vop_setattr_args *ap) goto done; } } +#if 0 + /* atime not supported */ + if (vap->va_atime.tv_sec != VNOVAL) { + hammer2_chain_modify(hmp, &ip->chain, 0); + ip->ip_data.atime = hammer2_timespec_to_time(&vap->va_atime); + kflags |= NOTE_ATTRIB; + } +#endif + if (vap->va_mtime.tv_sec != VNOVAL) { + hammer2_chain_modify(hmp, &ip->chain, 0); + ip->ip_data.mtime = hammer2_timespec_to_time(&vap->va_mtime); + kflags |= NOTE_ATTRIB; + } + if (vap->va_mode != (mode_t)VNOVAL) { + mode_t cur_mode = ip->ip_data.mode; + uid_t cur_uid = hammer2_to_unix_xid(&ip->ip_data.uid); + gid_t cur_gid = hammer2_to_unix_xid(&ip->ip_data.gid); + + error = vop_helper_chmod(ap->a_vp, vap->va_mode, ap->a_cred, + cur_uid, cur_gid, &cur_mode); + if (error == 0 && ip->ip_data.mode != cur_mode) { + ip->ip_data.mode = cur_mode; + ip->ip_data.ctime = ctime; + kflags |= NOTE_ATTRIB; + } + } done: hammer2_inode_unlock_ex(ip); return (error); @@ -587,7 +649,6 @@ hammer2_vop_write(struct vop_write_args *ap) * might wind up being copied into the embedded data area. */ hammer2_inode_lock_ex(ip); - hammer2_chain_modify(hmp, &ip->chain, 0); error = hammer2_write_file(ip, uio, ap->a_ioflag, seqcount); hammer2_inode_unlock_ex(ip); @@ -652,6 +713,7 @@ hammer2_write_file(hammer2_inode_t *ip, struct uio *uio, struct buf *bp; int kflags; int error; + int modified = 0; /* * Setup if append @@ -671,6 +733,7 @@ hammer2_write_file(hammer2_inode_t *ip, struct uio *uio, */ old_eof = ip->ip_data.size; if (uio->uio_offset + uio->uio_resid > ip->ip_data.size) { + modified = 1; hammer2_extend_file(ip, uio->uio_offset + uio->uio_resid); kflags |= NOTE_EXTEND; } @@ -792,13 +855,14 @@ hammer2_write_file(hammer2_inode_t *ip, struct uio *uio, error = uiomove(bp->b_data + loff, n, uio); hammer2_chain_lock(ip->hmp, &ip->chain, HAMMER2_RESOLVE_ALWAYS); kflags |= NOTE_WRITE; + modified = 1; if (error) { brelse(bp); break; } - /* XXX update ino_data.mtime */ + /* XXX update ip_data.mtime */ /* * Once we dirty a buffer any cached offset becomes invalid. @@ -828,9 +892,13 @@ hammer2_write_file(hammer2_inode_t *ip, struct uio *uio, * Cleanup. If we extended the file EOF but failed to write through * the entire write is a failure and we have to back-up. */ - if (error && ip->ip_data.size != old_eof) + if (error && ip->ip_data.size != old_eof) { hammer2_truncate_file(ip, old_eof); - /* hammer2_knote(ip->vp, kflags); */ + } else if (modified) { + hammer2_chain_modify(ip->hmp, &ip->chain, 0); + hammer2_update_time(&ip->ip_data.mtime); + } + hammer2_knote(ip->vp, kflags); return error; }