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