summaryrefslogtreecommitdiffstats
path: root/sys/ufs/lfs
diff options
context:
space:
mode:
Diffstat (limited to 'sys/ufs/lfs')
-rw-r--r--sys/ufs/lfs/lfs.h284
-rw-r--r--sys/ufs/lfs/lfs_alloc.c14
-rw-r--r--sys/ufs/lfs/lfs_balloc.c149
-rw-r--r--sys/ufs/lfs/lfs_bio.c31
-rw-r--r--sys/ufs/lfs/lfs_cksum.c4
-rw-r--r--sys/ufs/lfs/lfs_extern.h14
-rw-r--r--sys/ufs/lfs/lfs_inode.c107
-rw-r--r--sys/ufs/lfs/lfs_segment.c177
-rw-r--r--sys/ufs/lfs/lfs_subr.c9
-rw-r--r--sys/ufs/lfs/lfs_syscalls.c59
-rw-r--r--sys/ufs/lfs/lfs_vfsops.c130
-rw-r--r--sys/ufs/lfs/lfs_vnops.c63
12 files changed, 671 insertions, 370 deletions
diff --git a/sys/ufs/lfs/lfs.h b/sys/ufs/lfs/lfs.h
index 87b8c22..855b331 100644
--- a/sys/ufs/lfs/lfs.h
+++ b/sys/ufs/lfs/lfs.h
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)lfs.h 8.3 (Berkeley) 9/23/93
+ * @(#)lfs.h 8.9 (Berkeley) 5/8/95
*/
#define LFS_LABELPAD 8192 /* LFS label size */
@@ -55,14 +55,15 @@
/* On-disk and in-memory checkpoint segment usage structure. */
typedef struct segusage SEGUSE;
struct segusage {
- u_long su_nbytes; /* number of live bytes */
- u_long su_lastmod; /* SEGUSE last modified timestamp */
- u_short su_nsums; /* number of summaries in segment */
- u_short su_ninos; /* number of inode blocks in seg */
-#define SEGUSE_ACTIVE 0x1 /* segment is currently being written */
-#define SEGUSE_DIRTY 0x2 /* segment has data in it */
-#define SEGUSE_SUPERBLOCK 0x4 /* segment contains a superblock */
- u_long su_flags;
+ u_int32_t su_nbytes; /* number of live bytes */
+ u_int32_t su_lastmod; /* SEGUSE last modified timestamp */
+ u_int16_t su_nsums; /* number of summaries in segment */
+ u_int16_t su_ninos; /* number of inode blocks in seg */
+
+#define SEGUSE_ACTIVE 0x01 /* segment is currently being written */
+#define SEGUSE_DIRTY 0x02 /* segment has data in it */
+#define SEGUSE_SUPERBLOCK 0x04 /* segment contains a superblock */
+ u_int32_t su_flags;
};
#define SEGUPB(fs) (1 << (fs)->lfs_sushift)
@@ -72,98 +73,102 @@ struct segusage {
/* On-disk file information. One per file with data blocks in the segment. */
typedef struct finfo FINFO;
struct finfo {
- u_long fi_nblocks; /* number of blocks */
- u_long fi_version; /* version number */
- u_long fi_ino; /* inode number */
- long fi_blocks[1]; /* array of logical block numbers */
+ u_int32_t fi_nblocks; /* number of blocks */
+ u_int32_t fi_version; /* version number */
+ u_int32_t fi_ino; /* inode number */
+ u_int32_t fi_lastlength; /* length of last block in array */
+ ufs_daddr_t fi_blocks[1]; /* array of logical block numbers */
};
/* On-disk and in-memory super block. */
struct lfs {
#define LFS_MAGIC 0x070162
- u_long lfs_magic; /* magic number */
+ u_int32_t lfs_magic; /* magic number */
#define LFS_VERSION 1
- u_long lfs_version; /* version number */
+ u_int32_t lfs_version; /* version number */
- u_long lfs_size; /* number of blocks in fs */
- u_long lfs_ssize; /* number of blocks per segment */
- u_long lfs_dsize; /* number of disk blocks in fs */
- u_long lfs_bsize; /* file system block size */
- u_long lfs_fsize; /* size of frag blocks in fs */
- u_long lfs_frag; /* number of frags in a block in fs */
+ u_int32_t lfs_size; /* number of blocks in fs */
+ u_int32_t lfs_ssize; /* number of blocks per segment */
+ u_int32_t lfs_dsize; /* number of disk blocks in fs */
+ u_int32_t lfs_bsize; /* file system block size */
+ u_int32_t lfs_fsize; /* size of frag blocks in fs */
+ u_int32_t lfs_frag; /* number of frags in a block in fs */
/* Checkpoint region. */
- ino_t lfs_free; /* start of the free list */
- u_long lfs_bfree; /* number of free disk blocks */
- u_long lfs_nfiles; /* number of allocated inodes */
- long lfs_avail; /* blocks available for writing */
- u_long lfs_uinodes; /* inodes in cache not yet on disk */
- daddr_t lfs_idaddr; /* inode file disk address */
- ino_t lfs_ifile; /* inode file inode number */
- daddr_t lfs_lastseg; /* address of last segment written */
- daddr_t lfs_nextseg; /* address of next segment to write */
- daddr_t lfs_curseg; /* current segment being written */
- daddr_t lfs_offset; /* offset in curseg for next partial */
- daddr_t lfs_lastpseg; /* address of last partial written */
- u_long lfs_tstamp; /* time stamp */
+ ino_t lfs_free; /* start of the free list */
+ u_int32_t lfs_bfree; /* number of free disk blocks */
+ u_int32_t lfs_nfiles; /* number of allocated inodes */
+ int32_t lfs_avail; /* blocks available for writing */
+ u_int32_t lfs_uinodes; /* inodes in cache not yet on disk */
+ ufs_daddr_t lfs_idaddr; /* inode file disk address */
+ ino_t lfs_ifile; /* inode file inode number */
+ ufs_daddr_t lfs_lastseg; /* address of last segment written */
+ ufs_daddr_t lfs_nextseg; /* address of next segment to write */
+ ufs_daddr_t lfs_curseg; /* current segment being written */
+ ufs_daddr_t lfs_offset; /* offset in curseg for next partial */
+ ufs_daddr_t lfs_lastpseg; /* address of last partial written */
+ u_int32_t lfs_tstamp; /* time stamp */
/* These are configuration parameters. */
- u_long lfs_minfree; /* minimum percentage of free blocks */
+ u_int32_t lfs_minfree; /* minimum percentage of free blocks */
/* These fields can be computed from the others. */
- u_quad_t lfs_maxfilesize; /* maximum representable file size */
- u_long lfs_dbpseg; /* disk blocks per segment */
- u_long lfs_inopb; /* inodes per block */
- u_long lfs_ifpb; /* IFILE entries per block */
- u_long lfs_sepb; /* SEGUSE entries per block */
- u_long lfs_nindir; /* indirect pointers per block */
- u_long lfs_nseg; /* number of segments */
- u_long lfs_nspf; /* number of sectors per fragment */
- u_long lfs_cleansz; /* cleaner info size in blocks */
- u_long lfs_segtabsz; /* segment table size in blocks */
-
- u_long lfs_segmask; /* calculate offset within a segment */
- u_long lfs_segshift; /* fast mult/div for segments */
- u_long lfs_bmask; /* calc block offset from file offset */
- u_long lfs_bshift; /* calc block number from file offset */
- u_long lfs_ffmask; /* calc frag offset from file offset */
- u_long lfs_ffshift; /* fast mult/div for frag from file */
- u_long lfs_fbmask; /* calc frag offset from block offset */
- u_long lfs_fbshift; /* fast mult/div for frag from block */
- u_long lfs_fsbtodb; /* fsbtodb and dbtofsb shift constant */
- u_long lfs_sushift; /* fast mult/div for segusage table */
+ u_int64_t lfs_maxfilesize; /* maximum representable file size */
+ u_int32_t lfs_dbpseg; /* disk blocks per segment */
+ u_int32_t lfs_inopb; /* inodes per block */
+ u_int32_t lfs_ifpb; /* IFILE entries per block */
+ u_int32_t lfs_sepb; /* SEGUSE entries per block */
+ u_int32_t lfs_nindir; /* indirect pointers per block */
+ u_int32_t lfs_nseg; /* number of segments */
+ u_int32_t lfs_nspf; /* number of sectors per fragment */
+ u_int32_t lfs_cleansz; /* cleaner info size in blocks */
+ u_int32_t lfs_segtabsz; /* segment table size in blocks */
+
+ u_int32_t lfs_segmask; /* calculate offset within a segment */
+ u_int32_t lfs_segshift; /* fast mult/div for segments */
+ u_int64_t lfs_bmask; /* calc block offset from file offset */
+ u_int32_t lfs_bshift; /* calc block number from file offset */
+ u_int64_t lfs_ffmask; /* calc frag offset from file offset */
+ u_int32_t lfs_ffshift; /* fast mult/div for frag from file */
+ u_int64_t lfs_fbmask; /* calc frag offset from block offset */
+ u_int32_t lfs_fbshift; /* fast mult/div for frag from block */
+ u_int32_t lfs_fsbtodb; /* fsbtodb and dbtofsb shift constant */
+ u_int32_t lfs_sushift; /* fast mult/div for segusage table */
+
+ int32_t lfs_maxsymlinklen; /* max length of an internal symlink */
#define LFS_MIN_SBINTERVAL 5 /* minimum superblock segment spacing */
#define LFS_MAXNUMSB 10 /* superblock disk offsets */
- daddr_t lfs_sboffs[LFS_MAXNUMSB];
+ ufs_daddr_t lfs_sboffs[LFS_MAXNUMSB];
+
+/* Checksum -- last valid disk field. */
+ u_int32_t lfs_cksum; /* checksum for superblock checking */
/* These fields are set at mount time and are meaningless on disk. */
- struct segment *lfs_sp; /* current segment being written */
- struct vnode *lfs_ivnode; /* vnode for the ifile */
- u_long lfs_seglock; /* single-thread the segment writer */
- pid_t lfs_lockpid; /* pid of lock holder */
- u_long lfs_iocount; /* number of ios pending */
- u_long lfs_writer; /* don't allow any dirops to start */
- u_long lfs_dirops; /* count of active directory ops */
- u_long lfs_doifile; /* Write ifile blocks on next write */
- u_long lfs_nactive; /* Number of segments since last ckp */
- u_char lfs_fmod; /* super block modified flag */
- u_char lfs_clean; /* file system is clean flag */
- u_char lfs_ronly; /* mounted read-only flag */
- u_char lfs_flags; /* currently unused flag */
- u_char lfs_fsmnt[MNAMELEN]; /* name mounted on */
- u_char pad[3]; /* long-align */
-
-/* Checksum; valid on disk. */
- u_long lfs_cksum; /* checksum for superblock checking */
+ struct segment *lfs_sp; /* current segment being written */
+ struct vnode *lfs_ivnode; /* vnode for the ifile */
+ u_long lfs_seglock; /* single-thread the segment writer */
+ pid_t lfs_lockpid; /* pid of lock holder */
+ u_long lfs_iocount; /* number of ios pending */
+ u_long lfs_writer; /* don't allow any dirops to start */
+ u_long lfs_dirops; /* count of active directory ops */
+ u_long lfs_doifile; /* Write ifile blocks on next write */
+ u_long lfs_nactive; /* Number of segments since last ckp */
+ int8_t lfs_fmod; /* super block modified flag */
+ int8_t lfs_clean; /* file system is clean flag */
+ int8_t lfs_ronly; /* mounted read-only flag */
+ int8_t lfs_flags; /* currently unused flag */
+ u_char lfs_fsmnt[MNAMELEN]; /* name mounted on */
+
+ int32_t lfs_pad[40]; /* round to 512 bytes */
};
/*
- * Inode 0 is the out-of-band inode number, inode 1 is the inode number for
- * the IFILE, the root inode is 2 and the lost+found inode is 3.
+ * Inode 0: out-of-band inode number
+ * Inode 1: IFILE inode number
+ * Inode 2: root inode
+ * Inode 3: lost+found inode number
*/
-
-/* Fixed inode numbers. */
#define LFS_UNUSED_INUM 0 /* out of band inode number */
#define LFS_IFILE_INUM 1 /* IFILE inode number */
#define LOSTFOUNDINO 3 /* lost+found inode number */
@@ -182,10 +187,10 @@ struct lfs {
typedef struct ifile IFILE;
struct ifile {
- u_long if_version; /* inode version number */
+ u_int32_t if_version; /* inode version number */
#define LFS_UNUSED_DADDR 0 /* out-of-band daddr */
- daddr_t if_daddr; /* inode disk address */
- ino_t if_nextfree; /* next-unallocated inode */
+ ufs_daddr_t if_daddr; /* inode disk address */
+ ino_t if_nextfree; /* next-unallocated inode */
};
/*
@@ -193,8 +198,8 @@ struct ifile {
* to pass information between the cleaner and the kernel.
*/
typedef struct _cleanerinfo {
- u_long clean; /* K: number of clean segments */
- u_long dirty; /* K: number of dirty segments */
+ u_int32_t clean; /* K: number of clean segments */
+ u_int32_t dirty; /* K: number of dirty segments */
} CLEANERINFO;
#define CLEANSIZE_SU(fs) \
@@ -209,16 +214,19 @@ typedef struct _cleanerinfo {
/* On-disk segment summary information */
typedef struct segsum SEGSUM;
struct segsum {
- u_long ss_sumsum; /* check sum of summary block */
- u_long ss_datasum; /* check sum of data */
- daddr_t ss_next; /* next segment */
- u_long ss_create; /* creation time stamp */
- u_short ss_nfinfo; /* number of file info structures */
- u_short ss_ninos; /* number of inodes in summary */
+ u_int32_t ss_sumsum; /* check sum of summary block */
+ u_int32_t ss_datasum; /* check sum of data */
+ u_int32_t ss_magic; /* segment summary magic number */
+#define SS_MAGIC 0x061561
+ ufs_daddr_t ss_next; /* next segment */
+ u_int32_t ss_create; /* creation time stamp */
+ u_int16_t ss_nfinfo; /* number of file info structures */
+ u_int16_t ss_ninos; /* number of inodes in summary */
+
#define SS_DIROP 0x01 /* segment begins a dirop */
#define SS_CONT 0x02 /* more partials to finish this write*/
- u_short ss_flags; /* used for directory operations */
- u_short ss_pad; /* extra space */
+ u_int16_t ss_flags; /* used for directory operations */
+ u_int16_t ss_pad; /* extra space */
/* FINFO's and inode daddr's... */
};
@@ -228,26 +236,48 @@ struct segsum {
/* INOPB is the number of inodes in a secondary storage block. */
#define INOPB(fs) ((fs)->lfs_inopb)
-#define blksize(fs) ((fs)->lfs_bsize)
-#define blkoff(fs, loc) ((loc) & (fs)->lfs_bmask)
+#define blksize(fs, ip, lbn) \
+ (((lbn) >= NDADDR || (ip)->i_size >= ((lbn) + 1) << (fs)->lfs_bshift) \
+ ? (fs)->lfs_bsize \
+ : (fragroundup(fs, blkoff(fs, (ip)->i_size))))
+#define blkoff(fs, loc) ((int)((loc) & (fs)->lfs_bmask))
+#define fragoff(fs, loc) /* calculates (loc % fs->lfs_fsize) */ \
+ ((int)((loc) & (fs)->lfs_ffmask))
#define fsbtodb(fs, b) ((b) << (fs)->lfs_fsbtodb)
#define dbtofsb(fs, b) ((b) >> (fs)->lfs_fsbtodb)
+#define fragstodb(fs, b) ((b) << (fs)->lfs_fsbtodb - (fs)->lfs_fbshift)
+#define dbtofrags(fs, b) ((b) >> (fs)->lfs_fsbtodb - (fs)->lfs_fbshift)
#define lblkno(fs, loc) ((loc) >> (fs)->lfs_bshift)
#define lblktosize(fs, blk) ((blk) << (fs)->lfs_bshift)
-#define numfrags(fs, loc) /* calculates (loc / fs->fs_fsize) */ \
- ((loc) >> (fs)->lfs_bshift)
-
+#define numfrags(fs, loc) /* calculates (loc / fs->lfs_fsize) */ \
+ ((loc) >> (fs)->lfs_ffshift)
+#define blkroundup(fs, size) /* calculates roundup(size, fs->lfs_bsize) */ \
+ ((int)(((size) + (fs)->lfs_bmask) & (~(fs)->lfs_bmask)))
+#define fragroundup(fs, size) /* calculates roundup(size, fs->lfs_fsize) */ \
+ ((int)(((size) + (fs)->lfs_ffmask) & (~(fs)->lfs_ffmask)))
+#define fragstoblks(fs, frags) /* calculates (frags / fs->lfs_frag) */ \
+ ((frags) >> (fs)->lfs_fbshift)
+#define blkstofrags(fs, blks) /* calculates (blks * fs->lfs_frag) */ \
+ ((blks) << (fs)->lfs_fbshift)
+#define fragnum(fs, fsb) /* calculates (fsb % fs->lfs_frag) */ \
+ ((fsb) & ((fs)->lfs_frag - 1))
+#define blknum(fs, fsb) /* calculates rounddown(fsb, fs->lfs_frag) */ \
+ ((fsb) &~ ((fs)->lfs_frag - 1))
+#define dblksize(fs, dip, lbn) \
+ (((lbn) >= NDADDR || (dip)->di_size >= ((lbn) + 1) << (fs)->lfs_bshift)\
+ ? (fs)->lfs_bsize \
+ : (fragroundup(fs, blkoff(fs, (dip)->di_size))))
#define datosn(fs, daddr) /* disk address to segment number */ \
(((daddr) - (fs)->lfs_sboffs[0]) / fsbtodb((fs), (fs)->lfs_ssize))
#define sntoda(fs, sn) /* segment number to disk address */ \
- ((daddr_t)((sn) * ((fs)->lfs_ssize << (fs)->lfs_fsbtodb) + \
+ ((ufs_daddr_t)((sn) * ((fs)->lfs_ssize << (fs)->lfs_fsbtodb) + \
(fs)->lfs_sboffs[0]))
/* Read in the block with the cleaner info from the ifile. */
#define LFS_CLEANERINFO(CP, F, BP) { \
VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS; \
if (bread((F)->lfs_ivnode, \
- (daddr_t)0, (F)->lfs_bsize, NOCRED, &(BP))) \
+ (ufs_daddr_t)0, (F)->lfs_bsize, NOCRED, &(BP))) \
panic("lfs: ifile read"); \
(CP) = (CLEANERINFO *)(BP)->b_data; \
}
@@ -281,8 +311,8 @@ struct segsum {
* the segment usage table, plus an ifile page.
*/
#define LFS_FITS(fs, db) \
- ((long)((db + ((fs)->lfs_uinodes + INOPB((fs))) / INOPB((fs)) + \
- fsbtodb(fs, 1) + LFS_SUMMARY_SIZE / DEV_BSIZE + \
+ ((int32_t)((db + ((fs)->lfs_uinodes + INOPB((fs))) / \
+ INOPB((fs)) + fsbtodb(fs, 1) + LFS_SUMMARY_SIZE / DEV_BSIZE + \
(fs)->lfs_segtabsz)) < (fs)->lfs_avail)
/* Determine if a buffer belongs to the ifile */
@@ -294,32 +324,34 @@ struct segsum {
*/
typedef struct block_info {
ino_t bi_inode; /* inode # */
- daddr_t bi_lbn; /* logical block w/in file */
- daddr_t bi_daddr; /* disk address of block */
+ ufs_daddr_t bi_lbn; /* logical block w/in file */
+ ufs_daddr_t bi_daddr; /* disk address of block */
time_t bi_segcreate; /* origin segment create time */
int bi_version; /* file version number */
void *bi_bp; /* data buffer */
+ int bi_size; /* size of the block (if fragment) */
} BLOCK_INFO;
/* In-memory description of a segment about to be written. */
struct segment {
- struct lfs *fs; /* file system pointer */
+ struct lfs *fs; /* file system pointer */
struct buf **bpp; /* pointer to buffer array */
struct buf **cbpp; /* pointer to next available bp */
struct buf **start_bpp; /* pointer to first bp in this set */
- struct buf *ibp; /* buffer pointer to inode page */
- struct finfo *fip; /* current fileinfo pointer */
- struct vnode *vp; /* vnode being gathered */
- void *segsum; /* segment summary info */
- u_long ninodes; /* number of inodes in this segment */
- u_long seg_bytes_left; /* bytes left in segment */
- u_long sum_bytes_left; /* bytes left in summary block */
- u_long seg_number; /* number of this segment */
- daddr_t *start_lbp; /* beginning lbn for this set */
+ struct buf *ibp; /* buffer pointer to inode page */
+ struct finfo *fip; /* current fileinfo pointer */
+ struct vnode *vp; /* vnode being gathered */
+ void *segsum; /* segment summary info */
+ u_int32_t ninodes; /* number of inodes in this segment */
+ u_int32_t seg_bytes_left; /* bytes left in segment */
+ u_int32_t sum_bytes_left; /* bytes left in summary block */
+ u_int32_t seg_number; /* number of this segment */
+ ufs_daddr_t *start_lbp; /* beginning lbn for this set */
+
#define SEGM_CKP 0x01 /* doing a checkpoint */
#define SEGM_CLEAN 0x02 /* cleaner call; don't sort */
#define SEGM_SYNC 0x04 /* wait for segment */
- u_long seg_flags; /* run-time flags for this segment */
+ u_int16_t seg_flags; /* run-time flags for this segment */
};
#define ISSPACE(F, BB, C) \
@@ -336,18 +368,18 @@ struct segment {
#ifdef DOSTATS
/* Statistics Counters */
struct lfs_stats {
- int segsused;
- int psegwrites;
- int psyncwrites;
- int pcleanwrites;
- int blocktot;
- int cleanblocks;
- int ncheckpoints;
- int nwrites;
- int nsync_writes;
- int wait_exceeded;
- int write_exceeded;
- int flush_invoked;
+ u_int segsused;
+ u_int psegwrites;
+ u_int psyncwrites;
+ u_int pcleanwrites;
+ u_int blocktot;
+ u_int cleanblocks;
+ u_int ncheckpoints;
+ u_int nwrites;
+ u_int nsync_writes;
+ u_int wait_exceeded;
+ u_int write_exceeded;
+ u_int flush_invoked;
};
extern struct lfs_stats lfs_stats;
#endif
diff --git a/sys/ufs/lfs/lfs_alloc.c b/sys/ufs/lfs/lfs_alloc.c
index 3f06c81..837d2ea 100644
--- a/sys/ufs/lfs/lfs_alloc.c
+++ b/sys/ufs/lfs/lfs_alloc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1991, 1993
+ * Copyright (c) 1991, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)lfs_alloc.c 8.4 (Berkeley) 1/4/94
+ * @(#)lfs_alloc.c 8.7 (Berkeley) 5/14/95
*/
#include <sys/param.h>
@@ -46,6 +46,7 @@
#include <ufs/ufs/quota.h>
#include <ufs/ufs/inode.h>
#include <ufs/ufs/ufsmount.h>
+#include <ufs/ufs/ufs_extern.h>
#include <ufs/lfs/lfs.h>
#include <ufs/lfs/lfs_extern.h>
@@ -68,7 +69,7 @@ lfs_valloc(ap)
struct ifile *ifp;
struct inode *ip;
struct vnode *vp;
- daddr_t blkno;
+ ufs_daddr_t blkno;
ino_t new_ino;
u_long i, max;
int error;
@@ -95,7 +96,7 @@ lfs_valloc(ap)
vp = fs->lfs_ivnode;
ip = VTOI(vp);
blkno = lblkno(fs, ip->i_size);
- lfs_balloc(vp, fs->lfs_bsize, blkno, &bp);
+ lfs_balloc(vp, 0, fs->lfs_bsize, blkno, &bp);
ip->i_size += fs->lfs_bsize;
vnode_pager_setsize(vp, (u_long)ip->i_size);
vnode_pager_uncache(vp);
@@ -172,14 +173,13 @@ lfs_vcreate(mp, ino, vpp)
/* Initialize the inode. */
MALLOC(ip, struct inode *, sizeof(struct inode), M_LFSNODE, M_WAITOK);
+ lockinit(&ip->i_lock, PINOD, "lfsinode", 0, 0);
(*vpp)->v_data = ip;
ip->i_vnode = *vpp;
ip->i_devvp = ump->um_devvp;
ip->i_flag = IN_MODIFIED;
ip->i_dev = ump->um_dev;
ip->i_number = ip->i_din.di_inumber = ino;
-ip->i_din.di_spare[0] = 0xdeadbeef;
-ip->i_din.di_spare[1] = 0xdeadbeef;
ip->i_lfs = ump->um_lfs;
#ifdef QUOTA
for (i = 0; i < MAXQUOTAS; i++)
@@ -209,7 +209,7 @@ lfs_vfree(ap)
struct ifile *ifp;
struct inode *ip;
struct lfs *fs;
- daddr_t old_iaddr;
+ ufs_daddr_t old_iaddr;
ino_t ino;
/* Get the inode number and file system. */
diff --git a/sys/ufs/lfs/lfs_balloc.c b/sys/ufs/lfs/lfs_balloc.c
index b56bc9e..ec0c027 100644
--- a/sys/ufs/lfs/lfs_balloc.c
+++ b/sys/ufs/lfs/lfs_balloc.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)lfs_balloc.c 8.1 (Berkeley) 6/11/93
+ * @(#)lfs_balloc.c 8.4 (Berkeley) 5/8/95
*/
#include <sys/param.h>
#include <sys/buf.h>
@@ -50,18 +50,20 @@
#include <ufs/lfs/lfs_extern.h>
int
-lfs_balloc(vp, iosize, lbn, bpp)
+lfs_balloc(vp, offset, iosize, lbn, bpp)
struct vnode *vp;
+ int offset;
u_long iosize;
- daddr_t lbn;
+ ufs_daddr_t lbn;
struct buf **bpp;
{
struct buf *ibp, *bp;
struct inode *ip;
struct lfs *fs;
struct indir indirs[NIADDR+2];
- daddr_t daddr;
- int bb, error, i, num;
+ ufs_daddr_t daddr, lastblock;
+ int bb; /* number of disk blocks in a block disk blocks */
+ int error, frags, i, nsize, osize, num;
ip = VTOI(vp);
fs = ip->i_lfs;
@@ -74,43 +76,90 @@ lfs_balloc(vp, iosize, lbn, bpp)
* or written earlier). If it did, make sure we don't count it as a
* new block or zero out its contents. If it did not, make sure
* we allocate any necessary indirect blocks.
+ * If we are writing a block beyond the end of the file, we need to
+ * check if the old last block was a fragment. If it was, we need
+ * to rewrite it.
*/
*bpp = NULL;
if (error = ufs_bmaparray(vp, lbn, &daddr, &indirs[0], &num, NULL ))
return (error);
- *bpp = bp = getblk(vp, lbn, fs->lfs_bsize, 0, 0);
+ /* Check for block beyond end of file and fragment extension needed. */
+ lastblock = lblkno(fs, ip->i_size);
+ if (lastblock < NDADDR && lastblock < lbn) {
+ osize = blksize(fs, ip, lastblock);
+ if (osize < fs->lfs_bsize && osize > 0) {
+ if (error = lfs_fragextend(vp, osize, fs->lfs_bsize,
+ lastblock, &bp))
+ return(error);
+ ip->i_size = (lastblock + 1) * fs->lfs_bsize;
+ vnode_pager_setsize(vp, (u_long)ip->i_size);
+ ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ VOP_BWRITE(bp);
+ }
+ }
+
bb = VFSTOUFS(vp->v_mount)->um_seqinc;
if (daddr == UNASSIGNED)
/* May need to allocate indirect blocks */
for (i = 1; i < num; ++i)
if (!indirs[i].in_exists) {
- ibp =
- getblk(vp, indirs[i].in_lbn, fs->lfs_bsize,
- 0, 0);
- if (!(ibp->b_flags & (B_DONE | B_DELWRI))) {
- if (!ISSPACE(fs, bb, curproc->p_ucred)){
- ibp->b_flags |= B_INVAL;
- brelse(ibp);
- error = ENOSPC;
- } else {
- ip->i_blocks += bb;
- ip->i_lfs->lfs_bfree -= bb;
- clrbuf(ibp);
- error = VOP_BWRITE(ibp);
- }
- } else
+ ibp = getblk(vp, indirs[i].in_lbn, fs->lfs_bsize,
+ 0, 0);
+ if ((ibp->b_flags & (B_DONE | B_DELWRI)))
panic ("Indirect block should not exist");
+
+ if (!ISSPACE(fs, bb, curproc->p_ucred)){
+ ibp->b_flags |= B_INVAL;
+ brelse(ibp);
+ return(ENOSPC);
+ } else {
+ ip->i_blocks += bb;
+ ip->i_lfs->lfs_bfree -= bb;
+ clrbuf(ibp);
+ if(error = VOP_BWRITE(ibp))
+ return(error);
+ }
}
- if (error) {
- if (bp)
- brelse(bp);
- return(error);
- }
+ /*
+ * If the block we are writing is a direct block, it's the last
+ * block in the file, and offset + iosize is less than a full
+ * block, we can write one or more fragments. There are two cases:
+ * the block is brand new and we should allocate it the correct
+ * size or it already exists and contains some fragments and
+ * may need to extend it.
+ */
+ if (lbn < NDADDR && lblkno(fs, ip->i_size) == lbn) {
+ nsize = fragroundup(fs, offset + iosize);
+ frags = numfrags(fs, nsize);
+ bb = fragstodb(fs, frags);
+ if (lblktosize(fs, lbn) == ip->i_size)
+ /* Brand new block or fragment */
+ *bpp = bp = getblk(vp, lbn, nsize, 0, 0);
+ else {
+ /* Extend existing block */
+ if (error = lfs_fragextend(vp, (int)blksize(fs, ip, lbn),
+ nsize, lbn, &bp))
+ return(error);
+ *bpp = bp;
+ }
+ } else {
+ /*
+ * Get the existing block from the cache either because the
+ * block is 1) not a direct block or because it's not the last
+ * block in the file.
+ */
+ frags = dbtofrags(fs, bb);
+ *bpp = bp = getblk(vp, lbn, blksize(fs, ip, lbn), 0, 0);
+ }
- /* Now, we may need to allocate the data block */
+ /*
+ * The block we are writing may be a brand new block
+ * in which case we need to do accounting (i.e. check
+ * for free space and update the inode number of blocks.
+ */
if (!(bp->b_flags & (B_CACHE | B_DONE | B_DELWRI))) {
if (daddr == UNASSIGNED)
if (!ISSPACE(fs, bb, curproc->p_ucred)) {
@@ -124,13 +173,55 @@ lfs_balloc(vp, iosize, lbn, bpp)
clrbuf(bp);
}
else if (iosize == fs->lfs_bsize)
- bp->b_blkno = daddr; /* Skip the I/O */
+ /* Optimization: I/O is unnecessary. */
+ bp->b_blkno = daddr;
else {
+ /*
+ * We need to read the block to preserve the
+ * existing bytes.
+ */
bp->b_blkno = daddr;
bp->b_flags |= B_READ;
VOP_STRATEGY(bp);
return(biowait(bp));
}
}
- return (error);
+ return (0);
+}
+
+lfs_fragextend(vp, osize, nsize, lbn, bpp)
+ struct vnode *vp;
+ int osize;
+ int nsize;
+ daddr_t lbn;
+ struct buf **bpp;
+{
+ struct inode *ip;
+ struct lfs *fs;
+ long bb;
+ int error;
+
+ ip = VTOI(vp);
+ fs = ip->i_lfs;
+ bb = (long)fragstodb(fs, numfrags(fs, nsize - osize));
+ if (!ISSPACE(fs, bb, curproc->p_ucred)) {
+ return(ENOSPC);
+ }
+
+ if (error = bread(vp, lbn, osize, NOCRED, bpp)) {
+ brelse(*bpp);
+ return(error);
+ }
+#ifdef QUOTA
+ if (error = chkdq(ip, bb, curproc->p_ucred, 0)) {
+ brelse(*bpp);
+ return (error);
+ }
+#endif
+ ip->i_blocks += bb;
+ ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ fs->lfs_bfree -= fragstodb(fs, numfrags(fs, (nsize - osize)));
+ allocbuf(*bpp, nsize);
+ bzero((char *)((*bpp)->b_data) + osize, (u_int)(nsize - osize));
+ return(0);
}
diff --git a/sys/ufs/lfs/lfs_bio.c b/sys/ufs/lfs/lfs_bio.c
index 0f021f1..837e8aa 100644
--- a/sys/ufs/lfs/lfs_bio.c
+++ b/sys/ufs/lfs/lfs_bio.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)lfs_bio.c 8.4 (Berkeley) 12/30/93
+ * @(#)lfs_bio.c 8.10 (Berkeley) 6/10/95
*/
#include <sys/param.h>
@@ -76,7 +76,7 @@ lfs_bwrite(ap)
register struct buf *bp = ap->a_bp;
struct lfs *fs;
struct inode *ip;
- int error, s;
+ int db, error, s;
/*
* Set the delayed write flag and use reassignbuf to move the buffer
@@ -94,10 +94,12 @@ lfs_bwrite(ap)
*/
if (!(bp->b_flags & B_LOCKED)) {
fs = VFSTOUFS(bp->b_vp->v_mount)->um_lfs;
- while (!LFS_FITS(fs, fsbtodb(fs, 1)) && !IS_IFILE(bp) &&
+ db = fragstodb(fs, numfrags(fs, bp->b_bcount));
+ while (!LFS_FITS(fs, db) && !IS_IFILE(bp) &&
bp->b_lblkno > 0) {
/* Out of space, need cleaner to run */
wakeup(&lfs_allclean_wakeup);
+ wakeup(&fs->lfs_nextseg);
if (error = tsleep(&fs->lfs_avail, PCATCH | PUSER,
"cleaner", NULL)) {
brelse(bp);
@@ -108,7 +110,7 @@ lfs_bwrite(ap)
if (!(ip->i_flag & IN_MODIFIED))
++fs->lfs_uinodes;
ip->i_flag |= IN_CHANGE | IN_MODIFIED | IN_UPDATE;
- fs->lfs_avail -= fsbtodb(fs, 1);
+ fs->lfs_avail -= db;
++locked_queue_count;
bp->b_flags |= B_DELWRI | B_LOCKED;
bp->b_flags &= ~(B_READ | B_ERROR);
@@ -131,7 +133,8 @@ lfs_bwrite(ap)
void
lfs_flush()
{
- register struct mount *mp;
+ register struct mount *mp, *nmp;
+ struct proc *p = curproc; /* XXX */
#ifdef DOSTATS
++lfs_stats.write_exceeded;
@@ -139,10 +142,14 @@ lfs_flush()
if (lfs_writing)
return;
lfs_writing = 1;
- for (mp = mountlist.tqh_first; mp != NULL; mp = mp->mnt_list.tqe_next) {
- /* The lock check below is to avoid races with unmount. */
- if (mp->mnt_stat.f_type == MOUNT_LFS &&
- (mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_UNMOUNT)) == 0 &&
+ simple_lock(&mountlist_slock);
+ for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
+ if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
+ nmp = mp->mnt_list.cqe_next;
+ continue;
+ }
+ if (mp->mnt_stat.f_type == lfs_mount_type &&
+ (mp->mnt_flag & MNT_RDONLY) == 0 &&
!((((struct ufsmount *)mp->mnt_data))->ufsmount_u.lfs)->lfs_dirops ) {
/*
* We set the queue to 0 here because we are about to
@@ -156,14 +163,18 @@ lfs_flush()
#endif
lfs_segwrite(mp, 0);
}
+ simple_lock(&mountlist_slock);
+ nmp = mp->mnt_list.cqe_next;
+ vfs_unbusy(mp, p);
}
+ simple_unlock(&mountlist_slock);
lfs_writing = 0;
}
int
lfs_check(vp, blkno)
struct vnode *vp;
- daddr_t blkno;
+ ufs_daddr_t blkno;
{
extern int lfs_allclean_wakeup;
int error;
diff --git a/sys/ufs/lfs/lfs_cksum.c b/sys/ufs/lfs/lfs_cksum.c
index 77b011a..cd513fd 100644
--- a/sys/ufs/lfs/lfs_cksum.c
+++ b/sys/ufs/lfs/lfs_cksum.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)lfs_cksum.c 8.1 (Berkeley) 6/11/93
+ * @(#)lfs_cksum.c 8.2 (Berkeley) 10/9/94
*/
#include <sys/types.h>
@@ -52,7 +52,7 @@ cksum(str, len)
len &= ~(sizeof(u_short) - 1);
for (sum = 0; len; len -= sizeof(u_short)) {
sum ^= *(u_short *)str;
- ++(u_short *)str;
+ str = (void *)((u_short *)str + 1);
}
return (sum);
}
diff --git a/sys/ufs/lfs/lfs_extern.h b/sys/ufs/lfs/lfs_extern.h
index c1157ad..1841146 100644
--- a/sys/ufs/lfs/lfs_extern.h
+++ b/sys/ufs/lfs/lfs_extern.h
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)lfs_extern.h 8.2 (Berkeley) 4/16/94
+ * @(#)lfs_extern.h 8.6 (Berkeley) 5/8/95
*/
struct fid;
@@ -45,10 +45,10 @@ struct mbuf;
__BEGIN_DECLS
u_long cksum __P((void *, size_t)); /* XXX */
-int lfs_balloc __P((struct vnode *, u_long, daddr_t, struct buf **));
+int lfs_balloc __P((struct vnode *, int, u_long, ufs_daddr_t, struct buf **));
int lfs_blkatoff __P((struct vop_blkatoff_args *));
int lfs_bwrite __P((struct vop_bwrite_args *));
-int lfs_check __P((struct vnode *, daddr_t));
+int lfs_check __P((struct vnode *, ufs_daddr_t));
int lfs_close __P((struct vop_close_args *));
int lfs_create __P((struct vop_create_args *));
int lfs_fhtovp __P((struct mount *, struct fid *, struct mbuf *,
@@ -58,7 +58,7 @@ int lfs_getattr __P((struct vop_getattr_args *));
struct dinode *
lfs_ifind __P((struct lfs *, ino_t, struct dinode *));
int lfs_inactive __P((struct vop_inactive_args *));
-int lfs_init __P((void));
+int lfs_init __P((struct vfsconf *));
int lfs_initseg __P((struct lfs *));
int lfs_link __P((struct vop_link_args *));
int lfs_makeinode __P((int, struct nameidata *, struct inode **));
@@ -68,8 +68,9 @@ int lfs_mount __P((struct mount *,
char *, caddr_t, struct nameidata *, struct proc *));
int lfs_mountroot __P((void));
struct buf *
- lfs_newbuf __P((struct vnode *, daddr_t, size_t));
+ lfs_newbuf __P((struct vnode *, ufs_daddr_t, size_t));
int lfs_read __P((struct vop_read_args *));
+int lfs_reclaim __P((struct vop_reclaim_args *));
int lfs_remove __P((struct vop_remove_args *));
int lfs_rmdir __P((struct vop_rmdir_args *));
int lfs_rename __P((struct vop_rename_args *));
@@ -79,6 +80,8 @@ int lfs_segwrite __P((struct mount *, int));
int lfs_statfs __P((struct mount *, struct statfs *, struct proc *));
int lfs_symlink __P((struct vop_symlink_args *));
int lfs_sync __P((struct mount *, int, struct ucred *, struct proc *));
+#define lfs_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
+ size_t, struct proc *)))eopnotsupp)
int lfs_truncate __P((struct vop_truncate_args *));
int lfs_unmount __P((struct mount *, int, struct proc *));
int lfs_update __P((struct vop_update_args *));
@@ -96,6 +99,7 @@ void lfs_dump_dinode __P((struct dinode *));
void lfs_dump_super __P((struct lfs *));
#endif
__END_DECLS
+extern int lfs_mount_type;
extern int (**lfs_vnodeop_p)();
extern int (**lfs_specop_p)();
#ifdef FIFO
diff --git a/sys/ufs/lfs/lfs_inode.c b/sys/ufs/lfs/lfs_inode.c
index 1a06aa2..be7d37f 100644
--- a/sys/ufs/lfs/lfs_inode.c
+++ b/sys/ufs/lfs/lfs_inode.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)lfs_inode.c 8.5 (Berkeley) 12/30/93
+ * @(#)lfs_inode.c 8.9 (Berkeley) 5/8/95
*/
#include <sys/param.h>
@@ -53,12 +53,6 @@
#include <ufs/lfs/lfs.h>
#include <ufs/lfs/lfs_extern.h>
-int
-lfs_init()
-{
- return (ufs_init());
-}
-
/* Search a block for a specific dinode. */
struct dinode *
lfs_ifind(fs, ino, dip)
@@ -96,13 +90,13 @@ lfs_update(ap)
(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0)
return (0);
if (ip->i_flag & IN_ACCESS)
- ip->i_atime.ts_sec = ap->a_access->tv_sec;
+ ip->i_atime = ap->a_access->tv_sec;
if (ip->i_flag & IN_UPDATE) {
- ip->i_mtime.ts_sec = ap->a_modify->tv_sec;
+ ip->i_mtime = ap->a_modify->tv_sec;
(ip)->i_modrev++;
}
if (ip->i_flag & IN_CHANGE)
- ip->i_ctime.ts_sec = time.tv_sec;
+ ip->i_ctime = time.tv_sec;
ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE);
if (!(ip->i_flag & IN_MODIFIED))
@@ -117,22 +111,22 @@ lfs_update(ap)
#define UPDATE_SEGUSE \
if (lastseg != -1) { \
LFS_SEGENTRY(sup, fs, lastseg, sup_bp); \
- if ((num << fs->lfs_bshift) > sup->su_nbytes) \
+ if (num > sup->su_nbytes) \
panic("lfs_truncate: negative bytes in segment %d\n", \
lastseg); \
- sup->su_nbytes -= num << fs->lfs_bshift; \
+ sup->su_nbytes -= num; \
e1 = VOP_BWRITE(sup_bp); \
- blocksreleased += num; \
+ fragsreleased += numfrags(fs, num); \
}
-#define SEGDEC { \
+#define SEGDEC(S) { \
if (daddr != 0) { \
if (lastseg != (seg = datosn(fs, daddr))) { \
UPDATE_SEGUSE; \
- num = 1; \
+ num = (S); \
lastseg = seg; \
} else \
- ++num; \
+ num += (S); \
} \
}
@@ -153,7 +147,7 @@ lfs_truncate(ap)
{
register struct indir *inp;
register int i;
- register daddr_t *daddrp;
+ register ufs_daddr_t *daddrp;
register struct vnode *vp = ap->a_vp;
off_t length = ap->a_length;
struct buf *bp, *sup_bp;
@@ -163,9 +157,10 @@ lfs_truncate(ap)
struct lfs *fs;
struct indir a[NIADDR + 2], a_end[NIADDR + 2];
SEGUSE *sup;
- daddr_t daddr, lastblock, lbn, olastblock;
- long off, a_released, blocksreleased, i_released;
- int e1, e2, depth, lastseg, num, offset, seg, size;
+ ufs_daddr_t daddr, lastblock, lbn, olastblock;
+ ufs_daddr_t oldsize_lastblock, oldsize_newlast, newsize;
+ long off, a_released, fragsreleased, i_released;
+ int e1, e2, depth, lastseg, num, offset, seg, freesize;
ip = VTOI(vp);
tv = time;
@@ -201,24 +196,29 @@ lfs_truncate(ap)
* Update the size of the file. If the file is not being truncated to
* a block boundry, the contents of the partial block following the end
* of the file must be zero'ed in case it ever become accessable again
- * because of subsequent file growth.
+ * because of subsequent file growth. For this part of the code,
+ * oldsize_newlast refers to the old size of the new last block in the file.
*/
offset = blkoff(fs, length);
+ lbn = lblkno(fs, length);
+ oldsize_newlast = blksize(fs, ip, lbn);
+
+ /* Now set oldsize to the current size of the current last block */
+ oldsize_lastblock = blksize(fs, ip, olastblock);
if (offset == 0)
ip->i_size = length;
else {
- lbn = lblkno(fs, length);
#ifdef QUOTA
if (e1 = getinoquota(ip))
return (e1);
#endif
- if (e1 = bread(vp, lbn, fs->lfs_bsize, NOCRED, &bp))
+ if (e1 = bread(vp, lbn, oldsize_newlast, NOCRED, &bp))
return (e1);
ip->i_size = length;
- size = blksize(fs);
(void)vnode_pager_uncache(vp);
- bzero((char *)bp->b_data + offset, (u_int)(size - offset));
- allocbuf(bp, size);
+ newsize = blksize(fs, ip, lbn);
+ bzero((char *)bp->b_data + offset, (u_int)(newsize - offset));
+ allocbuf(bp, newsize);
if (e1 = VOP_BWRITE(bp))
return (e1);
}
@@ -226,20 +226,24 @@ lfs_truncate(ap)
* Modify sup->su_nbyte counters for each deleted block; keep track
* of number of blocks removed for ip->i_blocks.
*/
- blocksreleased = 0;
+ fragsreleased = 0;
num = 0;
lastseg = -1;
for (lbn = olastblock; lbn >= lastblock;) {
/* XXX use run length from bmap array to make this faster */
ufs_bmaparray(vp, lbn, &daddr, a, &depth, NULL);
- if (lbn == olastblock)
+ if (lbn == olastblock) {
for (i = NIADDR + 2; i--;)
a_end[i] = a[i];
+ freesize = oldsize_lastblock;
+ } else
+ freesize = fs->lfs_bsize;
+
switch (depth) {
case 0: /* Direct block. */
daddr = ip->i_db[lbn];
- SEGDEC;
+ SEGDEC(freesize);
ip->i_db[lbn] = 0;
--lbn;
break;
@@ -261,19 +265,20 @@ lfs_truncate(ap)
inp->in_lbn, fs->lfs_bsize, NOCRED, &bp))
panic("lfs_truncate: bread bno %d",
inp->in_lbn);
- daddrp = (daddr_t *)bp->b_data + inp->in_off;
+ daddrp = (ufs_daddr_t *)bp->b_data +
+ inp->in_off;
for (i = inp->in_off;
i++ <= a_end[depth].in_off;) {
daddr = *daddrp++;
- SEGDEC;
+ SEGDEC(freesize);
}
a_end[depth].in_off = NINDIR(fs) - 1;
if (inp->in_off == 0)
brelse (bp);
else {
- bzero((daddr_t *)bp->b_data +
+ bzero((ufs_daddr_t *)bp->b_data +
inp->in_off, fs->lfs_bsize -
- inp->in_off * sizeof(daddr_t));
+ inp->in_off * sizeof(ufs_daddr_t));
if (e1 = VOP_BWRITE(bp))
return (e1);
}
@@ -281,7 +286,7 @@ lfs_truncate(ap)
if (depth == 0 && a[1].in_off == 0) {
off = a[0].in_off;
daddr = ip->i_ib[off];
- SEGDEC;
+ SEGDEC(freesize);
ip->i_ib[off] = 0;
}
if (lbn == lastblock || lbn <= NDADDR)
@@ -303,13 +308,14 @@ lfs_truncate(ap)
}
#ifdef DIAGNOSTIC
- if (ip->i_blocks < fsbtodb(fs, blocksreleased)) {
- printf("lfs_truncate: block count < 0\n");
- blocksreleased = ip->i_blocks;
+ if (ip->i_blocks < fragstodb(fs, fragsreleased)) {
+ printf("lfs_truncate: frag count < 0\n");
+ fragsreleased = dbtofrags(fs, ip->i_blocks);
+ panic("lfs_truncate: frag count < 0\n");
}
#endif
- ip->i_blocks -= fsbtodb(fs, blocksreleased);
- fs->lfs_bfree += fsbtodb(fs, blocksreleased);
+ ip->i_blocks -= fragstodb(fs, fragsreleased);
+ fs->lfs_bfree += fragstodb(fs, fragsreleased);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
/*
* Traverse dirty block list counting number of dirty buffers
@@ -320,7 +326,7 @@ lfs_truncate(ap)
i_released = 0;
for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = bp->b_vnbufs.le_next)
if (bp->b_flags & B_LOCKED) {
- ++a_released;
+ a_released += numfrags(fs, bp->b_bcount);
/*
* XXX
* When buffers are created in the cache, their block
@@ -333,25 +339,28 @@ lfs_truncate(ap)
* here.
*/
if (bp->b_blkno == bp->b_lblkno)
- ++i_released;
+ i_released += numfrags(fs, bp->b_bcount);
}
- blocksreleased = fsbtodb(fs, i_released);
+ fragsreleased = i_released;
#ifdef DIAGNOSTIC
- if (blocksreleased > ip->i_blocks) {
+ if (fragsreleased > dbtofrags(fs, ip->i_blocks)) {
printf("lfs_inode: Warning! %s\n",
- "more blocks released from inode than are in inode");
- blocksreleased = ip->i_blocks;
+ "more frags released from inode than are in inode");
+ fragsreleased = dbtofrags(fs, ip->i_blocks);
+ panic("lfs_inode: Warning. More frags released\n");
}
#endif
- fs->lfs_bfree += blocksreleased;
- ip->i_blocks -= blocksreleased;
+ fs->lfs_bfree += fragstodb(fs, fragsreleased);
+ ip->i_blocks -= fragstodb(fs, fragsreleased);
#ifdef DIAGNOSTIC
- if (length == 0 && ip->i_blocks != 0)
+ if (length == 0 && ip->i_blocks != 0) {
printf("lfs_inode: Warning! %s%d%s\n",
"Truncation to zero, but ", ip->i_blocks,
" blocks left on inode");
+ panic("lfs_inode");
+ }
#endif
- fs->lfs_avail += fsbtodb(fs, a_released);
+ fs->lfs_avail += fragstodb(fs, a_released);
e1 = vinvalbuf(vp, (length > 0) ? V_SAVE : 0, ap->a_cred, ap->a_p,
0, 0);
e2 = VOP_UPDATE(vp, &tv, &tv, 0);
diff --git a/sys/ufs/lfs/lfs_segment.c b/sys/ufs/lfs/lfs_segment.c
index 249d59d..5e43695 100644
--- a/sys/ufs/lfs/lfs_segment.c
+++ b/sys/ufs/lfs/lfs_segment.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)lfs_segment.c 8.5 (Berkeley) 1/4/94
+ * @(#)lfs_segment.c 8.10 (Berkeley) 6/10/95
*/
#include <sys/param.h>
@@ -74,13 +74,13 @@ void lfs_callback __P((struct buf *));
void lfs_gather __P((struct lfs *, struct segment *,
struct vnode *, int (*) __P((struct lfs *, struct buf *))));
int lfs_gatherblock __P((struct segment *, struct buf *, int *));
-void lfs_iset __P((struct inode *, daddr_t, time_t));
+void lfs_iset __P((struct inode *, ufs_daddr_t, time_t));
int lfs_match_data __P((struct lfs *, struct buf *));
int lfs_match_dindir __P((struct lfs *, struct buf *));
int lfs_match_indir __P((struct lfs *, struct buf *));
int lfs_match_tindir __P((struct lfs *, struct buf *));
void lfs_newseg __P((struct lfs *));
-void lfs_shellsort __P((struct buf **, daddr_t *, register int));
+void lfs_shellsort __P((struct buf **, ufs_daddr_t *, register int));
void lfs_supercallback __P((struct buf *));
void lfs_updatemeta __P((struct segment *));
int lfs_vref __P((struct vnode *));
@@ -158,10 +158,23 @@ lfs_writevnodes(fs, mp, sp, op)
struct inode *ip;
struct vnode *vp;
+/* BEGIN HACK */
+#define VN_OFFSET (((void *)&vp->v_mntvnodes.le_next) - (void *)vp)
+#define BACK_VP(VP) ((struct vnode *)(((void *)VP->v_mntvnodes.le_prev) - VN_OFFSET))
+#define BEG_OF_VLIST ((struct vnode *)(((void *)&mp->mnt_vnodelist.lh_first) - VN_OFFSET))
+
+/* Find last vnode. */
+loop: for (vp = mp->mnt_vnodelist.lh_first;
+ vp && vp->v_mntvnodes.le_next != NULL;
+ vp = vp->v_mntvnodes.le_next);
+ for (; vp && vp != BEG_OF_VLIST; vp = BACK_VP(vp)) {
+/* END HACK */
+/*
loop:
for (vp = mp->mnt_vnodelist.lh_first;
vp != NULL;
vp = vp->v_mntvnodes.le_next) {
+*/
/*
* If the vnode that we are about to sync is no longer
* associated with this mount point, start over.
@@ -207,13 +220,14 @@ lfs_segwrite(mp, flags)
struct mount *mp;
int flags; /* Do a checkpoint. */
{
+ struct proc *p = curproc; /* XXX */
struct buf *bp;
struct inode *ip;
struct lfs *fs;
struct segment *sp;
struct vnode *vp;
SEGUSE *segusep;
- daddr_t ibno;
+ ufs_daddr_t ibno;
CLEANERINFO *cip;
int clean, do_ckp, error, i;
@@ -227,14 +241,15 @@ lfs_segwrite(mp, flags)
LFS_CLEANERINFO(cip, fs, bp);
clean = cip->clean;
brelse(bp);
- if (clean <= 2) {
- printf ("segs clean: %d\n", clean);
+ if (clean <= 2 || fs->lfs_avail <= 0) {
+ /* printf ("segs clean: %d\n", clean); */
wakeup(&lfs_allclean_wakeup);
+ wakeup(&fs->lfs_nextseg);
if (error = tsleep(&fs->lfs_avail, PRIBIO + 1,
"lfs writer", 0))
return (error);
}
- } while (clean <= 2 );
+ } while (clean <= 2 || fs->lfs_avail <= 0);
/*
* Allocate a segment structure and enough space to hold pointers to
@@ -282,7 +297,8 @@ lfs_segwrite(mp, flags)
if (do_ckp || fs->lfs_doifile) {
redo:
vp = fs->lfs_ivnode;
- while (vget(vp, 1));
+ while (vget(vp, LK_EXCLUSIVE, p))
+ continue;
ip = VTOI(vp);
if (vp->v_dirtyblkhd.lh_first != NULL)
lfs_writefile(fs, sp, vp);
@@ -331,7 +347,7 @@ lfs_writefile(fs, sp, vp)
sp->sum_bytes_left < sizeof(struct finfo))
(void) lfs_writeseg(fs, sp);
- sp->sum_bytes_left -= sizeof(struct finfo) - sizeof(daddr_t);
+ sp->sum_bytes_left -= sizeof(struct finfo) - sizeof(ufs_daddr_t);
++((SEGSUM *)(sp->segsum))->ss_nfinfo;
fip = sp->fip;
@@ -357,10 +373,10 @@ lfs_writefile(fs, sp, vp)
if (fip->fi_nblocks != 0) {
sp->fip =
(struct finfo *)((caddr_t)fip + sizeof(struct finfo) +
- sizeof(daddr_t) * (fip->fi_nblocks - 1));
+ sizeof(ufs_daddr_t) * (fip->fi_nblocks - 1));
sp->start_lbp = &sp->fip->fi_blocks[0];
} else {
- sp->sum_bytes_left += sizeof(struct finfo) - sizeof(daddr_t);
+ sp->sum_bytes_left += sizeof(struct finfo) - sizeof(ufs_daddr_t);
--((SEGSUM *)(sp->segsum))->ss_nfinfo;
}
}
@@ -374,7 +390,7 @@ lfs_writeinode(fs, sp, ip)
struct buf *bp, *ibp;
IFILE *ifp;
SEGUSE *sup;
- daddr_t daddr;
+ ufs_daddr_t daddr;
ino_t ino;
int error, i, ndx;
int redo_ifile = 0;
@@ -386,7 +402,7 @@ lfs_writeinode(fs, sp, ip)
if (sp->ibp == NULL) {
/* Allocate a new segment if necessary. */
if (sp->seg_bytes_left < fs->lfs_bsize ||
- sp->sum_bytes_left < sizeof(daddr_t))
+ sp->sum_bytes_left < sizeof(ufs_daddr_t))
(void) lfs_writeseg(fs, sp);
/* Get next inode block. */
@@ -402,10 +418,10 @@ lfs_writeinode(fs, sp, ip)
fs->lfs_avail -= fsbtodb(fs, 1);
/* Set remaining space counters. */
sp->seg_bytes_left -= fs->lfs_bsize;
- sp->sum_bytes_left -= sizeof(daddr_t);
- ndx = LFS_SUMMARY_SIZE / sizeof(daddr_t) -
+ sp->sum_bytes_left -= sizeof(ufs_daddr_t);
+ ndx = LFS_SUMMARY_SIZE / sizeof(ufs_daddr_t) -
sp->ninodes / INOPB(fs) - 1;
- ((daddr_t *)(sp->segsum))[ndx] = daddr;
+ ((ufs_daddr_t *)(sp->segsum))[ndx] = daddr;
}
/* Update the inode times and copy the inode onto the inode page. */
@@ -478,8 +494,8 @@ lfs_gatherblock(sp, bp, sptr)
panic ("lfs_gatherblock: Null vp in segment");
#endif
fs = sp->fs;
- if (sp->sum_bytes_left < sizeof(daddr_t) ||
- sp->seg_bytes_left < fs->lfs_bsize) {
+ if (sp->sum_bytes_left < sizeof(ufs_daddr_t) ||
+ sp->seg_bytes_left < bp->b_bcount) {
if (sptr)
splx(*sptr);
lfs_updatemeta(sp);
@@ -492,7 +508,7 @@ lfs_gatherblock(sp, bp, sptr)
/* Add the current file to the segment summary. */
++((SEGSUM *)(sp->segsum))->ss_nfinfo;
sp->sum_bytes_left -=
- sizeof(struct finfo) - sizeof(daddr_t);
+ sizeof(struct finfo) - sizeof(ufs_daddr_t);
if (sptr)
*sptr = splbio();
@@ -504,8 +520,8 @@ lfs_gatherblock(sp, bp, sptr)
*sp->cbpp++ = bp;
sp->fip->fi_blocks[sp->fip->fi_nblocks++] = bp->b_lblkno;
- sp->sum_bytes_left -= sizeof(daddr_t);
- sp->seg_bytes_left -= fs->lfs_bsize;
+ sp->sum_bytes_left -= sizeof(ufs_daddr_t);
+ sp->seg_bytes_left -= bp->b_bcount;
return(0);
}
@@ -521,7 +537,19 @@ lfs_gather(fs, sp, vp, match)
sp->vp = vp;
s = splbio();
-loop: for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = bp->b_vnbufs.le_next) {
+/* This is a hack to see if ordering the blocks in LFS makes a difference. */
+/* BEGIN HACK */
+#define BUF_OFFSET (((void *)&bp->b_vnbufs.le_next) - (void *)bp)
+#define BACK_BUF(BP) ((struct buf *)(((void *)BP->b_vnbufs.le_prev) - BUF_OFFSET))
+#define BEG_OF_LIST ((struct buf *)(((void *)&vp->v_dirtyblkhd.lh_first) - BUF_OFFSET))
+
+
+/*loop: for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = bp->b_vnbufs.le_next) {*/
+/* Find last buffer. */
+loop: for (bp = vp->v_dirtyblkhd.lh_first; bp && bp->b_vnbufs.le_next != NULL;
+ bp = bp->b_vnbufs.le_next);
+ for (; bp && bp != BEG_OF_LIST; bp = BACK_BUF(bp)) {
+/* END HACK */
if (bp->b_flags & B_BUSY || !match(fs, bp) ||
bp->b_flags & B_GATHERED)
continue;
@@ -554,11 +582,13 @@ lfs_updatemeta(sp)
struct vnode *vp;
struct indir a[NIADDR + 2], *ap;
struct inode *ip;
- daddr_t daddr, lbn, off;
- int db_per_fsb, error, i, nblocks, num;
+ ufs_daddr_t daddr, lbn, off;
+ int error, i, nblocks, num;
vp = sp->vp;
nblocks = &sp->fip->fi_blocks[sp->fip->fi_nblocks] - sp->start_lbp;
+ if (nblocks < 0)
+ panic("This is a bad thing\n");
if (vp == NULL || nblocks == 0)
return;
@@ -567,15 +597,23 @@ lfs_updatemeta(sp)
lfs_shellsort(sp->start_bpp, sp->start_lbp, nblocks);
/*
+ * Record the length of the last block in case it's a fragment.
+ * If there are indirect blocks present, they sort last. An
+ * indirect block will be lfs_bsize and its presence indicates
+ * that you cannot have fragments.
+ */
+ sp->fip->fi_lastlength = sp->start_bpp[nblocks - 1]->b_bcount;
+
+ /*
* Assign disk addresses, and update references to the logical
* block and the segment usage information.
*/
fs = sp->fs;
- db_per_fsb = fsbtodb(fs, 1);
for (i = nblocks; i--; ++sp->start_bpp) {
lbn = *sp->start_lbp++;
(*sp->start_bpp)->b_blkno = off = fs->lfs_offset;
- fs->lfs_offset += db_per_fsb;
+ fs->lfs_offset +=
+ fragstodb(fs, numfrags(fs, (*sp->start_bpp)->b_bcount));
if (error = ufs_bmaparray(vp, lbn, &daddr, a, &num, NULL))
panic("lfs_updatemeta: ufs_bmaparray %d", error);
@@ -597,11 +635,10 @@ lfs_updatemeta(sp)
* to get counted for the inode.
*/
if (bp->b_blkno == -1 && !(bp->b_flags & B_CACHE)) {
-printf ("Updatemeta allocating indirect block: shouldn't happen\n");
- ip->i_blocks += btodb(fs->lfs_bsize);
- fs->lfs_bfree -= btodb(fs->lfs_bsize);
+ ip->i_blocks += fsbtodb(fs, 1);
+ fs->lfs_bfree -= fragstodb(fs, fs->lfs_frag);
}
- ((daddr_t *)bp->b_data)[ap->in_off] = off;
+ ((ufs_daddr_t *)bp->b_data)[ap->in_off] = off;
VOP_BWRITE(bp);
}
@@ -610,14 +647,16 @@ printf ("Updatemeta allocating indirect block: shouldn't happen\n");
!(daddr >= fs->lfs_lastpseg && daddr <= off)) {
LFS_SEGENTRY(sup, fs, datosn(fs, daddr), bp);
#ifdef DIAGNOSTIC
- if (sup->su_nbytes < fs->lfs_bsize) {
+ if (sup->su_nbytes < (*sp->start_bpp)->b_bcount) {
/* XXX -- Change to a panic. */
printf("lfs: negative bytes (segment %d)\n",
datosn(fs, daddr));
+ printf("lfs: bp = 0x%x, addr = 0x%x\n",
+ bp, bp->b_un.b_addr);
panic ("Negative Bytes");
}
#endif
- sup->su_nbytes -= fs->lfs_bsize;
+ sup->su_nbytes -= (*sp->start_bpp)->b_bcount;
error = VOP_BWRITE(bp);
}
}
@@ -643,6 +682,7 @@ lfs_initseg(fs)
if (!LFS_PARTIAL_FITS(fs)) {
/* Wake up any cleaning procs waiting on this file system. */
wakeup(&lfs_allclean_wakeup);
+ wakeup(&fs->lfs_nextseg);
lfs_newseg(fs);
repeat = 1;
@@ -684,11 +724,13 @@ lfs_initseg(fs)
ssp = sp->segsum;
ssp->ss_next = fs->lfs_nextseg;
ssp->ss_nfinfo = ssp->ss_ninos = 0;
+ ssp->ss_magic = SS_MAGIC;
/* Set pointer to first FINFO, initialize it. */
- sp->fip = (struct finfo *)(sp->segsum + sizeof(SEGSUM));
+ sp->fip = (struct finfo *)((caddr_t)sp->segsum + sizeof(SEGSUM));
sp->fip->fi_nblocks = 0;
sp->start_lbp = &sp->fip->fi_blocks[0];
+ sp->fip->fi_lastlength = 0;
sp->seg_bytes_left -= LFS_SUMMARY_SIZE;
sp->sum_bytes_left = LFS_SUMMARY_SIZE - sizeof(SEGSUM);
@@ -750,9 +792,8 @@ lfs_writeseg(fs, sp)
SEGUSE *sup;
SEGSUM *ssp;
dev_t i_dev;
- size_t size;
u_long *datap, *dp;
- int ch_per_blk, do_again, i, nblocks, num, s;
+ int do_again, i, nblocks, s;
int (*strategy)__P((struct vop_strategy_args *));
struct vop_strategy_args vop_strategy_a;
u_short ninos;
@@ -766,12 +807,16 @@ lfs_writeseg(fs, sp)
if ((nblocks = sp->cbpp - sp->bpp) == 1)
return (0);
- ssp = (SEGSUM *)sp->segsum;
-
/* Update the segment usage information. */
LFS_SEGENTRY(sup, fs, sp->seg_number, bp);
+
+ /* Loop through all blocks, except the segment summary. */
+ for (bpp = sp->bpp; ++bpp < sp->cbpp; )
+ sup->su_nbytes += (*bpp)->b_bcount;
+
+ ssp = (SEGSUM *)sp->segsum;
+
ninos = (ssp->ss_ninos + INOPB(fs) - 1) / INOPB(fs);
- sup->su_nbytes += nblocks - 1 - ninos << fs->lfs_bshift;
sup->su_nbytes += ssp->ss_ninos * sizeof(struct dinode);
sup->su_nbytes += LFS_SUMMARY_SIZE;
sup->su_lastmod = time.tv_sec;
@@ -824,23 +869,21 @@ lfs_writeseg(fs, sp)
* easily make the buffers contiguous in kernel memory and if that's
* fast enough.
*/
- ch_per_blk = MAXPHYS / fs->lfs_bsize;
for (bpp = sp->bpp, i = nblocks; i;) {
- num = ch_per_blk;
- if (num > i)
- num = i;
- i -= num;
- size = num * fs->lfs_bsize;
-
cbp = lfs_newbuf(VTOI(fs->lfs_ivnode)->i_devvp,
- (*bpp)->b_blkno, size);
+ (*bpp)->b_blkno, MAXPHYS);
cbp->b_dev = i_dev;
cbp->b_flags |= B_ASYNC | B_BUSY;
+ cbp->b_bcount = 0;
s = splbio();
++fs->lfs_iocount;
- for (p = cbp->b_data; num--;) {
- bp = *bpp++;
+ for (p = cbp->b_data; i && cbp->b_bcount < MAXPHYS; i--) {
+ bp = *bpp;
+ if (bp->b_bcount > (MAXPHYS - cbp->b_bcount))
+ break;
+ bpp++;
+
/*
* Fake buffers from the cleaner are marked as B_INVAL.
* We need to copy the data from user space rather than
@@ -853,6 +896,7 @@ lfs_writeseg(fs, sp)
} else
bcopy(bp->b_data, p, bp->b_bcount);
p += bp->b_bcount;
+ cbp->b_bcount += bp->b_bcount;
if (bp->b_flags & B_LOCKED)
--locked_queue_count;
bp->b_flags &= ~(B_ERROR | B_READ | B_DELWRI |
@@ -872,7 +916,6 @@ lfs_writeseg(fs, sp)
}
++cbp->b_vp->v_numoutput;
splx(s);
- cbp->b_bcount = p - (char *)cbp->b_data;
/*
* XXXX This is a gross and disgusting hack. Since these
* buffers are physically addressed, they hang off the
@@ -992,7 +1035,7 @@ lfs_match_tindir(fs, bp)
struct buf *
lfs_newbuf(vp, daddr, size)
struct vnode *vp;
- daddr_t daddr;
+ ufs_daddr_t daddr;
size_t size;
{
struct buf *bp;
@@ -1059,7 +1102,7 @@ lfs_supercallback(bp)
void
lfs_shellsort(bp_array, lb_array, nmemb)
struct buf **bp_array;
- daddr_t *lb_array;
+ ufs_daddr_t *lb_array;
register int nmemb;
{
static int __rsshell_increments[] = { 4, 1, 0 };
@@ -1088,24 +1131,36 @@ lfs_shellsort(bp_array, lb_array, nmemb)
lfs_vref(vp)
register struct vnode *vp;
{
+ struct proc *p = curproc; /* XXX */
- if (vp->v_flag & VXLOCK)
+ if (vp->v_flag & VXLOCK) /* XXX */
return(1);
- return (vget(vp, 0));
+ return (vget(vp, 0, p));
}
+/*
+ * This is vrele except that we do not want to VOP_INACTIVE this vnode. We
+ * inline vrele here to avoid the vn_lock and VOP_INACTIVE call at the end.
+ */
void
lfs_vunref(vp)
register struct vnode *vp;
{
- extern int lfs_no_inactive;
-
+ struct proc *p = curproc; /* XXX */
+ extern struct simplelock vnode_free_list_slock; /* XXX */
+ extern TAILQ_HEAD(freelst, vnode) vnode_free_list; /* XXX */
+
+ simple_lock(&vp->v_interlock);
+ vp->v_usecount--;
+ if (vp->v_usecount > 0) {
+ simple_unlock(&vp->v_interlock);
+ return;
+ }
/*
- * This is vrele except that we do not want to VOP_INACTIVE
- * this vnode. Rather than inline vrele here, we use a global
- * flag to tell lfs_inactive not to run. Yes, its gross.
+ * insert at tail of LRU list
*/
- lfs_no_inactive = 1;
- vrele(vp);
- lfs_no_inactive = 0;
+ simple_lock(&vnode_free_list_slock);
+ TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
+ simple_unlock(&vnode_free_list_slock);
+ simple_unlock(&vp->v_interlock);
}
diff --git a/sys/ufs/lfs/lfs_subr.c b/sys/ufs/lfs/lfs_subr.c
index afcd8c2..c839622 100644
--- a/sys/ufs/lfs/lfs_subr.c
+++ b/sys/ufs/lfs/lfs_subr.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)lfs_subr.c 8.2 (Berkeley) 9/21/93
+ * @(#)lfs_subr.c 8.4 (Berkeley) 5/8/95
*/
#include <sys/param.h>
@@ -63,13 +63,13 @@ lfs_blkatoff(ap)
register struct lfs *fs;
struct inode *ip;
struct buf *bp;
- daddr_t lbn;
+ ufs_daddr_t lbn;
int bsize, error;
ip = VTOI(ap->a_vp);
fs = ip->i_lfs;
lbn = lblkno(fs, ap->a_offset);
- bsize = blksize(fs);
+ bsize = blksize(fs, ip, lbn);
*ap->a_bpp = NULL;
if (error = bread(ap->a_vp, lbn, bsize, NOCRED, &bp)) {
@@ -109,7 +109,8 @@ lfs_seglock(fs, flags)
sp = fs->lfs_sp = malloc(sizeof(struct segment), M_SEGMENT, M_WAITOK);
sp->bpp = malloc(((LFS_SUMMARY_SIZE - sizeof(SEGSUM)) /
- sizeof(daddr_t) + 1) * sizeof(struct buf *), M_SEGMENT, M_WAITOK);
+ sizeof(ufs_daddr_t) + 1) * sizeof(struct buf *),
+ M_SEGMENT, M_WAITOK);
sp->seg_flags = flags;
sp->vp = NULL;
(void) lfs_initseg(fs);
diff --git a/sys/ufs/lfs/lfs_syscalls.c b/sys/ufs/lfs/lfs_syscalls.c
index 666595e..c6034e2 100644
--- a/sys/ufs/lfs/lfs_syscalls.c
+++ b/sys/ufs/lfs/lfs_syscalls.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)lfs_syscalls.c 8.5 (Berkeley) 4/20/94
+ * @(#)lfs_syscalls.c 8.10 (Berkeley) 5/14/95
*/
#include <sys/param.h>
@@ -64,6 +64,10 @@ if (sp->sum_bytes_left < (s)) { \
}
struct buf *lfs_fakebuf __P((struct vnode *, int, size_t, caddr_t));
+int debug_cleaner = 0;
+int clean_vnlocked = 0;
+int clean_inlocked = 0;
+
/*
* lfs_markv:
*
@@ -99,7 +103,7 @@ lfs_markv(p, uap, retval)
fsid_t fsid;
void *start;
ino_t lastino;
- daddr_t b_daddr, v_daddr;
+ ufs_daddr_t b_daddr, v_daddr;
u_long bsize;
int cnt, error;
@@ -108,7 +112,7 @@ lfs_markv(p, uap, retval)
if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t)))
return (error);
- if ((mntp = getvfs(&fsid)) == NULL)
+ if ((mntp = vfs_getvfs(&fsid)) == NULL)
return (EINVAL);
cnt = uap->blkcnt;
@@ -135,7 +139,7 @@ lfs_markv(p, uap, retval)
if (sp->fip->fi_nblocks == 0) {
DEC_FINFO(sp);
sp->sum_bytes_left +=
- sizeof(FINFO) - sizeof(daddr_t);
+ sizeof(FINFO) - sizeof(ufs_daddr_t);
} else {
lfs_updatemeta(sp);
BUMP_FIP(sp);
@@ -147,7 +151,7 @@ lfs_markv(p, uap, retval)
/* Start a new file */
CHECK_SEG(sizeof(FINFO));
- sp->sum_bytes_left -= sizeof(FINFO) - sizeof(daddr_t);
+ sp->sum_bytes_left -= sizeof(FINFO) - sizeof(ufs_daddr_t);
INC_FINFO(sp);
sp->start_lbp = &sp->fip->fi_blocks[0];
sp->vp = NULL;
@@ -172,6 +176,7 @@ lfs_markv(p, uap, retval)
#ifdef DIAGNOSTIC
printf("lfs_markv: VFS_VGET failed (%d)\n",
blkp->bi_inode);
+ panic("lfs_markv VFS_VGET FAILED");
#endif
lastino = LFS_UNUSED_INUM;
v_daddr = LFS_UNUSED_DADDR;
@@ -202,7 +207,7 @@ lfs_markv(p, uap, retval)
bp = getblk(vp, blkp->bi_lbn, bsize, 0, 0);
if (!(bp->b_flags & (B_DELWRI | B_DONE | B_CACHE)) &&
(error = copyin(blkp->bi_bp, bp->b_data,
- bsize)))
+ blkp->bi_size)))
goto err2;
if (error = VOP_BWRITE(bp))
goto err2;
@@ -213,7 +218,7 @@ lfs_markv(p, uap, retval)
if (sp->fip->fi_nblocks == 0) {
DEC_FINFO(sp);
sp->sum_bytes_left +=
- sizeof(FINFO) - sizeof(daddr_t);
+ sizeof(FINFO) - sizeof(ufs_daddr_t);
} else
lfs_updatemeta(sp);
@@ -267,10 +272,11 @@ lfs_bmapv(p, uap, retval)
{
BLOCK_INFO *blkp;
struct mount *mntp;
+ struct ufsmount *ump;
struct vnode *vp;
fsid_t fsid;
void *start;
- daddr_t daddr;
+ ufs_daddr_t daddr;
int cnt, error, step;
if (error = suser(p->p_ucred, &p->p_acflag))
@@ -278,7 +284,7 @@ lfs_bmapv(p, uap, retval)
if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t)))
return (error);
- if ((mntp = getvfs(&fsid)) == NULL)
+ if ((mntp = vfs_getvfs(&fsid)) == NULL)
return (EINVAL);
cnt = uap->blkcnt;
@@ -291,10 +297,18 @@ lfs_bmapv(p, uap, retval)
for (step = cnt; step--; ++blkp) {
if (blkp->bi_lbn == LFS_UNUSED_LBN)
continue;
- /* Could be a deadlock ? */
- if (VFS_VGET(mntp, blkp->bi_inode, &vp))
+ /*
+ * A regular call to VFS_VGET could deadlock
+ * here. Instead, we try an unlocked access.
+ */
+ ump = VFSTOUFS(mntp);
+ if ((vp =
+ ufs_ihashlookup(ump->um_dev, blkp->bi_inode)) != NULL) {
+ if (VOP_BMAP(vp, blkp->bi_lbn, NULL, &daddr, NULL))
+ daddr = LFS_UNUSED_DADDR;
+ } else if (VFS_VGET(mntp, blkp->bi_inode, &vp))
daddr = LFS_UNUSED_DADDR;
- else {
+ else {
if (VOP_BMAP(vp, blkp->bi_lbn, NULL, &daddr, NULL))
daddr = LFS_UNUSED_DADDR;
vput(vp);
@@ -337,7 +351,7 @@ lfs_segclean(p, uap, retval)
if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t)))
return (error);
- if ((mntp = getvfs(&fsid)) == NULL)
+ if ((mntp = vfs_getvfs(&fsid)) == NULL)
return (EINVAL);
fs = VFSTOUFS(mntp)->um_lfs;
@@ -402,14 +416,14 @@ lfs_segwait(p, uap, retval)
if (fsid == (fsid_t)-1)
addr = &lfs_allclean_wakeup;
else {
- if ((mntp = getvfs(&fsid)) == NULL)
+ if ((mntp = vfs_getvfs(&fsid)) == NULL)
return (EINVAL);
addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg;
}
#else
if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t)))
return (error);
- if ((mntp = getvfs(&fsid)) == NULL)
+ if ((mntp = vfs_getvfs(&fsid)) == NULL)
addr = &lfs_allclean_wakeup;
else
addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg;
@@ -441,7 +455,7 @@ int
lfs_fastvget(mp, ino, daddr, vpp, dinp)
struct mount *mp;
ino_t ino;
- daddr_t daddr;
+ ufs_daddr_t daddr;
struct vnode **vpp;
struct dinode *dinp;
{
@@ -462,14 +476,12 @@ lfs_fastvget(mp, ino, daddr, vpp, dinp)
if ((*vpp = ufs_ihashlookup(dev, ino)) != NULL) {
lfs_vref(*vpp);
if ((*vpp)->v_flag & VXLOCK)
- printf ("Cleaned vnode VXLOCKED\n");
+ clean_vnlocked++;
ip = VTOI(*vpp);
- if (ip->i_flags & IN_LOCKED)
- printf("cleaned vnode locked\n");
- if (!(ip->i_flag & IN_MODIFIED)) {
+ if (lockstatus(&ip->i_lock))
+ clean_inlocked++;
+ if (!(ip->i_flag & IN_MODIFIED))
++ump->um_lfs->lfs_uinodes;
- ip->i_flag |= IN_MODIFIED;
- }
ip->i_flag |= IN_MODIFIED;
return (0);
}
@@ -522,9 +534,6 @@ lfs_fastvget(mp, ino, daddr, vpp, dinp)
brelse(bp);
}
- /* Inode was just read from user space or disk, make sure it's locked */
- ip->i_flag |= IN_LOCKED;
-
/*
* Initialize the vnode from the inode, check for aliases. In all
* cases re-init ip, the underlying vnode/inode may have changed.
diff --git a/sys/ufs/lfs/lfs_vfsops.c b/sys/ufs/lfs/lfs_vfsops.c
index 0c8186e..6f61ef8 100644
--- a/sys/ufs/lfs/lfs_vfsops.c
+++ b/sys/ufs/lfs/lfs_vfsops.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)lfs_vfsops.c 8.7 (Berkeley) 4/16/94
+ * @(#)lfs_vfsops.c 8.20 (Berkeley) 6/10/95
*/
#include <sys/param.h>
@@ -73,12 +73,42 @@ struct vfsops lfs_vfsops = {
lfs_fhtovp,
lfs_vptofh,
lfs_init,
+ lfs_sysctl,
};
-int
+/*
+ * Called by main() when ufs is going to be mounted as root.
+ */
lfs_mountroot()
{
- panic("lfs_mountroot"); /* XXX -- implement */
+ extern struct vnode *rootvp;
+ struct fs *fs;
+ struct mount *mp;
+ struct proc *p = curproc; /* XXX */
+ int error;
+
+ /*
+ * Get vnodes for swapdev and rootdev.
+ */
+ if ((error = bdevvp(swapdev, &swapdev_vp)) ||
+ (error = bdevvp(rootdev, &rootvp))) {
+ printf("lfs_mountroot: can't setup bdevvp's");
+ return (error);
+ }
+ if (error = vfs_rootmountalloc("lfs", "root_device", &mp))
+ return (error);
+ if (error = lfs_mountfs(rootvp, mp, p)) {
+ mp->mnt_vfc->vfc_refcount--;
+ vfs_unbusy(mp, p);
+ free(mp, M_MOUNT);
+ return (error);
+ }
+ simple_lock(&mountlist_slock);
+ CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
+ simple_unlock(&mountlist_slock);
+ (void)lfs_statfs(mp, &mp->mnt_stat, p);
+ vfs_unbusy(mp, p);
+ return (0);
}
/*
@@ -99,6 +129,7 @@ lfs_mount(mp, path, data, ndp, p)
register struct lfs *fs; /* LFS */
u_int size;
int error;
+ mode_t accessmode;
if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
return (error);
@@ -113,15 +144,23 @@ lfs_mount(mp, path, data, ndp, p)
*/
if (mp->mnt_flag & MNT_UPDATE) {
ump = VFSTOUFS(mp);
-#ifdef NOTLFS /* LFS */
- fs = ump->um_fs;
- if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0)
- fs->fs_ronly = 0;
-#else
- fs = ump->um_lfs;
- if (fs->lfs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0)
+ if (fs->lfs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) {
+ /*
+ * If upgrade to read-write by non-root, then verify
+ * that user has necessary permissions on the device.
+ */
+ if (p->p_ucred->cr_uid != 0) {
+ vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY,
+ p);
+ if (error = VOP_ACCESS(ump->um_devvp,
+ VREAD | VWRITE, p->p_ucred, p)) {
+ VOP_UNLOCK(ump->um_devvp, 0, p);
+ return (error);
+ }
+ VOP_UNLOCK(ump->um_devvp, 0, p);
+ }
fs->lfs_ronly = 0;
-#endif
+ }
if (args.fspec == 0) {
/*
* Process export requests.
@@ -145,6 +184,21 @@ lfs_mount(mp, path, data, ndp, p)
vrele(devvp);
return (ENXIO);
}
+ /*
+ * If mount by non-root, then verify that user has necessary
+ * permissions on the device.
+ */
+ if (p->p_ucred->cr_uid != 0) {
+ accessmode = VREAD;
+ if ((mp->mnt_flag & MNT_RDONLY) == 0)
+ accessmode |= VWRITE;
+ vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
+ if (error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) {
+ vput(devvp);
+ return (error);
+ }
+ VOP_UNLOCK(devvp, 0, p);
+ }
if ((mp->mnt_flag & MNT_UPDATE) == 0)
error = lfs_mountfs(devvp, mp, p); /* LFS */
else {
@@ -199,7 +253,9 @@ lfs_mountfs(devvp, mp, p)
struct partinfo dpart;
dev_t dev;
int error, i, ronly, size;
+ struct ucred *cred;
+ cred = p ? p->p_ucred : NOCRED;
/*
* Disallow multiple mounts of the same device.
* Disallow mounting of a device that is currently in use
@@ -210,14 +266,14 @@ lfs_mountfs(devvp, mp, p)
return (error);
if (vcount(devvp) > 1 && devvp != rootvp)
return (EBUSY);
- if (error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0))
+ if (error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0))
return (error);
ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p))
return (error);
- if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
+ if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0)
size = DEV_BSIZE;
else {
size = dpart.disklab->d_secsize;
@@ -234,7 +290,7 @@ lfs_mountfs(devvp, mp, p)
ump = NULL;
/* Read in the superblock. */
- if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, NOCRED, &bp))
+ if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, cred, &bp))
goto out;
fs = (struct lfs *)bp->b_data;
@@ -272,7 +328,8 @@ lfs_mountfs(devvp, mp, p)
dev = devvp->v_rdev;
mp->mnt_data = (qaddr_t)ump;
mp->mnt_stat.f_fsid.val[0] = (long)dev;
- mp->mnt_stat.f_fsid.val[1] = MOUNT_LFS;
+ mp->mnt_stat.f_fsid.val[1] = lfs_mount_type;
+ mp->mnt_maxsymlinklen = fs->lfs_maxsymlinklen;
mp->mnt_flag |= MNT_LOCAL;
ump->um_mountp = mp;
ump->um_dev = dev;
@@ -300,7 +357,7 @@ lfs_mountfs(devvp, mp, p)
out:
if (bp)
brelse(bp);
- (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
+ (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
if (ump) {
free(ump->um_lfs, M_UFSMNT);
free(ump, M_UFSMNT);
@@ -323,11 +380,8 @@ lfs_unmount(mp, mntflags, p)
int i, error, flags, ronly;
flags = 0;
- if (mntflags & MNT_FORCE) {
- if (!doforce || (mp->mnt_flag & MNT_ROOTFS))
- return (EINVAL);
+ if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
- }
ump = VFSTOUFS(mp);
fs = ump->um_lfs;
@@ -383,17 +437,23 @@ lfs_statfs(mp, sbp, p)
fs = ump->um_lfs;
if (fs->lfs_magic != LFS_MAGIC)
panic("lfs_statfs: magic");
- sbp->f_type = MOUNT_LFS;
- sbp->f_bsize = fs->lfs_bsize;
+ sbp->f_bsize = fs->lfs_fsize;
sbp->f_iosize = fs->lfs_bsize;
- sbp->f_blocks = dbtofsb(fs,fs->lfs_dsize);
- sbp->f_bfree = dbtofsb(fs, fs->lfs_bfree);
- sbp->f_bavail = (fs->lfs_dsize * (100 - fs->lfs_minfree) / 100) -
- (fs->lfs_dsize - fs->lfs_bfree);
- sbp->f_bavail = dbtofsb(fs, sbp->f_bavail);
+ sbp->f_blocks = dbtofrags(fs,fs->lfs_dsize);
+ sbp->f_bfree = dbtofrags(fs, fs->lfs_bfree);
+ /*
+ * To compute the available space. Subtract the minimum free
+ * from the total number of blocks in the file system. Set avail
+ * to the smaller of this number and fs->lfs_bfree.
+ */
+ sbp->f_bavail = fs->lfs_dsize * (100 - fs->lfs_minfree) / 100;
+ sbp->f_bavail =
+ sbp->f_bavail > fs->lfs_bfree ? fs->lfs_bfree : sbp->f_bavail;
+ sbp->f_bavail = dbtofrags(fs, sbp->f_bavail);
sbp->f_files = fs->lfs_nfiles;
sbp->f_ffree = sbp->f_bfree * INOPB(fs);
if (sbp != &mp->mnt_stat) {
+ sbp->f_type = mp->mnt_vfc->vfc_typenum;
bcopy((caddr_t)mp->mnt_stat.f_mntonname,
(caddr_t)&sbp->f_mntonname[0], MNAMELEN);
bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
@@ -442,7 +502,7 @@ lfs_vget(mp, ino, vpp)
struct ifile *ifp;
struct vnode *vp;
struct ufsmount *ump;
- daddr_t daddr;
+ ufs_daddr_t daddr;
dev_t dev;
int error;
@@ -571,3 +631,17 @@ lfs_vptofh(vp, fhp)
ufhp->ufid_gen = ip->i_gen;
return (0);
}
+
+/*
+ * Initialize the filesystem, most work done by ufs_init.
+ */
+int lfs_mount_type;
+
+int
+lfs_init(vfsp)
+ struct vfsconf *vfsp;
+{
+
+ lfs_mount_type = vfsp->vfc_typenum;
+ return (ufs_init(vfsp));
+}
diff --git a/sys/ufs/lfs/lfs_vnops.c b/sys/ufs/lfs/lfs_vnops.c
index fc6bd48..721d6f2 100644
--- a/sys/ufs/lfs/lfs_vnops.c
+++ b/sys/ufs/lfs/lfs_vnops.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1986, 1989, 1991, 1993
+ * Copyright (c) 1986, 1989, 1991, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)lfs_vnops.c 8.5 (Berkeley) 12/30/93
+ * @(#)lfs_vnops.c 8.13 (Berkeley) 6/10/95
*/
#include <sys/param.h>
@@ -67,6 +67,7 @@ struct vnodeopv_entry_desc lfs_vnodeop_entries[] = {
{ &vop_default_desc, vn_default_error },
{ &vop_lookup_desc, ufs_lookup }, /* lookup */
{ &vop_create_desc, ufs_create }, /* create */
+ { &vop_whiteout_desc, ufs_whiteout }, /* whiteout */
{ &vop_mknod_desc, ufs_mknod }, /* mknod */
{ &vop_open_desc, ufs_open }, /* open */
{ &vop_close_desc, lfs_close }, /* close */
@@ -75,8 +76,10 @@ struct vnodeopv_entry_desc lfs_vnodeop_entries[] = {
{ &vop_setattr_desc, ufs_setattr }, /* setattr */
{ &vop_read_desc, lfs_read }, /* read */
{ &vop_write_desc, lfs_write }, /* write */
+ { &vop_lease_desc, ufs_lease_check }, /* lease */
{ &vop_ioctl_desc, ufs_ioctl }, /* ioctl */
{ &vop_select_desc, ufs_select }, /* select */
+ { &vop_revoke_desc, ufs_revoke }, /* revoke */
{ &vop_mmap_desc, ufs_mmap }, /* mmap */
{ &vop_fsync_desc, lfs_fsync }, /* fsync */
{ &vop_seek_desc, ufs_seek }, /* seek */
@@ -89,8 +92,8 @@ struct vnodeopv_entry_desc lfs_vnodeop_entries[] = {
{ &vop_readdir_desc, ufs_readdir }, /* readdir */
{ &vop_readlink_desc, ufs_readlink }, /* readlink */
{ &vop_abortop_desc, ufs_abortop }, /* abortop */
- { &vop_inactive_desc, lfs_inactive }, /* inactive */
- { &vop_reclaim_desc, ufs_reclaim }, /* reclaim */
+ { &vop_inactive_desc, ufs_inactive }, /* inactive */
+ { &vop_reclaim_desc, lfs_reclaim }, /* reclaim */
{ &vop_lock_desc, ufs_lock }, /* lock */
{ &vop_unlock_desc, ufs_unlock }, /* unlock */
{ &vop_bmap_desc, ufs_bmap }, /* bmap */
@@ -123,8 +126,10 @@ struct vnodeopv_entry_desc lfs_specop_entries[] = {
{ &vop_setattr_desc, ufs_setattr }, /* setattr */
{ &vop_read_desc, ufsspec_read }, /* read */
{ &vop_write_desc, ufsspec_write }, /* write */
+ { &vop_lease_desc, spec_lease_check }, /* lease */
{ &vop_ioctl_desc, spec_ioctl }, /* ioctl */
{ &vop_select_desc, spec_select }, /* select */
+ { &vop_revoke_desc, spec_revoke }, /* revoke */
{ &vop_mmap_desc, spec_mmap }, /* mmap */
{ &vop_fsync_desc, spec_fsync }, /* fsync */
{ &vop_seek_desc, spec_seek }, /* seek */
@@ -137,8 +142,8 @@ struct vnodeopv_entry_desc lfs_specop_entries[] = {
{ &vop_readdir_desc, spec_readdir }, /* readdir */
{ &vop_readlink_desc, spec_readlink }, /* readlink */
{ &vop_abortop_desc, spec_abortop }, /* abortop */
- { &vop_inactive_desc, lfs_inactive }, /* inactive */
- { &vop_reclaim_desc, ufs_reclaim }, /* reclaim */
+ { &vop_inactive_desc, ufs_inactive }, /* inactive */
+ { &vop_reclaim_desc, lfs_reclaim }, /* reclaim */
{ &vop_lock_desc, ufs_lock }, /* lock */
{ &vop_unlock_desc, ufs_unlock }, /* unlock */
{ &vop_bmap_desc, spec_bmap }, /* bmap */
@@ -172,8 +177,10 @@ struct vnodeopv_entry_desc lfs_fifoop_entries[] = {
{ &vop_setattr_desc, ufs_setattr }, /* setattr */
{ &vop_read_desc, ufsfifo_read }, /* read */
{ &vop_write_desc, ufsfifo_write }, /* write */
+ { &vop_lease_desc, fifo_lease_check }, /* lease */
{ &vop_ioctl_desc, fifo_ioctl }, /* ioctl */
{ &vop_select_desc, fifo_select }, /* select */
+ { &vop_revoke_desc, fifo_revoke }, /* revoke */
{ &vop_mmap_desc, fifo_mmap }, /* mmap */
{ &vop_fsync_desc, fifo_fsync }, /* fsync */
{ &vop_seek_desc, fifo_seek }, /* seek */
@@ -186,8 +193,8 @@ struct vnodeopv_entry_desc lfs_fifoop_entries[] = {
{ &vop_readdir_desc, fifo_readdir }, /* readdir */
{ &vop_readlink_desc, fifo_readlink }, /* readlink */
{ &vop_abortop_desc, fifo_abortop }, /* abortop */
- { &vop_inactive_desc, lfs_inactive }, /* inactive */
- { &vop_reclaim_desc, ufs_reclaim }, /* reclaim */
+ { &vop_inactive_desc, ufs_inactive }, /* inactive */
+ { &vop_reclaim_desc, lfs_reclaim }, /* reclaim */
{ &vop_lock_desc, ufs_lock }, /* lock */
{ &vop_unlock_desc, ufs_unlock }, /* unlock */
{ &vop_bmap_desc, fifo_bmap }, /* bmap */
@@ -371,10 +378,10 @@ lfs_link(ap)
{
int ret;
- SET_DIROP(VTOI(ap->a_vp)->i_lfs);
- MARK_VNODE(ap->a_vp);
+ SET_DIROP(VTOI(ap->a_tdvp)->i_lfs);
+ MARK_VNODE(ap->a_tdvp);
ret = ufs_link(ap);
- SET_ENDOP(VTOI(ap->a_vp)->i_lfs);
+ SET_ENDOP(VTOI(ap->a_tdvp)->i_lfs);
return (ret);
}
@@ -422,9 +429,12 @@ lfs_getattr(ap)
vap->va_gid = ip->i_gid;
vap->va_rdev = (dev_t)ip->i_rdev;
vap->va_size = ip->i_din.di_size;
- vap->va_atime = ip->i_atime;
- vap->va_mtime = ip->i_mtime;
- vap->va_ctime = ip->i_ctime;
+ vap->va_atime.ts_sec = ip->i_atime;
+ vap->va_atime.ts_nsec = ip->i_atimensec;
+ vap->va_mtime.ts_sec = ip->i_mtime;
+ vap->va_mtime.ts_nsec = ip->i_mtimensec;
+ vap->va_ctime.ts_sec = ip->i_ctime;
+ vap->va_ctime.ts_nsec = ip->i_ctimensec;
vap->va_flags = ip->i_flags;
vap->va_gen = ip->i_gen;
/* this doesn't belong here */
@@ -460,28 +470,33 @@ lfs_close(ap)
register struct inode *ip = VTOI(vp);
int mod;
- if (vp->v_usecount > 1 && !(ip->i_flag & IN_LOCKED)) {
+ simple_lock(&vp->v_interlock);
+ if (vp->v_usecount > 1) {
mod = ip->i_flag & IN_MODIFIED;
ITIMES(ip, &time, &time);
if (!mod && ip->i_flag & IN_MODIFIED)
ip->i_lfs->lfs_uinodes++;
}
+ simple_unlock(&vp->v_interlock);
return (0);
}
/*
- * Stub inactive routine that avoid calling ufs_inactive in some cases.
+ * Reclaim an inode so that it can be used for other purposes.
*/
-int lfs_no_inactive = 0;
-
int
-lfs_inactive(ap)
- struct vop_inactive_args /* {
+lfs_reclaim(ap)
+ struct vop_reclaim_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
-
- if (lfs_no_inactive)
- return (0);
- return (ufs_inactive(ap));
+ register struct vnode *vp = ap->a_vp;
+ int error;
+
+ if (error = ufs_reclaim(vp, ap->a_p))
+ return (error);
+ FREE(vp->v_data, M_LFSNODE);
+ vp->v_data = NULL;
+ return (0);
}
OpenPOWER on IntegriCloud