diff options
Diffstat (limited to 'fs/xiafs/truncate.c')
-rw-r--r-- | fs/xiafs/truncate.c | 197 |
1 files changed, 0 insertions, 197 deletions
diff --git a/fs/xiafs/truncate.c b/fs/xiafs/truncate.c deleted file mode 100644 index bdb9d39be..000000000 --- a/fs/xiafs/truncate.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * linux/fs/xiafs/truncate.c - * - * Copyright (C) Q. Frank Xia, 1993. - * - * Based on Linus' minix/truncate.c - * Copyright (C) Linus Torvalds, 1991, 1992. - * - * This software may be redistributed per Linux Copyright. - */ - -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/xia_fs.h> -#include <linux/stat.h> -#include <linux/fcntl.h> - -#include "xiafs_mac.h" - -/* - * Linus' comment: - * - * Truncate has the most races in the whole filesystem: coding it is - * a pain in the a**. Especially as I don't do any locking... - * - * The code may look a bit weird, but that's just because I've tried to - * handle things like file-size changes in a somewhat graceful manner. - * Anyway, truncating a file at the same time somebody else writes to it - * is likely to result in pretty weird behaviour... - * - * The new code handles normal truncates (size = 0) as well as the more - * general case (size = XXX). I hope. - */ - -#define DT_ZONE ((inode->i_size + XIAFS_ZSIZE(inode->i_sb) - 1) \ - >> XIAFS_ZSIZE_BITS(inode->i_sb) ) - -static int trunc_direct(struct inode * inode) -{ - u_long * lp; - struct buffer_head * bh; - int i, tmp; - int retry = 0; - -repeat: - for (i = DT_ZONE ; i < 8 ; i++) { - if (i < DT_ZONE) - goto repeat; - lp=i + inode->u.xiafs_i.i_zone; - if (!(tmp = *lp)) - continue; - bh = getblk(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb)); - if (i < DT_ZONE) { - brelse(bh); - goto repeat; - } - if ((bh && bh->b_count != 1) || tmp != *lp) - retry = 1; - else { - *lp = 0; - inode->i_dirt = 1; - inode->i_blocks-=2 << XIAFS_ZSHIFT(inode->i_sb); - xiafs_free_zone(inode->i_sb, tmp); - } - brelse(bh); - } - return retry; -} - -static int trunc_indirect(struct inode * inode, int addr_off, u_long * lp) -{ - -#define INDT_ZONE (DT_ZONE - addr_off) - - struct buffer_head * bh, * ind_bh; - int i, tmp; - u_long * indp; - int retry = 0; - - if ( !(tmp=*lp) ) - return 0; - ind_bh = bread(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb)); - if (tmp != *lp) { - brelse(ind_bh); - return 1; - } - if (!ind_bh) { - *lp = 0; - return 0; - } -repeat: - for (i = INDT_ZONE<0?0:INDT_ZONE; i < XIAFS_ADDRS_PER_Z(inode->i_sb); i++) { - if (i < INDT_ZONE) - goto repeat; - indp = i+(u_long *) ind_bh->b_data; - if (!(tmp=*indp)) - continue; - bh = getblk(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb)); - if (i < INDT_ZONE) { - brelse(bh); - goto repeat; - } - if ((bh && bh->b_count != 1) || tmp != *indp) - retry = 1; - else { - *indp = 0; - mark_buffer_dirty(ind_bh, 1); - inode->i_blocks-= 2 << XIAFS_ZSHIFT(inode->i_sb); - xiafs_free_zone(inode->i_sb, tmp); - } - brelse(bh); - } - indp = (u_long *) ind_bh->b_data; - for (i = 0; i < XIAFS_ADDRS_PER_Z(inode->i_sb) && !(*indp++); i++) ; - if (i >= XIAFS_ADDRS_PER_Z(inode->i_sb)) { - if (ind_bh->b_count != 1) - retry = 1; - else { - tmp = *lp; - *lp = 0; - inode->i_blocks-= 2 << XIAFS_ZSHIFT(inode->i_sb); - xiafs_free_zone(inode->i_sb, tmp); - } - } - brelse(ind_bh); - return retry; -} - -static int trunc_dindirect(struct inode * inode) -{ - -#define DINDT_ZONE \ - ((DT_ZONE-XIAFS_ADDRS_PER_Z(inode->i_sb)-8)>>XIAFS_ADDRS_PER_Z_BITS(inode->i_sb)) - - int i, tmp; - struct buffer_head * dind_bh; - u_long * dindp, * lp; - int retry = 0; - - lp = &(inode->u.xiafs_i.i_dind_zone); - if (!(tmp = *lp)) - return 0; - dind_bh = bread(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb)); - if (tmp != *lp) { - brelse(dind_bh); - return 1; - } - if (!dind_bh) { - *lp = 0; - return 0; - } -repeat: - for (i=DINDT_ZONE<0?0:DINDT_ZONE ; i < XIAFS_ADDRS_PER_Z(inode->i_sb) ; i ++) { - if (i < DINDT_ZONE) - goto repeat; - dindp = i+(u_long *) dind_bh->b_data; - retry |= trunc_indirect(inode, - 8+((1+i)<<XIAFS_ADDRS_PER_Z_BITS(inode->i_sb)), - dindp); - mark_buffer_dirty(dind_bh, 1); - } - dindp = (u_long *) dind_bh->b_data; - for (i = 0; i < XIAFS_ADDRS_PER_Z(inode->i_sb) && !(*dindp++); i++); - if (i >= XIAFS_ADDRS_PER_Z(inode->i_sb)) { - if (dind_bh->b_count != 1) - retry = 1; - else { - tmp = *lp; - *lp = 0; - inode->i_dirt = 1; - inode->i_blocks-=2 << XIAFS_ZSHIFT(inode->i_sb); - xiafs_free_zone(inode->i_sb, tmp); - } - } - brelse(dind_bh); - return retry; -} - -void xiafs_truncate(struct inode * inode) -{ - int retry; - - if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode))) - return; - while (1) { - retry = trunc_direct(inode); - retry |= trunc_indirect(inode, 8, &(inode->u.xiafs_i.i_ind_zone)); - retry |= trunc_dindirect(inode); - if (!retry) - break; - current->counter = 0; - schedule(); - } - inode->i_ctime = inode->i_mtime = CURRENT_TIME; - inode->i_dirt = 1; -} |