diff options
Diffstat (limited to 'fs/xiafs')
-rw-r--r-- | fs/xiafs/Makefile | 14 | ||||
-rw-r--r-- | fs/xiafs/bitmap.c | 389 | ||||
-rw-r--r-- | fs/xiafs/dir.c | 131 | ||||
-rw-r--r-- | fs/xiafs/file.c | 256 | ||||
-rw-r--r-- | fs/xiafs/fsync.c | 159 | ||||
-rw-r--r-- | fs/xiafs/inode.c | 540 | ||||
-rw-r--r-- | fs/xiafs/namei.c | 854 | ||||
-rw-r--r-- | fs/xiafs/symlink.c | 120 | ||||
-rw-r--r-- | fs/xiafs/truncate.c | 197 | ||||
-rw-r--r-- | fs/xiafs/xiafs_mac.h | 32 |
10 files changed, 0 insertions, 2692 deletions
diff --git a/fs/xiafs/Makefile b/fs/xiafs/Makefile deleted file mode 100644 index e596cc559..000000000 --- a/fs/xiafs/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# -# Makefile for the XIAFS filesystem routines. -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -# Note 2! The CFLAGS definitions are now in the main makefile... - -O_TARGET := xiafs.o -O_OBJS := bitmap.o truncate.o namei.o inode.o file.o dir.o symlink.o fsync.o -M_OBJS := $(O_TARGET) - -include $(TOPDIR)/Rules.make diff --git a/fs/xiafs/bitmap.c b/fs/xiafs/bitmap.c deleted file mode 100644 index 15028ce85..000000000 --- a/fs/xiafs/bitmap.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - * linux/fs/xiafs/bitmap.c - * - * Copyright (C) Q. Frank Xia, 1993. - * - * Based on Linus' minix/bitmap.c - * Copyright (C) Linus Torvalds, 1991, 1992. - * - * This software may be redistributed per Linux Copyright. - */ - -/* bitmap.c contains the code that handles the inode and block bitmaps */ - -#include <linux/sched.h> -#include <linux/locks.h> -#include <linux/xia_fs.h> -#include <linux/stat.h> -#include <linux/kernel.h> -#include <linux/string.h> - -#include <asm/bitops.h> - -#include "xiafs_mac.h" - - -char internal_error_message[]="XIA-FS: internal error %s %d\n"; - -static int find_first_zero(struct buffer_head *bh, int start_bit, int end_bit) -{ - /* This routine searches first 0 bit from (start_bit) to (end_bit-1). - * If found the bit is set to 1 and the bit # is returned, otherwise, - * -1 is returned. Race condition is avoid by using "btsl" and - * "goto repeat". ---Frank. - */ - - int end, i, j, tmp; - u_long *bmap; - - bmap=(u_long *)bh->b_data; - end = end_bit >> 5; - -repeat: - i=start_bit >> 5; - if ( (tmp=(~bmap[i]) & (0xffffffff << (start_bit & 31))) ) - goto zone_found; - while (++i < end) - if (~bmap[i]) { - tmp=~bmap[i]; - goto zone_found; - } - if ( !(tmp=~bmap[i] & ((1 << (end_bit & 31)) -1)) ) - return -1; -zone_found: - for (j=0; j < 32; j++) - if (tmp & (1 << j)) - break; - if (set_bit(j,bmap+i)) { - start_bit=j + (i << 5) + 1; - goto repeat; - } - mark_buffer_dirty(bh, 1); - return j + (i << 5); -} - -static void clear_buf(struct buffer_head * bh) -{ - register int i; - register long * lp; - - lp=(long *)bh->b_data; - for (i= bh->b_size >> 2; i-- > 0; ) - *lp++=0; -} - -static void que(struct buffer_head * bmap[], int bznr[], int pos) -{ - struct buffer_head * tbh; - int tmp; - int i; - - tbh=bmap[pos]; - tmp=bznr[pos]; - for (i=pos; i > 0; i--) { - bmap[i]=bmap[i-1]; - bznr[i]=bznr[i-1]; - } - bmap[0]=tbh; - bznr[0]=tmp; -} - -#define get_imap_zone(sb, bit_nr, not_que) \ - get__map_zone((sb), (sb)->u.xiafs_sb.s_imap_buf, \ - (sb)->u.xiafs_sb.s_imap_iznr, \ - (sb)->u.xiafs_sb.s_imap_cached, 1, \ - (sb)->u.xiafs_sb.s_imap_zones, _XIAFS_IMAP_SLOTS, \ - bit_nr, not_que) - -#define get_zmap_zone(sb, bit_nr, not_que) \ - get__map_zone((sb), (sb)->u.xiafs_sb.s_zmap_buf, \ - (sb)->u.xiafs_sb.s_zmap_zznr, \ - (sb)->u.xiafs_sb.s_zmap_cached, \ - 1+(sb)->u.xiafs_sb.s_imap_zones, \ - (sb)->u.xiafs_sb.s_zmap_zones, _XIAFS_ZMAP_SLOTS, \ - bit_nr, not_que) - -static struct buffer_head * -get__map_zone(struct super_block *sb, struct buffer_head * bmap_buf[], - int bznr[], u_char cache, int first_zone, - int bmap_zones, int slots, u_long bit_nr, int * not_que) -{ - struct buffer_head * tmp_bh; - int z_nr, i; - - z_nr = bit_nr >> XIAFS_BITS_PER_Z_BITS(sb); - if (z_nr >= bmap_zones) { - printk("XIA-FS: bad inode/zone number (%s %d)\n", WHERE_ERR); - return NULL; - } - if (!cache) - return bmap_buf[z_nr]; - lock_super(sb); - for (i=0; i < slots; i++) - if (bznr[i]==z_nr) - break; - if (i < slots) { /* cache hit */ - if (not_que) { - *not_que=i; - return bmap_buf[i]; - } else { - que(bmap_buf, bznr, i); - return bmap_buf[0]; - } - } - tmp_bh=bread(sb->s_dev, z_nr+first_zone, XIAFS_ZSIZE(sb)); /* cache not hit */ - if (!tmp_bh) { - printk("XIA-FS: read bitmap failed (%s %d)\n", WHERE_ERR); - unlock_super(sb); - return NULL; - } - brelse(bmap_buf[slots-1]); - bmap_buf[slots-1]=tmp_bh; - bznr[slots-1]=z_nr; - if (not_que) - *not_que=slots-1; - else - que(bmap_buf, bznr, slots-1); - return tmp_bh; -} - -#define xiafs_unlock_super(sb, cache) if (cache) unlock_super(sb); - -#define get_free_ibit(sb, prev_bit) \ - get_free__bit(sb, sb->u.xiafs_sb.s_imap_buf, \ - sb->u.xiafs_sb.s_imap_iznr, \ - sb->u.xiafs_sb.s_imap_cached, \ - 1, sb->u.xiafs_sb.s_imap_zones, \ - _XIAFS_IMAP_SLOTS, prev_bit); - -#define get_free_zbit(sb, prev_bit) \ - get_free__bit(sb, sb->u.xiafs_sb.s_zmap_buf, \ - sb->u.xiafs_sb.s_zmap_zznr, \ - sb->u.xiafs_sb.s_zmap_cached, \ - 1 + sb->u.xiafs_sb.s_imap_zones, \ - sb->u.xiafs_sb.s_zmap_zones, \ - _XIAFS_ZMAP_SLOTS, prev_bit); - -static u_long -get_free__bit(struct super_block *sb, struct buffer_head * bmap_buf[], - int bznr[], u_char cache, int first_zone, int bmap_zones, - int slots, u_long prev_bit) -{ - struct buffer_head * bh; - int not_done=0; - u_long pos, start_bit, end_bit, total_bits; - int z_nr, tmp; - - total_bits=bmap_zones << XIAFS_BITS_PER_Z_BITS(sb); - if (prev_bit >= total_bits) - prev_bit=0; - pos=prev_bit+1; - end_bit=XIAFS_BITS_PER_Z(sb); - - do { - if (pos >= total_bits) - pos=0; - if (!not_done) { /* first time */ - not_done=1; - start_bit= pos & (end_bit-1); - } else - start_bit=0; - if ( pos < prev_bit && pos+end_bit >= prev_bit) { /* last time */ - not_done=0; - end_bit=prev_bit & (end_bit-1); /* only here end_bit modified */ - } - bh = get__map_zone(sb, bmap_buf, bznr, cache, first_zone, - bmap_zones, slots, pos, &z_nr); - if (!bh) - return 0; - tmp=find_first_zero(bh, start_bit, end_bit); - if (tmp >= 0) - break; - xiafs_unlock_super(sb, sb->u.xiafs_sb.s_zmap_cached); - pos=(pos & ~(end_bit-1))+end_bit; - } while (not_done); - - if (tmp < 0) - return 0; - if (cache) - que(bmap_buf, bznr, z_nr); - xiafs_unlock_super(sb, cache); - return (pos & ~(XIAFS_BITS_PER_Z(sb)-1))+tmp; -} - -void xiafs_free_zone(struct super_block * sb, int d_addr) -{ - struct buffer_head * bh; - unsigned int bit, offset; - - if (!sb) { - printk(INTERN_ERR); - return; - } - if (d_addr < sb->u.xiafs_sb.s_firstdatazone || - d_addr >= sb->u.xiafs_sb.s_nzones) { - printk("XIA-FS: bad zone number (%s %d)\n", WHERE_ERR); - return; - } - bh = get_hash_table(sb->s_dev, d_addr, XIAFS_ZSIZE(sb)); - if (bh) - mark_buffer_clean(bh); - brelse(bh); - bit=d_addr - sb->u.xiafs_sb.s_firstdatazone + 1; - bh = get_zmap_zone(sb, bit, NULL); - if (!bh) - return; - offset = bit & (XIAFS_BITS_PER_Z(sb) -1); - if (!clear_bit(offset, bh->b_data)) - printk("XIA-FS: dev %s" - " block bit %u (0x%x) already cleared (%s %d)\n", - kdevname(sb->s_dev), bit, bit, WHERE_ERR); - mark_buffer_dirty(bh, 1); - xiafs_unlock_super(sb, sb->u.xiafs_sb.s_zmap_cached); -} - -int xiafs_new_zone(struct super_block * sb, u_long prev_addr) -{ - struct buffer_head * bh; - int prev_znr, tmp; - - if (!sb) { - printk(INTERN_ERR); - return 0; - } - if (prev_addr < sb->u.xiafs_sb.s_firstdatazone || - prev_addr >= sb->u.xiafs_sb.s_nzones) { - prev_addr=sb->u.xiafs_sb.s_firstdatazone; - } - prev_znr=prev_addr-sb->u.xiafs_sb.s_firstdatazone+1; - tmp=get_free_zbit(sb, prev_znr); - if (!tmp) - return 0; - tmp += sb->u.xiafs_sb.s_firstdatazone -1; - if (!(bh = getblk(sb->s_dev, tmp, XIAFS_ZSIZE(sb)))) { - printk("XIA-FS: I/O error (%s %d)\n", WHERE_ERR); - return 0; - } - if (bh->b_count != 1) { - printk(INTERN_ERR); - return 0; - } - clear_buf(bh); - mark_buffer_uptodate(bh, 1); - mark_buffer_dirty(bh, 1); - brelse(bh); - return tmp; -} - -void xiafs_free_inode(struct inode * inode) -{ - struct buffer_head * bh; - struct super_block * sb; - unsigned long ino; - - if (!inode) - return; - if (!inode->i_dev || inode->i_count!=1 - || inode->i_nlink || !inode->i_sb || inode->i_ino < 3 - || inode->i_ino > inode->i_sb->u.xiafs_sb.s_ninodes) { - printk("XIA-FS: bad inode (%s %d)\n", WHERE_ERR); - return; - } - sb = inode->i_sb; - ino = inode->i_ino; - bh = get_imap_zone(sb, ino, NULL); - if (!bh) - return; - clear_inode(inode); - if (!clear_bit(ino & (XIAFS_BITS_PER_Z(sb)-1), bh->b_data)) - printk("XIA-FS: dev %s" - "inode bit %ld (0x%lx) already cleared (%s %d)\n", - kdevname(inode->i_dev), ino, ino, WHERE_ERR); - mark_buffer_dirty(bh, 1); - xiafs_unlock_super(sb, sb->u.xiafs_sb.s_imap_cached); -} - -struct inode * xiafs_new_inode(struct inode * dir) -{ - struct super_block * sb; - struct inode * inode; - ino_t tmp; - - sb = dir->i_sb; - if (!dir || !(inode = get_empty_inode())) - return NULL; - inode->i_sb = sb; - inode->i_flags = inode->i_sb->s_flags; - - tmp=get_free_ibit(sb, dir->i_ino); - if (!tmp) { - iput(inode); - return NULL; - } - inode->i_count = 1; - inode->i_nlink = 1; - inode->i_dev = sb->s_dev; - inode->i_uid = current->fsuid; - inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; - inode->i_dirt = 1; - inode->i_ino = tmp; - inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; - inode->i_op = NULL; - inode->i_blocks = 0; - inode->i_blksize = XIAFS_ZSIZE(inode->i_sb); - insert_inode_hash(inode); - return inode; -} - -static int nibblemap[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 }; - -static u_long count_zone(struct buffer_head * bh) -{ - int i, tmp; - u_long sum; - - sum=0; - for (i=bh->b_size; i-- > 0; ) { - tmp=bh->b_data[i]; - sum += nibblemap[tmp & 0xf] + nibblemap[(tmp & 0xff) >> 4]; - } - return sum; -} - -unsigned long xiafs_count_free_inodes(struct super_block *sb) -{ - struct buffer_head * bh; - int izones, i, not_que; - u_long sum; - - sum=0; - izones=sb->u.xiafs_sb.s_imap_zones; - for (i=0; i < izones; i++) { - bh=get_imap_zone(sb, i << XIAFS_BITS_PER_Z_BITS(sb), ¬_que); - if (bh) { - sum += count_zone(bh); - xiafs_unlock_super(sb, sb->u.xiafs_sb.s_imap_cached); - } - } - i=izones << XIAFS_BITS_PER_Z_BITS(sb); - return i - sum; -} - -unsigned long xiafs_count_free_zones(struct super_block *sb) -{ - struct buffer_head * bh; - int zzones, i, not_que; - u_long sum; - - sum=0; - zzones=sb->u.xiafs_sb.s_zmap_zones; - for (i=0; i < zzones; i++) { - bh=get_zmap_zone(sb, i << XIAFS_BITS_PER_Z_BITS(sb), ¬_que); - if (bh) { - sum += count_zone(bh); - xiafs_unlock_super(sb, sb->u.xiafs_sb.s_zmap_cached); - } - } - i=zzones << XIAFS_BITS_PER_Z_BITS(sb); - return i - sum; -} diff --git a/fs/xiafs/dir.c b/fs/xiafs/dir.c deleted file mode 100644 index 856d3cdcd..000000000 --- a/fs/xiafs/dir.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * linux/fs/xiafs/dir.c - * - * Copyright (C) Q. Frank Xia, 1993. - * - * Based on Linus' minix/dir.c - * Copyright (C) Linus Torvalds, 1991, 1992. - * - * This software may be redistributed per Linux Copyright. - */ - -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/fs.h> -#include <linux/xia_fs.h> -#include <linux/stat.h> - -#include <asm/uaccess.h> - -#include "xiafs_mac.h" - -static long xiafs_dir_read(struct inode *, struct file *, char *, unsigned long); -static int xiafs_readdir(struct inode *, struct file *, void *, filldir_t); - -static struct file_operations xiafs_dir_operations = { - NULL, /* lseek - default */ - xiafs_dir_read, /* read */ - NULL, /* write - bad */ - xiafs_readdir, /* readdir */ - NULL, /* select - default */ - NULL, /* ioctl - default */ - NULL, /* mmap */ - NULL, /* no special open code */ - NULL, /* no special release code */ - file_fsync /* default fsync */ -}; - -/* - * directories can handle most operations... - */ -struct inode_operations xiafs_dir_inode_operations = { - &xiafs_dir_operations, /* default directory file-ops */ - xiafs_create, /* create */ - xiafs_lookup, /* lookup */ - xiafs_link, /* link */ - xiafs_unlink, /* unlink */ - xiafs_symlink, /* symlink */ - xiafs_mkdir, /* mkdir */ - xiafs_rmdir, /* rmdir */ - xiafs_mknod, /* mknod */ - xiafs_rename, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* bmap */ - xiafs_truncate, /* truncate */ - NULL /* permission */ -}; - -static long xiafs_dir_read(struct inode * inode, struct file * filp, - char * buf, unsigned long count) -{ - return -EISDIR; -} - -static int xiafs_readdir(struct inode * inode, struct file * filp, - void * dirent, filldir_t filldir) -{ - u_int offset, i; - struct buffer_head * bh; - struct xiafs_direct * de; - - if (!inode || !inode->i_sb || !S_ISDIR(inode->i_mode)) - return -EBADF; - if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb) - 1) ) - return -EBADF; - while (filp->f_pos < inode->i_size) { - offset = filp->f_pos & (XIAFS_ZSIZE(inode->i_sb) - 1); - bh = xiafs_bread(inode, filp->f_pos >> XIAFS_ZSIZE_BITS(inode->i_sb),0); - if (!bh) { - filp->f_pos += XIAFS_ZSIZE(inode->i_sb)-offset; - continue; - } - for (i = 0; i < XIAFS_ZSIZE(inode->i_sb) && i < offset; ) { - de = (struct xiafs_direct *) (bh->b_data + i); - if (!de->d_rec_len) - break; - i += de->d_rec_len; - } - offset = i; - de = (struct xiafs_direct *) (offset + bh->b_data); - - while (offset < XIAFS_ZSIZE(inode->i_sb) && filp->f_pos < inode->i_size) { - if (de->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes || - de->d_rec_len < 12 || - (char *)de+de->d_rec_len > XIAFS_ZSIZE(inode->i_sb)+bh->b_data || - de->d_name_len < 1 || de->d_name_len + 8 > de->d_rec_len || - de->d_name_len > _XIAFS_NAME_LEN || - de->d_name[de->d_name_len] ) { - printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR); - brelse(bh); - return 0; - } - if (de->d_ino) { - if (!IS_RDONLY (inode)) { - inode->i_atime=CURRENT_TIME; - inode->i_dirt=1; - } - if (filldir(dirent, de->d_name, de->d_name_len, filp->f_pos, de->d_ino) < 0) { - brelse(bh); - return 0; - } - } - offset += de->d_rec_len; - filp->f_pos += de->d_rec_len; - de = (struct xiafs_direct *) (offset + bh->b_data); - } - brelse(bh); - if (offset > XIAFS_ZSIZE(inode->i_sb)) { - printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR); - return 0; - } - } - if (!IS_RDONLY (inode)) { - inode->i_atime=CURRENT_TIME; - inode->i_dirt=1; - } - return 0; -} diff --git a/fs/xiafs/file.c b/fs/xiafs/file.c deleted file mode 100644 index 822b4b520..000000000 --- a/fs/xiafs/file.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * linux/fs/xiafs/file.c - * - * Copyright (C) Q. Frank Xia, 1993. - * - * Based on Linus' minix/file.c - * Copyright (C) Linus Torvalds, 1991, 1992. - * - * This software may be redistributed per Linux Copyright. - */ - -#include <linux/sched.h> -#include <linux/fs.h> -#include <linux/xia_fs.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/fcntl.h> -#include <linux/stat.h> -#include <linux/locks.h> -#include <linux/pagemap.h> - -#include <asm/uaccess.h> -#include <asm/system.h> - -#include "xiafs_mac.h" - -#define NBUF 32 - -#define MIN(a,b) (((a)<(b))?(a):(b)) -#define MAX(a,b) (((a)>(b))?(a):(b)) - -static long xiafs_file_read(struct inode *, struct file *, char *, unsigned long); -static long xiafs_file_write(struct inode *, struct file *, const char *, unsigned long); - -/* - * We have mostly NULL's here: the current defaults are ok for - * the xiafs filesystem. - */ -static struct file_operations xiafs_file_operations = { - NULL, /* lseek - default */ - xiafs_file_read, /* read */ - xiafs_file_write, /* write */ - NULL, /* readdir - bad */ - NULL, /* select - default */ - NULL, /* ioctl - default */ - generic_file_mmap, /* mmap */ - NULL, /* no special open is needed */ - NULL, /* release */ - xiafs_sync_file /* fsync */ -}; - -struct inode_operations xiafs_file_inode_operations = { - &xiafs_file_operations, /* default file operations */ - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - generic_readpage, /* readpage */ - NULL, /* writepage */ - xiafs_bmap, /* bmap */ - xiafs_truncate, /* truncate */ - NULL /* permission */ -}; - -static long -xiafs_file_read(struct inode * inode, struct file * filp, char * buf, unsigned long count) -{ - int read, left, chars; - int zone_nr, zones, f_zones, offset; - int bhrequest, uptodate; - struct buffer_head ** bhb, ** bhe; - struct buffer_head * bhreq[NBUF]; - struct buffer_head * buflist[NBUF]; - - if (!inode) { - printk("XIA-FS: inode = NULL (%s %d)\n", WHERE_ERR); - return -EINVAL; - } - if (!S_ISREG(inode->i_mode)) { - printk("XIA-FS: mode != regular (%s %d)\n", WHERE_ERR); - return -EINVAL; - } - offset = filp->f_pos; - left = inode->i_size - offset; - if (left > count) - left = count; - if (left <= 0) - return 0; - read = 0; - zone_nr = offset >> XIAFS_ZSIZE_BITS(inode->i_sb); - offset &= XIAFS_ZSIZE(inode->i_sb) -1 ; - f_zones =(inode->i_size+XIAFS_ZSIZE(inode->i_sb)-1)>>XIAFS_ZSIZE_BITS(inode->i_sb); - zones = (left+offset+XIAFS_ZSIZE(inode->i_sb)-1) >> XIAFS_ZSIZE_BITS(inode->i_sb); - bhb = bhe = buflist; - if (filp->f_reada) { - if(zones < read_ahead[MAJOR(inode->i_dev)] >> (1+XIAFS_ZSHIFT(inode->i_sb))) - zones = read_ahead[MAJOR(inode->i_dev)] >> (1+XIAFS_ZSHIFT(inode->i_sb)); - if (zone_nr + zones > f_zones) - zones = f_zones - zone_nr; - } - - /* We do this in a two stage process. We first try to request - as many blocks as we can, then we wait for the first one to - complete, and then we try to wrap up as many as are actually - done. This routine is rather generic, in that it can be used - in a filesystem by substituting the appropriate function in - for getblk. - - This routine is optimized to make maximum use of the various - buffers and caches. */ - - do { - bhrequest = 0; - uptodate = 1; - while (zones--) { - *bhb = xiafs_getblk(inode, zone_nr++, 0); - if (*bhb && !buffer_uptodate(*bhb)) { - uptodate = 0; - bhreq[bhrequest++] = *bhb; - } - - if (++bhb == &buflist[NBUF]) - bhb = buflist; - - /* If the block we have on hand is uptodate, go ahead - and complete processing. */ - if (uptodate) - break; - if (bhb == bhe) - break; - } - - /* Now request them all */ - if (bhrequest) - ll_rw_block(READ, bhrequest, bhreq); - - do { /* Finish off all I/O that has actually completed */ - if (*bhe) { - wait_on_buffer(*bhe); - if (!buffer_uptodate(*bhe)) { /* read error? */ - brelse(*bhe); - if (++bhe == &buflist[NBUF]) - bhe = buflist; - left = 0; - break; - } - } - if (left < XIAFS_ZSIZE(inode->i_sb) - offset) - chars = left; - else - chars = XIAFS_ZSIZE(inode->i_sb) - offset; - filp->f_pos += chars; - left -= chars; - read += chars; - if (*bhe) { - copy_to_user(buf,offset+(*bhe)->b_data,chars); - brelse(*bhe); - buf += chars; - } else { - while (chars-->0) - put_user(0,buf++); - } - offset = 0; - if (++bhe == &buflist[NBUF]) - bhe = buflist; - } while (left > 0 && bhe != bhb && (!*bhe || !buffer_locked(*bhe))); - } while (left > 0); - -/* Release the read-ahead blocks */ - while (bhe != bhb) { - brelse(*bhe); - if (++bhe == &buflist[NBUF]) - bhe = buflist; - }; - if (!read) - return -EIO; - filp->f_reada = 1; - if (!IS_RDONLY (inode)) { - inode->i_atime = CURRENT_TIME; - inode->i_dirt = 1; - } - return read; -} - -static long -xiafs_file_write(struct inode * inode, struct file * filp, const char * buf, unsigned long count) -{ - off_t pos; - int written, c; - struct buffer_head * bh; - char * cp; - - if (!inode) { - printk("XIA-FS: inode = NULL (%s %d)\n", WHERE_ERR); - return -EINVAL; - } - if (!S_ISREG(inode->i_mode)) { - printk("XIA-FS: mode != regular (%s %d)\n", WHERE_ERR); - return -EINVAL; - } -/* - * ok, append may not work when many processes are writing at the same time - * but so what. That way leads to madness anyway. - */ - if (filp->f_flags & O_APPEND) - pos = inode->i_size; - else - pos = filp->f_pos; - written = 0; - while (written < count) { - bh = xiafs_getblk(inode, pos >> XIAFS_ZSIZE_BITS(inode->i_sb), 1); - if (!bh) { - if (!written) - written = -ENOSPC; - break; - } - c = XIAFS_ZSIZE(inode->i_sb) - (pos & (XIAFS_ZSIZE(inode->i_sb) - 1)); - if (c > count-written) - c = count-written; - if (c != XIAFS_ZSIZE(inode->i_sb) && !buffer_uptodate(bh)) { - ll_rw_block(READ, 1, &bh); - wait_on_buffer(bh); - if (!buffer_uptodate(bh)) { - brelse(bh); - if (!written) - written = -EIO; - break; - } - } - cp = (pos & (XIAFS_ZSIZE(inode->i_sb)-1)) + bh->b_data; - copy_from_user(cp,buf,c); - update_vm_cache(inode,pos,cp,c); - pos += c; - if (pos > inode->i_size) { - inode->i_size = pos; - inode->i_dirt = 1; - } - written += c; - buf += c; - mark_buffer_uptodate(bh, 1); - mark_buffer_dirty(bh, 0); - brelse(bh); - } - inode->i_mtime = inode->i_ctime = CURRENT_TIME; - filp->f_pos = pos; - inode->i_dirt = 1; - - return written; -} diff --git a/fs/xiafs/fsync.c b/fs/xiafs/fsync.c deleted file mode 100644 index f491e3d8e..000000000 --- a/fs/xiafs/fsync.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * linux/fs/xiafs/fsync.c - * - * Changes Copyright (C) 1993 Stephen Tweedie (sct@dcs.ed.ac.uk) - * from - * Copyright (C) 1991, 1992 Linus Torvalds - * - * xiafs fsync primitive - */ - -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/stat.h> -#include <linux/fcntl.h> -#include <linux/locks.h> - -#include <linux/fs.h> -#include <linux/xia_fs.h> - -#include <asm/uaccess.h> -#include <asm/system.h> - -#include "xiafs_mac.h" - - -#define blocksize (XIAFS_ZSIZE(inode->i_sb)) -#define addr_per_block (XIAFS_ADDRS_PER_Z(inode->i_sb)) - -static int sync_block (struct inode * inode, unsigned long * block, int wait) -{ - struct buffer_head * bh; - int tmp; - - if (!*block) - return 0; - tmp = *block; - bh = get_hash_table(inode->i_dev, *block, blocksize); - if (!bh) - return 0; - if (*block != tmp) { - brelse (bh); - return 1; - } - if (wait && buffer_req(bh) && !buffer_uptodate(bh)) { - brelse(bh); - return -1; - } - if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) - { - brelse(bh); - return 0; - } - ll_rw_block(WRITE, 1, &bh); - bh->b_count--; - return 0; -} - -static int sync_iblock (struct inode * inode, unsigned long * iblock, - struct buffer_head **bh, int wait) -{ - int rc, tmp; - - *bh = NULL; - tmp = *iblock; - if (!tmp) - return 0; - rc = sync_block (inode, iblock, wait); - if (rc) - return rc; - *bh = bread(inode->i_dev, tmp, blocksize); - if (tmp != *iblock) { - brelse(*bh); - *bh = NULL; - return 1; - } - if (!*bh) - return -1; - return 0; -} - - -static int sync_direct(struct inode *inode, int wait) -{ - int i; - int rc, err = 0; - - for (i = 0; i < 8; i++) { - rc = sync_block (inode, inode->u.ext_i.i_data + i, wait); - if (rc > 0) - break; - if (rc) - err = rc; - } - return err; -} - -static int sync_indirect(struct inode *inode, unsigned long *iblock, int wait) -{ - int i; - struct buffer_head * ind_bh; - int rc, err = 0; - - rc = sync_iblock (inode, iblock, &ind_bh, wait); - if (rc || !ind_bh) - return rc; - - for (i = 0; i < addr_per_block; i++) { - rc = sync_block (inode, - ((unsigned long *) ind_bh->b_data) + i, - wait); - if (rc > 0) - break; - if (rc) - err = rc; - } - brelse(ind_bh); - return err; -} - -static int sync_dindirect(struct inode *inode, unsigned long *diblock, - int wait) -{ - int i; - struct buffer_head * dind_bh; - int rc, err = 0; - - rc = sync_iblock (inode, diblock, &dind_bh, wait); - if (rc || !dind_bh) - return rc; - - for (i = 0; i < addr_per_block; i++) { - rc = sync_indirect (inode, - ((unsigned long *) dind_bh->b_data) + i, - wait); - if (rc > 0) - break; - if (rc) - err = rc; - } - brelse(dind_bh); - return err; -} - -int xiafs_sync_file(struct inode * inode, struct file * file) -{ - int wait, err = 0; - - if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode))) - return -EINVAL; - for (wait=0; wait<=1; wait++) - { - err |= sync_direct(inode, wait); - err |= sync_indirect(inode, &inode->u.xiafs_i.i_ind_zone, wait); - err |= sync_dindirect(inode, &inode->u.xiafs_i.i_dind_zone, wait); - } - err |= xiafs_sync_inode (inode); - return (err < 0) ? -EIO : 0; -} diff --git a/fs/xiafs/inode.c b/fs/xiafs/inode.c deleted file mode 100644 index 48b31e972..000000000 --- a/fs/xiafs/inode.c +++ /dev/null @@ -1,540 +0,0 @@ -/* - * linux/fs/xiafs/inode.c - * - * Copyright (C) Q. Frank Xia, 1993. - * - * Based on Linus' minix/inode.c - * Copyright (C) Linus Torvalds, 1991, 1992. - * - * This software may be redistributed per Linux Copyright. - */ - -#include <linux/module.h> - -#include <linux/sched.h> -#include <linux/xia_fs.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/string.h> -#include <linux/stat.h> -#include <linux/locks.h> -#include <asm/system.h> -#include <asm/uaccess.h> - -#include "xiafs_mac.h" - -static u_long random_nr; - -void xiafs_put_inode(struct inode *inode) -{ - if (inode->i_nlink) - return; - inode->i_size = 0; - xiafs_truncate(inode); - xiafs_free_inode(inode); -} - -void xiafs_put_super(struct super_block *sb) -{ - int i; - - lock_super(sb); - sb->s_dev = 0; - for(i = 0 ; i < _XIAFS_IMAP_SLOTS ; i++) - brelse(sb->u.xiafs_sb.s_imap_buf[i]); - for(i = 0 ; i < _XIAFS_ZMAP_SLOTS ; i++) - brelse(sb->u.xiafs_sb.s_zmap_buf[i]); - unlock_super(sb); - MOD_DEC_USE_COUNT; -} - -static struct super_operations xiafs_sops = { - xiafs_read_inode, - NULL, - xiafs_write_inode, - xiafs_put_inode, - xiafs_put_super, - NULL, - xiafs_statfs, - NULL -}; - -struct super_block *xiafs_read_super(struct super_block *s, void *data, - int silent) -{ - struct buffer_head *bh; - struct xiafs_super_block *sp; - int i, z; - kdev_t dev; - - MOD_INC_USE_COUNT; - dev = s->s_dev; - lock_super(s); - - set_blocksize(dev, BLOCK_SIZE); - - if (!(bh = bread(dev, 0, BLOCK_SIZE))) { - s->s_dev = 0; - unlock_super(s); - printk("XIA-FS: read super_block failed (%s %d)\n", WHERE_ERR); - MOD_DEC_USE_COUNT; - return NULL; - } - sp = (struct xiafs_super_block *) bh->b_data; - s->s_magic = sp->s_magic; - if (s->s_magic != _XIAFS_SUPER_MAGIC) { - s->s_dev = 0; - unlock_super(s); - brelse(bh); - if (!silent) - printk("VFS: Can't find a xiafs filesystem on dev " - "%s.\n", kdevname(dev)); - MOD_DEC_USE_COUNT; - return NULL; - } - s->s_blocksize = sp->s_zone_size; - s->s_blocksize_bits = 10 + sp->s_zone_shift; - if (s->s_blocksize != BLOCK_SIZE && - (s->s_blocksize == 1024 || s->s_blocksize == 2048 || - s->s_blocksize == 4096)) { - brelse(bh); - set_blocksize(dev, s->s_blocksize); - bh = bread (dev, 0, s->s_blocksize); - if(!bh) { - MOD_DEC_USE_COUNT; - return NULL; - } - sp = (struct xiafs_super_block *) (((char *)bh->b_data) + BLOCK_SIZE) ; - }; - s->u.xiafs_sb.s_nzones = sp->s_nzones; - s->u.xiafs_sb.s_ninodes = sp->s_ninodes; - s->u.xiafs_sb.s_ndatazones = sp->s_ndatazones; - s->u.xiafs_sb.s_imap_zones = sp->s_imap_zones; - s->u.xiafs_sb.s_zmap_zones = sp->s_zmap_zones; - s->u.xiafs_sb.s_firstdatazone = sp->s_firstdatazone; - s->u.xiafs_sb.s_zone_shift = sp->s_zone_shift; - s->u.xiafs_sb.s_max_size = sp->s_max_size; - brelse(bh); - for (i=0;i < _XIAFS_IMAP_SLOTS;i++) { - s->u.xiafs_sb.s_imap_buf[i] = NULL; - s->u.xiafs_sb.s_imap_iznr[i] = -1; - } - for (i=0;i < _XIAFS_ZMAP_SLOTS;i++) { - s->u.xiafs_sb.s_zmap_buf[i] = NULL; - s->u.xiafs_sb.s_zmap_zznr[i] = -1; - } - z=1; - if ( s->u.xiafs_sb.s_imap_zones > _XIAFS_IMAP_SLOTS ) - s->u.xiafs_sb.s_imap_cached=1; - else { - s->u.xiafs_sb.s_imap_cached=0; - for (i=0 ; i < s->u.xiafs_sb.s_imap_zones ; i++) { - if (!(s->u.xiafs_sb.s_imap_buf[i]=bread(dev, z++, XIAFS_ZSIZE(s)))) - goto xiafs_read_super_fail; - s->u.xiafs_sb.s_imap_iznr[i]=i; - } - } - if ( s->u.xiafs_sb.s_zmap_zones > _XIAFS_ZMAP_SLOTS ) - s->u.xiafs_sb.s_zmap_cached=1; - else { - s->u.xiafs_sb.s_zmap_cached=0; - for (i=0 ; i < s->u.xiafs_sb.s_zmap_zones ; i++) { - if (!(s->u.xiafs_sb.s_zmap_buf[i]=bread(dev, z++, XIAFS_ZSIZE(s)))) - goto xiafs_read_super_fail; - s->u.xiafs_sb.s_zmap_zznr[i]=i; - } - } - /* set up enough so that it can read an inode */ - s->s_dev = dev; - s->s_op = &xiafs_sops; - s->s_mounted = iget(s, _XIAFS_ROOT_INO); - if (!s->s_mounted) - goto xiafs_read_super_fail; - unlock_super(s); - random_nr=CURRENT_TIME; - return s; - -xiafs_read_super_fail: - for(i=0; i < _XIAFS_IMAP_SLOTS; i++) - brelse(s->u.xiafs_sb.s_imap_buf[i]); - for(i=0; i < _XIAFS_ZMAP_SLOTS; i++) - brelse(s->u.xiafs_sb.s_zmap_buf[i]); - s->s_dev = 0; - unlock_super(s); - printk("XIA-FS: read bitmaps failed (%s %d)\n", WHERE_ERR); - MOD_DEC_USE_COUNT; - return NULL; -} - -void xiafs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) -{ - struct statfs tmp; - - tmp.f_type = _XIAFS_SUPER_MAGIC; - tmp.f_bsize = XIAFS_ZSIZE(sb); - tmp.f_blocks = sb->u.xiafs_sb.s_ndatazones; - tmp.f_bfree = xiafs_count_free_zones(sb); - tmp.f_bavail = tmp.f_bfree; - tmp.f_files = sb->u.xiafs_sb.s_ninodes; - tmp.f_ffree = xiafs_count_free_inodes(sb); - tmp.f_namelen = _XIAFS_NAME_LEN; - copy_to_user(buf, &tmp, bufsiz); -} - -static int zone_bmap(struct buffer_head * bh, int nr) -{ - int tmp; - - if (!bh) - return 0; - tmp = ((u_long *) bh->b_data)[nr]; - brelse(bh); - return tmp; -} - -int xiafs_bmap(struct inode * inode,int zone) -{ - int i; - - if (zone < 0) { - printk("XIA-FS: block < 0 (%s %d)\n", WHERE_ERR); - return 0; - } - if (zone >= 8+(1+XIAFS_ADDRS_PER_Z(inode->i_sb))*XIAFS_ADDRS_PER_Z(inode->i_sb)) { - printk("XIA-FS: zone > big (%s %d)\n", WHERE_ERR); - return 0; - } - if (!IS_RDONLY (inode)) { - inode->i_atime = CURRENT_TIME; - inode->i_dirt = 1; - } - if (zone < 8) - return inode->u.xiafs_i.i_zone[zone]; - zone -= 8; - if (zone < XIAFS_ADDRS_PER_Z(inode->i_sb)) { - i = inode->u.xiafs_i.i_ind_zone; - if (i) - i = zone_bmap(bread(inode->i_dev, i, XIAFS_ZSIZE(inode->i_sb)), zone); - return i; - } - zone -= XIAFS_ADDRS_PER_Z(inode->i_sb); - i = inode->u.xiafs_i.i_dind_zone; - if (i) - i = zone_bmap(bread(inode->i_dev, i, XIAFS_ZSIZE(inode->i_sb)), - zone >> XIAFS_ADDRS_PER_Z_BITS(inode->i_sb)); - if (i) - i= zone_bmap(bread(inode->i_dev,i, XIAFS_ZSIZE(inode->i_sb)), - zone & (XIAFS_ADDRS_PER_Z(inode->i_sb)-1)); - return i; -} - -static u_long get_prev_addr(struct inode * inode, int zone) -{ - u_long tmp; - - if (zone > 0) - while (--zone >= 0) /* only files with holes suffer */ - if ((tmp=xiafs_bmap(inode, zone))) - return tmp; - random_nr=(random_nr+23)%inode->i_sb->u.xiafs_sb.s_ndatazones; - return random_nr + inode->i_sb->u.xiafs_sb.s_firstdatazone; -} - -static struct buffer_head * -dt_getblk(struct inode * inode, u_long *lp, int create, u_long prev_addr) -{ - int tmp; - struct buffer_head * result; - -repeat: - if ((tmp=*lp)) { - result = getblk(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb)); - if (tmp == *lp) - return result; - brelse(result); - goto repeat; - } - if (!create) - return NULL; - tmp = xiafs_new_zone(inode->i_sb, prev_addr); - if (!tmp) - return NULL; - result = getblk(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb)); - if (*lp) { - xiafs_free_zone(inode->i_sb, tmp); - brelse(result); - goto repeat; - } - *lp = tmp; - inode->i_blocks+=2 << XIAFS_ZSHIFT(inode->i_sb); - return result; -} - -static struct buffer_head * -indt_getblk(struct inode * inode, struct buffer_head * bh, - int nr, int create, u_long prev_addr) -{ - int tmp; - u_long *lp; - struct buffer_head * result; - - if (!bh) - return NULL; - if (!buffer_uptodate(bh)) { - ll_rw_block(READ, 1, &bh); - wait_on_buffer(bh); - if (!buffer_uptodate(bh)) { - brelse(bh); - return NULL; - } - } - lp = nr + (u_long *) bh->b_data; -repeat: - if ((tmp=*lp)) { - result = getblk(bh->b_dev, tmp, XIAFS_ZSIZE(inode->i_sb)); - if (tmp == *lp) { - brelse(bh); - return result; - } - brelse(result); - goto repeat; - } - if (!create) { - brelse(bh); - return NULL; - } - tmp = xiafs_new_zone(inode->i_sb, prev_addr); - if (!tmp) { - brelse(bh); - return NULL; - } - result = getblk(bh->b_dev, tmp, XIAFS_ZSIZE(inode->i_sb)); - if (*lp) { - xiafs_free_zone(inode->i_sb, tmp); - brelse(result); - goto repeat; - } - *lp = tmp; - inode->i_blocks+=2 << XIAFS_ZSHIFT(inode->i_sb); - mark_buffer_dirty(bh, 1); - brelse(bh); - return result; -} - -struct buffer_head * xiafs_getblk(struct inode * inode, int zone, int create) -{ - struct buffer_head * bh; - u_long prev_addr=0; - - if (zone<0) { - printk("XIA-FS: zone < 0 (%s %d)\n", WHERE_ERR); - return NULL; - } - if (zone >= 8+(1+XIAFS_ADDRS_PER_Z(inode->i_sb))*XIAFS_ADDRS_PER_Z(inode->i_sb)) { - if (!create) - printk("XIA-FS: zone > big (%s %d)\n", WHERE_ERR); - return NULL; - } - if (create) - prev_addr=get_prev_addr(inode, zone); - if (zone < 8) - return dt_getblk(inode, zone+inode->u.xiafs_i.i_zone, create, prev_addr); - zone -= 8; - if (zone < XIAFS_ADDRS_PER_Z(inode->i_sb)) { - bh = dt_getblk(inode, &(inode->u.xiafs_i.i_ind_zone), create, prev_addr); - bh = indt_getblk(inode, bh, zone, create, prev_addr); - return bh; - } - zone -= XIAFS_ADDRS_PER_Z(inode->i_sb); - bh = dt_getblk(inode, &(inode->u.xiafs_i.i_dind_zone), create, prev_addr); - bh = indt_getblk(inode, bh, zone>>XIAFS_ADDRS_PER_Z_BITS(inode->i_sb), - create, prev_addr); - bh = indt_getblk(inode, bh, zone&(XIAFS_ADDRS_PER_Z(inode->i_sb)-1), - create, prev_addr); - return bh; -} - -struct buffer_head * xiafs_bread(struct inode * inode, int zone, int create) -{ - struct buffer_head * bh; - - bh = xiafs_getblk(inode, zone, create); - if (!bh || buffer_uptodate(bh)) - return bh; - ll_rw_block(READ, 1, &bh); - wait_on_buffer(bh); - if (buffer_uptodate(bh)) - return bh; - brelse(bh); - return NULL; -} - -void xiafs_read_inode(struct inode * inode) -{ - struct buffer_head * bh; - struct xiafs_inode * raw_inode; - int zone; - ino_t ino; - - ino = inode->i_ino; - inode->i_op = NULL; - inode->i_mode=0; - if (!ino || ino > inode->i_sb->u.xiafs_sb.s_ninodes) { - printk("XIA-FS: bad inode number (%s %d)\n", WHERE_ERR); - return; - } - zone = 1 + inode->i_sb->u.xiafs_sb.s_imap_zones + - inode->i_sb->u.xiafs_sb.s_zmap_zones + - (ino-1)/ XIAFS_INODES_PER_Z(inode->i_sb); - if (!(bh=bread(inode->i_dev, zone, XIAFS_ZSIZE(inode->i_sb)))) { - printk("XIA-FS: read i-node zone failed (%s %d)\n", WHERE_ERR); - return; - } - raw_inode = ((struct xiafs_inode *) bh->b_data) + - ((ino-1) & (XIAFS_INODES_PER_Z(inode->i_sb) - 1)); - inode->i_mode = raw_inode->i_mode; - inode->i_uid = raw_inode->i_uid; - inode->i_gid = raw_inode->i_gid; - inode->i_nlink = raw_inode->i_nlinks; - inode->i_size = raw_inode->i_size; - inode->i_mtime = raw_inode->i_mtime; - inode->i_atime = raw_inode->i_atime; - inode->i_ctime = raw_inode->i_ctime; - inode->i_blksize = XIAFS_ZSIZE(inode->i_sb); - if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { - inode->i_blocks=0; - inode->i_rdev = to_kdev_t(raw_inode->i_zone[0]); - } else { - XIAFS_GET_BLOCKS(raw_inode, inode->i_blocks); - for (zone = 0; zone < 8; zone++) - inode->u.xiafs_i.i_zone[zone] = raw_inode->i_zone[zone] & 0xffffff; - inode->u.xiafs_i.i_ind_zone = raw_inode->i_ind_zone & 0xffffff; - inode->u.xiafs_i.i_dind_zone = raw_inode->i_dind_zone & 0xffffff; - } - brelse(bh); - if (S_ISREG(inode->i_mode)) - inode->i_op = &xiafs_file_inode_operations; - else if (S_ISDIR(inode->i_mode)) - inode->i_op = &xiafs_dir_inode_operations; - else if (S_ISLNK(inode->i_mode)) - inode->i_op = &xiafs_symlink_inode_operations; - else if (S_ISCHR(inode->i_mode)) - inode->i_op = &chrdev_inode_operations; - else if (S_ISBLK(inode->i_mode)) - inode->i_op = &blkdev_inode_operations; - else if (S_ISFIFO(inode->i_mode)) - init_fifo(inode); -} - -static struct buffer_head * xiafs_update_inode(struct inode * inode) -{ - struct buffer_head * bh; - struct xiafs_inode * raw_inode; - int zone; - ino_t ino; - - if (IS_RDONLY (inode)) { - printk("XIA-FS: write_inode on a read-only filesystem (%s %d)\n", WHERE_ERR); - inode->i_dirt = 0; - return 0; - } - - ino = inode->i_ino; - if (!ino || ino > inode->i_sb->u.xiafs_sb.s_ninodes) { - printk("XIA-FS: bad inode number (%s %d)\n", WHERE_ERR); - inode->i_dirt=0; - return 0; - } - zone = 1 + inode->i_sb->u.xiafs_sb.s_imap_zones + - inode->i_sb->u.xiafs_sb.s_zmap_zones + - (ino-1) / XIAFS_INODES_PER_Z(inode->i_sb); - if (!(bh=bread(inode->i_dev, zone, XIAFS_ZSIZE(inode->i_sb)))) { - printk("XIA-FS: read i-node zone failed (%s %d)\n", WHERE_ERR); - inode->i_dirt=0; - return 0; - } - raw_inode = ((struct xiafs_inode *)bh->b_data) + - ((ino-1) & (XIAFS_INODES_PER_Z(inode->i_sb) -1)); - raw_inode->i_mode = inode->i_mode; - raw_inode->i_uid = inode->i_uid; - raw_inode->i_gid = inode->i_gid; - raw_inode->i_nlinks = inode->i_nlink; - raw_inode->i_size = inode->i_size; - raw_inode->i_atime = inode->i_atime; - raw_inode->i_ctime = inode->i_ctime; - raw_inode->i_mtime = inode->i_mtime; - if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - raw_inode->i_zone[0] = kdev_t_to_nr(inode->i_rdev); - else { - XIAFS_PUT_BLOCKS(raw_inode, inode->i_blocks); - for (zone = 0; zone < 8; zone++) - raw_inode->i_zone[zone] = (raw_inode->i_zone[zone] & 0xff000000) - | (inode->u.xiafs_i.i_zone[zone] & 0xffffff); - raw_inode->i_ind_zone = (raw_inode->i_ind_zone & 0xff000000) - | (inode->u.xiafs_i.i_ind_zone & 0xffffff); - raw_inode->i_dind_zone = (raw_inode->i_dind_zone & 0xff000000) - | (inode->u.xiafs_i.i_dind_zone & 0xffffff); - } - inode->i_dirt=0; - mark_buffer_dirty(bh, 1); - return bh; -} - - -void xiafs_write_inode(struct inode * inode) -{ - struct buffer_head * bh; - bh = xiafs_update_inode(inode); - brelse (bh); -} - -int xiafs_sync_inode (struct inode *inode) -{ - int err = 0; - struct buffer_head *bh; - - bh = xiafs_update_inode(inode); - if (bh && buffer_dirty(bh)) - { - ll_rw_block(WRITE, 1, &bh); - wait_on_buffer(bh); - if (buffer_req(bh) && !buffer_uptodate(bh)) - { - printk ("IO error syncing xiafs inode [%s:%lu]\n", - kdevname(inode->i_dev), inode->i_ino); - err = -1; - } - } - else if (!bh) - err = -1; - brelse (bh); - return err; -} - -/* Every kernel module contains stuff like this. */ - -static struct file_system_type xiafs_fs_type = { - xiafs_read_super, "xiafs", 1, NULL -}; - -int init_xiafs_fs(void) -{ - return register_filesystem(&xiafs_fs_type); -} - -#ifdef MODULE -int init_module(void) -{ - int status; - - if ((status = init_xiafs_fs()) == 0) - register_symtab(0); - return status; -} - -void cleanup_module(void) -{ - unregister_filesystem(&xiafs_fs_type); -} - -#endif diff --git a/fs/xiafs/namei.c b/fs/xiafs/namei.c deleted file mode 100644 index b23c4bf71..000000000 --- a/fs/xiafs/namei.c +++ /dev/null @@ -1,854 +0,0 @@ -/* - * Linux/fs/xiafs/namei.c - * - * Copyright (C) Q. Frank Xia, 1993. - * - * Based on Linus' minix/namei.c - * Copyright (C) Linus Torvalds, 1991, 1992. - * - * This software may be redistributed per Linux Copyright. - */ - -#include <linux/sched.h> -#include <linux/xia_fs.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/stat.h> -#include <linux/fcntl.h> -#include <linux/errno.h> - -#include <asm/uaccess.h> - -#include "xiafs_mac.h" - -#define RNDUP4(x) ((3+(u_long)(x)) & ~3) -/* - * ok, we cannot use strncmp, as the name is not in our data space. - * Thus we'll have to use xiafs_match. No big problem. Match also makes - * some sanity tests. - * - * NOTE! unlike strncmp, xiafs_match returns 1 for success, 0 for failure. - */ -static int xiafs_match(int len, const char * name, struct xiafs_direct * dep) -{ - int i; - - if (!dep || !dep->d_ino || len > _XIAFS_NAME_LEN) - return 0; - /* "" means "." ---> so paths like "/usr/lib//libc.a" work */ - if (!len && (dep->d_name[0]=='.') && (dep->d_name[1]=='\0')) - return 1; - if (len != dep->d_name_len) - return 0; - for (i=0; i < len; i++) - if (*name++ != dep->d_name[i]) - return 0; - return 1; -} - -/* - * xiafs_find_entry() - * - * finds an entry in the specified directory with the wanted name. It - * returns the cache buffer in which the entry was found, and the entry - * itself (as a parameter - res_dir). It does NOT read the inode of the - * entry - you'll have to do that yourself if you want to. - */ -static struct buffer_head * -xiafs_find_entry(struct inode * inode, const char * name, int namelen, - struct xiafs_direct ** res_dir, struct xiafs_direct ** res_pre) -{ - int i, zones, pos; - struct buffer_head * bh; - struct xiafs_direct * dep, * dep_pre; - - *res_dir = NULL; - if (!inode) - return NULL; - if (namelen > _XIAFS_NAME_LEN) - return NULL; - - if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb) - 1)) { - printk("XIA-FS: bad dir size (%s %d)\n", WHERE_ERR); - return NULL; - } - zones=inode->i_size >> XIAFS_ZSIZE_BITS(inode->i_sb); - for (i=0; i < zones; i++ ) { - bh = xiafs_bread(inode, i, 0); - if (!bh) - continue; - dep_pre=dep=(struct xiafs_direct *)bh->b_data; - if (!i && (dep->d_rec_len != 12 || !dep->d_ino || - dep->d_name_len != 1 || strcmp(dep->d_name, "."))) { - printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR); - brelse(bh); - return NULL; - } - pos = 0; - while ( pos < XIAFS_ZSIZE(inode->i_sb) ) { - if (dep->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes || - dep->d_rec_len < 12 || - dep->d_rec_len+(char *)dep > bh->b_data+XIAFS_ZSIZE(inode->i_sb) || - dep->d_name_len + 8 > dep->d_rec_len || dep->d_name_len <= 0 || - dep->d_name[dep->d_name_len] ) { - brelse(bh); - return NULL; - } - if (xiafs_match(namelen, name, dep)) { - *res_dir=dep; - if (res_pre) - *res_pre=dep_pre; - return bh; - } - pos += dep->d_rec_len; - dep_pre=dep; - dep=(struct xiafs_direct *)(bh->b_data + pos); - } - brelse(bh); - if (pos > XIAFS_ZSIZE(inode->i_sb)) { - printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR); - return NULL; - } - } - return NULL; -} - -int xiafs_lookup(struct inode * dir, const char * name, int len, - struct inode ** result) -{ - int ino; - struct xiafs_direct * dep; - struct buffer_head * bh; - - *result = NULL; - if (!dir) - return -ENOENT; - if (!S_ISDIR(dir->i_mode)) { - iput(dir); - return -ENOENT; - } - if (!(bh = xiafs_find_entry(dir, name, len, &dep, NULL))) { - iput(dir); - return -ENOENT; - } - ino = dep->d_ino; - brelse(bh); - if (!(*result = iget(dir->i_sb, ino))) { - iput(dir); - return -EACCES; - } - iput(dir); - return 0; -} - -/* - * xiafs_add_entry() - * - * adds a file entry to the specified directory, using the same - * semantics as xiafs_find_entry(). It returns NULL if it failed. - * - * NOTE!! The inode part of 'de' is left at 0 - which means you - * may not sleep between calling this and putting something into - * the entry, as someone else might have used it while you slept. - */ -static struct buffer_head * xiafs_add_entry(struct inode * dir, - const char * name, int namelen, struct xiafs_direct ** res_dir, - struct xiafs_direct ** res_pre) -{ - int i, pos, offset; - struct buffer_head * bh; - struct xiafs_direct * de, * de_pre; - - *res_dir = NULL; - if (!dir || !namelen || namelen > _XIAFS_NAME_LEN) - return NULL; - - if (dir->i_size & (XIAFS_ZSIZE(dir->i_sb) - 1)) { - printk("XIA-FS: bad dir size (%s %d)\n", WHERE_ERR); - return NULL; - } - pos=0; - for ( ; ; ) { - bh = xiafs_bread(dir, pos >> XIAFS_ZSIZE_BITS(dir->i_sb), pos ? 1:0); - if (!bh) - return NULL; - de_pre=de=(struct xiafs_direct *)bh->b_data; - if (!pos) { - if (de->d_rec_len != 12 || !de->d_ino || de->d_name_len != 1 || - strcmp(de->d_name, ".")) { - printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR); - brelse(bh); - return NULL; - } - offset = 12; - de_pre=de=(struct xiafs_direct *)(bh->b_data+12); - } else - offset = 0; - while (offset < XIAFS_ZSIZE(dir->i_sb)) { - if (pos >= dir->i_size) { - de->d_ino=0; - de->d_name_len=0; - de->d_name[0]=0; - de->d_rec_len=XIAFS_ZSIZE(dir->i_sb); - dir->i_size += XIAFS_ZSIZE(dir->i_sb); - dir->i_dirt = 1; - } else { - if (de->d_ino > dir->i_sb->u.xiafs_sb.s_ninodes || - de->d_rec_len < 12 || - (char *)de+de->d_rec_len > bh->b_data+XIAFS_ZSIZE(dir->i_sb) || - de->d_name_len + 8 > de->d_rec_len || - de->d_name[de->d_name_len]) { - printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR); - brelse(bh); - return NULL; - } - if (de->d_ino && - RNDUP4(de->d_name_len)+RNDUP4(namelen)+16<=de->d_rec_len) { - i=RNDUP4(de->d_name_len)+8; - de_pre=de; - de=(struct xiafs_direct *)(i+(u_char *)de_pre); - de->d_ino=0; - de->d_rec_len=de_pre->d_rec_len-i; - de_pre->d_rec_len=i; - } - } - if (!de->d_ino && RNDUP4(namelen)+8 <= de->d_rec_len) { - /* - * XXX all times should be set by caller upon successful - * completion. - */ - dir->i_ctime = dir->i_mtime = CURRENT_TIME; - dir->i_dirt = 1; - memcpy(de->d_name, name, namelen); - de->d_name[namelen]=0; - de->d_name_len=namelen; - mark_buffer_dirty(bh, 1); - *res_dir = de; - if (res_pre) - *res_pre = de_pre; - return bh; - } - offset+=de->d_rec_len; - de_pre=de; - de=(struct xiafs_direct *)(bh->b_data+offset); - } - brelse(bh); - if (offset > XIAFS_ZSIZE(dir->i_sb)) { - printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR); - return NULL; - } - pos+=XIAFS_ZSIZE(dir->i_sb); - } - return NULL; -} - -int xiafs_create(struct inode * dir, const char * name, int len, int mode, - struct inode ** result) -{ - struct inode * inode; - struct buffer_head * bh; - struct xiafs_direct * de; - - *result = NULL; - if (!dir) - return -ENOENT; - inode = xiafs_new_inode(dir); - if (!inode) { - iput(dir); - return -ENOSPC; - } - inode->i_op = &xiafs_file_inode_operations; - inode->i_mode = mode; - inode->i_dirt = 1; - bh = xiafs_add_entry(dir, name, len, &de, NULL); - if (!bh) { - inode->i_nlink--; - inode->i_dirt = 1; - iput(inode); - iput(dir); - return -ENOSPC; - } - de->d_ino = inode->i_ino; - mark_buffer_dirty(bh, 1); - brelse(bh); - iput(dir); - *result = inode; - return 0; -} - -int xiafs_mknod(struct inode *dir, const char *name, int len, int mode, int rdev) -{ - struct inode * inode; - struct buffer_head * bh; - struct xiafs_direct * de; - - if (!dir) - return -ENOENT; - bh = xiafs_find_entry(dir,name,len,&de, NULL); - if (bh) { - brelse(bh); - iput(dir); - return -EEXIST; - } - inode = xiafs_new_inode(dir); - if (!inode) { - iput(dir); - return -ENOSPC; - } - inode->i_uid = current->fsuid; - inode->i_mode = mode; - inode->i_op = NULL; - if (S_ISREG(inode->i_mode)) - inode->i_op = &xiafs_file_inode_operations; - else if (S_ISDIR(inode->i_mode)) { - inode->i_op = &xiafs_dir_inode_operations; - if (dir->i_mode & S_ISGID) - inode->i_mode |= S_ISGID; - } - else if (S_ISLNK(inode->i_mode)) - inode->i_op = &xiafs_symlink_inode_operations; - else if (S_ISCHR(inode->i_mode)) - inode->i_op = &chrdev_inode_operations; - else if (S_ISBLK(inode->i_mode)) - inode->i_op = &blkdev_inode_operations; - else if (S_ISFIFO(inode->i_mode)) - init_fifo(inode); - if (S_ISBLK(mode) || S_ISCHR(mode)) - inode->i_rdev = to_kdev_t(rdev); - inode->i_atime = inode->i_ctime = inode->i_atime = CURRENT_TIME; - inode->i_dirt = 1; - bh = xiafs_add_entry(dir, name, len, &de, NULL); - if (!bh) { - inode->i_nlink--; - inode->i_dirt = 1; - iput(inode); - iput(dir); - return -ENOSPC; - } - de->d_ino = inode->i_ino; - mark_buffer_dirty(bh, 1); - brelse(bh); - iput(dir); - iput(inode); - return 0; -} - -int xiafs_mkdir(struct inode * dir, const char * name, int len, int mode) -{ - struct inode * inode; - struct buffer_head * bh, *dir_block; - struct xiafs_direct * de; - - bh = xiafs_find_entry(dir,name,len,&de, NULL); - if (bh) { - brelse(bh); - iput(dir); - return -EEXIST; - } - if (dir->i_nlink > 64000) { - iput(dir); - return -EMLINK; - } - inode = xiafs_new_inode(dir); - if (!inode) { - iput(dir); - return -ENOSPC; - } - inode->i_op = &xiafs_dir_inode_operations; - inode->i_size = XIAFS_ZSIZE(dir->i_sb); - inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME; - inode->i_dirt = 1; - dir_block = xiafs_bread(inode,0,1); - if (!dir_block) { - iput(dir); - inode->i_nlink--; - inode->i_dirt = 1; - iput(inode); - return -ENOSPC; - } - de = (struct xiafs_direct *) dir_block->b_data; - de->d_ino=inode->i_ino; - strcpy(de->d_name,"."); - de->d_name_len=1; - de->d_rec_len=12; - de =(struct xiafs_direct *)(12 + dir_block->b_data); - de->d_ino = dir->i_ino; - strcpy(de->d_name,".."); - de->d_name_len=2; - de->d_rec_len=XIAFS_ZSIZE(dir->i_sb)-12; - inode->i_nlink = 2; - mark_buffer_dirty(dir_block, 1); - brelse(dir_block); - inode->i_mode = S_IFDIR | (mode & S_IRWXUGO & ~current->fs->umask); - if (dir->i_mode & S_ISGID) - inode->i_mode |= S_ISGID; - inode->i_dirt = 1; - bh = xiafs_add_entry(dir, name, len, &de, NULL); - if (!bh) { - iput(dir); - inode->i_nlink=0; - iput(inode); - return -ENOSPC; - } - de->d_ino = inode->i_ino; - mark_buffer_dirty(bh, 1); - dir->i_nlink++; - dir->i_dirt = 1; - iput(dir); - iput(inode); - brelse(bh); - return 0; -} - -/* - * routine to check that the specified directory is empty (for rmdir) - */ -static int empty_dir(struct inode * inode) -{ - int i, zones, offset; - struct buffer_head * bh; - struct xiafs_direct * de; - - if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb)-1) ) { - printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR); - return 1; - } - - zones=inode->i_size >> XIAFS_ZSIZE_BITS(inode->i_sb); - for (i=0; i < zones; i++) { - bh = xiafs_bread(inode, i, 0); - if (!i) { - if (!bh) { - printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR); - return 1; - } - de=(struct xiafs_direct *)bh->b_data; - if (de->d_ino != inode->i_ino || strcmp(".", de->d_name) || - de->d_rec_len != 12 ) { - printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR); - brelse(bh); - return 1; - } - de=(struct xiafs_direct *)(12 + bh->b_data); - if (!de->d_ino || strcmp("..", de->d_name)) { - printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR); - brelse(bh); - return 1; - } - offset=de->d_rec_len+12; - } - else - offset = 0; - if (!bh) - continue; - while (offset < XIAFS_ZSIZE(inode->i_sb)) { - de=(struct xiafs_direct *)(bh->b_data+offset); - if (de->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes || - de->d_rec_len < 12 || - (char *)de+de->d_rec_len > bh->b_data+XIAFS_ZSIZE(inode->i_sb) || - de->d_name_len + 8 > de->d_rec_len || - de->d_name[de->d_name_len]) { - printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR); - brelse(bh); - return 1; - } - if (de->d_ino) { - brelse(bh); - return 0; - } - offset+=de->d_rec_len; - } - brelse(bh); - } - return 1; -} - -static void xiafs_rm_entry(struct xiafs_direct *de, struct xiafs_direct * de_pre) -{ - if (de==de_pre) { - de->d_ino=0; - return; - } - while (de_pre->d_rec_len+(u_char *)de_pre < (u_char *)de) { - if (de_pre->d_rec_len < 12) { - printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR); - return; - } - de_pre=(struct xiafs_direct *)(de_pre->d_rec_len+(u_char *)de_pre); - } - if (de_pre->d_rec_len+(u_char *)de_pre > (u_char *)de) { - printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR); - return; - } - de_pre->d_rec_len+=de->d_rec_len; -} - -int xiafs_rmdir(struct inode * dir, const char * name, int len) -{ - int retval; - struct inode * inode; - struct buffer_head * bh; - struct xiafs_direct * de, * de_pre; - - inode = NULL; - bh = xiafs_find_entry(dir, name, len, &de, &de_pre); - retval = -ENOENT; - if (!bh) - goto end_rmdir; - retval = -EPERM; - if (!(inode = iget(dir->i_sb, de->d_ino))) - goto end_rmdir; - if ((dir->i_mode & S_ISVTX) && !fsuser() && - current->fsuid != inode->i_uid && - current->fsuid != dir->i_uid) - goto end_rmdir; - if (inode->i_dev != dir->i_dev) - goto end_rmdir; - if (inode == dir) /* we may not delete ".", but "../dir" is ok */ - goto end_rmdir; - if (!S_ISDIR(inode->i_mode)) { - retval = -ENOTDIR; - goto end_rmdir; - } - if (!empty_dir(inode)) { - retval = -ENOTEMPTY; - goto end_rmdir; - } - if (inode->i_count > 1) { - retval = -EBUSY; - goto end_rmdir; - } - if (inode->i_nlink != 2) - printk("XIA-FS: empty directory has nlink!=2 (%s %d)\n", WHERE_ERR); - xiafs_rm_entry(de, de_pre); - mark_buffer_dirty(bh, 1); - inode->i_nlink=0; - inode->i_dirt=1; - dir->i_nlink--; - inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; - dir->i_dirt=1; - retval = 0; -end_rmdir: - iput(dir); - iput(inode); - brelse(bh); - return retval; -} - -int xiafs_unlink(struct inode * dir, const char * name, int len) -{ - int retval; - struct inode * inode; - struct buffer_head * bh; - struct xiafs_direct * de, * de_pre; - -repeat: - retval = -ENOENT; - inode = NULL; - bh = xiafs_find_entry(dir, name, len, &de, &de_pre); - if (!bh) - goto end_unlink; - if (!(inode = iget(dir->i_sb, de->d_ino))) - goto end_unlink; - retval = -EPERM; - if (S_ISDIR(inode->i_mode)) - goto end_unlink; - if (de->d_ino != inode->i_ino) { - iput(inode); - brelse(bh); - current->counter = 0; - schedule(); - goto repeat; - } - if ((dir->i_mode & S_ISVTX) && !fsuser() && - current->fsuid != inode->i_uid && - current->fsuid != dir->i_uid) - goto end_unlink; - if (!inode->i_nlink) { - printk("XIA-FS: Deleting nonexistent file (%s %d)\n", WHERE_ERR); - inode->i_nlink=1; - } - xiafs_rm_entry(de, de_pre); - mark_buffer_dirty(bh, 1); - inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; - dir->i_dirt = 1; - inode->i_nlink--; - inode->i_dirt = 1; - retval = 0; -end_unlink: - brelse(bh); - iput(inode); - iput(dir); - return retval; -} - -int xiafs_symlink(struct inode * dir, const char * name, - int len, const char * symname) -{ - struct xiafs_direct * de; - struct inode * inode = NULL; - struct buffer_head * bh = NULL, * name_block = NULL; - int i; - char c; - - bh = xiafs_find_entry(dir,name,len, &de, NULL); - if (bh) { - brelse(bh); - iput(dir); - return -EEXIST; - } - if (!(inode = xiafs_new_inode(dir))) { - iput(dir); - return -ENOSPC; - } - inode->i_mode = S_IFLNK | S_IRWXUGO; - inode->i_op = &xiafs_symlink_inode_operations; - name_block = xiafs_bread(inode,0,1); - if (!name_block) { - iput(dir); - inode->i_nlink--; - inode->i_dirt = 1; - iput(inode); - return -ENOSPC; - } - for (i = 0; i < BLOCK_SIZE-1 && (c=*symname++); i++) - name_block->b_data[i] = c; - name_block->b_data[i] = 0; - mark_buffer_dirty(name_block, 1); - brelse(name_block); - inode->i_size = i; - inode->i_dirt = 1; - bh = xiafs_add_entry(dir, name, len, &de, NULL); - if (!bh) { - inode->i_nlink--; - inode->i_dirt = 1; - iput(inode); - iput(dir); - return -ENOSPC; - } - de->d_ino = inode->i_ino; - mark_buffer_dirty(bh, 1); - brelse(bh); - iput(dir); - iput(inode); - return 0; -} - -int xiafs_link(struct inode * oldinode, struct inode * dir, - const char * name, int len) -{ - struct xiafs_direct * de; - struct buffer_head * bh; - - if (S_ISDIR(oldinode->i_mode)) { - iput(oldinode); - iput(dir); - return -EPERM; - } - if (oldinode->i_nlink > 64000) { - iput(oldinode); - iput(dir); - return -EMLINK; - } - bh = xiafs_find_entry(dir, name, len, &de, NULL); - if (bh) { - brelse(bh); - iput(dir); - iput(oldinode); - return -EEXIST; - } - bh = xiafs_add_entry(dir, name, len, &de, NULL); - if (!bh) { - iput(dir); - iput(oldinode); - return -ENOSPC; - } - de->d_ino = oldinode->i_ino; - mark_buffer_dirty(bh, 1); - brelse(bh); - iput(dir); - oldinode->i_nlink++; - oldinode->i_ctime = CURRENT_TIME; - oldinode->i_dirt = 1; - iput(oldinode); - return 0; -} - -static int subdir(struct inode * new_inode, struct inode * old_inode) -{ - int ino; - int result; - - new_inode->i_count++; - result = 0; - for (;;) { - if (new_inode == old_inode) { - result = 1; - break; - } - if (new_inode->i_dev != old_inode->i_dev) - break; - ino = new_inode->i_ino; - if (xiafs_lookup(new_inode,"..",2,&new_inode)) - break; - if (new_inode->i_ino == ino) - break; - } - iput(new_inode); - return result; -} - -#define PARENT_INO(buffer) \ - (((struct xiafs_direct *) ((u_char *)(buffer) + 12))->d_ino) - -/* - * rename uses retry to avoid race-conditions: at least they should be minimal. - * it tries to allocate all the blocks, then sanity-checks, and if the sanity- - * checks fail, it tries to restart itself again. Very practical - no changes - * are done until we know everything works ok.. and then all the changes can be - * done in one fell swoop when we have claimed all the buffers needed. - * - * Anybody can rename anything with this: the permission checks are left to the - * higher-level routines. - */ -static int do_xiafs_rename(struct inode * old_dir, const char * old_name, - int old_len, struct inode * new_dir, - const char * new_name, int new_len, - int must_be_dir) -{ - struct inode * old_inode, * new_inode; - struct buffer_head * old_bh, * new_bh, * dir_bh; - struct xiafs_direct * old_de, * old_de_pre, * new_de, * new_de_pre; - int retval; - -try_again: - old_inode = new_inode = NULL; - old_bh = new_bh = dir_bh = NULL; - old_bh = xiafs_find_entry(old_dir, old_name, old_len, &old_de, &old_de_pre); - retval = -ENOENT; - if (!old_bh) - goto end_rename; - old_inode = __iget(old_dir->i_sb, old_de->d_ino, 0); /* don't cross mnt-points */ - if (!old_inode) - goto end_rename; - if (must_be_dir && !S_ISDIR(old_inode->i_mode)) - goto end_rename; - retval = -EPERM; - if ((old_dir->i_mode & S_ISVTX) && - current->fsuid != old_inode->i_uid && - current->fsuid != old_dir->i_uid && !fsuser()) - goto end_rename; - new_bh = xiafs_find_entry(new_dir, new_name, new_len, &new_de, NULL); - if (new_bh) { - new_inode = __iget(new_dir->i_sb, new_de->d_ino, 0); - if (!new_inode) { - brelse(new_bh); - new_bh = NULL; - } - } - if (new_inode == old_inode) { - retval = 0; - goto end_rename; - } - if (new_inode && S_ISDIR(new_inode->i_mode)) { - retval = -EEXIST; - goto end_rename; - } - retval = -EPERM; - if (new_inode && (new_dir->i_mode & S_ISVTX) && - current->fsuid != new_inode->i_uid && - current->fsuid != new_dir->i_uid && !fsuser()) - goto end_rename; - if (S_ISDIR(old_inode->i_mode)) { - retval = -EEXIST; - if (new_bh) - goto end_rename; - if ((retval = permission(old_inode, MAY_WRITE)) != 0) - goto end_rename; - retval = -EINVAL; - if (subdir(new_dir, old_inode)) - goto end_rename; - retval = -EIO; - dir_bh = xiafs_bread(old_inode,0,0); - if (!dir_bh) - goto end_rename; - if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino) - goto end_rename; - retval = -EMLINK; - if (new_dir->i_nlink > 64000) - goto end_rename; - } - if (!new_bh) - new_bh = xiafs_add_entry(new_dir, new_name, new_len, &new_de, &new_de_pre); - retval = -ENOSPC; - if (!new_bh) - goto end_rename; - /* sanity checking */ - if ( (new_inode && (new_de->d_ino != new_inode->i_ino)) - || (new_de->d_ino && !new_inode) - || (old_de->d_ino != old_inode->i_ino)) { - xiafs_rm_entry(new_de, new_de_pre); - brelse(old_bh); - brelse(new_bh); - brelse(dir_bh); - iput(old_inode); - iput(new_inode); - current->counter=0; - schedule(); - goto try_again; - } - xiafs_rm_entry(old_de, old_de_pre); - new_de->d_ino = old_inode->i_ino; - if (new_inode) { - new_inode->i_nlink--; - new_inode->i_dirt = 1; - } - mark_buffer_dirty(old_bh, 1); - mark_buffer_dirty(new_bh, 1); - if (dir_bh) { - PARENT_INO(dir_bh->b_data) = new_dir->i_ino; - mark_buffer_dirty(dir_bh, 1); - old_dir->i_nlink--; - new_dir->i_nlink++; - old_dir->i_dirt = 1; - new_dir->i_dirt = 1; - } - retval = 0; -end_rename: - brelse(dir_bh); - brelse(old_bh); - brelse(new_bh); - iput(old_inode); - iput(new_inode); - iput(old_dir); - iput(new_dir); - return retval; -} - -/* - * Ok, rename also locks out other renames, as they can change the parent of - * a directory, and we don't want any races. Other races are checked for by - * "do_rename()", which restarts if there are inconsistencies. - * - * Note that there is no race between different filesystems: it's only within - * the same device that races occur: many renames can happen at once, as long - * as they are on different partitions. - */ -int xiafs_rename(struct inode * old_dir, const char * old_name, int old_len, - struct inode * new_dir, const char * new_name, int new_len, - int must_be_dir) -{ - static struct wait_queue * wait = NULL; - static int lock = 0; - int result; - - while (lock) - sleep_on(&wait); - lock = 1; - result = do_xiafs_rename(old_dir, old_name, old_len, - new_dir, new_name, new_len, - must_be_dir); - lock = 0; - wake_up(&wait); - return result; -} diff --git a/fs/xiafs/symlink.c b/fs/xiafs/symlink.c deleted file mode 100644 index 1803ae457..000000000 --- a/fs/xiafs/symlink.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * linux/fs/xiafs/symlink.c - * - * Copyright (C) Q. Frank Xia, 1993. - * - * Based on Linus' minix/symlink.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/fs.h> -#include <linux/xia_fs.h> -#include <linux/stat.h> - -#include <asm/uaccess.h> - -static int -xiafs_readlink(struct inode *, char *, int); - -static int -xiafs_follow_link(struct inode *, struct inode *, int, int, struct inode **); - -/* - * symlinks can't do much... - */ -struct inode_operations xiafs_symlink_inode_operations = { - NULL, /* no file-operations */ - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - xiafs_readlink, /* readlink */ - xiafs_follow_link, /* follow_link */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* bmap */ - NULL, /* truncate */ - NULL /* permission */ -}; - -static int xiafs_readlink(struct inode * inode, char * buffer, int buflen) -{ - struct buffer_head * bh; - int i; - char c; - - if (!S_ISLNK(inode->i_mode)) { - iput(inode); - return -EINVAL; - } - if (buflen > BLOCK_SIZE) - buflen = BLOCK_SIZE; - bh = xiafs_bread(inode, 0, 0); - if (!IS_RDONLY (inode)) { - inode->i_atime=CURRENT_TIME; - inode->i_dirt=1; - } - iput(inode); - if (!bh) - return 0; - for (i=0; i < buflen && (c=bh->b_data[i]); i++) - put_user(c, buffer++); - if (i < buflen-1) - put_user('\0', buffer); - brelse(bh); - return i; -} - -static int xiafs_follow_link(struct inode * dir, struct inode * inode, - int flag, int mode, struct inode ** res_inode) -{ - int error; - struct buffer_head * bh; - - *res_inode = NULL; - if (!dir) { - dir = current->fs->root; - dir->i_count++; - } - if (!inode) { - iput(dir); - return -ENOENT; - } - if (!S_ISLNK(inode->i_mode)) { - iput(dir); - *res_inode = inode; - return 0; - } - if (!IS_RDONLY (inode)) { - inode->i_atime=CURRENT_TIME; - inode->i_dirt=1; - } - if (current->link_count > 5) { - iput(inode); - iput(dir); - return -ELOOP; - } - if (!(bh = xiafs_bread(inode, 0, 0))) { - iput(inode); - iput(dir); - return -EIO; - } - iput(inode); - current->link_count++; - error = open_namei(bh->b_data,flag,mode,res_inode,dir); - current->link_count--; - brelse(bh); - return error; -} - - - 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; -} diff --git a/fs/xiafs/xiafs_mac.h b/fs/xiafs/xiafs_mac.h deleted file mode 100644 index 05af6e42a..000000000 --- a/fs/xiafs/xiafs_mac.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * linux/fs/xiafs/xiafs_mac.h - * - * Copyright (C) Q. Frank Xia, 1993. - */ - -extern char internal_error_message[]; -#define INTERN_ERR internal_error_message, __FILE__, __LINE__ -#define WHERE_ERR __FILE__, __LINE__ - -#define XIAFS_ZSHIFT(sp) ((sp)->u.xiafs_sb.s_zone_shift) -#define XIAFS_ZSIZE(sp) (BLOCK_SIZE << XIAFS_ZSHIFT(sp)) -#define XIAFS_ZSIZE_BITS(sp) (BLOCK_SIZE_BITS + XIAFS_ZSHIFT(sp)) -#define XIAFS_ADDRS_PER_Z(sp) (BLOCK_SIZE >> (2 - XIAFS_ZSHIFT(sp))) -#define XIAFS_ADDRS_PER_Z_BITS(sp) (BLOCK_SIZE_BITS - 2 + XIAFS_ZSHIFT(sp)) -#define XIAFS_BITS_PER_Z(sp) (BLOCK_SIZE << (3 + XIAFS_ZSHIFT(sp))) -#define XIAFS_BITS_PER_Z_BITS(sp) (BLOCK_SIZE_BITS + 3 + XIAFS_ZSHIFT(sp)) -#define XIAFS_INODES_PER_Z(sp) (_XIAFS_INODES_PER_BLOCK << XIAFS_ZSHIFT(sp)) - -/* Use the most significant bytes of zone pointers to store block counter. */ -/* This is ugly, but it works. Note, We have another 7 bytes for "expansion". */ - -#define XIAFS_GET_BLOCKS(row_ip, blocks) \ - blocks=((((row_ip)->i_zone[0] >> 24) & 0xff )|\ - (((row_ip)->i_zone[1] >> 16) & 0xff00 )|\ - (((row_ip)->i_zone[2] >> 8) & 0xff0000 ) ) - -/* XIAFS_PUT_BLOCKS should be called before saving zone pointers */ -#define XIAFS_PUT_BLOCKS(row_ip, blocks) \ - (row_ip)->i_zone[2]=((blocks)<< 8) & 0xff000000;\ - (row_ip)->i_zone[1]=((blocks)<<16) & 0xff000000;\ - (row_ip)->i_zone[0]=((blocks)<<24) & 0xff000000 |