patch-2.4.13 linux/fs/fat/misc.c
Next file: linux/fs/fat/msbuffer.h
Previous file: linux/fs/fat/inode.c
Back to the patch index
Back to the overall index
- Lines: 343
- Date:
Fri Oct 12 13:48:42 2001
- Orig file:
v2.4.12/linux/fs/fat/misc.c
- Orig date:
Thu May 24 15:36:34 2001
diff -u --recursive --new-file v2.4.12/linux/fs/fat/misc.c linux/fs/fat/misc.c
@@ -2,6 +2,8 @@
* linux/fs/fat/misc.c
*
* Written 1992,1993 by Werner Almesberger
+ * 22/11/2000 - Fixed fat_date_unix2dos for dates earlier than 01/01/1980
+ * and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru)
*/
#include <linux/fs.h>
@@ -12,8 +14,6 @@
#include <linux/string.h>
#include <linux/stat.h>
-#include "msbuffer.h"
-
#if 0
# define PRINTK(x) printk x
#else
@@ -75,30 +75,11 @@
}
}
-
-/* File creation lock. This is system-wide to avoid deadlocks in rename. */
-/* (rename might deadlock before detecting cross-FS moves.) */
-
-static DECLARE_MUTEX(creation_lock);
-
-void fat_lock_creation(void)
-{
- down(&creation_lock);
-}
-
-
-void fat_unlock_creation(void)
-{
- up(&creation_lock);
-}
-
-
void lock_fat(struct super_block *sb)
{
down(&(MSDOS_SB(sb)->fat_lock));
}
-
void unlock_fat(struct super_block *sb)
{
up(&(MSDOS_SB(sb)->fat_lock));
@@ -132,39 +113,44 @@
}
/*
- * fat_add_cluster tries to allocate a new cluster and adds it to the file
- * represented by inode. The cluster is zero-initialized.
+ * fat_add_cluster tries to allocate a new cluster and adds it to the
+ * file represented by 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 count, nr, limit, last, curr, file_cluster;
+ int cluster_size = MSDOS_SB(sb)->cluster_size;
int res = -ENOSPC;
-
- if (!MSDOS_SB(sb)->free_clusters) return res;
+
lock_fat(sb);
+
+ if (MSDOS_SB(sb)->free_clusters == 0) {
+ unlock_fat(sb);
+ return res;
+ }
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;
+ 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));
+
+ MSDOS_SB(sb)->prev_free = (count + MSDOS_SB(sb)->prev_free + 1) % limit;
+ 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);
-
+
/* We must locate the last cluster of the file to add this
new one (nr) to the end of the link list (the FAT).
@@ -177,12 +163,12 @@
*/
last = file_cluster = 0;
if ((curr = MSDOS_I(inode)->i_start) != 0) {
- fat_cache_lookup(inode,INT_MAX,&last,&curr);
+ 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");
+ fat_fs_panic(sb, "File without EOF");
return res;
}
}
@@ -195,94 +181,34 @@
MSDOS_I(inode)->i_logstart = nr;
mark_inode_dirty(inode);
}
+ if (file_cluster
+ != inode->i_blocks / cluster_size / (sb->s_blocksize / 512)) {
+ printk ("file_cluster badly computed!!! %d <> %ld\n",
+ file_cluster,
+ inode->i_blocks / cluster_size / (sb->s_blocksize / 512));
+ fat_cache_inval_inode(inode);
+ }
inode->i_blocks += (1 << MSDOS_SB(sb)->cluster_bits) / 512;
- return 0;
+
+ return nr;
}
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;
- struct buffer_head *bh, *res=NULL;
+ int nr, sector, last_sector;
+ struct buffer_head *bh, *res = NULL;
int cluster_size = MSDOS_SB(sb)->cluster_size;
if (MSDOS_SB(sb)->fat_bits != 32) {
if (inode->i_ino == MSDOS_ROOT_INO)
return res;
}
- 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;
- }
- PRINTK (("cnt = %d --", count));
-#ifdef DEBUG
- printk("free cluster: %d\n", nr);
-#endif
- if (count >= limit) {
- MSDOS_SB(sb)->free_clusters = 0;
- unlock_fat(sb);
+ nr = fat_add_cluster(inode);
+ if (nr < 0)
return res;
- }
-
- MSDOS_SB(sb)->prev_free = (count + MSDOS_SB(sb)->prev_free + 1) % limit;
- 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);
-
-#ifdef DEBUG
- printk("set to %x\n", fat_access(sb, nr, -1));
-#endif
-
- /* 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.
- */
- last = 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){
- PRINTK (("."));
- file_cluster++;
- if (!(curr = fat_access(sb, last = curr, -1))) {
- fat_fs_panic(sb,"File without EOF");
- return res;
- }
- }
- PRINTK ((" -- "));
- }
-#ifdef DEBUG
- printk("last = %d\n", last);
-#endif
- if (last)
- fat_access(sb, last, nr);
- else {
- MSDOS_I(inode)->i_start = nr;
- MSDOS_I(inode)->i_logstart = nr;
- mark_inode_dirty(inode);
- }
-#ifdef DEBUG
- if (last)
- printk("next set to %d\n",fat_access(sb, last, -1));
-#endif
+
sector = MSDOS_SB(sb)->data_start + (nr - 2) * cluster_size;
last_sector = sector + cluster_size;
if (MSDOS_SB(sb)->cvf_format && MSDOS_SB(sb)->cvf_format->zero_out_cluster)
@@ -305,23 +231,15 @@
}
}
}
- if (file_cluster
- != inode->i_blocks / cluster_size / (sb->s_blocksize / 512)) {
- printk ("file_cluster badly computed!!! %d <> %ld\n",
- file_cluster,
- inode->i_blocks / cluster_size / (sb->s_blocksize / 512));
- }else{
- fat_cache_add(inode, file_cluster, nr);
- }
- inode->i_blocks += (1 << MSDOS_SB(sb)->cluster_bits) / 512;
if (inode->i_size & (sb->s_blocksize - 1)) {
fat_fs_panic(sb, "Odd directory size");
- inode->i_size = (inode->i_size + sb->s_blocksize) &
- ~(sb->s_blocksize - 1);
+ inode->i_size = (inode->i_size + sb->s_blocksize)
+ & ~(sb->s_blocksize - 1);
}
inode->i_size += 1 << MSDOS_SB(sb)->cluster_bits;
MSDOS_I(inode)->mmu_private += 1 << MSDOS_SB(sb)->cluster_bits;
mark_inode_dirty(inode);
+
return res;
}
@@ -340,7 +258,9 @@
{
int month,year,secs;
- month = ((date >> 5) & 15)-1;
+ /* first subtract and mask after that... Otherwise, if
+ date == 0, bad things happen */
+ month = ((date >> 5) - 1) & 15;
year = date >> 9;
secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400*
((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
@@ -359,7 +279,10 @@
int day,year,nl_day,month;
unix_date -= sys_tz.tz_minuteswest*60;
- if (sys_tz.tz_dsttime) unix_date += 3600;
+
+ /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */
+ if (unix_date < 315532800)
+ unix_date = 315532800;
*time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
(((unix_date/3600) % 24) << 11);
@@ -592,61 +515,9 @@
}
/*
- * fat_parent_ino returns the inode number of the parent directory of dir.
- * File creation has to be deferred while fat_parent_ino is running to
- * prevent renames.
- *
- * AV. Bad, bad, bad... We need a mapping that would give us inode by
- * first cluster. Sheeeeit... OK, we can do it on fat_fill_inode() and
- * update on fat_add_cluster(). When will we remove it? fat_clear_inode()
- * and fat_truncate() to zero?
- */
-
-int fat_parent_ino(struct inode *dir,int locked)
-{
- static int zero = 0;
- int error,curr,prev,nr;
-
- PRINTK(("fat_parent_ino: Debug 0\n"));
- if (!S_ISDIR(dir->i_mode)) panic("Non-directory fed to m_p_i");
- if (dir->i_ino == MSDOS_ROOT_INO) return dir->i_ino;
- if (!locked) fat_lock_creation(); /* prevent renames */
- if ((curr = raw_scan(dir->i_sb,MSDOS_I(dir)->i_start,MSDOS_DOTDOT,
- &zero,NULL,NULL,NULL)) < 0) {
- if (!locked) fat_unlock_creation();
- return curr;
- }
- PRINTK(("fat_parent_ino: Debug 1 curr=%d\n", curr));
- if (!curr) nr = MSDOS_ROOT_INO;
- else {
- PRINTK(("fat_parent_ino: Debug 2\n"));
- if ((prev = raw_scan(dir->i_sb,curr,MSDOS_DOTDOT,&zero,NULL,
- NULL,NULL)) < 0) {
- PRINTK(("fat_parent_ino: Debug 3 prev=%d\n", prev));
- if (!locked) fat_unlock_creation();
- return prev;
- }
- PRINTK(("fat_parent_ino: Debug 4 prev=%d\n", prev));
- if (prev == 0 && MSDOS_SB(dir->i_sb)->fat_bits == 32) {
- prev = MSDOS_SB(dir->i_sb)->root_cluster;
- }
- if ((error = raw_scan(dir->i_sb,prev,NULL,&curr,&nr,NULL,
- NULL)) < 0) {
- PRINTK(("fat_parent_ino: Debug 5 error=%d\n", error));
- if (!locked) fat_unlock_creation();
- return error;
- }
- PRINTK(("fat_parent_ino: Debug 6 nr=%d\n", nr));
- }
- if (!locked) fat_unlock_creation();
- return nr;
-}
-
-/*
* fat_subdirs counts the number of sub-directories of dir. It can be run
* on directories being created.
*/
-
int fat_subdirs(struct inode *dir)
{
int count;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)