Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/fs/v7fs/v7fs_vnops.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/fs/v7fs/v7fs_vnops.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.11 retrieving revision 1.11.2.3 diff -u -p -r1.11 -r1.11.2.3 --- src/sys/fs/v7fs/v7fs_vnops.c 2012/04/29 22:54:00 1.11 +++ src/sys/fs/v7fs/v7fs_vnops.c 2017/12/03 11:38:44 1.11.2.3 @@ -1,4 +1,4 @@ -/* $NetBSD: v7fs_vnops.c,v 1.11 2012/04/29 22:54:00 chs Exp $ */ +/* $NetBSD: v7fs_vnops.c,v 1.11.2.3 2017/12/03 11:38:44 jdolecek Exp $ */ /*- * Copyright (c) 2004, 2011 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: v7fs_vnops.c,v 1.11 2012/04/29 22:54:00 chs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: v7fs_vnops.c,v 1.11.2.3 2017/12/03 11:38:44 jdolecek Exp $"); #if defined _KERNEL_OPT #include "opt_v7fs.h" #endif @@ -41,7 +41,7 @@ __KERNEL_RCSID(0, "$NetBSD: v7fs_vnops.c #include #include #include -#include +#include #include #include #include @@ -64,11 +64,6 @@ __KERNEL_RCSID(0, "$NetBSD: v7fs_vnops.c #define DPRINTF(arg...) ((void)0) #endif -MALLOC_JUSTDEFINE(M_V7FS_VNODE, "v7fs vnode", "v7fs vnode structures"); -MALLOC_DECLARE(M_V7FS); - -int v7fs_vnode_reload(struct mount *, struct vnode *); - static v7fs_mode_t vtype_to_v7fs_mode(enum vtype); static uint8_t v7fs_mode_to_d_type(v7fs_mode_t); @@ -93,7 +88,7 @@ v7fs_mode_to_d_type(v7fs_mode_t mode) int v7fs_lookup(void *v) { - struct vop_lookup_args /* { + struct vop_lookup_v2_args /* { struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; @@ -134,6 +129,10 @@ v7fs_lookup(void *v) return EROFS; } + /* No lookup on removed directory */ + if (v7fs_inode_nlink(parent) == 0) + return ENOENT; + /* "." */ if (namelen == 1 && name[0] == '.') { if ((nameiop == RENAME) && islastcn) { @@ -183,6 +182,8 @@ v7fs_lookup(void *v) if (isdotdot) { vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); } + if (vpp != dvp) + VOP_UNLOCK(vpp); *a->a_vpp = vpp; DPRINTF("done.(%s)\n", name); @@ -192,7 +193,7 @@ v7fs_lookup(void *v) int v7fs_create(void *v) { - struct vop_create_args /* { + struct vop_create_v3_args /* { struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; @@ -222,7 +223,7 @@ v7fs_create(void *v) if ((error = v7fs_file_allocate(fs, &parent_node->inode, a->a_cnp->cn_nameptr, &attr, &ino))) { DPRINTF("v7fs_file_allocate failed.\n"); - goto unlock_exit; + return error; } /* Sync dirent size change. */ uvm_vnp_setsize(a->a_dvp, v7fs_inode_filesize(&parent_node->inode)); @@ -231,7 +232,7 @@ v7fs_create(void *v) *a->a_vpp = 0; if ((error = v7fs_vget(mp, ino, a->a_vpp))) { DPRINTF("v7fs_vget failed.\n"); - goto unlock_exit; + return error; } /* Scheduling update time. real update by v7fs_update */ @@ -241,9 +242,8 @@ v7fs_create(void *v) newnode->update_atime = true; DPRINTF("allocated %s->#%d\n", a->a_cnp->cn_nameptr, ino); -unlock_exit: - /* unlock parent directory */ - vput(a->a_dvp); /* locked at v7fs_lookup(); */ + if (error == 0) + VOP_UNLOCK(*a->a_vpp); return error; } @@ -251,7 +251,7 @@ unlock_exit: int v7fs_mknod(void *v) { - struct vop_mknod_args /* { + struct vop_mknod_v3_args /* { struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; @@ -280,21 +280,21 @@ v7fs_mknod(void *v) if ((error = v7fs_file_allocate(fs, &parent_node->inode, cnp->cn_nameptr, &attr, &ino))) - goto unlock_exit; + return error; /* Sync dirent size change. */ uvm_vnp_setsize(dvp, v7fs_inode_filesize(&parent_node->inode)); if ((error = v7fs_vget(mp, ino, a->a_vpp))) { DPRINTF("can't get vnode.\n"); - goto unlock_exit; + return error; } struct v7fs_node *newnode = (*a->a_vpp)->v_data; newnode->update_ctime = true; newnode->update_mtime = true; newnode->update_atime = true; -unlock_exit: - vput(dvp); + if (error == 0) + VOP_UNLOCK(*a->a_vpp); return error; } @@ -374,7 +374,7 @@ v7fs_check_permitted(struct vnode *vp, s struct v7fs_inode *inode = &v7node->inode; - return kauth_authorize_vnode(cred, kauth_access_action(mode, + return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, vp->v_type, inode->mode), vp, NULL, genfs_can_access(vp->v_type, inode->mode, inode->uid, inode->gid, mode, cred)); } @@ -423,6 +423,11 @@ v7fs_getattr(void *v) vap->va_fsid = v7fsmount->devvp->v_rdev; vap->va_fileid = inode->inode_number; vap->va_size = vp->v_size; + if (vp->v_type == VLNK) { + /* Ajust for trailing NUL. */ + KASSERT(vap->va_size > 0); + vap->va_size -= 1; + } vap->va_atime.tv_sec = inode->atime; vap->va_mtime.tv_sec = inode->mtime; vap->va_ctime.tv_sec = inode->ctime; @@ -494,8 +499,11 @@ v7fs_setattr(void *v) /* File size change. */ if ((vap->va_size != VNOVAL) && (vp->v_type == VREG)) { error = v7fs_datablock_size_change(fs, vap->va_size, inode); - if (error == 0) + if (error == 0) { uvm_vnp_setsize(vp, vap->va_size); + v7node->update_mtime = true; + v7node->update_ctime = true; + } } uid_t uid = inode->uid; gid_t gid = inode->gid; @@ -589,7 +597,7 @@ v7fs_read(void *v) } v7node->update_atime = true; - return error; + return error; } int @@ -672,7 +680,7 @@ v7fs_fsync(void *v) int v7fs_remove(void *v) { - struct vop_remove_args /* { + struct vop_remove_v2_args /* { struct vnodeop_desc *a_desc; struct vnode * a_dvp; struct vnode * a_vp; @@ -681,10 +689,9 @@ v7fs_remove(void *v) struct v7fs_node *parent_node = a->a_dvp->v_data; struct v7fs_mount *v7fsmount = parent_node->v7fsmount; struct vnode *vp = a->a_vp; - struct v7fs_inode *inode = &((struct v7fs_node *)vp->v_data)->inode; struct vnode *dvp = a->a_dvp; + struct v7fs_inode *inode = &((struct v7fs_node *)vp->v_data)->inode; struct v7fs_self *fs = v7fsmount->core; - bool remove; int error = 0; DPRINTF("delete %s\n", a->a_cnp->cn_nameptr); @@ -694,27 +701,22 @@ v7fs_remove(void *v) goto out; } - remove = v7fs_inode_nlink(inode) == 1; - if (remove) - uvm_vnp_setsize(vp, 0); - if ((error = v7fs_file_deallocate(fs, &parent_node->inode, a->a_cnp->cn_nameptr))) { DPRINTF("v7fs_file_delete failed.\n"); goto out; } + error = v7fs_inode_load(fs, inode, inode->inode_number); + if (error) + goto out; /* Sync dirent size change. */ uvm_vnp_setsize(dvp, v7fs_inode_filesize(&parent_node->inode)); - /* This inode is no longer used. -> v7fs_inactive */ - if (remove) - memset(inode, 0, sizeof(*inode)); out: if (dvp == vp) vrele(vp); /* v_usecount-- of unlocked vp */ else vput(vp); /* unlock vp and then v_usecount-- */ - vput(dvp); return error; } @@ -722,7 +724,7 @@ out: int v7fs_link(void *v) { - struct vop_link_args /* { + struct vop_link_v2_args /* { struct vnode *a_dvp; struct vnode *a_vp; struct componentname *a_cnp; @@ -750,8 +752,6 @@ v7fs_link(void *v) VOP_UNLOCK(vp); unlock: - vput(dvp); - return error; } @@ -791,8 +791,12 @@ v7fs_rename(void *v) &parent_to->inode, to_name); /* 'to file' inode may be changed. (hard-linked and it is cached.) t_vnops rename_reg_nodir */ - if (tvp) { - v7fs_vnode_reload(parent_from->v7fsmount->mountp, tvp); + if (error == 0 && tvp) { + struct v7fs_inode *inode = + &((struct v7fs_node *)tvp->v_data)->inode; + + error = v7fs_inode_load(fs, inode, inode->inode_number); + uvm_vnp_setsize(tvp, v7fs_inode_filesize(inode)); } /* Sync dirent size change. */ uvm_vnp_setsize(tdvp, v7fs_inode_filesize(&parent_to->inode)); @@ -813,7 +817,7 @@ out: int v7fs_mkdir(void *v) { - struct vop_mkdir_args /* { + struct vop_mkdir_v3_args /* { struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; @@ -839,7 +843,7 @@ v7fs_mkdir(void *v) if ((error = v7fs_file_allocate(fs, &parent_node->inode, cnp->cn_nameptr, &attr, &ino))) - goto unlock_exit; + return error; /* Sync dirent size change. */ uvm_vnp_setsize(dvp, v7fs_inode_filesize(&parent_node->inode)); @@ -851,8 +855,8 @@ v7fs_mkdir(void *v) newnode->update_mtime = true; newnode->update_atime = true; -unlock_exit: - vput(dvp); + if (error == 0) + VOP_UNLOCK(*a->a_vpp); return error; } @@ -860,7 +864,7 @@ unlock_exit: int v7fs_rmdir(void *v) { - struct vop_rmdir_args /* { + struct vop_rmdir_v2_args /* { struct vnode *a_dvp; struct vnode *a_vp; struct componentname *a_cnp; @@ -882,14 +886,14 @@ v7fs_rmdir(void *v) DPRINTF("v7fs_directory_deallocate failed.\n"); goto out; } - uvm_vnp_setsize(vp, 0); + error = v7fs_inode_load(fs, inode, inode->inode_number); + if (error) + goto out; + uvm_vnp_setsize(vp, v7fs_inode_filesize(inode)); /* Sync dirent size change. */ uvm_vnp_setsize(dvp, v7fs_inode_filesize(&parent_node->inode)); - /* This inode is no longer used. -> v7fs_inactive */ - memset(inode, 0, sizeof(*inode)); out: vput(vp); - vput(dvp); return error; } @@ -983,7 +987,7 @@ v7fs_readdir(void *v) DPRINTF("uio buffer too small\n"); return ENOMEM; } - dp = malloc(sizeof(*dp), M_V7FS, M_WAITOK | M_ZERO); + dp = kmem_zalloc(sizeof(*dp), KM_SLEEP); arg.cnt = 0; arg.dp = dp; arg.uio = uio; @@ -996,7 +1000,7 @@ v7fs_readdir(void *v) if (error < 0) error = 0; - free(dp, M_V7FS); + kmem_free(dp, sizeof(*dp)); return error; } @@ -1004,7 +1008,7 @@ v7fs_readdir(void *v) int v7fs_inactive(void *v) { - struct vop_inactive_args /* { + struct vop_inactive_v2_args /* { struct vnode *a_vp; bool *a_recycle; } */ *a = v; @@ -1013,15 +1017,13 @@ v7fs_inactive(void *v) struct v7fs_inode *inode = &v7node->inode; DPRINTF("%p #%d\n", vp, inode->inode_number); - if (v7fs_inode_allocated(inode)) { + if (v7fs_inode_nlink(inode) > 0) { v7fs_update(vp, 0, 0, UPDATE_WAIT); *a->a_recycle = false; } else { *a->a_recycle = true; } - VOP_UNLOCK(vp); - return 0; } @@ -1030,19 +1032,28 @@ v7fs_reclaim(void *v) { /*This vnode is no longer referenced by kernel. */ extern struct pool v7fs_node_pool; - struct vop_reclaim_args /* { + struct vop_reclaim_v2_args /* { struct vnode *a_vp; } */ *a = v; struct vnode *vp = a->a_vp; struct v7fs_node *v7node = vp->v_data; + struct v7fs_self *fs = v7node->v7fsmount->core; + struct v7fs_inode *inode = &v7node->inode; + + VOP_UNLOCK(vp); - DPRINTF("%p #%d\n", vp, v7node->inode.inode_number); - mutex_enter(&mntvnode_lock); - LIST_REMOVE(v7node, link); - mutex_exit(&mntvnode_lock); + DPRINTF("%p #%d\n", vp, inode->inode_number); + if (v7fs_inode_nlink(inode) == 0) { + v7fs_datablock_size_change(fs, 0, inode); + DPRINTF("remove datablock\n"); + v7fs_inode_deallocate(fs, inode->inode_number); + DPRINTF("remove inode\n"); + } genfs_node_destroy(vp); pool_put(&v7fs_node_pool, v7node); + mutex_enter(vp->v_interlock); vp->v_data = NULL; + mutex_exit(vp->v_interlock); return 0; } @@ -1238,7 +1249,7 @@ v7fs_update(struct vnode *vp, const stru int v7fs_symlink(void *v) { - struct vop_symlink_args /* { + struct vop_symlink_v3_args /* { struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; @@ -1270,7 +1281,7 @@ v7fs_symlink(void *v) if ((error = v7fs_file_allocate (fs, &parent_node->inode, to, &attr, &ino))) { - goto unlock_exit; + return error; } /* Sync dirent size change. */ uvm_vnp_setsize(a->a_dvp, v7fs_inode_filesize(&parent_node->inode)); @@ -1288,9 +1299,9 @@ v7fs_symlink(void *v) newnode->update_ctime = true; newnode->update_mtime = true; newnode->update_atime = true; -unlock_exit: - /* unlock parent directory */ - vput(a->a_dvp); + + if (error == 0) + VOP_UNLOCK(*a->a_vpp); return error; }