This source file includes following definitions.
- ext2fs_read
- ext2fs_write
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/resourcevar.h>
40 #include <sys/kernel.h>
41 #include <sys/file.h>
42 #include <sys/stat.h>
43 #include <sys/buf.h>
44 #include <sys/proc.h>
45 #include <sys/conf.h>
46 #include <sys/mount.h>
47 #include <sys/vnode.h>
48 #include <sys/malloc.h>
49 #include <sys/signalvar.h>
50
51 #include <ufs/ufs/quota.h>
52 #include <ufs/ufs/inode.h>
53 #include <ufs/ext2fs/ext2fs.h>
54 #include <ufs/ext2fs/ext2fs_extern.h>
55
56
57 #define doclusterread 0
58 #define doclusterwrite 0
59
60
61
62
63
64 int
65 ext2fs_read(void *v)
66 {
67 struct vop_read_args *ap = v;
68 struct vnode *vp;
69 struct inode *ip;
70 struct uio *uio;
71 struct m_ext2fs *fs;
72 struct buf *bp;
73 daddr64_t lbn, nextlbn;
74 off_t bytesinfile;
75 long size, xfersize, blkoffset;
76 int error;
77
78 vp = ap->a_vp;
79 ip = VTOI(vp);
80 uio = ap->a_uio;
81
82 #ifdef DIAGNOSTIC
83 if (uio->uio_rw != UIO_READ)
84 panic("%s: mode", "ext2fs_read");
85
86 if (vp->v_type == VLNK) {
87 if ((int)ext2fs_size(ip) < vp->v_mount->mnt_maxsymlinklen ||
88 (vp->v_mount->mnt_maxsymlinklen == 0 &&
89 ip->i_e2fs_nblock == 0))
90 panic("%s: short symlink", "ext2fs_read");
91 } else if (vp->v_type != VREG && vp->v_type != VDIR)
92 panic("%s: type %d", "ext2fs_read", vp->v_type);
93 #endif
94 fs = ip->i_e2fs;
95 if ((u_int64_t)uio->uio_offset >
96 ((u_int64_t)0x80000000 * fs->e2fs_bsize - 1))
97 return (EFBIG);
98 if (uio->uio_resid == 0)
99 return (0);
100
101 for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) {
102 if ((bytesinfile = ext2fs_size(ip) - uio->uio_offset) <= 0)
103 break;
104 lbn = lblkno(fs, uio->uio_offset);
105 nextlbn = lbn + 1;
106 size = fs->e2fs_bsize;
107 blkoffset = blkoff(fs, uio->uio_offset);
108 xfersize = fs->e2fs_bsize - blkoffset;
109 if (uio->uio_resid < xfersize)
110 xfersize = uio->uio_resid;
111 if (bytesinfile < xfersize)
112 xfersize = bytesinfile;
113
114 if (lblktosize(fs, nextlbn) >= ext2fs_size(ip))
115 error = bread(vp, lbn, size, NOCRED, &bp);
116 else if (lbn - 1 == ip->i_ci.ci_lastr) {
117 int nextsize = fs->e2fs_bsize;
118 error = breadn(vp, lbn,
119 size, &nextlbn, &nextsize, 1, NOCRED, &bp);
120 } else
121 error = bread(vp, lbn, size, NOCRED, &bp);
122 if (error)
123 break;
124 ip->i_ci.ci_lastr = lbn;
125
126
127
128
129
130
131
132
133 size -= bp->b_resid;
134 if (size < xfersize) {
135 if (size == 0)
136 break;
137 xfersize = size;
138 }
139 error = uiomove((char *)bp->b_data + blkoffset, xfersize, uio);
140 if (error)
141 break;
142 brelse(bp);
143 }
144 if (bp != NULL)
145 brelse(bp);
146
147 if (!(vp->v_mount->mnt_flag & MNT_NOATIME)) {
148 ip->i_flag |= IN_ACCESS;
149 }
150 return (error);
151 }
152
153
154
155
156 int
157 ext2fs_write(void *v)
158 {
159 struct vop_write_args *ap = v;
160 struct vnode *vp;
161 struct uio *uio;
162 struct inode *ip;
163 struct m_ext2fs *fs;
164 struct buf *bp;
165 struct proc *p;
166 int32_t lbn;
167 off_t osize;
168 int blkoffset, error, flags, ioflag, resid, size, xfersize;
169
170 ioflag = ap->a_ioflag;
171 uio = ap->a_uio;
172 vp = ap->a_vp;
173 ip = VTOI(vp);
174
175 #ifdef DIAGNOSTIC
176 if (uio->uio_rw != UIO_WRITE)
177 panic("%s: mode", "ext2fs_write");
178 #endif
179
180
181
182
183
184 if (uio->uio_resid == 0)
185 return (0);
186
187 switch (vp->v_type) {
188 case VREG:
189 if (ioflag & IO_APPEND)
190 uio->uio_offset = ext2fs_size(ip);
191 if ((ip->i_e2fs_flags & EXT2_APPEND) &&
192 uio->uio_offset != ext2fs_size(ip))
193 return (EPERM);
194
195 case VLNK:
196 break;
197 case VDIR:
198 if ((ioflag & IO_SYNC) == 0)
199 panic("%s: nonsync dir write", "ext2fs_write");
200 break;
201 default:
202 panic("%s: type", "ext2fs_write");
203 }
204
205 fs = ip->i_e2fs;
206 if (uio->uio_offset < 0 ||
207 (u_int64_t)uio->uio_offset + uio->uio_resid >
208 ((u_int64_t)0x80000000 * fs->e2fs_bsize - 1))
209 return (EFBIG);
210
211
212
213
214 p = uio->uio_procp;
215 if (vp->v_type == VREG && p &&
216 uio->uio_offset + uio->uio_resid >
217 p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
218 psignal(p, SIGXFSZ);
219 return (EFBIG);
220 }
221
222 resid = uio->uio_resid;
223 osize = ext2fs_size(ip);
224 flags = ioflag & IO_SYNC ? B_SYNC : 0;
225
226 for (error = 0; uio->uio_resid > 0;) {
227 lbn = lblkno(fs, uio->uio_offset);
228 blkoffset = blkoff(fs, uio->uio_offset);
229 xfersize = fs->e2fs_bsize - blkoffset;
230 if (uio->uio_resid < xfersize)
231 xfersize = uio->uio_resid;
232 if (fs->e2fs_bsize > xfersize)
233 flags |= B_CLRBUF;
234 else
235 flags &= ~B_CLRBUF;
236
237 error = ext2fs_buf_alloc(ip,
238 lbn, blkoffset + xfersize, ap->a_cred, &bp, flags);
239 if (error)
240 break;
241 if (uio->uio_offset + xfersize > ext2fs_size(ip)) {
242 error = ext2fs_setsize(ip, uio->uio_offset + xfersize);
243 if (error)
244 break;
245 uvm_vnp_setsize(vp, ip->i_e2fs_size);
246 }
247 uvm_vnp_uncache(vp);
248
249 size = fs->e2fs_bsize - bp->b_resid;
250 if (size < xfersize)
251 xfersize = size;
252
253 error =
254 uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio);
255 if (ioflag & IO_SYNC)
256 (void)bwrite(bp);
257 else if (xfersize + blkoffset == fs->e2fs_bsize) {
258 if (doclusterwrite)
259 cluster_write(bp, &ip->i_ci, ext2fs_size(ip));
260 else
261 bawrite(bp);
262 } else
263 bdwrite(bp);
264 if (error || xfersize == 0)
265 break;
266 ip->i_flag |= IN_CHANGE | IN_UPDATE;
267 }
268
269
270
271
272
273 if (resid > uio->uio_resid && ap->a_cred && ap->a_cred->cr_uid != 0)
274 ip->i_e2fs_mode &= ~(ISUID | ISGID);
275 if (error) {
276 if (ioflag & IO_UNIT) {
277 (void)ext2fs_truncate(ip, osize,
278 ioflag & IO_SYNC, ap->a_cred);
279 uio->uio_offset -= resid - uio->uio_resid;
280 uio->uio_resid = resid;
281 }
282 } else if (resid > uio->uio_resid && (ioflag & IO_SYNC)) {
283 error = ext2fs_update(ip, NULL, NULL, 1);
284 }
285 return (error);
286 }