4 * Written 1992,1993 by Werner Almesberger
6 * regular file handling primitives for fat-based filesystems
9 #include <linux/time.h>
10 #include <linux/msdos_fs.h>
11 #include <linux/smp_lock.h>
12 #include <linux/buffer_head.h>
14 static ssize_t
fat_file_write(struct file
*filp
, const char __user
*buf
,
15 size_t count
, loff_t
*ppos
);
17 struct file_operations fat_file_operations
= {
18 .llseek
= generic_file_llseek
,
19 .read
= generic_file_read
,
20 .write
= fat_file_write
,
21 .mmap
= generic_file_mmap
,
23 .readv
= generic_file_readv
,
24 .writev
= generic_file_writev
,
25 .sendfile
= generic_file_sendfile
,
28 struct inode_operations fat_file_inode_operations
= {
29 .truncate
= fat_truncate
,
30 .setattr
= fat_notify_change
,
33 int fat_get_block(struct inode
*inode
, sector_t iblock
,
34 struct buffer_head
*bh_result
, int create
)
36 struct super_block
*sb
= inode
->i_sb
;
41 err
= fat_bmap(inode
, iblock
, &phys
);
45 map_bh(bh_result
, sb
, phys
);
50 if (iblock
!= MSDOS_I(inode
)->mmu_private
>> sb
->s_blocksize_bits
) {
51 fat_fs_panic(sb
, "corrupted file size (i_pos %lld, %lld)",
52 MSDOS_I(inode
)->i_pos
, MSDOS_I(inode
)->mmu_private
);
55 if (!((unsigned long)iblock
& (MSDOS_SB(sb
)->sec_per_clus
- 1))) {
58 error
= fat_add_cluster(inode
);
62 MSDOS_I(inode
)->mmu_private
+= sb
->s_blocksize
;
63 err
= fat_bmap(inode
, iblock
, &phys
);
68 set_buffer_new(bh_result
);
69 map_bh(bh_result
, sb
, phys
);
73 static ssize_t
fat_file_write(struct file
*filp
, const char __user
*buf
,
74 size_t count
, loff_t
*ppos
)
76 struct inode
*inode
= filp
->f_dentry
->d_inode
;
79 retval
= generic_file_write(filp
, buf
, count
, ppos
);
81 inode
->i_mtime
= inode
->i_ctime
= CURRENT_TIME
;
82 MSDOS_I(inode
)->i_attrs
|= ATTR_ARCH
;
83 mark_inode_dirty(inode
);
88 void fat_truncate(struct inode
*inode
)
90 struct msdos_sb_info
*sbi
= MSDOS_SB(inode
->i_sb
);
91 const unsigned int cluster_size
= sbi
->cluster_size
;
95 * This protects against truncating a file bigger than it was then
96 * trying to write into the hole.
98 if (MSDOS_I(inode
)->mmu_private
> inode
->i_size
)
99 MSDOS_I(inode
)->mmu_private
= inode
->i_size
;
101 nr_clusters
= (inode
->i_size
+ (cluster_size
- 1)) >> sbi
->cluster_bits
;
104 fat_free(inode
, nr_clusters
);
105 MSDOS_I(inode
)->i_attrs
|= ATTR_ARCH
;
107 inode
->i_ctime
= inode
->i_mtime
= CURRENT_TIME
;
108 mark_inode_dirty(inode
);