-/* ffs_inode.c 4.13 82/06/29 */
+/* ffs_inode.c 4.23 82/08/10 */
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/conf.h"
#include "../h/buf.h"
#include "../h/inline.h"
+#ifdef QUOTA
+#include "../h/quota.h"
+#endif
#define INOHSZ 63
#if ((INOHSZ&(INOHSZ-1)) == 0)
register struct fs *fs;
ino_t ino;
{
- register struct inode *ip; /* known to be r11 - see "asm" below */
- register union ihead *ih; /* known to be r10 - see "asm" below */
+ register struct inode *ip;
+ register union ihead *ih;
register struct mount *mp;
register struct buf *bp;
register struct dinode *dp;
* but that doesn't matter), and put it on the chain for
* its new (ino, dev) pair
*/
-#ifndef UNFAST
- asm("remque (r11),r0");
- asm("insque (r11),(r10)");
-#else
- /* remque */
- ip->i_back->i_forw = ip->i_forw;
- ip->i_forw->i_back = ip->i_back;
- /* insque */
- ip->i_forw = ih->ih_chain[0];
- ip->i_back = (struct inode *)ih;
- ih->ih_chain[0]->i_back = ip;
- ih->ih_chain[0] = ip;
+ remque(ip);
+ insque(ip, ih);
+#ifdef QUOTA
+ dqrele(ip->i_dquot);
#endif
ip->i_dev = dev;
ip->i_fs = fs;
* be misleading to leave it on its hash chain.
* 'iput' will take care of putting it back on the free list.
*/
-#ifndef UNFAST
- asm("remque (r11),r0");
-#else
- ip->i_back->i_forw = ip->i_forw;
- ip->i_forw->i_back = ip->i_back;
-#endif
+ remque(ip);
ip->i_forw = ip;
ip->i_back = ip;
/*
* (probably the two methods are interchangable)
*/
ip->i_number = 0;
+#ifdef QUOTA
+ ip->i_dquot = NODQUOT;
+#endif
iput(ip);
return(NULL);
}
dp += itoo(fs, ino);
ip->i_ic = dp->di_ic;
brelse(bp);
+#ifdef QUOTA
+ if (ip->i_mode == 0)
+ ip->i_dquot = NODQUOT;
+ else
+ ip->i_dquot = inoquota(ip);
+#endif
return (ip);
}
if (ip->i_count == 1) {
ip->i_flag |= ILOCK;
if (ip->i_nlink <= 0) {
- itrunc(ip);
+ itrunc(ip, 0);
mode = ip->i_mode;
ip->i_mode = 0;
+ ip->i_rdev = 0;
ip->i_flag |= IUPD|ICHG;
ifree(ip, ip->i_number, mode);
+#ifdef QUOTA
+ chkiq(ip->i_dev, ip, ip->i_uid, 0);
+ dqrele(ip->i_dquot);
+ ip->i_dquot = NODQUOT;
+#endif
}
IUPDAT(ip, &time, &time, 0);
iunlock(ip);
if (ip->i_flag&ICHG)
ip->i_ctime = time;
ip->i_flag &= ~(IUPD|IACC|ICHG);
+ dp = bp->b_un.b_dino + itoo(fp, ip->i_number);
+ dp->di_ic = ip->i_ic;
if (waitfor)
bwrite(bp);
else
}
/*
- * Free all the disk blocks associated
- * with the specified inode structure.
- * The blocks of the file are removed
- * in reverse order. This FILO
- * algorithm will tend to maintain
- * a contiguous free list much longer
- * than FIFO.
+ * Truncate the inode ip to at most
+ * length size. Free affected disk
+ * blocks -- the blocks of the file
+ * are removed in reverse order.
*/
-itrunc(ip)
+itrunc(ip, length)
register struct inode *ip;
+ register int length;
{
register i;
dev_t dev;
daddr_t bn;
struct inode itmp;
register struct fs *fs;
-
+#ifdef QUOTA
+ register long cnt = 0;
+ long tloop();
+#endif
+ /*
+ * Only plain files, directories and symbolic
+ * links contain blocks.
+ */
i = ip->i_mode & IFMT;
if (i != IFREG && i != IFDIR && i != IFLNK)
return;
+ if (ip->i_size <= length)
+ return;
+
/*
* Clean inode on disk before freeing blocks
* to insure no duplicates if system crashes.
*/
itmp = *ip;
- itmp.i_size = 0;
+ itmp.i_size = length;
for (i = 0; i < NDADDR; i++)
itmp.i_db[i] = 0;
for (i = 0; i < NIADDR; i++)
bn = ip->i_ib[NIADDR-1];
if (bn != (daddr_t)0) {
ip->i_ib[NIADDR - 1] = (daddr_t)0;
- tloop(ip, bn, 1);
+#ifdef QUOTA
+ cnt +=
+#endif
+ tloop(ip, bn, 1);
}
/*
* release single indirect blocks second
bn = ip->i_ib[i];
if (bn != (daddr_t)0) {
ip->i_ib[i] = (daddr_t)0;
- tloop(ip, bn, 0);
+#ifdef QUOTA
+ cnt +=
+#endif
+ tloop(ip, bn, 0);
}
}
/*
* finally release direct blocks
*/
for (i = NDADDR - 1; i>=0; i--) {
+ register size;
+
bn = ip->i_db[i];
if (bn == (daddr_t)0)
continue;
ip->i_db[i] = (daddr_t)0;
- fre(ip, bn, (off_t)blksize(fs, ip, i));
+ fre(ip, bn, size = (off_t)blksize(fs, ip, i));
+#ifdef QUOTA
+ cnt += size / DEV_BSIZE;
+#endif
}
ip->i_size = 0;
/*
* Inode was written and flags updated above.
* No need to modify flags here.
*/
+#ifdef QUOTA
+ (void) chkdq(ip, -cnt, 0);
+#endif
}
+#ifdef QUOTA
+long
+#endif
tloop(ip, bn, indflg)
register struct inode *ip;
daddr_t bn;
register daddr_t *bap;
register struct fs *fs;
daddr_t nb;
+#ifdef QUOTA
+ register long cnt = 0;
+#endif
bp = NULL;
fs = ip->i_fs;
nb = bap[i];
if (nb == (daddr_t)0)
continue;
- if (indflg)
- tloop(ip, nb, 0);
- else
+ if (indflg) {
+#ifdef QUOTA
+ cnt +=
+#endif
+ tloop(ip, nb, 0);
+ } else {
fre(ip, nb, fs->fs_bsize);
+#ifdef QUOTA
+ cnt += fs->fs_bsize / DEV_BSIZE;
+#endif
+ }
}
if (bp != NULL)
brelse(bp);
fre(ip, bn, fs->fs_bsize);
-}
-
-/*
- * Make a new file.
- */
-struct inode *
-maknode(mode)
- int mode;
-{
- register struct inode *ip;
- ino_t ipref;
-
- if ((mode & IFMT) == IFDIR)
- ipref = dirpref(u.u_pdir->i_fs);
- else
- ipref = u.u_pdir->i_number;
- ip = ialloc(u.u_pdir, ipref, mode);
- if (ip == NULL) {
- iput(u.u_pdir);
- return(NULL);
- }
- ip->i_flag |= IACC|IUPD|ICHG;
- if ((mode & IFMT) == 0)
- mode |= IFREG;
- ip->i_mode = mode & ~u.u_cmask;
- ip->i_nlink = 1;
- ip->i_uid = u.u_uid;
- ip->i_gid = u.u_pdir->i_gid;
-
- /*
- * Make sure inode goes to disk before directory entry.
- */
- iupdat(ip, &time, &time, 1);
- wdir(ip);
- if (u.u_error) {
- /*
- * write error occurred trying to update directory
- * so must deallocate the inode
- */
- ip->i_nlink = 0;
- ip->i_flag |= ICHG;
- iput(ip);
- return(NULL);
- }
- return(ip);
-}
-
-/*
- * Write a directory entry with
- * parameters left as side effects
- * to a call to namei.
- */
-wdir(ip)
- struct inode *ip;
-{
- register struct direct *dp, *ndp;
- struct fs *fs;
- struct buf *bp;
- int lbn, bn, base;
- int loc, dsize, spccnt, newsize;
- char *dirbuf;
-
- u.u_dent.d_ino = ip->i_number;
- u.u_segflg = 1;
- newsize = DIRSIZ(&u.u_dent);
- /*
- * if u.u_count == 0, a new directory block must be allocated.
- */
- if (u.u_count == 0) {
- u.u_dent.d_reclen = DIRBLKSIZ;
- u.u_count = newsize;
- u.u_base = (caddr_t)&u.u_dent;
- writei(u.u_pdir);
- iput(u.u_pdir);
- return;
- }
- /*
- * must read in an existing directory block
- * to prepare to place the new entry into it.
- */
- fs = u.u_pdir->i_fs;
- lbn = lblkno(fs, u.u_offset);
- base = blkoff(fs, u.u_offset);
- bn = fsbtodb(fs, bmap(u.u_pdir, lbn, B_WRITE, base + u.u_count));
- if (u.u_offset + u.u_count > u.u_pdir->i_size)
- u.u_pdir->i_size = u.u_offset + u.u_count;
- bp = bread(u.u_pdir->i_dev, bn, blksize(fs, u.u_pdir, lbn));
- if (bp->b_flags & B_ERROR) {
- brelse(bp);
- return;
- }
- dirbuf = bp->b_un.b_addr + base;
- dp = (struct direct *)dirbuf;
- dsize = DIRSIZ(dp);
- spccnt = dp->d_reclen - dsize;
- /*
- * if there is insufficient room to make an entry at this point
- * namei insures that compacting from u.u_offset for u.u_count
- * bytes will provide the necessary space.
- */
- for (loc = dp->d_reclen; loc < u.u_count; ) {
- ndp = (struct direct *)(dirbuf + loc);
- if (dp->d_ino == 0) {
- spccnt += dsize;
- } else {
- dp->d_reclen = dsize;
- dp = (struct direct *)((char *)dp + dsize);
- }
- dsize = DIRSIZ(ndp);
- spccnt += ndp->d_reclen - dsize;
- loc += ndp->d_reclen;
- bcopy(ndp, dp, dsize);
- }
- /*
- * Update the pointer fields in the previous entry (if any),
- * copy in the new entry, and write out the block.
- */
- if (dp->d_ino == 0) {
- if (spccnt + dsize < newsize)
- panic("wdir: compact failed");
- u.u_dent.d_reclen = spccnt + dsize;
- } else {
- if (spccnt < newsize)
- panic("wdir: compact failed");
- u.u_dent.d_reclen = spccnt;
- dp->d_reclen = dsize;
- dp = (struct direct *)((char *)dp + dsize);
- }
- bcopy(&u.u_dent, dp, newsize);
- bwrite(bp);
- u.u_pdir->i_flag |= IUPD|ICHG;
- iput(u.u_pdir);
+#ifdef QUOTA
+ cnt += fs->fs_bsize / DEV_BSIZE;
+ return(cnt);
+#endif
}
/*
*
* this is called from sumount()/sys3.c when dev is being unmounted
*/
+#ifdef QUOTA
+iflush(dev, iq)
+ dev_t dev;
+ struct inode *iq;
+#else
iflush(dev)
dev_t dev;
+#endif
{
- register struct inode *ip; /* known to be r11 - see 'asm' below */
+ register struct inode *ip;
register open = 0;
for (ip = inode; ip < inodeNINODE; ip++) {
+#ifdef QUOTA
+ if (ip != iq && ip->i_dev == dev)
+#else
if (ip->i_dev == dev)
+#endif
if (ip->i_count)
return(-1);
else {
-#ifndef UNFAST
- asm("remque (r11),r0");
-#else
- ip->i_back->i_forw = ip->i_forw;
- ip->i_forw->i_back = ip->i_back;
-#endif
+ remque(ip);
ip->i_forw = ip;
ip->i_back = ip;
/*
* infrequently, we would gain very little,
* while making the code bigger.
*/
+#ifdef QUOTA
+ dqrele(ip->i_dquot);
+ ip->i_dquot = NODQUOT;
+#endif
}
else if (ip->i_count && (ip->i_mode&IFMT)==IFBLK &&
ip->i_rdev == dev)