1 /*
2 * Copyright (c) 1982, 1986, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 *
7 * @(#)ffs_vnops.c 8.15 (Berkeley) 05/14/95
8 */
9
10 #include <sys/param.h>
11 #include <sys/systm.h>
12 #include <sys/resourcevar.h>
13 #include <sys/kernel.h>
14 #include <sys/file.h>
15 #include <sys/stat.h>
16 #include <sys/buf.h>
17 #include <sys/proc.h>
18 #include <sys/conf.h>
19 #include <sys/mount.h>
20 #include <sys/vnode.h>
21 #include <sys/malloc.h>
22
23 #include <vm/vm.h>
24
25 #include <miscfs/specfs/specdev.h>
26 #include <miscfs/fifofs/fifo.h>
27
28 #include <ufs/ufs/lockf.h>
29 #include <ufs/ufs/quota.h>
30 #include <ufs/ufs/inode.h>
31 #include <ufs/ufs/dir.h>
32 #include <ufs/ufs/ufsmount.h>
33 #include <ufs/ufs/ufs_extern.h>
34
35 #include <ufs/ffs/fs.h>
36 #include <ufs/ffs/ffs_extern.h>
37
38 /* Global vfs data structures for ufs. */
39 int (**ffs_vnodeop_p)();
40 struct vnodeopv_entry_desc ffs_vnodeop_entries[] = {
41 { &vop_default_desc, vn_default_error },
42 { &vop_lookup_desc, ufs_lookup }, /* lookup */
43 { &vop_create_desc, ufs_create }, /* create */
44 { &vop_whiteout_desc, ufs_whiteout }, /* whiteout */
45 { &vop_mknod_desc, ufs_mknod }, /* mknod */
46 { &vop_open_desc, ufs_open }, /* open */
47 { &vop_close_desc, ufs_close }, /* close */
48 { &vop_access_desc, ufs_access }, /* access */
49 { &vop_getattr_desc, ufs_getattr }, /* getattr */
50 { &vop_setattr_desc, ufs_setattr }, /* setattr */
51 { &vop_read_desc, ffs_read }, /* read */
52 { &vop_write_desc, ffs_write }, /* write */
53 { &vop_lease_desc, ufs_lease_check }, /* lease */
54 { &vop_ioctl_desc, ufs_ioctl }, /* ioctl */
55 { &vop_select_desc, ufs_select }, /* select */
56 { &vop_revoke_desc, ufs_revoke }, /* revoke */
57 { &vop_mmap_desc, ufs_mmap }, /* mmap */
58 { &vop_fsync_desc, ffs_fsync }, /* fsync */
59 { &vop_seek_desc, ufs_seek }, /* seek */
60 { &vop_remove_desc, ufs_remove }, /* remove */
61 { &vop_link_desc, ufs_link }, /* link */
62 { &vop_rename_desc, ufs_rename }, /* rename */
63 { &vop_mkdir_desc, ufs_mkdir }, /* mkdir */
64 { &vop_rmdir_desc, ufs_rmdir }, /* rmdir */
65 { &vop_symlink_desc, ufs_symlink }, /* symlink */
66 { &vop_readdir_desc, ufs_readdir }, /* readdir */
67 { &vop_readlink_desc, ufs_readlink }, /* readlink */
68 { &vop_abortop_desc, ufs_abortop }, /* abortop */
69 { &vop_inactive_desc, ufs_inactive }, /* inactive */
70 { &vop_reclaim_desc, ffs_reclaim }, /* reclaim */
71 { &vop_lock_desc, ufs_lock }, /* lock */
72 { &vop_unlock_desc, ufs_unlock }, /* unlock */
73 { &vop_bmap_desc, ufs_bmap }, /* bmap */
74 { &vop_strategy_desc, ufs_strategy }, /* strategy */
75 { &vop_print_desc, ufs_print }, /* print */
76 { &vop_islocked_desc, ufs_islocked }, /* islocked */
77 { &vop_pathconf_desc, ufs_pathconf }, /* pathconf */
78 { &vop_advlock_desc, ufs_advlock }, /* advlock */
79 { &vop_blkatoff_desc, ffs_blkatoff }, /* blkatoff */
80 { &vop_valloc_desc, ffs_valloc }, /* valloc */
81 { &vop_reallocblks_desc, ffs_reallocblks }, /* reallocblks */
82 { &vop_vfree_desc, ffs_vfree }, /* vfree */
83 { &vop_truncate_desc, ffs_truncate }, /* truncate */
84 { &vop_update_desc, ffs_update }, /* update */
85 { &vop_bwrite_desc, vn_bwrite },
86 { (struct vnodeop_desc*)NULL, (int(*)())NULL }
87 };
88 struct vnodeopv_desc ffs_vnodeop_opv_desc =
89 { &ffs_vnodeop_p, ffs_vnodeop_entries };
90
91 int (**ffs_specop_p)();
92 struct vnodeopv_entry_desc ffs_specop_entries[] = {
93 { &vop_default_desc, vn_default_error },
94 { &vop_lookup_desc, spec_lookup }, /* lookup */
95 { &vop_create_desc, spec_create }, /* create */
96 { &vop_mknod_desc, spec_mknod }, /* mknod */
97 { &vop_open_desc, spec_open }, /* open */
98 { &vop_close_desc, ufsspec_close }, /* close */
99 { &vop_access_desc, ufs_access }, /* access */
100 { &vop_getattr_desc, ufs_getattr }, /* getattr */
101 { &vop_setattr_desc, ufs_setattr }, /* setattr */
102 { &vop_read_desc, ufsspec_read }, /* read */
103 { &vop_write_desc, ufsspec_write }, /* write */
104 { &vop_lease_desc, spec_lease_check }, /* lease */
105 { &vop_ioctl_desc, spec_ioctl }, /* ioctl */
106 { &vop_select_desc, spec_select }, /* select */
107 { &vop_revoke_desc, spec_revoke }, /* revoke */
108 { &vop_mmap_desc, spec_mmap }, /* mmap */
109 { &vop_fsync_desc, ffs_fsync }, /* fsync */
110 { &vop_seek_desc, spec_seek }, /* seek */
111 { &vop_remove_desc, spec_remove }, /* remove */
112 { &vop_link_desc, spec_link }, /* link */
113 { &vop_rename_desc, spec_rename }, /* rename */
114 { &vop_mkdir_desc, spec_mkdir }, /* mkdir */
115 { &vop_rmdir_desc, spec_rmdir }, /* rmdir */
116 { &vop_symlink_desc, spec_symlink }, /* symlink */
117 { &vop_readdir_desc, spec_readdir }, /* readdir */
118 { &vop_readlink_desc, spec_readlink }, /* readlink */
119 { &vop_abortop_desc, spec_abortop }, /* abortop */
120 { &vop_inactive_desc, ufs_inactive }, /* inactive */
121 { &vop_reclaim_desc, ffs_reclaim }, /* reclaim */
122 { &vop_lock_desc, ufs_lock }, /* lock */
123 { &vop_unlock_desc, ufs_unlock }, /* unlock */
124 { &vop_bmap_desc, spec_bmap }, /* bmap */
125 { &vop_strategy_desc, spec_strategy }, /* strategy */
126 { &vop_print_desc, ufs_print }, /* print */
127 { &vop_islocked_desc, ufs_islocked }, /* islocked */
128 { &vop_pathconf_desc, spec_pathconf }, /* pathconf */
129 { &vop_advlock_desc, spec_advlock }, /* advlock */
130 { &vop_blkatoff_desc, spec_blkatoff }, /* blkatoff */
131 { &vop_valloc_desc, spec_valloc }, /* valloc */
132 { &vop_reallocblks_desc, spec_reallocblks }, /* reallocblks */
133 { &vop_vfree_desc, ffs_vfree }, /* vfree */
134 { &vop_truncate_desc, spec_truncate }, /* truncate */
135 { &vop_update_desc, ffs_update }, /* update */
136 { &vop_bwrite_desc, vn_bwrite },
137 { (struct vnodeop_desc*)NULL, (int(*)())NULL }
138 };
139 struct vnodeopv_desc ffs_specop_opv_desc =
140 { &ffs_specop_p, ffs_specop_entries };
141
142 #ifdef FIFO
143 int (**ffs_fifoop_p)();
144 struct vnodeopv_entry_desc ffs_fifoop_entries[] = {
145 { &vop_default_desc, vn_default_error },
146 { &vop_lookup_desc, fifo_lookup }, /* lookup */
147 { &vop_create_desc, fifo_create }, /* create */
148 { &vop_mknod_desc, fifo_mknod }, /* mknod */
149 { &vop_open_desc, fifo_open }, /* open */
150 { &vop_close_desc, ufsfifo_close }, /* close */
151 { &vop_access_desc, ufs_access }, /* access */
152 { &vop_getattr_desc, ufs_getattr }, /* getattr */
153 { &vop_setattr_desc, ufs_setattr }, /* setattr */
154 { &vop_read_desc, ufsfifo_read }, /* read */
155 { &vop_write_desc, ufsfifo_write }, /* write */
156 { &vop_lease_desc, fifo_lease_check }, /* lease */
157 { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */
158 { &vop_select_desc, fifo_select }, /* select */
159 { &vop_revoke_desc, fifo_revoke }, /* revoke */
160 { &vop_mmap_desc, fifo_mmap }, /* mmap */
161 { &vop_fsync_desc, ffs_fsync }, /* fsync */
162 { &vop_seek_desc, fifo_seek }, /* seek */
163 { &vop_remove_desc, fifo_remove }, /* remove */
164 { &vop_link_desc, fifo_link }, /* link */
165 { &vop_rename_desc, fifo_rename }, /* rename */
166 { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */
167 { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */
168 { &vop_symlink_desc, fifo_symlink }, /* symlink */
169 { &vop_readdir_desc, fifo_readdir }, /* readdir */
170 { &vop_readlink_desc, fifo_readlink }, /* readlink */
171 { &vop_abortop_desc, fifo_abortop }, /* abortop */
172 { &vop_inactive_desc, ufs_inactive }, /* inactive */
173 { &vop_reclaim_desc, ffs_reclaim }, /* reclaim */
174 { &vop_lock_desc, ufs_lock }, /* lock */
175 { &vop_unlock_desc, ufs_unlock }, /* unlock */
176 { &vop_bmap_desc, fifo_bmap }, /* bmap */
177 { &vop_strategy_desc, fifo_strategy }, /* strategy */
178 { &vop_print_desc, ufs_print }, /* print */
179 { &vop_islocked_desc, ufs_islocked }, /* islocked */
180 { &vop_pathconf_desc, fifo_pathconf }, /* pathconf */
181 { &vop_advlock_desc, fifo_advlock }, /* advlock */
182 { &vop_blkatoff_desc, fifo_blkatoff }, /* blkatoff */
183 { &vop_valloc_desc, fifo_valloc }, /* valloc */
184 { &vop_reallocblks_desc, fifo_reallocblks }, /* reallocblks */
185 { &vop_vfree_desc, ffs_vfree }, /* vfree */
186 { &vop_truncate_desc, fifo_truncate }, /* truncate */
187 { &vop_update_desc, ffs_update }, /* update */
188 { &vop_bwrite_desc, vn_bwrite },
189 { (struct vnodeop_desc*)NULL, (int(*)())NULL }
190 };
191 struct vnodeopv_desc ffs_fifoop_opv_desc =
192 { &ffs_fifoop_p, ffs_fifoop_entries };
193 #endif /* FIFO */
194
195 /*
196 * Enabling cluster read/write operations.
197 */
198 int doclusterread = 1;
199 int doclusterwrite = 1;
200
201 #include <ufs/ufs/ufs_readwrite.c>
202
203 /*
204 * Synch an open file.
205 */
206 /* ARGSUSED */
207 int
ffs_fsync(ap)208 ffs_fsync(ap)
209 struct vop_fsync_args /* {
210 struct vnode *a_vp;
211 struct ucred *a_cred;
212 int a_waitfor;
213 struct proc *a_p;
214 } */ *ap;
215 {
216 register struct vnode *vp = ap->a_vp;
217 register struct buf *bp;
218 struct timeval tv;
219 struct buf *nbp;
220 int s;
221
222 /*
223 * Flush all dirty buffers associated with a vnode.
224 */
225 loop:
226 s = splbio();
227 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
228 nbp = bp->b_vnbufs.le_next;
229 if ((bp->b_flags & B_BUSY))
230 continue;
231 if ((bp->b_flags & B_DELWRI) == 0)
232 panic("ffs_fsync: not dirty");
233 bremfree(bp);
234 bp->b_flags |= B_BUSY;
235 splx(s);
236 /*
237 * Wait for I/O associated with indirect blocks to complete,
238 * since there is no way to quickly wait for them below.
239 */
240 if (bp->b_vp == vp || ap->a_waitfor == MNT_NOWAIT)
241 (void) bawrite(bp);
242 else
243 (void) bwrite(bp);
244 goto loop;
245 }
246 if (ap->a_waitfor == MNT_WAIT) {
247 while (vp->v_numoutput) {
248 vp->v_flag |= VBWAIT;
249 sleep((caddr_t)&vp->v_numoutput, PRIBIO + 1);
250 }
251 #ifdef DIAGNOSTIC
252 if (vp->v_dirtyblkhd.lh_first) {
253 vprint("ffs_fsync: dirty", vp);
254 goto loop;
255 }
256 #endif
257 }
258 splx(s);
259 tv = time;
260 return (VOP_UPDATE(ap->a_vp, &tv, &tv, ap->a_waitfor == MNT_WAIT));
261 }
262
263 /*
264 * Reclaim an inode so that it can be used for other purposes.
265 */
266 int
ffs_reclaim(ap)267 ffs_reclaim(ap)
268 struct vop_reclaim_args /* {
269 struct vnode *a_vp;
270 struct proc *a_p;
271 } */ *ap;
272 {
273 register struct vnode *vp = ap->a_vp;
274 int error;
275
276 if (error = ufs_reclaim(vp, ap->a_p))
277 return (error);
278 FREE(vp->v_data, VFSTOUFS(vp->v_mount)->um_devvp->v_tag == VT_MFS ?
279 M_MFSNODE : M_FFSNODE);
280 vp->v_data = NULL;
281 return (0);
282 }
283