mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-03-06 19:51:13 +00:00
Merge branch 'hpfs'
* hpfs: HPFS: Remove unused variable HPFS: Move declaration up, so that there are no out-of-scope pointers HPFS: Fix some unaligned accesses HPFS: Fix endianity. Make hpfs work on big-endian machines HPFS: Implement fsync for hpfs HPFS: Fix a bug that filesystem was not marked dirty when remounting it HPFS: Restrict uid and gid to 16-bit values HPFS: When marking or clearing the dirty bit, sync the filesystem HPFS: Use types with defined width HPFS: Remove mark_inode_dirty HPFS: Remove CR/LF conversion option HPFS: Remove remaining locks HPFS: Introduce a global mutex and lock it on every callback from VFS. HPFS: Make HPFS compile on preempt and SMP
This commit is contained in:
commit
7f4238a0ef
@ -1,7 +1,6 @@
|
||||
config HPFS_FS
|
||||
tristate "OS/2 HPFS file system support"
|
||||
depends on BLOCK
|
||||
depends on BROKEN || !PREEMPT
|
||||
help
|
||||
OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS
|
||||
is the file system used for organizing files on OS/2 hard disk
|
||||
|
118
fs/hpfs/alloc.c
118
fs/hpfs/alloc.c
@ -8,8 +8,6 @@
|
||||
|
||||
#include "hpfs_fn.h"
|
||||
|
||||
static int hpfs_alloc_if_possible_nolock(struct super_block *s, secno sec);
|
||||
|
||||
/*
|
||||
* Check if a sector is allocated in bitmap
|
||||
* This is really slow. Turned on only if chk==2
|
||||
@ -18,9 +16,9 @@ static int hpfs_alloc_if_possible_nolock(struct super_block *s, secno sec);
|
||||
static int chk_if_allocated(struct super_block *s, secno sec, char *msg)
|
||||
{
|
||||
struct quad_buffer_head qbh;
|
||||
unsigned *bmp;
|
||||
u32 *bmp;
|
||||
if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "chk"))) goto fail;
|
||||
if ((bmp[(sec & 0x3fff) >> 5] >> (sec & 0x1f)) & 1) {
|
||||
if ((cpu_to_le32(bmp[(sec & 0x3fff) >> 5]) >> (sec & 0x1f)) & 1) {
|
||||
hpfs_error(s, "sector '%s' - %08x not allocated in bitmap", msg, sec);
|
||||
goto fail1;
|
||||
}
|
||||
@ -28,7 +26,7 @@ static int chk_if_allocated(struct super_block *s, secno sec, char *msg)
|
||||
if (sec >= hpfs_sb(s)->sb_dirband_start && sec < hpfs_sb(s)->sb_dirband_start + hpfs_sb(s)->sb_dirband_size) {
|
||||
unsigned ssec = (sec - hpfs_sb(s)->sb_dirband_start) / 4;
|
||||
if (!(bmp = hpfs_map_dnode_bitmap(s, &qbh))) goto fail;
|
||||
if ((bmp[ssec >> 5] >> (ssec & 0x1f)) & 1) {
|
||||
if ((le32_to_cpu(bmp[ssec >> 5]) >> (ssec & 0x1f)) & 1) {
|
||||
hpfs_error(s, "sector '%s' - %08x not allocated in directory bitmap", msg, sec);
|
||||
goto fail1;
|
||||
}
|
||||
@ -75,7 +73,6 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne
|
||||
hpfs_error(s, "Bad allocation size: %d", n);
|
||||
return 0;
|
||||
}
|
||||
lock_super(s);
|
||||
if (bs != ~0x3fff) {
|
||||
if (!(bmp = hpfs_map_bitmap(s, near >> 14, &qbh, "aib"))) goto uls;
|
||||
} else {
|
||||
@ -85,10 +82,6 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne
|
||||
ret = bs + nr;
|
||||
goto rt;
|
||||
}
|
||||
/*if (!tstbits(bmp, nr + n, n + forward)) {
|
||||
ret = bs + nr + n;
|
||||
goto rt;
|
||||
}*/
|
||||
q = nr + n; b = 0;
|
||||
while ((a = tstbits(bmp, q, n + forward)) != 0) {
|
||||
q += a;
|
||||
@ -105,14 +98,14 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne
|
||||
goto rt;
|
||||
}
|
||||
nr >>= 5;
|
||||
/*for (i = nr + 1; i != nr; i++, i &= 0x1ff) {*/
|
||||
/*for (i = nr + 1; i != nr; i++, i &= 0x1ff) */
|
||||
i = nr;
|
||||
do {
|
||||
if (!bmp[i]) goto cont;
|
||||
if (n + forward >= 0x3f && bmp[i] != -1) goto cont;
|
||||
if (!le32_to_cpu(bmp[i])) goto cont;
|
||||
if (n + forward >= 0x3f && le32_to_cpu(bmp[i]) != 0xffffffff) goto cont;
|
||||
q = i<<5;
|
||||
if (i > 0) {
|
||||
unsigned k = bmp[i-1];
|
||||
unsigned k = le32_to_cpu(bmp[i-1]);
|
||||
while (k & 0x80000000) {
|
||||
q--; k <<= 1;
|
||||
}
|
||||
@ -132,18 +125,17 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne
|
||||
} while (i != nr);
|
||||
rt:
|
||||
if (ret) {
|
||||
if (hpfs_sb(s)->sb_chk && ((ret >> 14) != (bs >> 14) || (bmp[(ret & 0x3fff) >> 5] | ~(((1 << n) - 1) << (ret & 0x1f))) != 0xffffffff)) {
|
||||
if (hpfs_sb(s)->sb_chk && ((ret >> 14) != (bs >> 14) || (le32_to_cpu(bmp[(ret & 0x3fff) >> 5]) | ~(((1 << n) - 1) << (ret & 0x1f))) != 0xffffffff)) {
|
||||
hpfs_error(s, "Allocation doesn't work! Wanted %d, allocated at %08x", n, ret);
|
||||
ret = 0;
|
||||
goto b;
|
||||
}
|
||||
bmp[(ret & 0x3fff) >> 5] &= ~(((1 << n) - 1) << (ret & 0x1f));
|
||||
bmp[(ret & 0x3fff) >> 5] &= cpu_to_le32(~(((1 << n) - 1) << (ret & 0x1f)));
|
||||
hpfs_mark_4buffers_dirty(&qbh);
|
||||
}
|
||||
b:
|
||||
hpfs_brelse4(&qbh);
|
||||
uls:
|
||||
unlock_super(s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -155,7 +147,7 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne
|
||||
* sectors
|
||||
*/
|
||||
|
||||
secno hpfs_alloc_sector(struct super_block *s, secno near, unsigned n, int forward, int lock)
|
||||
secno hpfs_alloc_sector(struct super_block *s, secno near, unsigned n, int forward)
|
||||
{
|
||||
secno sec;
|
||||
int i;
|
||||
@ -167,7 +159,6 @@ secno hpfs_alloc_sector(struct super_block *s, secno near, unsigned n, int forwa
|
||||
forward = -forward;
|
||||
f_p = 1;
|
||||
}
|
||||
if (lock) hpfs_lock_creation(s);
|
||||
n_bmps = (sbi->sb_fs_size + 0x4000 - 1) >> 14;
|
||||
if (near && near < sbi->sb_fs_size) {
|
||||
if ((sec = alloc_in_bmp(s, near, n, f_p ? forward : forward/4))) goto ret;
|
||||
@ -214,18 +205,17 @@ secno hpfs_alloc_sector(struct super_block *s, secno near, unsigned n, int forwa
|
||||
ret:
|
||||
if (sec && f_p) {
|
||||
for (i = 0; i < forward; i++) {
|
||||
if (!hpfs_alloc_if_possible_nolock(s, sec + i + 1)) {
|
||||
if (!hpfs_alloc_if_possible(s, sec + i + 1)) {
|
||||
hpfs_error(s, "Prealloc doesn't work! Wanted %d, allocated at %08x, can't allocate %d", forward, sec, i);
|
||||
sec = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lock) hpfs_unlock_creation(s);
|
||||
return sec;
|
||||
}
|
||||
|
||||
static secno alloc_in_dirband(struct super_block *s, secno near, int lock)
|
||||
static secno alloc_in_dirband(struct super_block *s, secno near)
|
||||
{
|
||||
unsigned nr = near;
|
||||
secno sec;
|
||||
@ -236,49 +226,35 @@ static secno alloc_in_dirband(struct super_block *s, secno near, int lock)
|
||||
nr = sbi->sb_dirband_start + sbi->sb_dirband_size - 4;
|
||||
nr -= sbi->sb_dirband_start;
|
||||
nr >>= 2;
|
||||
if (lock) hpfs_lock_creation(s);
|
||||
sec = alloc_in_bmp(s, (~0x3fff) | nr, 1, 0);
|
||||
if (lock) hpfs_unlock_creation(s);
|
||||
if (!sec) return 0;
|
||||
return ((sec & 0x3fff) << 2) + sbi->sb_dirband_start;
|
||||
}
|
||||
|
||||
/* Alloc sector if it's free */
|
||||
|
||||
static int hpfs_alloc_if_possible_nolock(struct super_block *s, secno sec)
|
||||
int hpfs_alloc_if_possible(struct super_block *s, secno sec)
|
||||
{
|
||||
struct quad_buffer_head qbh;
|
||||
unsigned *bmp;
|
||||
lock_super(s);
|
||||
u32 *bmp;
|
||||
if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "aip"))) goto end;
|
||||
if (bmp[(sec & 0x3fff) >> 5] & (1 << (sec & 0x1f))) {
|
||||
bmp[(sec & 0x3fff) >> 5] &= ~(1 << (sec & 0x1f));
|
||||
if (le32_to_cpu(bmp[(sec & 0x3fff) >> 5]) & (1 << (sec & 0x1f))) {
|
||||
bmp[(sec & 0x3fff) >> 5] &= cpu_to_le32(~(1 << (sec & 0x1f)));
|
||||
hpfs_mark_4buffers_dirty(&qbh);
|
||||
hpfs_brelse4(&qbh);
|
||||
unlock_super(s);
|
||||
return 1;
|
||||
}
|
||||
hpfs_brelse4(&qbh);
|
||||
end:
|
||||
unlock_super(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hpfs_alloc_if_possible(struct super_block *s, secno sec)
|
||||
{
|
||||
int r;
|
||||
hpfs_lock_creation(s);
|
||||
r = hpfs_alloc_if_possible_nolock(s, sec);
|
||||
hpfs_unlock_creation(s);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Free sectors in bitmaps */
|
||||
|
||||
void hpfs_free_sectors(struct super_block *s, secno sec, unsigned n)
|
||||
{
|
||||
struct quad_buffer_head qbh;
|
||||
unsigned *bmp;
|
||||
u32 *bmp;
|
||||
struct hpfs_sb_info *sbi = hpfs_sb(s);
|
||||
/*printk("2 - ");*/
|
||||
if (!n) return;
|
||||
@ -286,26 +262,22 @@ void hpfs_free_sectors(struct super_block *s, secno sec, unsigned n)
|
||||
hpfs_error(s, "Trying to free reserved sector %08x", sec);
|
||||
return;
|
||||
}
|
||||
lock_super(s);
|
||||
sbi->sb_max_fwd_alloc += n > 0xffff ? 0xffff : n;
|
||||
if (sbi->sb_max_fwd_alloc > 0xffffff) sbi->sb_max_fwd_alloc = 0xffffff;
|
||||
new_map:
|
||||
if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "free"))) {
|
||||
unlock_super(s);
|
||||
return;
|
||||
}
|
||||
new_tst:
|
||||
if ((bmp[(sec & 0x3fff) >> 5] >> (sec & 0x1f) & 1)) {
|
||||
if ((le32_to_cpu(bmp[(sec & 0x3fff) >> 5]) >> (sec & 0x1f) & 1)) {
|
||||
hpfs_error(s, "sector %08x not allocated", sec);
|
||||
hpfs_brelse4(&qbh);
|
||||
unlock_super(s);
|
||||
return;
|
||||
}
|
||||
bmp[(sec & 0x3fff) >> 5] |= 1 << (sec & 0x1f);
|
||||
bmp[(sec & 0x3fff) >> 5] |= cpu_to_le32(1 << (sec & 0x1f));
|
||||
if (!--n) {
|
||||
hpfs_mark_4buffers_dirty(&qbh);
|
||||
hpfs_brelse4(&qbh);
|
||||
unlock_super(s);
|
||||
return;
|
||||
}
|
||||
if (!(++sec & 0x3fff)) {
|
||||
@ -327,13 +299,13 @@ int hpfs_check_free_dnodes(struct super_block *s, int n)
|
||||
int n_bmps = (hpfs_sb(s)->sb_fs_size + 0x4000 - 1) >> 14;
|
||||
int b = hpfs_sb(s)->sb_c_bitmap & 0x0fffffff;
|
||||
int i, j;
|
||||
unsigned *bmp;
|
||||
u32 *bmp;
|
||||
struct quad_buffer_head qbh;
|
||||
if ((bmp = hpfs_map_dnode_bitmap(s, &qbh))) {
|
||||
for (j = 0; j < 512; j++) {
|
||||
unsigned k;
|
||||
if (!bmp[j]) continue;
|
||||
for (k = bmp[j]; k; k >>= 1) if (k & 1) if (!--n) {
|
||||
if (!le32_to_cpu(bmp[j])) continue;
|
||||
for (k = le32_to_cpu(bmp[j]); k; k >>= 1) if (k & 1) if (!--n) {
|
||||
hpfs_brelse4(&qbh);
|
||||
return 0;
|
||||
}
|
||||
@ -352,10 +324,10 @@ int hpfs_check_free_dnodes(struct super_block *s, int n)
|
||||
chk_bmp:
|
||||
if (bmp) {
|
||||
for (j = 0; j < 512; j++) {
|
||||
unsigned k;
|
||||
if (!bmp[j]) continue;
|
||||
u32 k;
|
||||
if (!le32_to_cpu(bmp[j])) continue;
|
||||
for (k = 0xf; k; k <<= 4)
|
||||
if ((bmp[j] & k) == k) {
|
||||
if ((le32_to_cpu(bmp[j]) & k) == k) {
|
||||
if (!--n) {
|
||||
hpfs_brelse4(&qbh);
|
||||
return 0;
|
||||
@ -379,44 +351,40 @@ void hpfs_free_dnode(struct super_block *s, dnode_secno dno)
|
||||
hpfs_free_sectors(s, dno, 4);
|
||||
} else {
|
||||
struct quad_buffer_head qbh;
|
||||
unsigned *bmp;
|
||||
u32 *bmp;
|
||||
unsigned ssec = (dno - hpfs_sb(s)->sb_dirband_start) / 4;
|
||||
lock_super(s);
|
||||
if (!(bmp = hpfs_map_dnode_bitmap(s, &qbh))) {
|
||||
unlock_super(s);
|
||||
return;
|
||||
}
|
||||
bmp[ssec >> 5] |= 1 << (ssec & 0x1f);
|
||||
bmp[ssec >> 5] |= cpu_to_le32(1 << (ssec & 0x1f));
|
||||
hpfs_mark_4buffers_dirty(&qbh);
|
||||
hpfs_brelse4(&qbh);
|
||||
unlock_super(s);
|
||||
}
|
||||
}
|
||||
|
||||
struct dnode *hpfs_alloc_dnode(struct super_block *s, secno near,
|
||||
dnode_secno *dno, struct quad_buffer_head *qbh,
|
||||
int lock)
|
||||
dnode_secno *dno, struct quad_buffer_head *qbh)
|
||||
{
|
||||
struct dnode *d;
|
||||
if (hpfs_count_one_bitmap(s, hpfs_sb(s)->sb_dmap) > FREE_DNODES_ADD) {
|
||||
if (!(*dno = alloc_in_dirband(s, near, lock)))
|
||||
if (!(*dno = hpfs_alloc_sector(s, near, 4, 0, lock))) return NULL;
|
||||
if (!(*dno = alloc_in_dirband(s, near)))
|
||||
if (!(*dno = hpfs_alloc_sector(s, near, 4, 0))) return NULL;
|
||||
} else {
|
||||
if (!(*dno = hpfs_alloc_sector(s, near, 4, 0, lock)))
|
||||
if (!(*dno = alloc_in_dirband(s, near, lock))) return NULL;
|
||||
if (!(*dno = hpfs_alloc_sector(s, near, 4, 0)))
|
||||
if (!(*dno = alloc_in_dirband(s, near))) return NULL;
|
||||
}
|
||||
if (!(d = hpfs_get_4sectors(s, *dno, qbh))) {
|
||||
hpfs_free_dnode(s, *dno);
|
||||
return NULL;
|
||||
}
|
||||
memset(d, 0, 2048);
|
||||
d->magic = DNODE_MAGIC;
|
||||
d->first_free = 52;
|
||||
d->magic = cpu_to_le32(DNODE_MAGIC);
|
||||
d->first_free = cpu_to_le32(52);
|
||||
d->dirent[0] = 32;
|
||||
d->dirent[2] = 8;
|
||||
d->dirent[30] = 1;
|
||||
d->dirent[31] = 255;
|
||||
d->self = *dno;
|
||||
d->self = cpu_to_le32(*dno);
|
||||
return d;
|
||||
}
|
||||
|
||||
@ -424,16 +392,16 @@ struct fnode *hpfs_alloc_fnode(struct super_block *s, secno near, fnode_secno *f
|
||||
struct buffer_head **bh)
|
||||
{
|
||||
struct fnode *f;
|
||||
if (!(*fno = hpfs_alloc_sector(s, near, 1, FNODE_ALLOC_FWD, 1))) return NULL;
|
||||
if (!(*fno = hpfs_alloc_sector(s, near, 1, FNODE_ALLOC_FWD))) return NULL;
|
||||
if (!(f = hpfs_get_sector(s, *fno, bh))) {
|
||||
hpfs_free_sectors(s, *fno, 1);
|
||||
return NULL;
|
||||
}
|
||||
memset(f, 0, 512);
|
||||
f->magic = FNODE_MAGIC;
|
||||
f->ea_offs = 0xc4;
|
||||
f->magic = cpu_to_le32(FNODE_MAGIC);
|
||||
f->ea_offs = cpu_to_le16(0xc4);
|
||||
f->btree.n_free_nodes = 8;
|
||||
f->btree.first_free = 8;
|
||||
f->btree.first_free = cpu_to_le16(8);
|
||||
return f;
|
||||
}
|
||||
|
||||
@ -441,16 +409,16 @@ struct anode *hpfs_alloc_anode(struct super_block *s, secno near, anode_secno *a
|
||||
struct buffer_head **bh)
|
||||
{
|
||||
struct anode *a;
|
||||
if (!(*ano = hpfs_alloc_sector(s, near, 1, ANODE_ALLOC_FWD, 1))) return NULL;
|
||||
if (!(*ano = hpfs_alloc_sector(s, near, 1, ANODE_ALLOC_FWD))) return NULL;
|
||||
if (!(a = hpfs_get_sector(s, *ano, bh))) {
|
||||
hpfs_free_sectors(s, *ano, 1);
|
||||
return NULL;
|
||||
}
|
||||
memset(a, 0, 512);
|
||||
a->magic = ANODE_MAGIC;
|
||||
a->self = *ano;
|
||||
a->magic = cpu_to_le32(ANODE_MAGIC);
|
||||
a->self = cpu_to_le32(*ano);
|
||||
a->btree.n_free_nodes = 40;
|
||||
a->btree.n_used_nodes = 0;
|
||||
a->btree.first_free = 8;
|
||||
a->btree.first_free = cpu_to_le16(8);
|
||||
return a;
|
||||
}
|
||||
|
138
fs/hpfs/anode.c
138
fs/hpfs/anode.c
@ -22,8 +22,8 @@ secno hpfs_bplus_lookup(struct super_block *s, struct inode *inode,
|
||||
if (hpfs_sb(s)->sb_chk) if (hpfs_stop_cycles(s, a, &c1, &c2, "hpfs_bplus_lookup")) return -1;
|
||||
if (btree->internal) {
|
||||
for (i = 0; i < btree->n_used_nodes; i++)
|
||||
if (btree->u.internal[i].file_secno > sec) {
|
||||
a = btree->u.internal[i].down;
|
||||
if (le32_to_cpu(btree->u.internal[i].file_secno) > sec) {
|
||||
a = le32_to_cpu(btree->u.internal[i].down);
|
||||
brelse(bh);
|
||||
if (!(anode = hpfs_map_anode(s, a, &bh))) return -1;
|
||||
btree = &anode->btree;
|
||||
@ -34,18 +34,18 @@ secno hpfs_bplus_lookup(struct super_block *s, struct inode *inode,
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < btree->n_used_nodes; i++)
|
||||
if (btree->u.external[i].file_secno <= sec &&
|
||||
btree->u.external[i].file_secno + btree->u.external[i].length > sec) {
|
||||
a = btree->u.external[i].disk_secno + sec - btree->u.external[i].file_secno;
|
||||
if (le32_to_cpu(btree->u.external[i].file_secno) <= sec &&
|
||||
le32_to_cpu(btree->u.external[i].file_secno) + le32_to_cpu(btree->u.external[i].length) > sec) {
|
||||
a = le32_to_cpu(btree->u.external[i].disk_secno) + sec - le32_to_cpu(btree->u.external[i].file_secno);
|
||||
if (hpfs_sb(s)->sb_chk) if (hpfs_chk_sectors(s, a, 1, "data")) {
|
||||
brelse(bh);
|
||||
return -1;
|
||||
}
|
||||
if (inode) {
|
||||
struct hpfs_inode_info *hpfs_inode = hpfs_i(inode);
|
||||
hpfs_inode->i_file_sec = btree->u.external[i].file_secno;
|
||||
hpfs_inode->i_disk_sec = btree->u.external[i].disk_secno;
|
||||
hpfs_inode->i_n_secs = btree->u.external[i].length;
|
||||
hpfs_inode->i_file_sec = le32_to_cpu(btree->u.external[i].file_secno);
|
||||
hpfs_inode->i_disk_sec = le32_to_cpu(btree->u.external[i].disk_secno);
|
||||
hpfs_inode->i_n_secs = le32_to_cpu(btree->u.external[i].length);
|
||||
}
|
||||
brelse(bh);
|
||||
return a;
|
||||
@ -83,8 +83,8 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
|
||||
return -1;
|
||||
}
|
||||
if (btree->internal) {
|
||||
a = btree->u.internal[n].down;
|
||||
btree->u.internal[n].file_secno = -1;
|
||||
a = le32_to_cpu(btree->u.internal[n].down);
|
||||
btree->u.internal[n].file_secno = cpu_to_le32(-1);
|
||||
mark_buffer_dirty(bh);
|
||||
brelse(bh);
|
||||
if (hpfs_sb(s)->sb_chk)
|
||||
@ -94,15 +94,15 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
|
||||
goto go_down;
|
||||
}
|
||||
if (n >= 0) {
|
||||
if (btree->u.external[n].file_secno + btree->u.external[n].length != fsecno) {
|
||||
if (le32_to_cpu(btree->u.external[n].file_secno) + le32_to_cpu(btree->u.external[n].length) != fsecno) {
|
||||
hpfs_error(s, "allocated size %08x, trying to add sector %08x, %cnode %08x",
|
||||
btree->u.external[n].file_secno + btree->u.external[n].length, fsecno,
|
||||
le32_to_cpu(btree->u.external[n].file_secno) + le32_to_cpu(btree->u.external[n].length), fsecno,
|
||||
fnod?'f':'a', node);
|
||||
brelse(bh);
|
||||
return -1;
|
||||
}
|
||||
if (hpfs_alloc_if_possible(s, se = btree->u.external[n].disk_secno + btree->u.external[n].length)) {
|
||||
btree->u.external[n].length++;
|
||||
if (hpfs_alloc_if_possible(s, se = le32_to_cpu(btree->u.external[n].disk_secno) + le32_to_cpu(btree->u.external[n].length))) {
|
||||
btree->u.external[n].length = cpu_to_le32(le32_to_cpu(btree->u.external[n].length) + 1);
|
||||
mark_buffer_dirty(bh);
|
||||
brelse(bh);
|
||||
return se;
|
||||
@ -115,20 +115,20 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
|
||||
}
|
||||
se = !fnod ? node : (node + 16384) & ~16383;
|
||||
}
|
||||
if (!(se = hpfs_alloc_sector(s, se, 1, fsecno*ALLOC_M>ALLOC_FWD_MAX ? ALLOC_FWD_MAX : fsecno*ALLOC_M<ALLOC_FWD_MIN ? ALLOC_FWD_MIN : fsecno*ALLOC_M, 1))) {
|
||||
if (!(se = hpfs_alloc_sector(s, se, 1, fsecno*ALLOC_M>ALLOC_FWD_MAX ? ALLOC_FWD_MAX : fsecno*ALLOC_M<ALLOC_FWD_MIN ? ALLOC_FWD_MIN : fsecno*ALLOC_M))) {
|
||||
brelse(bh);
|
||||
return -1;
|
||||
}
|
||||
fs = n < 0 ? 0 : btree->u.external[n].file_secno + btree->u.external[n].length;
|
||||
fs = n < 0 ? 0 : le32_to_cpu(btree->u.external[n].file_secno) + le32_to_cpu(btree->u.external[n].length);
|
||||
if (!btree->n_free_nodes) {
|
||||
up = a != node ? anode->up : -1;
|
||||
up = a != node ? le32_to_cpu(anode->up) : -1;
|
||||
if (!(anode = hpfs_alloc_anode(s, a, &na, &bh1))) {
|
||||
brelse(bh);
|
||||
hpfs_free_sectors(s, se, 1);
|
||||
return -1;
|
||||
}
|
||||
if (a == node && fnod) {
|
||||
anode->up = node;
|
||||
anode->up = cpu_to_le32(node);
|
||||
anode->btree.fnode_parent = 1;
|
||||
anode->btree.n_used_nodes = btree->n_used_nodes;
|
||||
anode->btree.first_free = btree->first_free;
|
||||
@ -137,9 +137,9 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
|
||||
btree->internal = 1;
|
||||
btree->n_free_nodes = 11;
|
||||
btree->n_used_nodes = 1;
|
||||
btree->first_free = (char *)&(btree->u.internal[1]) - (char *)btree;
|
||||
btree->u.internal[0].file_secno = -1;
|
||||
btree->u.internal[0].down = na;
|
||||
btree->first_free = cpu_to_le16((char *)&(btree->u.internal[1]) - (char *)btree);
|
||||
btree->u.internal[0].file_secno = cpu_to_le32(-1);
|
||||
btree->u.internal[0].down = cpu_to_le32(na);
|
||||
mark_buffer_dirty(bh);
|
||||
} else if (!(ranode = hpfs_alloc_anode(s, /*a*/0, &ra, &bh2))) {
|
||||
brelse(bh);
|
||||
@ -153,15 +153,15 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
|
||||
btree = &anode->btree;
|
||||
}
|
||||
btree->n_free_nodes--; n = btree->n_used_nodes++;
|
||||
btree->first_free += 12;
|
||||
btree->u.external[n].disk_secno = se;
|
||||
btree->u.external[n].file_secno = fs;
|
||||
btree->u.external[n].length = 1;
|
||||
btree->first_free = cpu_to_le16(le16_to_cpu(btree->first_free) + 12);
|
||||
btree->u.external[n].disk_secno = cpu_to_le32(se);
|
||||
btree->u.external[n].file_secno = cpu_to_le32(fs);
|
||||
btree->u.external[n].length = cpu_to_le32(1);
|
||||
mark_buffer_dirty(bh);
|
||||
brelse(bh);
|
||||
if ((a == node && fnod) || na == -1) return se;
|
||||
c2 = 0;
|
||||
while (up != -1) {
|
||||
while (up != (anode_secno)-1) {
|
||||
struct anode *new_anode;
|
||||
if (hpfs_sb(s)->sb_chk)
|
||||
if (hpfs_stop_cycles(s, up, &c1, &c2, "hpfs_add_sector_to_btree #2")) return -1;
|
||||
@ -174,47 +174,47 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
|
||||
}
|
||||
if (btree->n_free_nodes) {
|
||||
btree->n_free_nodes--; n = btree->n_used_nodes++;
|
||||
btree->first_free += 8;
|
||||
btree->u.internal[n].file_secno = -1;
|
||||
btree->u.internal[n].down = na;
|
||||
btree->u.internal[n-1].file_secno = fs;
|
||||
btree->first_free = cpu_to_le16(le16_to_cpu(btree->first_free) + 8);
|
||||
btree->u.internal[n].file_secno = cpu_to_le32(-1);
|
||||
btree->u.internal[n].down = cpu_to_le32(na);
|
||||
btree->u.internal[n-1].file_secno = cpu_to_le32(fs);
|
||||
mark_buffer_dirty(bh);
|
||||
brelse(bh);
|
||||
brelse(bh2);
|
||||
hpfs_free_sectors(s, ra, 1);
|
||||
if ((anode = hpfs_map_anode(s, na, &bh))) {
|
||||
anode->up = up;
|
||||
anode->up = cpu_to_le32(up);
|
||||
anode->btree.fnode_parent = up == node && fnod;
|
||||
mark_buffer_dirty(bh);
|
||||
brelse(bh);
|
||||
}
|
||||
return se;
|
||||
}
|
||||
up = up != node ? anode->up : -1;
|
||||
btree->u.internal[btree->n_used_nodes - 1].file_secno = /*fs*/-1;
|
||||
up = up != node ? le32_to_cpu(anode->up) : -1;
|
||||
btree->u.internal[btree->n_used_nodes - 1].file_secno = cpu_to_le32(/*fs*/-1);
|
||||
mark_buffer_dirty(bh);
|
||||
brelse(bh);
|
||||
a = na;
|
||||
if ((new_anode = hpfs_alloc_anode(s, a, &na, &bh))) {
|
||||
anode = new_anode;
|
||||
/*anode->up = up != -1 ? up : ra;*/
|
||||
/*anode->up = cpu_to_le32(up != -1 ? up : ra);*/
|
||||
anode->btree.internal = 1;
|
||||
anode->btree.n_used_nodes = 1;
|
||||
anode->btree.n_free_nodes = 59;
|
||||
anode->btree.first_free = 16;
|
||||
anode->btree.u.internal[0].down = a;
|
||||
anode->btree.u.internal[0].file_secno = -1;
|
||||
anode->btree.first_free = cpu_to_le16(16);
|
||||
anode->btree.u.internal[0].down = cpu_to_le32(a);
|
||||
anode->btree.u.internal[0].file_secno = cpu_to_le32(-1);
|
||||
mark_buffer_dirty(bh);
|
||||
brelse(bh);
|
||||
if ((anode = hpfs_map_anode(s, a, &bh))) {
|
||||
anode->up = na;
|
||||
anode->up = cpu_to_le32(na);
|
||||
mark_buffer_dirty(bh);
|
||||
brelse(bh);
|
||||
}
|
||||
} else na = a;
|
||||
}
|
||||
if ((anode = hpfs_map_anode(s, na, &bh))) {
|
||||
anode->up = node;
|
||||
anode->up = cpu_to_le32(node);
|
||||
if (fnod) anode->btree.fnode_parent = 1;
|
||||
mark_buffer_dirty(bh);
|
||||
brelse(bh);
|
||||
@ -232,14 +232,14 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
|
||||
}
|
||||
btree = &fnode->btree;
|
||||
}
|
||||
ranode->up = node;
|
||||
memcpy(&ranode->btree, btree, btree->first_free);
|
||||
ranode->up = cpu_to_le32(node);
|
||||
memcpy(&ranode->btree, btree, le16_to_cpu(btree->first_free));
|
||||
if (fnod) ranode->btree.fnode_parent = 1;
|
||||
ranode->btree.n_free_nodes = (ranode->btree.internal ? 60 : 40) - ranode->btree.n_used_nodes;
|
||||
if (ranode->btree.internal) for (n = 0; n < ranode->btree.n_used_nodes; n++) {
|
||||
struct anode *unode;
|
||||
if ((unode = hpfs_map_anode(s, ranode->u.internal[n].down, &bh1))) {
|
||||
unode->up = ra;
|
||||
if ((unode = hpfs_map_anode(s, le32_to_cpu(ranode->u.internal[n].down), &bh1))) {
|
||||
unode->up = cpu_to_le32(ra);
|
||||
unode->btree.fnode_parent = 0;
|
||||
mark_buffer_dirty(bh1);
|
||||
brelse(bh1);
|
||||
@ -248,11 +248,11 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
|
||||
btree->internal = 1;
|
||||
btree->n_free_nodes = fnod ? 10 : 58;
|
||||
btree->n_used_nodes = 2;
|
||||
btree->first_free = (char *)&btree->u.internal[2] - (char *)btree;
|
||||
btree->u.internal[0].file_secno = fs;
|
||||
btree->u.internal[0].down = ra;
|
||||
btree->u.internal[1].file_secno = -1;
|
||||
btree->u.internal[1].down = na;
|
||||
btree->first_free = cpu_to_le16((char *)&btree->u.internal[2] - (char *)btree);
|
||||
btree->u.internal[0].file_secno = cpu_to_le32(fs);
|
||||
btree->u.internal[0].down = cpu_to_le32(ra);
|
||||
btree->u.internal[1].file_secno = cpu_to_le32(-1);
|
||||
btree->u.internal[1].down = cpu_to_le32(na);
|
||||
mark_buffer_dirty(bh);
|
||||
brelse(bh);
|
||||
mark_buffer_dirty(bh2);
|
||||
@ -279,7 +279,7 @@ void hpfs_remove_btree(struct super_block *s, struct bplus_header *btree)
|
||||
go_down:
|
||||
d2 = 0;
|
||||
while (btree1->internal) {
|
||||
ano = btree1->u.internal[pos].down;
|
||||
ano = le32_to_cpu(btree1->u.internal[pos].down);
|
||||
if (level) brelse(bh);
|
||||
if (hpfs_sb(s)->sb_chk)
|
||||
if (hpfs_stop_cycles(s, ano, &d1, &d2, "hpfs_remove_btree #1"))
|
||||
@ -290,7 +290,7 @@ void hpfs_remove_btree(struct super_block *s, struct bplus_header *btree)
|
||||
pos = 0;
|
||||
}
|
||||
for (i = 0; i < btree1->n_used_nodes; i++)
|
||||
hpfs_free_sectors(s, btree1->u.external[i].disk_secno, btree1->u.external[i].length);
|
||||
hpfs_free_sectors(s, le32_to_cpu(btree1->u.external[i].disk_secno), le32_to_cpu(btree1->u.external[i].length));
|
||||
go_up:
|
||||
if (!level) return;
|
||||
brelse(bh);
|
||||
@ -298,13 +298,13 @@ void hpfs_remove_btree(struct super_block *s, struct bplus_header *btree)
|
||||
if (hpfs_stop_cycles(s, ano, &c1, &c2, "hpfs_remove_btree #2")) return;
|
||||
hpfs_free_sectors(s, ano, 1);
|
||||
oano = ano;
|
||||
ano = anode->up;
|
||||
ano = le32_to_cpu(anode->up);
|
||||
if (--level) {
|
||||
if (!(anode = hpfs_map_anode(s, ano, &bh))) return;
|
||||
btree1 = &anode->btree;
|
||||
} else btree1 = btree;
|
||||
for (i = 0; i < btree1->n_used_nodes; i++) {
|
||||
if (btree1->u.internal[i].down == oano) {
|
||||
if (le32_to_cpu(btree1->u.internal[i].down) == oano) {
|
||||
if ((pos = i + 1) < btree1->n_used_nodes)
|
||||
goto go_down;
|
||||
else
|
||||
@ -411,7 +411,7 @@ void hpfs_truncate_btree(struct super_block *s, secno f, int fno, unsigned secs)
|
||||
if (fno) {
|
||||
btree->n_free_nodes = 8;
|
||||
btree->n_used_nodes = 0;
|
||||
btree->first_free = 8;
|
||||
btree->first_free = cpu_to_le16(8);
|
||||
btree->internal = 0;
|
||||
mark_buffer_dirty(bh);
|
||||
} else hpfs_free_sectors(s, f, 1);
|
||||
@ -421,22 +421,22 @@ void hpfs_truncate_btree(struct super_block *s, secno f, int fno, unsigned secs)
|
||||
while (btree->internal) {
|
||||
nodes = btree->n_used_nodes + btree->n_free_nodes;
|
||||
for (i = 0; i < btree->n_used_nodes; i++)
|
||||
if (btree->u.internal[i].file_secno >= secs) goto f;
|
||||
if (le32_to_cpu(btree->u.internal[i].file_secno) >= secs) goto f;
|
||||
brelse(bh);
|
||||
hpfs_error(s, "internal btree %08x doesn't end with -1", node);
|
||||
return;
|
||||
f:
|
||||
for (j = i + 1; j < btree->n_used_nodes; j++)
|
||||
hpfs_ea_remove(s, btree->u.internal[j].down, 1, 0);
|
||||
hpfs_ea_remove(s, le32_to_cpu(btree->u.internal[j].down), 1, 0);
|
||||
btree->n_used_nodes = i + 1;
|
||||
btree->n_free_nodes = nodes - btree->n_used_nodes;
|
||||
btree->first_free = 8 + 8 * btree->n_used_nodes;
|
||||
btree->first_free = cpu_to_le16(8 + 8 * btree->n_used_nodes);
|
||||
mark_buffer_dirty(bh);
|
||||
if (btree->u.internal[i].file_secno == secs) {
|
||||
if (btree->u.internal[i].file_secno == cpu_to_le32(secs)) {
|
||||
brelse(bh);
|
||||
return;
|
||||
}
|
||||
node = btree->u.internal[i].down;
|
||||
node = le32_to_cpu(btree->u.internal[i].down);
|
||||
brelse(bh);
|
||||
if (hpfs_sb(s)->sb_chk)
|
||||
if (hpfs_stop_cycles(s, node, &c1, &c2, "hpfs_truncate_btree"))
|
||||
@ -446,25 +446,25 @@ void hpfs_truncate_btree(struct super_block *s, secno f, int fno, unsigned secs)
|
||||
}
|
||||
nodes = btree->n_used_nodes + btree->n_free_nodes;
|
||||
for (i = 0; i < btree->n_used_nodes; i++)
|
||||
if (btree->u.external[i].file_secno + btree->u.external[i].length >= secs) goto ff;
|
||||
if (le32_to_cpu(btree->u.external[i].file_secno) + le32_to_cpu(btree->u.external[i].length) >= secs) goto ff;
|
||||
brelse(bh);
|
||||
return;
|
||||
ff:
|
||||
if (secs <= btree->u.external[i].file_secno) {
|
||||
if (secs <= le32_to_cpu(btree->u.external[i].file_secno)) {
|
||||
hpfs_error(s, "there is an allocation error in file %08x, sector %08x", f, secs);
|
||||
if (i) i--;
|
||||
}
|
||||
else if (btree->u.external[i].file_secno + btree->u.external[i].length > secs) {
|
||||
hpfs_free_sectors(s, btree->u.external[i].disk_secno + secs -
|
||||
btree->u.external[i].file_secno, btree->u.external[i].length
|
||||
- secs + btree->u.external[i].file_secno); /* I hope gcc optimizes this :-) */
|
||||
btree->u.external[i].length = secs - btree->u.external[i].file_secno;
|
||||
else if (le32_to_cpu(btree->u.external[i].file_secno) + le32_to_cpu(btree->u.external[i].length) > secs) {
|
||||
hpfs_free_sectors(s, le32_to_cpu(btree->u.external[i].disk_secno) + secs -
|
||||
le32_to_cpu(btree->u.external[i].file_secno), le32_to_cpu(btree->u.external[i].length)
|
||||
- secs + le32_to_cpu(btree->u.external[i].file_secno)); /* I hope gcc optimizes this :-) */
|
||||
btree->u.external[i].length = cpu_to_le32(secs - le32_to_cpu(btree->u.external[i].file_secno));
|
||||
}
|
||||
for (j = i + 1; j < btree->n_used_nodes; j++)
|
||||
hpfs_free_sectors(s, btree->u.external[j].disk_secno, btree->u.external[j].length);
|
||||
hpfs_free_sectors(s, le32_to_cpu(btree->u.external[j].disk_secno), le32_to_cpu(btree->u.external[j].length));
|
||||
btree->n_used_nodes = i + 1;
|
||||
btree->n_free_nodes = nodes - btree->n_used_nodes;
|
||||
btree->first_free = 8 + 12 * btree->n_used_nodes;
|
||||
btree->first_free = cpu_to_le16(8 + 12 * btree->n_used_nodes);
|
||||
mark_buffer_dirty(bh);
|
||||
brelse(bh);
|
||||
}
|
||||
@ -480,12 +480,12 @@ void hpfs_remove_fnode(struct super_block *s, fnode_secno fno)
|
||||
struct extended_attribute *ea_end;
|
||||
if (!(fnode = hpfs_map_fnode(s, fno, &bh))) return;
|
||||
if (!fnode->dirflag) hpfs_remove_btree(s, &fnode->btree);
|
||||
else hpfs_remove_dtree(s, fnode->u.external[0].disk_secno);
|
||||
else hpfs_remove_dtree(s, le32_to_cpu(fnode->u.external[0].disk_secno));
|
||||
ea_end = fnode_end_ea(fnode);
|
||||
for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
|
||||
if (ea->indirect)
|
||||
hpfs_ea_remove(s, ea_sec(ea), ea->anode, ea_len(ea));
|
||||
hpfs_ea_ext_remove(s, fnode->ea_secno, fnode->ea_anode, fnode->ea_size_l);
|
||||
hpfs_ea_ext_remove(s, le32_to_cpu(fnode->ea_secno), fnode->ea_anode, le32_to_cpu(fnode->ea_size_l));
|
||||
brelse(bh);
|
||||
hpfs_free_sectors(s, fno, 1);
|
||||
}
|
||||
|
@ -9,22 +9,6 @@
|
||||
#include <linux/slab.h>
|
||||
#include "hpfs_fn.h"
|
||||
|
||||
void hpfs_lock_creation(struct super_block *s)
|
||||
{
|
||||
#ifdef DEBUG_LOCKS
|
||||
printk("lock creation\n");
|
||||
#endif
|
||||
mutex_lock(&hpfs_sb(s)->hpfs_creation_de);
|
||||
}
|
||||
|
||||
void hpfs_unlock_creation(struct super_block *s)
|
||||
{
|
||||
#ifdef DEBUG_LOCKS
|
||||
printk("unlock creation\n");
|
||||
#endif
|
||||
mutex_unlock(&hpfs_sb(s)->hpfs_creation_de);
|
||||
}
|
||||
|
||||
/* Map a sector into a buffer and return pointers to it and to the buffer. */
|
||||
|
||||
void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head **bhp,
|
||||
@ -32,6 +16,8 @@ void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head
|
||||
{
|
||||
struct buffer_head *bh;
|
||||
|
||||
hpfs_lock_assert(s);
|
||||
|
||||
cond_resched();
|
||||
|
||||
*bhp = bh = sb_bread(s, secno);
|
||||
@ -50,6 +36,8 @@ void *hpfs_get_sector(struct super_block *s, unsigned secno, struct buffer_head
|
||||
struct buffer_head *bh;
|
||||
/*return hpfs_map_sector(s, secno, bhp, 0);*/
|
||||
|
||||
hpfs_lock_assert(s);
|
||||
|
||||
cond_resched();
|
||||
|
||||
if ((*bhp = bh = sb_getblk(s, secno)) != NULL) {
|
||||
@ -70,6 +58,8 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe
|
||||
struct buffer_head *bh;
|
||||
char *data;
|
||||
|
||||
hpfs_lock_assert(s);
|
||||
|
||||
cond_resched();
|
||||
|
||||
if (secno & 3) {
|
||||
@ -125,6 +115,8 @@ void *hpfs_get_4sectors(struct super_block *s, unsigned secno,
|
||||
{
|
||||
cond_resched();
|
||||
|
||||
hpfs_lock_assert(s);
|
||||
|
||||
if (secno & 3) {
|
||||
printk("HPFS: hpfs_get_4sectors: unaligned read\n");
|
||||
return NULL;
|
||||
|
@ -88,9 +88,9 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
||||
hpfs_error(inode->i_sb, "not a directory, fnode %08lx",
|
||||
(unsigned long)inode->i_ino);
|
||||
}
|
||||
if (hpfs_inode->i_dno != fno->u.external[0].disk_secno) {
|
||||
if (hpfs_inode->i_dno != le32_to_cpu(fno->u.external[0].disk_secno)) {
|
||||
e = 1;
|
||||
hpfs_error(inode->i_sb, "corrupted inode: i_dno == %08x, fnode -> dnode == %08x", hpfs_inode->i_dno, fno->u.external[0].disk_secno);
|
||||
hpfs_error(inode->i_sb, "corrupted inode: i_dno == %08x, fnode -> dnode == %08x", hpfs_inode->i_dno, le32_to_cpu(fno->u.external[0].disk_secno));
|
||||
}
|
||||
brelse(bh);
|
||||
if (e) {
|
||||
@ -156,7 +156,7 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
||||
goto again;
|
||||
}
|
||||
tempname = hpfs_translate_name(inode->i_sb, de->name, de->namelen, lc, de->not_8x3);
|
||||
if (filldir(dirent, tempname, de->namelen, old_pos, de->fnode, DT_UNKNOWN) < 0) {
|
||||
if (filldir(dirent, tempname, de->namelen, old_pos, le32_to_cpu(de->fnode), DT_UNKNOWN) < 0) {
|
||||
filp->f_pos = old_pos;
|
||||
if (tempname != de->name) kfree(tempname);
|
||||
hpfs_brelse4(&qbh);
|
||||
@ -221,7 +221,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name
|
||||
* Get inode number, what we're after.
|
||||
*/
|
||||
|
||||
ino = de->fnode;
|
||||
ino = le32_to_cpu(de->fnode);
|
||||
|
||||
/*
|
||||
* Go find or make an inode.
|
||||
@ -236,7 +236,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name
|
||||
hpfs_init_inode(result);
|
||||
if (de->directory)
|
||||
hpfs_read_inode(result);
|
||||
else if (de->ea_size && hpfs_sb(dir->i_sb)->sb_eas)
|
||||
else if (le32_to_cpu(de->ea_size) && hpfs_sb(dir->i_sb)->sb_eas)
|
||||
hpfs_read_inode(result);
|
||||
else {
|
||||
result->i_mode |= S_IFREG;
|
||||
@ -250,8 +250,6 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name
|
||||
hpfs_result = hpfs_i(result);
|
||||
if (!de->directory) hpfs_result->i_parent_dir = dir->i_ino;
|
||||
|
||||
hpfs_decide_conv(result, name, len);
|
||||
|
||||
if (de->has_acl || de->has_xtd_perm) if (!(dir->i_sb->s_flags & MS_RDONLY)) {
|
||||
hpfs_error(result->i_sb, "ACLs or XPERM found. This is probably HPFS386. This driver doesn't support it now. Send me some info on these structures");
|
||||
goto bail1;
|
||||
@ -263,19 +261,19 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name
|
||||
*/
|
||||
|
||||
if (!result->i_ctime.tv_sec) {
|
||||
if (!(result->i_ctime.tv_sec = local_to_gmt(dir->i_sb, de->creation_date)))
|
||||
if (!(result->i_ctime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(de->creation_date))))
|
||||
result->i_ctime.tv_sec = 1;
|
||||
result->i_ctime.tv_nsec = 0;
|
||||
result->i_mtime.tv_sec = local_to_gmt(dir->i_sb, de->write_date);
|
||||
result->i_mtime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(de->write_date));
|
||||
result->i_mtime.tv_nsec = 0;
|
||||
result->i_atime.tv_sec = local_to_gmt(dir->i_sb, de->read_date);
|
||||
result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(de->read_date));
|
||||
result->i_atime.tv_nsec = 0;
|
||||
hpfs_result->i_ea_size = de->ea_size;
|
||||
hpfs_result->i_ea_size = le32_to_cpu(de->ea_size);
|
||||
if (!hpfs_result->i_ea_mode && de->read_only)
|
||||
result->i_mode &= ~0222;
|
||||
if (!de->directory) {
|
||||
if (result->i_size == -1) {
|
||||
result->i_size = de->file_size;
|
||||
result->i_size = le32_to_cpu(de->file_size);
|
||||
result->i_data.a_ops = &hpfs_aops;
|
||||
hpfs_i(result)->mmu_private = result->i_size;
|
||||
/*
|
||||
|
174
fs/hpfs/dnode.c
174
fs/hpfs/dnode.c
@ -14,11 +14,11 @@ static loff_t get_pos(struct dnode *d, struct hpfs_dirent *fde)
|
||||
struct hpfs_dirent *de_end = dnode_end_de(d);
|
||||
int i = 1;
|
||||
for (de = dnode_first_de(d); de < de_end; de = de_next_de(de)) {
|
||||
if (de == fde) return ((loff_t) d->self << 4) | (loff_t)i;
|
||||
if (de == fde) return ((loff_t) le32_to_cpu(d->self) << 4) | (loff_t)i;
|
||||
i++;
|
||||
}
|
||||
printk("HPFS: get_pos: not_found\n");
|
||||
return ((loff_t)d->self << 4) | (loff_t)1;
|
||||
return ((loff_t)le32_to_cpu(d->self) << 4) | (loff_t)1;
|
||||
}
|
||||
|
||||
void hpfs_add_pos(struct inode *inode, loff_t *pos)
|
||||
@ -130,29 +130,30 @@ static void set_last_pointer(struct super_block *s, struct dnode *d, dnode_secno
|
||||
{
|
||||
struct hpfs_dirent *de;
|
||||
if (!(de = dnode_last_de(d))) {
|
||||
hpfs_error(s, "set_last_pointer: empty dnode %08x", d->self);
|
||||
hpfs_error(s, "set_last_pointer: empty dnode %08x", le32_to_cpu(d->self));
|
||||
return;
|
||||
}
|
||||
if (hpfs_sb(s)->sb_chk) {
|
||||
if (de->down) {
|
||||
hpfs_error(s, "set_last_pointer: dnode %08x has already last pointer %08x",
|
||||
d->self, de_down_pointer(de));
|
||||
le32_to_cpu(d->self), de_down_pointer(de));
|
||||
return;
|
||||
}
|
||||
if (de->length != 32) {
|
||||
hpfs_error(s, "set_last_pointer: bad last dirent in dnode %08x", d->self);
|
||||
if (le16_to_cpu(de->length) != 32) {
|
||||
hpfs_error(s, "set_last_pointer: bad last dirent in dnode %08x", le32_to_cpu(d->self));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (ptr) {
|
||||
if ((d->first_free += 4) > 2048) {
|
||||
hpfs_error(s,"set_last_pointer: too long dnode %08x", d->self);
|
||||
d->first_free -= 4;
|
||||
d->first_free = cpu_to_le32(le32_to_cpu(d->first_free) + 4);
|
||||
if (le32_to_cpu(d->first_free) > 2048) {
|
||||
hpfs_error(s, "set_last_pointer: too long dnode %08x", le32_to_cpu(d->self));
|
||||
d->first_free = cpu_to_le32(le32_to_cpu(d->first_free) - 4);
|
||||
return;
|
||||
}
|
||||
de->length = 36;
|
||||
de->length = cpu_to_le16(36);
|
||||
de->down = 1;
|
||||
*(dnode_secno *)((char *)de + 32) = ptr;
|
||||
*(dnode_secno *)((char *)de + 32) = cpu_to_le32(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -168,7 +169,7 @@ struct hpfs_dirent *hpfs_add_de(struct super_block *s, struct dnode *d,
|
||||
for (de = dnode_first_de(d); de < de_end; de = de_next_de(de)) {
|
||||
int c = hpfs_compare_names(s, name, namelen, de->name, de->namelen, de->last);
|
||||
if (!c) {
|
||||
hpfs_error(s, "name (%c,%d) already exists in dnode %08x", *name, namelen, d->self);
|
||||
hpfs_error(s, "name (%c,%d) already exists in dnode %08x", *name, namelen, le32_to_cpu(d->self));
|
||||
return NULL;
|
||||
}
|
||||
if (c < 0) break;
|
||||
@ -176,15 +177,14 @@ struct hpfs_dirent *hpfs_add_de(struct super_block *s, struct dnode *d,
|
||||
memmove((char *)de + d_size, de, (char *)de_end - (char *)de);
|
||||
memset(de, 0, d_size);
|
||||
if (down_ptr) {
|
||||
*(int *)((char *)de + d_size - 4) = down_ptr;
|
||||
*(dnode_secno *)((char *)de + d_size - 4) = cpu_to_le32(down_ptr);
|
||||
de->down = 1;
|
||||
}
|
||||
de->length = d_size;
|
||||
if (down_ptr) de->down = 1;
|
||||
de->length = cpu_to_le16(d_size);
|
||||
de->not_8x3 = hpfs_is_name_long(name, namelen);
|
||||
de->namelen = namelen;
|
||||
memcpy(de->name, name, namelen);
|
||||
d->first_free += d_size;
|
||||
d->first_free = cpu_to_le32(le32_to_cpu(d->first_free) + d_size);
|
||||
return de;
|
||||
}
|
||||
|
||||
@ -194,25 +194,25 @@ static void hpfs_delete_de(struct super_block *s, struct dnode *d,
|
||||
struct hpfs_dirent *de)
|
||||
{
|
||||
if (de->last) {
|
||||
hpfs_error(s, "attempt to delete last dirent in dnode %08x", d->self);
|
||||
hpfs_error(s, "attempt to delete last dirent in dnode %08x", le32_to_cpu(d->self));
|
||||
return;
|
||||
}
|
||||
d->first_free -= de->length;
|
||||
memmove(de, de_next_de(de), d->first_free + (char *)d - (char *)de);
|
||||
d->first_free = cpu_to_le32(le32_to_cpu(d->first_free) - le16_to_cpu(de->length));
|
||||
memmove(de, de_next_de(de), le32_to_cpu(d->first_free) + (char *)d - (char *)de);
|
||||
}
|
||||
|
||||
static void fix_up_ptrs(struct super_block *s, struct dnode *d)
|
||||
{
|
||||
struct hpfs_dirent *de;
|
||||
struct hpfs_dirent *de_end = dnode_end_de(d);
|
||||
dnode_secno dno = d->self;
|
||||
dnode_secno dno = le32_to_cpu(d->self);
|
||||
for (de = dnode_first_de(d); de < de_end; de = de_next_de(de))
|
||||
if (de->down) {
|
||||
struct quad_buffer_head qbh;
|
||||
struct dnode *dd;
|
||||
if ((dd = hpfs_map_dnode(s, de_down_pointer(de), &qbh))) {
|
||||
if (dd->up != dno || dd->root_dnode) {
|
||||
dd->up = dno;
|
||||
if (le32_to_cpu(dd->up) != dno || dd->root_dnode) {
|
||||
dd->up = cpu_to_le32(dno);
|
||||
dd->root_dnode = 0;
|
||||
hpfs_mark_4buffers_dirty(&qbh);
|
||||
}
|
||||
@ -262,7 +262,7 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,
|
||||
kfree(nname);
|
||||
return 1;
|
||||
}
|
||||
if (d->first_free + de_size(namelen, down_ptr) <= 2048) {
|
||||
if (le32_to_cpu(d->first_free) + de_size(namelen, down_ptr) <= 2048) {
|
||||
loff_t t;
|
||||
copy_de(de=hpfs_add_de(i->i_sb, d, name, namelen, down_ptr), new_de);
|
||||
t = get_pos(d, de);
|
||||
@ -286,11 +286,11 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,
|
||||
kfree(nname);
|
||||
return 1;
|
||||
}
|
||||
memcpy(nd, d, d->first_free);
|
||||
memcpy(nd, d, le32_to_cpu(d->first_free));
|
||||
copy_de(de = hpfs_add_de(i->i_sb, nd, name, namelen, down_ptr), new_de);
|
||||
for_all_poss(i, hpfs_pos_ins, get_pos(nd, de), 1);
|
||||
h = ((char *)dnode_last_de(nd) - (char *)nd) / 2 + 10;
|
||||
if (!(ad = hpfs_alloc_dnode(i->i_sb, d->up, &adno, &qbh1, 0))) {
|
||||
if (!(ad = hpfs_alloc_dnode(i->i_sb, le32_to_cpu(d->up), &adno, &qbh1))) {
|
||||
hpfs_error(i->i_sb, "unable to alloc dnode - dnode tree will be corrupted");
|
||||
hpfs_brelse4(&qbh);
|
||||
kfree(nd);
|
||||
@ -313,20 +313,21 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,
|
||||
down_ptr = adno;
|
||||
set_last_pointer(i->i_sb, ad, de->down ? de_down_pointer(de) : 0);
|
||||
de = de_next_de(de);
|
||||
memmove((char *)nd + 20, de, nd->first_free + (char *)nd - (char *)de);
|
||||
nd->first_free -= (char *)de - (char *)nd - 20;
|
||||
memcpy(d, nd, nd->first_free);
|
||||
memmove((char *)nd + 20, de, le32_to_cpu(nd->first_free) + (char *)nd - (char *)de);
|
||||
nd->first_free = cpu_to_le32(le32_to_cpu(nd->first_free) - ((char *)de - (char *)nd - 20));
|
||||
memcpy(d, nd, le32_to_cpu(nd->first_free));
|
||||
for_all_poss(i, hpfs_pos_del, (loff_t)dno << 4, pos);
|
||||
fix_up_ptrs(i->i_sb, ad);
|
||||
if (!d->root_dnode) {
|
||||
dno = ad->up = d->up;
|
||||
ad->up = d->up;
|
||||
dno = le32_to_cpu(ad->up);
|
||||
hpfs_mark_4buffers_dirty(&qbh);
|
||||
hpfs_brelse4(&qbh);
|
||||
hpfs_mark_4buffers_dirty(&qbh1);
|
||||
hpfs_brelse4(&qbh1);
|
||||
goto go_up;
|
||||
}
|
||||
if (!(rd = hpfs_alloc_dnode(i->i_sb, d->up, &rdno, &qbh2, 0))) {
|
||||
if (!(rd = hpfs_alloc_dnode(i->i_sb, le32_to_cpu(d->up), &rdno, &qbh2))) {
|
||||
hpfs_error(i->i_sb, "unable to alloc dnode - dnode tree will be corrupted");
|
||||
hpfs_brelse4(&qbh);
|
||||
hpfs_brelse4(&qbh1);
|
||||
@ -338,7 +339,7 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,
|
||||
i->i_blocks += 4;
|
||||
rd->root_dnode = 1;
|
||||
rd->up = d->up;
|
||||
if (!(fnode = hpfs_map_fnode(i->i_sb, d->up, &bh))) {
|
||||
if (!(fnode = hpfs_map_fnode(i->i_sb, le32_to_cpu(d->up), &bh))) {
|
||||
hpfs_free_dnode(i->i_sb, rdno);
|
||||
hpfs_brelse4(&qbh);
|
||||
hpfs_brelse4(&qbh1);
|
||||
@ -347,10 +348,11 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,
|
||||
kfree(nname);
|
||||
return 1;
|
||||
}
|
||||
fnode->u.external[0].disk_secno = rdno;
|
||||
fnode->u.external[0].disk_secno = cpu_to_le32(rdno);
|
||||
mark_buffer_dirty(bh);
|
||||
brelse(bh);
|
||||
d->up = ad->up = hpfs_i(i)->i_dno = rdno;
|
||||
hpfs_i(i)->i_dno = rdno;
|
||||
d->up = ad->up = cpu_to_le32(rdno);
|
||||
d->root_dnode = ad->root_dnode = 0;
|
||||
hpfs_mark_4buffers_dirty(&qbh);
|
||||
hpfs_brelse4(&qbh);
|
||||
@ -373,7 +375,7 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,
|
||||
|
||||
int hpfs_add_dirent(struct inode *i,
|
||||
const unsigned char *name, unsigned namelen,
|
||||
struct hpfs_dirent *new_de, int cdepth)
|
||||
struct hpfs_dirent *new_de)
|
||||
{
|
||||
struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
|
||||
struct dnode *d;
|
||||
@ -403,7 +405,6 @@ int hpfs_add_dirent(struct inode *i,
|
||||
}
|
||||
}
|
||||
hpfs_brelse4(&qbh);
|
||||
if (!cdepth) hpfs_lock_creation(i->i_sb);
|
||||
if (hpfs_check_free_dnodes(i->i_sb, FREE_DNODES_ADD)) {
|
||||
c = 1;
|
||||
goto ret;
|
||||
@ -411,7 +412,6 @@ int hpfs_add_dirent(struct inode *i,
|
||||
i->i_version++;
|
||||
c = hpfs_add_to_dnode(i, dno, name, namelen, new_de, 0);
|
||||
ret:
|
||||
if (!cdepth) hpfs_unlock_creation(i->i_sb);
|
||||
return c;
|
||||
}
|
||||
|
||||
@ -437,9 +437,9 @@ static secno move_to_top(struct inode *i, dnode_secno from, dnode_secno to)
|
||||
return 0;
|
||||
if (!(dnode = hpfs_map_dnode(i->i_sb, dno, &qbh))) return 0;
|
||||
if (hpfs_sb(i->i_sb)->sb_chk) {
|
||||
if (dnode->up != chk_up) {
|
||||
if (le32_to_cpu(dnode->up) != chk_up) {
|
||||
hpfs_error(i->i_sb, "move_to_top: up pointer from %08x should be %08x, is %08x",
|
||||
dno, chk_up, dnode->up);
|
||||
dno, chk_up, le32_to_cpu(dnode->up));
|
||||
hpfs_brelse4(&qbh);
|
||||
return 0;
|
||||
}
|
||||
@ -455,7 +455,7 @@ static secno move_to_top(struct inode *i, dnode_secno from, dnode_secno to)
|
||||
hpfs_brelse4(&qbh);
|
||||
}
|
||||
while (!(de = dnode_pre_last_de(dnode))) {
|
||||
dnode_secno up = dnode->up;
|
||||
dnode_secno up = le32_to_cpu(dnode->up);
|
||||
hpfs_brelse4(&qbh);
|
||||
hpfs_free_dnode(i->i_sb, dno);
|
||||
i->i_size -= 2048;
|
||||
@ -474,8 +474,8 @@ static secno move_to_top(struct inode *i, dnode_secno from, dnode_secno to)
|
||||
hpfs_brelse4(&qbh);
|
||||
return 0;
|
||||
}
|
||||
dnode->first_free -= 4;
|
||||
de->length -= 4;
|
||||
dnode->first_free = cpu_to_le32(le32_to_cpu(dnode->first_free) - 4);
|
||||
de->length = cpu_to_le16(le16_to_cpu(de->length) - 4);
|
||||
de->down = 0;
|
||||
hpfs_mark_4buffers_dirty(&qbh);
|
||||
dno = up;
|
||||
@ -483,12 +483,12 @@ static secno move_to_top(struct inode *i, dnode_secno from, dnode_secno to)
|
||||
t = get_pos(dnode, de);
|
||||
for_all_poss(i, hpfs_pos_subst, t, 4);
|
||||
for_all_poss(i, hpfs_pos_subst, t + 1, 5);
|
||||
if (!(nde = kmalloc(de->length, GFP_NOFS))) {
|
||||
if (!(nde = kmalloc(le16_to_cpu(de->length), GFP_NOFS))) {
|
||||
hpfs_error(i->i_sb, "out of memory for dirent - directory will be corrupted");
|
||||
hpfs_brelse4(&qbh);
|
||||
return 0;
|
||||
}
|
||||
memcpy(nde, de, de->length);
|
||||
memcpy(nde, de, le16_to_cpu(de->length));
|
||||
ddno = de->down ? de_down_pointer(de) : 0;
|
||||
hpfs_delete_de(i->i_sb, dnode, de);
|
||||
set_last_pointer(i->i_sb, dnode, ddno);
|
||||
@ -517,11 +517,11 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)
|
||||
try_it_again:
|
||||
if (hpfs_stop_cycles(i->i_sb, dno, &c1, &c2, "delete_empty_dnode")) return;
|
||||
if (!(dnode = hpfs_map_dnode(i->i_sb, dno, &qbh))) return;
|
||||
if (dnode->first_free > 56) goto end;
|
||||
if (dnode->first_free == 52 || dnode->first_free == 56) {
|
||||
if (le32_to_cpu(dnode->first_free) > 56) goto end;
|
||||
if (le32_to_cpu(dnode->first_free) == 52 || le32_to_cpu(dnode->first_free) == 56) {
|
||||
struct hpfs_dirent *de_end;
|
||||
int root = dnode->root_dnode;
|
||||
up = dnode->up;
|
||||
up = le32_to_cpu(dnode->up);
|
||||
de = dnode_first_de(dnode);
|
||||
down = de->down ? de_down_pointer(de) : 0;
|
||||
if (hpfs_sb(i->i_sb)->sb_chk) if (root && !down) {
|
||||
@ -545,13 +545,13 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)
|
||||
return;
|
||||
}
|
||||
if ((d1 = hpfs_map_dnode(i->i_sb, down, &qbh1))) {
|
||||
d1->up = up;
|
||||
d1->up = cpu_to_le32(up);
|
||||
d1->root_dnode = 1;
|
||||
hpfs_mark_4buffers_dirty(&qbh1);
|
||||
hpfs_brelse4(&qbh1);
|
||||
}
|
||||
if ((fnode = hpfs_map_fnode(i->i_sb, up, &bh))) {
|
||||
fnode->u.external[0].disk_secno = down;
|
||||
fnode->u.external[0].disk_secno = cpu_to_le32(down);
|
||||
mark_buffer_dirty(bh);
|
||||
brelse(bh);
|
||||
}
|
||||
@ -570,22 +570,22 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)
|
||||
for_all_poss(i, hpfs_pos_subst, ((loff_t)dno << 4) | 1, ((loff_t)up << 4) | p);
|
||||
if (!down) {
|
||||
de->down = 0;
|
||||
de->length -= 4;
|
||||
dnode->first_free -= 4;
|
||||
de->length = cpu_to_le16(le16_to_cpu(de->length) - 4);
|
||||
dnode->first_free = cpu_to_le32(le32_to_cpu(dnode->first_free) - 4);
|
||||
memmove(de_next_de(de), (char *)de_next_de(de) + 4,
|
||||
(char *)dnode + dnode->first_free - (char *)de_next_de(de));
|
||||
(char *)dnode + le32_to_cpu(dnode->first_free) - (char *)de_next_de(de));
|
||||
} else {
|
||||
struct dnode *d1;
|
||||
struct quad_buffer_head qbh1;
|
||||
*(dnode_secno *) ((void *) de + de->length - 4) = down;
|
||||
*(dnode_secno *) ((void *) de + le16_to_cpu(de->length) - 4) = down;
|
||||
if ((d1 = hpfs_map_dnode(i->i_sb, down, &qbh1))) {
|
||||
d1->up = up;
|
||||
d1->up = cpu_to_le32(up);
|
||||
hpfs_mark_4buffers_dirty(&qbh1);
|
||||
hpfs_brelse4(&qbh1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
hpfs_error(i->i_sb, "delete_empty_dnode: dnode %08x, first_free == %03x", dno, dnode->first_free);
|
||||
hpfs_error(i->i_sb, "delete_empty_dnode: dnode %08x, first_free == %03x", dno, le32_to_cpu(dnode->first_free));
|
||||
goto end;
|
||||
}
|
||||
|
||||
@ -596,18 +596,18 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)
|
||||
struct quad_buffer_head qbh1;
|
||||
if (!de_next->down) goto endm;
|
||||
ndown = de_down_pointer(de_next);
|
||||
if (!(de_cp = kmalloc(de->length, GFP_NOFS))) {
|
||||
if (!(de_cp = kmalloc(le16_to_cpu(de->length), GFP_NOFS))) {
|
||||
printk("HPFS: out of memory for dtree balancing\n");
|
||||
goto endm;
|
||||
}
|
||||
memcpy(de_cp, de, de->length);
|
||||
memcpy(de_cp, de, le16_to_cpu(de->length));
|
||||
hpfs_delete_de(i->i_sb, dnode, de);
|
||||
hpfs_mark_4buffers_dirty(&qbh);
|
||||
hpfs_brelse4(&qbh);
|
||||
for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | p, 4);
|
||||
for_all_poss(i, hpfs_pos_del, ((loff_t)up << 4) | p, 1);
|
||||
if (de_cp->down) if ((d1 = hpfs_map_dnode(i->i_sb, de_down_pointer(de_cp), &qbh1))) {
|
||||
d1->up = ndown;
|
||||
d1->up = cpu_to_le32(ndown);
|
||||
hpfs_mark_4buffers_dirty(&qbh1);
|
||||
hpfs_brelse4(&qbh1);
|
||||
}
|
||||
@ -635,7 +635,7 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)
|
||||
struct hpfs_dirent *del = dnode_last_de(d1);
|
||||
dlp = del->down ? de_down_pointer(del) : 0;
|
||||
if (!dlp && down) {
|
||||
if (d1->first_free > 2044) {
|
||||
if (le32_to_cpu(d1->first_free) > 2044) {
|
||||
if (hpfs_sb(i->i_sb)->sb_chk >= 2) {
|
||||
printk("HPFS: warning: unbalanced dnode tree, see hpfs.txt 4 more info\n");
|
||||
printk("HPFS: warning: terminating balancing operation\n");
|
||||
@ -647,38 +647,38 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)
|
||||
printk("HPFS: warning: unbalanced dnode tree, see hpfs.txt 4 more info\n");
|
||||
printk("HPFS: warning: goin'on\n");
|
||||
}
|
||||
del->length += 4;
|
||||
del->length = cpu_to_le16(le16_to_cpu(del->length) + 4);
|
||||
del->down = 1;
|
||||
d1->first_free += 4;
|
||||
d1->first_free = cpu_to_le32(le32_to_cpu(d1->first_free) + 4);
|
||||
}
|
||||
if (dlp && !down) {
|
||||
del->length -= 4;
|
||||
del->length = cpu_to_le16(le16_to_cpu(del->length) - 4);
|
||||
del->down = 0;
|
||||
d1->first_free -= 4;
|
||||
d1->first_free = cpu_to_le32(le32_to_cpu(d1->first_free) - 4);
|
||||
} else if (down)
|
||||
*(dnode_secno *) ((void *) del + del->length - 4) = down;
|
||||
*(dnode_secno *) ((void *) del + le16_to_cpu(del->length) - 4) = cpu_to_le32(down);
|
||||
} else goto endm;
|
||||
if (!(de_cp = kmalloc(de_prev->length, GFP_NOFS))) {
|
||||
if (!(de_cp = kmalloc(le16_to_cpu(de_prev->length), GFP_NOFS))) {
|
||||
printk("HPFS: out of memory for dtree balancing\n");
|
||||
hpfs_brelse4(&qbh1);
|
||||
goto endm;
|
||||
}
|
||||
hpfs_mark_4buffers_dirty(&qbh1);
|
||||
hpfs_brelse4(&qbh1);
|
||||
memcpy(de_cp, de_prev, de_prev->length);
|
||||
memcpy(de_cp, de_prev, le16_to_cpu(de_prev->length));
|
||||
hpfs_delete_de(i->i_sb, dnode, de_prev);
|
||||
if (!de_prev->down) {
|
||||
de_prev->length += 4;
|
||||
de_prev->length = cpu_to_le16(le16_to_cpu(de_prev->length) + 4);
|
||||
de_prev->down = 1;
|
||||
dnode->first_free += 4;
|
||||
dnode->first_free = cpu_to_le32(le32_to_cpu(dnode->first_free) + 4);
|
||||
}
|
||||
*(dnode_secno *) ((void *) de_prev + de_prev->length - 4) = ndown;
|
||||
*(dnode_secno *) ((void *) de_prev + le16_to_cpu(de_prev->length) - 4) = cpu_to_le32(ndown);
|
||||
hpfs_mark_4buffers_dirty(&qbh);
|
||||
hpfs_brelse4(&qbh);
|
||||
for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | (p - 1), 4);
|
||||
for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | p, ((loff_t)up << 4) | (p - 1));
|
||||
if (down) if ((d1 = hpfs_map_dnode(i->i_sb, de_down_pointer(de), &qbh1))) {
|
||||
d1->up = ndown;
|
||||
d1->up = cpu_to_le32(ndown);
|
||||
hpfs_mark_4buffers_dirty(&qbh1);
|
||||
hpfs_brelse4(&qbh1);
|
||||
}
|
||||
@ -701,7 +701,6 @@ int hpfs_remove_dirent(struct inode *i, dnode_secno dno, struct hpfs_dirent *de,
|
||||
{
|
||||
struct dnode *dnode = qbh->data;
|
||||
dnode_secno down = 0;
|
||||
int lock = 0;
|
||||
loff_t t;
|
||||
if (de->first || de->last) {
|
||||
hpfs_error(i->i_sb, "hpfs_remove_dirent: attempt to delete first or last dirent in dnode %08x", dno);
|
||||
@ -710,11 +709,8 @@ int hpfs_remove_dirent(struct inode *i, dnode_secno dno, struct hpfs_dirent *de,
|
||||
}
|
||||
if (de->down) down = de_down_pointer(de);
|
||||
if (depth && (de->down || (de == dnode_first_de(dnode) && de_next_de(de)->last))) {
|
||||
lock = 1;
|
||||
hpfs_lock_creation(i->i_sb);
|
||||
if (hpfs_check_free_dnodes(i->i_sb, FREE_DNODES_DEL)) {
|
||||
hpfs_brelse4(qbh);
|
||||
hpfs_unlock_creation(i->i_sb);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
@ -727,11 +723,9 @@ int hpfs_remove_dirent(struct inode *i, dnode_secno dno, struct hpfs_dirent *de,
|
||||
dnode_secno a = move_to_top(i, down, dno);
|
||||
for_all_poss(i, hpfs_pos_subst, 5, t);
|
||||
if (a) delete_empty_dnode(i, a);
|
||||
if (lock) hpfs_unlock_creation(i->i_sb);
|
||||
return !a;
|
||||
}
|
||||
delete_empty_dnode(i, dno);
|
||||
if (lock) hpfs_unlock_creation(i->i_sb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -751,8 +745,8 @@ void hpfs_count_dnodes(struct super_block *s, dnode_secno dno, int *n_dnodes,
|
||||
ptr = 0;
|
||||
go_up:
|
||||
if (!(dnode = hpfs_map_dnode(s, dno, &qbh))) return;
|
||||
if (hpfs_sb(s)->sb_chk) if (odno && odno != -1 && dnode->up != odno)
|
||||
hpfs_error(s, "hpfs_count_dnodes: bad up pointer; dnode %08x, down %08x points to %08x", odno, dno, dnode->up);
|
||||
if (hpfs_sb(s)->sb_chk) if (odno && odno != -1 && le32_to_cpu(dnode->up) != odno)
|
||||
hpfs_error(s, "hpfs_count_dnodes: bad up pointer; dnode %08x, down %08x points to %08x", odno, dno, le32_to_cpu(dnode->up));
|
||||
de = dnode_first_de(dnode);
|
||||
if (ptr) while(1) {
|
||||
if (de->down) if (de_down_pointer(de) == ptr) goto process_de;
|
||||
@ -776,7 +770,7 @@ void hpfs_count_dnodes(struct super_block *s, dnode_secno dno, int *n_dnodes,
|
||||
if (!de->first && !de->last && n_items) (*n_items)++;
|
||||
if ((de = de_next_de(de)) < dnode_end_de(dnode)) goto next_de;
|
||||
ptr = dno;
|
||||
dno = dnode->up;
|
||||
dno = le32_to_cpu(dnode->up);
|
||||
if (dnode->root_dnode) {
|
||||
hpfs_brelse4(&qbh);
|
||||
return;
|
||||
@ -824,8 +818,8 @@ dnode_secno hpfs_de_as_down_as_possible(struct super_block *s, dnode_secno dno)
|
||||
return d;
|
||||
if (!(de = map_nth_dirent(s, d, 1, &qbh, NULL))) return dno;
|
||||
if (hpfs_sb(s)->sb_chk)
|
||||
if (up && ((struct dnode *)qbh.data)->up != up)
|
||||
hpfs_error(s, "hpfs_de_as_down_as_possible: bad up pointer; dnode %08x, down %08x points to %08x", up, d, ((struct dnode *)qbh.data)->up);
|
||||
if (up && le32_to_cpu(((struct dnode *)qbh.data)->up) != up)
|
||||
hpfs_error(s, "hpfs_de_as_down_as_possible: bad up pointer; dnode %08x, down %08x points to %08x", up, d, le32_to_cpu(((struct dnode *)qbh.data)->up));
|
||||
if (!de->down) {
|
||||
hpfs_brelse4(&qbh);
|
||||
return d;
|
||||
@ -874,7 +868,7 @@ struct hpfs_dirent *map_pos_dirent(struct inode *inode, loff_t *posp,
|
||||
/* Going up */
|
||||
if (dnode->root_dnode) goto bail;
|
||||
|
||||
if (!(up_dnode = hpfs_map_dnode(inode->i_sb, dnode->up, &qbh0)))
|
||||
if (!(up_dnode = hpfs_map_dnode(inode->i_sb, le32_to_cpu(dnode->up), &qbh0)))
|
||||
goto bail;
|
||||
|
||||
end_up_de = dnode_end_de(up_dnode);
|
||||
@ -882,16 +876,16 @@ struct hpfs_dirent *map_pos_dirent(struct inode *inode, loff_t *posp,
|
||||
for (up_de = dnode_first_de(up_dnode); up_de < end_up_de;
|
||||
up_de = de_next_de(up_de)) {
|
||||
if (!(++c & 077)) hpfs_error(inode->i_sb,
|
||||
"map_pos_dirent: pos crossed dnode boundary; dnode = %08x", dnode->up);
|
||||
"map_pos_dirent: pos crossed dnode boundary; dnode = %08x", le32_to_cpu(dnode->up));
|
||||
if (up_de->down && de_down_pointer(up_de) == dno) {
|
||||
*posp = ((loff_t) dnode->up << 4) + c;
|
||||
*posp = ((loff_t) le32_to_cpu(dnode->up) << 4) + c;
|
||||
hpfs_brelse4(&qbh0);
|
||||
return de;
|
||||
}
|
||||
}
|
||||
|
||||
hpfs_error(inode->i_sb, "map_pos_dirent: pointer to dnode %08x not found in parent dnode %08x",
|
||||
dno, dnode->up);
|
||||
dno, le32_to_cpu(dnode->up));
|
||||
hpfs_brelse4(&qbh0);
|
||||
|
||||
bail:
|
||||
@ -1017,17 +1011,17 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno,
|
||||
/*name2[15] = 0xff;*/
|
||||
name1len = 15; name2len = 256;
|
||||
}
|
||||
if (!(upf = hpfs_map_fnode(s, f->up, &bh))) {
|
||||
if (!(upf = hpfs_map_fnode(s, le32_to_cpu(f->up), &bh))) {
|
||||
kfree(name2);
|
||||
return NULL;
|
||||
}
|
||||
if (!upf->dirflag) {
|
||||
brelse(bh);
|
||||
hpfs_error(s, "fnode %08x has non-directory parent %08x", fno, f->up);
|
||||
hpfs_error(s, "fnode %08x has non-directory parent %08x", fno, le32_to_cpu(f->up));
|
||||
kfree(name2);
|
||||
return NULL;
|
||||
}
|
||||
dno = upf->u.external[0].disk_secno;
|
||||
dno = le32_to_cpu(upf->u.external[0].disk_secno);
|
||||
brelse(bh);
|
||||
go_down:
|
||||
downd = 0;
|
||||
@ -1049,7 +1043,7 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno,
|
||||
return NULL;
|
||||
}
|
||||
next_de:
|
||||
if (de->fnode == fno) {
|
||||
if (le32_to_cpu(de->fnode) == fno) {
|
||||
kfree(name2);
|
||||
return de;
|
||||
}
|
||||
@ -1065,7 +1059,7 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno,
|
||||
goto go_down;
|
||||
}
|
||||
f:
|
||||
if (de->fnode == fno) {
|
||||
if (le32_to_cpu(de->fnode) == fno) {
|
||||
kfree(name2);
|
||||
return de;
|
||||
}
|
||||
@ -1074,7 +1068,7 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno,
|
||||
if ((de = de_next_de(de)) < de_end) goto next_de;
|
||||
if (d->root_dnode) goto not_found;
|
||||
downd = dno;
|
||||
dno = d->up;
|
||||
dno = le32_to_cpu(d->up);
|
||||
hpfs_brelse4(qbh);
|
||||
if (hpfs_sb(s)->sb_chk)
|
||||
if (hpfs_stop_cycles(s, downd, &d1, &d2, "map_fnode_dirent #2")) {
|
||||
|
136
fs/hpfs/ea.c
136
fs/hpfs/ea.c
@ -24,7 +24,7 @@ void hpfs_ea_ext_remove(struct super_block *s, secno a, int ano, unsigned len)
|
||||
}
|
||||
if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return;
|
||||
if (ea->indirect) {
|
||||
if (ea->valuelen != 8) {
|
||||
if (ea_valuelen(ea) != 8) {
|
||||
hpfs_error(s, "ea->indirect set while ea->valuelen!=8, %s %08x, pos %08x",
|
||||
ano ? "anode" : "sectors", a, pos);
|
||||
return;
|
||||
@ -33,7 +33,7 @@ void hpfs_ea_ext_remove(struct super_block *s, secno a, int ano, unsigned len)
|
||||
return;
|
||||
hpfs_ea_remove(s, ea_sec(ea), ea->anode, ea_len(ea));
|
||||
}
|
||||
pos += ea->namelen + ea->valuelen + 5;
|
||||
pos += ea->namelen + ea_valuelen(ea) + 5;
|
||||
}
|
||||
if (!ano) hpfs_free_sectors(s, a, (len+511) >> 9);
|
||||
else {
|
||||
@ -76,24 +76,24 @@ int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key,
|
||||
unsigned pos;
|
||||
int ano, len;
|
||||
secno a;
|
||||
char ex[4 + 255 + 1 + 8];
|
||||
struct extended_attribute *ea;
|
||||
struct extended_attribute *ea_end = fnode_end_ea(fnode);
|
||||
for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
|
||||
if (!strcmp(ea->name, key)) {
|
||||
if (ea->indirect)
|
||||
goto indirect;
|
||||
if (ea->valuelen >= size)
|
||||
if (ea_valuelen(ea) >= size)
|
||||
return -EINVAL;
|
||||
memcpy(buf, ea_data(ea), ea->valuelen);
|
||||
buf[ea->valuelen] = 0;
|
||||
memcpy(buf, ea_data(ea), ea_valuelen(ea));
|
||||
buf[ea_valuelen(ea)] = 0;
|
||||
return 0;
|
||||
}
|
||||
a = fnode->ea_secno;
|
||||
len = fnode->ea_size_l;
|
||||
a = le32_to_cpu(fnode->ea_secno);
|
||||
len = le32_to_cpu(fnode->ea_size_l);
|
||||
ano = fnode->ea_anode;
|
||||
pos = 0;
|
||||
while (pos < len) {
|
||||
char ex[4 + 255 + 1 + 8];
|
||||
ea = (struct extended_attribute *)ex;
|
||||
if (pos + 4 > len) {
|
||||
hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x",
|
||||
@ -106,14 +106,14 @@ int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key,
|
||||
if (!strcmp(ea->name, key)) {
|
||||
if (ea->indirect)
|
||||
goto indirect;
|
||||
if (ea->valuelen >= size)
|
||||
if (ea_valuelen(ea) >= size)
|
||||
return -EINVAL;
|
||||
if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea->valuelen, buf))
|
||||
if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea_valuelen(ea), buf))
|
||||
return -EIO;
|
||||
buf[ea->valuelen] = 0;
|
||||
buf[ea_valuelen(ea)] = 0;
|
||||
return 0;
|
||||
}
|
||||
pos += ea->namelen + ea->valuelen + 5;
|
||||
pos += ea->namelen + ea_valuelen(ea) + 5;
|
||||
}
|
||||
return -ENOENT;
|
||||
indirect:
|
||||
@ -138,16 +138,16 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si
|
||||
if (!strcmp(ea->name, key)) {
|
||||
if (ea->indirect)
|
||||
return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea));
|
||||
if (!(ret = kmalloc((*size = ea->valuelen) + 1, GFP_NOFS))) {
|
||||
if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) {
|
||||
printk("HPFS: out of memory for EA\n");
|
||||
return NULL;
|
||||
}
|
||||
memcpy(ret, ea_data(ea), ea->valuelen);
|
||||
ret[ea->valuelen] = 0;
|
||||
memcpy(ret, ea_data(ea), ea_valuelen(ea));
|
||||
ret[ea_valuelen(ea)] = 0;
|
||||
return ret;
|
||||
}
|
||||
a = fnode->ea_secno;
|
||||
len = fnode->ea_size_l;
|
||||
a = le32_to_cpu(fnode->ea_secno);
|
||||
len = le32_to_cpu(fnode->ea_size_l);
|
||||
ano = fnode->ea_anode;
|
||||
pos = 0;
|
||||
while (pos < len) {
|
||||
@ -164,18 +164,18 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si
|
||||
if (!strcmp(ea->name, key)) {
|
||||
if (ea->indirect)
|
||||
return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea));
|
||||
if (!(ret = kmalloc((*size = ea->valuelen) + 1, GFP_NOFS))) {
|
||||
if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) {
|
||||
printk("HPFS: out of memory for EA\n");
|
||||
return NULL;
|
||||
}
|
||||
if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea->valuelen, ret)) {
|
||||
if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea_valuelen(ea), ret)) {
|
||||
kfree(ret);
|
||||
return NULL;
|
||||
}
|
||||
ret[ea->valuelen] = 0;
|
||||
ret[ea_valuelen(ea)] = 0;
|
||||
return ret;
|
||||
}
|
||||
pos += ea->namelen + ea->valuelen + 5;
|
||||
pos += ea->namelen + ea_valuelen(ea) + 5;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -202,13 +202,13 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
|
||||
if (ea->indirect) {
|
||||
if (ea_len(ea) == size)
|
||||
set_indirect_ea(s, ea->anode, ea_sec(ea), data, size);
|
||||
} else if (ea->valuelen == size) {
|
||||
} else if (ea_valuelen(ea) == size) {
|
||||
memcpy(ea_data(ea), data, size);
|
||||
}
|
||||
return;
|
||||
}
|
||||
a = fnode->ea_secno;
|
||||
len = fnode->ea_size_l;
|
||||
a = le32_to_cpu(fnode->ea_secno);
|
||||
len = le32_to_cpu(fnode->ea_size_l);
|
||||
ano = fnode->ea_anode;
|
||||
pos = 0;
|
||||
while (pos < len) {
|
||||
@ -228,68 +228,70 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
|
||||
set_indirect_ea(s, ea->anode, ea_sec(ea), data, size);
|
||||
}
|
||||
else {
|
||||
if (ea->valuelen == size)
|
||||
if (ea_valuelen(ea) == size)
|
||||
hpfs_ea_write(s, a, ano, pos + 4 + ea->namelen + 1, size, data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
pos += ea->namelen + ea->valuelen + 5;
|
||||
pos += ea->namelen + ea_valuelen(ea) + 5;
|
||||
}
|
||||
if (!fnode->ea_offs) {
|
||||
/*if (fnode->ea_size_s) {
|
||||
if (!le16_to_cpu(fnode->ea_offs)) {
|
||||
/*if (le16_to_cpu(fnode->ea_size_s)) {
|
||||
hpfs_error(s, "fnode %08x: ea_size_s == %03x, ea_offs == 0",
|
||||
inode->i_ino, fnode->ea_size_s);
|
||||
inode->i_ino, le16_to_cpu(fnode->ea_size_s));
|
||||
return;
|
||||
}*/
|
||||
fnode->ea_offs = 0xc4;
|
||||
fnode->ea_offs = cpu_to_le16(0xc4);
|
||||
}
|
||||
if (fnode->ea_offs < 0xc4 || fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s > 0x200) {
|
||||
if (le16_to_cpu(fnode->ea_offs) < 0xc4 || le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s) > 0x200) {
|
||||
hpfs_error(s, "fnode %08lx: ea_offs == %03x, ea_size_s == %03x",
|
||||
(unsigned long)inode->i_ino,
|
||||
fnode->ea_offs, fnode->ea_size_s);
|
||||
le32_to_cpu(fnode->ea_offs), le16_to_cpu(fnode->ea_size_s));
|
||||
return;
|
||||
}
|
||||
if ((fnode->ea_size_s || !fnode->ea_size_l) &&
|
||||
fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s + strlen(key) + size + 5 <= 0x200) {
|
||||
if ((le16_to_cpu(fnode->ea_size_s) || !le32_to_cpu(fnode->ea_size_l)) &&
|
||||
le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s) + strlen(key) + size + 5 <= 0x200) {
|
||||
ea = fnode_end_ea(fnode);
|
||||
*(char *)ea = 0;
|
||||
ea->namelen = strlen(key);
|
||||
ea->valuelen = size;
|
||||
ea->valuelen_lo = size;
|
||||
ea->valuelen_hi = size >> 8;
|
||||
strcpy(ea->name, key);
|
||||
memcpy(ea_data(ea), data, size);
|
||||
fnode->ea_size_s += strlen(key) + size + 5;
|
||||
fnode->ea_size_s = cpu_to_le16(le16_to_cpu(fnode->ea_size_s) + strlen(key) + size + 5);
|
||||
goto ret;
|
||||
}
|
||||
/* Most the code here is 99.9993422% unused. I hope there are no bugs.
|
||||
But what .. HPFS.IFS has also bugs in ea management. */
|
||||
if (fnode->ea_size_s && !fnode->ea_size_l) {
|
||||
if (le16_to_cpu(fnode->ea_size_s) && !le32_to_cpu(fnode->ea_size_l)) {
|
||||
secno n;
|
||||
struct buffer_head *bh;
|
||||
char *data;
|
||||
if (!(n = hpfs_alloc_sector(s, fno, 1, 0, 1))) return;
|
||||
if (!(n = hpfs_alloc_sector(s, fno, 1, 0))) return;
|
||||
if (!(data = hpfs_get_sector(s, n, &bh))) {
|
||||
hpfs_free_sectors(s, n, 1);
|
||||
return;
|
||||
}
|
||||
memcpy(data, fnode_ea(fnode), fnode->ea_size_s);
|
||||
fnode->ea_size_l = fnode->ea_size_s;
|
||||
fnode->ea_size_s = 0;
|
||||
fnode->ea_secno = n;
|
||||
fnode->ea_anode = 0;
|
||||
memcpy(data, fnode_ea(fnode), le16_to_cpu(fnode->ea_size_s));
|
||||
fnode->ea_size_l = cpu_to_le32(le16_to_cpu(fnode->ea_size_s));
|
||||
fnode->ea_size_s = cpu_to_le16(0);
|
||||
fnode->ea_secno = cpu_to_le32(n);
|
||||
fnode->ea_anode = cpu_to_le32(0);
|
||||
mark_buffer_dirty(bh);
|
||||
brelse(bh);
|
||||
}
|
||||
pos = fnode->ea_size_l + 5 + strlen(key) + size;
|
||||
len = (fnode->ea_size_l + 511) >> 9;
|
||||
pos = le32_to_cpu(fnode->ea_size_l) + 5 + strlen(key) + size;
|
||||
len = (le32_to_cpu(fnode->ea_size_l) + 511) >> 9;
|
||||
if (pos >= 30000) goto bail;
|
||||
while (((pos + 511) >> 9) > len) {
|
||||
if (!len) {
|
||||
if (!(fnode->ea_secno = hpfs_alloc_sector(s, fno, 1, 0, 1)))
|
||||
goto bail;
|
||||
secno q = hpfs_alloc_sector(s, fno, 1, 0);
|
||||
if (!q) goto bail;
|
||||
fnode->ea_secno = cpu_to_le32(q);
|
||||
fnode->ea_anode = 0;
|
||||
len++;
|
||||
} else if (!fnode->ea_anode) {
|
||||
if (hpfs_alloc_if_possible(s, fnode->ea_secno + len)) {
|
||||
if (hpfs_alloc_if_possible(s, le32_to_cpu(fnode->ea_secno) + len)) {
|
||||
len++;
|
||||
} else {
|
||||
/* Aargh... don't know how to create ea anodes :-( */
|
||||
@ -298,26 +300,26 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
|
||||
anode_secno a_s;
|
||||
if (!(anode = hpfs_alloc_anode(s, fno, &a_s, &bh)))
|
||||
goto bail;
|
||||
anode->up = fno;
|
||||
anode->up = cpu_to_le32(fno);
|
||||
anode->btree.fnode_parent = 1;
|
||||
anode->btree.n_free_nodes--;
|
||||
anode->btree.n_used_nodes++;
|
||||
anode->btree.first_free += 12;
|
||||
anode->u.external[0].disk_secno = fnode->ea_secno;
|
||||
anode->u.external[0].file_secno = 0;
|
||||
anode->u.external[0].length = len;
|
||||
anode->btree.first_free = cpu_to_le16(le16_to_cpu(anode->btree.first_free) + 12);
|
||||
anode->u.external[0].disk_secno = cpu_to_le32(le32_to_cpu(fnode->ea_secno));
|
||||
anode->u.external[0].file_secno = cpu_to_le32(0);
|
||||
anode->u.external[0].length = cpu_to_le32(len);
|
||||
mark_buffer_dirty(bh);
|
||||
brelse(bh);
|
||||
fnode->ea_anode = 1;
|
||||
fnode->ea_secno = a_s;*/
|
||||
fnode->ea_secno = cpu_to_le32(a_s);*/
|
||||
secno new_sec;
|
||||
int i;
|
||||
if (!(new_sec = hpfs_alloc_sector(s, fno, 1, 1 - ((pos + 511) >> 9), 1)))
|
||||
if (!(new_sec = hpfs_alloc_sector(s, fno, 1, 1 - ((pos + 511) >> 9))))
|
||||
goto bail;
|
||||
for (i = 0; i < len; i++) {
|
||||
struct buffer_head *bh1, *bh2;
|
||||
void *b1, *b2;
|
||||
if (!(b1 = hpfs_map_sector(s, fnode->ea_secno + i, &bh1, len - i - 1))) {
|
||||
if (!(b1 = hpfs_map_sector(s, le32_to_cpu(fnode->ea_secno) + i, &bh1, len - i - 1))) {
|
||||
hpfs_free_sectors(s, new_sec, (pos + 511) >> 9);
|
||||
goto bail;
|
||||
}
|
||||
@ -331,13 +333,13 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
|
||||
mark_buffer_dirty(bh2);
|
||||
brelse(bh2);
|
||||
}
|
||||
hpfs_free_sectors(s, fnode->ea_secno, len);
|
||||
fnode->ea_secno = new_sec;
|
||||
hpfs_free_sectors(s, le32_to_cpu(fnode->ea_secno), len);
|
||||
fnode->ea_secno = cpu_to_le32(new_sec);
|
||||
len = (pos + 511) >> 9;
|
||||
}
|
||||
}
|
||||
if (fnode->ea_anode) {
|
||||
if (hpfs_add_sector_to_btree(s, fnode->ea_secno,
|
||||
if (hpfs_add_sector_to_btree(s, le32_to_cpu(fnode->ea_secno),
|
||||
0, len) != -1) {
|
||||
len++;
|
||||
} else {
|
||||
@ -349,17 +351,17 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
|
||||
h[1] = strlen(key);
|
||||
h[2] = size & 0xff;
|
||||
h[3] = size >> 8;
|
||||
if (hpfs_ea_write(s, fnode->ea_secno, fnode->ea_anode, fnode->ea_size_l, 4, h)) goto bail;
|
||||
if (hpfs_ea_write(s, fnode->ea_secno, fnode->ea_anode, fnode->ea_size_l + 4, h[1] + 1, key)) goto bail;
|
||||
if (hpfs_ea_write(s, fnode->ea_secno, fnode->ea_anode, fnode->ea_size_l + 5 + h[1], size, data)) goto bail;
|
||||
fnode->ea_size_l = pos;
|
||||
if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode->ea_anode, le32_to_cpu(fnode->ea_size_l), 4, h)) goto bail;
|
||||
if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode->ea_anode, le32_to_cpu(fnode->ea_size_l) + 4, h[1] + 1, key)) goto bail;
|
||||
if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode->ea_anode, le32_to_cpu(fnode->ea_size_l) + 5 + h[1], size, data)) goto bail;
|
||||
fnode->ea_size_l = cpu_to_le32(pos);
|
||||
ret:
|
||||
hpfs_i(inode)->i_ea_size += 5 + strlen(key) + size;
|
||||
return;
|
||||
bail:
|
||||
if (fnode->ea_secno)
|
||||
if (fnode->ea_anode) hpfs_truncate_btree(s, fnode->ea_secno, 1, (fnode->ea_size_l + 511) >> 9);
|
||||
else hpfs_free_sectors(s, fnode->ea_secno + ((fnode->ea_size_l + 511) >> 9), len - ((fnode->ea_size_l + 511) >> 9));
|
||||
else fnode->ea_secno = fnode->ea_size_l = 0;
|
||||
if (le32_to_cpu(fnode->ea_secno))
|
||||
if (fnode->ea_anode) hpfs_truncate_btree(s, le32_to_cpu(fnode->ea_secno), 1, (le32_to_cpu(fnode->ea_size_l) + 511) >> 9);
|
||||
else hpfs_free_sectors(s, le32_to_cpu(fnode->ea_secno) + ((le32_to_cpu(fnode->ea_size_l) + 511) >> 9), len - ((le32_to_cpu(fnode->ea_size_l) + 511) >> 9));
|
||||
else fnode->ea_secno = fnode->ea_size_l = cpu_to_le32(0);
|
||||
}
|
||||
|
||||
|
@ -20,8 +20,8 @@ static int hpfs_file_release(struct inode *inode, struct file *file)
|
||||
|
||||
int hpfs_file_fsync(struct file *file, int datasync)
|
||||
{
|
||||
/*return file_fsync(file, datasync);*/
|
||||
return 0; /* Don't fsync :-) */
|
||||
struct inode *inode = file->f_mapping->host;
|
||||
return sync_blockdev(inode->i_sb->s_bdev);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -48,38 +48,46 @@ static secno hpfs_bmap(struct inode *inode, unsigned file_secno)
|
||||
static void hpfs_truncate(struct inode *i)
|
||||
{
|
||||
if (IS_IMMUTABLE(i)) return /*-EPERM*/;
|
||||
hpfs_lock(i->i_sb);
|
||||
hpfs_lock_assert(i->i_sb);
|
||||
|
||||
hpfs_i(i)->i_n_secs = 0;
|
||||
i->i_blocks = 1 + ((i->i_size + 511) >> 9);
|
||||
hpfs_i(i)->mmu_private = i->i_size;
|
||||
hpfs_truncate_btree(i->i_sb, i->i_ino, 1, ((i->i_size + 511) >> 9));
|
||||
hpfs_write_inode(i);
|
||||
hpfs_i(i)->i_n_secs = 0;
|
||||
hpfs_unlock(i->i_sb);
|
||||
}
|
||||
|
||||
static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create)
|
||||
{
|
||||
int r;
|
||||
secno s;
|
||||
hpfs_lock(inode->i_sb);
|
||||
s = hpfs_bmap(inode, iblock);
|
||||
if (s) {
|
||||
map_bh(bh_result, inode->i_sb, s);
|
||||
return 0;
|
||||
goto ret_0;
|
||||
}
|
||||
if (!create) return 0;
|
||||
if (!create) goto ret_0;
|
||||
if (iblock<<9 != hpfs_i(inode)->mmu_private) {
|
||||
BUG();
|
||||
return -EIO;
|
||||
r = -EIO;
|
||||
goto ret_r;
|
||||
}
|
||||
if ((s = hpfs_add_sector_to_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1)) == -1) {
|
||||
hpfs_truncate_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1);
|
||||
return -ENOSPC;
|
||||
r = -ENOSPC;
|
||||
goto ret_r;
|
||||
}
|
||||
inode->i_blocks++;
|
||||
hpfs_i(inode)->mmu_private += 512;
|
||||
set_buffer_new(bh_result);
|
||||
map_bh(bh_result, inode->i_sb, s);
|
||||
return 0;
|
||||
ret_0:
|
||||
r = 0;
|
||||
ret_r:
|
||||
hpfs_unlock(inode->i_sb);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int hpfs_writepage(struct page *page, struct writeback_control *wbc)
|
||||
@ -130,8 +138,11 @@ static ssize_t hpfs_file_write(struct file *file, const char __user *buf,
|
||||
ssize_t retval;
|
||||
|
||||
retval = do_sync_write(file, buf, count, ppos);
|
||||
if (retval > 0)
|
||||
if (retval > 0) {
|
||||
hpfs_lock(file->f_path.dentry->d_sb);
|
||||
hpfs_i(file->f_path.dentry->d_inode)->i_dirty = 1;
|
||||
hpfs_unlock(file->f_path.dentry->d_sb);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
435
fs/hpfs/hpfs.h
435
fs/hpfs/hpfs.h
@ -19,9 +19,13 @@
|
||||
For definitive information on HPFS, ask somebody else -- this is guesswork.
|
||||
There are certain to be many mistakes. */
|
||||
|
||||
#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
|
||||
#error unknown endian
|
||||
#endif
|
||||
|
||||
/* Notation */
|
||||
|
||||
typedef unsigned secno; /* sector number, partition relative */
|
||||
typedef u32 secno; /* sector number, partition relative */
|
||||
|
||||
typedef secno dnode_secno; /* sector number of a dnode */
|
||||
typedef secno fnode_secno; /* sector number of an fnode */
|
||||
@ -38,28 +42,28 @@ typedef u32 time32_t; /* 32-bit time_t type */
|
||||
|
||||
struct hpfs_boot_block
|
||||
{
|
||||
unsigned char jmp[3];
|
||||
unsigned char oem_id[8];
|
||||
unsigned char bytes_per_sector[2]; /* 512 */
|
||||
unsigned char sectors_per_cluster;
|
||||
unsigned char n_reserved_sectors[2];
|
||||
unsigned char n_fats;
|
||||
unsigned char n_rootdir_entries[2];
|
||||
unsigned char n_sectors_s[2];
|
||||
unsigned char media_byte;
|
||||
unsigned short sectors_per_fat;
|
||||
unsigned short sectors_per_track;
|
||||
unsigned short heads_per_cyl;
|
||||
unsigned int n_hidden_sectors;
|
||||
unsigned int n_sectors_l; /* size of partition */
|
||||
unsigned char drive_number;
|
||||
unsigned char mbz;
|
||||
unsigned char sig_28h; /* 28h */
|
||||
unsigned char vol_serno[4];
|
||||
unsigned char vol_label[11];
|
||||
unsigned char sig_hpfs[8]; /* "HPFS " */
|
||||
unsigned char pad[448];
|
||||
unsigned short magic; /* aa55 */
|
||||
u8 jmp[3];
|
||||
u8 oem_id[8];
|
||||
u8 bytes_per_sector[2]; /* 512 */
|
||||
u8 sectors_per_cluster;
|
||||
u8 n_reserved_sectors[2];
|
||||
u8 n_fats;
|
||||
u8 n_rootdir_entries[2];
|
||||
u8 n_sectors_s[2];
|
||||
u8 media_byte;
|
||||
u16 sectors_per_fat;
|
||||
u16 sectors_per_track;
|
||||
u16 heads_per_cyl;
|
||||
u32 n_hidden_sectors;
|
||||
u32 n_sectors_l; /* size of partition */
|
||||
u8 drive_number;
|
||||
u8 mbz;
|
||||
u8 sig_28h; /* 28h */
|
||||
u8 vol_serno[4];
|
||||
u8 vol_label[11];
|
||||
u8 sig_hpfs[8]; /* "HPFS " */
|
||||
u8 pad[448];
|
||||
u16 magic; /* aa55 */
|
||||
};
|
||||
|
||||
|
||||
@ -71,31 +75,29 @@ struct hpfs_boot_block
|
||||
|
||||
struct hpfs_super_block
|
||||
{
|
||||
unsigned magic; /* f995 e849 */
|
||||
unsigned magic1; /* fa53 e9c5, more magic? */
|
||||
/*unsigned huh202;*/ /* ?? 202 = N. of B. in 1.00390625 S.*/
|
||||
char version; /* version of a filesystem usually 2 */
|
||||
char funcversion; /* functional version - oldest version
|
||||
u32 magic; /* f995 e849 */
|
||||
u32 magic1; /* fa53 e9c5, more magic? */
|
||||
u8 version; /* version of a filesystem usually 2 */
|
||||
u8 funcversion; /* functional version - oldest version
|
||||
of filesystem that can understand
|
||||
this disk */
|
||||
unsigned short int zero; /* 0 */
|
||||
u16 zero; /* 0 */
|
||||
fnode_secno root; /* fnode of root directory */
|
||||
secno n_sectors; /* size of filesystem */
|
||||
unsigned n_badblocks; /* number of bad blocks */
|
||||
u32 n_badblocks; /* number of bad blocks */
|
||||
secno bitmaps; /* pointers to free space bit maps */
|
||||
unsigned zero1; /* 0 */
|
||||
u32 zero1; /* 0 */
|
||||
secno badblocks; /* bad block list */
|
||||
unsigned zero3; /* 0 */
|
||||
u32 zero3; /* 0 */
|
||||
time32_t last_chkdsk; /* date last checked, 0 if never */
|
||||
/*unsigned zero4;*/ /* 0 */
|
||||
time32_t last_optimize; /* date last optimized, 0 if never */
|
||||
time32_t last_optimize; /* date last optimized, 0 if never */
|
||||
secno n_dir_band; /* number of sectors in dir band */
|
||||
secno dir_band_start; /* first sector in dir band */
|
||||
secno dir_band_end; /* last sector in dir band */
|
||||
secno dir_band_bitmap; /* free space map, 1 dnode per bit */
|
||||
char volume_name[32]; /* not used */
|
||||
u8 volume_name[32]; /* not used */
|
||||
secno user_id_table; /* 8 preallocated sectors - user id */
|
||||
unsigned zero6[103]; /* 0 */
|
||||
u32 zero6[103]; /* 0 */
|
||||
};
|
||||
|
||||
|
||||
@ -107,44 +109,65 @@ struct hpfs_super_block
|
||||
|
||||
struct hpfs_spare_block
|
||||
{
|
||||
unsigned magic; /* f991 1849 */
|
||||
unsigned magic1; /* fa52 29c5, more magic? */
|
||||
u32 magic; /* f991 1849 */
|
||||
u32 magic1; /* fa52 29c5, more magic? */
|
||||
|
||||
unsigned dirty: 1; /* 0 clean, 1 "improperly stopped" */
|
||||
/*unsigned flag1234: 4;*/ /* unknown flags */
|
||||
unsigned sparedir_used: 1; /* spare dirblks used */
|
||||
unsigned hotfixes_used: 1; /* hotfixes used */
|
||||
unsigned bad_sector: 1; /* bad sector, corrupted disk (???) */
|
||||
unsigned bad_bitmap: 1; /* bad bitmap */
|
||||
unsigned fast: 1; /* partition was fast formatted */
|
||||
unsigned old_wrote: 1; /* old version wrote to partion */
|
||||
unsigned old_wrote_1: 1; /* old version wrote to partion (?) */
|
||||
unsigned install_dasd_limits: 1; /* HPFS386 flags */
|
||||
unsigned resynch_dasd_limits: 1;
|
||||
unsigned dasd_limits_operational: 1;
|
||||
unsigned multimedia_active: 1;
|
||||
unsigned dce_acls_active: 1;
|
||||
unsigned dasd_limits_dirty: 1;
|
||||
unsigned flag67: 2;
|
||||
unsigned char mm_contlgulty;
|
||||
unsigned char unused;
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
u8 dirty: 1; /* 0 clean, 1 "improperly stopped" */
|
||||
u8 sparedir_used: 1; /* spare dirblks used */
|
||||
u8 hotfixes_used: 1; /* hotfixes used */
|
||||
u8 bad_sector: 1; /* bad sector, corrupted disk (???) */
|
||||
u8 bad_bitmap: 1; /* bad bitmap */
|
||||
u8 fast: 1; /* partition was fast formatted */
|
||||
u8 old_wrote: 1; /* old version wrote to partion */
|
||||
u8 old_wrote_1: 1; /* old version wrote to partion (?) */
|
||||
#else
|
||||
u8 old_wrote_1: 1; /* old version wrote to partion (?) */
|
||||
u8 old_wrote: 1; /* old version wrote to partion */
|
||||
u8 fast: 1; /* partition was fast formatted */
|
||||
u8 bad_bitmap: 1; /* bad bitmap */
|
||||
u8 bad_sector: 1; /* bad sector, corrupted disk (???) */
|
||||
u8 hotfixes_used: 1; /* hotfixes used */
|
||||
u8 sparedir_used: 1; /* spare dirblks used */
|
||||
u8 dirty: 1; /* 0 clean, 1 "improperly stopped" */
|
||||
#endif
|
||||
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
u8 install_dasd_limits: 1; /* HPFS386 flags */
|
||||
u8 resynch_dasd_limits: 1;
|
||||
u8 dasd_limits_operational: 1;
|
||||
u8 multimedia_active: 1;
|
||||
u8 dce_acls_active: 1;
|
||||
u8 dasd_limits_dirty: 1;
|
||||
u8 flag67: 2;
|
||||
#else
|
||||
u8 flag67: 2;
|
||||
u8 dasd_limits_dirty: 1;
|
||||
u8 dce_acls_active: 1;
|
||||
u8 multimedia_active: 1;
|
||||
u8 dasd_limits_operational: 1;
|
||||
u8 resynch_dasd_limits: 1;
|
||||
u8 install_dasd_limits: 1; /* HPFS386 flags */
|
||||
#endif
|
||||
|
||||
u8 mm_contlgulty;
|
||||
u8 unused;
|
||||
|
||||
secno hotfix_map; /* info about remapped bad sectors */
|
||||
unsigned n_spares_used; /* number of hotfixes */
|
||||
unsigned n_spares; /* number of spares in hotfix map */
|
||||
unsigned n_dnode_spares_free; /* spare dnodes unused */
|
||||
unsigned n_dnode_spares; /* length of spare_dnodes[] list,
|
||||
u32 n_spares_used; /* number of hotfixes */
|
||||
u32 n_spares; /* number of spares in hotfix map */
|
||||
u32 n_dnode_spares_free; /* spare dnodes unused */
|
||||
u32 n_dnode_spares; /* length of spare_dnodes[] list,
|
||||
follows in this block*/
|
||||
secno code_page_dir; /* code page directory block */
|
||||
unsigned n_code_pages; /* number of code pages */
|
||||
/*unsigned large_numbers[2];*/ /* ?? */
|
||||
unsigned super_crc; /* on HPFS386 and LAN Server this is
|
||||
u32 n_code_pages; /* number of code pages */
|
||||
u32 super_crc; /* on HPFS386 and LAN Server this is
|
||||
checksum of superblock, on normal
|
||||
OS/2 unused */
|
||||
unsigned spare_crc; /* on HPFS386 checksum of spareblock */
|
||||
unsigned zero1[15]; /* unused */
|
||||
u32 spare_crc; /* on HPFS386 checksum of spareblock */
|
||||
u32 zero1[15]; /* unused */
|
||||
dnode_secno spare_dnodes[100]; /* emergency free dnode list */
|
||||
unsigned zero2[1]; /* room for more? */
|
||||
u32 zero2[1]; /* room for more? */
|
||||
};
|
||||
|
||||
/* The bad block list is 4 sectors long. The first word must be zero,
|
||||
@ -179,18 +202,18 @@ struct hpfs_spare_block
|
||||
|
||||
struct code_page_directory
|
||||
{
|
||||
unsigned magic; /* 4945 21f7 */
|
||||
unsigned n_code_pages; /* number of pointers following */
|
||||
unsigned zero1[2];
|
||||
u32 magic; /* 4945 21f7 */
|
||||
u32 n_code_pages; /* number of pointers following */
|
||||
u32 zero1[2];
|
||||
struct {
|
||||
unsigned short ix; /* index */
|
||||
unsigned short code_page_number; /* code page number */
|
||||
unsigned bounds; /* matches corresponding word
|
||||
u16 ix; /* index */
|
||||
u16 code_page_number; /* code page number */
|
||||
u32 bounds; /* matches corresponding word
|
||||
in data block */
|
||||
secno code_page_data; /* sector number of a code_page_data
|
||||
containing c.p. array */
|
||||
unsigned short index; /* index in c.p. array in that sector*/
|
||||
unsigned short unknown; /* some unknown value; usually 0;
|
||||
u16 index; /* index in c.p. array in that sector*/
|
||||
u16 unknown; /* some unknown value; usually 0;
|
||||
2 in Japanese version */
|
||||
} array[31]; /* unknown length */
|
||||
};
|
||||
@ -201,21 +224,21 @@ struct code_page_directory
|
||||
|
||||
struct code_page_data
|
||||
{
|
||||
unsigned magic; /* 8945 21f7 */
|
||||
unsigned n_used; /* # elements used in c_p_data[] */
|
||||
unsigned bounds[3]; /* looks a bit like
|
||||
u32 magic; /* 8945 21f7 */
|
||||
u32 n_used; /* # elements used in c_p_data[] */
|
||||
u32 bounds[3]; /* looks a bit like
|
||||
(beg1,end1), (beg2,end2)
|
||||
one byte each */
|
||||
unsigned short offs[3]; /* offsets from start of sector
|
||||
u16 offs[3]; /* offsets from start of sector
|
||||
to start of c_p_data[ix] */
|
||||
struct {
|
||||
unsigned short ix; /* index */
|
||||
unsigned short code_page_number; /* code page number */
|
||||
unsigned short unknown; /* the same as in cp directory */
|
||||
unsigned char map[128]; /* upcase table for chars 80..ff */
|
||||
unsigned short zero2;
|
||||
u16 ix; /* index */
|
||||
u16 code_page_number; /* code page number */
|
||||
u16 unknown; /* the same as in cp directory */
|
||||
u8 map[128]; /* upcase table for chars 80..ff */
|
||||
u16 zero2;
|
||||
} code_page[3];
|
||||
unsigned char incognita[78];
|
||||
u8 incognita[78];
|
||||
};
|
||||
|
||||
|
||||
@ -255,50 +278,84 @@ struct code_page_data
|
||||
#define DNODE_MAGIC 0x77e40aae
|
||||
|
||||
struct dnode {
|
||||
unsigned magic; /* 77e4 0aae */
|
||||
unsigned first_free; /* offset from start of dnode to
|
||||
u32 magic; /* 77e4 0aae */
|
||||
u32 first_free; /* offset from start of dnode to
|
||||
first free dir entry */
|
||||
unsigned root_dnode:1; /* Is it root dnode? */
|
||||
unsigned increment_me:31; /* some kind of activity counter?
|
||||
Neither HPFS.IFS nor CHKDSK cares
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
u8 root_dnode: 1; /* Is it root dnode? */
|
||||
u8 increment_me: 7; /* some kind of activity counter? */
|
||||
/* Neither HPFS.IFS nor CHKDSK cares
|
||||
if you change this word */
|
||||
#else
|
||||
u8 increment_me: 7; /* some kind of activity counter? */
|
||||
/* Neither HPFS.IFS nor CHKDSK cares
|
||||
if you change this word */
|
||||
u8 root_dnode: 1; /* Is it root dnode? */
|
||||
#endif
|
||||
u8 increment_me2[3];
|
||||
secno up; /* (root dnode) directory's fnode
|
||||
(nonroot) parent dnode */
|
||||
dnode_secno self; /* pointer to this dnode */
|
||||
unsigned char dirent[2028]; /* one or more dirents */
|
||||
u8 dirent[2028]; /* one or more dirents */
|
||||
};
|
||||
|
||||
struct hpfs_dirent {
|
||||
unsigned short length; /* offset to next dirent */
|
||||
unsigned first: 1; /* set on phony ^A^A (".") entry */
|
||||
unsigned has_acl: 1;
|
||||
unsigned down: 1; /* down pointer present (after name) */
|
||||
unsigned last: 1; /* set on phony \377 entry */
|
||||
unsigned has_ea: 1; /* entry has EA */
|
||||
unsigned has_xtd_perm: 1; /* has extended perm list (???) */
|
||||
unsigned has_explicit_acl: 1;
|
||||
unsigned has_needea: 1; /* ?? some EA has NEEDEA set
|
||||
u16 length; /* offset to next dirent */
|
||||
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
u8 first: 1; /* set on phony ^A^A (".") entry */
|
||||
u8 has_acl: 1;
|
||||
u8 down: 1; /* down pointer present (after name) */
|
||||
u8 last: 1; /* set on phony \377 entry */
|
||||
u8 has_ea: 1; /* entry has EA */
|
||||
u8 has_xtd_perm: 1; /* has extended perm list (???) */
|
||||
u8 has_explicit_acl: 1;
|
||||
u8 has_needea: 1; /* ?? some EA has NEEDEA set
|
||||
I have no idea why this is
|
||||
interesting in a dir entry */
|
||||
unsigned read_only: 1; /* dos attrib */
|
||||
unsigned hidden: 1; /* dos attrib */
|
||||
unsigned system: 1; /* dos attrib */
|
||||
unsigned flag11: 1; /* would be volume label dos attrib */
|
||||
unsigned directory: 1; /* dos attrib */
|
||||
unsigned archive: 1; /* dos attrib */
|
||||
unsigned not_8x3: 1; /* name is not 8.3 */
|
||||
unsigned flag15: 1;
|
||||
#else
|
||||
u8 has_needea: 1; /* ?? some EA has NEEDEA set
|
||||
I have no idea why this is
|
||||
interesting in a dir entry */
|
||||
u8 has_explicit_acl: 1;
|
||||
u8 has_xtd_perm: 1; /* has extended perm list (???) */
|
||||
u8 has_ea: 1; /* entry has EA */
|
||||
u8 last: 1; /* set on phony \377 entry */
|
||||
u8 down: 1; /* down pointer present (after name) */
|
||||
u8 has_acl: 1;
|
||||
u8 first: 1; /* set on phony ^A^A (".") entry */
|
||||
#endif
|
||||
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
u8 read_only: 1; /* dos attrib */
|
||||
u8 hidden: 1; /* dos attrib */
|
||||
u8 system: 1; /* dos attrib */
|
||||
u8 flag11: 1; /* would be volume label dos attrib */
|
||||
u8 directory: 1; /* dos attrib */
|
||||
u8 archive: 1; /* dos attrib */
|
||||
u8 not_8x3: 1; /* name is not 8.3 */
|
||||
u8 flag15: 1;
|
||||
#else
|
||||
u8 flag15: 1;
|
||||
u8 not_8x3: 1; /* name is not 8.3 */
|
||||
u8 archive: 1; /* dos attrib */
|
||||
u8 directory: 1; /* dos attrib */
|
||||
u8 flag11: 1; /* would be volume label dos attrib */
|
||||
u8 system: 1; /* dos attrib */
|
||||
u8 hidden: 1; /* dos attrib */
|
||||
u8 read_only: 1; /* dos attrib */
|
||||
#endif
|
||||
|
||||
fnode_secno fnode; /* fnode giving allocation info */
|
||||
time32_t write_date; /* mtime */
|
||||
unsigned file_size; /* file length, bytes */
|
||||
u32 file_size; /* file length, bytes */
|
||||
time32_t read_date; /* atime */
|
||||
time32_t creation_date; /* ctime */
|
||||
unsigned ea_size; /* total EA length, bytes */
|
||||
unsigned char no_of_acls : 3; /* number of ACL's */
|
||||
unsigned char reserver : 5;
|
||||
unsigned char ix; /* code page index (of filename), see
|
||||
u32 ea_size; /* total EA length, bytes */
|
||||
u8 no_of_acls; /* number of ACL's (low 3 bits) */
|
||||
u8 ix; /* code page index (of filename), see
|
||||
struct code_page_data */
|
||||
unsigned char namelen, name[1]; /* file name */
|
||||
u8 namelen, name[1]; /* file name */
|
||||
/* dnode_secno down; btree down pointer, if present,
|
||||
follows name on next word boundary, or maybe it
|
||||
precedes next dirent, which is on a word boundary. */
|
||||
@ -318,38 +375,50 @@ struct hpfs_dirent {
|
||||
|
||||
struct bplus_leaf_node
|
||||
{
|
||||
unsigned file_secno; /* first file sector in extent */
|
||||
unsigned length; /* length, sectors */
|
||||
u32 file_secno; /* first file sector in extent */
|
||||
u32 length; /* length, sectors */
|
||||
secno disk_secno; /* first corresponding disk sector */
|
||||
};
|
||||
|
||||
struct bplus_internal_node
|
||||
{
|
||||
unsigned file_secno; /* subtree maps sectors < this */
|
||||
u32 file_secno; /* subtree maps sectors < this */
|
||||
anode_secno down; /* pointer to subtree */
|
||||
};
|
||||
|
||||
struct bplus_header
|
||||
{
|
||||
unsigned hbff: 1; /* high bit of first free entry offset */
|
||||
unsigned flag1: 1;
|
||||
unsigned flag2: 1;
|
||||
unsigned flag3: 1;
|
||||
unsigned flag4: 1;
|
||||
unsigned fnode_parent: 1; /* ? we're pointed to by an fnode,
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
u8 hbff: 1; /* high bit of first free entry offset */
|
||||
u8 flag1234: 4;
|
||||
u8 fnode_parent: 1; /* ? we're pointed to by an fnode,
|
||||
the data btree or some ea or the
|
||||
main ea bootage pointer ea_secno */
|
||||
/* also can get set in fnodes, which
|
||||
may be a chkdsk glitch or may mean
|
||||
this bit is irrelevant in fnodes,
|
||||
or this interpretation is all wet */
|
||||
unsigned binary_search: 1; /* suggest binary search (unused) */
|
||||
unsigned internal: 1; /* 1 -> (internal) tree of anodes
|
||||
u8 binary_search: 1; /* suggest binary search (unused) */
|
||||
u8 internal: 1; /* 1 -> (internal) tree of anodes
|
||||
0 -> (leaf) list of extents */
|
||||
unsigned char fill[3];
|
||||
unsigned char n_free_nodes; /* free nodes in following array */
|
||||
unsigned char n_used_nodes; /* used nodes in following array */
|
||||
unsigned short first_free; /* offset from start of header to
|
||||
#else
|
||||
u8 internal: 1; /* 1 -> (internal) tree of anodes
|
||||
0 -> (leaf) list of extents */
|
||||
u8 binary_search: 1; /* suggest binary search (unused) */
|
||||
u8 fnode_parent: 1; /* ? we're pointed to by an fnode,
|
||||
the data btree or some ea or the
|
||||
main ea bootage pointer ea_secno */
|
||||
/* also can get set in fnodes, which
|
||||
may be a chkdsk glitch or may mean
|
||||
this bit is irrelevant in fnodes,
|
||||
or this interpretation is all wet */
|
||||
u8 flag1234: 4;
|
||||
u8 hbff: 1; /* high bit of first free entry offset */
|
||||
#endif
|
||||
u8 fill[3];
|
||||
u8 n_free_nodes; /* free nodes in following array */
|
||||
u8 n_used_nodes; /* used nodes in following array */
|
||||
u16 first_free; /* offset from start of header to
|
||||
first free node in array */
|
||||
union {
|
||||
struct bplus_internal_node internal[0]; /* (internal) 2-word entries giving
|
||||
@ -369,37 +438,38 @@ struct bplus_header
|
||||
|
||||
struct fnode
|
||||
{
|
||||
unsigned magic; /* f7e4 0aae */
|
||||
unsigned zero1[2]; /* read history */
|
||||
unsigned char len, name[15]; /* true length, truncated name */
|
||||
u32 magic; /* f7e4 0aae */
|
||||
u32 zero1[2]; /* read history */
|
||||
u8 len, name[15]; /* true length, truncated name */
|
||||
fnode_secno up; /* pointer to file's directory fnode */
|
||||
/*unsigned zero2[3];*/
|
||||
secno acl_size_l;
|
||||
secno acl_secno;
|
||||
unsigned short acl_size_s;
|
||||
char acl_anode;
|
||||
char zero2; /* history bit count */
|
||||
unsigned ea_size_l; /* length of disk-resident ea's */
|
||||
u16 acl_size_s;
|
||||
u8 acl_anode;
|
||||
u8 zero2; /* history bit count */
|
||||
u32 ea_size_l; /* length of disk-resident ea's */
|
||||
secno ea_secno; /* first sector of disk-resident ea's*/
|
||||
unsigned short ea_size_s; /* length of fnode-resident ea's */
|
||||
u16 ea_size_s; /* length of fnode-resident ea's */
|
||||
|
||||
unsigned flag0: 1;
|
||||
unsigned ea_anode: 1; /* 1 -> ea_secno is an anode */
|
||||
unsigned flag2: 1;
|
||||
unsigned flag3: 1;
|
||||
unsigned flag4: 1;
|
||||
unsigned flag5: 1;
|
||||
unsigned flag6: 1;
|
||||
unsigned flag7: 1;
|
||||
unsigned dirflag: 1; /* 1 -> directory. first & only extent
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
u8 flag0: 1;
|
||||
u8 ea_anode: 1; /* 1 -> ea_secno is an anode */
|
||||
u8 flag234567: 6;
|
||||
#else
|
||||
u8 flag234567: 6;
|
||||
u8 ea_anode: 1; /* 1 -> ea_secno is an anode */
|
||||
u8 flag0: 1;
|
||||
#endif
|
||||
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
u8 dirflag: 1; /* 1 -> directory. first & only extent
|
||||
points to dnode. */
|
||||
unsigned flag9: 1;
|
||||
unsigned flag10: 1;
|
||||
unsigned flag11: 1;
|
||||
unsigned flag12: 1;
|
||||
unsigned flag13: 1;
|
||||
unsigned flag14: 1;
|
||||
unsigned flag15: 1;
|
||||
u8 flag9012345: 7;
|
||||
#else
|
||||
u8 flag9012345: 7;
|
||||
u8 dirflag: 1; /* 1 -> directory. first & only extent
|
||||
points to dnode. */
|
||||
#endif
|
||||
|
||||
struct bplus_header btree; /* b+ tree, 8 extents or 12 subtrees */
|
||||
union {
|
||||
@ -407,17 +477,16 @@ struct fnode
|
||||
struct bplus_internal_node internal[12];
|
||||
} u;
|
||||
|
||||
unsigned file_size; /* file length, bytes */
|
||||
unsigned n_needea; /* number of EA's with NEEDEA set */
|
||||
char user_id[16]; /* unused */
|
||||
unsigned short ea_offs; /* offset from start of fnode
|
||||
u32 file_size; /* file length, bytes */
|
||||
u32 n_needea; /* number of EA's with NEEDEA set */
|
||||
u8 user_id[16]; /* unused */
|
||||
u16 ea_offs; /* offset from start of fnode
|
||||
to first fnode-resident ea */
|
||||
char dasd_limit_treshhold;
|
||||
char dasd_limit_delta;
|
||||
unsigned dasd_limit;
|
||||
unsigned dasd_usage;
|
||||
/*unsigned zero5[2];*/
|
||||
unsigned char ea[316]; /* zero or more EA's, packed together
|
||||
u8 dasd_limit_treshhold;
|
||||
u8 dasd_limit_delta;
|
||||
u32 dasd_limit;
|
||||
u32 dasd_usage;
|
||||
u8 ea[316]; /* zero or more EA's, packed together
|
||||
with no alignment padding.
|
||||
(Do not use this name, get here
|
||||
via fnode + ea_offs. I think.) */
|
||||
@ -430,7 +499,7 @@ struct fnode
|
||||
|
||||
struct anode
|
||||
{
|
||||
unsigned magic; /* 37e4 0aae */
|
||||
u32 magic; /* 37e4 0aae */
|
||||
anode_secno self; /* pointer to this anode */
|
||||
secno up; /* parent anode or fnode */
|
||||
|
||||
@ -440,7 +509,7 @@ struct anode
|
||||
struct bplus_internal_node internal[60];
|
||||
} u;
|
||||
|
||||
unsigned fill[3]; /* unused */
|
||||
u32 fill[3]; /* unused */
|
||||
};
|
||||
|
||||
|
||||
@ -461,25 +530,31 @@ struct anode
|
||||
|
||||
struct extended_attribute
|
||||
{
|
||||
unsigned indirect: 1; /* 1 -> value gives sector number
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
u8 indirect: 1; /* 1 -> value gives sector number
|
||||
where real value starts */
|
||||
unsigned anode: 1; /* 1 -> sector is an anode
|
||||
u8 anode: 1; /* 1 -> sector is an anode
|
||||
that points to fragmented value */
|
||||
unsigned flag2: 1;
|
||||
unsigned flag3: 1;
|
||||
unsigned flag4: 1;
|
||||
unsigned flag5: 1;
|
||||
unsigned flag6: 1;
|
||||
unsigned needea: 1; /* required ea */
|
||||
unsigned char namelen; /* length of name, bytes */
|
||||
unsigned short valuelen; /* length of value, bytes */
|
||||
unsigned char name[0];
|
||||
u8 flag23456: 5;
|
||||
u8 needea: 1; /* required ea */
|
||||
#else
|
||||
u8 needea: 1; /* required ea */
|
||||
u8 flag23456: 5;
|
||||
u8 anode: 1; /* 1 -> sector is an anode
|
||||
that points to fragmented value */
|
||||
u8 indirect: 1; /* 1 -> value gives sector number
|
||||
where real value starts */
|
||||
#endif
|
||||
u8 namelen; /* length of name, bytes */
|
||||
u8 valuelen_lo; /* length of value, bytes */
|
||||
u8 valuelen_hi; /* length of value, bytes */
|
||||
u8 name[0];
|
||||
/*
|
||||
unsigned char name[namelen]; ascii attrib name
|
||||
unsigned char nul; terminating '\0', not counted
|
||||
unsigned char value[valuelen]; value, arbitrary
|
||||
u8 name[namelen]; ascii attrib name
|
||||
u8 nul; terminating '\0', not counted
|
||||
u8 value[valuelen]; value, arbitrary
|
||||
if this.indirect, valuelen is 8 and the value is
|
||||
unsigned length; real length of value, bytes
|
||||
u32 length; real length of value, bytes
|
||||
secno secno; sector address where it starts
|
||||
if this.anode, the above sector number is the root of an anode tree
|
||||
which points to the value.
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include "hpfs.h"
|
||||
|
||||
@ -51,18 +52,16 @@ struct hpfs_inode_info {
|
||||
unsigned i_disk_sec; /* (files) minimalist cache of alloc info */
|
||||
unsigned i_n_secs; /* (files) minimalist cache of alloc info */
|
||||
unsigned i_ea_size; /* size of extended attributes */
|
||||
unsigned i_conv : 2; /* (files) crlf->newline hackery */
|
||||
unsigned i_ea_mode : 1; /* file's permission is stored in ea */
|
||||
unsigned i_ea_uid : 1; /* file's uid is stored in ea */
|
||||
unsigned i_ea_gid : 1; /* file's gid is stored in ea */
|
||||
unsigned i_dirty : 1;
|
||||
struct mutex i_mutex;
|
||||
struct mutex i_parent_mutex;
|
||||
loff_t **i_rddir_off;
|
||||
struct inode vfs_inode;
|
||||
};
|
||||
|
||||
struct hpfs_sb_info {
|
||||
struct mutex hpfs_mutex; /* global hpfs lock */
|
||||
ino_t sb_root; /* inode number of root dir */
|
||||
unsigned sb_fs_size; /* file system size, sectors */
|
||||
unsigned sb_bitmaps; /* sector number of bitmap list */
|
||||
@ -74,7 +73,6 @@ struct hpfs_sb_info {
|
||||
uid_t sb_uid; /* uid from mount options */
|
||||
gid_t sb_gid; /* gid from mount options */
|
||||
umode_t sb_mode; /* mode from mount options */
|
||||
unsigned sb_conv : 2; /* crlf->newline hackery */
|
||||
unsigned sb_eas : 2; /* eas: 0-ignore, 1-ro, 2-rw */
|
||||
unsigned sb_err : 2; /* on errs: 0-cont, 1-ro, 2-panic */
|
||||
unsigned sb_chk : 2; /* checks: 0-no, 1-normal, 2-strict */
|
||||
@ -87,20 +85,9 @@ struct hpfs_sb_info {
|
||||
unsigned *sb_bmp_dir; /* main bitmap directory */
|
||||
unsigned sb_c_bitmap; /* current bitmap */
|
||||
unsigned sb_max_fwd_alloc; /* max forwad allocation */
|
||||
struct mutex hpfs_creation_de; /* when creating dirents, nobody else
|
||||
can alloc blocks */
|
||||
/*unsigned sb_mounting : 1;*/
|
||||
int sb_timeshift;
|
||||
};
|
||||
|
||||
/*
|
||||
* conv= options
|
||||
*/
|
||||
|
||||
#define CONV_BINARY 0 /* no conversion */
|
||||
#define CONV_TEXT 1 /* crlf->newline */
|
||||
#define CONV_AUTO 2 /* decide based on file contents */
|
||||
|
||||
/* Four 512-byte buffers and the 2k block obtained by concatenating them */
|
||||
|
||||
struct quad_buffer_head {
|
||||
@ -113,7 +100,7 @@ struct quad_buffer_head {
|
||||
static inline dnode_secno de_down_pointer (struct hpfs_dirent *de)
|
||||
{
|
||||
CHKCOND(de->down,("HPFS: de_down_pointer: !de->down\n"));
|
||||
return *(dnode_secno *) ((void *) de + de->length - 4);
|
||||
return le32_to_cpu(*(dnode_secno *) ((void *) de + le16_to_cpu(de->length) - 4));
|
||||
}
|
||||
|
||||
/* The first dir entry in a dnode */
|
||||
@ -127,41 +114,46 @@ static inline struct hpfs_dirent *dnode_first_de (struct dnode *dnode)
|
||||
|
||||
static inline struct hpfs_dirent *dnode_end_de (struct dnode *dnode)
|
||||
{
|
||||
CHKCOND(dnode->first_free>=0x14 && dnode->first_free<=0xa00,("HPFS: dnode_end_de: dnode->first_free = %d\n",(int)dnode->first_free));
|
||||
return (void *) dnode + dnode->first_free;
|
||||
CHKCOND(le32_to_cpu(dnode->first_free)>=0x14 && le32_to_cpu(dnode->first_free)<=0xa00,("HPFS: dnode_end_de: dnode->first_free = %x\n",(unsigned)le32_to_cpu(dnode->first_free)));
|
||||
return (void *) dnode + le32_to_cpu(dnode->first_free);
|
||||
}
|
||||
|
||||
/* The dir entry after dir entry de */
|
||||
|
||||
static inline struct hpfs_dirent *de_next_de (struct hpfs_dirent *de)
|
||||
{
|
||||
CHKCOND(de->length>=0x20 && de->length<0x800,("HPFS: de_next_de: de->length = %d\n",(int)de->length));
|
||||
return (void *) de + de->length;
|
||||
CHKCOND(le16_to_cpu(de->length)>=0x20 && le16_to_cpu(de->length)<0x800,("HPFS: de_next_de: de->length = %x\n",(unsigned)le16_to_cpu(de->length)));
|
||||
return (void *) de + le16_to_cpu(de->length);
|
||||
}
|
||||
|
||||
static inline struct extended_attribute *fnode_ea(struct fnode *fnode)
|
||||
{
|
||||
return (struct extended_attribute *)((char *)fnode + fnode->ea_offs + fnode->acl_size_s);
|
||||
return (struct extended_attribute *)((char *)fnode + le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s));
|
||||
}
|
||||
|
||||
static inline struct extended_attribute *fnode_end_ea(struct fnode *fnode)
|
||||
{
|
||||
return (struct extended_attribute *)((char *)fnode + fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s);
|
||||
return (struct extended_attribute *)((char *)fnode + le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s));
|
||||
}
|
||||
|
||||
static unsigned ea_valuelen(struct extended_attribute *ea)
|
||||
{
|
||||
return ea->valuelen_lo + 256 * ea->valuelen_hi;
|
||||
}
|
||||
|
||||
static inline struct extended_attribute *next_ea(struct extended_attribute *ea)
|
||||
{
|
||||
return (struct extended_attribute *)((char *)ea + 5 + ea->namelen + ea->valuelen);
|
||||
return (struct extended_attribute *)((char *)ea + 5 + ea->namelen + ea_valuelen(ea));
|
||||
}
|
||||
|
||||
static inline secno ea_sec(struct extended_attribute *ea)
|
||||
{
|
||||
return *(secno *)((char *)ea + 9 + ea->namelen);
|
||||
return le32_to_cpu(get_unaligned((secno *)((char *)ea + 9 + ea->namelen)));
|
||||
}
|
||||
|
||||
static inline secno ea_len(struct extended_attribute *ea)
|
||||
{
|
||||
return *(secno *)((char *)ea + 5 + ea->namelen);
|
||||
return le32_to_cpu(get_unaligned((secno *)((char *)ea + 5 + ea->namelen)));
|
||||
}
|
||||
|
||||
static inline char *ea_data(struct extended_attribute *ea)
|
||||
@ -186,13 +178,13 @@ static inline void copy_de(struct hpfs_dirent *dst, struct hpfs_dirent *src)
|
||||
dst->not_8x3 = n;
|
||||
}
|
||||
|
||||
static inline unsigned tstbits(unsigned *bmp, unsigned b, unsigned n)
|
||||
static inline unsigned tstbits(u32 *bmp, unsigned b, unsigned n)
|
||||
{
|
||||
int i;
|
||||
if ((b >= 0x4000) || (b + n - 1 >= 0x4000)) return n;
|
||||
if (!((bmp[(b & 0x3fff) >> 5] >> (b & 0x1f)) & 1)) return 1;
|
||||
if (!((le32_to_cpu(bmp[(b & 0x3fff) >> 5]) >> (b & 0x1f)) & 1)) return 1;
|
||||
for (i = 1; i < n; i++)
|
||||
if (/*b+i < 0x4000 &&*/ !((bmp[((b+i) & 0x3fff) >> 5] >> ((b+i) & 0x1f)) & 1))
|
||||
if (!((le32_to_cpu(bmp[((b+i) & 0x3fff) >> 5]) >> ((b+i) & 0x1f)) & 1))
|
||||
return i + 1;
|
||||
return 0;
|
||||
}
|
||||
@ -200,12 +192,12 @@ static inline unsigned tstbits(unsigned *bmp, unsigned b, unsigned n)
|
||||
/* alloc.c */
|
||||
|
||||
int hpfs_chk_sectors(struct super_block *, secno, int, char *);
|
||||
secno hpfs_alloc_sector(struct super_block *, secno, unsigned, int, int);
|
||||
secno hpfs_alloc_sector(struct super_block *, secno, unsigned, int);
|
||||
int hpfs_alloc_if_possible(struct super_block *, secno);
|
||||
void hpfs_free_sectors(struct super_block *, secno, unsigned);
|
||||
int hpfs_check_free_dnodes(struct super_block *, int);
|
||||
void hpfs_free_dnode(struct super_block *, secno);
|
||||
struct dnode *hpfs_alloc_dnode(struct super_block *, secno, dnode_secno *, struct quad_buffer_head *, int);
|
||||
struct dnode *hpfs_alloc_dnode(struct super_block *, secno, dnode_secno *, struct quad_buffer_head *);
|
||||
struct fnode *hpfs_alloc_fnode(struct super_block *, secno, fnode_secno *, struct buffer_head **);
|
||||
struct anode *hpfs_alloc_anode(struct super_block *, secno, anode_secno *, struct buffer_head **);
|
||||
|
||||
@ -222,8 +214,6 @@ void hpfs_remove_fnode(struct super_block *, fnode_secno fno);
|
||||
|
||||
/* buffer.c */
|
||||
|
||||
void hpfs_lock_creation(struct super_block *);
|
||||
void hpfs_unlock_creation(struct super_block *);
|
||||
void *hpfs_map_sector(struct super_block *, unsigned, struct buffer_head **, int);
|
||||
void *hpfs_get_sector(struct super_block *, unsigned, struct buffer_head **);
|
||||
void *hpfs_map_4sectors(struct super_block *, unsigned, struct quad_buffer_head *, int);
|
||||
@ -247,7 +237,7 @@ void hpfs_del_pos(struct inode *, loff_t *);
|
||||
struct hpfs_dirent *hpfs_add_de(struct super_block *, struct dnode *,
|
||||
const unsigned char *, unsigned, secno);
|
||||
int hpfs_add_dirent(struct inode *, const unsigned char *, unsigned,
|
||||
struct hpfs_dirent *, int);
|
||||
struct hpfs_dirent *);
|
||||
int hpfs_remove_dirent(struct inode *, dnode_secno, struct hpfs_dirent *, struct quad_buffer_head *, int);
|
||||
void hpfs_count_dnodes(struct super_block *, dnode_secno, int *, int *, int *);
|
||||
dnode_secno hpfs_de_as_down_as_possible(struct super_block *, dnode_secno dno);
|
||||
@ -303,7 +293,6 @@ int hpfs_compare_names(struct super_block *, const unsigned char *, unsigned,
|
||||
const unsigned char *, unsigned, int);
|
||||
int hpfs_is_name_long(const unsigned char *, unsigned);
|
||||
void hpfs_adjust_length(const unsigned char *, unsigned *);
|
||||
void hpfs_decide_conv(struct inode *, const unsigned char *, unsigned);
|
||||
|
||||
/* namei.c */
|
||||
|
||||
@ -346,21 +335,26 @@ static inline time32_t gmt_to_local(struct super_block *s, time_t t)
|
||||
/*
|
||||
* Locking:
|
||||
*
|
||||
* hpfs_lock() is a leftover from the big kernel lock.
|
||||
* Right now, these functions are empty and only left
|
||||
* for documentation purposes. The file system no longer
|
||||
* works on SMP systems, so the lock is not needed
|
||||
* any more.
|
||||
* hpfs_lock() locks the whole filesystem. It must be taken
|
||||
* on any method called by the VFS.
|
||||
*
|
||||
* If someone is interested in making it work again, this
|
||||
* would be the place to start by adding a per-superblock
|
||||
* mutex and fixing all the bugs and performance issues
|
||||
* caused by that.
|
||||
* We don't do any per-file locking anymore, it is hard to
|
||||
* review and HPFS is not performance-sensitive anyway.
|
||||
*/
|
||||
static inline void hpfs_lock(struct super_block *s)
|
||||
{
|
||||
struct hpfs_sb_info *sbi = hpfs_sb(s);
|
||||
mutex_lock(&sbi->hpfs_mutex);
|
||||
}
|
||||
|
||||
static inline void hpfs_unlock(struct super_block *s)
|
||||
{
|
||||
struct hpfs_sb_info *sbi = hpfs_sb(s);
|
||||
mutex_unlock(&sbi->hpfs_mutex);
|
||||
}
|
||||
|
||||
static inline void hpfs_lock_assert(struct super_block *s)
|
||||
{
|
||||
struct hpfs_sb_info *sbi = hpfs_sb(s);
|
||||
WARN_ON(!mutex_is_locked(&sbi->hpfs_mutex));
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ void hpfs_init_inode(struct inode *i)
|
||||
i->i_uid = hpfs_sb(sb)->sb_uid;
|
||||
i->i_gid = hpfs_sb(sb)->sb_gid;
|
||||
i->i_mode = hpfs_sb(sb)->sb_mode;
|
||||
hpfs_inode->i_conv = hpfs_sb(sb)->sb_conv;
|
||||
i->i_size = -1;
|
||||
i->i_blocks = -1;
|
||||
|
||||
@ -116,8 +115,8 @@ void hpfs_read_inode(struct inode *i)
|
||||
i->i_mode |= S_IFDIR;
|
||||
i->i_op = &hpfs_dir_iops;
|
||||
i->i_fop = &hpfs_dir_ops;
|
||||
hpfs_inode->i_parent_dir = fnode->up;
|
||||
hpfs_inode->i_dno = fnode->u.external[0].disk_secno;
|
||||
hpfs_inode->i_parent_dir = le32_to_cpu(fnode->up);
|
||||
hpfs_inode->i_dno = le32_to_cpu(fnode->u.external[0].disk_secno);
|
||||
if (hpfs_sb(sb)->sb_chk >= 2) {
|
||||
struct buffer_head *bh0;
|
||||
if (hpfs_map_fnode(sb, hpfs_inode->i_parent_dir, &bh0)) brelse(bh0);
|
||||
@ -133,7 +132,7 @@ void hpfs_read_inode(struct inode *i)
|
||||
i->i_op = &hpfs_file_iops;
|
||||
i->i_fop = &hpfs_file_ops;
|
||||
i->i_nlink = 1;
|
||||
i->i_size = fnode->file_size;
|
||||
i->i_size = le32_to_cpu(fnode->file_size);
|
||||
i->i_blocks = ((i->i_size + 511) >> 9) + 1;
|
||||
i->i_data.a_ops = &hpfs_aops;
|
||||
hpfs_i(i)->mmu_private = i->i_size;
|
||||
@ -144,7 +143,7 @@ void hpfs_read_inode(struct inode *i)
|
||||
static void hpfs_write_inode_ea(struct inode *i, struct fnode *fnode)
|
||||
{
|
||||
struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
|
||||
/*if (fnode->acl_size_l || fnode->acl_size_s) {
|
||||
/*if (le32_to_cpu(fnode->acl_size_l) || le16_to_cpu(fnode->acl_size_s)) {
|
||||
Some unknown structures like ACL may be in fnode,
|
||||
we'd better not overwrite them
|
||||
hpfs_error(i->i_sb, "fnode %08x has some unknown HPFS386 stuctures", i->i_ino);
|
||||
@ -187,9 +186,7 @@ void hpfs_write_inode(struct inode *i)
|
||||
kfree(hpfs_inode->i_rddir_off);
|
||||
hpfs_inode->i_rddir_off = NULL;
|
||||
}
|
||||
mutex_lock(&hpfs_inode->i_parent_mutex);
|
||||
if (!i->i_nlink) {
|
||||
mutex_unlock(&hpfs_inode->i_parent_mutex);
|
||||
return;
|
||||
}
|
||||
parent = iget_locked(i->i_sb, hpfs_inode->i_parent_dir);
|
||||
@ -200,14 +197,9 @@ void hpfs_write_inode(struct inode *i)
|
||||
hpfs_read_inode(parent);
|
||||
unlock_new_inode(parent);
|
||||
}
|
||||
mutex_lock(&hpfs_inode->i_mutex);
|
||||
hpfs_write_inode_nolock(i);
|
||||
mutex_unlock(&hpfs_inode->i_mutex);
|
||||
iput(parent);
|
||||
} else {
|
||||
mark_inode_dirty(i);
|
||||
}
|
||||
mutex_unlock(&hpfs_inode->i_parent_mutex);
|
||||
}
|
||||
|
||||
void hpfs_write_inode_nolock(struct inode *i)
|
||||
@ -226,30 +218,30 @@ void hpfs_write_inode_nolock(struct inode *i)
|
||||
}
|
||||
} else de = NULL;
|
||||
if (S_ISREG(i->i_mode)) {
|
||||
fnode->file_size = i->i_size;
|
||||
if (de) de->file_size = i->i_size;
|
||||
fnode->file_size = cpu_to_le32(i->i_size);
|
||||
if (de) de->file_size = cpu_to_le32(i->i_size);
|
||||
} else if (S_ISDIR(i->i_mode)) {
|
||||
fnode->file_size = 0;
|
||||
if (de) de->file_size = 0;
|
||||
fnode->file_size = cpu_to_le32(0);
|
||||
if (de) de->file_size = cpu_to_le32(0);
|
||||
}
|
||||
hpfs_write_inode_ea(i, fnode);
|
||||
if (de) {
|
||||
de->write_date = gmt_to_local(i->i_sb, i->i_mtime.tv_sec);
|
||||
de->read_date = gmt_to_local(i->i_sb, i->i_atime.tv_sec);
|
||||
de->creation_date = gmt_to_local(i->i_sb, i->i_ctime.tv_sec);
|
||||
de->write_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_mtime.tv_sec));
|
||||
de->read_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_atime.tv_sec));
|
||||
de->creation_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_ctime.tv_sec));
|
||||
de->read_only = !(i->i_mode & 0222);
|
||||
de->ea_size = hpfs_inode->i_ea_size;
|
||||
de->ea_size = cpu_to_le32(hpfs_inode->i_ea_size);
|
||||
hpfs_mark_4buffers_dirty(&qbh);
|
||||
hpfs_brelse4(&qbh);
|
||||
}
|
||||
if (S_ISDIR(i->i_mode)) {
|
||||
if ((de = map_dirent(i, hpfs_inode->i_dno, "\001\001", 2, NULL, &qbh))) {
|
||||
de->write_date = gmt_to_local(i->i_sb, i->i_mtime.tv_sec);
|
||||
de->read_date = gmt_to_local(i->i_sb, i->i_atime.tv_sec);
|
||||
de->creation_date = gmt_to_local(i->i_sb, i->i_ctime.tv_sec);
|
||||
de->write_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_mtime.tv_sec));
|
||||
de->read_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_atime.tv_sec));
|
||||
de->creation_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_ctime.tv_sec));
|
||||
de->read_only = !(i->i_mode & 0222);
|
||||
de->ea_size = /*hpfs_inode->i_ea_size*/0;
|
||||
de->file_size = 0;
|
||||
de->ea_size = cpu_to_le32(/*hpfs_inode->i_ea_size*/0);
|
||||
de->file_size = cpu_to_le32(0);
|
||||
hpfs_mark_4buffers_dirty(&qbh);
|
||||
hpfs_brelse4(&qbh);
|
||||
} else
|
||||
@ -269,6 +261,10 @@ int hpfs_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
hpfs_lock(inode->i_sb);
|
||||
if (inode->i_ino == hpfs_sb(inode->i_sb)->sb_root)
|
||||
goto out_unlock;
|
||||
if ((attr->ia_valid & ATTR_UID) && attr->ia_uid >= 0x10000)
|
||||
goto out_unlock;
|
||||
if ((attr->ia_valid & ATTR_GID) && attr->ia_gid >= 0x10000)
|
||||
goto out_unlock;
|
||||
if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size > inode->i_size)
|
||||
goto out_unlock;
|
||||
|
||||
@ -284,7 +280,6 @@ int hpfs_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
}
|
||||
|
||||
setattr_copy(inode, attr);
|
||||
mark_inode_dirty(inode);
|
||||
|
||||
hpfs_write_inode(inode);
|
||||
|
||||
|
@ -21,7 +21,7 @@ unsigned int *hpfs_map_bitmap(struct super_block *s, unsigned bmp_block,
|
||||
hpfs_error(s, "hpfs_map_bitmap called with bad parameter: %08x at %s", bmp_block, id);
|
||||
return NULL;
|
||||
}
|
||||
sec = hpfs_sb(s)->sb_bmp_dir[bmp_block];
|
||||
sec = le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[bmp_block]);
|
||||
if (!sec || sec > hpfs_sb(s)->sb_fs_size-4) {
|
||||
hpfs_error(s, "invalid bitmap block pointer %08x -> %08x at %s", bmp_block, sec, id);
|
||||
return NULL;
|
||||
@ -46,18 +46,18 @@ unsigned char *hpfs_load_code_page(struct super_block *s, secno cps)
|
||||
struct code_page_data *cpd;
|
||||
struct code_page_directory *cp = hpfs_map_sector(s, cps, &bh, 0);
|
||||
if (!cp) return NULL;
|
||||
if (cp->magic != CP_DIR_MAGIC) {
|
||||
printk("HPFS: Code page directory magic doesn't match (magic = %08x)\n", cp->magic);
|
||||
if (le32_to_cpu(cp->magic) != CP_DIR_MAGIC) {
|
||||
printk("HPFS: Code page directory magic doesn't match (magic = %08x)\n", le32_to_cpu(cp->magic));
|
||||
brelse(bh);
|
||||
return NULL;
|
||||
}
|
||||
if (!cp->n_code_pages) {
|
||||
if (!le32_to_cpu(cp->n_code_pages)) {
|
||||
printk("HPFS: n_code_pages == 0\n");
|
||||
brelse(bh);
|
||||
return NULL;
|
||||
}
|
||||
cpds = cp->array[0].code_page_data;
|
||||
cpi = cp->array[0].index;
|
||||
cpds = le32_to_cpu(cp->array[0].code_page_data);
|
||||
cpi = le16_to_cpu(cp->array[0].index);
|
||||
brelse(bh);
|
||||
|
||||
if (cpi >= 3) {
|
||||
@ -66,12 +66,12 @@ unsigned char *hpfs_load_code_page(struct super_block *s, secno cps)
|
||||
}
|
||||
|
||||
if (!(cpd = hpfs_map_sector(s, cpds, &bh, 0))) return NULL;
|
||||
if ((unsigned)cpd->offs[cpi] > 0x178) {
|
||||
if (le16_to_cpu(cpd->offs[cpi]) > 0x178) {
|
||||
printk("HPFS: Code page index out of sector\n");
|
||||
brelse(bh);
|
||||
return NULL;
|
||||
}
|
||||
ptr = (unsigned char *)cpd + cpd->offs[cpi] + 6;
|
||||
ptr = (unsigned char *)cpd + le16_to_cpu(cpd->offs[cpi]) + 6;
|
||||
if (!(cp_table = kmalloc(256, GFP_KERNEL))) {
|
||||
printk("HPFS: out of memory for code page table\n");
|
||||
brelse(bh);
|
||||
@ -125,7 +125,7 @@ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_hea
|
||||
if (hpfs_sb(s)->sb_chk) {
|
||||
struct extended_attribute *ea;
|
||||
struct extended_attribute *ea_end;
|
||||
if (fnode->magic != FNODE_MAGIC) {
|
||||
if (le32_to_cpu(fnode->magic) != FNODE_MAGIC) {
|
||||
hpfs_error(s, "bad magic on fnode %08lx",
|
||||
(unsigned long)ino);
|
||||
goto bail;
|
||||
@ -138,7 +138,7 @@ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_hea
|
||||
(unsigned long)ino);
|
||||
goto bail;
|
||||
}
|
||||
if (fnode->btree.first_free !=
|
||||
if (le16_to_cpu(fnode->btree.first_free) !=
|
||||
8 + fnode->btree.n_used_nodes * (fnode->btree.internal ? 8 : 12)) {
|
||||
hpfs_error(s,
|
||||
"bad first_free pointer in fnode %08lx",
|
||||
@ -146,12 +146,12 @@ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_hea
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
if (fnode->ea_size_s && ((signed int)fnode->ea_offs < 0xc4 ||
|
||||
(signed int)fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s > 0x200)) {
|
||||
if (le16_to_cpu(fnode->ea_size_s) && (le16_to_cpu(fnode->ea_offs) < 0xc4 ||
|
||||
le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s) > 0x200)) {
|
||||
hpfs_error(s,
|
||||
"bad EA info in fnode %08lx: ea_offs == %04x ea_size_s == %04x",
|
||||
(unsigned long)ino,
|
||||
fnode->ea_offs, fnode->ea_size_s);
|
||||
le16_to_cpu(fnode->ea_offs), le16_to_cpu(fnode->ea_size_s));
|
||||
goto bail;
|
||||
}
|
||||
ea = fnode_ea(fnode);
|
||||
@ -178,16 +178,20 @@ struct anode *hpfs_map_anode(struct super_block *s, anode_secno ano, struct buff
|
||||
if (hpfs_sb(s)->sb_chk) if (hpfs_chk_sectors(s, ano, 1, "anode")) return NULL;
|
||||
if ((anode = hpfs_map_sector(s, ano, bhp, ANODE_RD_AHEAD)))
|
||||
if (hpfs_sb(s)->sb_chk) {
|
||||
if (anode->magic != ANODE_MAGIC || anode->self != ano) {
|
||||
if (le32_to_cpu(anode->magic) != ANODE_MAGIC) {
|
||||
hpfs_error(s, "bad magic on anode %08x", ano);
|
||||
goto bail;
|
||||
}
|
||||
if (le32_to_cpu(anode->self) != ano) {
|
||||
hpfs_error(s, "self pointer invalid on anode %08x", ano);
|
||||
goto bail;
|
||||
}
|
||||
if ((unsigned)anode->btree.n_used_nodes + (unsigned)anode->btree.n_free_nodes !=
|
||||
(anode->btree.internal ? 60 : 40)) {
|
||||
hpfs_error(s, "bad number of nodes in anode %08x", ano);
|
||||
goto bail;
|
||||
}
|
||||
if (anode->btree.first_free !=
|
||||
if (le16_to_cpu(anode->btree.first_free) !=
|
||||
8 + anode->btree.n_used_nodes * (anode->btree.internal ? 8 : 12)) {
|
||||
hpfs_error(s, "bad first_free pointer in anode %08x", ano);
|
||||
goto bail;
|
||||
@ -219,26 +223,26 @@ struct dnode *hpfs_map_dnode(struct super_block *s, unsigned secno,
|
||||
unsigned p, pp = 0;
|
||||
unsigned char *d = (unsigned char *)dnode;
|
||||
int b = 0;
|
||||
if (dnode->magic != DNODE_MAGIC) {
|
||||
if (le32_to_cpu(dnode->magic) != DNODE_MAGIC) {
|
||||
hpfs_error(s, "bad magic on dnode %08x", secno);
|
||||
goto bail;
|
||||
}
|
||||
if (dnode->self != secno)
|
||||
hpfs_error(s, "bad self pointer on dnode %08x self = %08x", secno, dnode->self);
|
||||
if (le32_to_cpu(dnode->self) != secno)
|
||||
hpfs_error(s, "bad self pointer on dnode %08x self = %08x", secno, le32_to_cpu(dnode->self));
|
||||
/* Check dirents - bad dirents would cause infinite
|
||||
loops or shooting to memory */
|
||||
if (dnode->first_free > 2048/* || dnode->first_free < 84*/) {
|
||||
hpfs_error(s, "dnode %08x has first_free == %08x", secno, dnode->first_free);
|
||||
if (le32_to_cpu(dnode->first_free) > 2048) {
|
||||
hpfs_error(s, "dnode %08x has first_free == %08x", secno, le32_to_cpu(dnode->first_free));
|
||||
goto bail;
|
||||
}
|
||||
for (p = 20; p < dnode->first_free; p += d[p] + (d[p+1] << 8)) {
|
||||
for (p = 20; p < le32_to_cpu(dnode->first_free); p += d[p] + (d[p+1] << 8)) {
|
||||
struct hpfs_dirent *de = (struct hpfs_dirent *)((char *)dnode + p);
|
||||
if (de->length > 292 || (de->length < 32) || (de->length & 3) || p + de->length > 2048) {
|
||||
if (le16_to_cpu(de->length) > 292 || (le16_to_cpu(de->length) < 32) || (le16_to_cpu(de->length) & 3) || p + le16_to_cpu(de->length) > 2048) {
|
||||
hpfs_error(s, "bad dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp);
|
||||
goto bail;
|
||||
}
|
||||
if (((31 + de->namelen + de->down*4 + 3) & ~3) != de->length) {
|
||||
if (((31 + de->namelen + de->down*4 + 3) & ~3) < de->length && s->s_flags & MS_RDONLY) goto ok;
|
||||
if (((31 + de->namelen + de->down*4 + 3) & ~3) != le16_to_cpu(de->length)) {
|
||||
if (((31 + de->namelen + de->down*4 + 3) & ~3) < le16_to_cpu(de->length) && s->s_flags & MS_RDONLY) goto ok;
|
||||
hpfs_error(s, "namelen does not match dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp);
|
||||
goto bail;
|
||||
}
|
||||
@ -251,7 +255,7 @@ struct dnode *hpfs_map_dnode(struct super_block *s, unsigned secno,
|
||||
pp = p;
|
||||
|
||||
}
|
||||
if (p != dnode->first_free) {
|
||||
if (p != le32_to_cpu(dnode->first_free)) {
|
||||
hpfs_error(s, "size on last dirent does not match first_free; dnode %08x", secno);
|
||||
goto bail;
|
||||
}
|
||||
@ -277,7 +281,7 @@ dnode_secno hpfs_fnode_dno(struct super_block *s, ino_t ino)
|
||||
if (!fnode)
|
||||
return 0;
|
||||
|
||||
dno = fnode->u.external[0].disk_secno;
|
||||
dno = le32_to_cpu(fnode->u.external[0].disk_secno);
|
||||
brelse(bh);
|
||||
return dno;
|
||||
}
|
||||
|
@ -8,39 +8,6 @@
|
||||
|
||||
#include "hpfs_fn.h"
|
||||
|
||||
static const char *text_postfix[]={
|
||||
".ASM", ".BAS", ".BAT", ".C", ".CC", ".CFG", ".CMD", ".CON", ".CPP", ".DEF",
|
||||
".DOC", ".DPR", ".ERX", ".H", ".HPP", ".HTM", ".HTML", ".JAVA", ".LOG", ".PAS",
|
||||
".RC", ".TEX", ".TXT", ".Y", ""};
|
||||
|
||||
static const char *text_prefix[]={
|
||||
"AUTOEXEC.", "CHANGES", "COPYING", "CONFIG.", "CREDITS", "FAQ", "FILE_ID.DIZ",
|
||||
"MAKEFILE", "READ.ME", "README", "TERMCAP", ""};
|
||||
|
||||
void hpfs_decide_conv(struct inode *inode, const unsigned char *name, unsigned len)
|
||||
{
|
||||
struct hpfs_inode_info *hpfs_inode = hpfs_i(inode);
|
||||
int i;
|
||||
if (hpfs_inode->i_conv != CONV_AUTO) return;
|
||||
for (i = 0; *text_postfix[i]; i++) {
|
||||
int l = strlen(text_postfix[i]);
|
||||
if (l <= len)
|
||||
if (!hpfs_compare_names(inode->i_sb, text_postfix[i], l, name + len - l, l, 0))
|
||||
goto text;
|
||||
}
|
||||
for (i = 0; *text_prefix[i]; i++) {
|
||||
int l = strlen(text_prefix[i]);
|
||||
if (l <= len)
|
||||
if (!hpfs_compare_names(inode->i_sb, text_prefix[i], l, name, l, 0))
|
||||
goto text;
|
||||
}
|
||||
hpfs_inode->i_conv = CONV_BINARY;
|
||||
return;
|
||||
text:
|
||||
hpfs_inode->i_conv = CONV_TEXT;
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int not_allowed_char(unsigned char c)
|
||||
{
|
||||
return c<' ' || c=='"' || c=='*' || c=='/' || c==':' || c=='<' ||
|
||||
|
106
fs/hpfs/namei.c
106
fs/hpfs/namei.c
@ -29,7 +29,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
|
||||
fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);
|
||||
if (!fnode)
|
||||
goto bail;
|
||||
dnode = hpfs_alloc_dnode(dir->i_sb, fno, &dno, &qbh0, 1);
|
||||
dnode = hpfs_alloc_dnode(dir->i_sb, fno, &dno, &qbh0);
|
||||
if (!dnode)
|
||||
goto bail1;
|
||||
memset(&dee, 0, sizeof dee);
|
||||
@ -37,8 +37,8 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
|
||||
if (!(mode & 0222)) dee.read_only = 1;
|
||||
/*dee.archive = 0;*/
|
||||
dee.hidden = name[0] == '.';
|
||||
dee.fnode = fno;
|
||||
dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds());
|
||||
dee.fnode = cpu_to_le32(fno);
|
||||
dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));
|
||||
result = new_inode(dir->i_sb);
|
||||
if (!result)
|
||||
goto bail2;
|
||||
@ -46,7 +46,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
|
||||
result->i_ino = fno;
|
||||
hpfs_i(result)->i_parent_dir = dir->i_ino;
|
||||
hpfs_i(result)->i_dno = dno;
|
||||
result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date);
|
||||
result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));
|
||||
result->i_ctime.tv_nsec = 0;
|
||||
result->i_mtime.tv_nsec = 0;
|
||||
result->i_atime.tv_nsec = 0;
|
||||
@ -60,8 +60,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
|
||||
if (dee.read_only)
|
||||
result->i_mode &= ~0222;
|
||||
|
||||
mutex_lock(&hpfs_i(dir)->i_mutex);
|
||||
r = hpfs_add_dirent(dir, name, len, &dee, 0);
|
||||
r = hpfs_add_dirent(dir, name, len, &dee);
|
||||
if (r == 1)
|
||||
goto bail3;
|
||||
if (r == -1) {
|
||||
@ -70,21 +69,21 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
|
||||
}
|
||||
fnode->len = len;
|
||||
memcpy(fnode->name, name, len > 15 ? 15 : len);
|
||||
fnode->up = dir->i_ino;
|
||||
fnode->up = cpu_to_le32(dir->i_ino);
|
||||
fnode->dirflag = 1;
|
||||
fnode->btree.n_free_nodes = 7;
|
||||
fnode->btree.n_used_nodes = 1;
|
||||
fnode->btree.first_free = 0x14;
|
||||
fnode->u.external[0].disk_secno = dno;
|
||||
fnode->u.external[0].file_secno = -1;
|
||||
fnode->btree.first_free = cpu_to_le16(0x14);
|
||||
fnode->u.external[0].disk_secno = cpu_to_le32(dno);
|
||||
fnode->u.external[0].file_secno = cpu_to_le32(-1);
|
||||
dnode->root_dnode = 1;
|
||||
dnode->up = fno;
|
||||
dnode->up = cpu_to_le32(fno);
|
||||
de = hpfs_add_de(dir->i_sb, dnode, "\001\001", 2, 0);
|
||||
de->creation_date = de->write_date = de->read_date = gmt_to_local(dir->i_sb, get_seconds());
|
||||
de->creation_date = de->write_date = de->read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));
|
||||
if (!(mode & 0222)) de->read_only = 1;
|
||||
de->first = de->directory = 1;
|
||||
/*de->hidden = de->system = 0;*/
|
||||
de->fnode = fno;
|
||||
de->fnode = cpu_to_le32(fno);
|
||||
mark_buffer_dirty(bh);
|
||||
brelse(bh);
|
||||
hpfs_mark_4buffers_dirty(&qbh0);
|
||||
@ -101,11 +100,9 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
|
||||
hpfs_write_inode_nolock(result);
|
||||
}
|
||||
d_instantiate(dentry, result);
|
||||
mutex_unlock(&hpfs_i(dir)->i_mutex);
|
||||
hpfs_unlock(dir->i_sb);
|
||||
return 0;
|
||||
bail3:
|
||||
mutex_unlock(&hpfs_i(dir)->i_mutex);
|
||||
iput(result);
|
||||
bail2:
|
||||
hpfs_brelse4(&qbh0);
|
||||
@ -140,8 +137,8 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc
|
||||
if (!(mode & 0222)) dee.read_only = 1;
|
||||
dee.archive = 1;
|
||||
dee.hidden = name[0] == '.';
|
||||
dee.fnode = fno;
|
||||
dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds());
|
||||
dee.fnode = cpu_to_le32(fno);
|
||||
dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));
|
||||
|
||||
result = new_inode(dir->i_sb);
|
||||
if (!result)
|
||||
@ -154,9 +151,8 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc
|
||||
result->i_op = &hpfs_file_iops;
|
||||
result->i_fop = &hpfs_file_ops;
|
||||
result->i_nlink = 1;
|
||||
hpfs_decide_conv(result, name, len);
|
||||
hpfs_i(result)->i_parent_dir = dir->i_ino;
|
||||
result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date);
|
||||
result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));
|
||||
result->i_ctime.tv_nsec = 0;
|
||||
result->i_mtime.tv_nsec = 0;
|
||||
result->i_atime.tv_nsec = 0;
|
||||
@ -168,8 +164,7 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc
|
||||
result->i_data.a_ops = &hpfs_aops;
|
||||
hpfs_i(result)->mmu_private = 0;
|
||||
|
||||
mutex_lock(&hpfs_i(dir)->i_mutex);
|
||||
r = hpfs_add_dirent(dir, name, len, &dee, 0);
|
||||
r = hpfs_add_dirent(dir, name, len, &dee);
|
||||
if (r == 1)
|
||||
goto bail2;
|
||||
if (r == -1) {
|
||||
@ -178,7 +173,7 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc
|
||||
}
|
||||
fnode->len = len;
|
||||
memcpy(fnode->name, name, len > 15 ? 15 : len);
|
||||
fnode->up = dir->i_ino;
|
||||
fnode->up = cpu_to_le32(dir->i_ino);
|
||||
mark_buffer_dirty(bh);
|
||||
brelse(bh);
|
||||
|
||||
@ -193,12 +188,10 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc
|
||||
hpfs_write_inode_nolock(result);
|
||||
}
|
||||
d_instantiate(dentry, result);
|
||||
mutex_unlock(&hpfs_i(dir)->i_mutex);
|
||||
hpfs_unlock(dir->i_sb);
|
||||
return 0;
|
||||
|
||||
bail2:
|
||||
mutex_unlock(&hpfs_i(dir)->i_mutex);
|
||||
iput(result);
|
||||
bail1:
|
||||
brelse(bh);
|
||||
@ -232,8 +225,8 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t
|
||||
if (!(mode & 0222)) dee.read_only = 1;
|
||||
dee.archive = 1;
|
||||
dee.hidden = name[0] == '.';
|
||||
dee.fnode = fno;
|
||||
dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds());
|
||||
dee.fnode = cpu_to_le32(fno);
|
||||
dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));
|
||||
|
||||
result = new_inode(dir->i_sb);
|
||||
if (!result)
|
||||
@ -242,7 +235,7 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t
|
||||
hpfs_init_inode(result);
|
||||
result->i_ino = fno;
|
||||
hpfs_i(result)->i_parent_dir = dir->i_ino;
|
||||
result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date);
|
||||
result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));
|
||||
result->i_ctime.tv_nsec = 0;
|
||||
result->i_mtime.tv_nsec = 0;
|
||||
result->i_atime.tv_nsec = 0;
|
||||
@ -254,8 +247,7 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t
|
||||
result->i_blocks = 1;
|
||||
init_special_inode(result, mode, rdev);
|
||||
|
||||
mutex_lock(&hpfs_i(dir)->i_mutex);
|
||||
r = hpfs_add_dirent(dir, name, len, &dee, 0);
|
||||
r = hpfs_add_dirent(dir, name, len, &dee);
|
||||
if (r == 1)
|
||||
goto bail2;
|
||||
if (r == -1) {
|
||||
@ -264,19 +256,17 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t
|
||||
}
|
||||
fnode->len = len;
|
||||
memcpy(fnode->name, name, len > 15 ? 15 : len);
|
||||
fnode->up = dir->i_ino;
|
||||
fnode->up = cpu_to_le32(dir->i_ino);
|
||||
mark_buffer_dirty(bh);
|
||||
|
||||
insert_inode_hash(result);
|
||||
|
||||
hpfs_write_inode_nolock(result);
|
||||
d_instantiate(dentry, result);
|
||||
mutex_unlock(&hpfs_i(dir)->i_mutex);
|
||||
brelse(bh);
|
||||
hpfs_unlock(dir->i_sb);
|
||||
return 0;
|
||||
bail2:
|
||||
mutex_unlock(&hpfs_i(dir)->i_mutex);
|
||||
iput(result);
|
||||
bail1:
|
||||
brelse(bh);
|
||||
@ -310,8 +300,8 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
|
||||
memset(&dee, 0, sizeof dee);
|
||||
dee.archive = 1;
|
||||
dee.hidden = name[0] == '.';
|
||||
dee.fnode = fno;
|
||||
dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds());
|
||||
dee.fnode = cpu_to_le32(fno);
|
||||
dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));
|
||||
|
||||
result = new_inode(dir->i_sb);
|
||||
if (!result)
|
||||
@ -319,7 +309,7 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
|
||||
result->i_ino = fno;
|
||||
hpfs_init_inode(result);
|
||||
hpfs_i(result)->i_parent_dir = dir->i_ino;
|
||||
result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date);
|
||||
result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));
|
||||
result->i_ctime.tv_nsec = 0;
|
||||
result->i_mtime.tv_nsec = 0;
|
||||
result->i_atime.tv_nsec = 0;
|
||||
@ -333,8 +323,7 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
|
||||
result->i_op = &page_symlink_inode_operations;
|
||||
result->i_data.a_ops = &hpfs_symlink_aops;
|
||||
|
||||
mutex_lock(&hpfs_i(dir)->i_mutex);
|
||||
r = hpfs_add_dirent(dir, name, len, &dee, 0);
|
||||
r = hpfs_add_dirent(dir, name, len, &dee);
|
||||
if (r == 1)
|
||||
goto bail2;
|
||||
if (r == -1) {
|
||||
@ -343,7 +332,7 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
|
||||
}
|
||||
fnode->len = len;
|
||||
memcpy(fnode->name, name, len > 15 ? 15 : len);
|
||||
fnode->up = dir->i_ino;
|
||||
fnode->up = cpu_to_le32(dir->i_ino);
|
||||
hpfs_set_ea(result, fnode, "SYMLINK", symlink, strlen(symlink));
|
||||
mark_buffer_dirty(bh);
|
||||
brelse(bh);
|
||||
@ -352,11 +341,9 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
|
||||
|
||||
hpfs_write_inode_nolock(result);
|
||||
d_instantiate(dentry, result);
|
||||
mutex_unlock(&hpfs_i(dir)->i_mutex);
|
||||
hpfs_unlock(dir->i_sb);
|
||||
return 0;
|
||||
bail2:
|
||||
mutex_unlock(&hpfs_i(dir)->i_mutex);
|
||||
iput(result);
|
||||
bail1:
|
||||
brelse(bh);
|
||||
@ -374,7 +361,6 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry)
|
||||
struct hpfs_dirent *de;
|
||||
struct inode *inode = dentry->d_inode;
|
||||
dnode_secno dno;
|
||||
fnode_secno fno;
|
||||
int r;
|
||||
int rep = 0;
|
||||
int err;
|
||||
@ -382,8 +368,6 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry)
|
||||
hpfs_lock(dir->i_sb);
|
||||
hpfs_adjust_length(name, &len);
|
||||
again:
|
||||
mutex_lock(&hpfs_i(inode)->i_parent_mutex);
|
||||
mutex_lock(&hpfs_i(dir)->i_mutex);
|
||||
err = -ENOENT;
|
||||
de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh);
|
||||
if (!de)
|
||||
@ -397,7 +381,6 @@ again:
|
||||
if (de->directory)
|
||||
goto out1;
|
||||
|
||||
fno = de->fnode;
|
||||
r = hpfs_remove_dirent(dir, dno, de, &qbh, 1);
|
||||
switch (r) {
|
||||
case 1:
|
||||
@ -410,8 +393,6 @@ again:
|
||||
if (rep++)
|
||||
break;
|
||||
|
||||
mutex_unlock(&hpfs_i(dir)->i_mutex);
|
||||
mutex_unlock(&hpfs_i(inode)->i_parent_mutex);
|
||||
dentry_unhash(dentry);
|
||||
if (!d_unhashed(dentry)) {
|
||||
dput(dentry);
|
||||
@ -445,8 +426,6 @@ again:
|
||||
out1:
|
||||
hpfs_brelse4(&qbh);
|
||||
out:
|
||||
mutex_unlock(&hpfs_i(dir)->i_mutex);
|
||||
mutex_unlock(&hpfs_i(inode)->i_parent_mutex);
|
||||
hpfs_unlock(dir->i_sb);
|
||||
return err;
|
||||
}
|
||||
@ -459,15 +438,12 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
struct hpfs_dirent *de;
|
||||
struct inode *inode = dentry->d_inode;
|
||||
dnode_secno dno;
|
||||
fnode_secno fno;
|
||||
int n_items = 0;
|
||||
int err;
|
||||
int r;
|
||||
|
||||
hpfs_adjust_length(name, &len);
|
||||
hpfs_lock(dir->i_sb);
|
||||
mutex_lock(&hpfs_i(inode)->i_parent_mutex);
|
||||
mutex_lock(&hpfs_i(dir)->i_mutex);
|
||||
err = -ENOENT;
|
||||
de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh);
|
||||
if (!de)
|
||||
@ -486,7 +462,6 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
if (n_items)
|
||||
goto out1;
|
||||
|
||||
fno = de->fnode;
|
||||
r = hpfs_remove_dirent(dir, dno, de, &qbh, 1);
|
||||
switch (r) {
|
||||
case 1:
|
||||
@ -505,8 +480,6 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
out1:
|
||||
hpfs_brelse4(&qbh);
|
||||
out:
|
||||
mutex_unlock(&hpfs_i(dir)->i_mutex);
|
||||
mutex_unlock(&hpfs_i(inode)->i_parent_mutex);
|
||||
hpfs_unlock(dir->i_sb);
|
||||
return err;
|
||||
}
|
||||
@ -568,12 +541,6 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
|
||||
hpfs_lock(i->i_sb);
|
||||
/* order doesn't matter, due to VFS exclusion */
|
||||
mutex_lock(&hpfs_i(i)->i_parent_mutex);
|
||||
if (new_inode)
|
||||
mutex_lock(&hpfs_i(new_inode)->i_parent_mutex);
|
||||
mutex_lock(&hpfs_i(old_dir)->i_mutex);
|
||||
if (new_dir != old_dir)
|
||||
mutex_lock(&hpfs_i(new_dir)->i_mutex);
|
||||
|
||||
/* Erm? Moving over the empty non-busy directory is perfectly legal */
|
||||
if (new_inode && S_ISDIR(new_inode->i_mode)) {
|
||||
@ -610,9 +577,7 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
|
||||
if (new_dir == old_dir) hpfs_brelse4(&qbh);
|
||||
|
||||
hpfs_lock_creation(i->i_sb);
|
||||
if ((r = hpfs_add_dirent(new_dir, new_name, new_len, &de, 1))) {
|
||||
hpfs_unlock_creation(i->i_sb);
|
||||
if ((r = hpfs_add_dirent(new_dir, new_name, new_len, &de))) {
|
||||
if (r == -1) hpfs_error(new_dir->i_sb, "hpfs_rename: dirent already exists!");
|
||||
err = r == 1 ? -ENOSPC : -EFSERROR;
|
||||
if (new_dir != old_dir) hpfs_brelse4(&qbh);
|
||||
@ -621,20 +586,17 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
|
||||
if (new_dir == old_dir)
|
||||
if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, old_name, old_len, &dno, &qbh))) {
|
||||
hpfs_unlock_creation(i->i_sb);
|
||||
hpfs_error(i->i_sb, "lookup succeeded but map dirent failed at #2");
|
||||
err = -ENOENT;
|
||||
goto end1;
|
||||
}
|
||||
|
||||
if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 0))) {
|
||||
hpfs_unlock_creation(i->i_sb);
|
||||
hpfs_error(i->i_sb, "hpfs_rename: could not remove dirent");
|
||||
err = r == 2 ? -ENOSPC : -EFSERROR;
|
||||
goto end1;
|
||||
}
|
||||
hpfs_unlock_creation(i->i_sb);
|
||||
|
||||
|
||||
end:
|
||||
hpfs_i(i)->i_parent_dir = new_dir->i_ino;
|
||||
if (S_ISDIR(i->i_mode)) {
|
||||
@ -642,22 +604,14 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
drop_nlink(old_dir);
|
||||
}
|
||||
if ((fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) {
|
||||
fnode->up = new_dir->i_ino;
|
||||
fnode->up = cpu_to_le32(new_dir->i_ino);
|
||||
fnode->len = new_len;
|
||||
memcpy(fnode->name, new_name, new_len>15?15:new_len);
|
||||
if (new_len < 15) memset(&fnode->name[new_len], 0, 15 - new_len);
|
||||
mark_buffer_dirty(bh);
|
||||
brelse(bh);
|
||||
}
|
||||
hpfs_i(i)->i_conv = hpfs_sb(i->i_sb)->sb_conv;
|
||||
hpfs_decide_conv(i, new_name, new_len);
|
||||
end1:
|
||||
if (old_dir != new_dir)
|
||||
mutex_unlock(&hpfs_i(new_dir)->i_mutex);
|
||||
mutex_unlock(&hpfs_i(old_dir)->i_mutex);
|
||||
mutex_unlock(&hpfs_i(i)->i_parent_mutex);
|
||||
if (new_inode)
|
||||
mutex_unlock(&hpfs_i(new_inode)->i_parent_mutex);
|
||||
hpfs_unlock(i->i_sb);
|
||||
return err;
|
||||
}
|
||||
|
118
fs/hpfs/super.c
118
fs/hpfs/super.c
@ -18,15 +18,16 @@
|
||||
|
||||
/* Mark the filesystem dirty, so that chkdsk checks it when os/2 booted */
|
||||
|
||||
static void mark_dirty(struct super_block *s)
|
||||
static void mark_dirty(struct super_block *s, int remount)
|
||||
{
|
||||
if (hpfs_sb(s)->sb_chkdsk && !(s->s_flags & MS_RDONLY)) {
|
||||
if (hpfs_sb(s)->sb_chkdsk && (remount || !(s->s_flags & MS_RDONLY))) {
|
||||
struct buffer_head *bh;
|
||||
struct hpfs_spare_block *sb;
|
||||
if ((sb = hpfs_map_sector(s, 17, &bh, 0))) {
|
||||
sb->dirty = 1;
|
||||
sb->old_wrote = 0;
|
||||
mark_buffer_dirty(bh);
|
||||
sync_dirty_buffer(bh);
|
||||
brelse(bh);
|
||||
}
|
||||
}
|
||||
@ -40,10 +41,12 @@ static void unmark_dirty(struct super_block *s)
|
||||
struct buffer_head *bh;
|
||||
struct hpfs_spare_block *sb;
|
||||
if (s->s_flags & MS_RDONLY) return;
|
||||
sync_blockdev(s->s_bdev);
|
||||
if ((sb = hpfs_map_sector(s, 17, &bh, 0))) {
|
||||
sb->dirty = hpfs_sb(s)->sb_chkdsk > 1 - hpfs_sb(s)->sb_was_error;
|
||||
sb->old_wrote = hpfs_sb(s)->sb_chkdsk >= 2 && !hpfs_sb(s)->sb_was_error;
|
||||
mark_buffer_dirty(bh);
|
||||
sync_dirty_buffer(bh);
|
||||
brelse(bh);
|
||||
}
|
||||
}
|
||||
@ -63,13 +66,13 @@ void hpfs_error(struct super_block *s, const char *fmt, ...)
|
||||
if (!hpfs_sb(s)->sb_was_error) {
|
||||
if (hpfs_sb(s)->sb_err == 2) {
|
||||
printk("; crashing the system because you wanted it\n");
|
||||
mark_dirty(s);
|
||||
mark_dirty(s, 0);
|
||||
panic("HPFS panic");
|
||||
} else if (hpfs_sb(s)->sb_err == 1) {
|
||||
if (s->s_flags & MS_RDONLY) printk("; already mounted read-only\n");
|
||||
else {
|
||||
printk("; remounting read-only\n");
|
||||
mark_dirty(s);
|
||||
mark_dirty(s, 0);
|
||||
s->s_flags |= MS_RDONLY;
|
||||
}
|
||||
} else if (s->s_flags & MS_RDONLY) printk("; going on - but anything won't be destroyed because it's read-only\n");
|
||||
@ -102,9 +105,12 @@ static void hpfs_put_super(struct super_block *s)
|
||||
{
|
||||
struct hpfs_sb_info *sbi = hpfs_sb(s);
|
||||
|
||||
hpfs_lock(s);
|
||||
unmark_dirty(s);
|
||||
hpfs_unlock(s);
|
||||
|
||||
kfree(sbi->sb_cp_table);
|
||||
kfree(sbi->sb_bmp_dir);
|
||||
unmark_dirty(s);
|
||||
s->s_fs_info = NULL;
|
||||
kfree(sbi);
|
||||
}
|
||||
@ -129,7 +135,7 @@ static unsigned count_bitmaps(struct super_block *s)
|
||||
n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14;
|
||||
count = 0;
|
||||
for (n = 0; n < n_bands; n++)
|
||||
count += hpfs_count_one_bitmap(s, hpfs_sb(s)->sb_bmp_dir[n]);
|
||||
count += hpfs_count_one_bitmap(s, le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[n]));
|
||||
return count;
|
||||
}
|
||||
|
||||
@ -188,8 +194,6 @@ static void init_once(void *foo)
|
||||
{
|
||||
struct hpfs_inode_info *ei = (struct hpfs_inode_info *) foo;
|
||||
|
||||
mutex_init(&ei->i_mutex);
|
||||
mutex_init(&ei->i_parent_mutex);
|
||||
inode_init_once(&ei->vfs_inode);
|
||||
}
|
||||
|
||||
@ -218,7 +222,6 @@ static void destroy_inodecache(void)
|
||||
|
||||
enum {
|
||||
Opt_help, Opt_uid, Opt_gid, Opt_umask, Opt_case_lower, Opt_case_asis,
|
||||
Opt_conv_binary, Opt_conv_text, Opt_conv_auto,
|
||||
Opt_check_none, Opt_check_normal, Opt_check_strict,
|
||||
Opt_err_cont, Opt_err_ro, Opt_err_panic,
|
||||
Opt_eas_no, Opt_eas_ro, Opt_eas_rw,
|
||||
@ -233,9 +236,6 @@ static const match_table_t tokens = {
|
||||
{Opt_umask, "umask=%o"},
|
||||
{Opt_case_lower, "case=lower"},
|
||||
{Opt_case_asis, "case=asis"},
|
||||
{Opt_conv_binary, "conv=binary"},
|
||||
{Opt_conv_text, "conv=text"},
|
||||
{Opt_conv_auto, "conv=auto"},
|
||||
{Opt_check_none, "check=none"},
|
||||
{Opt_check_normal, "check=normal"},
|
||||
{Opt_check_strict, "check=strict"},
|
||||
@ -253,7 +253,7 @@ static const match_table_t tokens = {
|
||||
};
|
||||
|
||||
static int parse_opts(char *opts, uid_t *uid, gid_t *gid, umode_t *umask,
|
||||
int *lowercase, int *conv, int *eas, int *chk, int *errs,
|
||||
int *lowercase, int *eas, int *chk, int *errs,
|
||||
int *chkdsk, int *timeshift)
|
||||
{
|
||||
char *p;
|
||||
@ -295,15 +295,6 @@ static int parse_opts(char *opts, uid_t *uid, gid_t *gid, umode_t *umask,
|
||||
case Opt_case_asis:
|
||||
*lowercase = 0;
|
||||
break;
|
||||
case Opt_conv_binary:
|
||||
*conv = CONV_BINARY;
|
||||
break;
|
||||
case Opt_conv_text:
|
||||
*conv = CONV_TEXT;
|
||||
break;
|
||||
case Opt_conv_auto:
|
||||
*conv = CONV_AUTO;
|
||||
break;
|
||||
case Opt_check_none:
|
||||
*chk = 0;
|
||||
break;
|
||||
@ -370,9 +361,6 @@ HPFS filesystem options:\n\
|
||||
umask=xxx set mode of files that don't have mode specified in eas\n\
|
||||
case=lower lowercase all files\n\
|
||||
case=asis do not lowercase files (default)\n\
|
||||
conv=binary do not convert CR/LF -> LF (default)\n\
|
||||
conv=auto convert only files with known text extensions\n\
|
||||
conv=text convert all files\n\
|
||||
check=none no fs checks - kernel may crash on corrupted filesystem\n\
|
||||
check=normal do some checks - it should not crash (default)\n\
|
||||
check=strict do extra time-consuming checks, used for debugging\n\
|
||||
@ -394,7 +382,7 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
umode_t umask;
|
||||
int lowercase, conv, eas, chk, errs, chkdsk, timeshift;
|
||||
int lowercase, eas, chk, errs, chkdsk, timeshift;
|
||||
int o;
|
||||
struct hpfs_sb_info *sbi = hpfs_sb(s);
|
||||
char *new_opts = kstrdup(data, GFP_KERNEL);
|
||||
@ -405,11 +393,11 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
|
||||
lock_super(s);
|
||||
uid = sbi->sb_uid; gid = sbi->sb_gid;
|
||||
umask = 0777 & ~sbi->sb_mode;
|
||||
lowercase = sbi->sb_lowercase; conv = sbi->sb_conv;
|
||||
lowercase = sbi->sb_lowercase;
|
||||
eas = sbi->sb_eas; chk = sbi->sb_chk; chkdsk = sbi->sb_chkdsk;
|
||||
errs = sbi->sb_err; timeshift = sbi->sb_timeshift;
|
||||
|
||||
if (!(o = parse_opts(data, &uid, &gid, &umask, &lowercase, &conv,
|
||||
if (!(o = parse_opts(data, &uid, &gid, &umask, &lowercase,
|
||||
&eas, &chk, &errs, &chkdsk, ×hift))) {
|
||||
printk("HPFS: bad mount options.\n");
|
||||
goto out_err;
|
||||
@ -427,11 +415,11 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
|
||||
|
||||
sbi->sb_uid = uid; sbi->sb_gid = gid;
|
||||
sbi->sb_mode = 0777 & ~umask;
|
||||
sbi->sb_lowercase = lowercase; sbi->sb_conv = conv;
|
||||
sbi->sb_lowercase = lowercase;
|
||||
sbi->sb_eas = eas; sbi->sb_chk = chk; sbi->sb_chkdsk = chkdsk;
|
||||
sbi->sb_err = errs; sbi->sb_timeshift = timeshift;
|
||||
|
||||
if (!(*flags & MS_RDONLY)) mark_dirty(s);
|
||||
if (!(*flags & MS_RDONLY)) mark_dirty(s, 1);
|
||||
|
||||
replace_mount_options(s, new_opts);
|
||||
|
||||
@ -471,7 +459,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
umode_t umask;
|
||||
int lowercase, conv, eas, chk, errs, chkdsk, timeshift;
|
||||
int lowercase, eas, chk, errs, chkdsk, timeshift;
|
||||
|
||||
dnode_secno root_dno;
|
||||
struct hpfs_dirent *de = NULL;
|
||||
@ -479,11 +467,6 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
|
||||
|
||||
int o;
|
||||
|
||||
if (num_possible_cpus() > 1) {
|
||||
printk(KERN_ERR "HPFS is not SMP safe\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
save_mount_options(s, options);
|
||||
|
||||
sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
|
||||
@ -495,20 +478,20 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
|
||||
sbi->sb_bmp_dir = NULL;
|
||||
sbi->sb_cp_table = NULL;
|
||||
|
||||
mutex_init(&sbi->hpfs_creation_de);
|
||||
mutex_init(&sbi->hpfs_mutex);
|
||||
hpfs_lock(s);
|
||||
|
||||
uid = current_uid();
|
||||
gid = current_gid();
|
||||
umask = current_umask();
|
||||
lowercase = 0;
|
||||
conv = CONV_BINARY;
|
||||
eas = 2;
|
||||
chk = 1;
|
||||
errs = 1;
|
||||
chkdsk = 1;
|
||||
timeshift = 0;
|
||||
|
||||
if (!(o = parse_opts(options, &uid, &gid, &umask, &lowercase, &conv,
|
||||
if (!(o = parse_opts(options, &uid, &gid, &umask, &lowercase,
|
||||
&eas, &chk, &errs, &chkdsk, ×hift))) {
|
||||
printk("HPFS: bad mount options.\n");
|
||||
goto bail0;
|
||||
@ -526,9 +509,9 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
|
||||
if (!(spareblock = hpfs_map_sector(s, 17, &bh2, 0))) goto bail3;
|
||||
|
||||
/* Check magics */
|
||||
if (/*bootblock->magic != BB_MAGIC
|
||||
||*/ superblock->magic != SB_MAGIC
|
||||
|| spareblock->magic != SP_MAGIC) {
|
||||
if (/*le16_to_cpu(bootblock->magic) != BB_MAGIC
|
||||
||*/ le32_to_cpu(superblock->magic) != SB_MAGIC
|
||||
|| le32_to_cpu(spareblock->magic) != SP_MAGIC) {
|
||||
if (!silent) printk("HPFS: Bad magic ... probably not HPFS\n");
|
||||
goto bail4;
|
||||
}
|
||||
@ -549,19 +532,18 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
|
||||
s->s_op = &hpfs_sops;
|
||||
s->s_d_op = &hpfs_dentry_operations;
|
||||
|
||||
sbi->sb_root = superblock->root;
|
||||
sbi->sb_fs_size = superblock->n_sectors;
|
||||
sbi->sb_bitmaps = superblock->bitmaps;
|
||||
sbi->sb_dirband_start = superblock->dir_band_start;
|
||||
sbi->sb_dirband_size = superblock->n_dir_band;
|
||||
sbi->sb_dmap = superblock->dir_band_bitmap;
|
||||
sbi->sb_root = le32_to_cpu(superblock->root);
|
||||
sbi->sb_fs_size = le32_to_cpu(superblock->n_sectors);
|
||||
sbi->sb_bitmaps = le32_to_cpu(superblock->bitmaps);
|
||||
sbi->sb_dirband_start = le32_to_cpu(superblock->dir_band_start);
|
||||
sbi->sb_dirband_size = le32_to_cpu(superblock->n_dir_band);
|
||||
sbi->sb_dmap = le32_to_cpu(superblock->dir_band_bitmap);
|
||||
sbi->sb_uid = uid;
|
||||
sbi->sb_gid = gid;
|
||||
sbi->sb_mode = 0777 & ~umask;
|
||||
sbi->sb_n_free = -1;
|
||||
sbi->sb_n_free_dnodes = -1;
|
||||
sbi->sb_lowercase = lowercase;
|
||||
sbi->sb_conv = conv;
|
||||
sbi->sb_eas = eas;
|
||||
sbi->sb_chk = chk;
|
||||
sbi->sb_chkdsk = chkdsk;
|
||||
@ -573,7 +555,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
|
||||
sbi->sb_max_fwd_alloc = 0xffffff;
|
||||
|
||||
/* Load bitmap directory */
|
||||
if (!(sbi->sb_bmp_dir = hpfs_load_bitmap_directory(s, superblock->bitmaps)))
|
||||
if (!(sbi->sb_bmp_dir = hpfs_load_bitmap_directory(s, le32_to_cpu(superblock->bitmaps))))
|
||||
goto bail4;
|
||||
|
||||
/* Check for general fs errors*/
|
||||
@ -591,20 +573,20 @@ 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 (le32_to_cpu(spareblock->hotfixes_used) || le32_to_cpu(spareblock->n_spares_used)) {
|
||||
if (errs >= 2) {
|
||||
printk("HPFS: Hotfixes not supported here, try chkdsk\n");
|
||||
mark_dirty(s);
|
||||
mark_dirty(s, 0);
|
||||
goto bail4;
|
||||
}
|
||||
hpfs_error(s, "hotfixes not supported here, try chkdsk");
|
||||
if (errs == 0) printk("HPFS: Proceeding, but your filesystem will be probably corrupted by this driver...\n");
|
||||
else printk("HPFS: This driver may read bad files or crash when operating on disk with hotfixes.\n");
|
||||
}
|
||||
if (spareblock->n_dnode_spares != spareblock->n_dnode_spares_free) {
|
||||
if (le32_to_cpu(spareblock->n_dnode_spares) != le32_to_cpu(spareblock->n_dnode_spares_free)) {
|
||||
if (errs >= 2) {
|
||||
printk("HPFS: Spare dnodes used, try chkdsk\n");
|
||||
mark_dirty(s);
|
||||
mark_dirty(s, 0);
|
||||
goto bail4;
|
||||
}
|
||||
hpfs_error(s, "warning: spare dnodes used, try chkdsk");
|
||||
@ -612,26 +594,26 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
|
||||
}
|
||||
if (chk) {
|
||||
unsigned a;
|
||||
if (superblock->dir_band_end - superblock->dir_band_start + 1 != superblock->n_dir_band ||
|
||||
superblock->dir_band_end < superblock->dir_band_start || superblock->n_dir_band > 0x4000) {
|
||||
if (le32_to_cpu(superblock->dir_band_end) - le32_to_cpu(superblock->dir_band_start) + 1 != le32_to_cpu(superblock->n_dir_band) ||
|
||||
le32_to_cpu(superblock->dir_band_end) < le32_to_cpu(superblock->dir_band_start) || le32_to_cpu(superblock->n_dir_band) > 0x4000) {
|
||||
hpfs_error(s, "dir band size mismatch: dir_band_start==%08x, dir_band_end==%08x, n_dir_band==%08x",
|
||||
superblock->dir_band_start, superblock->dir_band_end, superblock->n_dir_band);
|
||||
le32_to_cpu(superblock->dir_band_start), le32_to_cpu(superblock->dir_band_end), le32_to_cpu(superblock->n_dir_band));
|
||||
goto bail4;
|
||||
}
|
||||
a = sbi->sb_dirband_size;
|
||||
sbi->sb_dirband_size = 0;
|
||||
if (hpfs_chk_sectors(s, superblock->dir_band_start, superblock->n_dir_band, "dir_band") ||
|
||||
hpfs_chk_sectors(s, superblock->dir_band_bitmap, 4, "dir_band_bitmap") ||
|
||||
hpfs_chk_sectors(s, superblock->bitmaps, 4, "bitmaps")) {
|
||||
mark_dirty(s);
|
||||
if (hpfs_chk_sectors(s, le32_to_cpu(superblock->dir_band_start), le32_to_cpu(superblock->n_dir_band), "dir_band") ||
|
||||
hpfs_chk_sectors(s, le32_to_cpu(superblock->dir_band_bitmap), 4, "dir_band_bitmap") ||
|
||||
hpfs_chk_sectors(s, le32_to_cpu(superblock->bitmaps), 4, "bitmaps")) {
|
||||
mark_dirty(s, 0);
|
||||
goto bail4;
|
||||
}
|
||||
sbi->sb_dirband_size = a;
|
||||
} else printk("HPFS: You really don't want any checks? You are crazy...\n");
|
||||
|
||||
/* Load code page table */
|
||||
if (spareblock->n_code_pages)
|
||||
if (!(sbi->sb_cp_table = hpfs_load_code_page(s, spareblock->code_page_dir)))
|
||||
if (le32_to_cpu(spareblock->n_code_pages))
|
||||
if (!(sbi->sb_cp_table = hpfs_load_code_page(s, le32_to_cpu(spareblock->code_page_dir))))
|
||||
printk("HPFS: Warning: code page support is disabled\n");
|
||||
|
||||
brelse(bh2);
|
||||
@ -660,13 +642,13 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
|
||||
if (!de)
|
||||
hpfs_error(s, "unable to find root dir");
|
||||
else {
|
||||
root->i_atime.tv_sec = local_to_gmt(s, de->read_date);
|
||||
root->i_atime.tv_sec = local_to_gmt(s, le32_to_cpu(de->read_date));
|
||||
root->i_atime.tv_nsec = 0;
|
||||
root->i_mtime.tv_sec = local_to_gmt(s, de->write_date);
|
||||
root->i_mtime.tv_sec = local_to_gmt(s, le32_to_cpu(de->write_date));
|
||||
root->i_mtime.tv_nsec = 0;
|
||||
root->i_ctime.tv_sec = local_to_gmt(s, de->creation_date);
|
||||
root->i_ctime.tv_sec = local_to_gmt(s, le32_to_cpu(de->creation_date));
|
||||
root->i_ctime.tv_nsec = 0;
|
||||
hpfs_i(root)->i_ea_size = de->ea_size;
|
||||
hpfs_i(root)->i_ea_size = le16_to_cpu(de->ea_size);
|
||||
hpfs_i(root)->i_parent_dir = root->i_ino;
|
||||
if (root->i_size == -1)
|
||||
root->i_size = 2048;
|
||||
@ -674,6 +656,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
|
||||
root->i_blocks = 5;
|
||||
hpfs_brelse4(&qbh);
|
||||
}
|
||||
hpfs_unlock(s);
|
||||
return 0;
|
||||
|
||||
bail4: brelse(bh2);
|
||||
@ -681,6 +664,7 @@ bail3: brelse(bh1);
|
||||
bail2: brelse(bh0);
|
||||
bail1:
|
||||
bail0:
|
||||
hpfs_unlock(s);
|
||||
kfree(sbi->sb_bmp_dir);
|
||||
kfree(sbi->sb_cp_table);
|
||||
s->s_fs_info = NULL;
|
||||
|
Loading…
x
Reference in New Issue
Block a user