1 /* $NetBSD: ufs_inode.c,v 1.33 2002/01/26 08:32:05 chs Exp $ */ 2 3 /* 4 * Copyright (c) 1991, 1993 5 * The Regents of the University of California. All rights reserved. 6 * (c) UNIX System Laboratories, Inc. 7 * All or some portions of this file are derived from material licensed 8 * to the University of California by American Telephone and Telegraph 9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 10 * the permission of UNIX System Laboratories, Inc. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * @(#)ufs_inode.c 8.9 (Berkeley) 5/14/95 41 */ 42 43 #include <sys/cdefs.h> 44 __KERNEL_RCSID(0, "$NetBSD: ufs_inode.c,v 1.33 2002/01/26 08:32:05 chs Exp $"); 45 46 #include "opt_quota.h" 47 48 #include <sys/param.h> 49 #include <sys/systm.h> 50 #include <sys/proc.h> 51 #include <sys/vnode.h> 52 #include <sys/mount.h> 53 #include <sys/kernel.h> 54 #include <sys/namei.h> 55 56 #include <ufs/ufs/quota.h> 57 #include <ufs/ufs/inode.h> 58 #include <ufs/ufs/ufsmount.h> 59 #include <ufs/ufs/ufs_extern.h> 60 61 #include <uvm/uvm.h> 62 63 extern int prtactive; 64 65 /* 66 * Last reference to an inode. If necessary, write or delete it. 67 */ 68 int 69 ufs_inactive(v) 70 void *v; 71 { 72 struct vop_inactive_args /* { 73 struct vnode *a_vp; 74 struct proc *a_p; 75 } */ *ap = v; 76 struct vnode *vp = ap->a_vp; 77 struct inode *ip = VTOI(vp); 78 struct proc *p = ap->a_p; 79 int mode, error = 0; 80 81 if (prtactive && vp->v_usecount != 0) 82 vprint("ufs_inactive: pushing active", vp); 83 84 /* 85 * Ignore inodes related to stale file handles. 86 */ 87 if (ip->i_ffs_mode == 0) 88 goto out; 89 if (ip->i_ffs_effnlink == 0 && DOINGSOFTDEP(vp)) 90 softdep_releasefile(ip); 91 92 if (ip->i_ffs_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 93 #ifdef QUOTA 94 if (!getinoquota(ip)) 95 (void)chkiq(ip, -1, NOCRED, 0); 96 #endif 97 if (ip->i_ffs_size != 0) { 98 error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED, p); 99 } 100 /* 101 * Setting the mode to zero needs to wait for the inode 102 * to be written just as does a change to the link count. 103 * So, rather than creating a new entry point to do the 104 * same thing, we just use softdep_change_linkcnt(). 105 */ 106 ip->i_ffs_rdev = 0; 107 mode = ip->i_ffs_mode; 108 ip->i_ffs_mode = 0; 109 ip->i_flag |= IN_CHANGE | IN_UPDATE; 110 if (DOINGSOFTDEP(vp)) 111 softdep_change_linkcnt(ip); 112 VOP_VFREE(vp, ip->i_number, mode); 113 } 114 115 if (ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFIED | IN_ACCESSED)) 116 VOP_UPDATE(vp, NULL, NULL, 0); 117 out: 118 VOP_UNLOCK(vp, 0); 119 /* 120 * If we are done with the inode, reclaim it 121 * so that it can be reused immediately. 122 */ 123 124 if (ip->i_ffs_mode == 0) 125 vrecycle(vp, NULL, p); 126 return (error); 127 } 128 129 /* 130 * Reclaim an inode so that it can be used for other purposes. 131 */ 132 int 133 ufs_reclaim(vp, p) 134 struct vnode *vp; 135 struct proc *p; 136 { 137 struct inode *ip; 138 139 if (prtactive && vp->v_usecount != 0) 140 vprint("ufs_reclaim: pushing active", vp); 141 /* 142 * Remove the inode from its hash chain. 143 */ 144 ip = VTOI(vp); 145 ufs_ihashrem(ip); 146 /* 147 * Purge old data structures associated with the inode. 148 */ 149 cache_purge(vp); 150 if (ip->i_devvp) { 151 vrele(ip->i_devvp); 152 ip->i_devvp = 0; 153 } 154 #ifdef QUOTA 155 { 156 int i; 157 for (i = 0; i < MAXQUOTAS; i++) { 158 if (ip->i_dquot[i] != NODQUOT) { 159 dqrele(vp, ip->i_dquot[i]); 160 ip->i_dquot[i] = NODQUOT; 161 } 162 } 163 } 164 #endif 165 return (0); 166 } 167 168 /* 169 * allocate a range of blocks in a file. 170 * after this function returns, any page entirely contained within the range 171 * will map to invalid data and thus must be overwritten before it is made 172 * accessible to others. 173 */ 174 175 int 176 ufs_balloc_range(vp, off, len, cred, flags) 177 struct vnode *vp; 178 off_t off, len; 179 struct ucred *cred; 180 int flags; 181 { 182 off_t oldeof, neweof, oldeob, neweob, pagestart; 183 struct uvm_object *uobj; 184 struct genfs_node *gp = VTOG(vp); 185 int i, delta, error, npages; 186 int bshift = vp->v_mount->mnt_fs_bshift; 187 int bsize = 1 << bshift; 188 int ppb = MAX(bsize >> PAGE_SHIFT, 1); 189 struct vm_page *pgs[ppb]; 190 UVMHIST_FUNC("ufs_balloc_range"); UVMHIST_CALLED(ubchist); 191 UVMHIST_LOG(ubchist, "vp %p off 0x%x len 0x%x u_size 0x%x", 192 vp, off, len, vp->v_size); 193 194 oldeof = vp->v_size; 195 GOP_SIZE(vp, oldeof, &oldeob); 196 197 neweof = MAX(vp->v_size, off + len); 198 GOP_SIZE(vp, neweof, &neweob); 199 200 error = 0; 201 uobj = &vp->v_uobj; 202 pgs[0] = NULL; 203 204 /* 205 * read or create pages covering the range of the allocation and 206 * keep them locked until the new block is allocated, so there 207 * will be no window where the old contents of the new block are 208 * visible to racing threads. 209 */ 210 211 pagestart = trunc_page(off) & ~(bsize - 1); 212 npages = MIN(ppb, (round_page(neweob) - pagestart) >> PAGE_SHIFT); 213 memset(pgs, 0, npages * sizeof(struct vm_page *)); 214 simple_lock(&uobj->vmobjlock); 215 error = VOP_GETPAGES(vp, pagestart, pgs, &npages, 0, 216 VM_PROT_READ, 0, PGO_SYNCIO|PGO_PASTEOF); 217 if (error) { 218 return error; 219 } 220 simple_lock(&uobj->vmobjlock); 221 uvm_lock_pageq(); 222 for (i = 0; i < npages; i++) { 223 UVMHIST_LOG(ubchist, "got pgs[%d] %p", i, pgs[i],0,0); 224 KASSERT((pgs[i]->flags & PG_RELEASED) == 0); 225 pgs[i]->flags &= ~PG_CLEAN; 226 uvm_pageactivate(pgs[i]); 227 } 228 uvm_unlock_pageq(); 229 simple_unlock(&uobj->vmobjlock); 230 231 /* 232 * adjust off to be block-aligned. 233 */ 234 235 delta = off & (bsize - 1); 236 off -= delta; 237 len += delta; 238 239 /* 240 * now allocate the range. 241 */ 242 243 lockmgr(&gp->g_glock, LK_EXCLUSIVE, NULL); 244 error = GOP_ALLOC(vp, off, len, flags, cred); 245 lockmgr(&gp->g_glock, LK_RELEASE, NULL); 246 247 /* 248 * clear PG_RDONLY on any pages we are holding 249 * (since they now have backing store) and unbusy them. 250 */ 251 252 simple_lock(&uobj->vmobjlock); 253 for (i = 0; i < npages; i++) { 254 pgs[i]->flags &= ~PG_RDONLY; 255 if (error) { 256 pgs[i]->flags |= PG_RELEASED; 257 } 258 } 259 if (error) { 260 uvm_lock_pageq(); 261 uvm_page_unbusy(pgs, npages); 262 uvm_unlock_pageq(); 263 } else { 264 uvm_page_unbusy(pgs, npages); 265 } 266 simple_unlock(&uobj->vmobjlock); 267 return error; 268 } 269