forked from Minki/linux
Merge git://git.infradead.org/mtd-2.6
* git://git.infradead.org/mtd-2.6: [MTD][NOR] Add physical address to point() method [JFFS2] Track parent inode for directories (for NFS export) [JFFS2] Invert last argument of jffs2_gc_fetch_inode(), make it boolean. [JFFS2] Quiet lockdep false positive. [JFFS2] Clean up jffs2_alloc_inode() and jffs2_i_init_once() [MTD] Delete long-unused jedec.h header file. [MTD] [NAND] at91_nand: use at91_nand_{en,dis}able consistently.
This commit is contained in:
commit
2c4aabcca8
@ -82,9 +82,8 @@ static struct mtd_info *cfi_intelext_setup (struct mtd_info *);
|
|||||||
static int cfi_intelext_partition_fixup(struct mtd_info *, struct cfi_private **);
|
static int cfi_intelext_partition_fixup(struct mtd_info *, struct cfi_private **);
|
||||||
|
|
||||||
static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len,
|
static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
size_t *retlen, u_char **mtdbuf);
|
size_t *retlen, void **virt, resource_size_t *phys);
|
||||||
static void cfi_intelext_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from,
|
static void cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len);
|
||||||
size_t len);
|
|
||||||
|
|
||||||
static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long adr, int mode);
|
static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long adr, int mode);
|
||||||
static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode);
|
static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode);
|
||||||
@ -1240,7 +1239,8 @@ static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t a
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf)
|
static int cfi_intelext_point(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
|
size_t *retlen, void **virt, resource_size_t *phys)
|
||||||
{
|
{
|
||||||
struct map_info *map = mtd->priv;
|
struct map_info *map = mtd->priv;
|
||||||
struct cfi_private *cfi = map->fldrv_priv;
|
struct cfi_private *cfi = map->fldrv_priv;
|
||||||
@ -1257,8 +1257,10 @@ static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, si
|
|||||||
chipnum = (from >> cfi->chipshift);
|
chipnum = (from >> cfi->chipshift);
|
||||||
ofs = from - (chipnum << cfi->chipshift);
|
ofs = from - (chipnum << cfi->chipshift);
|
||||||
|
|
||||||
*mtdbuf = (void *)map->virt + cfi->chips[chipnum].start + ofs;
|
*virt = map->virt + cfi->chips[chipnum].start + ofs;
|
||||||
*retlen = 0;
|
*retlen = 0;
|
||||||
|
if (phys)
|
||||||
|
*phys = map->phys + cfi->chips[chipnum].start + ofs;
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
unsigned long thislen;
|
unsigned long thislen;
|
||||||
@ -1291,7 +1293,7 @@ static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, si
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cfi_intelext_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len)
|
static void cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
|
||||||
{
|
{
|
||||||
struct map_info *map = mtd->priv;
|
struct map_info *map = mtd->priv;
|
||||||
struct cfi_private *cfi = map->fldrv_priv;
|
struct cfi_private *cfi = map->fldrv_priv;
|
||||||
|
@ -48,18 +48,21 @@ static int ram_erase(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int ram_point(struct mtd_info *mtd, loff_t from, size_t len,
|
static int ram_point(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
size_t *retlen, u_char **mtdbuf)
|
size_t *retlen, void **virt, resource_size_t *phys)
|
||||||
{
|
{
|
||||||
if (from + len > mtd->size)
|
if (from + len > mtd->size)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
*mtdbuf = mtd->priv + from;
|
/* can we return a physical address with this driver? */
|
||||||
|
if (phys)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
*virt = mtd->priv + from;
|
||||||
*retlen = len;
|
*retlen = len;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ram_unpoint(struct mtd_info *mtd, u_char * addr, loff_t from,
|
static void ram_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
|
||||||
size_t len)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,20 +57,21 @@ static int phram_erase(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int phram_point(struct mtd_info *mtd, loff_t from, size_t len,
|
static int phram_point(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
size_t *retlen, u_char **mtdbuf)
|
size_t *retlen, void **virt, resource_size_t *phys)
|
||||||
{
|
{
|
||||||
u_char *start = mtd->priv;
|
|
||||||
|
|
||||||
if (from + len > mtd->size)
|
if (from + len > mtd->size)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
*mtdbuf = start + from;
|
/* can we return a physical address with this driver? */
|
||||||
|
if (phys)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
*virt = mtd->priv + from;
|
||||||
*retlen = len;
|
*retlen = len;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void phram_unpoint(struct mtd_info *mtd, u_char *addr, loff_t from,
|
static void phram_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
|
||||||
size_t len)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +134,8 @@ static int pmc551_erase(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
eoff_lo = end & (priv->asize - 1);
|
eoff_lo = end & (priv->asize - 1);
|
||||||
soff_lo = instr->addr & (priv->asize - 1);
|
soff_lo = instr->addr & (priv->asize - 1);
|
||||||
|
|
||||||
pmc551_point(mtd, instr->addr, instr->len, &retlen, &ptr);
|
pmc551_point(mtd, instr->addr, instr->len, &retlen,
|
||||||
|
(void **)&ptr, NULL);
|
||||||
|
|
||||||
if (soff_hi == eoff_hi || mtd->size == priv->asize) {
|
if (soff_hi == eoff_hi || mtd->size == priv->asize) {
|
||||||
/* The whole thing fits within one access, so just one shot
|
/* The whole thing fits within one access, so just one shot
|
||||||
@ -154,7 +155,8 @@ static int pmc551_erase(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
}
|
}
|
||||||
soff_hi += priv->asize;
|
soff_hi += priv->asize;
|
||||||
pmc551_point(mtd, (priv->base_map0 | soff_hi),
|
pmc551_point(mtd, (priv->base_map0 | soff_hi),
|
||||||
priv->asize, &retlen, &ptr);
|
priv->asize, &retlen,
|
||||||
|
(void **)&ptr, NULL);
|
||||||
}
|
}
|
||||||
memset(ptr, 0xff, eoff_lo);
|
memset(ptr, 0xff, eoff_lo);
|
||||||
}
|
}
|
||||||
@ -170,7 +172,7 @@ static int pmc551_erase(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
|
static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
size_t * retlen, u_char ** mtdbuf)
|
size_t *retlen, void **virt, resource_size_t *phys)
|
||||||
{
|
{
|
||||||
struct mypriv *priv = mtd->priv;
|
struct mypriv *priv = mtd->priv;
|
||||||
u32 soff_hi;
|
u32 soff_hi;
|
||||||
@ -188,6 +190,10 @@ static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* can we return a physical address with this driver? */
|
||||||
|
if (phys)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
soff_hi = from & ~(priv->asize - 1);
|
soff_hi = from & ~(priv->asize - 1);
|
||||||
soff_lo = from & (priv->asize - 1);
|
soff_lo = from & (priv->asize - 1);
|
||||||
|
|
||||||
@ -198,13 +204,12 @@ static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
|
|||||||
priv->curr_map0 = soff_hi;
|
priv->curr_map0 = soff_hi;
|
||||||
}
|
}
|
||||||
|
|
||||||
*mtdbuf = priv->start + soff_lo;
|
*virt = priv->start + soff_lo;
|
||||||
*retlen = len;
|
*retlen = len;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pmc551_unpoint(struct mtd_info *mtd, u_char * addr, loff_t from,
|
static void pmc551_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
|
||||||
size_t len)
|
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_MTD_PMC551_DEBUG
|
#ifdef CONFIG_MTD_PMC551_DEBUG
|
||||||
printk(KERN_DEBUG "pmc551_unpoint()\n");
|
printk(KERN_DEBUG "pmc551_unpoint()\n");
|
||||||
@ -242,7 +247,7 @@ static int pmc551_read(struct mtd_info *mtd, loff_t from, size_t len,
|
|||||||
soff_lo = from & (priv->asize - 1);
|
soff_lo = from & (priv->asize - 1);
|
||||||
eoff_lo = end & (priv->asize - 1);
|
eoff_lo = end & (priv->asize - 1);
|
||||||
|
|
||||||
pmc551_point(mtd, from, len, retlen, &ptr);
|
pmc551_point(mtd, from, len, retlen, (void **)&ptr, NULL);
|
||||||
|
|
||||||
if (soff_hi == eoff_hi) {
|
if (soff_hi == eoff_hi) {
|
||||||
/* The whole thing fits within one access, so just one shot
|
/* The whole thing fits within one access, so just one shot
|
||||||
@ -263,7 +268,8 @@ static int pmc551_read(struct mtd_info *mtd, loff_t from, size_t len,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
soff_hi += priv->asize;
|
soff_hi += priv->asize;
|
||||||
pmc551_point(mtd, soff_hi, priv->asize, retlen, &ptr);
|
pmc551_point(mtd, soff_hi, priv->asize, retlen,
|
||||||
|
(void **)&ptr, NULL);
|
||||||
}
|
}
|
||||||
memcpy(copyto, ptr, eoff_lo);
|
memcpy(copyto, ptr, eoff_lo);
|
||||||
copyto += eoff_lo;
|
copyto += eoff_lo;
|
||||||
@ -308,7 +314,7 @@ static int pmc551_write(struct mtd_info *mtd, loff_t to, size_t len,
|
|||||||
soff_lo = to & (priv->asize - 1);
|
soff_lo = to & (priv->asize - 1);
|
||||||
eoff_lo = end & (priv->asize - 1);
|
eoff_lo = end & (priv->asize - 1);
|
||||||
|
|
||||||
pmc551_point(mtd, to, len, retlen, &ptr);
|
pmc551_point(mtd, to, len, retlen, (void **)&ptr, NULL);
|
||||||
|
|
||||||
if (soff_hi == eoff_hi) {
|
if (soff_hi == eoff_hi) {
|
||||||
/* The whole thing fits within one access, so just one shot
|
/* The whole thing fits within one access, so just one shot
|
||||||
@ -329,7 +335,8 @@ static int pmc551_write(struct mtd_info *mtd, loff_t to, size_t len,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
soff_hi += priv->asize;
|
soff_hi += priv->asize;
|
||||||
pmc551_point(mtd, soff_hi, priv->asize, retlen, &ptr);
|
pmc551_point(mtd, soff_hi, priv->asize, retlen,
|
||||||
|
(void **)&ptr, NULL);
|
||||||
}
|
}
|
||||||
memcpy(ptr, copyfrom, eoff_lo);
|
memcpy(ptr, copyfrom, eoff_lo);
|
||||||
copyfrom += eoff_lo;
|
copyfrom += eoff_lo;
|
||||||
|
@ -76,8 +76,9 @@ static char *map;
|
|||||||
static slram_mtd_list_t *slram_mtdlist = NULL;
|
static slram_mtd_list_t *slram_mtdlist = NULL;
|
||||||
|
|
||||||
static int slram_erase(struct mtd_info *, struct erase_info *);
|
static int slram_erase(struct mtd_info *, struct erase_info *);
|
||||||
static int slram_point(struct mtd_info *, loff_t, size_t, size_t *, u_char **);
|
static int slram_point(struct mtd_info *, loff_t, size_t, size_t *, void **,
|
||||||
static void slram_unpoint(struct mtd_info *, u_char *, loff_t, size_t);
|
resource_size_t *);
|
||||||
|
static void slram_unpoint(struct mtd_info *, loff_t, size_t);
|
||||||
static int slram_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *);
|
static int slram_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *);
|
||||||
static int slram_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
|
static int slram_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
|
||||||
|
|
||||||
@ -104,19 +105,23 @@ static int slram_erase(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int slram_point(struct mtd_info *mtd, loff_t from, size_t len,
|
static int slram_point(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
size_t *retlen, u_char **mtdbuf)
|
size_t *retlen, void **virt, resource_size_t *phys)
|
||||||
{
|
{
|
||||||
slram_priv_t *priv = mtd->priv;
|
slram_priv_t *priv = mtd->priv;
|
||||||
|
|
||||||
|
/* can we return a physical address with this driver? */
|
||||||
|
if (phys)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
if (from + len > mtd->size)
|
if (from + len > mtd->size)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
*mtdbuf = priv->start + from;
|
*virt = priv->start + from;
|
||||||
*retlen = len;
|
*retlen = len;
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void slram_unpoint(struct mtd_info *mtd, u_char *addr, loff_t from, size_t len)
|
static void slram_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,10 +40,12 @@ struct mtd_partition uclinux_romfs[] = {
|
|||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
int uclinux_point(struct mtd_info *mtd, loff_t from, size_t len,
|
int uclinux_point(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
size_t *retlen, u_char **mtdbuf)
|
size_t *retlen, void **virt, resource_size_t *phys)
|
||||||
{
|
{
|
||||||
struct map_info *map = mtd->priv;
|
struct map_info *map = mtd->priv;
|
||||||
*mtdbuf = (u_char *) (map->virt + ((int) from));
|
*virt = map->virt + from;
|
||||||
|
if (phys)
|
||||||
|
*phys = map->phys + from;
|
||||||
*retlen = len;
|
*retlen = len;
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ static int part_read (struct mtd_info *mtd, loff_t from, size_t len,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int part_point (struct mtd_info *mtd, loff_t from, size_t len,
|
static int part_point (struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
size_t *retlen, u_char **buf)
|
size_t *retlen, void **virt, resource_size_t *phys)
|
||||||
{
|
{
|
||||||
struct mtd_part *part = PART(mtd);
|
struct mtd_part *part = PART(mtd);
|
||||||
if (from >= mtd->size)
|
if (from >= mtd->size)
|
||||||
@ -76,14 +76,14 @@ static int part_point (struct mtd_info *mtd, loff_t from, size_t len,
|
|||||||
else if (from + len > mtd->size)
|
else if (from + len > mtd->size)
|
||||||
len = mtd->size - from;
|
len = mtd->size - from;
|
||||||
return part->master->point (part->master, from + part->offset,
|
return part->master->point (part->master, from + part->offset,
|
||||||
len, retlen, buf);
|
len, retlen, virt, phys);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void part_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len)
|
static void part_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
|
||||||
{
|
{
|
||||||
struct mtd_part *part = PART(mtd);
|
struct mtd_part *part = PART(mtd);
|
||||||
|
|
||||||
part->master->unpoint (part->master, addr, from + part->offset, len);
|
part->master->unpoint(part->master, from + part->offset, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int part_read_oob(struct mtd_info *mtd, loff_t from,
|
static int part_read_oob(struct mtd_info *mtd, loff_t from,
|
||||||
|
@ -93,6 +93,24 @@ struct at91_nand_host {
|
|||||||
void __iomem *ecc;
|
void __iomem *ecc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable NAND.
|
||||||
|
*/
|
||||||
|
static void at91_nand_enable(struct at91_nand_host *host)
|
||||||
|
{
|
||||||
|
if (host->board->enable_pin)
|
||||||
|
at91_set_gpio_value(host->board->enable_pin, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disable NAND.
|
||||||
|
*/
|
||||||
|
static void at91_nand_disable(struct at91_nand_host *host)
|
||||||
|
{
|
||||||
|
if (host->board->enable_pin)
|
||||||
|
at91_set_gpio_value(host->board->enable_pin, 1);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Hardware specific access to control-lines
|
* Hardware specific access to control-lines
|
||||||
*/
|
*/
|
||||||
@ -101,11 +119,11 @@ static void at91_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
|||||||
struct nand_chip *nand_chip = mtd->priv;
|
struct nand_chip *nand_chip = mtd->priv;
|
||||||
struct at91_nand_host *host = nand_chip->priv;
|
struct at91_nand_host *host = nand_chip->priv;
|
||||||
|
|
||||||
if (host->board->enable_pin && (ctrl & NAND_CTRL_CHANGE)) {
|
if (ctrl & NAND_CTRL_CHANGE) {
|
||||||
if (ctrl & NAND_NCE)
|
if (ctrl & NAND_NCE)
|
||||||
at91_set_gpio_value(host->board->enable_pin, 0);
|
at91_nand_enable(host);
|
||||||
else
|
else
|
||||||
at91_set_gpio_value(host->board->enable_pin, 1);
|
at91_nand_disable(host);
|
||||||
}
|
}
|
||||||
if (cmd == NAND_CMD_NONE)
|
if (cmd == NAND_CMD_NONE)
|
||||||
return;
|
return;
|
||||||
@ -127,24 +145,6 @@ static int at91_nand_device_ready(struct mtd_info *mtd)
|
|||||||
return at91_get_gpio_value(host->board->rdy_pin);
|
return at91_get_gpio_value(host->board->rdy_pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Enable NAND.
|
|
||||||
*/
|
|
||||||
static void at91_nand_enable(struct at91_nand_host *host)
|
|
||||||
{
|
|
||||||
if (host->board->enable_pin)
|
|
||||||
at91_set_gpio_value(host->board->enable_pin, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Disable NAND.
|
|
||||||
*/
|
|
||||||
static void at91_nand_disable(struct at91_nand_host *host)
|
|
||||||
{
|
|
||||||
if (host->board->enable_pin)
|
|
||||||
at91_set_gpio_value(host->board->enable_pin, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* write oob for small pages
|
* write oob for small pages
|
||||||
*/
|
*/
|
||||||
|
@ -46,7 +46,7 @@ next_inode(int *i, struct jffs2_inode_cache *ic, struct jffs2_sb_info *c)
|
|||||||
|
|
||||||
|
|
||||||
static void jffs2_build_inode_pass1(struct jffs2_sb_info *c,
|
static void jffs2_build_inode_pass1(struct jffs2_sb_info *c,
|
||||||
struct jffs2_inode_cache *ic)
|
struct jffs2_inode_cache *ic)
|
||||||
{
|
{
|
||||||
struct jffs2_full_dirent *fd;
|
struct jffs2_full_dirent *fd;
|
||||||
|
|
||||||
@ -68,11 +68,17 @@ static void jffs2_build_inode_pass1(struct jffs2_sb_info *c,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (child_ic->nlink++ && fd->type == DT_DIR) {
|
if (fd->type == DT_DIR) {
|
||||||
JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n",
|
if (child_ic->pino_nlink) {
|
||||||
fd->name, fd->ino, ic->ino);
|
JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n",
|
||||||
/* TODO: What do we do about it? */
|
fd->name, fd->ino, ic->ino);
|
||||||
}
|
/* TODO: What do we do about it? */
|
||||||
|
} else {
|
||||||
|
child_ic->pino_nlink = ic->ino;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
child_ic->pino_nlink++;
|
||||||
|
|
||||||
dbg_fsbuild("increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino);
|
dbg_fsbuild("increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino);
|
||||||
/* Can't free scan_dents so far. We might need them in pass 2 */
|
/* Can't free scan_dents so far. We might need them in pass 2 */
|
||||||
}
|
}
|
||||||
@ -125,7 +131,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c)
|
|||||||
dbg_fsbuild("pass 2 starting\n");
|
dbg_fsbuild("pass 2 starting\n");
|
||||||
|
|
||||||
for_each_inode(i, c, ic) {
|
for_each_inode(i, c, ic) {
|
||||||
if (ic->nlink)
|
if (ic->pino_nlink)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
jffs2_build_remove_unlinked_inode(c, ic, &dead_fds);
|
jffs2_build_remove_unlinked_inode(c, ic, &dead_fds);
|
||||||
@ -232,16 +238,19 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c,
|
|||||||
/* Reduce nlink of the child. If it's now zero, stick it on the
|
/* Reduce nlink of the child. If it's now zero, stick it on the
|
||||||
dead_fds list to be cleaned up later. Else just free the fd */
|
dead_fds list to be cleaned up later. Else just free the fd */
|
||||||
|
|
||||||
child_ic->nlink--;
|
if (fd->type == DT_DIR)
|
||||||
|
child_ic->pino_nlink = 0;
|
||||||
|
else
|
||||||
|
child_ic->pino_nlink--;
|
||||||
|
|
||||||
if (!child_ic->nlink) {
|
if (!child_ic->pino_nlink) {
|
||||||
dbg_fsbuild("inode #%u (\"%s\") has now got zero nlink, adding to dead_fds list.\n",
|
dbg_fsbuild("inode #%u (\"%s\") now has no links; adding to dead_fds list.\n",
|
||||||
fd->ino, fd->name);
|
fd->ino, fd->name);
|
||||||
fd->next = *dead_fds;
|
fd->next = *dead_fds;
|
||||||
*dead_fds = fd;
|
*dead_fds = fd;
|
||||||
} else {
|
} else {
|
||||||
dbg_fsbuild("inode #%u (\"%s\") has now got nlink %d. Ignoring.\n",
|
dbg_fsbuild("inode #%u (\"%s\") has now got nlink %d. Ignoring.\n",
|
||||||
fd->ino, fd->name, child_ic->nlink);
|
fd->ino, fd->name, child_ic->pino_nlink);
|
||||||
jffs2_free_full_dirent(fd);
|
jffs2_free_full_dirent(fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -208,6 +208,13 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
|
|||||||
f = JFFS2_INODE_INFO(inode);
|
f = JFFS2_INODE_INFO(inode);
|
||||||
dir_f = JFFS2_INODE_INFO(dir_i);
|
dir_f = JFFS2_INODE_INFO(dir_i);
|
||||||
|
|
||||||
|
/* jffs2_do_create() will want to lock it, _after_ reserving
|
||||||
|
space and taking c-alloc_sem. If we keep it locked here,
|
||||||
|
lockdep gets unhappy (although it's a false positive;
|
||||||
|
nothing else will be looking at this inode yet so there's
|
||||||
|
no chance of AB-BA deadlock involving its f->sem). */
|
||||||
|
mutex_unlock(&f->sem);
|
||||||
|
|
||||||
ret = jffs2_do_create(c, dir_f, f, ri,
|
ret = jffs2_do_create(c, dir_f, f, ri,
|
||||||
dentry->d_name.name, dentry->d_name.len);
|
dentry->d_name.name, dentry->d_name.len);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -219,7 +226,8 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
|
|||||||
d_instantiate(dentry, inode);
|
d_instantiate(dentry, inode);
|
||||||
|
|
||||||
D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld\n",
|
D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld\n",
|
||||||
inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink, inode->i_mapping->nrpages));
|
inode->i_ino, inode->i_mode, inode->i_nlink,
|
||||||
|
f->inocache->pino_nlink, inode->i_mapping->nrpages));
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
@ -243,7 +251,7 @@ static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry)
|
|||||||
ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name,
|
ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name,
|
||||||
dentry->d_name.len, dead_f, now);
|
dentry->d_name.len, dead_f, now);
|
||||||
if (dead_f->inocache)
|
if (dead_f->inocache)
|
||||||
dentry->d_inode->i_nlink = dead_f->inocache->nlink;
|
dentry->d_inode->i_nlink = dead_f->inocache->pino_nlink;
|
||||||
if (!ret)
|
if (!ret)
|
||||||
dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
|
dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
|
||||||
return ret;
|
return ret;
|
||||||
@ -276,7 +284,7 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de
|
|||||||
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
mutex_lock(&f->sem);
|
mutex_lock(&f->sem);
|
||||||
old_dentry->d_inode->i_nlink = ++f->inocache->nlink;
|
old_dentry->d_inode->i_nlink = ++f->inocache->pino_nlink;
|
||||||
mutex_unlock(&f->sem);
|
mutex_unlock(&f->sem);
|
||||||
d_instantiate(dentry, old_dentry->d_inode);
|
d_instantiate(dentry, old_dentry->d_inode);
|
||||||
dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
|
dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
|
||||||
@ -493,11 +501,14 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
|
|||||||
|
|
||||||
inode->i_op = &jffs2_dir_inode_operations;
|
inode->i_op = &jffs2_dir_inode_operations;
|
||||||
inode->i_fop = &jffs2_dir_operations;
|
inode->i_fop = &jffs2_dir_operations;
|
||||||
/* Directories get nlink 2 at start */
|
|
||||||
inode->i_nlink = 2;
|
|
||||||
|
|
||||||
f = JFFS2_INODE_INFO(inode);
|
f = JFFS2_INODE_INFO(inode);
|
||||||
|
|
||||||
|
/* Directories get nlink 2 at start */
|
||||||
|
inode->i_nlink = 2;
|
||||||
|
/* but ic->pino_nlink is the parent ino# */
|
||||||
|
f->inocache->pino_nlink = dir_i->i_ino;
|
||||||
|
|
||||||
ri->data_crc = cpu_to_je32(0);
|
ri->data_crc = cpu_to_je32(0);
|
||||||
ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
|
ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
|
||||||
|
|
||||||
@ -594,17 +605,25 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
|
|||||||
|
|
||||||
static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry)
|
static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry)
|
||||||
{
|
{
|
||||||
|
struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb);
|
||||||
|
struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
|
||||||
struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode);
|
struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode);
|
||||||
struct jffs2_full_dirent *fd;
|
struct jffs2_full_dirent *fd;
|
||||||
int ret;
|
int ret;
|
||||||
|
uint32_t now = get_seconds();
|
||||||
|
|
||||||
for (fd = f->dents ; fd; fd = fd->next) {
|
for (fd = f->dents ; fd; fd = fd->next) {
|
||||||
if (fd->ino)
|
if (fd->ino)
|
||||||
return -ENOTEMPTY;
|
return -ENOTEMPTY;
|
||||||
}
|
}
|
||||||
ret = jffs2_unlink(dir_i, dentry);
|
|
||||||
if (!ret)
|
ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name,
|
||||||
|
dentry->d_name.len, f, now);
|
||||||
|
if (!ret) {
|
||||||
|
dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
|
||||||
|
clear_nlink(dentry->d_inode);
|
||||||
drop_nlink(dir_i);
|
drop_nlink(dir_i);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -817,7 +836,10 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
|
|||||||
inode which didn't exist. */
|
inode which didn't exist. */
|
||||||
if (victim_f->inocache) {
|
if (victim_f->inocache) {
|
||||||
mutex_lock(&victim_f->sem);
|
mutex_lock(&victim_f->sem);
|
||||||
victim_f->inocache->nlink--;
|
if (S_ISDIR(new_dentry->d_inode->i_mode))
|
||||||
|
victim_f->inocache->pino_nlink = 0;
|
||||||
|
else
|
||||||
|
victim_f->inocache->pino_nlink--;
|
||||||
mutex_unlock(&victim_f->sem);
|
mutex_unlock(&victim_f->sem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -838,8 +860,8 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
|
|||||||
struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode);
|
struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode);
|
||||||
mutex_lock(&f->sem);
|
mutex_lock(&f->sem);
|
||||||
inc_nlink(old_dentry->d_inode);
|
inc_nlink(old_dentry->d_inode);
|
||||||
if (f->inocache)
|
if (f->inocache && !S_ISDIR(old_dentry->d_inode->i_mode))
|
||||||
f->inocache->nlink++;
|
f->inocache->pino_nlink++;
|
||||||
mutex_unlock(&f->sem);
|
mutex_unlock(&f->sem);
|
||||||
|
|
||||||
printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret);
|
printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret);
|
||||||
|
@ -294,7 +294,7 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
if (ic->nodes == (void *)ic && ic->nlink == 0)
|
if (ic->nodes == (void *)ic && ic->pino_nlink == 0)
|
||||||
jffs2_del_ino_cache(c, ic);
|
jffs2_del_ino_cache(c, ic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -332,7 +332,8 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
|
|||||||
if (c->mtd->point) {
|
if (c->mtd->point) {
|
||||||
unsigned long *wordebuf;
|
unsigned long *wordebuf;
|
||||||
|
|
||||||
ret = c->mtd->point(c->mtd, jeb->offset, c->sector_size, &retlen, (unsigned char **)&ebuf);
|
ret = c->mtd->point(c->mtd, jeb->offset, c->sector_size,
|
||||||
|
&retlen, &ebuf, NULL);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
D1(printk(KERN_DEBUG "MTD point failed %d\n", ret));
|
D1(printk(KERN_DEBUG "MTD point failed %d\n", ret));
|
||||||
goto do_flash_read;
|
goto do_flash_read;
|
||||||
@ -340,7 +341,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
|
|||||||
if (retlen < c->sector_size) {
|
if (retlen < c->sector_size) {
|
||||||
/* Don't muck about if it won't let us point to the whole erase sector */
|
/* Don't muck about if it won't let us point to the whole erase sector */
|
||||||
D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", retlen));
|
D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", retlen));
|
||||||
c->mtd->unpoint(c->mtd, ebuf, jeb->offset, retlen);
|
c->mtd->unpoint(c->mtd, jeb->offset, retlen);
|
||||||
goto do_flash_read;
|
goto do_flash_read;
|
||||||
}
|
}
|
||||||
wordebuf = ebuf-sizeof(*wordebuf);
|
wordebuf = ebuf-sizeof(*wordebuf);
|
||||||
@ -349,7 +350,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
|
|||||||
if (*++wordebuf != ~0)
|
if (*++wordebuf != ~0)
|
||||||
break;
|
break;
|
||||||
} while(--retlen);
|
} while(--retlen);
|
||||||
c->mtd->unpoint(c->mtd, ebuf, jeb->offset, c->sector_size);
|
c->mtd->unpoint(c->mtd, jeb->offset, c->sector_size);
|
||||||
if (retlen) {
|
if (retlen) {
|
||||||
printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08tx\n",
|
printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08tx\n",
|
||||||
*wordebuf, jeb->offset + c->sector_size-retlen*sizeof(*wordebuf));
|
*wordebuf, jeb->offset + c->sector_size-retlen*sizeof(*wordebuf));
|
||||||
|
@ -273,7 +273,7 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
|
|||||||
inode->i_mtime = ITIME(je32_to_cpu(latest_node.mtime));
|
inode->i_mtime = ITIME(je32_to_cpu(latest_node.mtime));
|
||||||
inode->i_ctime = ITIME(je32_to_cpu(latest_node.ctime));
|
inode->i_ctime = ITIME(je32_to_cpu(latest_node.ctime));
|
||||||
|
|
||||||
inode->i_nlink = f->inocache->nlink;
|
inode->i_nlink = f->inocache->pino_nlink;
|
||||||
|
|
||||||
inode->i_blocks = (inode->i_size + 511) >> 9;
|
inode->i_blocks = (inode->i_size + 511) >> 9;
|
||||||
|
|
||||||
@ -286,13 +286,12 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
|
|||||||
case S_IFDIR:
|
case S_IFDIR:
|
||||||
{
|
{
|
||||||
struct jffs2_full_dirent *fd;
|
struct jffs2_full_dirent *fd;
|
||||||
|
inode->i_nlink = 2; /* parent and '.' */
|
||||||
|
|
||||||
for (fd=f->dents; fd; fd = fd->next) {
|
for (fd=f->dents; fd; fd = fd->next) {
|
||||||
if (fd->type == DT_DIR && fd->ino)
|
if (fd->type == DT_DIR && fd->ino)
|
||||||
inc_nlink(inode);
|
inc_nlink(inode);
|
||||||
}
|
}
|
||||||
/* and '..' */
|
|
||||||
inc_nlink(inode);
|
|
||||||
/* Root dir gets i_nlink 3 for some reason */
|
/* Root dir gets i_nlink 3 for some reason */
|
||||||
if (inode->i_ino == 1)
|
if (inode->i_ino == 1)
|
||||||
inc_nlink(inode);
|
inc_nlink(inode);
|
||||||
@ -586,11 +585,12 @@ void jffs2_gc_release_inode(struct jffs2_sb_info *c,
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
|
struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
|
||||||
int inum, int nlink)
|
int inum, int unlinked)
|
||||||
{
|
{
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
struct jffs2_inode_cache *ic;
|
struct jffs2_inode_cache *ic;
|
||||||
if (!nlink) {
|
|
||||||
|
if (unlinked) {
|
||||||
/* The inode has zero nlink but its nodes weren't yet marked
|
/* The inode has zero nlink but its nodes weren't yet marked
|
||||||
obsolete. This has to be because we're still waiting for
|
obsolete. This has to be because we're still waiting for
|
||||||
the final (close() and) iput() to happen.
|
the final (close() and) iput() to happen.
|
||||||
@ -638,8 +638,8 @@ struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
|
|||||||
return ERR_CAST(inode);
|
return ERR_CAST(inode);
|
||||||
}
|
}
|
||||||
if (is_bad_inode(inode)) {
|
if (is_bad_inode(inode)) {
|
||||||
printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u. nlink %d\n",
|
printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u. unlinked %d\n",
|
||||||
inum, nlink);
|
inum, unlinked);
|
||||||
/* NB. This will happen again. We need to do something appropriate here. */
|
/* NB. This will happen again. We need to do something appropriate here. */
|
||||||
iput(inode);
|
iput(inode);
|
||||||
return ERR_PTR(-EIO);
|
return ERR_PTR(-EIO);
|
||||||
|
@ -161,8 +161,8 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ic->nlink) {
|
if (!ic->pino_nlink) {
|
||||||
D1(printk(KERN_DEBUG "Skipping check of ino #%d with nlink zero\n",
|
D1(printk(KERN_DEBUG "Skipping check of ino #%d with nlink/pino zero\n",
|
||||||
ic->ino));
|
ic->ino));
|
||||||
spin_unlock(&c->inocache_lock);
|
spin_unlock(&c->inocache_lock);
|
||||||
jffs2_xattr_delete_inode(c, ic);
|
jffs2_xattr_delete_inode(c, ic);
|
||||||
@ -398,10 +398,10 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
|
|||||||
it's vaguely possible. */
|
it's vaguely possible. */
|
||||||
|
|
||||||
inum = ic->ino;
|
inum = ic->ino;
|
||||||
nlink = ic->nlink;
|
nlink = ic->pino_nlink;
|
||||||
spin_unlock(&c->inocache_lock);
|
spin_unlock(&c->inocache_lock);
|
||||||
|
|
||||||
f = jffs2_gc_fetch_inode(c, inum, nlink);
|
f = jffs2_gc_fetch_inode(c, inum, !nlink);
|
||||||
if (IS_ERR(f)) {
|
if (IS_ERR(f)) {
|
||||||
ret = PTR_ERR(f);
|
ret = PTR_ERR(f);
|
||||||
goto release_sem;
|
goto release_sem;
|
||||||
|
@ -177,7 +177,10 @@ struct jffs2_inode_cache {
|
|||||||
#ifdef CONFIG_JFFS2_FS_XATTR
|
#ifdef CONFIG_JFFS2_FS_XATTR
|
||||||
struct jffs2_xattr_ref *xref;
|
struct jffs2_xattr_ref *xref;
|
||||||
#endif
|
#endif
|
||||||
int nlink;
|
uint32_t pino_nlink; /* Directories store parent inode
|
||||||
|
here; other inodes store nlink.
|
||||||
|
Zero always means that it's
|
||||||
|
completely unlinked. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Inode states for 'state' above. We need the 'GC' state to prevent
|
/* Inode states for 'state' above. We need the 'GC' state to prevent
|
||||||
|
@ -709,7 +709,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
if (ic->nodes == (void *)ic && ic->nlink == 0)
|
if (ic->nodes == (void *)ic && ic->pino_nlink == 0)
|
||||||
jffs2_del_ino_cache(c, ic);
|
jffs2_del_ino_cache(c, ic);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -187,7 +187,7 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent);
|
|||||||
void jffs2_gc_release_inode(struct jffs2_sb_info *c,
|
void jffs2_gc_release_inode(struct jffs2_sb_info *c,
|
||||||
struct jffs2_inode_info *f);
|
struct jffs2_inode_info *f);
|
||||||
struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
|
struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
|
||||||
int inum, int nlink);
|
int inum, int unlinked);
|
||||||
|
|
||||||
unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c,
|
unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c,
|
||||||
struct jffs2_inode_info *f,
|
struct jffs2_inode_info *f,
|
||||||
|
@ -63,10 +63,11 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info
|
|||||||
/* TODO: instead, incapsulate point() stuff to jffs2_flash_read(),
|
/* TODO: instead, incapsulate point() stuff to jffs2_flash_read(),
|
||||||
* adding and jffs2_flash_read_end() interface. */
|
* adding and jffs2_flash_read_end() interface. */
|
||||||
if (c->mtd->point) {
|
if (c->mtd->point) {
|
||||||
err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer);
|
err = c->mtd->point(c->mtd, ofs, len, &retlen,
|
||||||
|
(void **)&buffer, NULL);
|
||||||
if (!err && retlen < len) {
|
if (!err && retlen < len) {
|
||||||
JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize);
|
JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize);
|
||||||
c->mtd->unpoint(c->mtd, buffer, ofs, retlen);
|
c->mtd->unpoint(c->mtd, ofs, retlen);
|
||||||
} else if (err)
|
} else if (err)
|
||||||
JFFS2_WARNING("MTD point failed: error code %d.\n", err);
|
JFFS2_WARNING("MTD point failed: error code %d.\n", err);
|
||||||
else
|
else
|
||||||
@ -100,7 +101,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info
|
|||||||
kfree(buffer);
|
kfree(buffer);
|
||||||
#ifndef __ECOS
|
#ifndef __ECOS
|
||||||
else
|
else
|
||||||
c->mtd->unpoint(c->mtd, buffer, ofs, len);
|
c->mtd->unpoint(c->mtd, ofs, len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (crc != tn->data_crc) {
|
if (crc != tn->data_crc) {
|
||||||
@ -136,7 +137,7 @@ free_out:
|
|||||||
kfree(buffer);
|
kfree(buffer);
|
||||||
#ifndef __ECOS
|
#ifndef __ECOS
|
||||||
else
|
else
|
||||||
c->mtd->unpoint(c->mtd, buffer, ofs, len);
|
c->mtd->unpoint(c->mtd, ofs, len);
|
||||||
#endif
|
#endif
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -1123,7 +1124,8 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
|
|||||||
size_t retlen;
|
size_t retlen;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dbg_readinode("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink);
|
dbg_readinode("ino #%u pino/nlink is %d\n", f->inocache->ino,
|
||||||
|
f->inocache->pino_nlink);
|
||||||
|
|
||||||
memset(&rii, 0, sizeof(rii));
|
memset(&rii, 0, sizeof(rii));
|
||||||
|
|
||||||
@ -1358,7 +1360,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
|
|||||||
}
|
}
|
||||||
dbg_readinode("creating inocache for root inode\n");
|
dbg_readinode("creating inocache for root inode\n");
|
||||||
memset(f->inocache, 0, sizeof(struct jffs2_inode_cache));
|
memset(f->inocache, 0, sizeof(struct jffs2_inode_cache));
|
||||||
f->inocache->ino = f->inocache->nlink = 1;
|
f->inocache->ino = f->inocache->pino_nlink = 1;
|
||||||
f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
|
f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
|
||||||
f->inocache->state = INO_STATE_READING;
|
f->inocache->state = INO_STATE_READING;
|
||||||
jffs2_add_ino_cache(c, f->inocache);
|
jffs2_add_ino_cache(c, f->inocache);
|
||||||
@ -1401,7 +1403,7 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
|
|||||||
jffs2_clear_acl(f);
|
jffs2_clear_acl(f);
|
||||||
jffs2_xattr_delete_inode(c, f->inocache);
|
jffs2_xattr_delete_inode(c, f->inocache);
|
||||||
mutex_lock(&f->sem);
|
mutex_lock(&f->sem);
|
||||||
deleted = f->inocache && !f->inocache->nlink;
|
deleted = f->inocache && !f->inocache->pino_nlink;
|
||||||
|
|
||||||
if (f->inocache && f->inocache->state != INO_STATE_CHECKING)
|
if (f->inocache && f->inocache->state != INO_STATE_CHECKING)
|
||||||
jffs2_set_inocache_state(c, f->inocache, INO_STATE_CLEARING);
|
jffs2_set_inocache_state(c, f->inocache, INO_STATE_CLEARING);
|
||||||
|
@ -97,11 +97,12 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
|
|||||||
size_t pointlen;
|
size_t pointlen;
|
||||||
|
|
||||||
if (c->mtd->point) {
|
if (c->mtd->point) {
|
||||||
ret = c->mtd->point (c->mtd, 0, c->mtd->size, &pointlen, &flashbuf);
|
ret = c->mtd->point(c->mtd, 0, c->mtd->size, &pointlen,
|
||||||
|
(void **)&flashbuf, NULL);
|
||||||
if (!ret && pointlen < c->mtd->size) {
|
if (!ret && pointlen < c->mtd->size) {
|
||||||
/* Don't muck about if it won't let us point to the whole flash */
|
/* Don't muck about if it won't let us point to the whole flash */
|
||||||
D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", pointlen));
|
D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", pointlen));
|
||||||
c->mtd->unpoint(c->mtd, flashbuf, 0, pointlen);
|
c->mtd->unpoint(c->mtd, 0, pointlen);
|
||||||
flashbuf = NULL;
|
flashbuf = NULL;
|
||||||
}
|
}
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -267,7 +268,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
|
|||||||
kfree(flashbuf);
|
kfree(flashbuf);
|
||||||
#ifndef __ECOS
|
#ifndef __ECOS
|
||||||
else
|
else
|
||||||
c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size);
|
c->mtd->unpoint(c->mtd, 0, c->mtd->size);
|
||||||
#endif
|
#endif
|
||||||
if (s)
|
if (s)
|
||||||
kfree(s);
|
kfree(s);
|
||||||
@ -940,7 +941,7 @@ struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uin
|
|||||||
ic->nodes = (void *)ic;
|
ic->nodes = (void *)ic;
|
||||||
jffs2_add_ino_cache(c, ic);
|
jffs2_add_ino_cache(c, ic);
|
||||||
if (ino == 1)
|
if (ino == 1)
|
||||||
ic->nlink = 1;
|
ic->pino_nlink = 1;
|
||||||
return ic;
|
return ic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,11 +31,12 @@ static struct kmem_cache *jffs2_inode_cachep;
|
|||||||
|
|
||||||
static struct inode *jffs2_alloc_inode(struct super_block *sb)
|
static struct inode *jffs2_alloc_inode(struct super_block *sb)
|
||||||
{
|
{
|
||||||
struct jffs2_inode_info *ei;
|
struct jffs2_inode_info *f;
|
||||||
ei = (struct jffs2_inode_info *)kmem_cache_alloc(jffs2_inode_cachep, GFP_KERNEL);
|
|
||||||
if (!ei)
|
f = kmem_cache_alloc(jffs2_inode_cachep, GFP_KERNEL);
|
||||||
|
if (!f)
|
||||||
return NULL;
|
return NULL;
|
||||||
return &ei->vfs_inode;
|
return &f->vfs_inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void jffs2_destroy_inode(struct inode *inode)
|
static void jffs2_destroy_inode(struct inode *inode)
|
||||||
@ -45,10 +46,10 @@ static void jffs2_destroy_inode(struct inode *inode)
|
|||||||
|
|
||||||
static void jffs2_i_init_once(struct kmem_cache *cachep, void *foo)
|
static void jffs2_i_init_once(struct kmem_cache *cachep, void *foo)
|
||||||
{
|
{
|
||||||
struct jffs2_inode_info *ei = (struct jffs2_inode_info *) foo;
|
struct jffs2_inode_info *f = foo;
|
||||||
|
|
||||||
mutex_init(&ei->sem);
|
mutex_init(&f->sem);
|
||||||
inode_init_once(&ei->vfs_inode);
|
inode_init_once(&f->vfs_inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int jffs2_sync_fs(struct super_block *sb, int wait)
|
static int jffs2_sync_fs(struct super_block *sb, int wait)
|
||||||
|
@ -494,7 +494,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
|
|||||||
/* If it's an in-core inode, then we have to adjust any
|
/* If it's an in-core inode, then we have to adjust any
|
||||||
full_dirent or full_dnode structure to point to the
|
full_dirent or full_dnode structure to point to the
|
||||||
new version instead of the old */
|
new version instead of the old */
|
||||||
f = jffs2_gc_fetch_inode(c, ic->ino, ic->nlink);
|
f = jffs2_gc_fetch_inode(c, ic->ino, !ic->pino_nlink);
|
||||||
if (IS_ERR(f)) {
|
if (IS_ERR(f)) {
|
||||||
/* Should never happen; it _must_ be present */
|
/* Should never happen; it _must_ be present */
|
||||||
JFFS2_ERROR("Failed to iget() ino #%u, err %ld\n",
|
JFFS2_ERROR("Failed to iget() ino #%u, err %ld\n",
|
||||||
|
@ -19,7 +19,8 @@
|
|||||||
#include "compr.h"
|
#include "compr.h"
|
||||||
|
|
||||||
|
|
||||||
int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri)
|
int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
|
||||||
|
uint32_t mode, struct jffs2_raw_inode *ri)
|
||||||
{
|
{
|
||||||
struct jffs2_inode_cache *ic;
|
struct jffs2_inode_cache *ic;
|
||||||
|
|
||||||
@ -31,7 +32,7 @@ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint
|
|||||||
memset(ic, 0, sizeof(*ic));
|
memset(ic, 0, sizeof(*ic));
|
||||||
|
|
||||||
f->inocache = ic;
|
f->inocache = ic;
|
||||||
f->inocache->nlink = 1;
|
f->inocache->pino_nlink = 1; /* Will be overwritten shortly for directories */
|
||||||
f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
|
f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
|
||||||
f->inocache->state = INO_STATE_PRESENT;
|
f->inocache->state = INO_STATE_PRESENT;
|
||||||
|
|
||||||
@ -438,10 +439,10 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
|
|||||||
ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL,
|
ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL,
|
||||||
JFFS2_SUMMARY_INODE_SIZE);
|
JFFS2_SUMMARY_INODE_SIZE);
|
||||||
D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen));
|
D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen));
|
||||||
if (ret) {
|
if (ret)
|
||||||
mutex_unlock(&f->sem);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
|
||||||
|
mutex_lock(&f->sem);
|
||||||
|
|
||||||
ri->data_crc = cpu_to_je32(0);
|
ri->data_crc = cpu_to_je32(0);
|
||||||
ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
|
ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
|
||||||
@ -635,9 +636,9 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
|
|||||||
jffs2_mark_node_obsolete(c, fd->raw);
|
jffs2_mark_node_obsolete(c, fd->raw);
|
||||||
jffs2_free_full_dirent(fd);
|
jffs2_free_full_dirent(fd);
|
||||||
}
|
}
|
||||||
}
|
dead_f->inocache->pino_nlink = 0;
|
||||||
|
} else
|
||||||
dead_f->inocache->nlink--;
|
dead_f->inocache->pino_nlink--;
|
||||||
/* NB: Caller must set inode nlink if appropriate */
|
/* NB: Caller must set inode nlink if appropriate */
|
||||||
mutex_unlock(&dead_f->sem);
|
mutex_unlock(&dead_f->sem);
|
||||||
}
|
}
|
||||||
|
@ -592,7 +592,7 @@ void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache
|
|||||||
When an inode with XATTR is removed, those XATTRs must be removed. */
|
When an inode with XATTR is removed, those XATTRs must be removed. */
|
||||||
struct jffs2_xattr_ref *ref, *_ref;
|
struct jffs2_xattr_ref *ref, *_ref;
|
||||||
|
|
||||||
if (!ic || ic->nlink > 0)
|
if (!ic || ic->pino_nlink > 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
down_write(&c->xattr_sem);
|
down_write(&c->xattr_sem);
|
||||||
@ -829,7 +829,7 @@ void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
|
|||||||
ref->xd and ref->ic are not valid yet. */
|
ref->xd and ref->ic are not valid yet. */
|
||||||
xd = jffs2_find_xattr_datum(c, ref->xid);
|
xd = jffs2_find_xattr_datum(c, ref->xid);
|
||||||
ic = jffs2_get_ino_cache(c, ref->ino);
|
ic = jffs2_get_ino_cache(c, ref->ino);
|
||||||
if (!xd || !ic || !ic->nlink) {
|
if (!xd || !ic || !ic->pino_nlink) {
|
||||||
dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) is orphan.\n",
|
dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) is orphan.\n",
|
||||||
ref->ino, ref->xid, ref->xseqno);
|
ref->ino, ref->xid, ref->xseqno);
|
||||||
ref->xseqno |= XREF_DELETE_MARKER;
|
ref->xseqno |= XREF_DELETE_MARKER;
|
||||||
|
@ -1,66 +0,0 @@
|
|||||||
|
|
||||||
/* JEDEC Flash Interface.
|
|
||||||
* This is an older type of interface for self programming flash. It is
|
|
||||||
* commonly use in older AMD chips and is obsolete compared with CFI.
|
|
||||||
* It is called JEDEC because the JEDEC association distributes the ID codes
|
|
||||||
* for the chips.
|
|
||||||
*
|
|
||||||
* See the AMD flash databook for information on how to operate the interface.
|
|
||||||
*
|
|
||||||
* $Id: jedec.h,v 1.4 2005/11/07 11:14:54 gleixner Exp $
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __LINUX_MTD_JEDEC_H__
|
|
||||||
#define __LINUX_MTD_JEDEC_H__
|
|
||||||
|
|
||||||
#include <linux/types.h>
|
|
||||||
|
|
||||||
#define MAX_JEDEC_CHIPS 16
|
|
||||||
|
|
||||||
// Listing of all supported chips and their information
|
|
||||||
struct JEDECTable
|
|
||||||
{
|
|
||||||
__u16 jedec;
|
|
||||||
char *name;
|
|
||||||
unsigned long size;
|
|
||||||
unsigned long sectorsize;
|
|
||||||
__u32 capabilities;
|
|
||||||
};
|
|
||||||
|
|
||||||
// JEDEC being 0 is the end of the chip array
|
|
||||||
struct jedec_flash_chip
|
|
||||||
{
|
|
||||||
__u16 jedec;
|
|
||||||
unsigned long size;
|
|
||||||
unsigned long sectorsize;
|
|
||||||
|
|
||||||
// *(__u8*)(base + (adder << addrshift)) = data << datashift
|
|
||||||
// Address size = size << addrshift
|
|
||||||
unsigned long base; // Byte 0 of the flash, will be unaligned
|
|
||||||
unsigned int datashift; // Useful for 32bit/16bit accesses
|
|
||||||
unsigned int addrshift;
|
|
||||||
unsigned long offset; // linerized start. base==offset for unbanked, uninterleaved flash
|
|
||||||
|
|
||||||
__u32 capabilities;
|
|
||||||
|
|
||||||
// These markers are filled in by the flash_chip_scan function
|
|
||||||
unsigned long start;
|
|
||||||
unsigned long length;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct jedec_private
|
|
||||||
{
|
|
||||||
unsigned long size; // Total size of all the devices
|
|
||||||
|
|
||||||
/* Bank handling. If sum(bank_fill) == size then this is linear flash.
|
|
||||||
Otherwise the mapping has holes in it. bank_fill may be used to
|
|
||||||
find the holes, but in the common symetric case
|
|
||||||
bank_fill[0] == bank_fill[*], thus addresses may be computed
|
|
||||||
mathmatically. bank_fill must be powers of two */
|
|
||||||
unsigned is_banked;
|
|
||||||
unsigned long bank_fill[MAX_JEDEC_CHIPS];
|
|
||||||
|
|
||||||
struct jedec_flash_chip chips[MAX_JEDEC_CHIPS];
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -143,10 +143,12 @@ struct mtd_info {
|
|||||||
int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
|
int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
|
||||||
|
|
||||||
/* This stuff for eXecute-In-Place */
|
/* This stuff for eXecute-In-Place */
|
||||||
int (*point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf);
|
/* phys is optional and may be set to NULL */
|
||||||
|
int (*point) (struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
|
size_t *retlen, void **virt, resource_size_t *phys);
|
||||||
|
|
||||||
/* We probably shouldn't allow XIP if the unpoint isn't a NULL */
|
/* We probably shouldn't allow XIP if the unpoint isn't a NULL */
|
||||||
void (*unpoint) (struct mtd_info *mtd, u_char * addr, loff_t from, size_t len);
|
void (*unpoint) (struct mtd_info *mtd, loff_t from, size_t len);
|
||||||
|
|
||||||
|
|
||||||
int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
|
int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
|
||||||
|
@ -36,8 +36,9 @@ struct mypriv {
|
|||||||
* Function Prototypes
|
* Function Prototypes
|
||||||
*/
|
*/
|
||||||
static int pmc551_erase(struct mtd_info *, struct erase_info *);
|
static int pmc551_erase(struct mtd_info *, struct erase_info *);
|
||||||
static void pmc551_unpoint(struct mtd_info *, u_char *, loff_t, size_t);
|
static void pmc551_unpoint(struct mtd_info *, loff_t, size_t);
|
||||||
static int pmc551_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf);
|
static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
|
size_t *retlen, void **virt, resource_size_t *phys);
|
||||||
static int pmc551_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *);
|
static int pmc551_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *);
|
||||||
static int pmc551_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
|
static int pmc551_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user