|
|
1.1 root 1: /*
2: * linux/fs/truncate.c
3: *
4: * (C) 1991 Linus Torvalds
5: */
6:
7: #include <linux/sched.h>
8: #include <linux/minix_fs.h>
9: #include <linux/tty.h>
10:
11: #include <errno.h>
12: #include <fcntl.h>
13: #include <sys/stat.h>
14:
1.1.1.3 ! root 15: /*
! 16: * Truncate has the most races in the whole filesystem: coding it is
! 17: * a pain in the a**. Especially as I don't do any locking...
! 18: *
! 19: * The code may look a bit weird, but that's just because I've tried to
! 20: * handle things like file-size changes in a somewhat graceful manner.
! 21: * Anyway, truncating a file at the same time somebody else writes to it
! 22: * is likely to result in pretty weird behaviour...
! 23: *
! 24: * The new code handles normal truncates (size = 0) as well as the more
! 25: * general case (size = XXX). I hope.
! 26: */
! 27:
! 28: static int trunc_direct(struct inode * inode)
1.1 root 29: {
30: int i;
1.1.1.3 ! root 31: int result = 0;
! 32: #define DIRECT_BLOCK ((inode->i_size + 1023) >> 10)
1.1 root 33:
1.1.1.3 ! root 34: repeat:
! 35: for (i = DIRECT_BLOCK ; i < 7 ; i++) {
! 36: if (i < DIRECT_BLOCK)
! 37: goto repeat;
! 38: if (!inode->i_data[i])
! 39: continue;
! 40: result = 1;
! 41: if (minix_free_block(inode->i_dev,inode->i_data[i]))
! 42: inode->i_data[i] = 0;
1.1 root 43: }
1.1.1.3 ! root 44: return result;
1.1 root 45: }
46:
1.1.1.3 ! root 47: static int trunc_indirect(struct inode * inode, int offset, unsigned short * p)
1.1 root 48: {
49: int i;
1.1.1.3 ! root 50: struct buffer_head * bh = NULL;
! 51: unsigned short * ind;
! 52: int result = 0;
! 53: #define INDIRECT_BLOCK (DIRECT_BLOCK-offset)
! 54:
! 55: if (*p)
! 56: bh = bread(inode->i_dev,*p);
! 57: if (!bh)
! 58: return 0;
! 59: repeat:
! 60: for (i = INDIRECT_BLOCK ; i < 512 ; i++) {
! 61: if (i < 0)
! 62: i = 0;
! 63: if (i < INDIRECT_BLOCK)
! 64: goto repeat;
! 65: ind = i+(unsigned short *) bh->b_data;
! 66: if (!*ind)
! 67: continue;
! 68: result = 1;
! 69: if (minix_free_block(inode->i_dev,*ind))
! 70: *ind = 0;
1.1 root 71: }
1.1.1.3 ! root 72: ind = (unsigned short *) bh->b_data;
! 73: for (i = 0; i < 512; i++)
! 74: if (*(ind++))
! 75: break;
! 76: brelse(bh);
! 77: if (i >= 512) {
! 78: result = 1;
! 79: if (minix_free_block(inode->i_dev,*p))
! 80: *p = 0;
! 81: }
! 82: return result;
! 83: }
! 84:
! 85: static int trunc_dindirect(struct inode * inode)
! 86: {
! 87: int i;
! 88: struct buffer_head * bh = NULL;
! 89: unsigned short * dind;
! 90: int result = 0;
! 91: #define DINDIRECT_BLOCK ((DIRECT_BLOCK-(512+7))>>9)
! 92:
! 93: if (inode->i_data[8])
! 94: bh = bread(inode->i_dev,inode->i_data[8]);
! 95: if (!bh)
1.1 root 96: return 0;
1.1.1.3 ! root 97: repeat:
! 98: for (i = DINDIRECT_BLOCK ; i < 512 ; i ++) {
! 99: if (i < 0)
! 100: i = 0;
! 101: if (i < DINDIRECT_BLOCK)
! 102: goto repeat;
! 103: dind = i+(unsigned short *) bh->b_data;
! 104: if (!*dind)
! 105: continue;
! 106: result |= trunc_indirect(inode,7+512+(i<<9),dind);
! 107: }
! 108: dind = (unsigned short *) bh->b_data;
! 109: for (i = 0; i < 512; i++)
! 110: if (*(dind++))
! 111: break;
! 112: brelse(bh);
! 113: if (i >= 512) {
! 114: result = 1;
! 115: if (minix_free_block(inode->i_dev,inode->i_data[8]))
! 116: inode->i_data[8] = 0;
! 117: }
! 118: return result;
1.1 root 119: }
1.1.1.3 ! root 120:
1.1 root 121: void minix_truncate(struct inode * inode)
122: {
1.1.1.3 ! root 123: int flag;
1.1 root 124:
125: if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
126: S_ISLNK(inode->i_mode)))
127: return;
1.1.1.3 ! root 128: if (inode->i_data[7] & 0xffff0000)
! 129: printk("BAD! minix inode has 16 high bits set\n");
! 130: while (1) {
! 131: flag = trunc_direct(inode);
! 132: flag |= trunc_indirect(inode,7,(unsigned short *)&inode->i_data[7]);
! 133: flag |= trunc_dindirect(inode);
! 134: if (!flag)
! 135: break;
1.1 root 136: current->counter = 0;
137: schedule();
138: }
139: inode->i_mtime = inode->i_ctime = CURRENT_TIME;
1.1.1.3 ! root 140: inode->i_dirt = 1;
1.1 root 141: }
142:
143: /*
144: * Called when a inode is released. Note that this is different
145: * from minix_open: open gets called at every open, but release
146: * gets called only when /all/ the files are closed.
147: */
148: void minix_release(struct inode * inode, struct file * filp)
149: {
150: printk("minix_release not implemented\n");
151: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.