mirror of
https://github.com/torvalds/linux.git
synced 2024-11-19 02:21:47 +00:00
Merge branch 'hpfs' (patches from Mikulas)
Merge hpfs upddate from Mikulas Patocka. * emailed patches from Mikulas Patocka <mikulas@twibright.com>: hpfs: update ctime and mtime on directory modification hpfs: support hotfixes
This commit is contained in:
commit
824b005c86
@ -10,6 +10,30 @@
|
||||
#include <linux/blkdev.h>
|
||||
#include "hpfs_fn.h"
|
||||
|
||||
secno hpfs_search_hotfix_map(struct super_block *s, secno sec)
|
||||
{
|
||||
unsigned i;
|
||||
struct hpfs_sb_info *sbi = hpfs_sb(s);
|
||||
for (i = 0; unlikely(i < sbi->n_hotfixes); i++) {
|
||||
if (sbi->hotfix_from[i] == sec) {
|
||||
return sbi->hotfix_to[i];
|
||||
}
|
||||
}
|
||||
return sec;
|
||||
}
|
||||
|
||||
unsigned hpfs_search_hotfix_map_for_range(struct super_block *s, secno sec, unsigned n)
|
||||
{
|
||||
unsigned i;
|
||||
struct hpfs_sb_info *sbi = hpfs_sb(s);
|
||||
for (i = 0; unlikely(i < sbi->n_hotfixes); i++) {
|
||||
if (sbi->hotfix_from[i] >= sec && sbi->hotfix_from[i] < sec + n) {
|
||||
n = sbi->hotfix_from[i] - sec;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void hpfs_prefetch_sectors(struct super_block *s, unsigned secno, int n)
|
||||
{
|
||||
struct buffer_head *bh;
|
||||
@ -18,6 +42,9 @@ void hpfs_prefetch_sectors(struct super_block *s, unsigned secno, int n)
|
||||
if (n <= 0 || unlikely(secno >= hpfs_sb(s)->sb_fs_size))
|
||||
return;
|
||||
|
||||
if (unlikely(hpfs_search_hotfix_map_for_range(s, secno, n) != n))
|
||||
return;
|
||||
|
||||
bh = sb_find_get_block(s, secno);
|
||||
if (bh) {
|
||||
if (buffer_uptodate(bh)) {
|
||||
@ -51,7 +78,7 @@ void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head
|
||||
|
||||
cond_resched();
|
||||
|
||||
*bhp = bh = sb_bread(s, secno);
|
||||
*bhp = bh = sb_bread(s, hpfs_search_hotfix_map(s, secno));
|
||||
if (bh != NULL)
|
||||
return bh->b_data;
|
||||
else {
|
||||
@ -71,7 +98,7 @@ void *hpfs_get_sector(struct super_block *s, unsigned secno, struct buffer_head
|
||||
|
||||
cond_resched();
|
||||
|
||||
if ((*bhp = bh = sb_getblk(s, secno)) != NULL) {
|
||||
if ((*bhp = bh = sb_getblk(s, hpfs_search_hotfix_map(s, secno))) != NULL) {
|
||||
if (!buffer_uptodate(bh)) wait_on_buffer(bh);
|
||||
set_buffer_uptodate(bh);
|
||||
return bh->b_data;
|
||||
@ -99,10 +126,10 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe
|
||||
|
||||
hpfs_prefetch_sectors(s, secno, 4 + ahead);
|
||||
|
||||
if (!(qbh->bh[0] = sb_bread(s, secno + 0))) goto bail0;
|
||||
if (!(qbh->bh[1] = sb_bread(s, secno + 1))) goto bail1;
|
||||
if (!(qbh->bh[2] = sb_bread(s, secno + 2))) goto bail2;
|
||||
if (!(qbh->bh[3] = sb_bread(s, secno + 3))) goto bail3;
|
||||
if (!hpfs_map_sector(s, secno + 0, &qbh->bh[0], 0)) goto bail0;
|
||||
if (!hpfs_map_sector(s, secno + 1, &qbh->bh[1], 0)) goto bail1;
|
||||
if (!hpfs_map_sector(s, secno + 2, &qbh->bh[2], 0)) goto bail2;
|
||||
if (!hpfs_map_sector(s, secno + 3, &qbh->bh[3], 0)) goto bail3;
|
||||
|
||||
if (likely(qbh->bh[1]->b_data == qbh->bh[0]->b_data + 1 * 512) &&
|
||||
likely(qbh->bh[2]->b_data == qbh->bh[0]->b_data + 2 * 512) &&
|
||||
|
@ -83,6 +83,11 @@ static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_he
|
||||
if (s) {
|
||||
if (bh_result->b_size >> 9 < n_secs)
|
||||
n_secs = bh_result->b_size >> 9;
|
||||
n_secs = hpfs_search_hotfix_map_for_range(inode->i_sb, s, n_secs);
|
||||
if (unlikely(!n_secs)) {
|
||||
s = hpfs_search_hotfix_map(inode->i_sb, s);
|
||||
n_secs = 1;
|
||||
}
|
||||
map_bh(bh_result, inode->i_sb, s);
|
||||
bh_result->b_size = n_secs << 9;
|
||||
goto ret_0;
|
||||
@ -101,7 +106,7 @@ static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_he
|
||||
inode->i_blocks++;
|
||||
hpfs_i(inode)->mmu_private += 512;
|
||||
set_buffer_new(bh_result);
|
||||
map_bh(bh_result, inode->i_sb, s);
|
||||
map_bh(bh_result, inode->i_sb, hpfs_search_hotfix_map(inode->i_sb, s));
|
||||
ret_0:
|
||||
r = 0;
|
||||
ret_r:
|
||||
@ -181,7 +186,7 @@ static int hpfs_write_end(struct file *file, struct address_space *mapping,
|
||||
|
||||
static sector_t _hpfs_bmap(struct address_space *mapping, sector_t block)
|
||||
{
|
||||
return generic_block_bmap(mapping,block,hpfs_get_block);
|
||||
return generic_block_bmap(mapping, block, hpfs_get_block);
|
||||
}
|
||||
|
||||
const struct address_space_operations hpfs_aops = {
|
||||
|
@ -88,6 +88,10 @@ struct hpfs_sb_info {
|
||||
unsigned sb_max_fwd_alloc; /* max forwad allocation */
|
||||
int sb_timeshift;
|
||||
struct rcu_head rcu;
|
||||
|
||||
unsigned n_hotfixes;
|
||||
secno hotfix_from[256];
|
||||
secno hotfix_to[256];
|
||||
};
|
||||
|
||||
/* Four 512-byte buffers and the 2k block obtained by concatenating them */
|
||||
@ -217,6 +221,8 @@ void hpfs_remove_fnode(struct super_block *, fnode_secno fno);
|
||||
|
||||
/* buffer.c */
|
||||
|
||||
secno hpfs_search_hotfix_map(struct super_block *s, secno sec);
|
||||
unsigned hpfs_search_hotfix_map_for_range(struct super_block *s, secno sec, unsigned n);
|
||||
void hpfs_prefetch_sectors(struct super_block *, unsigned, int);
|
||||
void *hpfs_map_sector(struct super_block *, unsigned, struct buffer_head **, int);
|
||||
void *hpfs_get_sector(struct super_block *, unsigned, struct buffer_head **);
|
||||
@ -285,6 +291,7 @@ __le32 *hpfs_map_bitmap(struct super_block *, unsigned, struct quad_buffer_head
|
||||
void hpfs_prefetch_bitmap(struct super_block *, unsigned);
|
||||
unsigned char *hpfs_load_code_page(struct super_block *, secno);
|
||||
__le32 *hpfs_load_bitmap_directory(struct super_block *, secno bmp);
|
||||
void hpfs_load_hotfix_map(struct super_block *s, struct hpfs_spare_block *spareblock);
|
||||
struct fnode *hpfs_map_fnode(struct super_block *s, ino_t, struct buffer_head **);
|
||||
struct anode *hpfs_map_anode(struct super_block *s, anode_secno, struct buffer_head **);
|
||||
struct dnode *hpfs_map_dnode(struct super_block *s, dnode_secno, struct quad_buffer_head *);
|
||||
|
@ -130,6 +130,32 @@ __le32 *hpfs_load_bitmap_directory(struct super_block *s, secno bmp)
|
||||
return b;
|
||||
}
|
||||
|
||||
void hpfs_load_hotfix_map(struct super_block *s, struct hpfs_spare_block *spareblock)
|
||||
{
|
||||
struct quad_buffer_head qbh;
|
||||
u32 *directory;
|
||||
u32 n_hotfixes, n_used_hotfixes;
|
||||
unsigned i;
|
||||
|
||||
n_hotfixes = le32_to_cpu(spareblock->n_spares);
|
||||
n_used_hotfixes = le32_to_cpu(spareblock->n_spares_used);
|
||||
|
||||
if (n_hotfixes > 256 || n_used_hotfixes > n_hotfixes) {
|
||||
hpfs_error(s, "invalid number of hotfixes: %u, used: %u", n_hotfixes, n_used_hotfixes);
|
||||
return;
|
||||
}
|
||||
if (!(directory = hpfs_map_4sectors(s, le32_to_cpu(spareblock->hotfix_map), &qbh, 0))) {
|
||||
hpfs_error(s, "can't load hotfix map");
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < n_used_hotfixes; i++) {
|
||||
hpfs_sb(s)->hotfix_from[i] = le32_to_cpu(directory[i]);
|
||||
hpfs_sb(s)->hotfix_to[i] = le32_to_cpu(directory[n_hotfixes + i]);
|
||||
}
|
||||
hpfs_sb(s)->n_hotfixes = n_used_hotfixes;
|
||||
hpfs_brelse4(&qbh);
|
||||
}
|
||||
|
||||
/*
|
||||
* Load fnode to memory
|
||||
*/
|
||||
|
@ -8,6 +8,17 @@
|
||||
#include <linux/sched.h>
|
||||
#include "hpfs_fn.h"
|
||||
|
||||
static void hpfs_update_directory_times(struct inode *dir)
|
||||
{
|
||||
time_t t = get_seconds();
|
||||
if (t == dir->i_mtime.tv_sec &&
|
||||
t == dir->i_ctime.tv_sec)
|
||||
return;
|
||||
dir->i_mtime.tv_sec = dir->i_ctime.tv_sec = t;
|
||||
dir->i_mtime.tv_nsec = dir->i_ctime.tv_nsec = 0;
|
||||
hpfs_write_inode_nolock(dir);
|
||||
}
|
||||
|
||||
static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
const unsigned char *name = dentry->d_name.name;
|
||||
@ -99,6 +110,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||
result->i_mode = mode | S_IFDIR;
|
||||
hpfs_write_inode_nolock(result);
|
||||
}
|
||||
hpfs_update_directory_times(dir);
|
||||
d_instantiate(dentry, result);
|
||||
hpfs_unlock(dir->i_sb);
|
||||
return 0;
|
||||
@ -187,6 +199,7 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, b
|
||||
result->i_mode = mode | S_IFREG;
|
||||
hpfs_write_inode_nolock(result);
|
||||
}
|
||||
hpfs_update_directory_times(dir);
|
||||
d_instantiate(dentry, result);
|
||||
hpfs_unlock(dir->i_sb);
|
||||
return 0;
|
||||
@ -262,6 +275,7 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, de
|
||||
insert_inode_hash(result);
|
||||
|
||||
hpfs_write_inode_nolock(result);
|
||||
hpfs_update_directory_times(dir);
|
||||
d_instantiate(dentry, result);
|
||||
brelse(bh);
|
||||
hpfs_unlock(dir->i_sb);
|
||||
@ -340,6 +354,7 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
|
||||
insert_inode_hash(result);
|
||||
|
||||
hpfs_write_inode_nolock(result);
|
||||
hpfs_update_directory_times(dir);
|
||||
d_instantiate(dentry, result);
|
||||
hpfs_unlock(dir->i_sb);
|
||||
return 0;
|
||||
@ -423,6 +438,8 @@ again:
|
||||
out1:
|
||||
hpfs_brelse4(&qbh);
|
||||
out:
|
||||
if (!err)
|
||||
hpfs_update_directory_times(dir);
|
||||
hpfs_unlock(dir->i_sb);
|
||||
return err;
|
||||
}
|
||||
@ -477,6 +494,8 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
out1:
|
||||
hpfs_brelse4(&qbh);
|
||||
out:
|
||||
if (!err)
|
||||
hpfs_update_directory_times(dir);
|
||||
hpfs_unlock(dir->i_sb);
|
||||
return err;
|
||||
}
|
||||
@ -595,7 +614,7 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
goto end1;
|
||||
}
|
||||
|
||||
end:
|
||||
end:
|
||||
hpfs_i(i)->i_parent_dir = new_dir->i_ino;
|
||||
if (S_ISDIR(i->i_mode)) {
|
||||
inc_nlink(new_dir);
|
||||
@ -610,6 +629,10 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
brelse(bh);
|
||||
}
|
||||
end1:
|
||||
if (!err) {
|
||||
hpfs_update_directory_times(old_dir);
|
||||
hpfs_update_directory_times(new_dir);
|
||||
}
|
||||
hpfs_unlock(i->i_sb);
|
||||
return err;
|
||||
}
|
||||
|
@ -628,6 +628,9 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
|
||||
goto bail4;
|
||||
}
|
||||
|
||||
if (spareblock->n_spares_used)
|
||||
hpfs_load_hotfix_map(s, spareblock);
|
||||
|
||||
/* Load bitmap directory */
|
||||
if (!(sbi->sb_bmp_dir = hpfs_load_bitmap_directory(s, le32_to_cpu(superblock->bitmaps))))
|
||||
goto bail4;
|
||||
@ -647,18 +650,6 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
|
||||
mark_buffer_dirty(bh2);
|
||||
}
|
||||
|
||||
if (spareblock->hotfixes_used || spareblock->n_spares_used) {
|
||||
if (errs >= 2) {
|
||||
pr_err("Hotfixes not supported here, try chkdsk\n");
|
||||
mark_dirty(s, 0);
|
||||
goto bail4;
|
||||
}
|
||||
hpfs_error(s, "hotfixes not supported here, try chkdsk");
|
||||
if (errs == 0)
|
||||
pr_err("Proceeding, but your filesystem will be probably corrupted by this driver...\n");
|
||||
else
|
||||
pr_err("This driver may read bad files or crash when operating on disk with hotfixes.\n");
|
||||
}
|
||||
if (le32_to_cpu(spareblock->n_dnode_spares) != le32_to_cpu(spareblock->n_dnode_spares_free)) {
|
||||
if (errs >= 2) {
|
||||
pr_err("Spare dnodes used, try chkdsk\n");
|
||||
|
Loading…
Reference in New Issue
Block a user