/[nova]/nova/kern/fs-ext2.c
ViewVC logotype

Diff of /nova/kern/fs-ext2.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1.1.1 by jrydberg, Tue Feb 12 19:28:41 2002 UTC revision 1.2 by jrydberg, Wed Mar 27 23:21:54 2002 UTC
# Line 1  Line 1 
1  /* ext2 file system.  /* Copyright 2002 Johan Rydberg, jrydberg@rtmk.org.
    Copyright 2002 Johan Rydberg, jrydberg@rtmk.org.  
2    
3  This program is free software; you can redistribute it and/or modify  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by  it under the terms of the GNU General Public License as published by
# Line 15  You should have received a copy of the G Line 14  You should have received a copy of the G
14  along with this program; if not, write to the Free Software  along with this program; if not, write to the Free Software
15  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
16    
17    #include <sys/param.h>
18  #include <stdio.h>  #include <stdio.h>
19    #include <errno.h>
20    #include <stdlib.h>
21    #include <string.h>
22    #include <dirent.h>
23    
24  #include "nova-intern.h"  #include "io-vfs.h"
25  #include "module.h"  #include "io-vnode.h"
 #include "vfs.h"  
26  #include "io-buf.h"  #include "io-buf.h"
27    #include "module.h"
28    
29  #include "fs-ext2.h"  #include "fs-ext2.h"
30  #include "fs-spec.h"  #include "fs-spec.h"
31    
32    #include "nova-intern.h"
33    
34  #ifndef DEV_BSIZE  #ifndef DEV_BSIZE
35  # define DEV_BSIZE 512  # define DEV_BSIZE 512
36  #endif  #endif
37    
38  #define EXT2_DINODE_SIZE (sizeof (struct ext2fs_dinode))  /* Hash buckets for fast <VFS, INO> lookup.  */
39  /* The minimum length for a directory entry.    struct queue_entry ext2fs_hash_buckets [256];
40     XXX Does ext2fs need this?  */  pthread_mutex_t ext2fs_hash_lock = PTHREAD_MUTEX_INITIALIZER;
41  #define EXT2FS_MINENT   12  
42    /* Hash function for calculating hash bucket index.  */
43  static int ext2fs_mountroot (struct vfs *vfs, dev_t rootdev);  #define EXT2FS_HASH(VFS, INO) ((unsigned int) (((int) (VFS) >> 3) + (INO)) % 256)
44  static int ext2fs_root (struct vfs *vfs, struct vnode **vpp);  
45  static int ext2fs_lookup (struct vnode *vp, char *cname, struct vnode **vpp);  /* Forward declarations.  */
46  static int ext2fs_open (struct vnode *vp, int mode, struct ucred *ucred, struct proc *p);  static void add_cache (struct vnode *vp);
47  static int ext2fs_access (struct vnode *vp, int mode, struct ucred *ucred, struct proc *p);  static void remove_cache (struct vnode *vp);
48  static int ext2fs_read (struct vnode *vp, struct io_uio *uio, struct ucred *ucred);  static struct vnode *lookup_cache (struct vfs *vfs, ino_t ino);
49    extern struct vnode_ops ext2fs_vnops;
 static struct vfs_ops ext2fs_vfsops =  
 {  
   0,                    /* mount */  
   0,                    /* umount */  
   ext2fs_mountroot,     /* mountroot */  
   ext2fs_root           /* root */  
 };  
   
 static struct vnode_ops ext2fs_vnops =  
 {  
   ext2fs_open,  
   ext2fs_access,  
   ext2fs_lookup,  
   0,                    /* strategy */  
   ext2fs_read  
 };  
   
