|
|
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: {
1.1.1.7 ! root 29: unsigned short * p;
! 30: struct buffer_head * bh;
! 31: int i, tmp;
! 32: int retry = 0;
1.1.1.3 root 33: #define DIRECT_BLOCK ((inode->i_size + 1023) >> 10)
1.1 root 34:
1.1.1.3 root 35: repeat:
36: for (i = DIRECT_BLOCK ; i < 7 ; i++) {
1.1.1.7 ! root 37: p = i + inode->u.minix_i.i_data;
! 38: if (!(tmp = *p))
! 39: continue;
! 40: bh = getblk(inode->i_dev,tmp,BLOCK_SIZE);
! 41: if (i < DIRECT_BLOCK) {
! 42: brelse(bh);
1.1.1.3 root 43: goto repeat;
1.1.1.7 ! root 44: }
! 45: if ((bh && bh->b_count != 1) || tmp != *p) {
! 46: retry = 1;
! 47: brelse(bh);
1.1.1.3 root 48: continue;
1.1.1.7 ! root 49: }
! 50: *p = 0;
! 51: inode->i_dirt = 1;
! 52: brelse(bh);
! 53: minix_free_block(inode->i_dev,tmp);
1.1 root 54: }
1.1.1.7 ! root 55: return retry;
1.1 root 56: }
57:
1.1.1.3 root 58: static int trunc_indirect(struct inode * inode, int offset, unsigned short * p)
1.1 root 59: {
1.1.1.7 ! root 60: struct buffer_head * bh;
! 61: int i, tmp;
! 62: struct buffer_head * ind_bh;
1.1.1.3 root 63: unsigned short * ind;
1.1.1.7 ! root 64: int retry = 0;
1.1.1.3 root 65: #define INDIRECT_BLOCK (DIRECT_BLOCK-offset)
66:
1.1.1.7 ! root 67: tmp = *p;
! 68: if (!tmp)
! 69: return 0;
! 70: ind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
! 71: if (tmp != *p) {
! 72: brelse(ind_bh);
! 73: return 1;
! 74: }
! 75: if (!ind_bh) {
! 76: *p = 0;
1.1.1.3 root 77: return 0;
1.1.1.7 ! root 78: }
1.1.1.3 root 79: repeat:
80: for (i = INDIRECT_BLOCK ; i < 512 ; i++) {
81: if (i < 0)
82: i = 0;
83: if (i < INDIRECT_BLOCK)
84: goto repeat;
1.1.1.7 ! root 85: ind = i+(unsigned short *) ind_bh->b_data;
! 86: tmp = *ind;
! 87: if (!tmp)
1.1.1.3 root 88: continue;
1.1.1.7 ! root 89: bh = getblk(inode->i_dev,tmp,BLOCK_SIZE);
! 90: if (i < INDIRECT_BLOCK) {
! 91: brelse(bh);
! 92: goto repeat;
! 93: }
! 94: if ((bh && bh->b_count != 1) || tmp != *ind) {
! 95: retry = 1;
! 96: brelse(bh);
! 97: continue;
! 98: }
! 99: *ind = 0;
! 100: ind_bh->b_dirt = 1;
! 101: brelse(bh);
! 102: minix_free_block(inode->i_dev,tmp);
1.1 root 103: }
1.1.1.7 ! root 104: ind = (unsigned short *) ind_bh->b_data;
1.1.1.3 root 105: for (i = 0; i < 512; i++)
106: if (*(ind++))
107: break;
1.1.1.7 ! root 108: if (i >= 512)
! 109: if (ind_bh->b_count != 1)
! 110: retry = 1;
! 111: else {
! 112: tmp = *p;
1.1.1.3 root 113: *p = 0;
1.1.1.7 ! root 114: minix_free_block(inode->i_dev,tmp);
! 115: }
! 116: brelse(ind_bh);
! 117: return retry;
1.1.1.3 root 118: }
119:
120: static int trunc_dindirect(struct inode * inode)
121: {
1.1.1.7 ! root 122: int i, tmp;
! 123: struct buffer_head * dind_bh;
! 124: unsigned short * dind, * p;
! 125: int retry = 0;
1.1.1.3 root 126: #define DINDIRECT_BLOCK ((DIRECT_BLOCK-(512+7))>>9)
127:
1.1.1.7 ! root 128: p = 8 + inode->u.minix_i.i_data;
! 129: if (!(tmp = *p))
1.1 root 130: return 0;
1.1.1.7 ! root 131: dind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
! 132: if (tmp != *p) {
! 133: brelse(dind_bh);
! 134: return 1;
! 135: }
! 136: if (!dind_bh) {
! 137: *p = 0;
! 138: return 0;
! 139: }
1.1.1.3 root 140: repeat:
141: for (i = DINDIRECT_BLOCK ; i < 512 ; i ++) {
142: if (i < 0)
143: i = 0;
144: if (i < DINDIRECT_BLOCK)
145: goto repeat;
1.1.1.7 ! root 146: dind = i+(unsigned short *) dind_bh->b_data;
! 147: retry |= trunc_indirect(inode,7+512+(i<<9),dind);
! 148: dind_bh->b_dirt = 1;
1.1.1.3 root 149: }
1.1.1.7 ! root 150: dind = (unsigned short *) dind_bh->b_data;
1.1.1.3 root 151: for (i = 0; i < 512; i++)
152: if (*(dind++))
153: break;
1.1.1.7 ! root 154: if (i >= 512)
! 155: if (dind_bh->b_count != 1)
! 156: retry = 1;
! 157: else {
! 158: tmp = *p;
! 159: *p = 0;
! 160: inode->i_dirt = 1;
! 161: minix_free_block(inode->i_dev,tmp);
! 162: }
! 163: brelse(dind_bh);
! 164: return retry;
1.1 root 165: }
1.1.1.3 root 166:
1.1 root 167: void minix_truncate(struct inode * inode)
168: {
1.1.1.7 ! root 169: int retry;
1.1 root 170:
171: if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
172: S_ISLNK(inode->i_mode)))
173: return;
1.1.1.3 root 174: while (1) {
1.1.1.7 ! root 175: retry = trunc_direct(inode);
! 176: retry |= trunc_indirect(inode,7,inode->u.minix_i.i_data+7);
! 177: retry |= trunc_dindirect(inode);
! 178: if (!retry)
1.1.1.3 root 179: break;
1.1 root 180: current->counter = 0;
181: schedule();
182: }
183: inode->i_mtime = inode->i_ctime = CURRENT_TIME;
1.1.1.3 root 184: inode->i_dirt = 1;
1.1 root 185: }
186:
187: /*
188: * Called when a inode is released. Note that this is different
189: * from minix_open: open gets called at every open, but release
190: * gets called only when /all/ the files are closed.
191: */
192: void minix_release(struct inode * inode, struct file * filp)
193: {
194: printk("minix_release not implemented\n");
195: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.