Line data Source code
1 : /* $OpenBSD: ext2fs_subr.c,v 1.35 2016/08/10 07:53:02 natano Exp $ */
2 : /* $NetBSD: ext2fs_subr.c,v 1.1 1997/06/11 09:34:03 bouyer Exp $ */
3 :
4 : /*
5 : * Copyright (c) 1997 Manuel Bouyer.
6 : * Copyright (c) 1982, 1986, 1989, 1993
7 : * The Regents of the University of California. All rights reserved.
8 : *
9 : * Redistribution and use in source and binary forms, with or without
10 : * modification, are permitted provided that the following conditions
11 : * are met:
12 : * 1. Redistributions of source code must retain the above copyright
13 : * notice, this list of conditions and the following disclaimer.
14 : * 2. Redistributions in binary form must reproduce the above copyright
15 : * notice, this list of conditions and the following disclaimer in the
16 : * documentation and/or other materials provided with the distribution.
17 : * 3. Neither the name of the University nor the names of its contributors
18 : * may be used to endorse or promote products derived from this software
19 : * without specific prior written permission.
20 : *
21 : * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 : * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 : * SUCH DAMAGE.
32 : *
33 : * @(#)ffs_subr.c 8.2 (Berkeley) 9/21/93
34 : * Modified for ext2fs by Manuel Bouyer.
35 : */
36 :
37 : #include <sys/param.h>
38 : #include <sys/systm.h>
39 : #include <sys/vnode.h>
40 : #include <sys/mount.h>
41 : #include <sys/buf.h>
42 : #include <sys/specdev.h>
43 :
44 : #include <ufs/ufs/quota.h>
45 : #include <ufs/ufs/inode.h>
46 : #include <ufs/ufs/ufsmount.h>
47 :
48 : #include <ufs/ext2fs/ext2fs.h>
49 : #include <ufs/ext2fs/ext2fs_extern.h>
50 : #include <ufs/ext2fs/ext2fs_extents.h>
51 :
52 : #ifdef _KERNEL
53 :
54 : /*
55 : * Return buffer with the contents of block "offset" from the beginning of
56 : * directory "ip". If "res" is non-zero, fill it in with a pointer to the
57 : * remaining space in the directory.
58 : */
59 : int
60 0 : ext2fs_bufatoff(struct inode *ip, off_t offset, char **res, struct buf **bpp)
61 : {
62 : struct vnode *vp;
63 : struct m_ext2fs *fs;
64 0 : struct buf *bp;
65 : daddr_t lbn, pos;
66 : int error;
67 :
68 0 : vp = ITOV(ip);
69 0 : fs = ip->i_e2fs;
70 0 : lbn = lblkno(fs, offset);
71 :
72 0 : if (ip->i_e2din->e2di_flags & EXT4_EXTENTS) {
73 0 : struct ext4_extent_path path;
74 : struct ext4_extent *ep;
75 :
76 0 : memset(&path, 0, sizeof path);
77 0 : if (ext4_ext_find_extent(fs, ip, lbn, &path) == NULL ||
78 0 : (ep = path.ep_ext) == NULL)
79 0 : goto normal;
80 :
81 0 : if (path.ep_bp != NULL) {
82 0 : brelse(path.ep_bp);
83 0 : path.ep_bp = NULL;
84 0 : }
85 0 : pos = lbn - ep->e_blk + (((daddr_t)ep->e_start_hi << 32) | ep->e_start_lo);
86 0 : error = bread(ip->i_devvp, fsbtodb(fs, pos), fs->e2fs_bsize, &bp);
87 0 : if (error) {
88 0 : brelse(bp);
89 0 : return (error);
90 : }
91 :
92 0 : if (res)
93 0 : *res = (char *)bp->b_data + blkoff(fs, offset);
94 :
95 0 : *bpp = bp;
96 :
97 0 : return (0);
98 0 : }
99 :
100 : normal:
101 0 : *bpp = NULL;
102 0 : if ((error = bread(vp, lbn, fs->e2fs_bsize, &bp)) != 0) {
103 0 : brelse(bp);
104 0 : return (error);
105 : }
106 0 : if (res)
107 0 : *res = (char *)bp->b_data + blkoff(fs, offset);
108 0 : *bpp = bp;
109 0 : return (0);
110 0 : }
111 : #endif
112 :
113 : #if defined(_KERNEL) && defined(DIAGNOSTIC)
114 : void
115 0 : ext2fs_checkoverlap(struct buf *bp, struct inode *ip)
116 : {
117 : struct buf *ep;
118 0 : struct vnode *vp;
119 : daddr_t start, last;
120 :
121 0 : start = bp->b_blkno;
122 0 : last = start + btodb(bp->b_bcount) - 1;
123 0 : LIST_FOREACH(ep, &bufhead, b_list) {
124 0 : if (ep == bp || (ep->b_flags & B_INVAL) ||
125 0 : ep->b_vp == NULLVP)
126 : continue;
127 0 : if (VOP_BMAP(ep->b_vp, 0, &vp, NULL, NULL))
128 : continue;
129 0 : if (vp != ip->i_devvp)
130 : continue;
131 : /* look for overlap */
132 0 : if (ep->b_bcount == 0 || ep->b_blkno > last ||
133 0 : ep->b_blkno + btodb(ep->b_bcount) <= start)
134 : continue;
135 0 : vprint("Disk overlap", vp);
136 0 : printf("\tstart %lld, end %lld overlap start %lld, end %lld\n",
137 0 : start, last, (long long)ep->b_blkno,
138 0 : (long long)(ep->b_blkno + btodb(ep->b_bcount) - 1));
139 0 : panic("Disk buffer overlap");
140 : }
141 0 : }
142 : #endif /* DIAGNOSTIC */
143 :
144 : /*
145 : * Initialize the vnode associated with a new inode, handle aliased vnodes.
146 : */
147 : int
148 0 : ext2fs_vinit(struct mount *mp, struct vnode **vpp)
149 : {
150 : struct inode *ip;
151 : struct vnode *vp, *nvp;
152 0 : struct timeval tv;
153 :
154 0 : vp = *vpp;
155 0 : ip = VTOI(vp);
156 0 : vp->v_type = IFTOVT(ip->i_e2fs_mode);
157 :
158 0 : switch(vp->v_type) {
159 : case VCHR:
160 : case VBLK:
161 0 : vp->v_op = &ext2fs_specvops;
162 :
163 0 : nvp = checkalias(vp, letoh32(ip->i_e2din->e2di_rdev), mp);
164 0 : if (nvp != NULL) {
165 : /*
166 : * Discard unneeded vnode, but save its inode. Note
167 : * that the lock is carried over in the inode to the
168 : * replacement vnode.
169 : */
170 0 : nvp->v_data = vp->v_data;
171 0 : vp->v_data = NULL;
172 0 : vp->v_op = &spec_vops;
173 : #ifdef VFSLCKDEBUG
174 : vp->v_flag &= ~VLOCKSWORK;
175 : #endif
176 0 : vrele(vp);
177 0 : vgone(vp);
178 : /* Reinitialize aliased vnode. */
179 : vp = nvp;
180 0 : ip->i_vnode = vp;
181 0 : }
182 :
183 : break;
184 :
185 : case VFIFO:
186 : #ifdef FIFO
187 0 : vp->v_op = &ext2fs_fifovops;
188 0 : break;
189 : #else
190 : return (EOPNOTSUPP);
191 : #endif /* FIFO */
192 :
193 : default:
194 :
195 : break;
196 : }
197 :
198 0 : if (ip->i_number == EXT2_ROOTINO)
199 0 : vp->v_flag |= VROOT;
200 :
201 : /* Initialize modrev times */
202 0 : getmicrouptime(&tv);
203 0 : ip->i_modrev = (u_quad_t)tv.tv_sec << 32;
204 0 : ip->i_modrev |= (u_quad_t)tv.tv_usec * 4294;
205 :
206 0 : *vpp = vp;
207 :
208 0 : return (0);
209 0 : }
|