Commit | Line | Data |
---|---|---|
f86df66c | 1 | /* subr_xxx.c 3.2 %G% */ |
ae9e2121 BJ |
2 | |
3 | #include "../h/param.h" | |
4 | #include "../h/systm.h" | |
5 | #include "../h/conf.h" | |
6 | #include "../h/inode.h" | |
7 | #include "../h/dir.h" | |
8 | #include "../h/user.h" | |
9 | #include "../h/buf.h" | |
10 | #include "../h/proc.h" | |
11 | ||
12 | /* | |
13 | * Bmap defines the structure of file system storage | |
14 | * by returning the physical block number on a device given the | |
15 | * inode and the logical block number in a file. | |
16 | * When convenient, it also leaves the physical | |
17 | * block number of the next block of the file in rablock | |
18 | * for use in read-ahead. | |
19 | */ | |
20 | daddr_t | |
21 | bmap(ip, bn, rwflg) | |
22 | register struct inode *ip; | |
23 | daddr_t bn; | |
24 | { | |
25 | register i; | |
26 | struct buf *bp, *nbp; | |
27 | int j, sh; | |
28 | daddr_t nb, *bap; | |
29 | dev_t dev; | |
30 | ||
31 | if(bn < 0) { | |
32 | u.u_error = EFBIG; | |
33 | return((daddr_t)0); | |
34 | } | |
35 | dev = ip->i_dev; | |
36 | rablock = 0; | |
37 | ||
38 | /* | |
39 | * blocks 0..NADDR-4 are direct blocks | |
40 | */ | |
41 | if(bn < NADDR-3) { | |
42 | i = bn; | |
43 | nb = ip->i_un.i_addr[i]; | |
44 | if(nb == 0) { | |
45 | if(rwflg==B_READ || (bp = alloc(dev))==NULL) | |
46 | return((daddr_t)-1); | |
47 | nb = dbtofsb(bp->b_blkno); | |
48 | bdwrite(bp); | |
49 | ip->i_un.i_addr[i] = nb; | |
50 | ip->i_flag |= IUPD|ICHG; | |
51 | } | |
52 | if(i < NADDR-4) | |
53 | rablock = ip->i_un.i_addr[i+1]; | |
54 | return(nb); | |
55 | } | |
56 | ||
57 | /* | |
58 | * addresses NADDR-3, NADDR-2, and NADDR-1 | |
59 | * have single, double, triple indirect blocks. | |
60 | * the first step is to determine | |
61 | * how many levels of indirection. | |
62 | */ | |
63 | sh = 0; | |
64 | nb = 1; | |
65 | bn -= NADDR-3; | |
66 | for(j=3; j>0; j--) { | |
67 | sh += NSHIFT; | |
68 | nb <<= NSHIFT; | |
69 | if(bn < nb) | |
70 | break; | |
71 | bn -= nb; | |
72 | } | |
73 | if(j == 0) { | |
74 | u.u_error = EFBIG; | |
75 | return((daddr_t)0); | |
76 | } | |
77 | ||
78 | /* | |
79 | * fetch the address from the inode | |
80 | */ | |
81 | nb = ip->i_un.i_addr[NADDR-j]; | |
82 | if(nb == 0) { | |
83 | if(rwflg==B_READ || (bp = alloc(dev))==NULL) | |
84 | return((daddr_t)-1); | |
85 | nb = dbtofsb(bp->b_blkno); | |
86 | bdwrite(bp); | |
87 | ip->i_un.i_addr[NADDR-j] = nb; | |
88 | ip->i_flag |= IUPD|ICHG; | |
89 | } | |
90 | ||
91 | /* | |
92 | * fetch through the indirect blocks | |
93 | */ | |
94 | for(; j<=3; j++) { | |
95 | bp = bread(dev, nb); | |
96 | if(bp->b_flags & B_ERROR) { | |
97 | brelse(bp); | |
98 | return((daddr_t)0); | |
99 | } | |
100 | bap = bp->b_un.b_daddr; | |
101 | sh -= NSHIFT; | |
102 | i = (bn>>sh) & NMASK; | |
103 | nb = bap[i]; | |
104 | if(nb == 0) { | |
105 | if(rwflg==B_READ || (nbp = alloc(dev))==NULL) { | |
106 | brelse(bp); | |
107 | return((daddr_t)-1); | |
108 | } | |
109 | nb = dbtofsb(nbp->b_blkno); | |
110 | bdwrite(nbp); | |
111 | bap[i] = nb; | |
112 | bdwrite(bp); | |
113 | } else | |
114 | brelse(bp); | |
115 | } | |
116 | ||
117 | /* | |
118 | * calculate read-ahead. | |
119 | */ | |
120 | if(i < NINDIR-1) | |
121 | rablock = bap[i+1]; | |
122 | return(nb); | |
123 | } | |
124 | ||
125 | /* | |
126 | * Pass back c to the user at his location u_base; | |
127 | * update u_base, u_count, and u_offset. Return -1 | |
128 | * on the last character of the user's read. | |
129 | * u_base is in the user address space unless u_segflg is set. | |
130 | */ | |
131 | passc(c) | |
132 | register c; | |
133 | { | |
134 | register id; | |
135 | ||
136 | if((id = u.u_segflg) == 1) | |
137 | *u.u_base = c; | |
138 | else | |
139 | if(id?suibyte(u.u_base, c):subyte(u.u_base, c) < 0) { | |
140 | u.u_error = EFAULT; | |
141 | return(-1); | |
142 | } | |
143 | u.u_count--; | |
144 | u.u_offset++; | |
145 | u.u_base++; | |
146 | return(u.u_count == 0? -1: 0); | |
147 | } | |
148 | ||
149 | /* | |
150 | * Pick up and return the next character from the user's | |
151 | * write call at location u_base; | |
152 | * update u_base, u_count, and u_offset. Return -1 | |
153 | * when u_count is exhausted. u_base is in the user's | |
154 | * address space unless u_segflg is set. | |
155 | */ | |
156 | /* | |
157 | cpass() | |
158 | { | |
159 | register c, id; | |
160 | ||
161 | if(u.u_count == 0) | |
162 | return(-1); | |
163 | if((id = u.u_segflg) == 1) | |
164 | c = *u.u_base; | |
165 | else | |
166 | if((c = id==0?fubyte(u.u_base):fuibyte(u.u_base)) < 0) { | |
167 | u.u_error = EFAULT; | |
168 | return(-1); | |
169 | } | |
170 | u.u_count--; | |
171 | u.u_offset++; | |
172 | u.u_base++; | |
173 | return(c&0377); | |
174 | } | |
175 | */ | |
176 | ||
177 | /* | |
178 | * Routine which sets a user error; placed in | |
179 | * illegal entries in the bdevsw and cdevsw tables. | |
180 | */ | |
181 | nodev() | |
182 | { | |
183 | ||
184 | u.u_error = ENODEV; | |
185 | } | |
186 | ||
187 | /* | |
188 | * Null routine; placed in insignificant entries | |
189 | * in the bdevsw and cdevsw tables. | |
190 | */ | |
191 | nulldev() | |
192 | { | |
193 | ||
194 | } | |
195 | ||
196 | imin(a, b) | |
197 | { | |
198 | ||
199 | return (a < b ? a : b); | |
200 | } | |
201 | ||
202 | imax(a, b) | |
203 | { | |
204 | ||
205 | return (a > b ? a : b); | |
206 | } | |
207 | ||
208 | struct proc * | |
209 | pfind(pid) | |
210 | int pid; | |
211 | { | |
212 | register struct proc *p; | |
213 | ||
214 | for (p = &proc[pidhash[PIDHASH(pid)]]; p != &proc[0]; p = &proc[p->p_idhash]) | |
215 | if (p->p_pid == pid) | |
216 | return (p); | |
217 | return ((struct proc *)0); | |
218 | } |