0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include "fat.h"
0011 #include <linux/iversion.h>
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 void __fat_fs_error(struct super_block *sb, int report, const char *fmt, ...)
0022 {
0023 struct fat_mount_options *opts = &MSDOS_SB(sb)->options;
0024 va_list args;
0025 struct va_format vaf;
0026
0027 if (report) {
0028 va_start(args, fmt);
0029 vaf.fmt = fmt;
0030 vaf.va = &args;
0031 fat_msg(sb, KERN_ERR, "error, %pV", &vaf);
0032 va_end(args);
0033 }
0034
0035 if (opts->errors == FAT_ERRORS_PANIC)
0036 panic("FAT-fs (%s): fs panic from previous error\n", sb->s_id);
0037 else if (opts->errors == FAT_ERRORS_RO && !sb_rdonly(sb)) {
0038 sb->s_flags |= SB_RDONLY;
0039 fat_msg(sb, KERN_ERR, "Filesystem has been set read-only");
0040 }
0041 }
0042 EXPORT_SYMBOL_GPL(__fat_fs_error);
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 void _fat_msg(struct super_block *sb, const char *level, const char *fmt, ...)
0055 {
0056 struct va_format vaf;
0057 va_list args;
0058
0059 va_start(args, fmt);
0060 vaf.fmt = fmt;
0061 vaf.va = &args;
0062 _printk(FAT_PRINTK_PREFIX "%pV\n", level, sb->s_id, &vaf);
0063 va_end(args);
0064 }
0065
0066
0067
0068 int fat_clusters_flush(struct super_block *sb)
0069 {
0070 struct msdos_sb_info *sbi = MSDOS_SB(sb);
0071 struct buffer_head *bh;
0072 struct fat_boot_fsinfo *fsinfo;
0073
0074 if (!is_fat32(sbi))
0075 return 0;
0076
0077 bh = sb_bread(sb, sbi->fsinfo_sector);
0078 if (bh == NULL) {
0079 fat_msg(sb, KERN_ERR, "bread failed in fat_clusters_flush");
0080 return -EIO;
0081 }
0082
0083 fsinfo = (struct fat_boot_fsinfo *)bh->b_data;
0084
0085 if (!IS_FSINFO(fsinfo)) {
0086 fat_msg(sb, KERN_ERR, "Invalid FSINFO signature: "
0087 "0x%08x, 0x%08x (sector = %lu)",
0088 le32_to_cpu(fsinfo->signature1),
0089 le32_to_cpu(fsinfo->signature2),
0090 sbi->fsinfo_sector);
0091 } else {
0092 if (sbi->free_clusters != -1)
0093 fsinfo->free_clusters = cpu_to_le32(sbi->free_clusters);
0094 if (sbi->prev_free != -1)
0095 fsinfo->next_cluster = cpu_to_le32(sbi->prev_free);
0096 mark_buffer_dirty(bh);
0097 }
0098 brelse(bh);
0099
0100 return 0;
0101 }
0102
0103
0104
0105
0106
0107 int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster)
0108 {
0109 struct super_block *sb = inode->i_sb;
0110 struct msdos_sb_info *sbi = MSDOS_SB(sb);
0111 int ret, new_fclus, last;
0112
0113
0114
0115
0116
0117 last = new_fclus = 0;
0118 if (MSDOS_I(inode)->i_start) {
0119 int fclus, dclus;
0120
0121 ret = fat_get_cluster(inode, FAT_ENT_EOF, &fclus, &dclus);
0122 if (ret < 0)
0123 return ret;
0124 new_fclus = fclus + 1;
0125 last = dclus;
0126 }
0127
0128
0129 if (last) {
0130 struct fat_entry fatent;
0131
0132 fatent_init(&fatent);
0133 ret = fat_ent_read(inode, &fatent, last);
0134 if (ret >= 0) {
0135 int wait = inode_needs_sync(inode);
0136 ret = fat_ent_write(inode, &fatent, new_dclus, wait);
0137 fatent_brelse(&fatent);
0138 }
0139 if (ret < 0)
0140 return ret;
0141
0142
0143
0144
0145
0146 } else {
0147 MSDOS_I(inode)->i_start = new_dclus;
0148 MSDOS_I(inode)->i_logstart = new_dclus;
0149
0150
0151
0152
0153 if (S_ISDIR(inode->i_mode) && IS_DIRSYNC(inode)) {
0154 ret = fat_sync_inode(inode);
0155 if (ret)
0156 return ret;
0157 } else
0158 mark_inode_dirty(inode);
0159 }
0160 if (new_fclus != (inode->i_blocks >> (sbi->cluster_bits - 9))) {
0161 fat_fs_error(sb, "clusters badly computed (%d != %llu)",
0162 new_fclus,
0163 (llu)(inode->i_blocks >> (sbi->cluster_bits - 9)));
0164 fat_cache_inval_inode(inode);
0165 }
0166 inode->i_blocks += nr_cluster << (sbi->cluster_bits - 9);
0167
0168 return 0;
0169 }
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181 #define SECS_PER_MIN 60
0182 #define SECS_PER_HOUR (60 * 60)
0183 #define SECS_PER_DAY (SECS_PER_HOUR * 24)
0184
0185 #define DAYS_DELTA (365 * 10 + 2)
0186
0187 #define YEAR_2100 120
0188 #define IS_LEAP_YEAR(y) (!((y) & 3) && (y) != YEAR_2100)
0189
0190
0191 static long days_in_year[] = {
0192
0193 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0,
0194 };
0195
0196 static inline int fat_tz_offset(const struct msdos_sb_info *sbi)
0197 {
0198 return (sbi->options.tz_set ?
0199 -sbi->options.time_offset :
0200 sys_tz.tz_minuteswest) * SECS_PER_MIN;
0201 }
0202
0203
0204 void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec64 *ts,
0205 __le16 __time, __le16 __date, u8 time_cs)
0206 {
0207 u16 time = le16_to_cpu(__time), date = le16_to_cpu(__date);
0208 time64_t second;
0209 long day, leap_day, month, year;
0210
0211 year = date >> 9;
0212 month = max(1, (date >> 5) & 0xf);
0213 day = max(1, date & 0x1f) - 1;
0214
0215 leap_day = (year + 3) / 4;
0216 if (year > YEAR_2100)
0217 leap_day--;
0218 if (IS_LEAP_YEAR(year) && month > 2)
0219 leap_day++;
0220
0221 second = (time & 0x1f) << 1;
0222 second += ((time >> 5) & 0x3f) * SECS_PER_MIN;
0223 second += (time >> 11) * SECS_PER_HOUR;
0224 second += (time64_t)(year * 365 + leap_day
0225 + days_in_year[month] + day
0226 + DAYS_DELTA) * SECS_PER_DAY;
0227
0228 second += fat_tz_offset(sbi);
0229
0230 if (time_cs) {
0231 ts->tv_sec = second + (time_cs / 100);
0232 ts->tv_nsec = (time_cs % 100) * 10000000;
0233 } else {
0234 ts->tv_sec = second;
0235 ts->tv_nsec = 0;
0236 }
0237 }
0238
0239
0240 EXPORT_SYMBOL_GPL(fat_time_fat2unix);
0241
0242
0243 void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec64 *ts,
0244 __le16 *time, __le16 *date, u8 *time_cs)
0245 {
0246 struct tm tm;
0247 time64_to_tm(ts->tv_sec, -fat_tz_offset(sbi), &tm);
0248
0249
0250 if (tm.tm_year < 1980 - 1900) {
0251 *time = 0;
0252 *date = cpu_to_le16((0 << 9) | (1 << 5) | 1);
0253 if (time_cs)
0254 *time_cs = 0;
0255 return;
0256 }
0257 if (tm.tm_year > 2107 - 1900) {
0258 *time = cpu_to_le16((23 << 11) | (59 << 5) | 29);
0259 *date = cpu_to_le16((127 << 9) | (12 << 5) | 31);
0260 if (time_cs)
0261 *time_cs = 199;
0262 return;
0263 }
0264
0265
0266 tm.tm_year -= 80;
0267
0268 tm.tm_mon++;
0269
0270 tm.tm_sec >>= 1;
0271
0272 *time = cpu_to_le16(tm.tm_hour << 11 | tm.tm_min << 5 | tm.tm_sec);
0273 *date = cpu_to_le16(tm.tm_year << 9 | tm.tm_mon << 5 | tm.tm_mday);
0274 if (time_cs)
0275 *time_cs = (ts->tv_sec & 1) * 100 + ts->tv_nsec / 10000000;
0276 }
0277 EXPORT_SYMBOL_GPL(fat_time_unix2fat);
0278
0279 static inline struct timespec64 fat_timespec64_trunc_2secs(struct timespec64 ts)
0280 {
0281 return (struct timespec64){ ts.tv_sec & ~1ULL, 0 };
0282 }
0283
0284
0285
0286
0287 struct timespec64 fat_truncate_atime(const struct msdos_sb_info *sbi,
0288 const struct timespec64 *ts)
0289 {
0290
0291 time64_t seconds = ts->tv_sec - fat_tz_offset(sbi);
0292 s32 remainder;
0293
0294 div_s64_rem(seconds, SECS_PER_DAY, &remainder);
0295
0296 seconds = seconds + fat_tz_offset(sbi) - remainder;
0297
0298 return (struct timespec64){ seconds, 0 };
0299 }
0300
0301
0302
0303
0304 struct timespec64 fat_truncate_mtime(const struct msdos_sb_info *sbi,
0305 const struct timespec64 *ts)
0306 {
0307 return fat_timespec64_trunc_2secs(*ts);
0308 }
0309
0310
0311
0312
0313
0314 int fat_truncate_time(struct inode *inode, struct timespec64 *now, int flags)
0315 {
0316 struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
0317 struct timespec64 ts;
0318
0319 if (inode->i_ino == MSDOS_ROOT_INO)
0320 return 0;
0321
0322 if (now == NULL) {
0323 now = &ts;
0324 ts = current_time(inode);
0325 }
0326
0327 if (flags & S_ATIME)
0328 inode->i_atime = fat_truncate_atime(sbi, now);
0329
0330
0331
0332
0333
0334 if (flags & S_MTIME)
0335 inode->i_mtime = inode->i_ctime = fat_truncate_mtime(sbi, now);
0336
0337 return 0;
0338 }
0339 EXPORT_SYMBOL_GPL(fat_truncate_time);
0340
0341 int fat_update_time(struct inode *inode, struct timespec64 *now, int flags)
0342 {
0343 int dirty_flags = 0;
0344
0345 if (inode->i_ino == MSDOS_ROOT_INO)
0346 return 0;
0347
0348 if (flags & (S_ATIME | S_CTIME | S_MTIME)) {
0349 fat_truncate_time(inode, now, flags);
0350 if (inode->i_sb->s_flags & SB_LAZYTIME)
0351 dirty_flags |= I_DIRTY_TIME;
0352 else
0353 dirty_flags |= I_DIRTY_SYNC;
0354 }
0355
0356 if ((flags & S_VERSION) && inode_maybe_inc_iversion(inode, false))
0357 dirty_flags |= I_DIRTY_SYNC;
0358
0359 __mark_inode_dirty(inode, dirty_flags);
0360 return 0;
0361 }
0362 EXPORT_SYMBOL_GPL(fat_update_time);
0363
0364 int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs)
0365 {
0366 int i, err = 0;
0367
0368 for (i = 0; i < nr_bhs; i++)
0369 write_dirty_buffer(bhs[i], 0);
0370
0371 for (i = 0; i < nr_bhs; i++) {
0372 wait_on_buffer(bhs[i]);
0373 if (!err && !buffer_uptodate(bhs[i]))
0374 err = -EIO;
0375 }
0376 return err;
0377 }