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