50    
51  /* Map indirect blocks from logical block numbers to filesystem blocks.  */  /* Map indirect blocks from logical block numbers to filesystem blocks.  */
52  u_int32_t  u_int32_t
53  ext2fs_bmap (struct ext2fs_softc *sc, int level, u_int32_t mblk,  search_bmap (struct ext2fs_softc *sc, int level, u_int32_t mblk,
54               u_int32_t lblk, u_int32_t addr_per_block)               u_int32_t lblk, u_int32_t addr_per_block, int *runp)
55  {  {
56    struct io_buf *bp;    struct io_buf *bp;
57    u_int32_t b = 0;    u_int32_t b = 0;
# Line 78  ext2fs_bmap (struct ext2fs_softc *sc, in Line 67  ext2fs_bmap (struct ext2fs_softc *sc, in
67      }      }
68    
69    /* Read the map block into memory.  */    /* Read the map block into memory.  */
70    err = io_bread (sc->sc_vp, fsbtodb (sc, mblk), sc->sc_bsize, &bp);    err = io_buf_read (sc->sc_vp, fsbtodb (sc, mblk), sc->sc_bsize, 0, &bp);
71    if (err)    if (err)
72      return err;      return err;
73    
74    /* Look up block in table.  If LEVEL isn't zero, indirect further.  */    /* Look up block in table.  If LEVEL isn't zero, indirect further.  */
75    b = ((u_int32_t *) bp->b_data) [lblk / addr_per_block];    b = ((u_int32_t *) bp->data) [lblk / addr_per_block];
76    io_brelease (bp);    
77      if (runp && !level)
78        {
79          u_int32_t *p = ((u_int32_t *) bp->data);
80          int blkno = lblk / addr_per_block, i;
81    
82          *runp = 0;
83    
84          for (i = blkno; i < (int) ((sc->sc_bsize/sizeof b) - 1); i++)
85            {
86              if (p [i + 1] == p [i] + 1)
87                { (*runp)++; continue; }
88              break;
89            }
90        }
91    
92      io_buf_release (bp);
93    if (level != 0)    if (level != 0)
94      return ext2fs_bmap (sc, level - 1, b, lblk % (sc->sc_bsize / sizeof b),      return search_bmap (sc, level - 1, b, lblk % (sc->sc_bsize / sizeof b),
95                          addr_per_block / (sc->sc_bsize / sizeof b));                          addr_per_block / (sc->sc_bsize / sizeof b), runp);
96    return b;    return b;
97  }  }
98    
99  /* Map a logical block number to a filesystem block number.  */  /* Map a logical block number to a filesystem block number.  */
100  static u_int32_t  static u_int32_t
101  getblk (struct ext2fs_softc *sc, struct ext2fs_dinode *ip, u_int32_t lblk)  getblk (struct ext2fs_softc *sc, struct ext2fs_dinode *ip, u_int32_t lblk,
102            int *runp)
103  {  {
104    u_int32_t addr_per_block = sc->sc_bsize / sizeof (u_int32_t);    u_int32_t addr_per_block = sc->sc_bsize / sizeof (u_int32_t);
105    int indirect;    int indirect;
106    
107    if (lblk < NDIRECT)    if (lblk < NDIRECT)
108      return ip->blocks [lblk];      {
109          if (runp)
110            {
111              *runp = 0;
112              for (indirect = lblk; indirect < NDIRECT - 1; indirect++)
113                {
114                  if (ip->blocks [indirect] + 1 == ip->blocks [indirect + 1])
115                    { (*runp)++; continue; }
116                  break;
117                }
118            }
119          return ip->blocks [lblk];
120        }
121    lblk = lblk - NDIRECT;    lblk = lblk - NDIRECT;
122        
123    for (indirect = 0; lblk >= addr_per_block; )    for (indirect = 0; lblk >= addr_per_block; )
# Line 108  getblk (struct ext2fs_softc *sc, struct Line 126  getblk (struct ext2fs_softc *sc, struct
126        addr_per_block = addr_per_block * addr_per_block;        addr_per_block = addr_per_block * addr_per_block;
127        indirect++;        indirect++;
128      }      }
129    return ext2fs_bmap (sc, indirect, ip->blocks [NDIRECT + indirect],    return
130                        lblk, addr_per_block / (sc->sc_bsize / sizeof (u_int32_t)));      search_bmap (sc, indirect, ip->blocks [NDIRECT + indirect],
131                     lblk, addr_per_block / (sc->sc_bsize / sizeof (u_int32_t)),
132                     runp);
133  }  }
134    
135  /* Initialize the vnode associated with a new inode.  */  /* Initialize the vnode associated with a new inode.  */
   
