aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-06-27 22:13:56 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-27 22:13:56 -0400
commit936813a8807c5684c6a97f1081b31027403d4a93 (patch)
treebc3a1343ea1548195ab4e5dd11b1830f8b9cc52b
parent73a0e405dce7d720808536b708f7c738b413b1a2 (diff)
parent6a93096195305f6f2a39544a034e77e2e74d5799 (diff)
Merge git://git.infradead.org/mtd-2.6
* git://git.infradead.org/mtd-2.6: [MTD] NAND: Select chip before checking write protect status [MTD] CORE mtdchar.c: fix off-by-one error in lseek() [MTD] NAND: Fix typo in mtd/nand/ts7250.c [JFFS2][XATTR] coexistence between xattr and write buffering support. [JFFS2][XATTR] Fix wrong copyright [JFFS2][XATTR] Re-define xd->refcnt as atomic_t [JFFS2][XATTR] Fix memory leak with jffs2_xattr_ref [JFFS2][XATTR] rid unnecessary writing of delete marker. [JFFS2][XATTR] Fix ACL bug when updating null xattr by null ACL. [JFFS2][XATTR] using 'delete marker' for xdatum/xref deletion [MTD] Fix off-by-one error in physmap.c [MTD] Remove unused 'nr_banks' variable from ixp2000 map driver [MTD NAND] s3c2412 support in s3c2410.c [MTD] Initialize 'writesize' [MTD] NAND: ndfc fix address offset thinko [MTD] NAND: S3C2410 convert prinks to dev_*()s [MTD] NAND: Missing fixups
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c1
-rw-r--r--drivers/mtd/chips/jedec.c1
-rw-r--r--drivers/mtd/chips/map_absent.c3
-rw-r--r--drivers/mtd/chips/map_ram.c1
-rw-r--r--drivers/mtd/chips/map_rom.c1
-rw-r--r--drivers/mtd/devices/block2mtd.c1
-rw-r--r--drivers/mtd/devices/ms02-nv.c1
-rw-r--r--drivers/mtd/devices/mtd_dataflash.c1
-rw-r--r--drivers/mtd/devices/phram.c1
-rw-r--r--drivers/mtd/devices/pmc551.c3
-rw-r--r--drivers/mtd/devices/slram.c1
-rw-r--r--drivers/mtd/maps/ixp2000.c2
-rw-r--r--drivers/mtd/maps/physmap.c2
-rw-r--r--drivers/mtd/mtdchar.c2
-rw-r--r--drivers/mtd/nand/nand_base.c16
-rw-r--r--drivers/mtd/nand/ndfc.c6
-rw-r--r--drivers/mtd/nand/s3c2410.c164
-rw-r--r--drivers/mtd/nand/ts7250.c2
-rw-r--r--fs/Kconfig2
-rw-r--r--fs/jffs2/acl.c2
-rw-r--r--fs/jffs2/erase.c19
-rw-r--r--fs/jffs2/fs.c2
-rw-r--r--fs/jffs2/gc.c6
-rw-r--r--fs/jffs2/jffs2_fs_sb.h3
-rw-r--r--fs/jffs2/malloc.c2
-rw-r--r--fs/jffs2/nodelist.c3
-rw-r--r--fs/jffs2/nodemgmt.c21
-rw-r--r--fs/jffs2/readinode.c1
-rw-r--r--fs/jffs2/scan.c55
-rw-r--r--fs/jffs2/summary.c41
-rw-r--r--fs/jffs2/xattr.c632
-rw-r--r--fs/jffs2/xattr.h21
-rw-r--r--include/asm-arm/arch-s3c2410/regs-nand.h48
-rw-r--r--include/linux/jffs2.h1
34 files changed, 657 insertions, 411 deletions
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index 0d435814aaa1..39edb8250fbc 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -357,6 +357,7 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
357 mtd->resume = cfi_intelext_resume; 357 mtd->resume = cfi_intelext_resume;
358 mtd->flags = MTD_CAP_NORFLASH; 358 mtd->flags = MTD_CAP_NORFLASH;
359 mtd->name = map->name; 359 mtd->name = map->name;
360 mtd->writesize = 1;
360 361
361 mtd->reboot_notifier.notifier_call = cfi_intelext_reboot; 362 mtd->reboot_notifier.notifier_call = cfi_intelext_reboot;
362 363
diff --git a/drivers/mtd/chips/jedec.c b/drivers/mtd/chips/jedec.c
index c40b48dabed3..2c3f019197c1 100644
--- a/drivers/mtd/chips/jedec.c
+++ b/drivers/mtd/chips/jedec.c
@@ -256,6 +256,7 @@ static struct mtd_info *jedec_probe(struct map_info *map)
256 MTD->name = map->name; 256 MTD->name = map->name;
257 MTD->type = MTD_NORFLASH; 257 MTD->type = MTD_NORFLASH;
258 MTD->flags = MTD_CAP_NORFLASH; 258 MTD->flags = MTD_CAP_NORFLASH;
259 MTD->writesize = 1;
259 MTD->erasesize = SectorSize*(map->buswidth); 260 MTD->erasesize = SectorSize*(map->buswidth);
260 // printk("MTD->erasesize is %x\n",(unsigned int)MTD->erasesize); 261 // printk("MTD->erasesize is %x\n",(unsigned int)MTD->erasesize);
261 MTD->size = priv->size; 262 MTD->size = priv->size;
diff --git a/drivers/mtd/chips/map_absent.c b/drivers/mtd/chips/map_absent.c
index a611de9b1515..ac01a949b687 100644
--- a/drivers/mtd/chips/map_absent.c
+++ b/drivers/mtd/chips/map_absent.c
@@ -64,7 +64,8 @@ static struct mtd_info *map_absent_probe(struct map_info *map)
64 mtd->write = map_absent_write; 64 mtd->write = map_absent_write;
65 mtd->sync = map_absent_sync; 65 mtd->sync = map_absent_sync;
66 mtd->flags = 0; 66 mtd->flags = 0;
67 mtd->erasesize = PAGE_SIZE; 67 mtd->erasesize = PAGE_SIZE;
68 mtd->writesize = 1;
68 69
69 __module_get(THIS_MODULE); 70 __module_get(THIS_MODULE);
70 return mtd; 71 return mtd;
diff --git a/drivers/mtd/chips/map_ram.c b/drivers/mtd/chips/map_ram.c
index 763925747db6..3a66680abfd0 100644
--- a/drivers/mtd/chips/map_ram.c
+++ b/drivers/mtd/chips/map_ram.c
@@ -71,6 +71,7 @@ static struct mtd_info *map_ram_probe(struct map_info *map)
71 mtd->write = mapram_write; 71 mtd->write = mapram_write;
72 mtd->sync = mapram_nop; 72 mtd->sync = mapram_nop;
73 mtd->flags = MTD_CAP_RAM; 73 mtd->flags = MTD_CAP_RAM;
74 mtd->writesize = 1;
74 75
75 mtd->erasesize = PAGE_SIZE; 76 mtd->erasesize = PAGE_SIZE;
76 while(mtd->size & (mtd->erasesize - 1)) 77 while(mtd->size & (mtd->erasesize - 1))
diff --git a/drivers/mtd/chips/map_rom.c b/drivers/mtd/chips/map_rom.c
index bc6ee9ef8a31..1b328b1378fd 100644
--- a/drivers/mtd/chips/map_rom.c
+++ b/drivers/mtd/chips/map_rom.c
@@ -47,6 +47,7 @@ static struct mtd_info *map_rom_probe(struct map_info *map)
47 mtd->sync = maprom_nop; 47 mtd->sync = maprom_nop;
48 mtd->flags = MTD_CAP_ROM; 48 mtd->flags = MTD_CAP_ROM;
49 mtd->erasesize = map->size; 49 mtd->erasesize = map->size;
50 mtd->writesize = 1;
50 51
51 __module_get(THIS_MODULE); 52 __module_get(THIS_MODULE);
52 return mtd; 53 return mtd;
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index 0d98c223c5fc..be3f1c136d02 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -324,6 +324,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
324 324
325 dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK; 325 dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
326 dev->mtd.erasesize = erase_size; 326 dev->mtd.erasesize = erase_size;
327 dev->mtd.writesize = 1;
327 dev->mtd.type = MTD_RAM; 328 dev->mtd.type = MTD_RAM;
328 dev->mtd.flags = MTD_CAP_RAM; 329 dev->mtd.flags = MTD_CAP_RAM;
329 dev->mtd.erase = block2mtd_erase; 330 dev->mtd.erase = block2mtd_erase;
diff --git a/drivers/mtd/devices/ms02-nv.c b/drivers/mtd/devices/ms02-nv.c
index 4ab7670770e4..08dfb899b272 100644
--- a/drivers/mtd/devices/ms02-nv.c
+++ b/drivers/mtd/devices/ms02-nv.c
@@ -225,6 +225,7 @@ static int __init ms02nv_init_one(ulong addr)
225 mtd->owner = THIS_MODULE; 225 mtd->owner = THIS_MODULE;
226 mtd->read = ms02nv_read; 226 mtd->read = ms02nv_read;
227 mtd->write = ms02nv_write; 227 mtd->write = ms02nv_write;
228 mtd->writesize = 1;
228 229
229 ret = -EIO; 230 ret = -EIO;
230 if (add_mtd_device(mtd)) { 231 if (add_mtd_device(mtd)) {
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index a19480d07888..04271d02b6b6 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -478,6 +478,7 @@ add_dataflash(struct spi_device *spi, char *name,
478 device->name = (pdata && pdata->name) ? pdata->name : priv->name; 478 device->name = (pdata && pdata->name) ? pdata->name : priv->name;
479 device->size = nr_pages * pagesize; 479 device->size = nr_pages * pagesize;
480 device->erasesize = pagesize; 480 device->erasesize = pagesize;
481 device->writesize = pagesize;
481 device->owner = THIS_MODULE; 482 device->owner = THIS_MODULE;
482 device->type = MTD_DATAFLASH; 483 device->type = MTD_DATAFLASH;
483 device->flags = MTD_CAP_NORFLASH; 484 device->flags = MTD_CAP_NORFLASH;
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
index e09e416667d3..6c7337f9ebbb 100644
--- a/drivers/mtd/devices/phram.c
+++ b/drivers/mtd/devices/phram.c
@@ -151,6 +151,7 @@ static int register_device(char *name, unsigned long start, unsigned long len)
151 new->mtd.owner = THIS_MODULE; 151 new->mtd.owner = THIS_MODULE;
152 new->mtd.type = MTD_RAM; 152 new->mtd.type = MTD_RAM;
153 new->mtd.erasesize = PAGE_SIZE; 153 new->mtd.erasesize = PAGE_SIZE;
154 new->mtd.writesize = 1;
154 155
155 ret = -EAGAIN; 156 ret = -EAGAIN;
156 if (add_mtd_device(&new->mtd)) { 157 if (add_mtd_device(&new->mtd)) {
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c
index 666cce1bf60c..f620d74f1004 100644
--- a/drivers/mtd/devices/pmc551.c
+++ b/drivers/mtd/devices/pmc551.c
@@ -778,7 +778,8 @@ static int __init init_pmc551(void)
778 mtd->type = MTD_RAM; 778 mtd->type = MTD_RAM;
779 mtd->name = "PMC551 RAM board"; 779 mtd->name = "PMC551 RAM board";
780 mtd->erasesize = 0x10000; 780 mtd->erasesize = 0x10000;
781 mtd->owner = THIS_MODULE; 781 mtd->writesize = 1;
782 mtd->owner = THIS_MODULE;
782 783
783 if (add_mtd_device(mtd)) { 784 if (add_mtd_device(mtd)) {
784 printk(KERN_NOTICE "pmc551: Failed to register new device\n"); 785 printk(KERN_NOTICE "pmc551: Failed to register new device\n");
diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c
index b3f665e3c38b..542a0c009006 100644
--- a/drivers/mtd/devices/slram.c
+++ b/drivers/mtd/devices/slram.c
@@ -209,6 +209,7 @@ static int register_device(char *name, unsigned long start, unsigned long length
209 (*curmtd)->mtdinfo->owner = THIS_MODULE; 209 (*curmtd)->mtdinfo->owner = THIS_MODULE;
210 (*curmtd)->mtdinfo->type = MTD_RAM; 210 (*curmtd)->mtdinfo->type = MTD_RAM;
211 (*curmtd)->mtdinfo->erasesize = SLRAM_BLK_SZ; 211 (*curmtd)->mtdinfo->erasesize = SLRAM_BLK_SZ;
212 (*curmtd)->mtdinfo->writesize = 1;
212 213
213 if (add_mtd_device((*curmtd)->mtdinfo)) { 214 if (add_mtd_device((*curmtd)->mtdinfo)) {
214 E("slram: Failed to register new device\n"); 215 E("slram: Failed to register new device\n");
diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c
index 2c9cc7f37e92..c26488a1793a 100644
--- a/drivers/mtd/maps/ixp2000.c
+++ b/drivers/mtd/maps/ixp2000.c
@@ -42,7 +42,6 @@ struct ixp2000_flash_info {
42 struct map_info map; 42 struct map_info map;
43 struct mtd_partition *partitions; 43 struct mtd_partition *partitions;
44 struct resource *res; 44 struct resource *res;
45 int nr_banks;
46}; 45};
47 46
48static inline unsigned long flash_bank_setup(struct map_info *map, unsigned long ofs) 47static inline unsigned long flash_bank_setup(struct map_info *map, unsigned long ofs)
@@ -183,7 +182,6 @@ static int ixp2000_flash_probe(struct platform_device *dev)
183 */ 182 */
184 info->map.phys = NO_XIP; 183 info->map.phys = NO_XIP;
185 184
186 info->nr_banks = ixp_data->nr_banks;
187 info->map.size = ixp_data->nr_banks * window_size; 185 info->map.size = ixp_data->nr_banks * window_size;
188 info->map.bankwidth = 1; 186 info->map.bankwidth = 1;
189 187
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index 433c3cac3ca9..d6301f08906d 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -182,7 +182,7 @@ static struct physmap_flash_data physmap_flash_data = {
182 182
183static struct resource physmap_flash_resource = { 183static struct resource physmap_flash_resource = {
184 .start = CONFIG_MTD_PHYSMAP_START, 184 .start = CONFIG_MTD_PHYSMAP_START,
185 .end = CONFIG_MTD_PHYSMAP_START + CONFIG_MTD_PHYSMAP_LEN, 185 .end = CONFIG_MTD_PHYSMAP_START + CONFIG_MTD_PHYSMAP_LEN - 1,
186 .flags = IORESOURCE_MEM, 186 .flags = IORESOURCE_MEM,
187}; 187};
188 188
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index aa18d45b264b..9a4b59d92525 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -78,7 +78,7 @@ static loff_t mtd_lseek (struct file *file, loff_t offset, int orig)
78 return -EINVAL; 78 return -EINVAL;
79 } 79 }
80 80
81 if (offset >= 0 && offset < mtd->size) 81 if (offset >= 0 && offset <= mtd->size)
82 return file->f_pos = offset; 82 return file->f_pos = offset;
83 83
84 return -EINVAL; 84 return -EINVAL;
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 27083ed0a017..80a76654d963 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1176,7 +1176,7 @@ static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
1176 1176
1177 status = chip->waitfunc(mtd, chip); 1177 status = chip->waitfunc(mtd, chip);
1178 1178
1179 return status; 1179 return status & NAND_STATUS_FAIL ? -EIO : 0;
1180} 1180}
1181 1181
1182/** 1182/**
@@ -1271,10 +1271,6 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
1271 sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd); 1271 sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd);
1272 buf = nand_transfer_oob(chip, buf, ops); 1272 buf = nand_transfer_oob(chip, buf, ops);
1273 1273
1274 readlen -= ops->ooblen;
1275 if (!readlen)
1276 break;
1277
1278 if (!(chip->options & NAND_NO_READRDY)) { 1274 if (!(chip->options & NAND_NO_READRDY)) {
1279 /* 1275 /*
1280 * Apply delay or wait for ready/busy pin. Do this 1276 * Apply delay or wait for ready/busy pin. Do this
@@ -1288,6 +1284,10 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
1288 nand_wait_ready(mtd); 1284 nand_wait_ready(mtd);
1289 } 1285 }
1290 1286
1287 readlen -= ops->ooblen;
1288 if (!readlen)
1289 break;
1290
1291 /* Increment page address */ 1291 /* Increment page address */
1292 realpage++; 1292 realpage++;
1293 1293
@@ -1610,13 +1610,13 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
1610 if (!writelen) 1610 if (!writelen)
1611 return 0; 1611 return 0;
1612 1612
1613 chipnr = (int)(to >> chip->chip_shift);
1614 chip->select_chip(mtd, chipnr);
1615
1613 /* Check, if it is write protected */ 1616 /* Check, if it is write protected */
1614 if (nand_check_wp(mtd)) 1617 if (nand_check_wp(mtd))
1615 return -EIO; 1618 return -EIO;
1616 1619
1617 chipnr = (int)(to >> chip->chip_shift);
1618 chip->select_chip(mtd, chipnr);
1619
1620 realpage = (int)(to >> chip->page_shift); 1620 realpage = (int)(to >> chip->page_shift);
1621 page = realpage & chip->pagemask; 1621 page = realpage & chip->pagemask;
1622 blockmask = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; 1622 blockmask = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index fe8d38514ba6..e5bd88f2d560 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -61,15 +61,15 @@ static void ndfc_select_chip(struct mtd_info *mtd, int chip)
61 61
62static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) 62static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
63{ 63{
64 struct nand_chip *chip = mtd->priv; 64 struct ndfc_controller *ndfc = &ndfc_ctrl;
65 65
66 if (cmd == NAND_CMD_NONE) 66 if (cmd == NAND_CMD_NONE)
67 return; 67 return;
68 68
69 if (ctrl & NAND_CLE) 69 if (ctrl & NAND_CLE)
70 writel(cmd & 0xFF, chip->IO_ADDR_W + NDFC_CMD); 70 writel(cmd & 0xFF, ndfc->ndfcbase + NDFC_CMD);
71 else 71 else
72 writel(cmd & 0xFF, chip->IO_ADDR_W + NDFC_ALE); 72 writel(cmd & 0xFF, ndfc->ndfcbase + NDFC_ALE);
73} 73}
74 74
75static int ndfc_ready(struct mtd_info *mtd) 75static int ndfc_ready(struct mtd_info *mtd)
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 2c262fe03d8a..ff5cef24d5bb 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -63,8 +63,6 @@
63#include <asm/arch/regs-nand.h> 63#include <asm/arch/regs-nand.h>
64#include <asm/arch/nand.h> 64#include <asm/arch/nand.h>
65 65
66#define PFX "s3c2410-nand: "
67
68#ifdef CONFIG_MTD_NAND_S3C2410_HWECC 66#ifdef CONFIG_MTD_NAND_S3C2410_HWECC
69static int hardware_ecc = 1; 67static int hardware_ecc = 1;
70#else 68#else
@@ -99,6 +97,12 @@ struct s3c2410_nand_mtd {
99 int scan_res; 97 int scan_res;
100}; 98};
101 99
100enum s3c_cpu_type {
101 TYPE_S3C2410,
102 TYPE_S3C2412,
103 TYPE_S3C2440,
104};
105
102/* overview of the s3c2410 nand state */ 106/* overview of the s3c2410 nand state */
103 107
104struct s3c2410_nand_info { 108struct s3c2410_nand_info {
@@ -112,9 +116,11 @@ struct s3c2410_nand_info {
112 struct resource *area; 116 struct resource *area;
113 struct clk *clk; 117 struct clk *clk;
114 void __iomem *regs; 118 void __iomem *regs;
119 void __iomem *sel_reg;
120 int sel_bit;
115 int mtd_count; 121 int mtd_count;
116 122
117 unsigned char is_s3c2440; 123 enum s3c_cpu_type cpu_type;
118}; 124};
119 125
120/* conversion functions */ 126/* conversion functions */
@@ -148,7 +154,7 @@ static inline int allow_clk_stop(struct s3c2410_nand_info *info)
148 154
149#define NS_IN_KHZ 1000000 155#define NS_IN_KHZ 1000000
150 156
151static int s3c2410_nand_calc_rate(int wanted, unsigned long clk, int max) 157static int s3c_nand_calc_rate(int wanted, unsigned long clk, int max)
152{ 158{
153 int result; 159 int result;
154 160
@@ -172,53 +178,58 @@ static int s3c2410_nand_calc_rate(int wanted, unsigned long clk, int max)
172 178
173/* controller setup */ 179/* controller setup */
174 180
175static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, struct platform_device *pdev) 181static int s3c2410_nand_inithw(struct s3c2410_nand_info *info,
182 struct platform_device *pdev)
176{ 183{
177 struct s3c2410_platform_nand *plat = to_nand_plat(pdev); 184 struct s3c2410_platform_nand *plat = to_nand_plat(pdev);
178 unsigned long clkrate = clk_get_rate(info->clk); 185 unsigned long clkrate = clk_get_rate(info->clk);
186 int tacls_max = (info->cpu_type == TYPE_S3C2412) ? 8 : 4;
179 int tacls, twrph0, twrph1; 187 int tacls, twrph0, twrph1;
180 unsigned long cfg; 188 unsigned long cfg = 0;
181 189
182 /* calculate the timing information for the controller */ 190 /* calculate the timing information for the controller */
183 191
184 clkrate /= 1000; /* turn clock into kHz for ease of use */ 192 clkrate /= 1000; /* turn clock into kHz for ease of use */
185 193
186 if (plat != NULL) { 194 if (plat != NULL) {
187 tacls = s3c2410_nand_calc_rate(plat->tacls, clkrate, 4); 195 tacls = s3c_nand_calc_rate(plat->tacls, clkrate, tacls_max);
188 twrph0 = s3c2410_nand_calc_rate(plat->twrph0, clkrate, 8); 196 twrph0 = s3c_nand_calc_rate(plat->twrph0, clkrate, 8);
189 twrph1 = s3c2410_nand_calc_rate(plat->twrph1, clkrate, 8); 197 twrph1 = s3c_nand_calc_rate(plat->twrph1, clkrate, 8);
190 } else { 198 } else {
191 /* default timings */ 199 /* default timings */
192 tacls = 4; 200 tacls = tacls_max;
193 twrph0 = 8; 201 twrph0 = 8;
194 twrph1 = 8; 202 twrph1 = 8;
195 } 203 }
196 204
197 if (tacls < 0 || twrph0 < 0 || twrph1 < 0) { 205 if (tacls < 0 || twrph0 < 0 || twrph1 < 0) {
198 printk(KERN_ERR PFX "cannot get timings suitable for board\n"); 206 dev_err(info->device, "cannot get suitable timings\n");
199 return -EINVAL; 207 return -EINVAL;
200 } 208 }
201 209
202 printk(KERN_INFO PFX "Tacls=%d, %dns Twrph0=%d %dns, Twrph1=%d %dns\n", 210 dev_info(info->device, "Tacls=%d, %dns Twrph0=%d %dns, Twrph1=%d %dns\n",
203 tacls, to_ns(tacls, clkrate), twrph0, to_ns(twrph0, clkrate), twrph1, to_ns(twrph1, clkrate)); 211 tacls, to_ns(tacls, clkrate), twrph0, to_ns(twrph0, clkrate), twrph1, to_ns(twrph1, clkrate));
204 212
205 if (!info->is_s3c2440) { 213 switch (info->cpu_type) {
214 case TYPE_S3C2410:
206 cfg = S3C2410_NFCONF_EN; 215 cfg = S3C2410_NFCONF_EN;
207 cfg |= S3C2410_NFCONF_TACLS(tacls - 1); 216 cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
208 cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1); 217 cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
209 cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1); 218 cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
210 } else { 219 break;
220
221 case TYPE_S3C2440:
222 case TYPE_S3C2412:
211 cfg = S3C2440_NFCONF_TACLS(tacls - 1); 223 cfg = S3C2440_NFCONF_TACLS(tacls - 1);
212 cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1); 224 cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
213 cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1); 225 cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
214 226
215 /* enable the controller and de-assert nFCE */ 227 /* enable the controller and de-assert nFCE */
216 228
217 writel(S3C2440_NFCONT_ENABLE | S3C2440_NFCONT_ENABLE, 229 writel(S3C2440_NFCONT_ENABLE, info->regs + S3C2440_NFCONT);
218 info->regs + S3C2440_NFCONT);
219 } 230 }
220 231
221 pr_debug(PFX "NF_CONF is 0x%lx\n", cfg); 232 dev_dbg(info->device, "NF_CONF is 0x%lx\n", cfg);
222 233
223 writel(cfg, info->regs + S3C2410_NFCONF); 234 writel(cfg, info->regs + S3C2410_NFCONF);
224 return 0; 235 return 0;
@@ -231,26 +242,21 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
231 struct s3c2410_nand_info *info; 242 struct s3c2410_nand_info *info;
232 struct s3c2410_nand_mtd *nmtd; 243 struct s3c2410_nand_mtd *nmtd;
233 struct nand_chip *this = mtd->priv; 244 struct nand_chip *this = mtd->priv;
234 void __iomem *reg;
235 unsigned long cur; 245 unsigned long cur;
236 unsigned long bit;
237 246
238 nmtd = this->priv; 247 nmtd = this->priv;
239 info = nmtd->info; 248 info = nmtd->info;
240 249
241 bit = (info->is_s3c2440) ? S3C2440_NFCONT_nFCE : S3C2410_NFCONF_nFCE;
242 reg = info->regs + ((info->is_s3c2440) ? S3C2440_NFCONT : S3C2410_NFCONF);
243
244 if (chip != -1 && allow_clk_stop(info)) 250 if (chip != -1 && allow_clk_stop(info))
245 clk_enable(info->clk); 251 clk_enable(info->clk);
246 252
247 cur = readl(reg); 253 cur = readl(info->sel_reg);
248 254
249 if (chip == -1) { 255 if (chip == -1) {
250 cur |= bit; 256 cur |= info->sel_bit;
251 } else { 257 } else {
252 if (nmtd->set != NULL && chip > nmtd->set->nr_chips) { 258 if (nmtd->set != NULL && chip > nmtd->set->nr_chips) {
253 printk(KERN_ERR PFX "chip %d out of range\n", chip); 259 dev_err(info->device, "invalid chip %d\n", chip);
254 return; 260 return;
255 } 261 }
256 262
@@ -259,10 +265,10 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
259 (info->platform->select_chip) (nmtd->set, chip); 265 (info->platform->select_chip) (nmtd->set, chip);
260 } 266 }
261 267
262 cur &= ~bit; 268 cur &= ~info->sel_bit;
263 } 269 }
264 270
265 writel(cur, reg); 271 writel(cur, info->sel_reg);
266 272
267 if (chip == -1 && allow_clk_stop(info)) 273 if (chip == -1 && allow_clk_stop(info))
268 clk_disable(info->clk); 274 clk_disable(info->clk);
@@ -311,15 +317,25 @@ static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd,
311static int s3c2410_nand_devready(struct mtd_info *mtd) 317static int s3c2410_nand_devready(struct mtd_info *mtd)
312{ 318{
313 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); 319 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
314
315 if (info->is_s3c2440)
316 return readb(info->regs + S3C2440_NFSTAT) & S3C2440_NFSTAT_READY;
317 return readb(info->regs + S3C2410_NFSTAT) & S3C2410_NFSTAT_BUSY; 320 return readb(info->regs + S3C2410_NFSTAT) & S3C2410_NFSTAT_BUSY;
318} 321}
319 322
323static int s3c2440_nand_devready(struct mtd_info *mtd)
324{
325 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
326 return readb(info->regs + S3C2440_NFSTAT) & S3C2440_NFSTAT_READY;
327}
328
329static int s3c2412_nand_devready(struct mtd_info *mtd)
330{
331 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
332 return readb(info->regs + S3C2412_NFSTAT) & S3C2412_NFSTAT_READY;
333}
334
320/* ECC handling functions */ 335/* ECC handling functions */
321 336
322static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) 337static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
338 u_char *read_ecc, u_char *calc_ecc)
323{ 339{
324 pr_debug("s3c2410_nand_correct_data(%p,%p,%p,%p)\n", mtd, dat, read_ecc, calc_ecc); 340 pr_debug("s3c2410_nand_correct_data(%p,%p,%p,%p)\n", mtd, dat, read_ecc, calc_ecc);
325 341
@@ -487,11 +503,8 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
487 struct s3c2410_nand_set *set) 503 struct s3c2410_nand_set *set)
488{ 504{
489 struct nand_chip *chip = &nmtd->chip; 505 struct nand_chip *chip = &nmtd->chip;
506 void __iomem *regs = info->regs;
490 507
491 chip->IO_ADDR_R = info->regs + S3C2410_NFDATA;
492 chip->IO_ADDR_W = info->regs + S3C2410_NFDATA;
493 chip->cmd_ctrl = s3c2410_nand_hwcontrol;
494 chip->dev_ready = s3c2410_nand_devready;
495 chip->write_buf = s3c2410_nand_write_buf; 508 chip->write_buf = s3c2410_nand_write_buf;
496 chip->read_buf = s3c2410_nand_read_buf; 509 chip->read_buf = s3c2410_nand_read_buf;
497 chip->select_chip = s3c2410_nand_select_chip; 510 chip->select_chip = s3c2410_nand_select_chip;
@@ -500,11 +513,37 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
500 chip->options = 0; 513 chip->options = 0;
501 chip->controller = &info->controller; 514 chip->controller = &info->controller;
502 515
503 if (info->is_s3c2440) { 516 switch (info->cpu_type) {
504 chip->IO_ADDR_R = info->regs + S3C2440_NFDATA; 517 case TYPE_S3C2410:
505 chip->IO_ADDR_W = info->regs + S3C2440_NFDATA; 518 chip->IO_ADDR_W = regs + S3C2410_NFDATA;
506 chip->cmd_ctrl = s3c2440_nand_hwcontrol; 519 info->sel_reg = regs + S3C2410_NFCONF;
507 } 520 info->sel_bit = S3C2410_NFCONF_nFCE;
521 chip->cmd_ctrl = s3c2410_nand_hwcontrol;
522 chip->dev_ready = s3c2410_nand_devready;
523 break;
524
525 case TYPE_S3C2440:
526 chip->IO_ADDR_W = regs + S3C2440_NFDATA;
527 info->sel_reg = regs + S3C2440_NFCONT;
528 info->sel_bit = S3C2440_NFCONT_nFCE;
529 chip->cmd_ctrl = s3c2440_nand_hwcontrol;
530 chip->dev_ready = s3c2440_nand_devready;
531 break;
532
533 case TYPE_S3C2412:
534 chip->IO_ADDR_W = regs + S3C2440_NFDATA;
535 info->sel_reg = regs + S3C2440_NFCONT;
536 info->sel_bit = S3C2412_NFCONT_nFCE0;
537 chip->cmd_ctrl = s3c2440_nand_hwcontrol;
538 chip->dev_ready = s3c2412_nand_devready;
539
540 if (readl(regs + S3C2410_NFCONF) & S3C2412_NFCONF_NANDBOOT)
541 dev_info(info->device, "System booted from NAND\n");
542
543 break;
544 }
545
546 chip->IO_ADDR_R = chip->IO_ADDR_W;
508 547
509 nmtd->info = info; 548 nmtd->info = info;
510 nmtd->mtd.priv = chip; 549 nmtd->mtd.priv = chip;
@@ -512,17 +551,25 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
512 nmtd->set = set; 551 nmtd->set = set;
513 552
514 if (hardware_ecc) { 553 if (hardware_ecc) {
515 chip->ecc.correct = s3c2410_nand_correct_data;
516 chip->ecc.hwctl = s3c2410_nand_enable_hwecc;
517 chip->ecc.calculate = s3c2410_nand_calculate_ecc; 554 chip->ecc.calculate = s3c2410_nand_calculate_ecc;
555 chip->ecc.correct = s3c2410_nand_correct_data;
518 chip->ecc.mode = NAND_ECC_HW; 556 chip->ecc.mode = NAND_ECC_HW;
519 chip->ecc.size = 512; 557 chip->ecc.size = 512;
520 chip->ecc.bytes = 3; 558 chip->ecc.bytes = 3;
521 chip->ecc.layout = &nand_hw_eccoob; 559 chip->ecc.layout = &nand_hw_eccoob;
522 560
523 if (info->is_s3c2440) { 561 switch (info->cpu_type) {
524 chip->ecc.hwctl = s3c2440_nand_enable_hwecc; 562 case TYPE_S3C2410:
525 chip->ecc.calculate = s3c2440_nand_calculate_ecc; 563 chip->ecc.hwctl = s3c2410_nand_enable_hwecc;
564 chip->ecc.calculate = s3c2410_nand_calculate_ecc;
565 break;
566
567 case TYPE_S3C2412:
568 case TYPE_S3C2440:
569 chip->ecc.hwctl = s3c2440_nand_enable_hwecc;
570 chip->ecc.calculate = s3c2440_nand_calculate_ecc;
571 break;
572
526 } 573 }
527 } else { 574 } else {
528 chip->ecc.mode = NAND_ECC_SOFT; 575 chip->ecc.mode = NAND_ECC_SOFT;
@@ -537,7 +584,8 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
537 * nand layer to look for devices 584 * nand layer to look for devices
538*/ 585*/
539 586
540static int s3c24xx_nand_probe(struct platform_device *pdev, int is_s3c2440) 587static int s3c24xx_nand_probe(struct platform_device *pdev,
588 enum s3c_cpu_type cpu_type)
541{ 589{
542 struct s3c2410_platform_nand *plat = to_nand_plat(pdev); 590 struct s3c2410_platform_nand *plat = to_nand_plat(pdev);
543 struct s3c2410_nand_info *info; 591 struct s3c2410_nand_info *info;
@@ -592,7 +640,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev, int is_s3c2440)
592 info->device = &pdev->dev; 640 info->device = &pdev->dev;
593 info->platform = plat; 641 info->platform = plat;
594 info->regs = ioremap(res->start, size); 642 info->regs = ioremap(res->start, size);
595 info->is_s3c2440 = is_s3c2440; 643 info->cpu_type = cpu_type;
596 644
597 if (info->regs == NULL) { 645 if (info->regs == NULL) {
598 dev_err(&pdev->dev, "cannot reserve register region\n"); 646 dev_err(&pdev->dev, "cannot reserve register region\n");
@@ -699,12 +747,17 @@ static int s3c24xx_nand_resume(struct platform_device *dev)
699 747
700static int s3c2410_nand_probe(struct platform_device *dev) 748static int s3c2410_nand_probe(struct platform_device *dev)
701{ 749{
702 return s3c24xx_nand_probe(dev, 0); 750 return s3c24xx_nand_probe(dev, TYPE_S3C2410);
703} 751}
704 752
705static int s3c2440_nand_probe(struct platform_device *dev) 753static int s3c2440_nand_probe(struct platform_device *dev)
706{ 754{
707 return s3c24xx_nand_probe(dev, 1); 755 return s3c24xx_nand_probe(dev, TYPE_S3C2440);
756}
757
758static int s3c2412_nand_probe(struct platform_device *dev)
759{
760 return s3c24xx_nand_probe(dev, TYPE_S3C2412);
708} 761}
709 762
710static struct platform_driver s3c2410_nand_driver = { 763static struct platform_driver s3c2410_nand_driver = {
@@ -729,16 +782,29 @@ static struct platform_driver s3c2440_nand_driver = {
729 }, 782 },
730}; 783};
731 784
785static struct platform_driver s3c2412_nand_driver = {
786 .probe = s3c2412_nand_probe,
787 .remove = s3c2410_nand_remove,
788 .suspend = s3c24xx_nand_suspend,
789 .resume = s3c24xx_nand_resume,
790 .driver = {
791 .name = "s3c2412-nand",
792 .owner = THIS_MODULE,
793 },
794};
795
732static int __init s3c2410_nand_init(void) 796static int __init s3c2410_nand_init(void)
733{ 797{
734 printk("S3C24XX NAND Driver, (c) 2004 Simtec Electronics\n"); 798 printk("S3C24XX NAND Driver, (c) 2004 Simtec Electronics\n");
735 799
800 platform_driver_register(&s3c2412_nand_driver);
736 platform_driver_register(&s3c2440_nand_driver); 801 platform_driver_register(&s3c2440_nand_driver);
737 return platform_driver_register(&s3c2410_nand_driver); 802 return platform_driver_register(&s3c2410_nand_driver);
738} 803}
739 804
740static void __exit s3c2410_nand_exit(void) 805static void __exit s3c2410_nand_exit(void)
741{ 806{
807 platform_driver_unregister(&s3c2412_nand_driver);
742 platform_driver_unregister(&s3c2440_nand_driver); 808 platform_driver_unregister(&s3c2440_nand_driver);
743 platform_driver_unregister(&s3c2410_nand_driver); 809 platform_driver_unregister(&s3c2410_nand_driver);
744} 810}
diff --git a/drivers/mtd/nand/ts7250.c b/drivers/mtd/nand/ts7250.c
index a0b4b1edcb0d..f40081069ab2 100644
--- a/drivers/mtd/nand/ts7250.c
+++ b/drivers/mtd/nand/ts7250.c
@@ -97,7 +97,7 @@ static void ts7250_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
97 unsigned long addr = TS72XX_NAND_CONTROL_VIRT_BASE; 97 unsigned long addr = TS72XX_NAND_CONTROL_VIRT_BASE;
98 unsigned char bits; 98 unsigned char bits;
99 99
100 bits = (ctrl & NAND_CNE) << 2; 100 bits = (ctrl & NAND_NCE) << 2;
101 bits |= ctrl & NAND_CLE; 101 bits |= ctrl & NAND_CLE;
102 bits |= (ctrl & NAND_ALE) >> 2; 102 bits |= (ctrl & NAND_ALE) >> 2;
103 103
diff --git a/fs/Kconfig b/fs/Kconfig
index 00aa3d5c5a83..6dc8cfd6d80c 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1116,7 +1116,7 @@ config JFFS2_SUMMARY
1116 1116
1117config JFFS2_FS_XATTR 1117config JFFS2_FS_XATTR
1118 bool "JFFS2 XATTR support (EXPERIMENTAL)" 1118 bool "JFFS2 XATTR support (EXPERIMENTAL)"
1119 depends on JFFS2_FS && EXPERIMENTAL && !JFFS2_FS_WRITEBUFFER 1119 depends on JFFS2_FS && EXPERIMENTAL
1120 default n 1120 default n
1121 help 1121 help
1122 Extended attributes are name:value pairs associated with inodes by 1122 Extended attributes are name:value pairs associated with inodes by
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index 320dd48b834e..9c2077e7e081 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -267,6 +267,8 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
267 } 267 }
268 268
269 rc = do_jffs2_setxattr(inode, xprefix, "", value, size, 0); 269 rc = do_jffs2_setxattr(inode, xprefix, "", value, size, 0);
270 if (!value && rc == -ENODATA)
271 rc = 0;
270 if (value) 272 if (value)
271 kfree(value); 273 kfree(value);
272 if (!rc) { 274 if (!rc) {
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index b8886f048eaa..ad0121088dde 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -225,7 +225,6 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
225 at the end of the linked list. Stash it and continue 225 at the end of the linked list. Stash it and continue
226 from the beginning of the list */ 226 from the beginning of the list */
227 ic = (struct jffs2_inode_cache *)(*prev); 227 ic = (struct jffs2_inode_cache *)(*prev);
228 BUG_ON(ic->class != RAWNODE_CLASS_INODE_CACHE);
229 prev = &ic->nodes; 228 prev = &ic->nodes;
230 continue; 229 continue;
231 } 230 }
@@ -249,7 +248,8 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
249 248
250 /* PARANOIA */ 249 /* PARANOIA */
251 if (!ic) { 250 if (!ic) {
252 printk(KERN_WARNING "inode_cache not found in remove_node_refs()!!\n"); 251 JFFS2_WARNING("inode_cache/xattr_datum/xattr_ref"
252 " not found in remove_node_refs()!!\n");
253 return; 253 return;
254 } 254 }
255 255
@@ -274,8 +274,19 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
274 printk("\n"); 274 printk("\n");
275 }); 275 });
276 276
277 if (ic->nodes == (void *)ic && ic->nlink == 0) 277 switch (ic->class) {
278 jffs2_del_ino_cache(c, ic); 278#ifdef CONFIG_JFFS2_FS_XATTR
279 case RAWNODE_CLASS_XATTR_DATUM:
280 jffs2_release_xattr_datum(c, (struct jffs2_xattr_datum *)ic);
281 break;
282 case RAWNODE_CLASS_XATTR_REF:
283 jffs2_release_xattr_ref(c, (struct jffs2_xattr_ref *)ic);
284 break;
285#endif
286 default:
287 if (ic->nodes == (void *)ic && ic->nlink == 0)
288 jffs2_del_ino_cache(c, ic);
289 }
279} 290}
280 291
281void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) 292void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 2900ec3ec3af..97caa77d60cf 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -227,8 +227,6 @@ void jffs2_clear_inode (struct inode *inode)
227 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); 227 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
228 228
229 D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode)); 229 D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode));
230
231 jffs2_xattr_delete_inode(c, f->inocache);
232 jffs2_do_clear_inode(c, f); 230 jffs2_do_clear_inode(c, f);
233} 231}
234 232
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 477c526d638b..daff3341ff92 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -165,6 +165,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
165 D1(printk(KERN_DEBUG "Skipping check of ino #%d with nlink zero\n", 165 D1(printk(KERN_DEBUG "Skipping check of ino #%d with nlink zero\n",
166 ic->ino)); 166 ic->ino));
167 spin_unlock(&c->inocache_lock); 167 spin_unlock(&c->inocache_lock);
168 jffs2_xattr_delete_inode(c, ic);
168 continue; 169 continue;
169 } 170 }
170 switch(ic->state) { 171 switch(ic->state) {
@@ -275,13 +276,12 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
275 * We can decide whether this node is inode or xattr by ic->class. */ 276 * We can decide whether this node is inode or xattr by ic->class. */
276 if (ic->class == RAWNODE_CLASS_XATTR_DATUM 277 if (ic->class == RAWNODE_CLASS_XATTR_DATUM
277 || ic->class == RAWNODE_CLASS_XATTR_REF) { 278 || ic->class == RAWNODE_CLASS_XATTR_REF) {
278 BUG_ON(raw->next_in_ino != (void *)ic);
279 spin_unlock(&c->erase_completion_lock); 279 spin_unlock(&c->erase_completion_lock);
280 280
281 if (ic->class == RAWNODE_CLASS_XATTR_DATUM) { 281 if (ic->class == RAWNODE_CLASS_XATTR_DATUM) {
282 ret = jffs2_garbage_collect_xattr_datum(c, (struct jffs2_xattr_datum *)ic); 282 ret = jffs2_garbage_collect_xattr_datum(c, (struct jffs2_xattr_datum *)ic, raw);
283 } else { 283 } else {
284 ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic); 284 ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic, raw);
285 } 285 }
286 goto release_sem; 286 goto release_sem;
287 } 287 }
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
index 935fec1b1201..b98594992eed 100644
--- a/fs/jffs2/jffs2_fs_sb.h
+++ b/fs/jffs2/jffs2_fs_sb.h
@@ -119,8 +119,11 @@ struct jffs2_sb_info {
119#ifdef CONFIG_JFFS2_FS_XATTR 119#ifdef CONFIG_JFFS2_FS_XATTR
120#define XATTRINDEX_HASHSIZE (57) 120#define XATTRINDEX_HASHSIZE (57)
121 uint32_t highest_xid; 121 uint32_t highest_xid;
122 uint32_t highest_xseqno;
122 struct list_head xattrindex[XATTRINDEX_HASHSIZE]; 123 struct list_head xattrindex[XATTRINDEX_HASHSIZE];
123 struct list_head xattr_unchecked; 124 struct list_head xattr_unchecked;
125 struct list_head xattr_dead_list;
126 struct jffs2_xattr_ref *xref_dead_list;
124 struct jffs2_xattr_ref *xref_temp; 127 struct jffs2_xattr_ref *xref_temp;
125 struct rw_semaphore xattr_sem; 128 struct rw_semaphore xattr_sem;
126 uint32_t xdatum_mem_usage; 129 uint32_t xdatum_mem_usage;
diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c
index 4889d0700c0e..8310c95478e9 100644
--- a/fs/jffs2/malloc.c
+++ b/fs/jffs2/malloc.c
@@ -291,6 +291,7 @@ struct jffs2_xattr_datum *jffs2_alloc_xattr_datum(void)
291 291
292 memset(xd, 0, sizeof(struct jffs2_xattr_datum)); 292 memset(xd, 0, sizeof(struct jffs2_xattr_datum));
293 xd->class = RAWNODE_CLASS_XATTR_DATUM; 293 xd->class = RAWNODE_CLASS_XATTR_DATUM;
294 xd->node = (void *)xd;
294 INIT_LIST_HEAD(&xd->xindex); 295 INIT_LIST_HEAD(&xd->xindex);
295 return xd; 296 return xd;
296} 297}
@@ -309,6 +310,7 @@ struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void)
309 310
310 memset(ref, 0, sizeof(struct jffs2_xattr_ref)); 311 memset(ref, 0, sizeof(struct jffs2_xattr_ref));
311 ref->class = RAWNODE_CLASS_XATTR_REF; 312 ref->class = RAWNODE_CLASS_XATTR_REF;
313 ref->node = (void *)ref;
312 return ref; 314 return ref;
313} 315}
314 316
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index 927dfe42ba76..7675b33396c7 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -906,6 +906,9 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old)
906{ 906{
907 struct jffs2_inode_cache **prev; 907 struct jffs2_inode_cache **prev;
908 908
909#ifdef CONFIG_JFFS2_FS_XATTR
910 BUG_ON(old->xref);
911#endif
909 dbg_inocache("del %p (ino #%u)\n", old, old->ino); 912 dbg_inocache("del %p (ino #%u)\n", old, old->ino);
910 spin_lock(&c->inocache_lock); 913 spin_lock(&c->inocache_lock);
911 914
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index ac0c350ed7d7..d88376992ed9 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -683,19 +683,26 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
683 spin_lock(&c->erase_completion_lock); 683 spin_lock(&c->erase_completion_lock);
684 684
685 ic = jffs2_raw_ref_to_ic(ref); 685 ic = jffs2_raw_ref_to_ic(ref);
686 /* It seems we should never call jffs2_mark_node_obsolete() for
687 XATTR nodes.... yet. Make sure we notice if/when we change
688 that :) */
689 BUG_ON(ic->class != RAWNODE_CLASS_INODE_CACHE);
690 for (p = &ic->nodes; (*p) != ref; p = &((*p)->next_in_ino)) 686 for (p = &ic->nodes; (*p) != ref; p = &((*p)->next_in_ino))
691 ; 687 ;
692 688
693 *p = ref->next_in_ino; 689 *p = ref->next_in_ino;
694 ref->next_in_ino = NULL; 690 ref->next_in_ino = NULL;
695 691
696 if (ic->nodes == (void *)ic && ic->nlink == 0) 692 switch (ic->class) {
697 jffs2_del_ino_cache(c, ic); 693#ifdef CONFIG_JFFS2_FS_XATTR
698 694 case RAWNODE_CLASS_XATTR_DATUM:
695 jffs2_release_xattr_datum(c, (struct jffs2_xattr_datum *)ic);
696 break;
697 case RAWNODE_CLASS_XATTR_REF:
698 jffs2_release_xattr_ref(c, (struct jffs2_xattr_ref *)ic);
699 break;
700#endif
701 default:
702 if (ic->nodes == (void *)ic && ic->nlink == 0)
703 jffs2_del_ino_cache(c, ic);
704 break;
705 }
699 spin_unlock(&c->erase_completion_lock); 706 spin_unlock(&c->erase_completion_lock);
700 } 707 }
701 708
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 5fec012b02ed..cc1899268c43 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -968,6 +968,7 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
968 struct jffs2_full_dirent *fd, *fds; 968 struct jffs2_full_dirent *fd, *fds;
969 int deleted; 969 int deleted;
970 970
971 jffs2_xattr_delete_inode(c, f->inocache);
971 down(&f->sem); 972 down(&f->sem);
972 deleted = f->inocache && !f->inocache->nlink; 973 deleted = f->inocache && !f->inocache->nlink;
973 974
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 61618080b86f..2bfdc33752d3 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -317,20 +317,23 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
317 struct jffs2_summary *s) 317 struct jffs2_summary *s)
318{ 318{
319 struct jffs2_xattr_datum *xd; 319 struct jffs2_xattr_datum *xd;
320 uint32_t totlen, crc; 320 uint32_t xid, version, totlen, crc;
321 int err; 321 int err;
322 322
323 crc = crc32(0, rx, sizeof(struct jffs2_raw_xattr) - 4); 323 crc = crc32(0, rx, sizeof(struct jffs2_raw_xattr) - 4);
324 if (crc != je32_to_cpu(rx->node_crc)) { 324 if (crc != je32_to_cpu(rx->node_crc)) {
325 if (je32_to_cpu(rx->node_crc) != 0xffffffff) 325 JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
326 JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", 326 ofs, je32_to_cpu(rx->node_crc), crc);
327 ofs, je32_to_cpu(rx->node_crc), crc);
328 if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen)))) 327 if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen))))
329 return err; 328 return err;
330 return 0; 329 return 0;
331 } 330 }
332 331
333 totlen = PAD(sizeof(*rx) + rx->name_len + 1 + je16_to_cpu(rx->value_len)); 332 xid = je32_to_cpu(rx->xid);
333 version = je32_to_cpu(rx->version);
334
335 totlen = PAD(sizeof(struct jffs2_raw_xattr)
336 + rx->name_len + 1 + je16_to_cpu(rx->value_len));
334 if (totlen != je32_to_cpu(rx->totlen)) { 337 if (totlen != je32_to_cpu(rx->totlen)) {
335 JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u\n", 338 JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u\n",
336 ofs, je32_to_cpu(rx->totlen), totlen); 339 ofs, je32_to_cpu(rx->totlen), totlen);
@@ -339,22 +342,24 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
339 return 0; 342 return 0;
340 } 343 }
341 344
342 xd = jffs2_setup_xattr_datum(c, je32_to_cpu(rx->xid), je32_to_cpu(rx->version)); 345 xd = jffs2_setup_xattr_datum(c, xid, version);
343 if (IS_ERR(xd)) { 346 if (IS_ERR(xd))
344 if (PTR_ERR(xd) == -EEXIST) {
345 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rx->totlen)))))
346 return err;
347 return 0;
348 }
349 return PTR_ERR(xd); 347 return PTR_ERR(xd);
350 }
351 xd->xprefix = rx->xprefix;
352 xd->name_len = rx->name_len;
353 xd->value_len = je16_to_cpu(rx->value_len);
354 xd->data_crc = je32_to_cpu(rx->data_crc);
355 348
356 xd->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, NULL); 349 if (xd->version > version) {
357 /* FIXME */ xd->node->next_in_ino = (void *)xd; 350 struct jffs2_raw_node_ref *raw
351 = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, NULL);
352 raw->next_in_ino = xd->node->next_in_ino;
353 xd->node->next_in_ino = raw;
354 } else {
355 xd->version = version;
356 xd->xprefix = rx->xprefix;
357 xd->name_len = rx->name_len;
358 xd->value_len = je16_to_cpu(rx->value_len);
359 xd->data_crc = je32_to_cpu(rx->data_crc);
360
361 jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, (void *)xd);
362 }
358 363
359 if (jffs2_sum_active()) 364 if (jffs2_sum_active())
360 jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset); 365 jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset);
@@ -373,9 +378,8 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock
373 378
374 crc = crc32(0, rr, sizeof(*rr) - 4); 379 crc = crc32(0, rr, sizeof(*rr) - 4);
375 if (crc != je32_to_cpu(rr->node_crc)) { 380 if (crc != je32_to_cpu(rr->node_crc)) {
376 if (je32_to_cpu(rr->node_crc) != 0xffffffff) 381 JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
377 JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", 382 ofs, je32_to_cpu(rr->node_crc), crc);
378 ofs, je32_to_cpu(rr->node_crc), crc);
379 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rr->totlen))))) 383 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rr->totlen)))))
380 return err; 384 return err;
381 return 0; 385 return 0;
@@ -395,6 +399,7 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock
395 return -ENOMEM; 399 return -ENOMEM;
396 400
397 /* BEFORE jffs2_build_xattr_subsystem() called, 401 /* BEFORE jffs2_build_xattr_subsystem() called,
402 * and AFTER xattr_ref is marked as a dead xref,
398 * ref->xid is used to store 32bit xid, xd is not used 403 * ref->xid is used to store 32bit xid, xd is not used
399 * ref->ino is used to store 32bit inode-number, ic is not used 404 * ref->ino is used to store 32bit inode-number, ic is not used
400 * Thoes variables are declared as union, thus using those 405 * Thoes variables are declared as union, thus using those
@@ -404,11 +409,13 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock
404 */ 409 */
405 ref->ino = je32_to_cpu(rr->ino); 410 ref->ino = je32_to_cpu(rr->ino);
406 ref->xid = je32_to_cpu(rr->xid); 411 ref->xid = je32_to_cpu(rr->xid);
412 ref->xseqno = je32_to_cpu(rr->xseqno);
413 if (ref->xseqno > c->highest_xseqno)
414 c->highest_xseqno = (ref->xseqno & ~XREF_DELETE_MARKER);
407 ref->next = c->xref_temp; 415 ref->next = c->xref_temp;
408 c->xref_temp = ref; 416 c->xref_temp = ref;
409 417
410 ref->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rr->totlen)), NULL); 418 jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rr->totlen)), (void *)ref);
411 /* FIXME */ ref->node->next_in_ino = (void *)ref;
412 419
413 if (jffs2_sum_active()) 420 if (jffs2_sum_active())
414 jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset); 421 jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset);
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index be1acc3dad97..c19bd476e8ec 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -5,7 +5,7 @@
5 * Zoltan Sogor <weth@inf.u-szeged.hu>, 5 * Zoltan Sogor <weth@inf.u-szeged.hu>,
6 * Patrik Kluba <pajko@halom.u-szeged.hu>, 6 * Patrik Kluba <pajko@halom.u-szeged.hu>,
7 * University of Szeged, Hungary 7 * University of Szeged, Hungary
8 * 2005 KaiGai Kohei <kaigai@ak.jp.nec.com> 8 * 2006 KaiGai Kohei <kaigai@ak.jp.nec.com>
9 * 9 *
10 * For licensing information, see the file 'LICENCE' in this directory. 10 * For licensing information, see the file 'LICENCE' in this directory.
11 * 11 *
@@ -310,8 +310,6 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs,
310#ifdef CONFIG_JFFS2_FS_XATTR 310#ifdef CONFIG_JFFS2_FS_XATTR
311 case JFFS2_NODETYPE_XATTR: { 311 case JFFS2_NODETYPE_XATTR: {
312 struct jffs2_sum_xattr_mem *temp; 312 struct jffs2_sum_xattr_mem *temp;
313 if (je32_to_cpu(node->x.version) == 0xffffffff)
314 return 0;
315 temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL); 313 temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL);
316 if (!temp) 314 if (!temp)
317 goto no_mem; 315 goto no_mem;
@@ -327,10 +325,6 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs,
327 } 325 }
328 case JFFS2_NODETYPE_XREF: { 326 case JFFS2_NODETYPE_XREF: {
329 struct jffs2_sum_xref_mem *temp; 327 struct jffs2_sum_xref_mem *temp;
330
331 if (je32_to_cpu(node->r.ino) == 0xffffffff
332 && je32_to_cpu(node->r.xid) == 0xffffffff)
333 return 0;
334 temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL); 328 temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL);
335 if (!temp) 329 if (!temp)
336 goto no_mem; 330 goto no_mem;
@@ -483,22 +477,20 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
483 477
484 xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid), 478 xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid),
485 je32_to_cpu(spx->version)); 479 je32_to_cpu(spx->version));
486 if (IS_ERR(xd)) { 480 if (IS_ERR(xd))
487 if (PTR_ERR(xd) == -EEXIST) {
488 /* a newer version of xd exists */
489 if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(spx->totlen))))
490 return err;
491 sp += JFFS2_SUMMARY_XATTR_SIZE;
492 break;
493 }
494 JFFS2_NOTICE("allocation of xattr_datum failed\n");
495 return PTR_ERR(xd); 481 return PTR_ERR(xd);
482 if (xd->version > je32_to_cpu(spx->version)) {
483 /* node is not the newest one */
484 struct jffs2_raw_node_ref *raw
485 = sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED,
486 PAD(je32_to_cpu(spx->totlen)), NULL);
487 raw->next_in_ino = xd->node->next_in_ino;
488 xd->node->next_in_ino = raw;
489 } else {
490 xd->version = je32_to_cpu(spx->version);
491 sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED,
492 PAD(je32_to_cpu(spx->totlen)), (void *)xd);
496 } 493 }
497
498 xd->node = sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED,
499 PAD(je32_to_cpu(spx->totlen)), NULL);
500 /* FIXME */ xd->node->next_in_ino = (void *)xd;
501
502 *pseudo_random += je32_to_cpu(spx->xid); 494 *pseudo_random += je32_to_cpu(spx->xid);
503 sp += JFFS2_SUMMARY_XATTR_SIZE; 495 sp += JFFS2_SUMMARY_XATTR_SIZE;
504 496
@@ -519,14 +511,11 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
519 JFFS2_NOTICE("allocation of xattr_datum failed\n"); 511 JFFS2_NOTICE("allocation of xattr_datum failed\n");
520 return -ENOMEM; 512 return -ENOMEM;
521 } 513 }
522 ref->ino = 0xfffffffe;
523 ref->xid = 0xfffffffd;
524 ref->next = c->xref_temp; 514 ref->next = c->xref_temp;
525 c->xref_temp = ref; 515 c->xref_temp = ref;
526 516
527 ref->node = sum_link_node_ref(c, jeb, je32_to_cpu(spr->offset) | REF_UNCHECKED, 517 sum_link_node_ref(c, jeb, je32_to_cpu(spr->offset) | REF_UNCHECKED,
528 PAD(sizeof(struct jffs2_raw_xref)), NULL); 518 PAD(sizeof(struct jffs2_raw_xref)), (void *)ref);
529 /* FIXME */ ref->node->next_in_ino = (void *)ref;
530 519
531 *pseudo_random += ref->node->flash_offset; 520 *pseudo_random += ref->node->flash_offset;
532 sp += JFFS2_SUMMARY_XREF_SIZE; 521 sp += JFFS2_SUMMARY_XREF_SIZE;
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
index 2d82e250be34..18e66dbf23b4 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -23,18 +23,15 @@
23 * xattr_datum_hashkey(xprefix, xname, xvalue, xsize) 23 * xattr_datum_hashkey(xprefix, xname, xvalue, xsize)
24 * is used to calcurate xdatum hashkey. The reminder of hashkey into XATTRINDEX_HASHSIZE is 24 * is used to calcurate xdatum hashkey. The reminder of hashkey into XATTRINDEX_HASHSIZE is
25 * the index of the xattr name/value pair cache (c->xattrindex). 25 * the index of the xattr name/value pair cache (c->xattrindex).
26 * is_xattr_datum_unchecked(c, xd)
27 * returns 1, if xdatum contains any unchecked raw nodes. if all raw nodes are not
28 * unchecked, it returns 0.
26 * unload_xattr_datum(c, xd) 29 * unload_xattr_datum(c, xd)
27 * is used to release xattr name/value pair and detach from c->xattrindex. 30 * is used to release xattr name/value pair and detach from c->xattrindex.
28 * reclaim_xattr_datum(c) 31 * reclaim_xattr_datum(c)
29 * is used to reclaim xattr name/value pairs on the xattr name/value pair cache when 32 * is used to reclaim xattr name/value pairs on the xattr name/value pair cache when
30 * memory usage by cache is over c->xdatum_mem_threshold. Currentry, this threshold 33 * memory usage by cache is over c->xdatum_mem_threshold. Currentry, this threshold
31 * is hard coded as 32KiB. 34 * is hard coded as 32KiB.
32 * delete_xattr_datum_node(c, xd)
33 * is used to delete a jffs2 node is dominated by xdatum. When EBS(Erase Block Summary) is
34 * enabled, it overwrites the obsolete node by myself.
35 * delete_xattr_datum(c, xd)
36 * is used to delete jffs2_xattr_datum object. It must be called with 0-value of reference
37 * counter. (It means how many jffs2_xattr_ref object refers this xdatum.)
38 * do_verify_xattr_datum(c, xd) 35 * do_verify_xattr_datum(c, xd)
39 * is used to load the xdatum informations without name/value pair from the medium. 36 * is used to load the xdatum informations without name/value pair from the medium.
40 * It's necessary once, because those informations are not collected during mounting 37 * It's necessary once, because those informations are not collected during mounting
@@ -53,8 +50,10 @@
53 * is used to write xdatum to medium. xd->version will be incremented. 50 * is used to write xdatum to medium. xd->version will be incremented.
54 * create_xattr_datum(c, xprefix, xname, xvalue, xsize) 51 * create_xattr_datum(c, xprefix, xname, xvalue, xsize)
55 * is used to create new xdatum and write to medium. 52 * is used to create new xdatum and write to medium.
53 * delete_xattr_datum(c, xd)
54 * is used to delete a xdatum. It marks xd JFFS2_XFLAGS_DEAD, and allows
55 * GC to reclaim those physical nodes.
56 * -------------------------------------------------- */ 56 * -------------------------------------------------- */
57
58static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize) 57static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize)
59{ 58{
60 int name_len = strlen(xname); 59 int name_len = strlen(xname);
@@ -62,6 +61,22 @@ static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *
62 return crc32(xprefix, xname, name_len) ^ crc32(xprefix, xvalue, xsize); 61 return crc32(xprefix, xname, name_len) ^ crc32(xprefix, xvalue, xsize);
63} 62}
64 63
64static int is_xattr_datum_unchecked(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
65{
66 struct jffs2_raw_node_ref *raw;
67 int rc = 0;
68
69 spin_lock(&c->erase_completion_lock);
70 for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
71 if (ref_flags(raw) == REF_UNCHECKED) {
72 rc = 1;
73 break;
74 }
75 }
76 spin_unlock(&c->erase_completion_lock);
77 return rc;
78}
79
65static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) 80static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
66{ 81{
67 /* must be called under down_write(xattr_sem) */ 82 /* must be called under down_write(xattr_sem) */
@@ -107,77 +122,33 @@ static void reclaim_xattr_datum(struct jffs2_sb_info *c)
107 before, c->xdatum_mem_usage, before - c->xdatum_mem_usage); 122 before, c->xdatum_mem_usage, before - c->xdatum_mem_usage);
108} 123}
109 124
110static void delete_xattr_datum_node(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
111{
112 /* must be called under down_write(xattr_sem) */
113 struct jffs2_raw_xattr rx;
114 size_t length;
115 int rc;
116
117 if (!xd->node) {
118 JFFS2_WARNING("xdatum (xid=%u) is removed twice.\n", xd->xid);
119 return;
120 }
121 if (jffs2_sum_active()) {
122 memset(&rx, 0xff, sizeof(struct jffs2_raw_xattr));
123 rc = jffs2_flash_read(c, ref_offset(xd->node),
124 sizeof(struct jffs2_unknown_node),
125 &length, (char *)&rx);
126 if (rc || length != sizeof(struct jffs2_unknown_node)) {
127 JFFS2_ERROR("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n",
128 rc, sizeof(struct jffs2_unknown_node),
129 length, ref_offset(xd->node));
130 }
131 rc = jffs2_flash_write(c, ref_offset(xd->node), sizeof(rx),
132 &length, (char *)&rx);
133 if (rc || length != sizeof(struct jffs2_raw_xattr)) {
134 JFFS2_ERROR("jffs2_flash_write()=%d, req=%zu, wrote=%zu ar %#08x\n",
135 rc, sizeof(rx), length, ref_offset(xd->node));
136 }
137 }
138 spin_lock(&c->erase_completion_lock);
139 xd->node->next_in_ino = NULL;
140 spin_unlock(&c->erase_completion_lock);
141 jffs2_mark_node_obsolete(c, xd->node);
142 xd->node = NULL;
143}
144
145static void delete_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
146{
147 /* must be called under down_write(xattr_sem) */
148 BUG_ON(xd->refcnt);
149
150 unload_xattr_datum(c, xd);
151 if (xd->node) {
152 delete_xattr_datum_node(c, xd);
153 xd->node = NULL;
154 }
155 jffs2_free_xattr_datum(xd);
156}
157
158static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) 125static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
159{ 126{
160 /* must be called under down_write(xattr_sem) */ 127 /* must be called under down_write(xattr_sem) */
161 struct jffs2_eraseblock *jeb; 128 struct jffs2_eraseblock *jeb;
129 struct jffs2_raw_node_ref *raw;
162 struct jffs2_raw_xattr rx; 130 struct jffs2_raw_xattr rx;
163 size_t readlen; 131 size_t readlen;
164 uint32_t crc, totlen; 132 uint32_t crc, offset, totlen;
165 int rc; 133 int rc;
166 134
167 BUG_ON(!xd->node); 135 spin_lock(&c->erase_completion_lock);
168 BUG_ON(ref_flags(xd->node) != REF_UNCHECKED); 136 offset = ref_offset(xd->node);
137 if (ref_flags(xd->node) == REF_PRISTINE)
138 goto complete;
139 spin_unlock(&c->erase_completion_lock);
169 140
170 rc = jffs2_flash_read(c, ref_offset(xd->node), sizeof(rx), &readlen, (char *)&rx); 141 rc = jffs2_flash_read(c, offset, sizeof(rx), &readlen, (char *)&rx);
171 if (rc || readlen != sizeof(rx)) { 142 if (rc || readlen != sizeof(rx)) {
172 JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n", 143 JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n",
173 rc, sizeof(rx), readlen, ref_offset(xd->node)); 144 rc, sizeof(rx), readlen, offset);
174 return rc ? rc : -EIO; 145 return rc ? rc : -EIO;
175 } 146 }
176 crc = crc32(0, &rx, sizeof(rx) - 4); 147 crc = crc32(0, &rx, sizeof(rx) - 4);
177 if (crc != je32_to_cpu(rx.node_crc)) { 148 if (crc != je32_to_cpu(rx.node_crc)) {
178 if (je32_to_cpu(rx.node_crc) != 0xffffffff) 149 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
179 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", 150 offset, je32_to_cpu(rx.hdr_crc), crc);
180 ref_offset(xd->node), je32_to_cpu(rx.hdr_crc), crc); 151 xd->flags |= JFFS2_XFLAGS_INVALID;
181 return EIO; 152 return EIO;
182 } 153 }
183 totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len)); 154 totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len));
@@ -188,11 +159,12 @@ static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_dat
188 || je32_to_cpu(rx.version) != xd->version) { 159 || je32_to_cpu(rx.version) != xd->version) {
189 JFFS2_ERROR("inconsistent xdatum at %#08x, magic=%#04x/%#04x, " 160 JFFS2_ERROR("inconsistent xdatum at %#08x, magic=%#04x/%#04x, "
190 "nodetype=%#04x/%#04x, totlen=%u/%u, xid=%u/%u, version=%u/%u\n", 161 "nodetype=%#04x/%#04x, totlen=%u/%u, xid=%u/%u, version=%u/%u\n",
191 ref_offset(xd->node), je16_to_cpu(rx.magic), JFFS2_MAGIC_BITMASK, 162 offset, je16_to_cpu(rx.magic), JFFS2_MAGIC_BITMASK,
192 je16_to_cpu(rx.nodetype), JFFS2_NODETYPE_XATTR, 163 je16_to_cpu(rx.nodetype), JFFS2_NODETYPE_XATTR,
193 je32_to_cpu(rx.totlen), totlen, 164 je32_to_cpu(rx.totlen), totlen,
194 je32_to_cpu(rx.xid), xd->xid, 165 je32_to_cpu(rx.xid), xd->xid,
195 je32_to_cpu(rx.version), xd->version); 166 je32_to_cpu(rx.version), xd->version);
167 xd->flags |= JFFS2_XFLAGS_INVALID;
196 return EIO; 168 return EIO;
197 } 169 }
198 xd->xprefix = rx.xprefix; 170 xd->xprefix = rx.xprefix;
@@ -200,14 +172,17 @@ static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_dat
200 xd->value_len = je16_to_cpu(rx.value_len); 172 xd->value_len = je16_to_cpu(rx.value_len);
201 xd->data_crc = je32_to_cpu(rx.data_crc); 173 xd->data_crc = je32_to_cpu(rx.data_crc);
202 174
203 /* This JFFS2_NODETYPE_XATTR node is checked */
204 jeb = &c->blocks[ref_offset(xd->node) / c->sector_size];
205 totlen = PAD(je32_to_cpu(rx.totlen));
206
207 spin_lock(&c->erase_completion_lock); 175 spin_lock(&c->erase_completion_lock);
208 c->unchecked_size -= totlen; c->used_size += totlen; 176 complete:
209 jeb->unchecked_size -= totlen; jeb->used_size += totlen; 177 for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
210 xd->node->flash_offset = ref_offset(xd->node) | REF_PRISTINE; 178 jeb = &c->blocks[ref_offset(raw) / c->sector_size];
179 totlen = PAD(ref_totlen(c, jeb, raw));
180 if (ref_flags(raw) == REF_UNCHECKED) {
181 c->unchecked_size -= totlen; c->used_size += totlen;
182 jeb->unchecked_size -= totlen; jeb->used_size += totlen;
183 }
184 raw->flash_offset = ref_offset(raw) | ((xd->node==raw) ? REF_PRISTINE : REF_NORMAL);
185 }
211 spin_unlock(&c->erase_completion_lock); 186 spin_unlock(&c->erase_completion_lock);
212 187
213 /* unchecked xdatum is chained with c->xattr_unchecked */ 188 /* unchecked xdatum is chained with c->xattr_unchecked */
@@ -227,7 +202,6 @@ static int do_load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum
227 uint32_t crc, length; 202 uint32_t crc, length;
228 int i, ret, retry = 0; 203 int i, ret, retry = 0;
229 204
230 BUG_ON(!xd->node);
231 BUG_ON(ref_flags(xd->node) != REF_PRISTINE); 205 BUG_ON(ref_flags(xd->node) != REF_PRISTINE);
232 BUG_ON(!list_empty(&xd->xindex)); 206 BUG_ON(!list_empty(&xd->xindex));
233 retry: 207 retry:
@@ -253,6 +227,7 @@ static int do_load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum
253 " at %#08x, read: 0x%08x calculated: 0x%08x\n", 227 " at %#08x, read: 0x%08x calculated: 0x%08x\n",
254 ref_offset(xd->node), xd->data_crc, crc); 228 ref_offset(xd->node), xd->data_crc, crc);
255 kfree(data); 229 kfree(data);
230 xd->flags |= JFFS2_XFLAGS_INVALID;
256 return EIO; 231 return EIO;
257 } 232 }
258 233
@@ -286,16 +261,14 @@ static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
286 * rc > 0 : Unrecoverable error, this node should be deleted. 261 * rc > 0 : Unrecoverable error, this node should be deleted.
287 */ 262 */
288 int rc = 0; 263 int rc = 0;
289 BUG_ON(xd->xname); 264
290 if (!xd->node) 265 BUG_ON(xd->flags & JFFS2_XFLAGS_DEAD);
266 if (xd->xname)
267 return 0;
268 if (xd->flags & JFFS2_XFLAGS_INVALID)
291 return EIO; 269 return EIO;
292 if (unlikely(ref_flags(xd->node) != REF_PRISTINE)) { 270 if (unlikely(is_xattr_datum_unchecked(c, xd)))
293 rc = do_verify_xattr_datum(c, xd); 271 rc = do_verify_xattr_datum(c, xd);
294 if (rc > 0) {
295 list_del_init(&xd->xindex);
296 delete_xattr_datum_node(c, xd);
297 }
298 }
299 if (!rc) 272 if (!rc)
300 rc = do_load_xattr_datum(c, xd); 273 rc = do_load_xattr_datum(c, xd);
301 return rc; 274 return rc;
@@ -304,7 +277,6 @@ static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
304static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) 277static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
305{ 278{
306 /* must be called under down_write(xattr_sem) */ 279 /* must be called under down_write(xattr_sem) */
307 struct jffs2_raw_node_ref *raw;
308 struct jffs2_raw_xattr rx; 280 struct jffs2_raw_xattr rx;
309 struct kvec vecs[2]; 281 struct kvec vecs[2];
310 size_t length; 282 size_t length;
@@ -312,14 +284,16 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
312 uint32_t phys_ofs = write_ofs(c); 284 uint32_t phys_ofs = write_ofs(c);
313 285
314 BUG_ON(!xd->xname); 286 BUG_ON(!xd->xname);
287 BUG_ON(xd->flags & (JFFS2_XFLAGS_DEAD|JFFS2_XFLAGS_INVALID));
315 288
316 vecs[0].iov_base = &rx; 289 vecs[0].iov_base = &rx;
317 vecs[0].iov_len = PAD(sizeof(rx)); 290 vecs[0].iov_len = sizeof(rx);
318 vecs[1].iov_base = xd->xname; 291 vecs[1].iov_base = xd->xname;
319 vecs[1].iov_len = xd->name_len + 1 + xd->value_len; 292 vecs[1].iov_len = xd->name_len + 1 + xd->value_len;
320 totlen = vecs[0].iov_len + vecs[1].iov_len; 293 totlen = vecs[0].iov_len + vecs[1].iov_len;
321 294
322 /* Setup raw-xattr */ 295 /* Setup raw-xattr */
296 memset(&rx, 0, sizeof(rx));
323 rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 297 rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
324 rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR); 298 rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR);
325 rx.totlen = cpu_to_je32(PAD(totlen)); 299 rx.totlen = cpu_to_je32(PAD(totlen));
@@ -343,14 +317,8 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
343 317
344 return rc; 318 return rc;
345 } 319 }
346
347 /* success */ 320 /* success */
348 raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(totlen), NULL); 321 jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(totlen), (void *)xd);
349 /* FIXME */ raw->next_in_ino = (void *)xd;
350
351 if (xd->node)
352 delete_xattr_datum_node(c, xd);
353 xd->node = raw;
354 322
355 dbg_xattr("success on saving xdatum (xid=%u, version=%u, xprefix=%u, xname='%s')\n", 323 dbg_xattr("success on saving xdatum (xid=%u, version=%u, xprefix=%u, xname='%s')\n",
356 xd->xid, xd->version, xd->xprefix, xd->xname); 324 xd->xid, xd->version, xd->xprefix, xd->xname);
@@ -377,7 +345,7 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
377 && xd->value_len==xsize 345 && xd->value_len==xsize
378 && !strcmp(xd->xname, xname) 346 && !strcmp(xd->xname, xname)
379 && !memcmp(xd->xvalue, xvalue, xsize)) { 347 && !memcmp(xd->xvalue, xvalue, xsize)) {
380 xd->refcnt++; 348 atomic_inc(&xd->refcnt);
381 return xd; 349 return xd;
382 } 350 }
383 } 351 }
@@ -397,7 +365,7 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
397 strcpy(data, xname); 365 strcpy(data, xname);
398 memcpy(data + name_len + 1, xvalue, xsize); 366 memcpy(data + name_len + 1, xvalue, xsize);
399 367
400 xd->refcnt = 1; 368 atomic_set(&xd->refcnt, 1);
401 xd->xid = ++c->highest_xid; 369 xd->xid = ++c->highest_xid;
402 xd->flags |= JFFS2_XFLAGS_HOT; 370 xd->flags |= JFFS2_XFLAGS_HOT;
403 xd->xprefix = xprefix; 371 xd->xprefix = xprefix;
@@ -426,20 +394,36 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
426 return xd; 394 return xd;
427} 395}
428 396
397static void delete_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
398{
399 /* must be called under down_write(xattr_sem) */
400 BUG_ON(atomic_read(&xd->refcnt));
401
402 unload_xattr_datum(c, xd);
403 xd->flags |= JFFS2_XFLAGS_DEAD;
404 spin_lock(&c->erase_completion_lock);
405 if (xd->node == (void *)xd) {
406 BUG_ON(!(xd->flags & JFFS2_XFLAGS_INVALID));
407 jffs2_free_xattr_datum(xd);
408 } else {
409 list_add(&xd->xindex, &c->xattr_dead_list);
410 }
411 spin_unlock(&c->erase_completion_lock);
412 dbg_xattr("xdatum(xid=%u, version=%u) was removed.\n", xd->xid, xd->version);
413}
414
429/* -------- xref related functions ------------------ 415/* -------- xref related functions ------------------
430 * verify_xattr_ref(c, ref) 416 * verify_xattr_ref(c, ref)
431 * is used to load xref information from medium. Because summary data does not 417 * is used to load xref information from medium. Because summary data does not
432 * contain xid/ino, it's necessary to verify once while mounting process. 418 * contain xid/ino, it's necessary to verify once while mounting process.
433 * delete_xattr_ref_node(c, ref)
434 * is used to delete a jffs2 node is dominated by xref. When EBS is enabled,
435 * it overwrites the obsolete node by myself.
436 * delete_xattr_ref(c, ref)
437 * is used to delete jffs2_xattr_ref object. If the reference counter of xdatum
438 * is refered by this xref become 0, delete_xattr_datum() is called later.
439 * save_xattr_ref(c, ref) 419 * save_xattr_ref(c, ref)
440 * is used to write xref to medium. 420 * is used to write xref to medium. If delete marker is marked, it write
421 * a delete marker of xref into medium.
441 * create_xattr_ref(c, ic, xd) 422 * create_xattr_ref(c, ic, xd)
442 * is used to create a new xref and write to medium. 423 * is used to create a new xref and write to medium.
424 * delete_xattr_ref(c, ref)
425 * is used to delete jffs2_xattr_ref. It marks xref XREF_DELETE_MARKER,
426 * and allows GC to reclaim those physical nodes.
443 * jffs2_xattr_delete_inode(c, ic) 427 * jffs2_xattr_delete_inode(c, ic)
444 * is called to remove xrefs related to obsolete inode when inode is unlinked. 428 * is called to remove xrefs related to obsolete inode when inode is unlinked.
445 * jffs2_xattr_free_inode(c, ic) 429 * jffs2_xattr_free_inode(c, ic)
@@ -450,25 +434,29 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
450static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) 434static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
451{ 435{
452 struct jffs2_eraseblock *jeb; 436 struct jffs2_eraseblock *jeb;
437 struct jffs2_raw_node_ref *raw;
453 struct jffs2_raw_xref rr; 438 struct jffs2_raw_xref rr;
454 size_t readlen; 439 size_t readlen;
455 uint32_t crc, totlen; 440 uint32_t crc, offset, totlen;
456 int rc; 441 int rc;
457 442
458 BUG_ON(ref_flags(ref->node) != REF_UNCHECKED); 443 spin_lock(&c->erase_completion_lock);
444 if (ref_flags(ref->node) != REF_UNCHECKED)
445 goto complete;
446 offset = ref_offset(ref->node);
447 spin_unlock(&c->erase_completion_lock);
459 448
460 rc = jffs2_flash_read(c, ref_offset(ref->node), sizeof(rr), &readlen, (char *)&rr); 449 rc = jffs2_flash_read(c, offset, sizeof(rr), &readlen, (char *)&rr);
461 if (rc || sizeof(rr) != readlen) { 450 if (rc || sizeof(rr) != readlen) {
462 JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu, at %#08x\n", 451 JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu, at %#08x\n",
463 rc, sizeof(rr), readlen, ref_offset(ref->node)); 452 rc, sizeof(rr), readlen, offset);
464 return rc ? rc : -EIO; 453 return rc ? rc : -EIO;
465 } 454 }
466 /* obsolete node */ 455 /* obsolete node */
467 crc = crc32(0, &rr, sizeof(rr) - 4); 456 crc = crc32(0, &rr, sizeof(rr) - 4);
468 if (crc != je32_to_cpu(rr.node_crc)) { 457 if (crc != je32_to_cpu(rr.node_crc)) {
469 if (je32_to_cpu(rr.node_crc) != 0xffffffff) 458 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
470 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", 459 offset, je32_to_cpu(rr.node_crc), crc);
471 ref_offset(ref->node), je32_to_cpu(rr.node_crc), crc);
472 return EIO; 460 return EIO;
473 } 461 }
474 if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK 462 if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK
@@ -476,22 +464,28 @@ static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref
476 || je32_to_cpu(rr.totlen) != PAD(sizeof(rr))) { 464 || je32_to_cpu(rr.totlen) != PAD(sizeof(rr))) {
477 JFFS2_ERROR("inconsistent xref at %#08x, magic=%#04x/%#04x, " 465 JFFS2_ERROR("inconsistent xref at %#08x, magic=%#04x/%#04x, "
478 "nodetype=%#04x/%#04x, totlen=%u/%zu\n", 466 "nodetype=%#04x/%#04x, totlen=%u/%zu\n",
479 ref_offset(ref->node), je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK, 467 offset, je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK,
480 je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF, 468 je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF,
481 je32_to_cpu(rr.totlen), PAD(sizeof(rr))); 469 je32_to_cpu(rr.totlen), PAD(sizeof(rr)));
482 return EIO; 470 return EIO;
483 } 471 }
484 ref->ino = je32_to_cpu(rr.ino); 472 ref->ino = je32_to_cpu(rr.ino);
485 ref->xid = je32_to_cpu(rr.xid); 473 ref->xid = je32_to_cpu(rr.xid);
486 474 ref->xseqno = je32_to_cpu(rr.xseqno);
487 /* fixup superblock/eraseblock info */ 475 if (ref->xseqno > c->highest_xseqno)
488 jeb = &c->blocks[ref_offset(ref->node) / c->sector_size]; 476 c->highest_xseqno = (ref->xseqno & ~XREF_DELETE_MARKER);
489 totlen = PAD(sizeof(rr));
490 477
491 spin_lock(&c->erase_completion_lock); 478 spin_lock(&c->erase_completion_lock);
492 c->unchecked_size -= totlen; c->used_size += totlen; 479 complete:
493 jeb->unchecked_size -= totlen; jeb->used_size += totlen; 480 for (raw=ref->node; raw != (void *)ref; raw=raw->next_in_ino) {
494 ref->node->flash_offset = ref_offset(ref->node) | REF_PRISTINE; 481 jeb = &c->blocks[ref_offset(raw) / c->sector_size];
482 totlen = PAD(ref_totlen(c, jeb, raw));
483 if (ref_flags(raw) == REF_UNCHECKED) {
484 c->unchecked_size -= totlen; c->used_size += totlen;
485 jeb->unchecked_size -= totlen; jeb->used_size += totlen;
486 }
487 raw->flash_offset = ref_offset(raw) | ((ref->node==raw) ? REF_PRISTINE : REF_NORMAL);
488 }
495 spin_unlock(&c->erase_completion_lock); 489 spin_unlock(&c->erase_completion_lock);
496 490
497 dbg_xattr("success on verifying xref (ino=%u, xid=%u) at %#08x\n", 491 dbg_xattr("success on verifying xref (ino=%u, xid=%u) at %#08x\n",
@@ -499,58 +493,12 @@ static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref
499 return 0; 493 return 0;
500} 494}
501 495
502static void delete_xattr_ref_node(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
503{
504 struct jffs2_raw_xref rr;
505 size_t length;
506 int rc;
507
508 if (jffs2_sum_active()) {
509 memset(&rr, 0xff, sizeof(rr));
510 rc = jffs2_flash_read(c, ref_offset(ref->node),
511 sizeof(struct jffs2_unknown_node),
512 &length, (char *)&rr);
513 if (rc || length != sizeof(struct jffs2_unknown_node)) {
514 JFFS2_ERROR("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n",
515 rc, sizeof(struct jffs2_unknown_node),
516 length, ref_offset(ref->node));
517 }
518 rc = jffs2_flash_write(c, ref_offset(ref->node), sizeof(rr),
519 &length, (char *)&rr);
520 if (rc || length != sizeof(struct jffs2_raw_xref)) {
521 JFFS2_ERROR("jffs2_flash_write()=%d, req=%zu, wrote=%zu at %#08x\n",
522 rc, sizeof(rr), length, ref_offset(ref->node));
523 }
524 }
525 spin_lock(&c->erase_completion_lock);
526 ref->node->next_in_ino = NULL;
527 spin_unlock(&c->erase_completion_lock);
528 jffs2_mark_node_obsolete(c, ref->node);
529 ref->node = NULL;
530}
531
532static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
533{
534 /* must be called under down_write(xattr_sem) */
535 struct jffs2_xattr_datum *xd;
536
537 BUG_ON(!ref->node);
538 delete_xattr_ref_node(c, ref);
539
540 xd = ref->xd;
541 xd->refcnt--;
542 if (!xd->refcnt)
543 delete_xattr_datum(c, xd);
544 jffs2_free_xattr_ref(ref);
545}
546
547static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) 496static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
548{ 497{
549 /* must be called under down_write(xattr_sem) */ 498 /* must be called under down_write(xattr_sem) */
550 struct jffs2_raw_node_ref *raw;
551 struct jffs2_raw_xref rr; 499 struct jffs2_raw_xref rr;
552 size_t length; 500 size_t length;
553 uint32_t phys_ofs = write_ofs(c); 501 uint32_t xseqno, phys_ofs = write_ofs(c);
554 int ret; 502 int ret;
555 503
556 rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 504 rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -558,8 +506,16 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
558 rr.totlen = cpu_to_je32(PAD(sizeof(rr))); 506 rr.totlen = cpu_to_je32(PAD(sizeof(rr)));
559 rr.hdr_crc = cpu_to_je32(crc32(0, &rr, sizeof(struct jffs2_unknown_node) - 4)); 507 rr.hdr_crc = cpu_to_je32(crc32(0, &rr, sizeof(struct jffs2_unknown_node) - 4));
560 508
561 rr.ino = cpu_to_je32(ref->ic->ino); 509 xseqno = (c->highest_xseqno += 2);
562 rr.xid = cpu_to_je32(ref->xd->xid); 510 if (is_xattr_ref_dead(ref)) {
511 xseqno |= XREF_DELETE_MARKER;
512 rr.ino = cpu_to_je32(ref->ino);
513 rr.xid = cpu_to_je32(ref->xid);
514 } else {
515 rr.ino = cpu_to_je32(ref->ic->ino);
516 rr.xid = cpu_to_je32(ref->xd->xid);
517 }
518 rr.xseqno = cpu_to_je32(xseqno);
563 rr.node_crc = cpu_to_je32(crc32(0, &rr, sizeof(rr) - 4)); 519 rr.node_crc = cpu_to_je32(crc32(0, &rr, sizeof(rr) - 4));
564 520
565 ret = jffs2_flash_write(c, phys_ofs, sizeof(rr), &length, (char *)&rr); 521 ret = jffs2_flash_write(c, phys_ofs, sizeof(rr), &length, (char *)&rr);
@@ -572,12 +528,9 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
572 528
573 return ret; 529 return ret;
574 } 530 }
575 531 /* success */
576 raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), NULL); 532 ref->xseqno = xseqno;
577 /* FIXME */ raw->next_in_ino = (void *)ref; 533 jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), (void *)ref);
578 if (ref->node)
579 delete_xattr_ref_node(c, ref);
580 ref->node = raw;
581 534
582 dbg_xattr("success on saving xref (ino=%u, xid=%u)\n", ref->ic->ino, ref->xd->xid); 535 dbg_xattr("success on saving xref (ino=%u, xid=%u)\n", ref->ic->ino, ref->xd->xid);
583 536
@@ -610,6 +563,27 @@ static struct jffs2_xattr_ref *create_xattr_ref(struct jffs2_sb_info *c, struct
610 return ref; /* success */ 563 return ref; /* success */
611} 564}
612 565
566static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
567{
568 /* must be called under down_write(xattr_sem) */
569 struct jffs2_xattr_datum *xd;
570
571 xd = ref->xd;
572 ref->xseqno |= XREF_DELETE_MARKER;
573 ref->ino = ref->ic->ino;
574 ref->xid = ref->xd->xid;
575 spin_lock(&c->erase_completion_lock);
576 ref->next = c->xref_dead_list;
577 c->xref_dead_list = ref;
578 spin_unlock(&c->erase_completion_lock);
579
580 dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) was removed.\n",
581 ref->ino, ref->xid, ref->xseqno);
582
583 if (atomic_dec_and_test(&xd->refcnt))
584 delete_xattr_datum(c, xd);
585}
586
613void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) 587void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
614{ 588{
615 /* It's called from jffs2_clear_inode() on inode removing. 589 /* It's called from jffs2_clear_inode() on inode removing.
@@ -638,8 +612,7 @@ void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *i
638 for (ref = ic->xref; ref; ref = _ref) { 612 for (ref = ic->xref; ref; ref = _ref) {
639 _ref = ref->next; 613 _ref = ref->next;
640 xd = ref->xd; 614 xd = ref->xd;
641 xd->refcnt--; 615 if (atomic_dec_and_test(&xd->refcnt)) {
642 if (!xd->refcnt) {
643 unload_xattr_datum(c, xd); 616 unload_xattr_datum(c, xd);
644 jffs2_free_xattr_datum(xd); 617 jffs2_free_xattr_datum(xd);
645 } 618 }
@@ -655,7 +628,7 @@ static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cac
655 * duplicate name/value pairs. If duplicate name/value pair would be found, 628 * duplicate name/value pairs. If duplicate name/value pair would be found,
656 * one will be removed. 629 * one will be removed.
657 */ 630 */
658 struct jffs2_xattr_ref *ref, *cmp, **pref; 631 struct jffs2_xattr_ref *ref, *cmp, **pref, **pcmp;
659 int rc = 0; 632 int rc = 0;
660 633
661 if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED)) 634 if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED))
@@ -673,13 +646,13 @@ static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cac
673 } else if (unlikely(rc < 0)) 646 } else if (unlikely(rc < 0))
674 goto out; 647 goto out;
675 } 648 }
676 for (cmp=ref->next, pref=&ref->next; cmp; pref=&cmp->next, cmp=cmp->next) { 649 for (cmp=ref->next, pcmp=&ref->next; cmp; pcmp=&cmp->next, cmp=cmp->next) {
677 if (!cmp->xd->xname) { 650 if (!cmp->xd->xname) {
678 ref->xd->flags |= JFFS2_XFLAGS_BIND; 651 ref->xd->flags |= JFFS2_XFLAGS_BIND;
679 rc = load_xattr_datum(c, cmp->xd); 652 rc = load_xattr_datum(c, cmp->xd);
680 ref->xd->flags &= ~JFFS2_XFLAGS_BIND; 653 ref->xd->flags &= ~JFFS2_XFLAGS_BIND;
681 if (unlikely(rc > 0)) { 654 if (unlikely(rc > 0)) {
682 *pref = cmp->next; 655 *pcmp = cmp->next;
683 delete_xattr_ref(c, cmp); 656 delete_xattr_ref(c, cmp);
684 goto retry; 657 goto retry;
685 } else if (unlikely(rc < 0)) 658 } else if (unlikely(rc < 0))
@@ -687,8 +660,13 @@ static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cac
687 } 660 }
688 if (ref->xd->xprefix == cmp->xd->xprefix 661 if (ref->xd->xprefix == cmp->xd->xprefix
689 && !strcmp(ref->xd->xname, cmp->xd->xname)) { 662 && !strcmp(ref->xd->xname, cmp->xd->xname)) {
690 *pref = cmp->next; 663 if (ref->xseqno > cmp->xseqno) {
691 delete_xattr_ref(c, cmp); 664 *pcmp = cmp->next;
665 delete_xattr_ref(c, cmp);
666 } else {
667 *pref = ref->next;
668 delete_xattr_ref(c, ref);
669 }
692 goto retry; 670 goto retry;
693 } 671 }
694 } 672 }
@@ -719,9 +697,13 @@ void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c)
719 for (i=0; i < XATTRINDEX_HASHSIZE; i++) 697 for (i=0; i < XATTRINDEX_HASHSIZE; i++)
720 INIT_LIST_HEAD(&c->xattrindex[i]); 698 INIT_LIST_HEAD(&c->xattrindex[i]);
721 INIT_LIST_HEAD(&c->xattr_unchecked); 699 INIT_LIST_HEAD(&c->xattr_unchecked);
700 INIT_LIST_HEAD(&c->xattr_dead_list);
701 c->xref_dead_list = NULL;
722 c->xref_temp = NULL; 702 c->xref_temp = NULL;
723 703
724 init_rwsem(&c->xattr_sem); 704 init_rwsem(&c->xattr_sem);
705 c->highest_xid = 0;
706 c->highest_xseqno = 0;
725 c->xdatum_mem_usage = 0; 707 c->xdatum_mem_usage = 0;
726 c->xdatum_mem_threshold = 32 * 1024; /* Default 32KB */ 708 c->xdatum_mem_threshold = 32 * 1024; /* Default 32KB */
727} 709}
@@ -751,7 +733,11 @@ void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c)
751 _ref = ref->next; 733 _ref = ref->next;
752 jffs2_free_xattr_ref(ref); 734 jffs2_free_xattr_ref(ref);
753 } 735 }
754 c->xref_temp = NULL; 736
737 for (ref=c->xref_dead_list; ref; ref = _ref) {
738 _ref = ref->next;
739 jffs2_free_xattr_ref(ref);
740 }
755 741
756 for (i=0; i < XATTRINDEX_HASHSIZE; i++) { 742 for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
757 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) { 743 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
@@ -761,100 +747,143 @@ void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c)
761 jffs2_free_xattr_datum(xd); 747 jffs2_free_xattr_datum(xd);
762 } 748 }
763 } 749 }
750
751 list_for_each_entry_safe(xd, _xd, &c->xattr_dead_list, xindex) {
752 list_del(&xd->xindex);
753 jffs2_free_xattr_datum(xd);
754 }
764} 755}
765 756
757#define XREF_TMPHASH_SIZE (128)
766void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c) 758void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
767{ 759{
768 struct jffs2_xattr_ref *ref, *_ref; 760 struct jffs2_xattr_ref *ref, *_ref;
761 struct jffs2_xattr_ref *xref_tmphash[XREF_TMPHASH_SIZE];
769 struct jffs2_xattr_datum *xd, *_xd; 762 struct jffs2_xattr_datum *xd, *_xd;
770 struct jffs2_inode_cache *ic; 763 struct jffs2_inode_cache *ic;
771 int i, xdatum_count =0, xdatum_unchecked_count = 0, xref_count = 0; 764 struct jffs2_raw_node_ref *raw;
765 int i, xdatum_count = 0, xdatum_unchecked_count = 0, xref_count = 0;
766 int xdatum_orphan_count = 0, xref_orphan_count = 0, xref_dead_count = 0;
772 767
773 BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING)); 768 BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING));
774 769
775 /* Phase.1 */ 770 /* Phase.1 : Merge same xref */
771 for (i=0; i < XREF_TMPHASH_SIZE; i++)
772 xref_tmphash[i] = NULL;
776 for (ref=c->xref_temp; ref; ref=_ref) { 773 for (ref=c->xref_temp; ref; ref=_ref) {
774 struct jffs2_xattr_ref *tmp;
775
777 _ref = ref->next; 776 _ref = ref->next;
778 /* checking REF_UNCHECKED nodes */
779 if (ref_flags(ref->node) != REF_PRISTINE) { 777 if (ref_flags(ref->node) != REF_PRISTINE) {
780 if (verify_xattr_ref(c, ref)) { 778 if (verify_xattr_ref(c, ref)) {
781 delete_xattr_ref_node(c, ref); 779 BUG_ON(ref->node->next_in_ino != (void *)ref);
780 ref->node->next_in_ino = NULL;
781 jffs2_mark_node_obsolete(c, ref->node);
782 jffs2_free_xattr_ref(ref); 782 jffs2_free_xattr_ref(ref);
783 continue; 783 continue;
784 } 784 }
785 } 785 }
786 /* At this point, ref->xid and ref->ino contain XID and inode number. 786
787 ref->xd and ref->ic are not valid yet. */ 787 i = (ref->ino ^ ref->xid) % XREF_TMPHASH_SIZE;
788 xd = jffs2_find_xattr_datum(c, ref->xid); 788 for (tmp=xref_tmphash[i]; tmp; tmp=tmp->next) {
789 ic = jffs2_get_ino_cache(c, ref->ino); 789 if (tmp->ino == ref->ino && tmp->xid == ref->xid)
790 if (!xd || !ic) { 790 break;
791 if (ref_flags(ref->node) != REF_UNCHECKED) 791 }
792 JFFS2_WARNING("xref(ino=%u, xid=%u) is orphan. \n", 792 if (tmp) {
793 ref->ino, ref->xid); 793 raw = ref->node;
794 delete_xattr_ref_node(c, ref); 794 if (ref->xseqno > tmp->xseqno) {
795 tmp->xseqno = ref->xseqno;
796 raw->next_in_ino = tmp->node;
797 tmp->node = raw;
798 } else {
799 raw->next_in_ino = tmp->node->next_in_ino;
800 tmp->node->next_in_ino = raw;
801 }
795 jffs2_free_xattr_ref(ref); 802 jffs2_free_xattr_ref(ref);
796 continue; 803 continue;
804 } else {
805 ref->next = xref_tmphash[i];
806 xref_tmphash[i] = ref;
797 } 807 }
798 ref->xd = xd;
799 ref->ic = ic;
800 xd->refcnt++;
801 ref->next = ic->xref;
802 ic->xref = ref;
803 xref_count++;
804 } 808 }
805 c->xref_temp = NULL; 809 c->xref_temp = NULL;
806 /* After this, ref->xid/ino are NEVER used. */
807 810
808 /* Phase.2 */ 811 /* Phase.2 : Bind xref with inode_cache and xattr_datum */
812 for (i=0; i < XREF_TMPHASH_SIZE; i++) {
813 for (ref=xref_tmphash[i]; ref; ref=_ref) {
814 xref_count++;
815 _ref = ref->next;
816 if (is_xattr_ref_dead(ref)) {
817 ref->next = c->xref_dead_list;
818 c->xref_dead_list = ref;
819 xref_dead_count++;
820 continue;
821 }
822 /* At this point, ref->xid and ref->ino contain XID and inode number.
823 ref->xd and ref->ic are not valid yet. */
824 xd = jffs2_find_xattr_datum(c, ref->xid);
825 ic = jffs2_get_ino_cache(c, ref->ino);
826 if (!xd || !ic) {
827 dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) is orphan.\n",
828 ref->ino, ref->xid, ref->xseqno);
829 ref->xseqno |= XREF_DELETE_MARKER;
830 ref->next = c->xref_dead_list;
831 c->xref_dead_list = ref;
832 xref_orphan_count++;
833 continue;
834 }
835 ref->xd = xd;
836 ref->ic = ic;
837 atomic_inc(&xd->refcnt);
838 ref->next = ic->xref;
839 ic->xref = ref;
840 }
841 }
842
843 /* Phase.3 : Link unchecked xdatum to xattr_unchecked list */
809 for (i=0; i < XATTRINDEX_HASHSIZE; i++) { 844 for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
810 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) { 845 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
846 xdatum_count++;
811 list_del_init(&xd->xindex); 847 list_del_init(&xd->xindex);
812 if (!xd->refcnt) { 848 if (!atomic_read(&xd->refcnt)) {
813 if (ref_flags(xd->node) != REF_UNCHECKED) 849 dbg_xattr("xdatum(xid=%u, version=%u) is orphan.\n",
814 JFFS2_WARNING("orphan xdatum(xid=%u, version=%u) at %#08x\n", 850 xd->xid, xd->version);
815 xd->xid, xd->version, ref_offset(xd->node)); 851 xd->flags |= JFFS2_XFLAGS_DEAD;
816 delete_xattr_datum(c, xd); 852 list_add(&xd->xindex, &c->xattr_unchecked);
853 xdatum_orphan_count++;
817 continue; 854 continue;
818 } 855 }
819 if (ref_flags(xd->node) != REF_PRISTINE) { 856 if (is_xattr_datum_unchecked(c, xd)) {
820 dbg_xattr("unchecked xdatum(xid=%u) at %#08x\n", 857 dbg_xattr("unchecked xdatum(xid=%u, version=%u)\n",
821 xd->xid, ref_offset(xd->node)); 858 xd->xid, xd->version);
822 list_add(&xd->xindex, &c->xattr_unchecked); 859 list_add(&xd->xindex, &c->xattr_unchecked);
823 xdatum_unchecked_count++; 860 xdatum_unchecked_count++;
824 } 861 }
825 xdatum_count++;
826 } 862 }
827 } 863 }
828 /* build complete */ 864 /* build complete */
829 JFFS2_NOTICE("complete building xattr subsystem, %u of xdatum (%u unchecked) and " 865 JFFS2_NOTICE("complete building xattr subsystem, %u of xdatum"
830 "%u of xref found.\n", xdatum_count, xdatum_unchecked_count, xref_count); 866 " (%u unchecked, %u orphan) and "
867 "%u of xref (%u dead, %u orphan) found.\n",
868 xdatum_count, xdatum_unchecked_count, xdatum_orphan_count,
869 xref_count, xref_dead_count, xref_orphan_count);
831} 870}
832 871
833struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c, 872struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
834 uint32_t xid, uint32_t version) 873 uint32_t xid, uint32_t version)
835{ 874{
836 struct jffs2_xattr_datum *xd, *_xd; 875 struct jffs2_xattr_datum *xd;
837 876
838 _xd = jffs2_find_xattr_datum(c, xid); 877 xd = jffs2_find_xattr_datum(c, xid);
839 if (_xd) { 878 if (!xd) {
840 dbg_xattr("duplicate xdatum (xid=%u, version=%u/%u) at %#08x\n", 879 xd = jffs2_alloc_xattr_datum();
841 xid, version, _xd->version, ref_offset(_xd->node)); 880 if (!xd)
842 if (version < _xd->version) 881 return ERR_PTR(-ENOMEM);
843 return ERR_PTR(-EEXIST); 882 xd->xid = xid;
844 } 883 xd->version = version;
845 xd = jffs2_alloc_xattr_datum(); 884 if (xd->xid > c->highest_xid)
846 if (!xd) 885 c->highest_xid = xd->xid;
847 return ERR_PTR(-ENOMEM); 886 list_add_tail(&xd->xindex, &c->xattrindex[xid % XATTRINDEX_HASHSIZE]);
848 xd->xid = xid;
849 xd->version = version;
850 if (xd->xid > c->highest_xid)
851 c->highest_xid = xd->xid;
852 list_add_tail(&xd->xindex, &c->xattrindex[xid % XATTRINDEX_HASHSIZE]);
853
854 if (_xd) {
855 list_del_init(&_xd->xindex);
856 delete_xattr_datum_node(c, _xd);
857 jffs2_free_xattr_datum(_xd);
858 } 887 }
859 return xd; 888 return xd;
860} 889}
@@ -1080,9 +1109,23 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1080 goto out; 1109 goto out;
1081 } 1110 }
1082 if (!buffer) { 1111 if (!buffer) {
1083 *pref = ref->next; 1112 ref->ino = ic->ino;
1084 delete_xattr_ref(c, ref); 1113 ref->xid = xd->xid;
1085 rc = 0; 1114 ref->xseqno |= XREF_DELETE_MARKER;
1115 rc = save_xattr_ref(c, ref);
1116 if (!rc) {
1117 *pref = ref->next;
1118 spin_lock(&c->erase_completion_lock);
1119 ref->next = c->xref_dead_list;
1120 c->xref_dead_list = ref;
1121 spin_unlock(&c->erase_completion_lock);
1122 if (atomic_dec_and_test(&xd->refcnt))
1123 delete_xattr_datum(c, xd);
1124 } else {
1125 ref->ic = ic;
1126 ref->xd = xd;
1127 ref->xseqno &= ~XREF_DELETE_MARKER;
1128 }
1086 goto out; 1129 goto out;
1087 } 1130 }
1088 goto found; 1131 goto found;
@@ -1094,7 +1137,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1094 goto out; 1137 goto out;
1095 } 1138 }
1096 if (!buffer) { 1139 if (!buffer) {
1097 rc = -EINVAL; 1140 rc = -ENODATA;
1098 goto out; 1141 goto out;
1099 } 1142 }
1100 found: 1143 found:
@@ -1110,16 +1153,14 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1110 request = PAD(sizeof(struct jffs2_raw_xref)); 1153 request = PAD(sizeof(struct jffs2_raw_xref));
1111 rc = jffs2_reserve_space(c, request, &length, 1154 rc = jffs2_reserve_space(c, request, &length,
1112 ALLOC_NORMAL, JFFS2_SUMMARY_XREF_SIZE); 1155 ALLOC_NORMAL, JFFS2_SUMMARY_XREF_SIZE);
1156 down_write(&c->xattr_sem);
1113 if (rc) { 1157 if (rc) {
1114 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request); 1158 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);
1115 down_write(&c->xattr_sem); 1159 if (atomic_dec_and_test(&xd->refcnt))
1116 xd->refcnt--;
1117 if (!xd->refcnt)
1118 delete_xattr_datum(c, xd); 1160 delete_xattr_datum(c, xd);
1119 up_write(&c->xattr_sem); 1161 up_write(&c->xattr_sem);
1120 return rc; 1162 return rc;
1121 } 1163 }
1122 down_write(&c->xattr_sem);
1123 if (ref) 1164 if (ref)
1124 *pref = ref->next; 1165 *pref = ref->next;
1125 newref = create_xattr_ref(c, ic, xd); 1166 newref = create_xattr_ref(c, ic, xd);
@@ -1129,8 +1170,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1129 ic->xref = ref; 1170 ic->xref = ref;
1130 } 1171 }
1131 rc = PTR_ERR(newref); 1172 rc = PTR_ERR(newref);
1132 xd->refcnt--; 1173 if (atomic_dec_and_test(&xd->refcnt))
1133 if (!xd->refcnt)
1134 delete_xattr_datum(c, xd); 1174 delete_xattr_datum(c, xd);
1135 } else if (ref) { 1175 } else if (ref) {
1136 delete_xattr_ref(c, ref); 1176 delete_xattr_ref(c, ref);
@@ -1142,38 +1182,40 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1142} 1182}
1143 1183
1144/* -------- garbage collector functions ------------- 1184/* -------- garbage collector functions -------------
1145 * jffs2_garbage_collect_xattr_datum(c, xd) 1185 * jffs2_garbage_collect_xattr_datum(c, xd, raw)
1146 * is used to move xdatum into new node. 1186 * is used to move xdatum into new node.
1147 * jffs2_garbage_collect_xattr_ref(c, ref) 1187 * jffs2_garbage_collect_xattr_ref(c, ref, raw)
1148 * is used to move xref into new node. 1188 * is used to move xref into new node.
1149 * jffs2_verify_xattr(c) 1189 * jffs2_verify_xattr(c)
1150 * is used to call do_verify_xattr_datum() before garbage collecting. 1190 * is used to call do_verify_xattr_datum() before garbage collecting.
1191 * jffs2_release_xattr_datum(c, xd)
1192 * is used to release an in-memory object of xdatum.
1193 * jffs2_release_xattr_ref(c, ref)
1194 * is used to release an in-memory object of xref.
1151 * -------------------------------------------------- */ 1195 * -------------------------------------------------- */
1152int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) 1196int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd,
1197 struct jffs2_raw_node_ref *raw)
1153{ 1198{
1154 uint32_t totlen, length, old_ofs; 1199 uint32_t totlen, length, old_ofs;
1155 int rc = -EINVAL; 1200 int rc = 0;
1156 1201
1157 down_write(&c->xattr_sem); 1202 down_write(&c->xattr_sem);
1158 BUG_ON(!xd->node); 1203 if (xd->node != raw)
1159 1204 goto out;
1160 old_ofs = ref_offset(xd->node); 1205 if (xd->flags & (JFFS2_XFLAGS_DEAD|JFFS2_XFLAGS_INVALID))
1161 totlen = ref_totlen(c, c->gcblock, xd->node);
1162 if (totlen < sizeof(struct jffs2_raw_xattr))
1163 goto out; 1206 goto out;
1164 1207
1165 if (!xd->xname) { 1208 rc = load_xattr_datum(c, xd);
1166 rc = load_xattr_datum(c, xd); 1209 if (unlikely(rc)) {
1167 if (unlikely(rc > 0)) { 1210 rc = (rc > 0) ? 0 : rc;
1168 delete_xattr_datum_node(c, xd); 1211 goto out;
1169 rc = 0;
1170 goto out;
1171 } else if (unlikely(rc < 0))
1172 goto out;
1173 } 1212 }
1213 old_ofs = ref_offset(xd->node);
1214 totlen = PAD(sizeof(struct jffs2_raw_xattr)
1215 + xd->name_len + 1 + xd->value_len);
1174 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE); 1216 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE);
1175 if (rc || length < totlen) { 1217 if (rc) {
1176 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, totlen); 1218 JFFS2_WARNING("jffs2_reserve_space_gc()=%d, request=%u\n", rc, totlen);
1177 rc = rc ? rc : -EBADFD; 1219 rc = rc ? rc : -EBADFD;
1178 goto out; 1220 goto out;
1179 } 1221 }
@@ -1182,27 +1224,32 @@ int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xatt
1182 dbg_xattr("xdatum (xid=%u, version=%u) GC'ed from %#08x to %08x\n", 1224 dbg_xattr("xdatum (xid=%u, version=%u) GC'ed from %#08x to %08x\n",
1183 xd->xid, xd->version, old_ofs, ref_offset(xd->node)); 1225 xd->xid, xd->version, old_ofs, ref_offset(xd->node));
1184 out: 1226 out:
1227 if (!rc)
1228 jffs2_mark_node_obsolete(c, raw);
1185 up_write(&c->xattr_sem); 1229 up_write(&c->xattr_sem);
1186 return rc; 1230 return rc;
1187} 1231}
1188 1232
1189 1233int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref,
1190int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) 1234 struct jffs2_raw_node_ref *raw)
1191{ 1235{
1192 uint32_t totlen, length, old_ofs; 1236 uint32_t totlen, length, old_ofs;
1193 int rc = -EINVAL; 1237 int rc = 0;
1194 1238
1195 down_write(&c->xattr_sem); 1239 down_write(&c->xattr_sem);
1196 BUG_ON(!ref->node); 1240 BUG_ON(!ref->node);
1197 1241
1242 if (ref->node != raw)
1243 goto out;
1244 if (is_xattr_ref_dead(ref) && (raw->next_in_ino == (void *)ref))
1245 goto out;
1246
1198 old_ofs = ref_offset(ref->node); 1247 old_ofs = ref_offset(ref->node);
1199 totlen = ref_totlen(c, c->gcblock, ref->node); 1248 totlen = ref_totlen(c, c->gcblock, ref->node);
1200 if (totlen != sizeof(struct jffs2_raw_xref))
1201 goto out;
1202 1249
1203 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE); 1250 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE);
1204 if (rc || length < totlen) { 1251 if (rc) {
1205 JFFS2_WARNING("%s: jffs2_reserve_space() = %d, request = %u\n", 1252 JFFS2_WARNING("%s: jffs2_reserve_space_gc() = %d, request = %u\n",
1206 __FUNCTION__, rc, totlen); 1253 __FUNCTION__, rc, totlen);
1207 rc = rc ? rc : -EBADFD; 1254 rc = rc ? rc : -EBADFD;
1208 goto out; 1255 goto out;
@@ -1212,6 +1259,8 @@ int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_
1212 dbg_xattr("xref (ino=%u, xid=%u) GC'ed from %#08x to %08x\n", 1259 dbg_xattr("xref (ino=%u, xid=%u) GC'ed from %#08x to %08x\n",
1213 ref->ic->ino, ref->xd->xid, old_ofs, ref_offset(ref->node)); 1260 ref->ic->ino, ref->xd->xid, old_ofs, ref_offset(ref->node));
1214 out: 1261 out:
1262 if (!rc)
1263 jffs2_mark_node_obsolete(c, raw);
1215 up_write(&c->xattr_sem); 1264 up_write(&c->xattr_sem);
1216 return rc; 1265 return rc;
1217} 1266}
@@ -1219,20 +1268,59 @@ int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_
1219int jffs2_verify_xattr(struct jffs2_sb_info *c) 1268int jffs2_verify_xattr(struct jffs2_sb_info *c)
1220{ 1269{
1221 struct jffs2_xattr_datum *xd, *_xd; 1270 struct jffs2_xattr_datum *xd, *_xd;
1271 struct jffs2_eraseblock *jeb;
1272 struct jffs2_raw_node_ref *raw;
1273 uint32_t totlen;
1222 int rc; 1274 int rc;
1223 1275
1224 down_write(&c->xattr_sem); 1276 down_write(&c->xattr_sem);
1225 list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) { 1277 list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) {
1226 rc = do_verify_xattr_datum(c, xd); 1278 rc = do_verify_xattr_datum(c, xd);
1227 if (rc == 0) { 1279 if (rc < 0)
1228 list_del_init(&xd->xindex); 1280 continue;
1229 break; 1281 list_del_init(&xd->xindex);
1230 } else if (rc > 0) { 1282 spin_lock(&c->erase_completion_lock);
1231 list_del_init(&xd->xindex); 1283 for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
1232 delete_xattr_datum_node(c, xd); 1284 if (ref_flags(raw) != REF_UNCHECKED)
1285 continue;
1286 jeb = &c->blocks[ref_offset(raw) / c->sector_size];
1287 totlen = PAD(ref_totlen(c, jeb, raw));
1288 c->unchecked_size -= totlen; c->used_size += totlen;
1289 jeb->unchecked_size -= totlen; jeb->used_size += totlen;
1290 raw->flash_offset = ref_offset(raw)
1291 | ((xd->node == (void *)raw) ? REF_PRISTINE : REF_NORMAL);
1233 } 1292 }
1293 if (xd->flags & JFFS2_XFLAGS_DEAD)
1294 list_add(&xd->xindex, &c->xattr_dead_list);
1295 spin_unlock(&c->erase_completion_lock);
1234 } 1296 }
1235 up_write(&c->xattr_sem); 1297 up_write(&c->xattr_sem);
1236
1237 return list_empty(&c->xattr_unchecked) ? 1 : 0; 1298 return list_empty(&c->xattr_unchecked) ? 1 : 0;
1238} 1299}
1300
1301void jffs2_release_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
1302{
1303 /* must be called under spin_lock(&c->erase_completion_lock) */
1304 if (atomic_read(&xd->refcnt) || xd->node != (void *)xd)
1305 return;
1306
1307 list_del(&xd->xindex);
1308 jffs2_free_xattr_datum(xd);
1309}
1310
1311void jffs2_release_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
1312{
1313 /* must be called under spin_lock(&c->erase_completion_lock) */
1314 struct jffs2_xattr_ref *tmp, **ptmp;
1315
1316 if (ref->node != (void *)ref)
1317 return;
1318
1319 for (tmp=c->xref_dead_list, ptmp=&c->xref_dead_list; tmp; ptmp=&tmp->next, tmp=tmp->next) {
1320 if (ref == tmp) {
1321 *ptmp = tmp->next;
1322 break;
1323 }
1324 }
1325 jffs2_free_xattr_ref(ref);
1326}
diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h
index 2c199856c582..06a5c69dcf8b 100644
--- a/fs/jffs2/xattr.h
+++ b/fs/jffs2/xattr.h
@@ -16,6 +16,8 @@
16 16
17#define JFFS2_XFLAGS_HOT (0x01) /* This datum is HOT */ 17#define JFFS2_XFLAGS_HOT (0x01) /* This datum is HOT */
18#define JFFS2_XFLAGS_BIND (0x02) /* This datum is not reclaimed */ 18#define JFFS2_XFLAGS_BIND (0x02) /* This datum is not reclaimed */
19#define JFFS2_XFLAGS_DEAD (0x40) /* This datum is already dead */
20#define JFFS2_XFLAGS_INVALID (0x80) /* This datum contains crc error */
19 21
20struct jffs2_xattr_datum 22struct jffs2_xattr_datum
21{ 23{
@@ -23,10 +25,10 @@ struct jffs2_xattr_datum
23 struct jffs2_raw_node_ref *node; 25 struct jffs2_raw_node_ref *node;
24 uint8_t class; 26 uint8_t class;
25 uint8_t flags; 27 uint8_t flags;
26 uint16_t xprefix; /* see JFFS2_XATTR_PREFIX_* */ 28 uint16_t xprefix; /* see JFFS2_XATTR_PREFIX_* */
27 29
28 struct list_head xindex; /* chained from c->xattrindex[n] */ 30 struct list_head xindex; /* chained from c->xattrindex[n] */
29 uint32_t refcnt; /* # of xattr_ref refers this */ 31 atomic_t refcnt; /* # of xattr_ref refers this */
30 uint32_t xid; 32 uint32_t xid;
31 uint32_t version; 33 uint32_t version;
32 34
@@ -47,6 +49,7 @@ struct jffs2_xattr_ref
47 uint8_t flags; /* Currently unused */ 49 uint8_t flags; /* Currently unused */
48 u16 unused; 50 u16 unused;
49 51
52 uint32_t xseqno;
50 union { 53 union {
51 struct jffs2_inode_cache *ic; /* reference to jffs2_inode_cache */ 54 struct jffs2_inode_cache *ic; /* reference to jffs2_inode_cache */
52 uint32_t ino; /* only used in scanning/building */ 55 uint32_t ino; /* only used in scanning/building */
@@ -58,6 +61,12 @@ struct jffs2_xattr_ref
58 struct jffs2_xattr_ref *next; /* chained from ic->xref_list */ 61 struct jffs2_xattr_ref *next; /* chained from ic->xref_list */
59}; 62};
60 63
64#define XREF_DELETE_MARKER (0x00000001)
65static inline int is_xattr_ref_dead(struct jffs2_xattr_ref *ref)
66{
67 return ((ref->xseqno & XREF_DELETE_MARKER) != 0);
68}
69
61#ifdef CONFIG_JFFS2_FS_XATTR 70#ifdef CONFIG_JFFS2_FS_XATTR
62 71
63extern void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c); 72extern void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c);
@@ -70,9 +79,13 @@ extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c
70extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); 79extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
71extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); 80extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
72 81
73extern int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd); 82extern int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd,
74extern int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref); 83 struct jffs2_raw_node_ref *raw);
84extern int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref,
85 struct jffs2_raw_node_ref *raw);
75extern int jffs2_verify_xattr(struct jffs2_sb_info *c); 86extern int jffs2_verify_xattr(struct jffs2_sb_info *c);
87extern void jffs2_release_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd);
88extern void jffs2_release_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref);
76 89
77extern int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname, 90extern int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname,
78 char *buffer, size_t size); 91 char *buffer, size_t size);
diff --git a/include/asm-arm/arch-s3c2410/regs-nand.h b/include/asm-arm/arch-s3c2410/regs-nand.h
index 7cff235e667a..c1470c695c33 100644
--- a/include/asm-arm/arch-s3c2410/regs-nand.h
+++ b/include/asm-arm/arch-s3c2410/regs-nand.h
@@ -39,10 +39,19 @@
39#define S3C2440_NFESTAT1 S3C2410_NFREG(0x28) 39#define S3C2440_NFESTAT1 S3C2410_NFREG(0x28)
40#define S3C2440_NFMECC0 S3C2410_NFREG(0x2C) 40#define S3C2440_NFMECC0 S3C2410_NFREG(0x2C)
41#define S3C2440_NFMECC1 S3C2410_NFREG(0x30) 41#define S3C2440_NFMECC1 S3C2410_NFREG(0x30)
42#define S3C2440_NFSECC S3C2410_NFREG(0x34) 42#define S3C2440_NFSECC S3C24E10_NFREG(0x34)
43#define S3C2440_NFSBLK S3C2410_NFREG(0x38) 43#define S3C2440_NFSBLK S3C2410_NFREG(0x38)
44#define S3C2440_NFEBLK S3C2410_NFREG(0x3C) 44#define S3C2440_NFEBLK S3C2410_NFREG(0x3C)
45 45
46#define S3C2412_NFSBLK S3C2410_NFREG(0x20)
47#define S3C2412_NFEBLK S3C2410_NFREG(0x24)
48#define S3C2412_NFSTAT S3C2410_NFREG(0x28)
49#define S3C2412_NFMECC_ERR0 S3C2410_NFREG(0x2C)
50#define S3C2412_NFMECC_ERR1 S3C2410_NFREG(0x30)
51#define S3C2412_NFMECC0 S3C2410_NFREG(0x34)
52#define S3C2412_NFMECC1 S3C2410_NFREG(0x38)
53#define S3C2412_NFSECC S3C2410_NFREG(0x3C)
54
46#define S3C2410_NFCONF_EN (1<<15) 55#define S3C2410_NFCONF_EN (1<<15)
47#define S3C2410_NFCONF_512BYTE (1<<14) 56#define S3C2410_NFCONF_512BYTE (1<<14)
48#define S3C2410_NFCONF_4STEP (1<<13) 57#define S3C2410_NFCONF_4STEP (1<<13)
@@ -77,5 +86,42 @@
77#define S3C2440_NFSTAT_RnB_CHANGE (1<<2) 86#define S3C2440_NFSTAT_RnB_CHANGE (1<<2)
78#define S3C2440_NFSTAT_ILLEGAL_ACCESS (1<<3) 87#define S3C2440_NFSTAT_ILLEGAL_ACCESS (1<<3)
79 88
89#define S3C2412_NFCONF_NANDBOOT (1<<31)
90#define S3C2412_NFCONF_ECCCLKCON (1<<30)
91#define S3C2412_NFCONF_ECC_MLC (1<<24)
92#define S3C2412_NFCONF_TACLS_MASK (7<<12) /* 1 extra bit of Tacls */
93
94#define S3C2412_NFCONT_ECC4_DIRWR (1<<18)
95#define S3C2412_NFCONT_LOCKTIGHT (1<<17)
96#define S3C2412_NFCONT_SOFTLOCK (1<<16)
97#define S3C2412_NFCONT_ECC4_ENCINT (1<<13)
98#define S3C2412_NFCONT_ECC4_DECINT (1<<12)
99#define S3C2412_NFCONT_MAIN_ECC_LOCK (1<<7)
100#define S3C2412_NFCONT_INIT_MAIN_ECC (1<<5)
101#define S3C2412_NFCONT_nFCE1 (1<<2)
102#define S3C2412_NFCONT_nFCE0 (1<<1)
103
104#define S3C2412_NFSTAT_ECC_ENCDONE (1<<7)
105#define S3C2412_NFSTAT_ECC_DECDONE (1<<6)
106#define S3C2412_NFSTAT_ILLEGAL_ACCESS (1<<5)
107#define S3C2412_NFSTAT_RnB_CHANGE (1<<4)
108#define S3C2412_NFSTAT_nFCE1 (1<<3)
109#define S3C2412_NFSTAT_nFCE0 (1<<2)
110#define S3C2412_NFSTAT_Res1 (1<<1)
111#define S3C2412_NFSTAT_READY (1<<0)
112
113#define S3C2412_NFECCERR_SERRDATA(x) (((x) >> 21) & 0xf)
114#define S3C2412_NFECCERR_SERRBIT(x) (((x) >> 18) & 0x7)
115#define S3C2412_NFECCERR_MERRDATA(x) (((x) >> 7) & 0x3ff)
116#define S3C2412_NFECCERR_MERRBIT(x) (((x) >> 4) & 0x7)
117#define S3C2412_NFECCERR_SPARE_ERR(x) (((x) >> 2) & 0x3)
118#define S3C2412_NFECCERR_MAIN_ERR(x) (((x) >> 2) & 0x3)
119#define S3C2412_NFECCERR_NONE (0)
120#define S3C2412_NFECCERR_1BIT (1)
121#define S3C2412_NFECCERR_MULTIBIT (2)
122#define S3C2412_NFECCERR_ECCAREA (3)
123
124
125
80#endif /* __ASM_ARM_REGS_NAND */ 126#endif /* __ASM_ARM_REGS_NAND */
81 127
diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h
index c6f70660b371..c9c760700bc3 100644
--- a/include/linux/jffs2.h
+++ b/include/linux/jffs2.h
@@ -186,6 +186,7 @@ struct jffs2_raw_xref
186 jint32_t hdr_crc; 186 jint32_t hdr_crc;
187 jint32_t ino; /* inode number */ 187 jint32_t ino; /* inode number */
188 jint32_t xid; /* XATTR identifier number */ 188 jint32_t xid; /* XATTR identifier number */
189 jint32_t xseqno; /* xref sequencial number */
189 jint32_t node_crc; 190 jint32_t node_crc;
190} __attribute__((packed)); 191} __attribute__((packed));
191 192