diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-10-09 00:00:47 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-10-09 00:00:47 +0000 |
commit | d6434e1042f3b0a6dfe1b1f615af369486f9b1fa (patch) | |
tree | e2be02f33984c48ec019c654051d27964e42c441 /fs/fat/misc.c | |
parent | 609d1e803baf519487233b765eb487f9ec227a18 (diff) |
Merge with 2.3.19.
Diffstat (limited to 'fs/fat/misc.c')
-rw-r--r-- | fs/fat/misc.c | 110 |
1 files changed, 77 insertions, 33 deletions
diff --git a/fs/fat/misc.c b/fs/fat/misc.c index 4cd218d58..cd2762732 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c @@ -79,35 +79,29 @@ int fat_is_binary(char conversion,char *extension) /* File creation lock. This is system-wide to avoid deadlocks in rename. */ /* (rename might deadlock before detecting cross-FS moves.) */ -static DECLARE_WAIT_QUEUE_HEAD(creation_wait); -static int creation_lock = 0; - +static DECLARE_MUTEX(creation_lock); void fat_lock_creation(void) { - while (creation_lock) sleep_on(&creation_wait); - creation_lock = 1; + down(&creation_lock); } void fat_unlock_creation(void) { - creation_lock = 0; - wake_up(&creation_wait); + up(&creation_lock); } void lock_fat(struct super_block *sb) { - while (MSDOS_SB(sb)->fat_lock) sleep_on(&MSDOS_SB(sb)->fat_wait); - MSDOS_SB(sb)->fat_lock = 1; + down(&(MSDOS_SB(sb)->fat_lock)); } void unlock_fat(struct super_block *sb) { - MSDOS_SB(sb)->fat_lock = 0; - wake_up(&MSDOS_SB(sb)->fat_wait); + up(&(MSDOS_SB(sb)->fat_lock)); } /* Flushes the number of free clusters on FAT32 */ @@ -144,7 +138,70 @@ void fat_clusters_flush(struct super_block *sb) * represented by inode. The cluster is zero-initialized. */ -struct buffer_head *fat_add_cluster1(struct inode *inode) +/* not a directory */ + +int fat_add_cluster(struct inode *inode) +{ + struct super_block *sb = inode->i_sb; + int count,nr,limit,last,curr,file_cluster; + int res = -ENOSPC; + int cluster_size = MSDOS_SB(sb)->cluster_size; + + if (!MSDOS_SB(sb)->free_clusters) return res; + lock_fat(sb); + limit = MSDOS_SB(sb)->clusters; + nr = limit; /* to keep GCC happy */ + for (count = 0; count < limit; count++) { + nr = ((count+MSDOS_SB(sb)->prev_free) % limit)+2; + if (fat_access(sb,nr,-1) == 0) break; + } + MSDOS_SB(sb)->prev_free = (count+MSDOS_SB(sb)->prev_free+1) % limit; + if (count >= limit) { + MSDOS_SB(sb)->free_clusters = 0; + unlock_fat(sb); + return res; + } + fat_access(sb,nr,EOF_FAT(sb)); + if (MSDOS_SB(sb)->free_clusters != -1) + MSDOS_SB(sb)->free_clusters--; + if (MSDOS_SB(sb)->fat_bits == 32) + fat_clusters_flush(sb); + unlock_fat(sb); + last = 0; + /* We must locate the last cluster of the file to add this + new one (nr) to the end of the link list (the FAT). + + Here file_cluster will be the number of the last cluster of the + file (before we add nr). + + last is the corresponding cluster number on the disk. We will + use last to plug the nr cluster. We will use file_cluster to + update the cache. + */ + file_cluster = 0; + if ((curr = MSDOS_I(inode)->i_start) != 0) { + fat_cache_lookup(inode,INT_MAX,&last,&curr); + file_cluster = last; + while (curr && curr != -1){ + file_cluster++; + if (!(curr = fat_access(sb, last = curr,-1))) { + fat_fs_panic(sb,"File without EOF"); + return res; + } + } + } + if (last) fat_access(sb,last,nr); + else { + MSDOS_I(inode)->i_start = nr; + MSDOS_I(inode)->i_logstart = nr; + mark_inode_dirty(inode); + } + fat_cache_add(inode,file_cluster,nr); + inode->i_blocks += cluster_size; + return 0; +} + +struct buffer_head *fat_extend_dir(struct inode *inode) { struct super_block *sb = inode->i_sb; int count,nr,limit,last,curr,sector,last_sector,file_cluster; @@ -248,30 +305,17 @@ if (last) printk("next set to %d\n",fat_access(sb,last,-1)); fat_cache_add(inode,file_cluster,nr); } inode->i_blocks += cluster_size; - if (S_ISDIR(inode->i_mode)) { - if (inode->i_size & (SECTOR_SIZE-1)) { - fat_fs_panic(sb,"Odd directory size"); - inode->i_size = (inode->i_size+SECTOR_SIZE) & - ~(SECTOR_SIZE-1); - } - inode->i_size += SECTOR_SIZE*cluster_size; -#ifdef DEBUG -printk("size is %d now (%x)\n",inode->i_size,inode); -#endif - mark_inode_dirty(inode); + if (inode->i_size & (SECTOR_SIZE-1)) { + fat_fs_panic(sb,"Odd directory size"); + inode->i_size = (inode->i_size+SECTOR_SIZE) & + ~(SECTOR_SIZE-1); } + inode->i_size += SECTOR_SIZE*cluster_size; + MSDOS_I(inode)->i_realsize += SECTOR_SIZE*cluster_size; + mark_inode_dirty(inode); return res; } -int fat_add_cluster(struct inode *inode) -{ - struct buffer_head *bh = fat_add_cluster1(inode); - if (!bh) - return -ENOSPC; - fat_brelse(inode->i_sb, bh); - return 0; -} - /* Linear day numbers of the respective 1sts in non-leap years. */ static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 }; @@ -351,7 +395,7 @@ int fat__get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh, if (*bh) fat_brelse(sb, *bh); *bh = NULL; - if ((sector = fat_smap(dir,offset >> SECTOR_BITS)) == -1) + if ((sector = fat_bmap(dir,offset >> SECTOR_BITS)) == -1) return -1; PRINTK (("get_entry sector %d %p\n",sector,*bh)); PRINTK (("get_entry sector apres brelse\n")); |