only delete space used by inode, on inode deletion; required
[unix-history] / usr / src / sys / ufs / lfs / lfs_vnops.c
CommitLineData
da7c5cc6 1/*
d9f5f868 2 * Copyright (c) 1986, 1989, 1991 Regents of the University of California.
7188ac27 3 * All rights reserved.
da7c5cc6 4 *
b702c21d 5 * %sccs.include.redist.c%
7188ac27 6 *
6f68ec4a 7 * @(#)lfs_vnops.c 7.77 (Berkeley) %G%
da7c5cc6 8 */
6459ebe0 9
c7e94c3a
KB
10#include <sys/param.h>
11#include <sys/systm.h>
12#include <sys/namei.h>
13#include <sys/resourcevar.h>
14#include <sys/kernel.h>
15#include <sys/file.h>
16#include <sys/stat.h>
17#include <sys/buf.h>
18#include <sys/proc.h>
19#include <sys/conf.h>
20#include <sys/mount.h>
21#include <sys/vnode.h>
22#include <sys/specdev.h>
23#include <sys/fifo.h>
24#include <sys/malloc.h>
25
d9f5f868
KB
26#include <ufs/ufs/quota.h>
27#include <ufs/ufs/inode.h>
28#include <ufs/ufs/dir.h>
29#include <ufs/ufs/ufs_extern.h>
c7e94c3a 30
d9f5f868
KB
31#include <ufs/lfs/lfs.h>
32#include <ufs/lfs/lfs_extern.h>
c7e94c3a
KB
33
34/* Global vfs data structures for lfs. */
35struct vnodeops lfs_vnodeops = {
36 ufs_lookup, /* lookup */
37 ufs_create, /* create */
38 ufs_mknod, /* mknod */
39 ufs_open, /* open */
40 ufs_close, /* close */
41 ufs_access, /* access */
42 ufs_getattr, /* getattr */
43 ufs_setattr, /* setattr */
44 lfs_read, /* read */
45 lfs_write, /* write */
46 ufs_ioctl, /* ioctl */
47 ufs_select, /* select */
48 ufs_mmap, /* mmap */
49 lfs_fsync, /* fsync */
50 ufs_seek, /* seek */
51 ufs_remove, /* remove */
52 ufs_link, /* link */
53 ufs_rename, /* rename */
54 ufs_mkdir, /* mkdir */
55 ufs_rmdir, /* rmdir */
56 ufs_symlink, /* symlink */
57 ufs_readdir, /* readdir */
58 ufs_readlink, /* readlink */
59 ufs_abortop, /* abortop */
a2d9885d 60 lfs_inactive, /* inactive */
c7e94c3a
KB
61 ufs_reclaim, /* reclaim */
62 ufs_lock, /* lock */
63 ufs_unlock, /* unlock */
a2d9885d 64 lfs_bmap, /* bmap */
c7e94c3a
KB
65 ufs_strategy, /* strategy */
66 ufs_print, /* print */
67 ufs_islocked, /* islocked */
68 ufs_advlock, /* advlock */
a2d9885d
KM
69 lfs_blkatoff, /* blkatoff */
70 lfs_vget, /* vget */
71 lfs_valloc, /* valloc */
72 lfs_vfree, /* vfree */
73 lfs_truncate, /* truncate */
74 lfs_update, /* update */
75 lfs_bwrite, /* bwrite */
c7e94c3a 76};
528f664c 77
a2d9885d
KM
78struct vnodeops lfs_specops = {
79 spec_lookup, /* lookup */
80 spec_create, /* create */
81 spec_mknod, /* mknod */
82 spec_open, /* open */
83 ufsspec_close, /* close */
84 ufs_access, /* access */
85 ufs_getattr, /* getattr */
86 ufs_setattr, /* setattr */
87 ufsspec_read, /* read */
88 ufsspec_write, /* write */
89 spec_ioctl, /* ioctl */
90 spec_select, /* select */
91 spec_mmap, /* mmap */
92 spec_fsync, /* fsync */
93 spec_seek, /* seek */
94 spec_remove, /* remove */
95 spec_link, /* link */
96 spec_rename, /* rename */
97 spec_mkdir, /* mkdir */
98 spec_rmdir, /* rmdir */
99 spec_symlink, /* symlink */
100 spec_readdir, /* readdir */
101 spec_readlink, /* readlink */
102 spec_abortop, /* abortop */
103 lfs_inactive, /* inactive */
104 ufs_reclaim, /* reclaim */
105 ufs_lock, /* lock */
106 ufs_unlock, /* unlock */
107 spec_bmap, /* bmap */
108 spec_strategy, /* strategy */
109 ufs_print, /* print */
110 ufs_islocked, /* islocked */
111 spec_advlock, /* advlock */
112 spec_blkatoff, /* blkatoff */
113 spec_vget, /* vget */
114 spec_valloc, /* valloc */
115 spec_vfree, /* vfree */
116 spec_truncate, /* truncate */
117 lfs_update, /* update */
118 lfs_bwrite, /* bwrite */
119};
120
121#ifdef FIFO
122struct vnodeops lfs_fifoops = {
123 fifo_lookup, /* lookup */
124 fifo_create, /* create */
125 fifo_mknod, /* mknod */
126 fifo_open, /* open */
127 ufsfifo_close, /* close */
128 ufs_access, /* access */
129 ufs_getattr, /* getattr */
130 ufs_setattr, /* setattr */
131 ufsfifo_read, /* read */
132 ufsfifo_write, /* write */
133 fifo_ioctl, /* ioctl */
134 fifo_select, /* select */
135 fifo_mmap, /* mmap */
136 fifo_fsync, /* fsync */
137 fifo_seek, /* seek */
138 fifo_remove, /* remove */
139 fifo_link, /* link */
140 fifo_rename, /* rename */
141 fifo_mkdir, /* mkdir */
142 fifo_rmdir, /* rmdir */
143 fifo_symlink, /* symlink */
144 fifo_readdir, /* readdir */
145 fifo_readlink, /* readlink */
146 fifo_abortop, /* abortop */
147 lfs_inactive, /* inactive */
148 ufs_reclaim, /* reclaim */
149 ufs_lock, /* lock */
150 ufs_unlock, /* unlock */
151 fifo_bmap, /* bmap */
152 fifo_strategy, /* strategy */
153 ufs_print, /* print */
154 ufs_islocked, /* islocked */
155 fifo_advlock, /* advlock */
156 fifo_blkatoff, /* blkatoff */
157 fifo_vget, /* vget */
158 fifo_valloc, /* valloc */
159 fifo_vfree, /* vfree */
160 fifo_truncate, /* truncate */
161 lfs_update, /* update */
162 lfs_bwrite, /* bwrite */
163};
164#endif /* FIFO */
165
b373e060
KM
166/*
167 * Vnode op for reading.
168 */
169/* ARGSUSED */
a8c062c5 170lfs_read(vp, uio, ioflag, cred)
b373e060
KM
171 struct vnode *vp;
172 register struct uio *uio;
173 int ioflag;
174 struct ucred *cred;
175{
176 register struct inode *ip = VTOI(vp);
d9f5f868 177 register struct lfs *fs; /* LFS */
b373e060
KM
178 struct buf *bp;
179 daddr_t lbn, bn, rablock;
20aa076b 180 int size, diff, error = 0;
b373e060
KM
181 long n, on, type;
182
c6a63814
KB
183#ifdef VERBOSE
184 printf("lfs_read: ino %d\n", ip->i_number);
185#endif
5b169cb7 186#ifdef DIAGNOSTIC
b373e060
KM
187 if (uio->uio_rw != UIO_READ)
188 panic("ufs_read mode");
189 type = ip->i_mode & IFMT;
190 if (type != IFDIR && type != IFREG && type != IFLNK)
191 panic("ufs_read type");
5b169cb7 192#endif
b373e060
KM
193 if (uio->uio_resid == 0)
194 return (0);
195 if (uio->uio_offset < 0)
196 return (EINVAL);
197 ip->i_flag |= IACC;
0b4d6502
KB
198
199 fs = ip->i_lfs; /* LFS */
b373e060
KM
200 do {
201 lbn = lblkno(fs, uio->uio_offset);
202 on = blkoff(fs, uio->uio_offset);
0b4d6502 203 n = MIN((unsigned)(fs->lfs_bsize - on), uio->uio_resid);
b373e060
KM
204 diff = ip->i_size - uio->uio_offset;
205 if (diff <= 0)
206 return (0);
207 if (diff < n)
208 n = diff;
0b4d6502 209 size = blksize(fs); /* LFS */
e16fa59e 210 rablock = lbn + 1;
20aa076b
KM
211 if (vp->v_lastr + 1 == lbn &&
212 lblktosize(fs, rablock) < ip->i_size)
38f21582
KM
213 error = breadn(ITOV(ip), lbn, size, &rablock,
214 &size, 1, NOCRED, &bp);
b373e060 215 else
e16fa59e 216 error = bread(ITOV(ip), lbn, size, NOCRED, &bp);
de67eefc 217 vp->v_lastr = lbn;
b373e060
KM
218 n = MIN(n, size - bp->b_resid);
219 if (error) {
220 brelse(bp);
221 return (error);
222 }
223 error = uiomove(bp->b_un.b_addr + on, (int)n, uio);
0b4d6502 224 if (n + on == fs->lfs_bsize || uio->uio_offset == ip->i_size)
b373e060
KM
225 bp->b_flags |= B_AGE;
226 brelse(bp);
227 } while (error == 0 && uio->uio_resid > 0 && n != 0);
228 return (error);
229}
230
231/*
232 * Vnode op for writing.
233 */
a8c062c5 234lfs_write(vp, uio, ioflag, cred)
b373e060
KM
235 register struct vnode *vp;
236 struct uio *uio;
237 int ioflag;
238 struct ucred *cred;
239{
5b169cb7 240 struct proc *p = uio->uio_procp;
b373e060 241 register struct inode *ip = VTOI(vp);
a418dc41 242 register struct lfs *fs;
b373e060 243 struct buf *bp;
a418dc41 244 daddr_t lbn;
b373e060 245 u_long osize;
a418dc41 246 int n, on, flags, newblock;
8986c97c 247 int size, resid, error = 0;
b373e060 248
c6a63814
KB
249#ifdef VERBOSE
250 printf("lfs_write ino %d\n", ip->i_number);
251#endif
5b169cb7 252#ifdef DIAGNOSTIC
b373e060 253 if (uio->uio_rw != UIO_WRITE)
a418dc41 254 panic("lfs_write mode");
5b169cb7 255#endif
b373e060
KM
256 switch (vp->v_type) {
257 case VREG:
258 if (ioflag & IO_APPEND)
259 uio->uio_offset = ip->i_size;
260 /* fall through */
261 case VLNK:
262 break;
263
264 case VDIR:
a418dc41 265 /* XXX This may not be correct for LFS. */
b373e060 266 if ((ioflag & IO_SYNC) == 0)
a418dc41 267 panic("lfs_write nonsync dir write");
b373e060
KM
268 break;
269
270 default:
a418dc41 271 panic("lfs_write type");
b373e060
KM
272 }
273 if (uio->uio_offset < 0)
274 return (EINVAL);
275 if (uio->uio_resid == 0)
276 return (0);
277 /*
278 * Maybe this should be above the vnode op call, but so long as
279 * file servers have no limits, i don't think it matters
280 */
b326e282 281 if (vp->v_type == VREG && p &&
b373e060 282 uio->uio_offset + uio->uio_resid >
c6f5111d
MK
283 p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
284 psignal(p, SIGXFSZ);
b373e060
KM
285 return (EFBIG);
286 }
287 resid = uio->uio_resid;
288 osize = ip->i_size;
d5075120 289 fs = ip->i_lfs; /* LFS */
e16fa59e 290 flags = 0;
d5075120 291#ifdef NOTLFS
e16fa59e
KM
292 if (ioflag & IO_SYNC)
293 flags = B_SYNC;
d5075120 294#endif
b373e060
KM
295 do {
296 lbn = lblkno(fs, uio->uio_offset);
cb1fb5d7 297 on = blkoff(fs, uio->uio_offset);
d5075120 298 n = MIN((unsigned)(fs->lfs_bsize - on), uio->uio_resid);
a418dc41 299 if (error = lfs_balloc(vp, n, lbn, &bp))
b373e060 300 break;
8986c97c 301 if (uio->uio_offset + n > ip->i_size) {
b373e060 302 ip->i_size = uio->uio_offset + n;
e738d0da 303 vnode_pager_setsize(vp, (u_long)ip->i_size);
8986c97c 304 }
d5075120 305 size = blksize(fs);
8986c97c 306 (void) vnode_pager_uncache(vp);
b373e060 307 n = MIN(n, size - bp->b_resid);
b373e060 308 error = uiomove(bp->b_un.b_addr + on, n, uio);
d5075120 309#ifdef NOTLFS /* LFS */
b373e060
KM
310 if (ioflag & IO_SYNC)
311 (void) bwrite(bp);
312 else if (n + on == fs->fs_bsize) {
313 bp->b_flags |= B_AGE;
314 bawrite(bp);
315 } else
316 bdwrite(bp);
a418dc41 317 ip->i_flag |= IUPD|ICHG;
d5075120 318#else
a418dc41
KB
319 /* XXX This doesn't handle IO_SYNC. */
320 LFS_UBWRITE(bp);
d5075120 321#endif
b373e060
KM
322 if (cred->cr_uid != 0)
323 ip->i_mode &= ~(ISUID|ISGID);
324 } while (error == 0 && uio->uio_resid > 0 && n != 0);
325 if (error && (ioflag & IO_UNIT)) {
cb1fb5d7 326 (void)lfs_truncate(vp, osize, ioflag & IO_SYNC);
b373e060
KM
327 uio->uio_offset -= resid - uio->uio_resid;
328 uio->uio_resid = resid;
329 }
1c05ecaf 330 if (!error && (ioflag & IO_SYNC))
cb1fb5d7 331 error = lfs_update(vp, &time, &time, 1);
b373e060
KM
332 return (error);
333}
334
4f083fd7 335/*
7188ac27 336 * Synch an open file.
4f083fd7 337 */
7188ac27 338/* ARGSUSED */
a8c062c5 339lfs_fsync(vp, fflags, cred, waitfor, p)
7188ac27
KM
340 struct vnode *vp;
341 int fflags;
342 struct ucred *cred;
86cdabf6 343 int waitfor;
5b169cb7 344 struct proc *p;
528f664c 345{
c6a63814 346 struct inode *ip;
7188ac27 347
c6a63814
KB
348#ifdef VERBOSE
349 printf("lfs_fsync\n");
350#endif
351 ip = VTOI(vp);
5b169cb7 352 if (fflags & FWRITE)
7188ac27 353 ip->i_flag |= ICHG;
6f68ec4a 354 return (lfs_update(vp, &time, &time, waitfor == MNT_WAIT));
88a7a62a 355}
a2d9885d
KM
356
357/*
358 * Last reference to an inode, write the inode out and if necessary,
359 * truncate and deallocate the file.
360 */
361int
362lfs_inactive(vp, p)
363 struct vnode *vp;
364 struct proc *p;
365{
c6a63814 366 extern int prtactive;
a2d9885d
KM
367 register struct inode *ip;
368 int mode, error;
a2d9885d 369
c6a63814
KB
370#ifdef VERBOSE
371 printf("lfs_inactive\n");
372#endif
a2d9885d
KM
373 if (prtactive && vp->v_usecount != 0)
374 vprint("lfs_inactive: pushing active", vp);
375
376 /* Get rid of inodes related to stale file handles. */
377 ip = VTOI(vp);
378 if (ip->i_mode == 0) {
379 if ((vp->v_flag & VXLOCK) == 0)
380 vgone(vp);
381 return (0);
382 }
383
384 error = 0;
385 ILOCK(ip);
386 if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
387#ifdef QUOTA
388 if (!getinoquota(ip))
389 (void)chkiq(ip, -1, NOCRED, 0);
390#endif
391 error = lfs_truncate(vp, (u_long)0, 0);
392 mode = ip->i_mode;
393 ip->i_mode = 0;
394 ip->i_rdev = 0;
395 ip->i_flag |= IUPD|ICHG;
396 lfs_vfree(vp, ip->i_number, mode);
397 }
398 if (ip->i_flag&(IUPD|IACC|ICHG|IMOD))
399 lfs_update(vp, &time, &time, 0);
400 IUNLOCK(ip);
401 ip->i_flag = 0;
402 /*
403 * If we are done with the inode, reclaim it
404 * so that it can be reused immediately.
405 */
406 if (vp->v_usecount == 0 && ip->i_mode == 0)
407 vgone(vp);
408 return (error);
409}