136  int  int
137  ext2fs_vinit (struct vfs *vfs, struct vnode **vpp)  ext2fs_vinit (struct vfs *vfs, struct vnode **vpp)
138  {  {
139    struct ext2fs_inode *ip;    struct inode *ip;
140    struct vnode *vp;    struct vnode *vp;
141    
142    vp = *vpp;    vp = *vpp;
143    ip = (struct ext2fs_inode *) vp->v_data;    ip = VTOI (vp);
144    
145    vp->v_type = IFTOVT (ip->dinode.mode);    vp->v_type = IFTOVT (ip->i_dinode.mode);
146    if (vp->v_type == VBLK || vp->v_type == VCHR)    if (vp->v_type == VBLK || vp->v_type == VCHR)
147      {      {
148        vp->v_ops  = &specfs_vnops;        vp->v_ops  = &specfs_vnops;
149        vp->v_rdev = (dev_t) ip->dinode.blocks [0];        vp->v_rdev = (dev_t) ip->i_dinode.blocks [0];
150      }      }
151    
152    return 0;    return 0;
# Line 137  ext2fs_vinit (struct vfs *vfs, struct vn Line 156  ext2fs_vinit (struct vfs *vfs, struct vn
156     in from disk.  If it is in core, wait for the lock bit to clear, then     in from disk.  If it is in core, wait for the lock bit to clear, then
157     return the inode locked.  Detection and handling of mount points must be     return the inode locked.  Detection and handling of mount points must be
158     done by the calling routine.   */     done by the calling routine.   */
   
159  int  int
160  ext2fs_vget (struct vfs *vfs, ino_t ino, struct vnode **vpp)  ext2fs_vget (struct vfs *vfs, ino_t ino, struct vnode **vpp)
161  {  {
162    struct ext2fs_softc *sc = (struct ext2fs_softc *) vfs->vfs_data;    struct ext2fs_softc *sc = (struct ext2fs_softc *) vfs->vfs_data;
163    struct ext2fs_inode *ip;    struct inode *ip;
164    struct io_buf *bp;    struct io_buf *bp;
165    struct vnode *vp;    struct vnode *vp;
166    int err;    int err;
167    
168    /* ??? lookup in inode cache.  */    *vpp = lookup_cache (vfs, ino);
169      if (*vpp)
170        {
171          trace_printf ("ino %d is cache", ino);
172          return 0;
173        }
174    
175    err = vgetnode (vfs, /* &ext2fs_ops */ &ext2fs_vnops, &vp);    err = getnewvnode (vfs, &ext2fs_vnops, &vp);
176    if (err)    if (err)
177      return err;      return err;
178    
179    ip = malloc (sizeof (struct ext2fs_inode));    ip = malloc (sizeof (struct inode));
180    if (! ip)    if (! ip)
181      return ENOMEM;      return ENOMEM;
182    vp->v_data = ip;    vp->v_data = ip;
183    ip->sc     = (struct ext2fs_softc *) vfs->vfs_data;    ip->i_sc = (struct ext2fs_softc *) vfs->vfs_data;
184      ip->i_number = ino;
185    
186    if (ino == ROOTINO)    if (ino == ROOTINO)
187      vp->v_flag |= VROOT;      vp->v_flags |= VROOT;
188    
189    /* Read in the disk contents for the inode, copy into the inode. */    /* Read in the disk contents for the inode, copy into the inode. */
190    err = io_bread (sc->sc_vp, fsbtodb (sc, ino_to_fsba (sc, ino)),    err = io_buf_read (sc->sc_vp, fsbtodb (sc, ino_to_fsba (sc, ino)),
191                    (int) sc->sc_bsize, &bp);                       (int) sc->sc_bsize, 0, &bp);
192    if (err)    if (err)
193      { free (ip); return err; }      { free (ip); return err; }
194    
195    memcpy (&ip->dinode, bp->b_data + (ino_to_fsbo (sc, ino) * EXT2_DINODE_SIZE),    memcpy (&ip->i_dinode, bp->data + (ino_to_fsbo (sc, ino) * EXT2_DINODE_SIZE),
196            sizeof (struct ext2fs_dinode));            sizeof (struct ext2fs_dinode));
197    io_brelease (bp);    io_buf_release (bp);
198    
199    /* If the inode was deleted, reset all fields */    /* If the inode was deleted, reset all fields */
200    if (ip->dinode.dtime != 0)    if (ip->i_dinode.dtime != 0)
201      {      {
202        ip->dinode.mode = ip->dinode.size = ip->dinode.nblocks = 0;        ip->i_dinode.mode = ip->i_dinode.size = ip->i_dinode.nblocks = 0;
203        memset (& ip->dinode.blocks, 0, sizeof ip->dinode.blocks);        memset (& ip->i_dinode.blocks, 0, sizeof ip->i_dinode.blocks);
204      }      }
205    
206    /* Initialize the vnode from the inode, check for aliases.    /* Initialize the vnode from the inode, check for aliases.
# Line 184  ext2fs_vget (struct vfs *vfs, ino_t ino, Line 208  ext2fs_vget (struct vfs *vfs, ino_t ino,
208    err = ext2fs_vinit (vfs, &vp);    err = ext2fs_vinit (vfs, &vp);
209    if (err)    if (err)
210      return err;      return err;
211      add_cache (vp);
212    
213    *vpp = vp;    *vpp = vp;
214    return 0;    return 0;
215  }  }
216    
217  static int  /* Return root vnode of file system VFS.  */
218    int
219  ext2fs_root (struct vfs *vfs, struct vnode **vpp)  ext2fs_root (struct vfs *vfs, struct vnode **vpp)
220  {  {
221    return ext2fs_vget (vfs, ROOTINO, vpp);    return ext2fs_vget (vfs, ROOTINO, vpp);
222  }  }
223    
224  static int  
225    /* Check if we can mount a root file system on device
226       ROOTDEV.  VFS is our mountpoint structure.  */
227    int
228  ext2fs_mountroot (struct vfs *vfs, dev_t rootdev)  ext2fs_mountroot (struct vfs *vfs, dev_t rootdev)
229  {  {
230    struct ext2fs_softc *sc;    struct ext2fs_softc *sc;
# Line 203  ext2fs_mountroot (struct vfs *vfs, dev_t Line 232  ext2fs_mountroot (struct vfs *vfs, dev_t
232    struct vnode *vp;    struct vnode *vp;
233    int err, i;    int err, i;
234    
235  #define LOSE { if (bp) io_brelease (bp); goto lose; }  #define LOSE { if (bp) io_buf_release (bp); goto lose; }
236    
237    err = vdevvp (vfs, rootdev, VBLK, &vp);    err = vdevvp (vfs, rootdev, VBLK, &vp);
238    if (err)    if (err)
# Line 215  ext2fs_mountroot (struct vfs *vfs, dev_t Line 244  ext2fs_mountroot (struct vfs *vfs, dev_t
244      { err = ENOMEM; LOSE; }      { err = ENOMEM; LOSE; }
245    memset (sc, 0, sizeof (struct ext2fs_softc));    memset (sc, 0, sizeof (struct ext2fs_softc));
246    
247    err = io_bread (vp, (SBOFF / DEV_BSIZE), SBSIZE, &bp);    trace_printf ("before read");
248    
249      err = io_buf_read (vp, (SBOFF / DEV_BSIZE), SBSIZE, 0, &bp);
250    if (err)    if (err)
251      LOSE;      LOSE;
252    memcpy (&sc->sc_sb, bp->b_data, sizeof (struct ext2fs));    memcpy (&sc->sc_sb, bp->data, sizeof (struct ext2fs));
253    io_brelease (bp); bp = 0;    io_buf_release (bp); bp = 0;
254    
255      trace_printf ("after read");
256    
257    if (sc->sc_sb.e2fs_magic != E2FS_MAGIC)    if (sc->sc_sb.e2fs_magic != E2FS_MAGIC)
258      { err = ESTALE; LOSE; }      { err = ESTALE; LOSE; }
259    
   /* ??? */  
   
260    sc->sc_ncg = howmany (sc->sc_sb.e2fs_bcount - sc->sc_sb.e2fs_first_dblock,    sc->sc_ncg = howmany (sc->sc_sb.e2fs_bcount - sc->sc_sb.e2fs_first_dblock,
261                          sc->sc_sb.e2fs_bpg);                          sc->sc_sb.e2fs_bpg);
262    
# Line 244  ext2fs_mountroot (struct vfs *vfs, dev_t Line 275  ext2fs_mountroot (struct vfs *vfs, dev_t
275    if (! sc->sc_gd)    if (! sc->sc_gd)
276      { err = ENOMEM; LOSE; }      { err = ENOMEM; LOSE; }
277    
278    for (i = 0; i < sc->sc_ngdb; i++)    for (i = 0; i < sc->sc_ngdb; bp = 0, i++)
279      {      {
280        err = io_bread (vp, fsbtodb (sc, (sc->sc_bsize > 1024 ? 0 : 1) + i + 1),        err = io_buf_read (vp, fsbtodb (sc, (sc->sc_bsize > 1024 ? 0 : 1) + i + 1),
281                        sc->sc_bsize, &bp);                           sc->sc_bsize, 0, &bp);
282        if (err)        if (err)
283          LOSE;          LOSE;
284    
285        memcpy (& sc->sc_gd [i * sc->sc_bsize / sizeof (struct ext2_gd)],        memcpy (& sc->sc_gd [i * sc->sc_bsize / sizeof (struct ext2_gd)],
286                bp->b_data, sc->sc_bsize);                bp->data, sc->sc_bsize);
287        io_brelease (bp);        io_buf_release (bp);
288      }      }
289    
290    vfs->vfs_data = sc;    vfs->vfs_data = sc;
291      vfs->vfs_bsize = sc->sc_bsize;
292      vfs->vfs_devvp = sc->sc_vp;
293    return 0;    return 0;
294    
295   lose:   lose:
296      if (bp)
297        io_buf_release (bp);
298    return err;    return err;
299  }  }
300    
301  static int  /* Open vnode VP, with file modes MODE.  */
302  ext2fs_open (struct vnode *vp, int mode, struct ucred *ucred, struct proc *p)  int
303    ext2fs_open (struct vnode *vp, int mode, struct ucred *ucred)
304  {  {
305    return 0;    return 0;
306  }  }
307    
308  static int  /* Check if user with credentials UCRED may access vnode VP
309  ext2fs_access (struct vnode *vp, int mode, struct ucred *ucred, struct proc *p)     with mode MODE.  ??? need P?  */
310    int
311    ext2fs_access (struct vnode *vp, int mode, struct ucred *ucred)
312  {  {
313    return 0;    return 0;
314  }  }
315    
316    /* Get attributes for VP.  Put them in VA. */
317    int
318    ext2fs_getattr (struct vnode *vp, struct vattr *va)
319    {
320      struct inode *ip = VTOI (vp);
321    
322      va->va_type = vp->v_type;
323      va->va_mode = ip->i_dinode.mode;
324      va->va_uid  = ip->i_dinode.uid;
325      va->va_gid  = ip->i_dinode.gid;
326      va->va_size = ip->i_dinode.size;
327      va->va_atime.tv_sec = ip->i_dinode.atime;
328      va->va_mtime.tv_sec = ip->i_dinode.mtime;
329      va->va_ctime.tv_sec = ip->i_dinode.ctime;
330      return 0;
331    }
332    
333  /* Look up component CNAME in directory VP.  If found, return vnode  /* Look up component CNAME in directory VP.  If found, return vnode
334     in VPP.  */     in VPP.  */
335  static int  int
336  ext2fs_lookup (struct vnode *vp, char *cname, struct vnode **vpp)  ext2fs_lookup (struct vnode *vp, char *cname, struct vnode **vpp)
337  {  {
338    struct ext2fs_inode *ip;    struct inode *ip;
339    struct ext2fs_softc *sc;    struct ext2fs_softc *sc;
340    u_int32_t blk_no, off;    u_int32_t blk_no, off;
341    struct io_buf *bp;    struct io_buf *bp = 0;
342    size_t res, left;    size_t res, left;
343    ino_t ino = 0;    ino_t ino = 0;
344    int err, x = 0;    int err, x = 0;
# Line 292  ext2fs_lookup (struct vnode *vp, char *c Line 346  ext2fs_lookup (struct vnode *vp, char *c
346    if (vp->v_type != VDIR)    if (vp->v_type != VDIR)
347      return ENOTDIR;      return ENOTDIR;
348    
349    ip = (struct ext2fs_inode *) vp->v_data;    ip = VTOI (vp);
350    sc = ip->sc;    sc = ip->i_sc;
351    
352    off = 0;    off = 0;
353    res = ip->dinode.size;    res = ip->i_dinode.size;
354    
355    while (res)    while (res)
356      {      {
357        struct ext2fs_dirent *d;        struct ext2fs_dirent *d;
358    
359        res -= sc->sc_bsize;        res -= sc->sc_bsize;
360        blk_no = getblk (ip->sc, &ip->dinode, lblkno (ip->sc, off));        blk_no = getblk (ip->i_sc, &ip->i_dinode, lblkno (ip->i_sc, off), 0);
361        if (! blk_no)        if (! blk_no)
362          continue;          continue;
363        off += sc->sc_bsize;        off += sc->sc_bsize;
364    
365        err = io_bread (sc->sc_vp, fsbtodb (sc, blk_no), sc->sc_bsize, &bp);        err = io_buf_read (sc->sc_vp, fsbtodb (sc, blk_no), sc->sc_bsize, 0, &bp);
366        if (err)        if (err)
367          return err;          return err;
368        d = (struct ext2fs_dirent *) bp->b_data;  
369          d = (struct ext2fs_dirent *) bp->data;
370        left = sc->sc_bsize;        left = sc->sc_bsize;
371                
372        while (left >= EXT2FS_MINENT)        while (left >= EXT2FS_MINENT)
# Line 335  ext2fs_lookup (struct vnode *vp, char *c Line 390  ext2fs_lookup (struct vnode *vp, char *c
390            d = (struct ext2fs_dirent *) ((void *)d + d->reclen);            d = (struct ext2fs_dirent *) ((void *)d + d->reclen);
391        }        }
392    
393        io_brelease (bp);        io_buf_release (bp);
394      }      }
395    return ENOENT;    return ENOENT;
396    
397   found:   found:
398      if (bp)
399        io_buf_release (bp);
400    return ext2fs_vget (sc->sc_vfs, ino, vpp);    return ext2fs_vget (sc->sc_vfs, ino, vpp);
401  }  }
402    
403  static int  /* Read data from vnode VP.  Put the data in UIO.  Offset into file (vnode)
404       is UIO->uio_offset.  User credentials is located in UCRED.  */
405    int
406  ext2fs_read (struct vnode *vp, struct io_uio *uio, struct ucred *ucred)  ext2fs_read (struct vnode *vp, struct io_uio *uio, struct ucred *ucred)
407  {  {
408    off_t bytesinfile, blkoffset;    off_t bytesinfile, blkoffset;
409    struct ext2fs_inode *ip;    struct inode *ip = VTOI (vp);
410    struct ext2fs_softc *sc;    struct ext2fs_softc *sc;
411    struct io_buf *bp;    struct io_buf *bp;
412    size_t xfersize;    ssize_t xfersize;
   int err;  
413    u_int32_t blk_no;    u_int32_t blk_no;
414      int err;
415    
416    ip = (struct ext2fs_inode *) vp->v_data;    sc = ip->i_sc;
   sc = ip->sc;  
417    
418    if ((u_int64_t) uio->uio_offset > ((u_int64_t) 0x80000000 * sc->sc_bsize - 1))    if ((u_int64_t) uio->uio_offset > ((u_int64_t) 0x80000000 * sc->sc_bsize - 1))
419      return EFBIG;      return EFBIG;
# Line 365  ext2fs_read (struct vnode *vp, struct io Line 423  ext2fs_read (struct vnode *vp, struct io
423    
424    for (err = 0; uio->uio_resid > 0; bp = NULL)    for (err = 0; uio->uio_resid > 0; bp = NULL)
425      {      {
426        if ((bytesinfile = ip->dinode.size - uio->uio_offset) <= 0)        if ((bytesinfile = ip->i_dinode.size - uio->uio_offset) <= 0)
427          break;          break;
428                
429        blk_no = getblk (sc, &ip->dinode, lblkno (sc, uio->uio_offset));        blk_no = getblk (sc, &ip->i_dinode, lblkno (sc, uio->uio_offset), 0);
430        if (! blk_no)        if (! blk_no)
431          {          {
           printf ("hole in file for offset %d\n", uio->uio_offset);  
           fflush (stdout);  
   
432            uio->uio_offset += sc->sc_bsize;            uio->uio_offset += sc->sc_bsize;
433            uio->uio_resid  -= sc->sc_bsize;            uio->uio_resid  -= sc->sc_bsize;
434                        
# Line 381  ext2fs_read (struct vnode *vp, struct io Line 436  ext2fs_read (struct vnode *vp, struct io
436            continue;            continue;
437          }          }
438                
439        err = io_bread (sc->sc_vp, fsbtodb (sc, blk_no), sc->sc_bsize, &bp);        err = io_buf_read (vp, fsbtodb (sc, blk_no), sc->sc_bsize, ucred, &bp);
440        if (err)        if (err)
441          break;          break;
442                
443        blkoffset = blkoff (sc, uio->uio_offset);        blkoffset = blkoff (sc, uio->uio_offset);
444        xfersize = sc->sc_bsize - blkoffset;        xfersize = sc->sc_bsize - blkoffset;
445                
446        if (uio->uio_resid < xfersize)        if (uio->uio_resid < (size_t) xfersize)
447          xfersize = uio->uio_resid;          xfersize = uio->uio_resid;
448        if (bytesinfile < xfersize)        if (bytesinfile < xfersize)
449          xfersize = bytesinfile;          xfersize = bytesinfile;
450                
451        err = io_uio_move (uio, bp->b_data + blkoffset, xfersize);        err = io_uio_move (uio, bp->data + blkoffset, xfersize);
452        if (err)        if (err)
453          break;          break;
454        io_brelease (bp);        io_buf_release (bp);
455      }      }
456    
457    if (bp)    if (bp)
458      io_brelease (bp);      io_buf_release (bp);
459    return err;    return err;
460  }  }
461    
462    /* Return target name of a symbolic link, vnode VP.  */
463    int
464    ext2fs_readlink (struct vnode *vp, struct io_uio *uio,
465                     struct ucred *ucred)
466    {
467      struct inode *ip = VTOI (vp);
468      int isize;
469    
470      isize = ip->i_dinode.size;
471      if (ip->i_dinode.nblocks == 0)
472        {
473          io_uio_move (uio, &ip->i_dinode.blocks[0], isize);
474          return 0;
475        }
476      return (VOP_READ (vp, uio, ucred));
477    }
478    
479    
480    /* Return block number of offset OFFSET into vnode VP.  
481       Block number is returned in *BLKNO.  Number of sequental
482       blocks is returned in *RUNP.  Return error code.  */
483    int
484    ext2fs_bmap (struct vnode *vp, off_t offset, off_t *blkno, int *runp)
485    {
486      struct inode *ip = VTOI (vp);
487      struct ext2fs_softc *sc = ip->i_sc;
488    
489      *blkno = fsbtodb (sc, getblk (sc, &ip->i_dinode, lblkno (sc, offset), runp));
490      return 0;
491    }
492    
493    /* Vnode VP became inactive.  We do nothing right now. */
494    int
495    ext2fs_inactive (struct vnode *vp)
496    {
497      return 0;
498    }
499    
500    /* The system is reclaiming vnode VP.  We free all resources
501       (ie the inode) that this vnode holds.  */
502    int
503    ext2fs_reclaim (struct vnode *vp)
504    {
505      struct inode *ip = VTOI (vp);
506    
507      remove_cache (vp);
508      free (ip);
509      vp->v_data = 0;
510      return 0;
511    }
512    
513    /* Convert the on-disk entries to <sys/dirent.h> entries.
514       We put the dir entries in UIO.  */
515    int
516    ext2fs_readdir (struct vnode *vp, struct io_uio *uio, struct ucred *ucred)
517    {
518      size_t count, readcnt;
519      struct io_iovec iov;
520      struct io_uio auio;
521      void *dirbuf;
522      int error;
523    
524      if (vp->v_type != VDIR)
525        return ENOTDIR;
526    
527      count = uio->uio_resid;
528      /* count -= (uio->uio_offset + count) & (sc->sc_bsize - 1); */
529      if (count <= 0)
530        return EINVAL;
531    
532      dirbuf = malloc (count);
533      if (! dirbuf)
534        return ENOMEM;
535      memset (dirbuf, 0, count);
536      io_iov_init (&iov, dirbuf, count);
537      io_uio_init (&auio, IO_UIO_WRITE, IO_UIO_SYSSPACE, uio->uio_offset,
538                   count, &iov, 1, 0);
539    
540      error = VOP_READ (vp, &auio, ucred);
541      if (error == 0)
542        {
543          struct ext2fs_dirent *dp;
544          struct dirent de;
545    
546          readcnt = count - auio.uio_resid;
547    
548          trace_printf ("count is %d", readcnt);
549    
550          for (dp = (struct ext2fs_dirent *) dirbuf;
551               (char *)dp < (char *)dirbuf + readcnt;)
552            {
553              trace_printf ("dp ino %d type %d", dp->ino, dp->file_type);
554    
555              if (dp->reclen == 0 || dp->ino == 0)
556                {
557                  error = EIO;
558                  break;
559                }
560    
561              de.d_fileno = dp->ino;
562              de.d_namlen = dp->namlen;
563              de.d_reclen = ((sizeof de - 256 + dp->namlen + 1) + 3) & ~3;
564              de.d_type   = dp->file_type;
565              strncpy (de.d_name, dp->name, dp->namlen);
566              de.d_name [dp->namlen] = 0;
567    
568              /* printf ("read reclen %d: '%s'\n", dp->reclen, dp->name); */
569    
570              if (de.d_reclen > uio->uio_resid)
571                break;
572    
573              error = io_uio_move (uio, (void *) &de, de.d_reclen);
574              if (error)
575                break;
576              
577              /* advance dp */
578              dp = (struct ext2fs_dirent *) ((char *)dp + dp->reclen);
579            }
580        }
581    
582      free (dirbuf);
583      return error;
584    }
585    
586    /* ??? */
587    int
588    ext2fs_strategy (struct io_buf *bp)
589    {
590      struct inode *ip = VTOI (bp->vp);
591      struct ext2fs_softc *sc = ip->i_sc;
592    
593      bp->dev = sc->sc_vp->v_rdev;
594      return specfs_strategy (bp);
595    }
596    
597    
598    struct vfs_ops ext2fs_vfsops =
599    {
600      0,                    /* mount */
601      0,                    /* umount */
602      ext2fs_mountroot,     /* mountroot */
603      ext2fs_root           /* root */
604    };
605    
606    struct vnode_ops ext2fs_vnops =
607    {
608      ext2fs_open,
609      ext2fs_access,
610      ext2fs_lookup,
611      ext2fs_strategy,
612      ext2fs_read,
613      0,                    /* write */
614      ext2fs_getattr,
615      0,                    /* setattr */
616      ext2fs_bmap,
617      ext2fs_reclaim,
618      ext2fs_inactive,
619      ext2fs_readlink,
620      ext2fs_readdir
621    };
622    
623    
624    /* Add vnode VP to the hash lookup table.  We get
625       inode number from the inode structure.  */
626    static void
627    add_cache (struct vnode *vp)
628    {
629      struct inode *ip = VTOI (vp);
630      int hash_index = EXT2FS_HASH (vp->v_vfsp, ip->i_number);
631    
632      pthread_mutex_lock (&vp->v_lock);
633      pthread_mutex_lock (&ext2fs_hash_lock);
634      queue_enter (&ext2fs_hash_buckets [hash_index], vp, struct vnode *, v_hashq);
635      pthread_mutex_unlock (&vp->v_lock);
636      pthread_mutex_unlock (&ext2fs_hash_lock);
637    }
638    
639    /* Remove VP from hash lookup table. We get inode
640       number from the inode structure.  */
641    static void
642    remove_cache (struct vnode *vp)
643    {
644      struct inode *ip = VTOI (vp);
645      int hash_index = EXT2FS_HASH (vp->v_vfsp, ip->i_number);
646    
647      pthread_mutex_lock (&vp->v_lock);
648      pthread_mutex_lock (&ext2fs_hash_lock);
649      queue_remove (&ext2fs_hash_buckets [hash_index], vp, struct vnode *, v_hashq);
650      pthread_mutex_unlock (&ext2fs_hash_lock);
651      pthread_mutex_unlock (&vp->v_lock);
652    }
653    
654    /* Look in hash table for a vnode that belongs to
655       file system VFS and has the inode number INO.  If
656       we find it, we obtain a reference to it and return.
657       If we did not find any vnode, we return NULL.  */
658    static struct vnode *
659    lookup_cache (struct vfs *vfs, ino_t ino)
660    {
661      int hash_index = EXT2FS_HASH (vfs, ino);
662      struct vnode *vp;
663    
664      pthread_mutex_lock (&ext2fs_hash_lock);
665      queue_iterate (&ext2fs_hash_buckets [hash_index], vp,
666                     struct vnode *, v_hashq)
667        {
668          struct inode *ip = VTOI (vp);
669          
670          if (vp->v_vfsp == vfs && ip->i_number == ino)
671            {
672              vhold (vp);
673              pthread_mutex_unlock (&ext2fs_hash_lock);
674              return vp;
675            }
676        }
677      pthread_mutex_unlock (&ext2fs_hash_lock);
678      return NULL;
679    }
680    
681  static int  static int
682  ext2fs_init (struct md_descriptor *mdd)  ext2fs_init (struct md_descriptor *mdd)
683  {  {
684      int i;
685    
686      for (i = 0; i < 256; i++)
687        queue_init (&ext2fs_hash_buckets[i]);
688    
689    md_attach (mdd, (void *) &ext2fs_vfsops);    md_attach (mdd, (void *) &ext2fs_vfsops);
690    return 0;    return 0;
691  }  }

Legend:
Removed from v.1.1.1.1  
changed lines
  Added in v.1.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26