<sys/buf2.h>: Remove a number of unneeded #include's.
[dragonfly.git] / sys / vfs / mfs / mfs_vfsops.c
1 /*
2  * Copyright (c) 1989, 1990, 1993, 1994
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  *      @(#)mfs_vfsops.c        8.11 (Berkeley) 6/19/95
30  * $FreeBSD: src/sys/ufs/mfs/mfs_vfsops.c,v 1.81.2.3 2001/07/04 17:35:21 tegge Exp $
31  */
32
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/conf.h>
37 #include <sys/device.h>
38 #include <sys/kernel.h>
39 #include <sys/proc.h>
40 #include <sys/buf.h>
41 #include <sys/mount.h>
42 #include <sys/signalvar.h>
43 #include <sys/signal2.h>
44 #include <sys/spinlock2.h>
45 #include <sys/vnode.h>
46 #include <sys/malloc.h>
47 #include <sys/sysproto.h>
48 #include <sys/mman.h>
49 #include <sys/linker.h>
50 #include <sys/fcntl.h>
51 #include <sys/nlookup.h>
52 #include <sys/devfs.h>
53
54 #include <vm/vm.h>
55 #include <vm/vm_object.h>
56 #include <vm/vm_page.h>
57 #include <vm/vm_pager.h>
58 #include <vm/vnode_pager.h>
59 #include <vm/vm_extern.h>
60
61 #include <sys/buf2.h>
62 #include <sys/thread2.h>
63
64 #include <vfs/ufs/quota.h>
65 #include <vfs/ufs/inode.h>
66 #include <vfs/ufs/ufsmount.h>
67 #include <vfs/ufs/ufs_extern.h>
68 #include <vfs/ufs/fs.h>
69 #include <vfs/ufs/ffs_extern.h>
70
71 #include "mfsnode.h"
72 #include "mfs_extern.h"
73
74 MALLOC_DEFINE(M_MFSNODE, "MFS node", "MFS vnode private part");
75
76 static int      mfs_mount (struct mount *mp,
77                         char *path, caddr_t data, struct ucred *td);
78 static int      mfs_start (struct mount *mp, int flags);
79 static int      mfs_statfs (struct mount *mp, struct statfs *sbp,
80                         struct ucred *cred); 
81 static int      mfs_init (struct vfsconf *);
82 static void     mfs_doio(struct bio *bio, struct mfsnode *mfsp);
83
84 d_open_t        mfsopen;
85 d_close_t       mfsclose;
86 d_strategy_t    mfsstrategy;
87
88 static struct dev_ops mfs_ops = {
89         { "MFS", -1, D_DISK | D_NOEMERGPGR },
90         .d_open =       mfsopen,
91         .d_close =      mfsclose,
92         .d_read =       physread,
93         .d_write =      physwrite,
94         .d_strategy =   mfsstrategy,
95 };
96
97 /*
98  * mfs vfs operations.
99  */
100 static struct vfsops mfs_vfsops = {
101         .vfs_mount =            mfs_mount,
102         .vfs_start =            mfs_start,
103         .vfs_unmount =          ffs_unmount,
104         .vfs_root =             ufs_root,
105         .vfs_quotactl =         ufs_quotactl,
106         .vfs_statfs =           mfs_statfs,
107         .vfs_sync =             ffs_sync,
108         .vfs_vget =             ffs_vget,
109         .vfs_fhtovp =           ffs_fhtovp,
110         .vfs_checkexp =         ufs_check_export,
111         .vfs_vptofh =           ffs_vptofh,
112         .vfs_init =             mfs_init
113 };
114
115 VFS_SET(mfs_vfsops, mfs, 0);
116 MODULE_VERSION(mfs, 1);
117
118 /*
119  * We allow the underlying MFS block device to be opened and read.
120  */
121 int
122 mfsopen(struct dev_open_args *ap)
123 {
124         cdev_t dev = ap->a_head.a_dev;
125
126 #if 0
127         if (ap->a_oflags & FWRITE)
128                 return(EROFS);
129 #endif
130         if (dev->si_drv1)
131                 return(0);
132         return(ENXIO);
133 }
134
135 int
136 mfsclose(struct dev_close_args *ap)
137 {
138         cdev_t dev = ap->a_head.a_dev;
139         struct mfsnode *mfsp;
140
141         if ((mfsp = dev->si_drv1) == NULL)
142                 return(0);
143         mfsp->mfs_active = 0;
144         wakeup((caddr_t)mfsp);
145         return(0);
146 }
147
148 int
149 mfsstrategy(struct dev_strategy_args *ap)
150 {
151         cdev_t dev = ap->a_head.a_dev;
152         struct bio *bio = ap->a_bio;
153         struct buf *bp = bio->bio_buf;
154         off_t boff = bio->bio_offset;
155         off_t eoff = boff + bp->b_bcount;
156         struct mfsnode *mfsp;
157
158         if ((mfsp = dev->si_drv1) == NULL) {
159                 bp->b_error = ENXIO;
160                 goto error;
161         }
162         if (boff < 0)
163                 goto bad;
164         if (eoff > mfsp->mfs_size) {
165                 if (boff > mfsp->mfs_size || (bp->b_flags & B_BNOCLIP))
166                         goto bad;
167                 /*
168                  * Return EOF by completing the I/O with 0 bytes transfered.
169                  * Set B_INVAL to indicate that any data in the buffer is not
170                  * valid.
171                  */
172                 if (boff == mfsp->mfs_size) {
173                         bp->b_resid = bp->b_bcount;
174                         bp->b_flags |= B_INVAL;
175                         goto done;
176                 }
177                 bp->b_bcount = mfsp->mfs_size - boff;
178         }
179
180         /*
181          * Initiate I/O
182          */
183         if (mfsp->mfs_td == curthread) {
184                 mfs_doio(bio, mfsp);
185         } else {
186                 bioq_insert_tail(&mfsp->bio_queue, bio);
187                 wakeup((caddr_t)mfsp);
188         }
189         return(0);
190
191         /*
192          * Failure conditions on bio
193          */
194 bad:
195         bp->b_error = EINVAL;
196 error:
197         bp->b_flags |= B_ERROR | B_INVAL;
198 done:
199         biodone(bio);
200         return(0);
201 }
202
203 /*
204  * mfs_mount
205  *
206  * Called when mounting local physical media
207  *
208  * PARAMETERS:
209  *              mountroot
210  *                      mp      mount point structure
211  *                      path    NULL (flag for root mount!!!)
212  *                      data    <unused>
213  *                      ndp     <unused>
214  *                      p       process (user credentials check [statfs])
215  *
216  *              mount
217  *                      mp      mount point structure
218  *                      path    path to mount point
219  *                      data    pointer to argument struct in user space
220  *                      ndp     mount point namei() return (used for
221  *                              credentials on reload), reused to look
222  *                              up block device.
223  *                      p       process (user credentials check)
224  *
225  * RETURNS:     0       Success
226  *              !0      error number (errno.h)
227  *
228  * LOCK STATE:
229  *
230  *              ENTRY
231  *                      mount point is locked
232  *              EXIT
233  *                      mount point is locked
234  *
235  * NOTES:
236  *              A NULL path can be used for a flag since the mount
237  *              system call will fail with EFAULT in copyinstr in
238  *              namei() if it is a genuine NULL from the user.
239  */
240 /* ARGSUSED */
241 static int
242 mfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
243 {
244         struct vnode *devvp;
245         struct mfs_args args;
246         struct ufsmount *ump;
247         struct fs *fs;
248         struct mfsnode *mfsp;
249         struct nlookupdata nd;
250         size_t size;
251         char devname[16];
252         int flags;
253         int minnum;
254         int error;
255         cdev_t dev;
256
257         /*
258          * Use NULL path to flag a root mount
259          */
260         if (path == NULL) {
261                 /*
262                  ***
263                  * Mounting root file system
264                  ***
265                  */
266
267                 /* you lose */
268                 panic("mfs_mount: mount MFS as root: not configured!");
269         }
270
271         mfsp = NULL;
272
273         /*
274          ***
275          * Mounting non-root file system or updating a file system
276          ***
277          */
278
279         /* copy in user arguments*/
280         error = copyin(data, (caddr_t)&args, sizeof (struct mfs_args));
281         if (error)
282                 goto error_1;
283
284         /*
285          * If updating, check whether changing from read-only to
286          * read/write; if there is no device name, that's all we do.
287          */
288         if (mp->mnt_flag & MNT_UPDATE) {
289                 /*
290                  ********************
291                  * UPDATE
292                  ********************
293                  */
294                 ump = VFSTOUFS(mp);
295                 fs = ump->um_fs;
296                 if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
297                         flags = WRITECLOSE;
298                         if (mp->mnt_flag & MNT_FORCE)
299                                 flags |= FORCECLOSE;
300                         error = ffs_flushfiles(mp, flags);
301                         if (error)
302                                 goto error_1;
303                 }
304                 if (fs->fs_ronly && (mp->mnt_kern_flag & MNTK_WANTRDWR)) {
305                         /* XXX reopen the device vnode read-write */
306                         fs->fs_ronly = 0;
307                 }
308                 /* if not updating name...*/
309                 if (args.fspec == 0) {
310                         /*
311                          * Process export requests.  Jumping to "success"
312                          * will return the vfs_export() error code. 
313                          */
314                         error = vfs_export(mp, &ump->um_export, &args.export);
315                         goto success;
316                 }
317
318                 /* XXX MFS does not support name updating*/
319                 goto success;
320         }
321
322         /*
323          * Do the MALLOC before the make_dev since doing so afterward
324          * might cause a bogus v_data pointer to get dereferenced
325          * elsewhere if MALLOC should block.
326          */
327         mfsp = kmalloc(sizeof *mfsp, M_MFSNODE, M_WAITOK | M_ZERO);
328
329         minnum = (int)curproc->p_pid;
330
331         dev = make_dev(&mfs_ops, minnum, UID_ROOT, GID_WHEEL, 0600,
332                        "mfs%d", minnum);
333         /* It is not clear that these will get initialized otherwise */
334         dev->si_bsize_phys = DEV_BSIZE;
335         dev->si_iosize_max = MAXPHYS;
336         dev->si_drv1 = mfsp;
337         mfsp->mfs_baseoff = args.base;
338         mfsp->mfs_size = args.size;
339         mfsp->mfs_dev = dev;
340         mfsp->mfs_td = curthread;
341         mfsp->mfs_active = 1;
342         bioq_init(&mfsp->bio_queue);
343
344         devfs_config(); /* sync devfs work */
345         ksnprintf(devname, sizeof(devname), "/dev/mfs%d", minnum);
346         nlookup_init(&nd, devname, UIO_SYSSPACE, 0);
347         devvp = NULL;
348         error = nlookup(&nd);
349         if (error == 0) {
350                 devvp = nd.nl_nch.ncp->nc_vp;
351                 if (devvp == NULL)
352                         error = ENOENT;
353                 error = vget(devvp, LK_SHARED);
354         }
355         nlookup_done(&nd);
356
357         if (error)
358                 goto error_1;
359         vn_unlock(devvp);
360
361         /*
362          * Our 'block' device must be backed by a VM object.  Theoretically
363          * we could use the anonymous memory VM object supplied by userland,
364          * but it would be somewhat of a complex task to deal with it
365          * that way since it would result in I/O requests which supply
366          * the VM pages from our own object.
367          *
368          * vnode_pager_alloc() is typically called when a VM object is
369          * being referenced externally.  We have to undo the refs for
370          * the self reference between vnode and object.
371          */
372         vnode_pager_setsize(devvp, args.size);
373
374         /* Save "mounted from" info for mount point (NULL pad)*/
375         copyinstr(args.fspec,                   /* device name*/
376                   mp->mnt_stat.f_mntfromname,   /* save area*/
377                   MNAMELEN - 1,                 /* max size*/
378                   &size);                       /* real size*/
379         bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
380         /* vref is eaten by mount? */
381
382         error = ffs_mountfs(devvp, mp, M_MFSNODE);
383         if (error) {
384                 mfsp->mfs_active = 0;
385                 goto error_2;
386         }
387
388         /*
389          * Initialize FS stat information in mount struct; uses
390          * mp->mnt_stat.f_mntfromname.
391          *
392          * This code is common to root and non-root mounts
393          */
394         VFS_STATFS(mp, &mp->mnt_stat, cred);
395
396         /*
397          * Mark VFS_START MPSAFE; this is to avoid accessing
398          * per-mount token after VFS_START exits
399          */
400         mp->mnt_kern_flag |= MNTK_ST_MPSAFE;
401
402         goto success;
403
404 error_2:        /* error with devvp held*/
405         vrele(devvp);
406
407 error_1:        /* no state to back out*/
408         if (mfsp) {
409                 if (mfsp->mfs_dev) {
410                         destroy_dev(mfsp->mfs_dev);
411                         mfsp->mfs_dev = NULL;
412                 }
413                 kfree(mfsp, M_MFSNODE);
414         }
415
416 success:
417         return(error);
418 }
419
420 /*
421  * Used to grab the process and keep it in the kernel to service
422  * memory filesystem I/O requests.
423  *
424  * Loop servicing I/O requests.
425  * Copy the requested data into or out of the memory filesystem
426  * address space.
427  */
428 /* ARGSUSED */
429 static int
430 mfs_start(struct mount *mp, int flags)
431 {
432         struct vnode *vp = VFSTOUFS(mp)->um_devvp;
433         struct mfsnode *mfsp = vp->v_rdev->si_drv1;
434         struct bio *bio;
435         struct buf *bp;
436         int gotsig = 0, sig;
437         thread_t td = curthread;
438
439         /*
440          * We must prevent the system from trying to swap
441          * out or kill ( when swap space is low, see vm/pageout.c ) the
442          * process.  A deadlock can occur if the process is swapped out,
443          * and the system can loop trying to kill the unkillable ( while
444          * references exist ) MFS process when swap space is low.
445          */
446         KKASSERT(curproc);
447         PHOLD(curproc);
448
449         mfsp->mfs_td = td;
450
451         while (mfsp->mfs_active) {
452                 crit_enter();
453
454                 while ((bio = bioq_takefirst(&mfsp->bio_queue)) != NULL) {
455                         crit_exit();
456                         bp = bio->bio_buf;
457                         mfs_doio(bio, mfsp);
458                         wakeup(bp);
459                         crit_enter();
460                 }
461
462                 crit_exit();
463
464                 /*
465                  * If a non-ignored signal is received, try to unmount.
466                  * If that fails, clear the signal (it has been "processed"),
467                  * otherwise we will loop here, as tsleep will always return
468                  * EINTR/ERESTART.
469                  */
470                 /*
471                  * Note that dounmount() may fail if work was queued after
472                  * we slept. We have to jump hoops here to make sure that we
473                  * process any buffers after the sleep, before we dounmount()
474                  */
475                 if (gotsig) {
476                         gotsig = 0;
477                         if (dounmount(mp, 0, 0) != 0) {
478                                 KKASSERT(td->td_proc);
479                                 lwkt_gettoken(&td->td_proc->p_token);
480                                 sig = CURSIG(td->td_lwp);
481                                 if (sig) {
482                                         spin_lock(&td->td_lwp->lwp_spin);
483                                         lwp_delsig(td->td_lwp, sig, 1);
484                                         spin_unlock(&td->td_lwp->lwp_spin);
485                                 }
486                                 lwkt_reltoken(&td->td_proc->p_token);
487                         }
488                 }
489                 else if (tsleep((caddr_t)mfsp, PCATCH, "mfsidl", 0))
490                         gotsig++;       /* try to unmount in next pass */
491         }
492         PRELE(curproc);
493         if (mfsp->mfs_dev) {
494                 destroy_dev(mfsp->mfs_dev);
495                 mfsp->mfs_dev = NULL;
496         }
497         kfree(mfsp, M_MFSNODE);
498         return (EMOUNTEXIT);
499 }
500
501 /*
502  * Get file system statistics.
503  */
504 static int
505 mfs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
506 {
507         int error;
508
509         error = ffs_statfs(mp, sbp, cred);
510         sbp->f_type = mp->mnt_vfc->vfc_typenum;
511         return (error);
512 }
513
514 /*
515  * Memory based filesystem initialization.
516  */
517 static int
518 mfs_init(struct vfsconf *vfsp)
519 {
520         return (0);
521 }
522
523 /*
524  * Memory file system I/O.
525  *
526  * Trivial on the HP since buffer has already been mapping into KVA space.
527  *
528  * Read and Write are handled with a simple copyin and copyout.
529  *
530  * We also partially support VOP_FREEBLKS().  We can't implement
531  * completely -- for example, on fragments or inode metadata, but we can
532  * implement it for page-aligned requests.
533  */
534 static void
535 mfs_doio(struct bio *bio, struct mfsnode *mfsp)
536 {
537         struct buf *bp = bio->bio_buf;
538         caddr_t base = mfsp->mfs_baseoff + bio->bio_offset;
539         int bytes;
540
541         switch(bp->b_cmd) {
542         case BUF_CMD_FREEBLKS:
543                 /*
544                  * Implement FREEBLKS, which allows the filesystem to tell
545                  * a block device when blocks are no longer needed (like when
546                  * a file is deleted).  We use the hook to MADV_FREE the VM.
547                  * This makes an MFS filesystem work as well or better then
548                  * a sun-style swap-mounted filesystem.
549                  */
550                 bytes = bp->b_bcount;
551
552                 if ((vm_offset_t)base & PAGE_MASK) {
553                         int n = PAGE_SIZE - ((vm_offset_t)base & PAGE_MASK);
554                         bytes -= n;
555                         base += n;
556                 }
557                 if (bytes > 0) {
558                         struct madvise_args uap;
559
560                         bytes &= ~PAGE_MASK;
561                         if (bytes != 0) {
562                                 bzero(&uap, sizeof(uap));
563                                 uap.addr  = base;
564                                 uap.len   = bytes;
565                                 uap.behav = MADV_FREE;
566                                 sys_madvise(&uap);
567                         }
568                 }
569                 bp->b_error = 0;
570                 break;
571         case BUF_CMD_READ:
572                 /*
573                  * Read data from our 'memory' disk
574                  */
575                 bp->b_error = copyin(base, bp->b_data, bp->b_bcount);
576                 break;
577         case BUF_CMD_WRITE:
578                 /*
579                  * Write data to our 'memory' disk
580                  */
581                 bp->b_error = copyout(bp->b_data, base, bp->b_bcount);
582                 break;
583         default:
584                 panic("mfs: bad b_cmd %d", bp->b_cmd);
585         }
586         if (bp->b_error)
587                 bp->b_flags |= B_ERROR;
588         biodone(bio);
589 }