macroize cylinder group array references to allow dynamic tables
[unix-history] / usr / src / sys / ufs / lfs / lfs_vfsops.c
CommitLineData
da7c5cc6 1/*
0880b18e 2 * Copyright (c) 1982, 1986 Regents of the University of California.
da7c5cc6
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
27d00e76 6 * @(#)lfs_vfsops.c 7.7 (Berkeley) %G%
da7c5cc6 7 */
71e4e98b 8
94368568
JB
9#include "param.h"
10#include "systm.h"
11#include "dir.h"
12#include "user.h"
13#include "inode.h"
14#include "proc.h"
15#include "fs.h"
16#include "buf.h"
17#include "mount.h"
18#include "file.h"
19#include "conf.h"
ec67a3ce
MK
20#include "ioctl.h"
21#include "disklabel.h"
22#include "stat.h"
4def0c5e 23#include "malloc.h"
609e7cfa
MK
24#include "ioctl.h"
25#include "disklabel.h"
26#include "stat.h"
71e4e98b
SL
27
28smount()
29{
30 register struct a {
31 char *fspec;
32 char *freg;
33 int ronly;
715baff1 34 } *uap = (struct a *)u.u_ap;
71e4e98b
SL
35 dev_t dev;
36 register struct inode *ip;
37 register struct fs *fs;
715baff1 38 register struct nameidata *ndp = &u.u_nd;
76335100 39 u_int len;
71e4e98b 40
715baff1 41 u.u_error = getmdev(&dev, uap->fspec);
71e4e98b
SL
42 if (u.u_error)
43 return;
c2f29eff 44 ndp->ni_nameiop = LOOKUP | FOLLOW;
715baff1
KM
45 ndp->ni_segflg = UIO_USERSPACE;
46 ndp->ni_dirp = (caddr_t)uap->freg;
47 ip = namei(ndp);
71e4e98b
SL
48 if (ip == NULL)
49 return;
6d07f4cd 50 if (ip->i_count != 1) {
71e4e98b
SL
51 iput(ip);
52 u.u_error = EBUSY;
53 return;
54 }
6d07f4cd
KM
55 if ((ip->i_mode&IFMT) != IFDIR) {
56 iput(ip);
57 u.u_error = ENOTDIR;
58 return;
59 }
71e4e98b 60 fs = mountfs(dev, uap->ronly, ip);
27d00e76
KM
61 if (fs == 0) {
62 iput(ip);
71e4e98b 63 return;
27d00e76 64 }
76335100 65 (void) copyinstr(uap->freg, fs->fs_fsmnt, sizeof(fs->fs_fsmnt)-1, &len);
32af08ce 66 bzero(fs->fs_fsmnt + len, sizeof (fs->fs_fsmnt) - len);
71e4e98b
SL
67}
68
71e4e98b
SL
69struct fs *
70mountfs(dev, ronly, ip)
71 dev_t dev;
72 int ronly;
73 struct inode *ip;
74{
27d00e76
KM
75 register struct mount *mp;
76 struct mount *fmp = NULL;
77 struct buf *tp = NULL;
78 register struct buf *bp = NULL;
71e4e98b 79 register struct fs *fs;
ec67a3ce
MK
80 struct partinfo dpart;
81 int havepart = 0, blks;
27d00e76 82 caddr_t base, space;
71e4e98b 83 int i, size;
1c281610 84 register error;
6d07f4cd 85 int needclose = 0;
71e4e98b 86
27d00e76
KM
87 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
88 if (mp->m_fs == NULL) {
89 if (fmp == NULL)
90 fmp = mp;
91 } else if (dev == mp->m_dev) {
92 u.u_error = EBUSY; /* XXX */
93 return ((struct fs *) NULL);
94 }
95 }
96 if ((mp = fmp) == NULL) {
97 u.u_error = EMFILE; /* needs translation XXX */
98 return ((struct fs *) NULL);
99 }
100 mp->m_fs = (struct fs *)1; /* just to reserve this slot */
101 mp->m_dev = dev;
1c281610 102 error =
ec67a3ce
MK
103 (*bdevsw[major(dev)].d_open)(dev, ronly ? FREAD : FREAD|FWRITE,
104 S_IFBLK);
27d00e76
KM
105 if (error) {
106 u.u_error = error;
107 mp->m_fs = NULL;
108 return ((struct fs *) NULL);
109 }
6d07f4cd 110 needclose = 1;
609e7cfa
MK
111 if ((*bdevsw[major(dev)].d_ioctl)(dev, DIOCGPART,
112 (caddr_t)&dpart, FREAD) == 0) {
113 havepart = 1;
114 size = dpart.disklab->d_secsize;
115 } else
116 size = DEV_BSIZE;
ec67a3ce
MK
117#ifdef SECSIZE
118 /*
119 * If possible, determine hardware sector size
120 * and adjust fsbtodb to correspond.
121 */
122#endif SECSIZE
123 if ((*bdevsw[major(dev)].d_ioctl)(dev, DIOCGPART,
124 (caddr_t)&dpart, FREAD) == 0) {
125 havepart = 1;
126 size = dpart.disklab->d_secsize;
127#ifdef SECSIZE
128 if (size < MINSECSIZE) {
129 error = EINVAL;
130 goto out;
131 }
132#endif SECSIZE
133 } else
134 size = DEV_BSIZE;
135#ifdef SECSIZE
136 tp = bread(dev, (daddr_t)(SBOFF / size), SBSIZE, size);
137#else SECSIZE
71e4e98b 138 tp = bread(dev, SBLOCK, SBSIZE);
ec67a3ce 139#endif SECSIZE
27d00e76
KM
140 if (tp->b_flags & B_ERROR) {
141 mp->m_fs = NULL;
71e4e98b 142 goto out;
27d00e76
KM
143 }
144 fs = tp->b_un.b_fs;
ec67a3ce
MK
145 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
146 fs->fs_bsize < sizeof(struct fs)) {
1c281610
MK
147 error = EINVAL; /* also needs translation */
148 goto out;
149 }
4def0c5e
KM
150 mp->m_fs = (struct fs *)malloc(fs->fs_sbsize, M_SUPERBLK, M_WAITOK);
151 bcopy((caddr_t)tp->b_un.b_addr, (caddr_t)mp->m_fs,
71e4e98b
SL
152 (u_int)fs->fs_sbsize);
153 brelse(tp);
27d00e76 154 tp = NULL;
4def0c5e 155 fs = mp->m_fs;
71e4e98b
SL
156 fs->fs_ronly = (ronly != 0);
157 if (ronly == 0)
158 fs->fs_fmod = 1;
609e7cfa
MK
159 if (havepart) {
160 dpart.part->p_fstype = FS_BSDFFS;
161 dpart.part->p_fsize = fs->fs_fsize;
162 dpart.part->p_frag = fs->fs_frag;
42ff4c2e 163 dpart.part->p_cpg = fs->fs_cpg;
609e7cfa
MK
164 fs->fs_dbsize = size;
165 }
ec67a3ce
MK
166#ifdef SECSIZE
167 /*
168 * If we have a disk label, force per-partition
169 * filesystem information to be correct
170 * and set correct current fsbtodb shift.
171 */
172#endif SECSIZE
173 if (havepart) {
174 dpart.part->p_fstype = FS_BSDFFS;
175 dpart.part->p_fsize = fs->fs_fsize;
176 dpart.part->p_frag = fs->fs_frag;
177#ifdef SECSIZE
178#ifdef tahoe
179 /*
180 * Save the original fsbtodb shift to restore on updates.
181 * (Console doesn't understand fsbtodb changes.)
182 */
183 fs->fs_sparecon[0] = fs->fs_fsbtodb;
184#endif
185 i = fs->fs_fsize / size;
186 for (fs->fs_fsbtodb = 0; i > 1; i >>= 1)
187 fs->fs_fsbtodb++;
188#endif SECSIZE
189 fs->fs_dbsize = size;
190 }
71e4e98b 191 blks = howmany(fs->fs_cssize, fs->fs_fsize);
27d00e76
KM
192 base = space = (caddr_t)malloc(fs->fs_cssize, M_SUPERBLK, M_WAITOK);
193 if (space == NULL) {
1c281610 194 error = ENOMEM;
71e4e98b 195 goto out;
1c281610 196 }
71e4e98b
SL
197 for (i = 0; i < blks; i += fs->fs_frag) {
198 size = fs->fs_bsize;
199 if (i + fs->fs_frag > blks)
200 size = (blks - i) * fs->fs_fsize;
ec67a3ce
MK
201#ifdef SECSIZE
202 tp = bread(dev, fsbtodb(fs, fs->fs_csaddr + i), size,
203 fs->fs_dbsize);
204#else SECSIZE
71e4e98b 205 tp = bread(dev, fsbtodb(fs, fs->fs_csaddr + i), size);
ec67a3ce 206#endif SECSIZE
71e4e98b 207 if (tp->b_flags&B_ERROR) {
27d00e76 208 free(base, M_SUPERBLK);
71e4e98b
SL
209 goto out;
210 }
211 bcopy((caddr_t)tp->b_un.b_addr, space, (u_int)size);
60f9c9e3 212 fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space;
71e4e98b
SL
213 space += size;
214 brelse(tp);
27d00e76 215 tp = NULL;
71e4e98b
SL
216 }
217 mp->m_inodp = ip;
71e4e98b
SL
218 if (ip) {
219 ip->i_flag |= IMOUNT;
c2f29eff 220 cacheinval(ip);
71e4e98b
SL
221 iunlock(ip);
222 }
94354803
KM
223 /* Sanity checks for old file systems. XXX */
224 fs->fs_npsect = MAX(fs->fs_npsect, fs->fs_nsect); /* XXX */
225 fs->fs_interleave = MAX(fs->fs_interleave, 1); /* XXX */
ec67a3ce 226
609e7cfa 227
71e4e98b
SL
228 return (fs);
229out:
609e7cfa 230 if (needclose)
27d00e76
KM
231 (void) closei(dev, IFBLK, ronly? FREAD : FREAD|FWRITE);
232 if (mp->m_fs) {
4def0c5e 233 free((caddr_t)mp->m_fs, M_SUPERBLK);
27d00e76
KM
234 mp->m_fs = NULL;
235 }
71e4e98b
SL
236 if (tp)
237 brelse(tp);
27d00e76
KM
238 u.u_error = error ? error : EIO; /* XXX */
239 return ((struct fs *) NULL);
71e4e98b
SL
240}
241
242umount()
243{
244 struct a {
245 char *fspec;
715baff1 246 } *uap = (struct a *)u.u_ap;
71e4e98b 247
715baff1 248 u.u_error = unmount1(uap->fspec, 0);
71e4e98b
SL
249}
250
715baff1
KM
251unmount1(fname, forcibly)
252 caddr_t fname;
71e4e98b
SL
253 int forcibly;
254{
255 dev_t dev;
256 register struct mount *mp;
ec67a3ce 257 int error;
71e4e98b
SL
258 register struct inode *ip;
259 register struct fs *fs;
260
609e7cfa 261 forcibly = 0; /* XXX */
ec67a3ce 262 forcibly = 0; /* XXX */
715baff1 263 error = getmdev(&dev, fname);
71e4e98b
SL
264 if (error)
265 return (error);
266 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
4def0c5e 267 if (mp->m_fs != NULL && dev == mp->m_dev)
71e4e98b
SL
268 goto found;
269 return (EINVAL);
270found:
271 xumount(dev); /* remove unused sticky files from text table */
f93197fc 272 nchinval(dev); /* flush the name cache */
71e4e98b
SL
273 update();
274#ifdef QUOTA
ec67a3ce 275 if ((error = iflush(dev, mp->m_qinod)) && !forcibly)
71e4e98b 276#else
ec67a3ce 277 if ((error = iflush(dev)) && !forcibly)
71e4e98b 278#endif
ec67a3ce 279 return (error);
71e4e98b
SL
280#ifdef QUOTA
281 closedq(mp);
282 /*
283 * Here we have to iflush again to get rid of the quota inode.
ec67a3ce 284 * A drag, but it would be ugly to cheat, & this doesn't happen often.
71e4e98b
SL
285 */
286 (void)iflush(dev, (struct inode *)NULL);
287#endif
288 ip = mp->m_inodp;
289 ip->i_flag &= ~IMOUNT;
4def0c5e
KM
290 fs = mp->m_fs;
291 free((caddr_t)fs->fs_csp[0], M_SUPERBLK);
292 free((caddr_t)mp->m_fs, M_SUPERBLK);
27d00e76
KM
293 mp->m_fs = NULL;
294 mp->m_dev = NODEV;
71e4e98b 295 mpurge(mp - &mount[0]);
ec67a3ce
MK
296 error = closei(dev, IFBLK, fs->fs_ronly? FREAD : FREAD|FWRITE);
297 irele(ip);
298 return (error);
71e4e98b
SL
299}
300
301sbupdate(mp)
302 struct mount *mp;
303{
4def0c5e 304 register struct fs *fs = mp->m_fs;
71e4e98b
SL
305 register struct buf *bp;
306 int blks;
307 caddr_t space;
308 int i, size;
309
ec67a3ce
MK
310#ifdef SECSIZE
311 bp = getblk(mp->m_dev, (daddr_t)fsbtodb(fs, SBOFF / fs->fs_fsize),
312 (int)fs->fs_sbsize, fs->fs_dbsize);
313#else SECSIZE
71e4e98b 314 bp = getblk(mp->m_dev, SBLOCK, (int)fs->fs_sbsize);
ec67a3ce 315#endif SECSIZE
71e4e98b 316 bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize);
ec67a3ce
MK
317#ifdef SECSIZE
318#ifdef tahoe
319 /* restore standard fsbtodb shift */
320 bp->b_un.b_fs->fs_fsbtodb = fs->fs_sparecon[0];
321 bp->b_un.b_fs->fs_sparecon[0] = 0;
322#endif
323#endif SECSIZE
71e4e98b
SL
324 bwrite(bp);
325 blks = howmany(fs->fs_cssize, fs->fs_fsize);
326 space = (caddr_t)fs->fs_csp[0];
327 for (i = 0; i < blks; i += fs->fs_frag) {
328 size = fs->fs_bsize;
329 if (i + fs->fs_frag > blks)
330 size = (blks - i) * fs->fs_fsize;
ec67a3ce
MK
331#ifdef SECSIZE
332 bp = getblk(mp->m_dev, fsbtodb(fs, fs->fs_csaddr + i), size,
333 fs->fs_dbsize);
334#else SECSIZE
71e4e98b 335 bp = getblk(mp->m_dev, fsbtodb(fs, fs->fs_csaddr + i), size);
ec67a3ce 336#endif SECSIZE
71e4e98b
SL
337 bcopy(space, bp->b_un.b_addr, (u_int)size);
338 space += size;
339 bwrite(bp);
340 }
341}
342
343/*
344 * Common code for mount and umount.
345 * Check that the user's argument is a reasonable
346 * thing on which to mount, and return the device number if so.
347 */
715baff1
KM
348getmdev(pdev, fname)
349 caddr_t fname;
71e4e98b
SL
350 dev_t *pdev;
351{
352 dev_t dev;
353 register struct inode *ip;
715baff1 354 register struct nameidata *ndp = &u.u_nd;
71e4e98b
SL
355
356 if (!suser())
357 return (u.u_error);
715baff1
KM
358 ndp->ni_nameiop = LOOKUP | FOLLOW;
359 ndp->ni_segflg = UIO_USERSPACE;
360 ndp->ni_dirp = fname;
361 ip = namei(ndp);
6d07f4cd
KM
362 if (ip == NULL) {
363 if (u.u_error == ENOENT)
364 return (ENODEV); /* needs translation */
71e4e98b 365 return (u.u_error);
6d07f4cd 366 }
e95cdf5c
MK
367 if ((ip->i_mode&IFMT) != IFBLK) {
368 iput(ip);
71e4e98b 369 return (ENOTBLK);
e95cdf5c 370 }
71e4e98b 371 dev = (dev_t)ip->i_rdev;
e95cdf5c 372 iput(ip);
71e4e98b
SL
373 if (major(dev) >= nblkdev)
374 return (ENXIO);
71e4e98b
SL
375 *pdev = dev;
376 return (0);
377}