From 6b4f890b30bb9ed3617c02451fa52cbc263c6c4b Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Tue, 20 Nov 2007 22:55:40 +0000 Subject: [PATCH] HAMMER 5/many - in-memory cache and more vnops. Get more vnops working with the in-memory cache. Files can now be created, linked, and deleted. Directories can be scanned. NOTE: The topology is not yet flushed to the media. --- sys/vfs/hammer/hammer.h | 5 +- sys/vfs/hammer/hammer_cursor.c | 6 +- sys/vfs/hammer/hammer_cursor.h | 3 +- sys/vfs/hammer/hammer_disk.h | 10 ++- sys/vfs/hammer/hammer_inode.c | 31 +++++-- sys/vfs/hammer/hammer_object.c | 159 +++++++++++++++++++++++++++------ sys/vfs/hammer/hammer_subs.c | 32 ++++++- sys/vfs/hammer/hammer_vnops.c | 108 +++++++++++++++++++--- 8 files changed, 293 insertions(+), 61 deletions(-) diff --git a/sys/vfs/hammer/hammer.h b/sys/vfs/hammer/hammer.h index 4c9345887a..eef3940ca5 100644 --- a/sys/vfs/hammer/hammer.h +++ b/sys/vfs/hammer/hammer.h @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer.h,v 1.7 2007/11/20 07:16:28 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer.h,v 1.8 2007/11/20 22:55:40 dillon Exp $ */ /* * This header file contains structures used internally by the HAMMERFS @@ -179,7 +179,6 @@ struct hammer_record { struct hammer_inode *ip; union hammer_record_ondisk rec; union hammer_data_ondisk *data; - int32_t data_len; int flags; }; @@ -440,12 +439,14 @@ hammer_tid_t hammer_alloc_tid(hammer_transaction_t trans); hammer_tid_t hammer_alloc_recid(hammer_transaction_t trans); enum vtype hammer_get_vnode_type(u_int8_t obj_type); +int hammer_get_dtype(u_int8_t obj_type); u_int8_t hammer_get_obj_type(enum vtype vtype); int64_t hammer_directory_namekey(void *name, int len); int hammer_init_cursor_hmp(hammer_cursor_t cursor, hammer_mount_t hmp); int hammer_init_cursor_ip(hammer_cursor_t cursor, hammer_inode_t ip); void hammer_done_cursor(hammer_cursor_t cursor); +void hammer_mem_done(hammer_cursor_t cursor); int hammer_btree_lookup(hammer_cursor_t cursor); int hammer_btree_extract(hammer_cursor_t cursor, int flags); diff --git a/sys/vfs/hammer/hammer_cursor.c b/sys/vfs/hammer/hammer_cursor.c index 4baf855a17..8823dd79d5 100644 --- a/sys/vfs/hammer/hammer_cursor.c +++ b/sys/vfs/hammer/hammer_cursor.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer_cursor.c,v 1.2 2007/11/20 07:16:28 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_cursor.c,v 1.3 2007/11/20 22:55:40 dillon Exp $ */ /* @@ -123,8 +123,8 @@ hammer_done_cursor(hammer_cursor_t cursor) hammer_rel_buffer(cursor->record_buffer, 0); cursor->record_buffer = NULL; } - if (cursor->iprec) - hammer_rel_mem_record(&cursor->iprec); + if (cursor->ip) + hammer_mem_done(cursor); cursor->data = NULL; cursor->record = NULL; diff --git a/sys/vfs/hammer/hammer_cursor.h b/sys/vfs/hammer/hammer_cursor.h index 700725d6ef..28b6928687 100644 --- a/sys/vfs/hammer/hammer_cursor.h +++ b/sys/vfs/hammer/hammer_cursor.h @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer_cursor.h,v 1.2 2007/11/20 07:16:28 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_cursor.h,v 1.3 2007/11/20 22:55:40 dillon Exp $ */ /* @@ -93,6 +93,7 @@ struct hammer_cursor { */ struct hammer_inode *ip; struct hammer_record *iprec; + struct hammer_rec_rb_tree_scan_info scan; }; typedef struct hammer_cursor *hammer_cursor_t; diff --git a/sys/vfs/hammer/hammer_disk.h b/sys/vfs/hammer/hammer_disk.h index 54a11c4a06..b3188069ee 100644 --- a/sys/vfs/hammer/hammer_disk.h +++ b/sys/vfs/hammer/hammer_disk.h @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer_disk.h,v 1.7 2007/11/20 07:16:28 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_disk.h,v 1.8 2007/11/20 22:55:40 dillon Exp $ */ #ifndef _SYS_UUID_H_ @@ -67,6 +67,8 @@ typedef u_int64_t hammer_tid_t; #define HAMMER_MAX_TID 0xFFFFFFFFFFFFFFFFULL +#define HAMMER_MIN_KEY -0x8000000000000000LL +#define HAMMER_MAX_KEY 0x7FFFFFFFFFFFFFFFLL /* * Most HAMMER data structures are embedded in 16K filesystem buffers. @@ -508,8 +510,10 @@ struct hammer_data_record { * offset. A portion of the namekey is an iterator or randomizer to deal * with collisions. * - * Note that base.base.obj_type holds the filesystem object type of obj_id, - * e.g. a den_type equivalent. + * NOTE: base.base.obj_type holds the filesystem object type of obj_id, + * e.g. a den_type equivalent. + * + * NOTE: den_name / the filename data reference is NOT terminated with \0. * */ struct hammer_entry_record { diff --git a/sys/vfs/hammer/hammer_inode.c b/sys/vfs/hammer/hammer_inode.c index d8d9c941ce..ea7d1adc43 100644 --- a/sys/vfs/hammer/hammer_inode.c +++ b/sys/vfs/hammer/hammer_inode.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer_inode.c,v 1.5 2007/11/20 07:16:28 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_inode.c,v 1.6 2007/11/20 22:55:40 dillon Exp $ */ #include "hammer.h" @@ -235,11 +235,11 @@ hammer_create_inode(hammer_transaction_t trans, struct vattr *vap, { hammer_mount_t hmp; hammer_inode_t ip; + uid_t xuid; hmp = trans->hmp; ip = kmalloc(sizeof(*ip), M_HAMMER, M_WAITOK|M_ZERO); ip->obj_id = hammer_alloc_tid(trans); - kprintf("object id %llx\n", ip->obj_id); KKASSERT(ip->obj_id != 0); ip->obj_asof = HAMMER_MAX_TID; /* XXX */ ip->hmp = hmp; @@ -268,13 +268,24 @@ hammer_create_inode(hammer_transaction_t trans, struct vattr *vap, ip->ino_data.mode = vap->va_mode; ip->ino_data.ctime = trans->tid; ip->ino_data.parent_obj_id = (dip) ? dip->ino_rec.base.base.obj_id : 0; + + /* + * Calculate default uid/gid and overwrite with information from + * the vap. + */ + xuid = hammer_to_unix_xid(&dip->ino_data.uid); + ip->ino_data.gid = dip->ino_data.gid; + xuid = vop_helper_create_uid(hmp->mp, dip->ino_data.mode, xuid, cred, + &vap->va_mode); + ip->ino_data.mode = vap->va_mode; + if (vap->va_vaflags & VA_UID_UUID_VALID) ip->ino_data.uid = vap->va_uid_uuid; - else - hammer_guid_to_uuid(&ip->ino_data.uid, vap->va_uid); + else if (vap->va_uid != (uid_t)VNOVAL) + hammer_guid_to_uuid(&ip->ino_data.uid, xuid); if (vap->va_vaflags & VA_GID_UUID_VALID) ip->ino_data.gid = vap->va_gid_uuid; - else + else if (vap->va_gid != (gid_t)VNOVAL) hammer_guid_to_uuid(&ip->ino_data.gid, vap->va_gid); hammer_ref(&ip->lock); @@ -287,13 +298,13 @@ hammer_create_inode(hammer_transaction_t trans, struct vattr *vap, } /* - * Release a reference on an inode and unload it if told to flush + * Release a reference on an inode and unload it if told to flush. */ void hammer_rel_inode(struct hammer_inode *ip, int flush) { hammer_unref(&ip->lock); - if (flush) + if (flush || ip->ino_rec.ino_nlinks == 0) ip->flags |= HAMMER_INODE_FLUSH; if (ip->lock.refs == 0 && (ip->flags & HAMMER_INODE_FLUSH)) hammer_unload_inode(ip, NULL); @@ -311,11 +322,13 @@ hammer_unload_inode(struct hammer_inode *ip, void *data __unused) ("hammer_unload_inode: %d refs\n", ip->lock.refs)); KKASSERT(ip->vp == NULL); hammer_ref(&ip->lock); + + /* XXX flush inode to disk */ + kprintf("flush inode %p\n", ip); + RB_REMOVE(hammer_ino_rb_tree, &ip->hmp->rb_inos_root, ip); hammer_uncache_node(&ip->cache); - - /* XXX flush */ kfree(ip, M_HAMMER); return(0); } diff --git a/sys/vfs/hammer/hammer_object.c b/sys/vfs/hammer/hammer_object.c index d9a619d747..5b3422fe3d 100644 --- a/sys/vfs/hammer/hammer_object.c +++ b/sys/vfs/hammer/hammer_object.c @@ -31,13 +31,14 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer_object.c,v 1.3 2007/11/20 07:16:28 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_object.c,v 1.4 2007/11/20 22:55:40 dillon Exp $ */ #include "hammer.h" static int hammer_mem_add(hammer_transaction_t trans, hammer_record_t record); +static int hammer_mem_lookup(hammer_cursor_t cursor, hammer_inode_t ip); static int hammer_mem_search(hammer_cursor_t cursor, hammer_inode_t ip); /* @@ -107,6 +108,29 @@ hammer_rec_compare(hammer_base_elm_t info, hammer_record_t rec) return(0); } +/* + * RB_SCAN comparison code for hammer_mem_search(). The argument order + * is reversed so the comparison result has to be negated. key_beg and + * key_end are both inclusive boundaries. + */ +static +int +hammer_rec_scan_cmp(hammer_record_t rec, void *data) +{ + hammer_cursor_t cursor = data; + int r; + + r = hammer_rec_compare(&cursor->key_beg, rec); + if (r > 0) + return(-1); + if (r == 0) + return(0); + r = hammer_rec_compare(&cursor->key_end, rec); + if (r <= 0) + return(1); + return(0); +} + RB_GENERATE(hammer_rec_rb_tree, hammer_record, rb_node, hammer_rec_rb_compare); RB_GENERATE_XLOOKUP(hammer_rec_rb_tree, INFO, hammer_record, rb_node, hammer_rec_compare, hammer_base_elm_t); @@ -148,20 +172,20 @@ hammer_rel_mem_record(struct hammer_record **recordp) /* * Free a record. Clean the structure up even though we are throwing it * away as a sanity check. The actual free operation is delayed while - * the record is referenced. + * the record is referenced. However, the record is removed from the RB + * tree immediately. */ void hammer_free_mem_record(hammer_record_t record) { - if (record->lock.refs) { - record->flags |= HAMMER_RECF_DELETED; - return; - } - if (record->flags & HAMMER_RECF_ONRBTREE) { RB_REMOVE(hammer_rec_rb_tree, &record->ip->rec_tree, record); record->flags &= ~HAMMER_RECF_ONRBTREE; } + if (record->lock.refs) { + record->flags |= HAMMER_RECF_DELETED; + return; + } if (record->flags & HAMMER_RECF_ALLOCDATA) { kfree(record->data, M_HAMMER); record->flags &= ~HAMMER_RECF_ALLOCDATA; @@ -174,16 +198,24 @@ hammer_free_mem_record(hammer_record_t record) * Lookup an in-memory record given the key specified in the cursor. Works * just like hammer_btree_lookup() but operates on an inode's in-memory * record list. + * + * The lookup must fail if the record is marked for deferred deletion. */ static int -hammer_mem_search(hammer_cursor_t cursor, hammer_inode_t ip) +hammer_mem_lookup(hammer_cursor_t cursor, hammer_inode_t ip) { int error; if (cursor->iprec) hammer_rel_mem_record(&cursor->iprec); + if (cursor->ip) { + hammer_rec_rb_tree_scan_info_done(&cursor->scan, + &cursor->ip->rec_tree); + } cursor->ip = ip; + hammer_rec_rb_tree_scan_info_link(&cursor->scan, &ip->rec_tree); + cursor->scan.node = NULL; cursor->iprec = hammer_rec_rb_tree_RB_LOOKUP_INFO( &ip->rec_tree, &cursor->key_beg); if (cursor->iprec == NULL) { @@ -195,6 +227,61 @@ hammer_mem_search(hammer_cursor_t cursor, hammer_inode_t ip) return(error); } +/* + * hammer_mem_search() - locate the first in-memory record matching the + * cursor. + * + * The RB_SCAN function we use is designed as a callback. We terminate it + * (return -1) as soon as we get a match. + */ +static +int +hammer_rec_scan_callback(hammer_record_t rec, void *data) +{ + hammer_cursor_t cursor = data; + + if (cursor->iprec == NULL) { + cursor->iprec = rec; + hammer_ref(&rec->lock); + return(-1); + } + return(0); +} + +static +int +hammer_mem_search(hammer_cursor_t cursor, hammer_inode_t ip) +{ + if (cursor->iprec) + hammer_rel_mem_record(&cursor->iprec); + if (cursor->ip) { + hammer_rec_rb_tree_scan_info_done(&cursor->scan, + &cursor->ip->rec_tree); + } + cursor->ip = ip; + hammer_rec_rb_tree_scan_info_link(&cursor->scan, &ip->rec_tree); + cursor->scan.node = NULL; + hammer_rec_rb_tree_RB_SCAN(&ip->rec_tree, hammer_rec_scan_cmp, + hammer_rec_scan_callback, cursor); + if (cursor->iprec) { + cursor->scan.node = hammer_rec_rb_tree_RB_NEXT(cursor->iprec); + return(0); + } + return(ENOENT); +} + +void +hammer_mem_done(hammer_cursor_t cursor) +{ + if (cursor->ip) { + hammer_rec_rb_tree_scan_info_done(&cursor->scan, + &cursor->ip->rec_tree); + cursor->ip = NULL; + } + if (cursor->iprec) + hammer_rel_mem_record(&cursor->iprec); +} + /************************************************************************ * HAMMER IN-MEMORY RECORD FUNCTIONS * ************************************************************************ @@ -222,23 +309,26 @@ hammer_ip_add_directory(struct hammer_transaction *trans, record = hammer_alloc_mem_record(trans, dip); - bytes = ncp->nc_nlen + 1; + bytes = ncp->nc_nlen; /* NOTE: terminating \0 is NOT included */ + if (++trans->hmp->namekey_iterator == 0) + ++trans->hmp->namekey_iterator; record->rec.entry.base.base.obj_id = dip->obj_id; - record->rec.entry.base.base.key = hammer_directory_namekey(ncp->nc_name, bytes - 1); - record->rec.entry.base.base.key += trans->hmp->namekey_iterator++; + record->rec.entry.base.base.key = + hammer_directory_namekey(ncp->nc_name, bytes); + record->rec.entry.base.base.key += trans->hmp->namekey_iterator; record->rec.entry.base.base.create_tid = trans->tid; record->rec.entry.base.base.rec_type = HAMMER_RECTYPE_DIRENTRY; record->rec.entry.base.base.obj_type = ip->ino_rec.base.base.obj_type; - record->rec.entry.base.base.obj_id = ip->obj_id; + record->rec.entry.obj_id = ip->obj_id; if (bytes <= sizeof(record->rec.entry.den_name)) { record->data = (void *)record->rec.entry.den_name; } else { record->data = kmalloc(bytes, M_HAMMER, M_WAITOK); record->flags |= HAMMER_RECF_ALLOCDATA; - bcopy(ncp->nc_name, record->data, bytes); } - record->data_len = bytes; + bcopy(ncp->nc_name, record->data, bytes); + record->rec.entry.base.data_len = bytes; ++ip->ino_rec.ino_nlinks; hammer_modify_inode(trans, ip, HAMMER_INODE_RDIRTY); error = hammer_mem_add(trans, record); @@ -284,10 +374,17 @@ hammer_ip_del_directory(struct hammer_transaction *trans, } /* - * One less link + * One less link. Mark the inode and all of its records as deleted + * when the last link goes away. The inode will be automatically + * flushed when its last reference goes away. */ if (error == 0) { --ip->ino_rec.ino_nlinks; + if (ip->ino_rec.ino_nlinks == 0) + ip->ino_rec.base.base.delete_tid = trans->tid; + error = hammer_ip_delete_range(trans, ip, + HAMMER_MIN_KEY, HAMMER_MAX_KEY); + KKASSERT(RB_EMPTY(&ip->rec_tree)); hammer_modify_inode(trans, ip, HAMMER_INODE_RDIRTY); } return(error); @@ -353,7 +450,7 @@ hammer_ip_lookup(hammer_cursor_t cursor, struct hammer_inode *ip) * If the element is in-memory return it without searching the * on-disk B-Tree */ - error = hammer_mem_search(cursor, ip); + error = hammer_mem_lookup(cursor, ip); if (error == 0) { cursor->record = &cursor->iprec->rec; return(error); @@ -388,7 +485,7 @@ hammer_ip_first(hammer_cursor_t cursor, struct hammer_inode *ip) /* * Clean up fields and setup for merged scan */ - cursor->flags &= ~(HAMMER_CURSOR_ATEDISK | HAMMER_CURSOR_ATEMEM); + cursor->flags |= HAMMER_CURSOR_ATEDISK | HAMMER_CURSOR_ATEMEM; cursor->flags |= HAMMER_CURSOR_DISKEOF | HAMMER_CURSOR_MEMEOF; if (cursor->iprec) hammer_rel_mem_record(&cursor->iprec); @@ -400,8 +497,10 @@ hammer_ip_first(hammer_cursor_t cursor, struct hammer_inode *ip) error = hammer_btree_lookup(cursor); if (error && error != ENOENT) return(error); - if (error == 0) - cursor->flags &= ~HAMMER_CURSOR_DISKEOF; + if (error == 0) { + cursor->flags &= ~HAMMER_CURSOR_DISKEOF ; + cursor->flags &= ~HAMMER_CURSOR_ATEDISK ; + } } /* @@ -410,8 +509,10 @@ hammer_ip_first(hammer_cursor_t cursor, struct hammer_inode *ip) error = hammer_mem_search(cursor, ip); if (error && error != ENOENT) return(error); - if (error == 0) + if (error == 0) { cursor->flags &= ~HAMMER_CURSOR_MEMEOF; + cursor->flags &= ~HAMMER_CURSOR_ATEMEM; + } /* * This will return the first matching record. @@ -452,18 +553,18 @@ hammer_ip_next(hammer_cursor_t cursor) } /* - * Get the next in-memory record. Records marked for defered - * deletion must be skipped. + * Get the next in-memory record. The record can be ripped out + * of the RB tree so we maintain a scan_info structure to track + * the next node. */ if (cursor->flags & HAMMER_CURSOR_ATEMEM) { if ((cursor->flags & HAMMER_CURSOR_MEMEOF) == 0) { - rec = cursor->iprec; - do { - rec = hammer_rec_rb_tree_RB_NEXT(rec); - } while(rec && (rec->flags & HAMMER_RECF_DELETED)); + rec = cursor->scan.node; /* next node */ if (rec) { cursor->flags &= ~HAMMER_CURSOR_ATEMEM; hammer_ref(&rec->lock); + cursor->scan.node = + hammer_rec_rb_tree_RB_NEXT(rec); } else { cursor->flags |= HAMMER_CURSOR_MEMEOF; } @@ -477,7 +578,7 @@ hammer_ip_next(hammer_cursor_t cursor) * relative position. */ error = 0; - switch(cursor->flags & (HAMMER_CURSOR_DISKEOF | HAMMER_CURSOR_MEMEOF)) { + switch(cursor->flags & (HAMMER_CURSOR_ATEDISK | HAMMER_CURSOR_ATEMEM)) { case 0: /* * Both entries valid @@ -492,14 +593,14 @@ hammer_ip_next(hammer_cursor_t cursor) break; } /* fall through to the memory entry */ - case HAMMER_CURSOR_DISKEOF: + case HAMMER_CURSOR_ATEDISK: /* * Only the memory entry is valid */ cursor->record = &cursor->iprec->rec; cursor->flags |= HAMMER_CURSOR_ATEMEM; break; - case HAMMER_CURSOR_MEMEOF: + case HAMMER_CURSOR_ATEMEM: /* * Only the disk entry is valid */ diff --git a/sys/vfs/hammer/hammer_subs.c b/sys/vfs/hammer/hammer_subs.c index 5c0e52d87e..9a7f3e3d44 100644 --- a/sys/vfs/hammer/hammer_subs.c +++ b/sys/vfs/hammer/hammer_subs.c @@ -31,13 +31,14 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer_subs.c,v 1.4 2007/11/20 07:16:28 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_subs.c,v 1.5 2007/11/20 22:55:40 dillon Exp $ */ /* * HAMMER structural locking */ #include "hammer.h" +#include void hammer_lock_ex(struct hammer_lock *lock) @@ -210,6 +211,30 @@ hammer_get_vnode_type(u_int8_t obj_type) /* not reached */ } +int +hammer_get_dtype(u_int8_t obj_type) +{ + switch(obj_type) { + case HAMMER_OBJTYPE_DIRECTORY: + return(DT_DIR); + case HAMMER_OBJTYPE_REGFILE: + return(DT_REG); + case HAMMER_OBJTYPE_DBFILE: + return(DT_DBF); + case HAMMER_OBJTYPE_FIFO: + return(DT_FIFO); + case HAMMER_OBJTYPE_CDEV: + return(DT_CHR); + case HAMMER_OBJTYPE_BDEV: + return(DT_BLK); + case HAMMER_OBJTYPE_SOFTLINK: + return(DT_LNK); + default: + return(DT_UNKNOWN); + } + /* not reached */ +} + u_int8_t hammer_get_obj_type(enum vtype vtype) { @@ -239,13 +264,16 @@ hammer_get_obj_type(enum vtype vtype) * crc in the MSB and 0 in the LSB. The caller will use the low bits to * generate a unique key and will scan all entries with the same upper * 32 bits when issuing a lookup. + * + * We strip bit 63 in order to provide a positive key, this way a seek + * offset of 0 will represent the base of the directory. */ int64_t hammer_directory_namekey(void *name, int len) { int64_t key; - key = (int64_t)crc32(name, len) << 32; + key = (int64_t)(crc32(name, len) & 0x7FFFFFFF) << 32; return(key); } diff --git a/sys/vfs/hammer/hammer_vnops.c b/sys/vfs/hammer/hammer_vnops.c index 011948c424..09b55b0084 100644 --- a/sys/vfs/hammer/hammer_vnops.c +++ b/sys/vfs/hammer/hammer_vnops.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer_vnops.c,v 1.4 2007/11/20 07:16:28 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_vnops.c,v 1.5 2007/11/20 22:55:40 dillon Exp $ */ #include @@ -559,6 +559,8 @@ hammer_vop_nlink(struct vop_nlink_args *ap) if (error) { hammer_abort_transaction(&trans); } else { + cache_setunresolved(nch); + cache_setvp(nch, ap->a_vp); hammer_commit_transaction(&trans); } return (error); @@ -716,14 +718,101 @@ hammer_vop_print(struct vop_print_args *ap) } /* - * hammer_vop_readdir { vp, uio, cred, *eofflag } + * hammer_vop_readdir { vp, uio, cred, *eofflag, *ncookies, off_t **cookies } */ static int hammer_vop_readdir(struct vop_readdir_args *ap) { - kprintf("hammer_vop_readdir\n"); - return EOPNOTSUPP; + struct hammer_cursor cursor; + struct hammer_inode *ip; + struct uio *uio; + hammer_record_ondisk_t rec; + hammer_base_elm_t base; + int error; + int cookie_index; + int ncookies; + off_t *cookies; + off_t saveoff; + int r; + + ip = VTOI(ap->a_vp); + uio = ap->a_uio; + hammer_init_cursor_ip(&cursor, ip); + + /* + * Key range (begin and end inclusive) to scan. Directory keys + * directly translate to a 64 bit 'seek' position. + */ + cursor.key_beg.obj_id = ip->obj_id; + cursor.key_beg.create_tid = ip->obj_asof; + cursor.key_beg.delete_tid = 0; + cursor.key_beg.rec_type = HAMMER_RECTYPE_DIRENTRY; + cursor.key_beg.obj_type = 0; + cursor.key_beg.key = uio->uio_offset; + + cursor.key_end = cursor.key_beg; + cursor.key_end.key = HAMMER_MAX_KEY; + + if (ap->a_ncookies) { + ncookies = uio->uio_resid / 16 + 1; + if (ncookies > 1024) + ncookies = 1024; + cookies = kmalloc(ncookies * sizeof(off_t), M_TEMP, M_WAITOK); + cookie_index = 0; + } else { + ncookies = -1; + cookies = NULL; + cookie_index = 0; + } + + saveoff = cursor.key_beg.key; + error = hammer_ip_first(&cursor, ip); + + while (error == 0) { + error = hammer_ip_resolve_data(&cursor); + if (error) + break; + rec = cursor.record; + base = &rec->base.base; + saveoff = base->key; + + r = vop_write_dirent( + &error, uio, rec->entry.obj_id, + rec->entry.base.data_len, + hammer_get_dtype(rec->entry.base.base.obj_type), + (void *)cursor.data); + if (r) + break; + ++saveoff; + if (cookies) + cookies[cookie_index] = base->key; + ++cookie_index; + if (cookie_index == ncookies) + break; + error = hammer_ip_next(&cursor); + } + hammer_done_cursor(&cursor); + + if (ap->a_eofflag) + *ap->a_eofflag = (error == ENOENT); + if (error == ENOENT) + error = 0; + uio->uio_offset = saveoff; + if (error && cookie_index == 0) { + if (cookies) { + kfree(cookies, M_TEMP); + *ap->a_ncookies = 0; + *ap->a_cookies = NULL; + } + } else { + error = 0; + if (cookies) { + *ap->a_ncookies = cookie_index; + *ap->a_cookies = cookies; + } + } + return(error); } /* @@ -900,14 +989,14 @@ hammer_vop_setattr(struct vop_setattr_args *ap) } if (vap->va_uid != (uid_t)VNOVAL) { hammer_guid_to_uuid(&uuid, vap->va_uid); - if (bcmp(&uuid, &ip->ino_data.uid, sizeof(uuid)) == 0) { + if (bcmp(&uuid, &ip->ino_data.uid, sizeof(uuid)) != 0) { ip->ino_data.uid = uuid; modflags |= HAMMER_INODE_DDIRTY; } } if (vap->va_gid != (uid_t)VNOVAL) { - hammer_guid_to_uuid(&uuid, vap->va_uid); - if (bcmp(&uuid, &ip->ino_data.gid, sizeof(uuid)) == 0) { + hammer_guid_to_uuid(&uuid, vap->va_gid); + if (bcmp(&uuid, &ip->ino_data.gid, sizeof(uuid)) != 0) { ip->ino_data.gid = uuid; modflags |= HAMMER_INODE_DDIRTY; } @@ -1197,7 +1286,6 @@ hammer_dounlink(struct nchandle *nch, struct vnode *dvp, struct ucred *cred, hammer_inode_t ip; hammer_record_ondisk_t rec; struct hammer_cursor cursor; - struct vnode *vp; int64_t namekey; int error; @@ -1263,11 +1351,7 @@ hammer_dounlink(struct nchandle *nch, struct vnode *dvp, struct ucred *cred, } hammer_rel_inode(ip, 0); - error = hammer_vfs_vget(dip->hmp->mp, rec->entry.obj_id, &vp); if (error == 0) { - vn_unlock(vp); - cache_setvp(nch, vp); - vrele(vp); hammer_commit_transaction(&trans); } else { hammer_abort_transaction(&trans); -- 2.41.0