From 7a04d74f44666553c6e04a1703941125d3d48c1e Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Sun, 30 Dec 2007 00:47:22 +0000 Subject: [PATCH] HAMMER 12/many - add VOPs for symlinks, device, and fifo support. * Add some missing VOP bits. Add a fixed attribute record type and store the symlink path as fixed attribute record #1. * Adjust hammer_inode_data to add missing major and minor device fields. * Add support for adding generic records and special case deletion of an object's entire set of records. * Fix a minor bug that was causing the root cluster to be improperly kfree()'d. --- sbin/newfs_hammer/newfs_hammer.c | 4 +- sys/vfs/hammer/hammer.h | 8 +- sys/vfs/hammer/hammer_btree.c | 3 +- sys/vfs/hammer/hammer_cursor.c | 9 +- sys/vfs/hammer/hammer_disk.h | 16 +-- sys/vfs/hammer/hammer_inode.c | 34 ++++- sys/vfs/hammer/hammer_io.c | 12 +- sys/vfs/hammer/hammer_object.c | 100 +++++++++++++- sys/vfs/hammer/hammer_ondisk.c | 5 +- sys/vfs/hammer/hammer_vfsops.c | 4 +- sys/vfs/hammer/hammer_vnops.c | 219 +++++++++++++++++++++++++++++-- 11 files changed, 368 insertions(+), 46 deletions(-) diff --git a/sbin/newfs_hammer/newfs_hammer.c b/sbin/newfs_hammer/newfs_hammer.c index ba06e04782..a308eabe49 100644 --- a/sbin/newfs_hammer/newfs_hammer.c +++ b/sbin/newfs_hammer/newfs_hammer.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sbin/newfs_hammer/newfs_hammer.c,v 1.10 2007/12/14 08:05:37 dillon Exp $ + * $DragonFly: src/sbin/newfs_hammer/newfs_hammer.c,v 1.11 2007/12/30 00:47:20 dillon Exp $ */ #include "newfs_hammer.h" @@ -671,7 +671,7 @@ format_root(struct cluster_info *cluster) idata->version = HAMMER_INODE_DATA_VERSION; idata->mode = 0755; - rec->base.base.obj_id = 1; + rec->base.base.obj_id = HAMMER_OBJID_ROOT; rec->base.base.key = 0; rec->base.base.create_tid = createtid(); rec->base.base.delete_tid = 0; diff --git a/sys/vfs/hammer/hammer.h b/sys/vfs/hammer/hammer.h index 5001e508e5..e077daf91e 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.14 2007/12/29 09:01:27 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer.h,v 1.15 2007/12/30 00:47:22 dillon Exp $ */ /* * This header file contains structures used internally by the HAMMERFS @@ -406,6 +406,8 @@ struct hammer_sync_info { #if defined(_KERNEL) extern struct vop_ops hammer_vnode_vops; +extern struct vop_ops hammer_spec_vops; +extern struct vop_ops hammer_fifo_vops; extern struct hammer_alist_config Buf_alist_config; extern struct hammer_alist_config Vol_normal_alist_config; extern struct hammer_alist_config Vol_super_alist_config; @@ -577,9 +579,13 @@ int hammer_ip_add_directory(struct hammer_transaction *trans, int hammer_ip_del_directory(struct hammer_transaction *trans, hammer_cursor_t cursor, hammer_inode_t dip, hammer_inode_t ip); +int hammer_ip_add_record(struct hammer_transaction *trans, + hammer_record_t record); int hammer_ip_delete_range(struct hammer_transaction *trans, hammer_inode_t ip, int64_t ran_beg, int64_t ran_end, struct hammer_cursor **spikep); +int hammer_ip_delete_range_all(struct hammer_transaction *trans, + hammer_inode_t ip); int hammer_ip_sync_data(struct hammer_transaction *trans, hammer_inode_t ip, int64_t offset, void *data, int bytes, struct hammer_cursor **spikep); diff --git a/sys/vfs/hammer/hammer_btree.c b/sys/vfs/hammer/hammer_btree.c index ef8f428dc5..1840c532d1 100644 --- a/sys/vfs/hammer/hammer_btree.c +++ b/sys/vfs/hammer/hammer_btree.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_btree.c,v 1.11 2007/12/29 09:01:27 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_btree.c,v 1.12 2007/12/30 00:47:22 dillon Exp $ */ /* @@ -181,7 +181,6 @@ hammer_btree_iterate(hammer_cursor_t cursor) elm = &node->elms[cursor->index]; r = hammer_btree_cmp(&cursor->key_end, &elm[0].base); s = hammer_btree_cmp(&cursor->key_beg, &elm[1].base); - kprintf("SCAN %d r/s %d/%d\n", cursor->index, r, s); if (r < 0) { error = ENOENT; break; diff --git a/sys/vfs/hammer/hammer_cursor.c b/sys/vfs/hammer/hammer_cursor.c index 192315b2a4..a7edbb298d 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.6 2007/12/29 09:01:27 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_cursor.c,v 1.7 2007/12/30 00:47:22 dillon Exp $ */ /* @@ -268,6 +268,8 @@ hammer_load_cursor_parent_local(hammer_cursor_t cursor) break; } } + if (i == parent->ondisk->count) + panic("Bad B-Tree link: parent %p node %p\n", parent, node); KKASSERT(i != parent->ondisk->count); KKASSERT(parent->ondisk->elms[i].internal.rec_offset == 0); cursor->parent = parent; @@ -319,7 +321,6 @@ hammer_load_cursor_parent_cluster(hammer_cursor_t cursor) parent = hammer_get_node(pcluster, ondisk->clu_btree_parent_offset, &error); hammer_rel_cluster(pcluster, 0); - kprintf("parent %p clu_no %d\n", parent, clu_no); if (error) return (error); @@ -329,8 +330,6 @@ hammer_load_cursor_parent_cluster(hammer_cursor_t cursor) elm = NULL; for (i = 0; i < parent->ondisk->count; ++i) { elm = &parent->ondisk->elms[i]; - if (elm->internal.subtree_type == HAMMER_BTREE_TYPE_CLUSTER) - kprintf("SUBTEST CLU %d\n", elm->internal.subtree_clu_no); if (elm->internal.rec_offset != 0 && elm->internal.subtree_type == HAMMER_BTREE_TYPE_CLUSTER && elm->internal.subtree_clu_no == cursor->node->cluster->clu_no) { @@ -529,6 +528,8 @@ hammer_cursor_down(hammer_cursor_t cursor) &error); if (error == 0) { KKASSERT(elm->internal.subtree_type == node->ondisk->type); + if(node->ondisk->parent != cursor->parent->node_offset) + kprintf("node %p %d vs %d\n", node, node->ondisk->parent, cursor->parent->node_offset); KKASSERT(node->ondisk->parent == cursor->parent->node_offset); } } diff --git a/sys/vfs/hammer/hammer_disk.h b/sys/vfs/hammer/hammer_disk.h index 978d41a73c..0952cd6453 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.12 2007/12/14 08:05:39 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_disk.h,v 1.13 2007/12/30 00:47:22 dillon Exp $ */ #ifndef _SYS_UUID_H_ @@ -457,6 +457,9 @@ struct hammer_base_record { #define HAMMER_RECTYPE_DIRENTRY 0x11 #define HAMMER_RECTYPE_DB 0x12 #define HAMMER_RECTYPE_EXT 0x13 /* ext attributes */ +#define HAMMER_RECTYPE_FIX 0x14 /* fixed attribute */ + +#define HAMMER_FIXKEY_SYMLINK 1 #define HAMMER_OBJTYPE_UNKNOWN 0 /* (never exists on-disk) */ #define HAMMER_OBJTYPE_DIRECTORY 1 @@ -620,10 +623,6 @@ typedef union hammer_fsbuf_ondisk *hammer_fsbuf_ondisk_t; * modifications to the contents of this structure will result in a record * replacement operation. * - * state_sum allows a filesystem object to be validated to a degree by - * generating a checksum of all of its pieces (in no particular order) and - * checking it against this field. - * * short_data_off allows a small amount of data to be embedded in the * hammer_inode_data structure. HAMMER typically uses this to represent * up to 64 bytes of data, or to hold symlinks. Remember that allocations @@ -640,9 +639,8 @@ struct hammer_inode_data { u_int16_t version; /* inode data version */ u_int16_t mode; /* basic unix permissions */ u_int32_t uflags; /* chflags */ - u_int16_t short_data_off; /* degenerate data case */ - u_int16_t short_data_len; - u_int32_t state_sum; + u_int32_t rmajor; /* used by device nodes */ + u_int32_t rminor; /* used by device nodes */ u_int64_t ctime; u_int64_t parent_obj_id;/* parent directory obj_id */ uuid_t uid; @@ -652,6 +650,8 @@ struct hammer_inode_data { #define HAMMER_INODE_DATA_VERSION 1 +#define HAMMER_OBJID_ROOT 1 + /* * Rollup various structures embedded as record data */ diff --git a/sys/vfs/hammer/hammer_inode.c b/sys/vfs/hammer/hammer_inode.c index 341489a354..27050ed9ce 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.12 2007/12/29 09:01:27 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_inode.c,v 1.13 2007/12/30 00:47:22 dillon Exp $ */ #include "hammer.h" @@ -135,6 +135,23 @@ hammer_get_vnode(struct hammer_inode *ip, int lktype, struct vnode **vpp) ip->vp = vp; vp->v_type = hammer_get_vnode_type( ip->ino_rec.base.base.obj_type); + + switch(ip->ino_rec.base.base.obj_type) { + case HAMMER_OBJTYPE_CDEV: + case HAMMER_OBJTYPE_BDEV: + vp->v_ops = &ip->hmp->mp->mnt_vn_spec_ops; + addaliasu(vp, ip->ino_data.rmajor, + ip->ino_data.rminor); + break; + case HAMMER_OBJTYPE_FIFO: + vp->v_ops = &ip->hmp->mp->mnt_vn_fifo_ops; + break; + default: + break; + } + if (ip->obj_id == HAMMER_OBJID_ROOT) + vp->v_flag |= VROOT; + vp->v_data = (void *)ip; /* vnode locked by getnewvnode() */ /* make related vnode dirty if inode dirty? */ @@ -288,6 +305,16 @@ hammer_create_inode(hammer_transaction_t trans, struct vattr *vap, ip->ino_data.ctime = trans->tid; ip->ino_data.parent_obj_id = (dip) ? dip->ino_rec.base.base.obj_id : 0; + switch(ip->ino_rec.base.base.obj_type) { + case HAMMER_OBJTYPE_CDEV: + case HAMMER_OBJTYPE_BDEV: + ip->ino_data.rmajor = vap->va_rmajor; + ip->ino_data.rminor = vap->va_rminor; + break; + default: + break; + } + /* * Calculate default uid/gid and overwrite with information from * the vap. @@ -524,9 +551,8 @@ hammer_sync_inode(hammer_inode_t ip, int waitfor, int handle_delete) if (ip->ino_rec.ino_nlinks == 0 && handle_delete) { if (ip->vp) vtruncbuf(ip->vp, 0, HAMMER_BUFSIZE); - error = hammer_ip_delete_range(&trans, ip, - HAMMER_MIN_KEY, HAMMER_MAX_KEY, - NULL); + error = hammer_ip_delete_range_all(&trans, ip); + kprintf("delete_range_all error %d\n", error); KKASSERT(RB_EMPTY(&ip->rec_tree)); ip->flags &= ~HAMMER_INODE_TID; ip->ino_rec.base.base.delete_tid = trans.tid; diff --git a/sys/vfs/hammer/hammer_io.c b/sys/vfs/hammer/hammer_io.c index eaf74939d2..13e42e879d 100644 --- a/sys/vfs/hammer/hammer_io.c +++ b/sys/vfs/hammer/hammer_io.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_io.c,v 1.7 2007/12/29 09:01:27 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_io.c,v 1.8 2007/12/30 00:47:22 dillon Exp $ */ /* * IO Primitives and buffer cache management @@ -292,7 +292,6 @@ hammer_io_flush(struct hammer_io *io, struct hammer_sync_info *info) io->modified = 1; if (io->modified == 0) return; - kprintf("IO FLUSH BP %p TYPE %d REFS %d\n", bp, io->type, io->lock.refs); hammer_lock_ex(&io->lock); if ((bp = io->bp) != NULL && io->modified) { @@ -317,8 +316,8 @@ hammer_io_flush(struct hammer_io *io, struct hammer_sync_info *info) * also set B_LOCKED so we know something tried to * flush it. */ - kprintf("can't flush bp %p, %d refs - delaying\n", - bp, io->lock.refs); + kprintf("DELAYING IO FLUSH BP %p TYPE %d REFS %d\n", + bp, io->type, io->lock.refs); bp->b_flags |= B_LOCKED; bqrelse(bp); } @@ -359,8 +358,6 @@ hammer_io_complete(struct buf *bp) if (io->io.type == HAMMER_STRUCTURE_CLUSTER) { if (io->cluster.state == HAMMER_CLUSTER_ASYNC) { - kprintf("cluster write complete flags %08x\n", - io->cluster.ondisk->clu_flags); io->cluster.state = HAMMER_CLUSTER_OPEN; wakeup(&io->cluster); } @@ -503,7 +500,6 @@ hammer_io_checkwrite(struct buf *bp) * Cannot write out a cluster buffer if the cluster header * I/O opening the cluster has not completed. */ - kprintf("hammer_io_checkwrite: w/ depend - delayed\n"); bp->b_flags |= B_LOCKED; return(-1); } else if (iou->io.lock.refs) { @@ -511,7 +507,6 @@ hammer_io_checkwrite(struct buf *bp) * Cannot write out a bp if its associated buffer has active * references. */ - kprintf("hammer_io_checkwrite: w/ refs - delayed\n"); bp->b_flags |= B_LOCKED; return(-1); } else { @@ -521,7 +516,6 @@ hammer_io_checkwrite(struct buf *bp) */ if (iou->io.type == HAMMER_STRUCTURE_CLUSTER) hammer_close_cluster(&iou->cluster); - kprintf("hammer_io_checkwrite: ok\n"); KKASSERT(iou->io.released); hammer_io_disassociate(iou); return(0); diff --git a/sys/vfs/hammer/hammer_object.c b/sys/vfs/hammer/hammer_object.c index bb0bd65d27..e0db60a4f8 100644 --- a/sys/vfs/hammer/hammer_object.c +++ b/sys/vfs/hammer/hammer_object.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_object.c,v 1.10 2007/12/29 09:01:27 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_object.c,v 1.11 2007/12/30 00:47:22 dillon Exp $ */ #include "hammer.h" @@ -403,6 +403,47 @@ hammer_ip_del_directory(struct hammer_transaction *trans, return(error); } +/* + * Add a record to an inode. + * + * The caller must allocate the record with hammer_alloc_mem_record(ip) and + * initialize the following additional fields: + * + * record->rec.entry.base.base.key + * record->rec.entry.base.base.rec_type + * record->rec.entry.base.base.data_len + * record->data (a copy will be kmalloc'd if not embedded) + */ +int +hammer_ip_add_record(struct hammer_transaction *trans, hammer_record_t record) +{ + hammer_inode_t ip = record->ip; + int error; + int bytes; + void *data; + + record->rec.base.base.obj_id = ip->obj_id; + record->rec.base.base.create_tid = trans->tid; + record->rec.base.base.obj_type = ip->ino_rec.base.base.obj_type; + bytes = record->rec.base.data_len; + + if (record->data) { + if ((char *)record->data < (char *)&record->rec || + (char *)record->data >= (char *)(&record->rec + 1)) { + data = kmalloc(bytes, M_HAMMER, M_WAITOK); + record->flags |= HAMMER_RECF_ALLOCDATA; + bcopy(record->data, data, bytes); + record->data = data; + } else { + record->flags |= HAMMER_RECF_EMBEDDED_DATA; + } + } + hammer_modify_inode(trans, ip, + HAMMER_INODE_RDIRTY | HAMMER_INODE_TID); + error = hammer_mem_add(trans, record); + return(error); +} + /* * Sync data from a buffer cache buffer (typically) to the filesystem. This * is called via the strategy called from a cached data source. This code @@ -565,7 +606,7 @@ hammer_ip_sync_record(hammer_record_t record, struct hammer_cursor **spike) rec->base.data_offset = ((char *)bdata - (char *)&record->rec); KKASSERT(rec->base.data_offset >= 0 && - rec->base.data_offset + rec->base.data_len < + rec->base.data_offset + rec->base.data_len <= sizeof(*rec)); rec->base.data_offset += hammer_bclu_offset(cursor.record_buffer, rec); } else { @@ -1007,7 +1048,6 @@ hammer_ip_delete_range(hammer_transaction_t trans, hammer_inode_t ip, hammer_record_ondisk_t rec; hammer_base_elm_t base; int error; - int isregfile; int64_t off; hammer_init_cursor_ip(&cursor, ip); @@ -1023,7 +1063,6 @@ hammer_ip_delete_range(hammer_transaction_t trans, hammer_inode_t ip, cursor.key_beg.rec_type = HAMMER_RECTYPE_DB; cursor.key_end.rec_type = HAMMER_RECTYPE_DB; cursor.key_end.key = ran_end; - isregfile = 0; } else { /* * The key in the B-Tree is (base+bytes), so the first possible @@ -1040,7 +1079,6 @@ hammer_ip_delete_range(hammer_transaction_t trans, hammer_inode_t ip, cursor.key_end.key = 0x7FFFFFFFFFFFFFFFLL; else cursor.key_end.key = ran_end + MAXPHYS + 1; - isregfile = 1; } cursor.flags |= HAMMER_CURSOR_END_INCLUSIVE; @@ -1119,6 +1157,58 @@ hammer_ip_delete_range(hammer_transaction_t trans, hammer_inode_t ip, return(error); } +int +hammer_ip_delete_range_all(hammer_transaction_t trans, hammer_inode_t ip) +{ + struct hammer_cursor cursor; + hammer_record_ondisk_t rec; + hammer_base_elm_t base; + int error; + + hammer_init_cursor_ip(&cursor, ip); + + 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.obj_type = 0; + cursor.key_beg.rec_type = 0; + cursor.key_beg.key = HAMMER_MIN_KEY; + + cursor.key_end = cursor.key_beg; + cursor.key_end.rec_type = 0xFFFF; + cursor.key_end.key = HAMMER_MAX_KEY; + + cursor.flags |= HAMMER_CURSOR_END_INCLUSIVE; + + error = hammer_ip_first(&cursor, ip); + + /* + * Iterate through matching records and mark them as deleted. + */ + while (error == 0) { + rec = cursor.record; + base = &rec->base.base; + + KKASSERT(base->delete_tid == 0); + + /* + * Mark the record and B-Tree entry as deleted. This will + * also physically delete the B-Tree entry, record, and + * data if the retention policy dictates. The function + * will set HAMMER_CURSOR_DELBTREE which hammer_ip_next() + * uses to perform a fixup. + */ + error = hammer_ip_delete_record(&cursor, trans->tid); + if (error) + break; + error = hammer_ip_next(&cursor); + } + hammer_done_cursor(&cursor); + if (error == ENOENT) + error = 0; + return(error); +} + /* * Delete the record at the current cursor */ diff --git a/sys/vfs/hammer/hammer_ondisk.c b/sys/vfs/hammer/hammer_ondisk.c index 6436f26e99..edcad37bf2 100644 --- a/sys/vfs/hammer/hammer_ondisk.c +++ b/sys/vfs/hammer/hammer_ondisk.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_ondisk.c,v 1.11 2007/12/29 09:01:27 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_ondisk.c,v 1.12 2007/12/30 00:47:22 dillon Exp $ */ /* * Manage HAMMER's on-disk structures. These routines are primarily @@ -949,7 +949,8 @@ hammer_rel_cluster(hammer_cluster_t cluster, int flush) /* * Final cleanup */ - if (cluster->io.bp == NULL && + if (cluster != cluster->volume->hmp->rootcl && + cluster->io.bp == NULL && cluster->io.lock.refs == 1 && RB_EMPTY(&cluster->rb_nods_root)) { KKASSERT(RB_EMPTY(&cluster->rb_bufs_root)); diff --git a/sys/vfs/hammer/hammer_vfsops.c b/sys/vfs/hammer/hammer_vfsops.c index 75171fdef9..d11036f570 100644 --- a/sys/vfs/hammer/hammer_vfsops.c +++ b/sys/vfs/hammer/hammer_vfsops.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_vfsops.c,v 1.10 2007/12/29 09:01:27 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_vfsops.c,v 1.11 2007/12/30 00:47:22 dillon Exp $ */ #include @@ -191,6 +191,8 @@ hammer_vfs_mount(struct mount *mp, char *mntpt, caddr_t data, mp->mnt_flag |= MNT_LOCAL; vfs_add_vnodeops(mp, &hammer_vnode_vops, &mp->mnt_vn_norm_ops); + vfs_add_vnodeops(mp, &hammer_spec_vops, &mp->mnt_vn_spec_ops); + vfs_add_vnodeops(mp, &hammer_fifo_vops, &mp->mnt_vn_fifo_ops); /* * The root volume's ondisk pointer is only valid if we hold a diff --git a/sys/vfs/hammer/hammer_vnops.c b/sys/vfs/hammer/hammer_vnops.c index dec31cf15b..3eee9cdeea 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.10 2007/12/29 09:01:27 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_vnops.c,v 1.11 2007/12/30 00:47:22 dillon Exp $ */ #include @@ -44,6 +44,7 @@ #include #include #include +#include #include "hammer.h" /* @@ -76,6 +77,14 @@ static int hammer_vop_strategy(struct vop_strategy_args *); static int hammer_vop_nsymlink(struct vop_nsymlink_args *); static int hammer_vop_nwhiteout(struct vop_nwhiteout_args *); +static int hammer_vop_fifoclose (struct vop_close_args *); +static int hammer_vop_fiforead (struct vop_read_args *); +static int hammer_vop_fifowrite (struct vop_write_args *); + +static int hammer_vop_specclose (struct vop_close_args *); +static int hammer_vop_specread (struct vop_read_args *); +static int hammer_vop_specwrite (struct vop_write_args *); + struct vop_ops hammer_vnode_vops = { .vop_default = vop_defaultop, .vop_fsync = hammer_vop_fsync, @@ -109,6 +118,32 @@ struct vop_ops hammer_vnode_vops = { .vop_nwhiteout = hammer_vop_nwhiteout }; +struct vop_ops hammer_spec_vops = { + .vop_default = spec_vnoperate, + .vop_fsync = hammer_vop_fsync, + .vop_read = hammer_vop_specread, + .vop_write = hammer_vop_specwrite, + .vop_access = hammer_vop_access, + .vop_close = hammer_vop_specclose, + .vop_getattr = hammer_vop_getattr, + .vop_inactive = hammer_vop_inactive, + .vop_reclaim = hammer_vop_reclaim, + .vop_setattr = hammer_vop_setattr +}; + +struct vop_ops hammer_fifo_vops = { + .vop_default = fifo_vnoperate, + .vop_fsync = hammer_vop_fsync, + .vop_read = hammer_vop_fiforead, + .vop_write = hammer_vop_fifowrite, + .vop_access = hammer_vop_access, + .vop_close = hammer_vop_fifoclose, + .vop_getattr = hammer_vop_getattr, + .vop_inactive = hammer_vop_inactive, + .vop_reclaim = hammer_vop_reclaim, + .vop_setattr = hammer_vop_setattr +}; + static int hammer_dounlink(struct nchandle *nch, struct vnode *dvp, struct ucred *cred, int flags); static int hammer_vop_strategy_read(struct vop_strategy_args *ap); @@ -389,7 +424,7 @@ hammer_vop_ncreate(struct vop_ncreate_args *ap) /* * Create a new filesystem object of the requested type. The - * returned inode will be referenceds but not locked. + * returned inode will be referenced but not locked. */ error = hammer_create_inode(&trans, ap->a_vap, ap->a_cred, dip, &nip); @@ -469,6 +504,17 @@ hammer_vop_getattr(struct vop_getattr_args *ap) vap->va_fsid_uuid = ip->hmp->fsid; vap->va_vaflags = VA_UID_UUID_VALID | VA_GID_UUID_VALID | VA_FSID_UUID_VALID; + + switch (ip->ino_rec.base.base.obj_type) { + case HAMMER_OBJTYPE_CDEV: + case HAMMER_OBJTYPE_BDEV: + vap->va_rmajor = ip->ino_data.rmajor; + vap->va_rminor = ip->ino_data.rminor; + break; + default: + break; + } + return(0); } @@ -855,10 +901,13 @@ hammer_vop_readdir(struct vop_readdir_args *ap) base = &rec->base.base; saveoff = base->key; + if (base->obj_id != ip->obj_id) + panic("readdir: bad record at %p", cursor.node); + r = vop_write_dirent( &error, uio, rec->entry.obj_id, - rec->entry.base.data_len, hammer_get_dtype(rec->entry.base.base.obj_type), + rec->entry.base.data_len, (void *)cursor.data); if (r) break; @@ -874,8 +923,6 @@ hammer_vop_readdir(struct vop_readdir_args *ap) 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) { @@ -884,7 +931,8 @@ hammer_vop_readdir(struct vop_readdir_args *ap) *ap->a_cookies = NULL; } } else { - error = 0; + if (error == ENOENT) + error = 0; if (cookies) { *ap->a_ncookies = cookie_index; *ap->a_cookies = cookies; @@ -900,7 +948,35 @@ static int hammer_vop_readlink(struct vop_readlink_args *ap) { - return EOPNOTSUPP; + struct hammer_cursor cursor; + struct hammer_inode *ip; + int error; + + ip = VTOI(ap->a_vp); + 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_FIX; + cursor.key_beg.obj_type = 0; + cursor.key_beg.key = HAMMER_FIXKEY_SYMLINK; + + error = hammer_ip_lookup(&cursor, ip); + if (error == 0) { + error = hammer_ip_resolve_data(&cursor); + if (error == 0) { + error = uiomove((char *)cursor.data, + cursor.record->generic.base.data_len, + ap->a_uio); + } + } + hammer_done_cursor(&cursor); + return(error); } /* @@ -1155,7 +1231,80 @@ static int hammer_vop_nsymlink(struct vop_nsymlink_args *ap) { - return EOPNOTSUPP; + struct hammer_transaction trans; + struct hammer_inode *dip; + struct hammer_inode *nip; + struct nchandle *nch; + hammer_record_t record; + int error; + int bytes; + + ap->a_vap->va_type = VLNK; + + nch = ap->a_nch; + dip = VTOI(ap->a_dvp); + + /* + * Create a transaction to cover the operations we perform. + */ + hammer_start_transaction(&trans, dip->hmp); + + /* + * Create a new filesystem object of the requested type. The + * returned inode will be referenced but not locked. + */ + + error = hammer_create_inode(&trans, ap->a_vap, ap->a_cred, dip, &nip); + if (error) { + hammer_abort_transaction(&trans); + *ap->a_vpp = NULL; + return (error); + } + + /* + * Add the new filesystem object to the directory. This will also + * bump the inode's link count. + */ + error = hammer_ip_add_directory(&trans, dip, nch->ncp, nip); + + /* + * Add a record representing the symlink. symlink stores the link + * as pure data, not a string, and is no \0 terminated. + */ + if (error == 0) { + record = hammer_alloc_mem_record(nip); + bytes = strlen(ap->a_target); + + record->rec.generic.base.base.key = HAMMER_FIXKEY_SYMLINK; + record->rec.generic.base.base.rec_type = HAMMER_RECTYPE_FIX; + record->rec.generic.base.data_len = bytes; + if (bytes <= sizeof(record->rec.generic.filler)) { + record->data = (void *)record->rec.generic.filler; + bcopy(ap->a_target, record->data, bytes); + } else { + record->data = (void *)ap->a_target; + /* will be reallocated by routine below */ + } + error = hammer_ip_add_record(&trans, record); + } + + /* + * Finish up. + */ + if (error) { + hammer_rel_inode(nip, 0); + hammer_abort_transaction(&trans); + *ap->a_vpp = NULL; + } else { + hammer_commit_transaction(&trans); + error = hammer_get_vnode(nip, LK_EXCLUSIVE, ap->a_vpp); + hammer_rel_inode(nip, 0); + if (error == 0) { + cache_setunresolved(ap->a_nch); + cache_setvp(ap->a_nch, *ap->a_vpp); + } + } + return (error); } /* @@ -1491,3 +1640,57 @@ hammer_dounlink(struct nchandle *nch, struct vnode *dvp, struct ucred *cred, return (error); } +/************************************************************************ + * FIFO AND SPECFS OPS * + ************************************************************************ + * + */ + +static int +hammer_vop_fifoclose (struct vop_close_args *ap) +{ + /* XXX update itimes */ + return (VOCALL(&fifo_vnode_vops, &ap->a_head)); +} + +static int +hammer_vop_fiforead (struct vop_read_args *ap) +{ + int error; + + error = VOCALL(&fifo_vnode_vops, &ap->a_head); + /* XXX update access time */ + return (error); +} + +static int +hammer_vop_fifowrite (struct vop_write_args *ap) +{ + int error; + + error = VOCALL(&fifo_vnode_vops, &ap->a_head); + /* XXX update access time */ + return (error); +} + +static int +hammer_vop_specclose (struct vop_close_args *ap) +{ + /* XXX update itimes */ + return (VOCALL(&spec_vnode_vops, &ap->a_head)); +} + +static int +hammer_vop_specread (struct vop_read_args *ap) +{ + /* XXX update access time */ + return (VOCALL(&spec_vnode_vops, &ap->a_head)); +} + +static int +hammer_vop_specwrite (struct vop_write_args *ap) +{ + /* XXX update last change time */ + return (VOCALL(&spec_vnode_vops, &ap->a_head)); +} + -- 2.41.0