Commit 936813a8807c5684c6a97f1081b31027403d4a93

Authored by Linus Torvalds

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

Showing 34 changed files Side-by-side Diff

drivers/mtd/chips/cfi_cmdset_0001.c
... ... @@ -357,6 +357,7 @@
357 357 mtd->resume = cfi_intelext_resume;
358 358 mtd->flags = MTD_CAP_NORFLASH;
359 359 mtd->name = map->name;
  360 + mtd->writesize = 1;
360 361  
361 362 mtd->reboot_notifier.notifier_call = cfi_intelext_reboot;
362 363  
drivers/mtd/chips/jedec.c
... ... @@ -256,6 +256,7 @@
256 256 MTD->name = map->name;
257 257 MTD->type = MTD_NORFLASH;
258 258 MTD->flags = MTD_CAP_NORFLASH;
  259 + MTD->writesize = 1;
259 260 MTD->erasesize = SectorSize*(map->buswidth);
260 261 // printk("MTD->erasesize is %x\n",(unsigned int)MTD->erasesize);
261 262 MTD->size = priv->size;
drivers/mtd/chips/map_absent.c
... ... @@ -64,7 +64,8 @@
64 64 mtd->write = map_absent_write;
65 65 mtd->sync = map_absent_sync;
66 66 mtd->flags = 0;
67   - mtd->erasesize = PAGE_SIZE;
  67 + mtd->erasesize = PAGE_SIZE;
  68 + mtd->writesize = 1;
68 69  
69 70 __module_get(THIS_MODULE);
70 71 return mtd;
drivers/mtd/chips/map_ram.c
... ... @@ -71,6 +71,7 @@
71 71 mtd->write = mapram_write;
72 72 mtd->sync = mapram_nop;
73 73 mtd->flags = MTD_CAP_RAM;
  74 + mtd->writesize = 1;
74 75  
75 76 mtd->erasesize = PAGE_SIZE;
76 77 while(mtd->size & (mtd->erasesize - 1))
drivers/mtd/chips/map_rom.c
... ... @@ -47,6 +47,7 @@
47 47 mtd->sync = maprom_nop;
48 48 mtd->flags = MTD_CAP_ROM;
49 49 mtd->erasesize = map->size;
  50 + mtd->writesize = 1;
50 51  
51 52 __module_get(THIS_MODULE);
52 53 return mtd;
drivers/mtd/devices/block2mtd.c
... ... @@ -324,6 +324,7 @@
324 324  
325 325 dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
326 326 dev->mtd.erasesize = erase_size;
  327 + dev->mtd.writesize = 1;
327 328 dev->mtd.type = MTD_RAM;
328 329 dev->mtd.flags = MTD_CAP_RAM;
329 330 dev->mtd.erase = block2mtd_erase;
drivers/mtd/devices/ms02-nv.c
... ... @@ -225,6 +225,7 @@
225 225 mtd->owner = THIS_MODULE;
226 226 mtd->read = ms02nv_read;
227 227 mtd->write = ms02nv_write;
  228 + mtd->writesize = 1;
228 229  
229 230 ret = -EIO;
230 231 if (add_mtd_device(mtd)) {
drivers/mtd/devices/mtd_dataflash.c
... ... @@ -478,6 +478,7 @@
478 478 device->name = (pdata && pdata->name) ? pdata->name : priv->name;
479 479 device->size = nr_pages * pagesize;
480 480 device->erasesize = pagesize;
  481 + device->writesize = pagesize;
481 482 device->owner = THIS_MODULE;
482 483 device->type = MTD_DATAFLASH;
483 484 device->flags = MTD_CAP_NORFLASH;
drivers/mtd/devices/phram.c
... ... @@ -151,6 +151,7 @@
151 151 new->mtd.owner = THIS_MODULE;
152 152 new->mtd.type = MTD_RAM;
153 153 new->mtd.erasesize = PAGE_SIZE;
  154 + new->mtd.writesize = 1;
154 155  
155 156 ret = -EAGAIN;
156 157 if (add_mtd_device(&new->mtd)) {
drivers/mtd/devices/pmc551.c
... ... @@ -778,7 +778,8 @@
778 778 mtd->type = MTD_RAM;
779 779 mtd->name = "PMC551 RAM board";
780 780 mtd->erasesize = 0x10000;
781   - mtd->owner = THIS_MODULE;
  781 + mtd->writesize = 1;
  782 + mtd->owner = THIS_MODULE;
782 783  
783 784 if (add_mtd_device(mtd)) {
784 785 printk(KERN_NOTICE "pmc551: Failed to register new device\n");
drivers/mtd/devices/slram.c
... ... @@ -209,6 +209,7 @@
209 209 (*curmtd)->mtdinfo->owner = THIS_MODULE;
210 210 (*curmtd)->mtdinfo->type = MTD_RAM;
211 211 (*curmtd)->mtdinfo->erasesize = SLRAM_BLK_SZ;
  212 + (*curmtd)->mtdinfo->writesize = 1;
212 213  
213 214 if (add_mtd_device((*curmtd)->mtdinfo)) {
214 215 E("slram: Failed to register new device\n");
drivers/mtd/maps/ixp2000.c
... ... @@ -42,7 +42,6 @@
42 42 struct map_info map;
43 43 struct mtd_partition *partitions;
44 44 struct resource *res;
45   - int nr_banks;
46 45 };
47 46  
48 47 static inline unsigned long flash_bank_setup(struct map_info *map, unsigned long ofs)
... ... @@ -183,7 +182,6 @@
183 182 */
184 183 info->map.phys = NO_XIP;
185 184  
186   - info->nr_banks = ixp_data->nr_banks;
187 185 info->map.size = ixp_data->nr_banks * window_size;
188 186 info->map.bankwidth = 1;
189 187  
drivers/mtd/maps/physmap.c
... ... @@ -182,7 +182,7 @@
182 182  
183 183 static struct resource physmap_flash_resource = {
184 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 186 .flags = IORESOURCE_MEM,
187 187 };
188 188  
drivers/mtd/mtdchar.c
... ... @@ -78,7 +78,7 @@
78 78 return -EINVAL;
79 79 }
80 80  
81   - if (offset >= 0 && offset < mtd->size)
  81 + if (offset >= 0 && offset <= mtd->size)
82 82 return file->f_pos = offset;
83 83  
84 84 return -EINVAL;
drivers/mtd/nand/nand_base.c
... ... @@ -1176,7 +1176,7 @@
1176 1176  
1177 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 @@
1271 1271 sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd);
1272 1272 buf = nand_transfer_oob(chip, buf, ops);
1273 1273  
1274   - readlen -= ops->ooblen;
1275   - if (!readlen)
1276   - break;
1277   -
1278 1274 if (!(chip->options & NAND_NO_READRDY)) {
1279 1275 /*
1280 1276 * Apply delay or wait for ready/busy pin. Do this
... ... @@ -1288,6 +1284,10 @@
1288 1284 nand_wait_ready(mtd);
1289 1285 }
1290 1286  
  1287 + readlen -= ops->ooblen;
  1288 + if (!readlen)
  1289 + break;
  1290 +
1291 1291 /* Increment page address */
1292 1292 realpage++;
1293 1293  
1294 1294  
... ... @@ -1610,12 +1610,12 @@
1610 1610 if (!writelen)
1611 1611 return 0;
1612 1612  
  1613 + chipnr = (int)(to >> chip->chip_shift);
  1614 + chip->select_chip(mtd, chipnr);
  1615 +
1613 1616 /* Check, if it is write protected */
1614 1617 if (nand_check_wp(mtd))
1615 1618 return -EIO;
1616   -
1617   - chipnr = (int)(to >> chip->chip_shift);
1618   - chip->select_chip(mtd, chipnr);
1619 1619  
1620 1620 realpage = (int)(to >> chip->page_shift);
1621 1621 page = realpage & chip->pagemask;
drivers/mtd/nand/ndfc.c
... ... @@ -61,15 +61,15 @@
61 61  
62 62 static 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 66 if (cmd == NAND_CMD_NONE)
67 67 return;
68 68  
69 69 if (ctrl & NAND_CLE)
70   - writel(cmd & 0xFF, chip->IO_ADDR_W + NDFC_CMD);
  70 + writel(cmd & 0xFF, ndfc->ndfcbase + NDFC_CMD);
71 71 else
72   - writel(cmd & 0xFF, chip->IO_ADDR_W + NDFC_ALE);
  72 + writel(cmd & 0xFF, ndfc->ndfcbase + NDFC_ALE);
73 73 }
74 74  
75 75 static int ndfc_ready(struct mtd_info *mtd)
drivers/mtd/nand/s3c2410.c
... ... @@ -63,8 +63,6 @@
63 63 #include <asm/arch/regs-nand.h>
64 64 #include <asm/arch/nand.h>
65 65  
66   -#define PFX "s3c2410-nand: "
67   -
68 66 #ifdef CONFIG_MTD_NAND_S3C2410_HWECC
69 67 static int hardware_ecc = 1;
70 68 #else
... ... @@ -99,6 +97,12 @@
99 97 int scan_res;
100 98 };
101 99  
  100 +enum s3c_cpu_type {
  101 + TYPE_S3C2410,
  102 + TYPE_S3C2412,
  103 + TYPE_S3C2440,
  104 +};
  105 +
102 106 /* overview of the s3c2410 nand state */
103 107  
104 108 struct s3c2410_nand_info {
105 109  
... ... @@ -112,9 +116,11 @@
112 116 struct resource *area;
113 117 struct clk *clk;
114 118 void __iomem *regs;
  119 + void __iomem *sel_reg;
  120 + int sel_bit;
115 121 int mtd_count;
116 122  
117   - unsigned char is_s3c2440;
  123 + enum s3c_cpu_type cpu_type;
118 124 };
119 125  
120 126 /* conversion functions */
... ... @@ -148,7 +154,7 @@
148 154  
149 155 #define NS_IN_KHZ 1000000
150 156  
151   -static int s3c2410_nand_calc_rate(int wanted, unsigned long clk, int max)
  157 +static int s3c_nand_calc_rate(int wanted, unsigned long clk, int max)
152 158 {
153 159 int result;
154 160  
155 161  
156 162  
157 163  
158 164  
159 165  
160 166  
161 167  
162 168  
163 169  
164 170  
... ... @@ -172,53 +178,58 @@
172 178  
173 179 /* controller setup */
174 180  
175   -static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, struct platform_device *pdev)
  181 +static int s3c2410_nand_inithw(struct s3c2410_nand_info *info,
  182 + struct platform_device *pdev)
176 183 {
177 184 struct s3c2410_platform_nand *plat = to_nand_plat(pdev);
178 185 unsigned long clkrate = clk_get_rate(info->clk);
  186 + int tacls_max = (info->cpu_type == TYPE_S3C2412) ? 8 : 4;
179 187 int tacls, twrph0, twrph1;
180   - unsigned long cfg;
  188 + unsigned long cfg = 0;
181 189  
182 190 /* calculate the timing information for the controller */
183 191  
184 192 clkrate /= 1000; /* turn clock into kHz for ease of use */
185 193  
186 194 if (plat != NULL) {
187   - tacls = s3c2410_nand_calc_rate(plat->tacls, clkrate, 4);
188   - twrph0 = s3c2410_nand_calc_rate(plat->twrph0, clkrate, 8);
189   - twrph1 = s3c2410_nand_calc_rate(plat->twrph1, clkrate, 8);
  195 + tacls = s3c_nand_calc_rate(plat->tacls, clkrate, tacls_max);
  196 + twrph0 = s3c_nand_calc_rate(plat->twrph0, clkrate, 8);
  197 + twrph1 = s3c_nand_calc_rate(plat->twrph1, clkrate, 8);
190 198 } else {
191 199 /* default timings */
192   - tacls = 4;
  200 + tacls = tacls_max;
193 201 twrph0 = 8;
194 202 twrph1 = 8;
195 203 }
196 204  
197 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 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 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 215 cfg = S3C2410_NFCONF_EN;
207 216 cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
208 217 cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
209 218 cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
210   - } else {
  219 + break;
  220 +
  221 + case TYPE_S3C2440:
  222 + case TYPE_S3C2412:
211 223 cfg = S3C2440_NFCONF_TACLS(tacls - 1);
212 224 cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
213 225 cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
214 226  
215 227 /* enable the controller and de-assert nFCE */
216 228  
217   - writel(S3C2440_NFCONT_ENABLE | S3C2440_NFCONT_ENABLE,
218   - info->regs + S3C2440_NFCONT);
  229 + writel(S3C2440_NFCONT_ENABLE, 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 234 writel(cfg, info->regs + S3C2410_NFCONF);
224 235 return 0;
225 236  
226 237  
227 238  
228 239  
229 240  
... ... @@ -231,26 +242,21 @@
231 242 struct s3c2410_nand_info *info;
232 243 struct s3c2410_nand_mtd *nmtd;
233 244 struct nand_chip *this = mtd->priv;
234   - void __iomem *reg;
235 245 unsigned long cur;
236   - unsigned long bit;
237 246  
238 247 nmtd = this->priv;
239 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 250 if (chip != -1 && allow_clk_stop(info))
245 251 clk_enable(info->clk);
246 252  
247   - cur = readl(reg);
  253 + cur = readl(info->sel_reg);
248 254  
249 255 if (chip == -1) {
250   - cur |= bit;
  256 + cur |= info->sel_bit;
251 257 } else {
252 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 260 return;
255 261 }
256 262  
257 263  
... ... @@ -259,10 +265,10 @@
259 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 273 if (chip == -1 && allow_clk_stop(info))
268 274 clk_disable(info->clk);
269 275  
270 276  
... ... @@ -311,15 +317,25 @@
311 317 static int s3c2410_nand_devready(struct mtd_info *mtd)
312 318 {
313 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 320 return readb(info->regs + S3C2410_NFSTAT) & S3C2410_NFSTAT_BUSY;
318 321 }
319 322  
  323 +static 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 +
  329 +static 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 335 /* ECC handling functions */
321 336  
322   -static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
  337 +static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
  338 + u_char *read_ecc, u_char *calc_ecc)
323 339 {
324 340 pr_debug("s3c2410_nand_correct_data(%p,%p,%p,%p)\n", mtd, dat, read_ecc, calc_ecc);
325 341  
326 342  
... ... @@ -487,11 +503,8 @@
487 503 struct s3c2410_nand_set *set)
488 504 {
489 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 508 chip->write_buf = s3c2410_nand_write_buf;
496 509 chip->read_buf = s3c2410_nand_read_buf;
497 510 chip->select_chip = s3c2410_nand_select_chip;
498 511  
499 512  
500 513  
501 514  
... ... @@ -500,29 +513,63 @@
500 513 chip->options = 0;
501 514 chip->controller = &info->controller;
502 515  
503   - if (info->is_s3c2440) {
504   - chip->IO_ADDR_R = info->regs + S3C2440_NFDATA;
505   - chip->IO_ADDR_W = info->regs + S3C2440_NFDATA;
506   - chip->cmd_ctrl = s3c2440_nand_hwcontrol;
507   - }
  516 + switch (info->cpu_type) {
  517 + case TYPE_S3C2410:
  518 + chip->IO_ADDR_W = regs + S3C2410_NFDATA;
  519 + info->sel_reg = regs + S3C2410_NFCONF;
  520 + info->sel_bit = S3C2410_NFCONF_nFCE;
  521 + chip->cmd_ctrl = s3c2410_nand_hwcontrol;
  522 + chip->dev_ready = s3c2410_nand_devready;
  523 + break;
508 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;
  547 +
509 548 nmtd->info = info;
510 549 nmtd->mtd.priv = chip;
511 550 nmtd->mtd.owner = THIS_MODULE;
512 551 nmtd->set = set;
513 552  
514 553 if (hardware_ecc) {
515   - chip->ecc.correct = s3c2410_nand_correct_data;
516   - chip->ecc.hwctl = s3c2410_nand_enable_hwecc;
517 554 chip->ecc.calculate = s3c2410_nand_calculate_ecc;
  555 + chip->ecc.correct = s3c2410_nand_correct_data;
518 556 chip->ecc.mode = NAND_ECC_HW;
519 557 chip->ecc.size = 512;
520 558 chip->ecc.bytes = 3;
521 559 chip->ecc.layout = &nand_hw_eccoob;
522 560  
523   - if (info->is_s3c2440) {
524   - chip->ecc.hwctl = s3c2440_nand_enable_hwecc;
525   - chip->ecc.calculate = s3c2440_nand_calculate_ecc;
  561 + switch (info->cpu_type) {
  562 + case TYPE_S3C2410:
  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 574 } else {
528 575 chip->ecc.mode = NAND_ECC_SOFT;
... ... @@ -537,7 +584,8 @@
537 584 * nand layer to look for devices
538 585 */
539 586  
540   -static int s3c24xx_nand_probe(struct platform_device *pdev, int is_s3c2440)
  587 +static int s3c24xx_nand_probe(struct platform_device *pdev,
  588 + enum s3c_cpu_type cpu_type)
541 589 {
542 590 struct s3c2410_platform_nand *plat = to_nand_plat(pdev);
543 591 struct s3c2410_nand_info *info;
... ... @@ -592,7 +640,7 @@
592 640 info->device = &pdev->dev;
593 641 info->platform = plat;
594 642 info->regs = ioremap(res->start, size);
595   - info->is_s3c2440 = is_s3c2440;
  643 + info->cpu_type = cpu_type;
596 644  
597 645 if (info->regs == NULL) {
598 646 dev_err(&pdev->dev, "cannot reserve register region\n");
599 647  
600 648  
... ... @@ -699,14 +747,19 @@
699 747  
700 748 static 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  
705 753 static 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);
708 756 }
709 757  
  758 +static int s3c2412_nand_probe(struct platform_device *dev)
  759 +{
  760 + return s3c24xx_nand_probe(dev, TYPE_S3C2412);
  761 +}
  762 +
710 763 static struct platform_driver s3c2410_nand_driver = {
711 764 .probe = s3c2410_nand_probe,
712 765 .remove = s3c2410_nand_remove,
713 766  
714 767  
... ... @@ -729,16 +782,29 @@
729 782 },
730 783 };
731 784  
  785 +static 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 +
732 796 static int __init s3c2410_nand_init(void)
733 797 {
734 798 printk("S3C24XX NAND Driver, (c) 2004 Simtec Electronics\n");
735 799  
  800 + platform_driver_register(&s3c2412_nand_driver);
736 801 platform_driver_register(&s3c2440_nand_driver);
737 802 return platform_driver_register(&s3c2410_nand_driver);
738 803 }
739 804  
740 805 static void __exit s3c2410_nand_exit(void)
741 806 {
  807 + platform_driver_unregister(&s3c2412_nand_driver);
742 808 platform_driver_unregister(&s3c2440_nand_driver);
743 809 platform_driver_unregister(&s3c2410_nand_driver);
744 810 }
drivers/mtd/nand/ts7250.c
... ... @@ -97,7 +97,7 @@
97 97 unsigned long addr = TS72XX_NAND_CONTROL_VIRT_BASE;
98 98 unsigned char bits;
99 99  
100   - bits = (ctrl & NAND_CNE) << 2;
  100 + bits = (ctrl & NAND_NCE) << 2;
101 101 bits |= ctrl & NAND_CLE;
102 102 bits |= (ctrl & NAND_ALE) >> 2;
103 103  
... ... @@ -1116,7 +1116,7 @@
1116 1116  
1117 1117 config JFFS2_FS_XATTR
1118 1118 bool "JFFS2 XATTR support (EXPERIMENTAL)"
1119   - depends on JFFS2_FS && EXPERIMENTAL && !JFFS2_FS_WRITEBUFFER
  1119 + depends on JFFS2_FS && EXPERIMENTAL
1120 1120 default n
1121 1121 help
1122 1122 Extended attributes are name:value pairs associated with inodes by
... ... @@ -267,6 +267,8 @@
267 267 }
268 268  
269 269 rc = do_jffs2_setxattr(inode, xprefix, "", value, size, 0);
  270 + if (!value && rc == -ENODATA)
  271 + rc = 0;
270 272 if (value)
271 273 kfree(value);
272 274 if (!rc) {
... ... @@ -225,7 +225,6 @@
225 225 at the end of the linked list. Stash it and continue
226 226 from the beginning of the list */
227 227 ic = (struct jffs2_inode_cache *)(*prev);
228   - BUG_ON(ic->class != RAWNODE_CLASS_INODE_CACHE);
229 228 prev = &ic->nodes;
230 229 continue;
231 230 }
... ... @@ -249,7 +248,8 @@
249 248  
250 249 /* PARANOIA */
251 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 253 return;
254 254 }
255 255  
... ... @@ -274,8 +274,19 @@
274 274 printk("\n");
275 275 });
276 276  
277   - if (ic->nodes == (void *)ic && ic->nlink == 0)
278   - jffs2_del_ino_cache(c, ic);
  277 + switch (ic->class) {
  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  
281 292 void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
... ... @@ -227,8 +227,6 @@
227 227 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
228 228  
229 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 230 jffs2_do_clear_inode(c, f);
233 231 }
234 232  
... ... @@ -165,6 +165,7 @@
165 165 D1(printk(KERN_DEBUG "Skipping check of ino #%d with nlink zero\n",
166 166 ic->ino));
167 167 spin_unlock(&c->inocache_lock);
  168 + jffs2_xattr_delete_inode(c, ic);
168 169 continue;
169 170 }
170 171 switch(ic->state) {
171 172  
172 173  
... ... @@ -275,13 +276,12 @@
275 276 * We can decide whether this node is inode or xattr by ic->class. */
276 277 if (ic->class == RAWNODE_CLASS_XATTR_DATUM
277 278 || ic->class == RAWNODE_CLASS_XATTR_REF) {
278   - BUG_ON(raw->next_in_ino != (void *)ic);
279 279 spin_unlock(&c->erase_completion_lock);
280 280  
281 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 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 286 goto release_sem;
287 287 }
fs/jffs2/jffs2_fs_sb.h
... ... @@ -119,8 +119,11 @@
119 119 #ifdef CONFIG_JFFS2_FS_XATTR
120 120 #define XATTRINDEX_HASHSIZE (57)
121 121 uint32_t highest_xid;
  122 + uint32_t highest_xseqno;
122 123 struct list_head xattrindex[XATTRINDEX_HASHSIZE];
123 124 struct list_head xattr_unchecked;
  125 + struct list_head xattr_dead_list;
  126 + struct jffs2_xattr_ref *xref_dead_list;
124 127 struct jffs2_xattr_ref *xref_temp;
125 128 struct rw_semaphore xattr_sem;
126 129 uint32_t xdatum_mem_usage;
... ... @@ -291,6 +291,7 @@
291 291  
292 292 memset(xd, 0, sizeof(struct jffs2_xattr_datum));
293 293 xd->class = RAWNODE_CLASS_XATTR_DATUM;
  294 + xd->node = (void *)xd;
294 295 INIT_LIST_HEAD(&xd->xindex);
295 296 return xd;
296 297 }
... ... @@ -309,6 +310,7 @@
309 310  
310 311 memset(ref, 0, sizeof(struct jffs2_xattr_ref));
311 312 ref->class = RAWNODE_CLASS_XATTR_REF;
  313 + ref->node = (void *)ref;
312 314 return ref;
313 315 }
314 316  
... ... @@ -906,6 +906,9 @@
906 906 {
907 907 struct jffs2_inode_cache **prev;
908 908  
  909 +#ifdef CONFIG_JFFS2_FS_XATTR
  910 + BUG_ON(old->xref);
  911 +#endif
909 912 dbg_inocache("del %p (ino #%u)\n", old, old->ino);
910 913 spin_lock(&c->inocache_lock);
911 914  
... ... @@ -683,19 +683,26 @@
683 683 spin_lock(&c->erase_completion_lock);
684 684  
685 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 686 for (p = &ic->nodes; (*p) != ref; p = &((*p)->next_in_ino))
691 687 ;
692 688  
693 689 *p = ref->next_in_ino;
694 690 ref->next_in_ino = NULL;
695 691  
696   - if (ic->nodes == (void *)ic && ic->nlink == 0)
697   - jffs2_del_ino_cache(c, ic);
698   -
  692 + switch (ic->class) {
  693 +#ifdef CONFIG_JFFS2_FS_XATTR
  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 706 spin_unlock(&c->erase_completion_lock);
700 707 }
701 708  
fs/jffs2/readinode.c
... ... @@ -968,6 +968,7 @@
968 968 struct jffs2_full_dirent *fd, *fds;
969 969 int deleted;
970 970  
  971 + jffs2_xattr_delete_inode(c, f->inocache);
971 972 down(&f->sem);
972 973 deleted = f->inocache && !f->inocache->nlink;
973 974  
... ... @@ -317,20 +317,23 @@
317 317 struct jffs2_summary *s)
318 318 {
319 319 struct jffs2_xattr_datum *xd;
320   - uint32_t totlen, crc;
  320 + uint32_t xid, version, totlen, crc;
321 321 int err;
322 322  
323 323 crc = crc32(0, rx, sizeof(struct jffs2_raw_xattr) - 4);
324 324 if (crc != je32_to_cpu(rx->node_crc)) {
325   - if (je32_to_cpu(rx->node_crc) != 0xffffffff)
326   - JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
327   - ofs, je32_to_cpu(rx->node_crc), crc);
  325 + JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
  326 + ofs, je32_to_cpu(rx->node_crc), crc);
328 327 if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen))))
329 328 return err;
330 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 337 if (totlen != je32_to_cpu(rx->totlen)) {
335 338 JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u\n",
336 339 ofs, je32_to_cpu(rx->totlen), totlen);
337 340  
338 341  
339 342  
... ... @@ -339,23 +342,25 @@
339 342 return 0;
340 343 }
341 344  
342   - xd = jffs2_setup_xattr_datum(c, je32_to_cpu(rx->xid), je32_to_cpu(rx->version));
343   - 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   - }
  345 + xd = jffs2_setup_xattr_datum(c, xid, version);
  346 + if (IS_ERR(xd))
349 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);
357   - /* FIXME */ xd->node->next_in_ino = (void *)xd;
  349 + if (xd->version > version) {
  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);
358 360  
  361 + jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, (void *)xd);
  362 + }
  363 +
359 364 if (jffs2_sum_active())
360 365 jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset);
361 366 dbg_xattr("scaning xdatum at %#08x (xid=%u, version=%u)\n",
... ... @@ -373,9 +378,8 @@
373 378  
374 379 crc = crc32(0, rr, sizeof(*rr) - 4);
375 380 if (crc != je32_to_cpu(rr->node_crc)) {
376   - if (je32_to_cpu(rr->node_crc) != 0xffffffff)
377   - JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
378   - ofs, je32_to_cpu(rr->node_crc), crc);
  381 + JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
  382 + ofs, je32_to_cpu(rr->node_crc), crc);
379 383 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rr->totlen)))))
380 384 return err;
381 385 return 0;
... ... @@ -395,6 +399,7 @@
395 399 return -ENOMEM;
396 400  
397 401 /* BEFORE jffs2_build_xattr_subsystem() called,
  402 + * and AFTER xattr_ref is marked as a dead xref,
398 403 * ref->xid is used to store 32bit xid, xd is not used
399 404 * ref->ino is used to store 32bit inode-number, ic is not used
400 405 * Thoes variables are declared as union, thus using those
401 406  
... ... @@ -404,11 +409,13 @@
404 409 */
405 410 ref->ino = je32_to_cpu(rr->ino);
406 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 415 ref->next = c->xref_temp;
408 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);
411   - /* FIXME */ ref->node->next_in_ino = (void *)ref;
  418 + jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rr->totlen)), (void *)ref);
412 419  
413 420 if (jffs2_sum_active())
414 421 jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset);
... ... @@ -5,7 +5,7 @@
5 5 * Zoltan Sogor <weth@inf.u-szeged.hu>,
6 6 * Patrik Kluba <pajko@halom.u-szeged.hu>,
7 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 10 * For licensing information, see the file 'LICENCE' in this directory.
11 11 *
... ... @@ -310,8 +310,6 @@
310 310 #ifdef CONFIG_JFFS2_FS_XATTR
311 311 case JFFS2_NODETYPE_XATTR: {
312 312 struct jffs2_sum_xattr_mem *temp;
313   - if (je32_to_cpu(node->x.version) == 0xffffffff)
314   - return 0;
315 313 temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL);
316 314 if (!temp)
317 315 goto no_mem;
... ... @@ -327,10 +325,6 @@
327 325 }
328 326 case JFFS2_NODETYPE_XREF: {
329 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 328 temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL);
335 329 if (!temp)
336 330 goto no_mem;
337 331  
338 332  
... ... @@ -483,22 +477,20 @@
483 477  
484 478 xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid),
485 479 je32_to_cpu(spx->version));
486   - 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");
  480 + if (IS_ERR(xd))
495 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 494 *pseudo_random += je32_to_cpu(spx->xid);
503 495 sp += JFFS2_SUMMARY_XATTR_SIZE;
504 496  
505 497  
... ... @@ -519,14 +511,11 @@
519 511 JFFS2_NOTICE("allocation of xattr_datum failed\n");
520 512 return -ENOMEM;
521 513 }
522   - ref->ino = 0xfffffffe;
523   - ref->xid = 0xfffffffd;
524 514 ref->next = c->xref_temp;
525 515 c->xref_temp = ref;
526 516  
527   - ref->node = sum_link_node_ref(c, jeb, je32_to_cpu(spr->offset) | REF_UNCHECKED,
528   - PAD(sizeof(struct jffs2_raw_xref)), NULL);
529   - /* FIXME */ ref->node->next_in_ino = (void *)ref;
  517 + sum_link_node_ref(c, jeb, je32_to_cpu(spr->offset) | REF_UNCHECKED,
  518 + PAD(sizeof(struct jffs2_raw_xref)), (void *)ref);
530 519  
531 520 *pseudo_random += ref->node->flash_offset;
532 521 sp += JFFS2_SUMMARY_XREF_SIZE;
Changes suppressed. Click to show
... ... @@ -23,18 +23,15 @@
23 23 * xattr_datum_hashkey(xprefix, xname, xvalue, xsize)
24 24 * is used to calcurate xdatum hashkey. The reminder of hashkey into XATTRINDEX_HASHSIZE is
25 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 29 * unload_xattr_datum(c, xd)
27 30 * is used to release xattr name/value pair and detach from c->xattrindex.
28 31 * reclaim_xattr_datum(c)
29 32 * is used to reclaim xattr name/value pairs on the xattr name/value pair cache when
30 33 * memory usage by cache is over c->xdatum_mem_threshold. Currentry, this threshold
31 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 35 * do_verify_xattr_datum(c, xd)
39 36 * is used to load the xdatum informations without name/value pair from the medium.
40 37 * It's necessary once, because those informations are not collected during mounting
41 38  
... ... @@ -53,8 +50,10 @@
53 50 * is used to write xdatum to medium. xd->version will be incremented.
54 51 * create_xattr_datum(c, xprefix, xname, xvalue, xsize)
55 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   -
58 57 static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize)
59 58 {
60 59 int name_len = strlen(xname);
... ... @@ -62,6 +61,22 @@
62 61 return crc32(xprefix, xname, name_len) ^ crc32(xprefix, xvalue, xsize);
63 62 }
64 63  
  64 +static 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 +
65 80 static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
66 81 {
67 82 /* must be called under down_write(xattr_sem) */
68 83  
69 84  
70 85  
71 86  
72 87  
73 88  
... ... @@ -107,77 +122,33 @@
107 122 before, c->xdatum_mem_usage, before - c->xdatum_mem_usage);
108 123 }
109 124  
110   -static 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   -
145   -static 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   -
158 125 static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
159 126 {
160 127 /* must be called under down_write(xattr_sem) */
161 128 struct jffs2_eraseblock *jeb;
  129 + struct jffs2_raw_node_ref *raw;
162 130 struct jffs2_raw_xattr rx;
163 131 size_t readlen;
164   - uint32_t crc, totlen;
  132 + uint32_t crc, offset, totlen;
165 133 int rc;
166 134  
167   - BUG_ON(!xd->node);
168   - BUG_ON(ref_flags(xd->node) != REF_UNCHECKED);
  135 + spin_lock(&c->erase_completion_lock);
  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 142 if (rc || readlen != sizeof(rx)) {
172 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 145 return rc ? rc : -EIO;
175 146 }
176 147 crc = crc32(0, &rx, sizeof(rx) - 4);
177 148 if (crc != je32_to_cpu(rx.node_crc)) {
178   - if (je32_to_cpu(rx.node_crc) != 0xffffffff)
179   - JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
180   - ref_offset(xd->node), je32_to_cpu(rx.hdr_crc), crc);
  149 + JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
  150 + offset, je32_to_cpu(rx.hdr_crc), crc);
  151 + xd->flags |= JFFS2_XFLAGS_INVALID;
181 152 return EIO;
182 153 }
183 154 totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len));
184 155  
... ... @@ -188,11 +159,12 @@
188 159 || je32_to_cpu(rx.version) != xd->version) {
189 160 JFFS2_ERROR("inconsistent xdatum at %#08x, magic=%#04x/%#04x, "
190 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 163 je16_to_cpu(rx.nodetype), JFFS2_NODETYPE_XATTR,
193 164 je32_to_cpu(rx.totlen), totlen,
194 165 je32_to_cpu(rx.xid), xd->xid,
195 166 je32_to_cpu(rx.version), xd->version);
  167 + xd->flags |= JFFS2_XFLAGS_INVALID;
196 168 return EIO;
197 169 }
198 170 xd->xprefix = rx.xprefix;
199 171  
... ... @@ -200,14 +172,17 @@
200 172 xd->value_len = je16_to_cpu(rx.value_len);
201 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 175 spin_lock(&c->erase_completion_lock);
208   - c->unchecked_size -= totlen; c->used_size += totlen;
209   - jeb->unchecked_size -= totlen; jeb->used_size += totlen;
210   - xd->node->flash_offset = ref_offset(xd->node) | REF_PRISTINE;
  176 + complete:
  177 + for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
  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 186 spin_unlock(&c->erase_completion_lock);
212 187  
213 188 /* unchecked xdatum is chained with c->xattr_unchecked */
... ... @@ -227,7 +202,6 @@
227 202 uint32_t crc, length;
228 203 int i, ret, retry = 0;
229 204  
230   - BUG_ON(!xd->node);
231 205 BUG_ON(ref_flags(xd->node) != REF_PRISTINE);
232 206 BUG_ON(!list_empty(&xd->xindex));
233 207 retry:
... ... @@ -253,6 +227,7 @@
253 227 " at %#08x, read: 0x%08x calculated: 0x%08x\n",
254 228 ref_offset(xd->node), xd->data_crc, crc);
255 229 kfree(data);
  230 + xd->flags |= JFFS2_XFLAGS_INVALID;
256 231 return EIO;
257 232 }
258 233  
259 234  
260 235  
... ... @@ -286,16 +261,14 @@
286 261 * rc > 0 : Unrecoverable error, this node should be deleted.
287 262 */
288 263 int rc = 0;
289   - BUG_ON(xd->xname);
290   - if (!xd->node)
  264 +
  265 + BUG_ON(xd->flags & JFFS2_XFLAGS_DEAD);
  266 + if (xd->xname)
  267 + return 0;
  268 + if (xd->flags & JFFS2_XFLAGS_INVALID)
291 269 return EIO;
292   - if (unlikely(ref_flags(xd->node) != REF_PRISTINE)) {
  270 + if (unlikely(is_xattr_datum_unchecked(c, xd)))
293 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 272 if (!rc)
300 273 rc = do_load_xattr_datum(c, xd);
301 274 return rc;
... ... @@ -304,7 +277,6 @@
304 277 static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
305 278 {
306 279 /* must be called under down_write(xattr_sem) */
307   - struct jffs2_raw_node_ref *raw;
308 280 struct jffs2_raw_xattr rx;
309 281 struct kvec vecs[2];
310 282 size_t length;
311 283  
312 284  
... ... @@ -312,14 +284,16 @@
312 284 uint32_t phys_ofs = write_ofs(c);
313 285  
314 286 BUG_ON(!xd->xname);
  287 + BUG_ON(xd->flags & (JFFS2_XFLAGS_DEAD|JFFS2_XFLAGS_INVALID));
315 288  
316 289 vecs[0].iov_base = &rx;
317   - vecs[0].iov_len = PAD(sizeof(rx));
  290 + vecs[0].iov_len = sizeof(rx);
318 291 vecs[1].iov_base = xd->xname;
319 292 vecs[1].iov_len = xd->name_len + 1 + xd->value_len;
320 293 totlen = vecs[0].iov_len + vecs[1].iov_len;
321 294  
322 295 /* Setup raw-xattr */
  296 + memset(&rx, 0, sizeof(rx));
323 297 rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
324 298 rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR);
325 299 rx.totlen = cpu_to_je32(PAD(totlen));
326 300  
327 301  
... ... @@ -343,15 +317,9 @@
343 317  
344 318 return rc;
345 319 }
346   -
347 320 /* success */
348   - raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(totlen), NULL);
349   - /* FIXME */ raw->next_in_ino = (void *)xd;
  321 + jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(totlen), (void *)xd);
350 322  
351   - if (xd->node)
352   - delete_xattr_datum_node(c, xd);
353   - xd->node = raw;
354   -
355 323 dbg_xattr("success on saving xdatum (xid=%u, version=%u, xprefix=%u, xname='%s')\n",
356 324 xd->xid, xd->version, xd->xprefix, xd->xname);
357 325  
... ... @@ -377,7 +345,7 @@
377 345 && xd->value_len==xsize
378 346 && !strcmp(xd->xname, xname)
379 347 && !memcmp(xd->xvalue, xvalue, xsize)) {
380   - xd->refcnt++;
  348 + atomic_inc(&xd->refcnt);
381 349 return xd;
382 350 }
383 351 }
... ... @@ -397,7 +365,7 @@
397 365 strcpy(data, xname);
398 366 memcpy(data + name_len + 1, xvalue, xsize);
399 367  
400   - xd->refcnt = 1;
  368 + atomic_set(&xd->refcnt, 1);
401 369 xd->xid = ++c->highest_xid;
402 370 xd->flags |= JFFS2_XFLAGS_HOT;
403 371 xd->xprefix = xprefix;
404 372  
405 373  
406 374  
... ... @@ -426,20 +394,36 @@
426 394 return xd;
427 395 }
428 396  
  397 +static 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 415 /* -------- xref related functions ------------------
430 416 * verify_xattr_ref(c, ref)
431 417 * is used to load xref information from medium. Because summary data does not
432 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 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 422 * create_xattr_ref(c, ic, xd)
442 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 427 * jffs2_xattr_delete_inode(c, ic)
444 428 * is called to remove xrefs related to obsolete inode when inode is unlinked.
445 429 * jffs2_xattr_free_inode(c, ic)
446 430  
447 431  
448 432  
449 433  
450 434  
... ... @@ -450,25 +434,29 @@
450 434 static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
451 435 {
452 436 struct jffs2_eraseblock *jeb;
  437 + struct jffs2_raw_node_ref *raw;
453 438 struct jffs2_raw_xref rr;
454 439 size_t readlen;
455   - uint32_t crc, totlen;
  440 + uint32_t crc, offset, totlen;
456 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 450 if (rc || sizeof(rr) != readlen) {
462 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 453 return rc ? rc : -EIO;
465 454 }
466 455 /* obsolete node */
467 456 crc = crc32(0, &rr, sizeof(rr) - 4);
468 457 if (crc != je32_to_cpu(rr.node_crc)) {
469   - if (je32_to_cpu(rr.node_crc) != 0xffffffff)
470   - JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
471   - ref_offset(ref->node), je32_to_cpu(rr.node_crc), crc);
  458 + JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
  459 + offset, je32_to_cpu(rr.node_crc), crc);
472 460 return EIO;
473 461 }
474 462 if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK
475 463  
476 464  
477 465  
... ... @@ -476,22 +464,28 @@
476 464 || je32_to_cpu(rr.totlen) != PAD(sizeof(rr))) {
477 465 JFFS2_ERROR("inconsistent xref at %#08x, magic=%#04x/%#04x, "
478 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 468 je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF,
481 469 je32_to_cpu(rr.totlen), PAD(sizeof(rr)));
482 470 return EIO;
483 471 }
484 472 ref->ino = je32_to_cpu(rr.ino);
485 473 ref->xid = je32_to_cpu(rr.xid);
  474 + ref->xseqno = je32_to_cpu(rr.xseqno);
  475 + if (ref->xseqno > c->highest_xseqno)
  476 + c->highest_xseqno = (ref->xseqno & ~XREF_DELETE_MARKER);
486 477  
487   - /* fixup superblock/eraseblock info */
488   - jeb = &c->blocks[ref_offset(ref->node) / c->sector_size];
489   - totlen = PAD(sizeof(rr));
490   -
491 478 spin_lock(&c->erase_completion_lock);
492   - c->unchecked_size -= totlen; c->used_size += totlen;
493   - jeb->unchecked_size -= totlen; jeb->used_size += totlen;
494   - ref->node->flash_offset = ref_offset(ref->node) | REF_PRISTINE;
  479 + complete:
  480 + for (raw=ref->node; raw != (void *)ref; raw=raw->next_in_ino) {
  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 489 spin_unlock(&c->erase_completion_lock);
496 490  
497 491 dbg_xattr("success on verifying xref (ino=%u, xid=%u) at %#08x\n",
498 492  
499 493  
... ... @@ -499,58 +493,12 @@
499 493 return 0;
500 494 }
501 495  
502   -static 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   -
532   -static 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   -
547 496 static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
548 497 {
549 498 /* must be called under down_write(xattr_sem) */
550   - struct jffs2_raw_node_ref *raw;
551 499 struct jffs2_raw_xref rr;
552 500 size_t length;
553   - uint32_t phys_ofs = write_ofs(c);
  501 + uint32_t xseqno, phys_ofs = write_ofs(c);
554 502 int ret;
555 503  
556 504 rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
... ... @@ -558,8 +506,16 @@
558 506 rr.totlen = cpu_to_je32(PAD(sizeof(rr)));
559 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);
562   - rr.xid = cpu_to_je32(ref->xd->xid);
  509 + xseqno = (c->highest_xseqno += 2);
  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 519 rr.node_crc = cpu_to_je32(crc32(0, &rr, sizeof(rr) - 4));
564 520  
565 521 ret = jffs2_flash_write(c, phys_ofs, sizeof(rr), &length, (char *)&rr);
566 522  
... ... @@ -572,13 +528,10 @@
572 528  
573 529 return ret;
574 530 }
  531 + /* success */
  532 + ref->xseqno = xseqno;
  533 + jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), (void *)ref);
575 534  
576   - raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), NULL);
577   - /* FIXME */ raw->next_in_ino = (void *)ref;
578   - if (ref->node)
579   - delete_xattr_ref_node(c, ref);
580   - ref->node = raw;
581   -
582 535 dbg_xattr("success on saving xref (ino=%u, xid=%u)\n", ref->ic->ino, ref->xd->xid);
583 536  
584 537 return 0;
... ... @@ -610,6 +563,27 @@
610 563 return ref; /* success */
611 564 }
612 565  
  566 +static 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 +
613 587 void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
614 588 {
615 589 /* It's called from jffs2_clear_inode() on inode removing.
... ... @@ -638,8 +612,7 @@
638 612 for (ref = ic->xref; ref; ref = _ref) {
639 613 _ref = ref->next;
640 614 xd = ref->xd;
641   - xd->refcnt--;
642   - if (!xd->refcnt) {
  615 + if (atomic_dec_and_test(&xd->refcnt)) {
643 616 unload_xattr_datum(c, xd);
644 617 jffs2_free_xattr_datum(xd);
645 618 }
... ... @@ -655,7 +628,7 @@
655 628 * duplicate name/value pairs. If duplicate name/value pair would be found,
656 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 632 int rc = 0;
660 633  
661 634 if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED))
662 635  
... ... @@ -673,13 +646,13 @@
673 646 } else if (unlikely(rc < 0))
674 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 650 if (!cmp->xd->xname) {
678 651 ref->xd->flags |= JFFS2_XFLAGS_BIND;
679 652 rc = load_xattr_datum(c, cmp->xd);
680 653 ref->xd->flags &= ~JFFS2_XFLAGS_BIND;
681 654 if (unlikely(rc > 0)) {
682   - *pref = cmp->next;
  655 + *pcmp = cmp->next;
683 656 delete_xattr_ref(c, cmp);
684 657 goto retry;
685 658 } else if (unlikely(rc < 0))
... ... @@ -687,8 +660,13 @@
687 660 }
688 661 if (ref->xd->xprefix == cmp->xd->xprefix
689 662 && !strcmp(ref->xd->xname, cmp->xd->xname)) {
690   - *pref = cmp->next;
691   - delete_xattr_ref(c, cmp);
  663 + if (ref->xseqno > cmp->xseqno) {
  664 + *pcmp = cmp->next;
  665 + delete_xattr_ref(c, cmp);
  666 + } else {
  667 + *pref = ref->next;
  668 + delete_xattr_ref(c, ref);
  669 + }
692 670 goto retry;
693 671 }
694 672 }
695 673  
... ... @@ -719,9 +697,13 @@
719 697 for (i=0; i < XATTRINDEX_HASHSIZE; i++)
720 698 INIT_LIST_HEAD(&c->xattrindex[i]);
721 699 INIT_LIST_HEAD(&c->xattr_unchecked);
  700 + INIT_LIST_HEAD(&c->xattr_dead_list);
  701 + c->xref_dead_list = NULL;
722 702 c->xref_temp = NULL;
723 703  
724 704 init_rwsem(&c->xattr_sem);
  705 + c->highest_xid = 0;
  706 + c->highest_xseqno = 0;
725 707 c->xdatum_mem_usage = 0;
726 708 c->xdatum_mem_threshold = 32 * 1024; /* Default 32KB */
727 709 }
728 710  
... ... @@ -751,8 +733,12 @@
751 733 _ref = ref->next;
752 734 jffs2_free_xattr_ref(ref);
753 735 }
754   - c->xref_temp = NULL;
755 736  
  737 + for (ref=c->xref_dead_list; ref; ref = _ref) {
  738 + _ref = ref->next;
  739 + jffs2_free_xattr_ref(ref);
  740 + }
  741 +
756 742 for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
757 743 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
758 744 list_del(&xd->xindex);
759 745  
760 746  
761 747  
762 748  
763 749  
764 750  
765 751  
766 752  
767 753  
768 754  
769 755  
770 756  
771 757  
772 758  
773 759  
774 760  
775 761  
776 762  
777 763  
778 764  
... ... @@ -761,101 +747,144 @@
761 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)
766 758 void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
767 759 {
768 760 struct jffs2_xattr_ref *ref, *_ref;
  761 + struct jffs2_xattr_ref *xref_tmphash[XREF_TMPHASH_SIZE];
769 762 struct jffs2_xattr_datum *xd, *_xd;
770 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 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 773 for (ref=c->xref_temp; ref; ref=_ref) {
  774 + struct jffs2_xattr_ref *tmp;
  775 +
777 776 _ref = ref->next;
778   - /* checking REF_UNCHECKED nodes */
779 777 if (ref_flags(ref->node) != REF_PRISTINE) {
780 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 782 jffs2_free_xattr_ref(ref);
783 783 continue;
784 784 }
785 785 }
786   - /* At this point, ref->xid and ref->ino contain XID and inode number.
787   - ref->xd and ref->ic are not valid yet. */
788   - xd = jffs2_find_xattr_datum(c, ref->xid);
789   - ic = jffs2_get_ino_cache(c, ref->ino);
790   - if (!xd || !ic) {
791   - if (ref_flags(ref->node) != REF_UNCHECKED)
792   - JFFS2_WARNING("xref(ino=%u, xid=%u) is orphan. \n",
793   - ref->ino, ref->xid);
794   - delete_xattr_ref_node(c, ref);
  786 +
  787 + i = (ref->ino ^ ref->xid) % XREF_TMPHASH_SIZE;
  788 + for (tmp=xref_tmphash[i]; tmp; tmp=tmp->next) {
  789 + if (tmp->ino == ref->ino && tmp->xid == ref->xid)
  790 + break;
  791 + }
  792 + if (tmp) {
  793 + raw = ref->node;
  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 802 jffs2_free_xattr_ref(ref);
796 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 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 844 for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
810 845 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
  846 + xdatum_count++;
811 847 list_del_init(&xd->xindex);
812   - if (!xd->refcnt) {
813   - if (ref_flags(xd->node) != REF_UNCHECKED)
814   - JFFS2_WARNING("orphan xdatum(xid=%u, version=%u) at %#08x\n",
815   - xd->xid, xd->version, ref_offset(xd->node));
816   - delete_xattr_datum(c, xd);
  848 + if (!atomic_read(&xd->refcnt)) {
  849 + dbg_xattr("xdatum(xid=%u, version=%u) is orphan.\n",
  850 + xd->xid, xd->version);
  851 + xd->flags |= JFFS2_XFLAGS_DEAD;
  852 + list_add(&xd->xindex, &c->xattr_unchecked);
  853 + xdatum_orphan_count++;
817 854 continue;
818 855 }
819   - if (ref_flags(xd->node) != REF_PRISTINE) {
820   - dbg_xattr("unchecked xdatum(xid=%u) at %#08x\n",
821   - xd->xid, ref_offset(xd->node));
  856 + if (is_xattr_datum_unchecked(c, xd)) {
  857 + dbg_xattr("unchecked xdatum(xid=%u, version=%u)\n",
  858 + xd->xid, xd->version);
822 859 list_add(&xd->xindex, &c->xattr_unchecked);
823 860 xdatum_unchecked_count++;
824 861 }
825   - xdatum_count++;
826 862 }
827 863 }
828 864 /* build complete */
829   - JFFS2_NOTICE("complete building xattr subsystem, %u of xdatum (%u unchecked) and "
830   - "%u of xref found.\n", xdatum_count, xdatum_unchecked_count, xref_count);
  865 + JFFS2_NOTICE("complete building xattr subsystem, %u of xdatum"
  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  
833 872 struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
834 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);
839   - if (_xd) {
840   - dbg_xattr("duplicate xdatum (xid=%u, version=%u/%u) at %#08x\n",
841   - xid, version, _xd->version, ref_offset(_xd->node));
842   - if (version < _xd->version)
843   - return ERR_PTR(-EEXIST);
  877 + xd = jffs2_find_xattr_datum(c, xid);
  878 + if (!xd) {
  879 + xd = jffs2_alloc_xattr_datum();
  880 + if (!xd)
  881 + return ERR_PTR(-ENOMEM);
  882 + xd->xid = xid;
  883 + xd->version = version;
  884 + if (xd->xid > c->highest_xid)
  885 + c->highest_xid = xd->xid;
  886 + list_add_tail(&xd->xindex, &c->xattrindex[xid % XATTRINDEX_HASHSIZE]);
844 887 }
845   - xd = jffs2_alloc_xattr_datum();
846   - if (!xd)
847   - return ERR_PTR(-ENOMEM);
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   - }
859 888 return xd;
860 889 }
861 890  
... ... @@ -1080,9 +1109,23 @@
1080 1109 goto out;
1081 1110 }
1082 1111 if (!buffer) {
1083   - *pref = ref->next;
1084   - delete_xattr_ref(c, ref);
1085   - rc = 0;
  1112 + ref->ino = ic->ino;
  1113 + ref->xid = xd->xid;
  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 1129 goto out;
1087 1130 }
1088 1131 goto found;
... ... @@ -1094,7 +1137,7 @@
1094 1137 goto out;
1095 1138 }
1096 1139 if (!buffer) {
1097   - rc = -EINVAL;
  1140 + rc = -ENODATA;
1098 1141 goto out;
1099 1142 }
1100 1143 found:
1101 1144  
1102 1145  
... ... @@ -1110,16 +1153,14 @@
1110 1153 request = PAD(sizeof(struct jffs2_raw_xref));
1111 1154 rc = jffs2_reserve_space(c, request, &length,
1112 1155 ALLOC_NORMAL, JFFS2_SUMMARY_XREF_SIZE);
  1156 + down_write(&c->xattr_sem);
1113 1157 if (rc) {
1114 1158 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);
1115   - down_write(&c->xattr_sem);
1116   - xd->refcnt--;
1117   - if (!xd->refcnt)
  1159 + if (atomic_dec_and_test(&xd->refcnt))
1118 1160 delete_xattr_datum(c, xd);
1119 1161 up_write(&c->xattr_sem);
1120 1162 return rc;
1121 1163 }
1122   - down_write(&c->xattr_sem);
1123 1164 if (ref)
1124 1165 *pref = ref->next;
1125 1166 newref = create_xattr_ref(c, ic, xd);
... ... @@ -1129,8 +1170,7 @@
1129 1170 ic->xref = ref;
1130 1171 }
1131 1172 rc = PTR_ERR(newref);
1132   - xd->refcnt--;
1133   - if (!xd->refcnt)
  1173 + if (atomic_dec_and_test(&xd->refcnt))
1134 1174 delete_xattr_datum(c, xd);
1135 1175 } else if (ref) {
1136 1176 delete_xattr_ref(c, ref);
1137 1177  
1138 1178  
1139 1179  
1140 1180  
1141 1181  
1142 1182  
1143 1183  
1144 1184  
1145 1185  
... ... @@ -1142,38 +1182,40 @@
1142 1182 }
1143 1183  
1144 1184 /* -------- garbage collector functions -------------
1145   - * jffs2_garbage_collect_xattr_datum(c, xd)
  1185 + * jffs2_garbage_collect_xattr_datum(c, xd, raw)
1146 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 1188 * is used to move xref into new node.
1149 1189 * jffs2_verify_xattr(c)
1150 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 * -------------------------------------------------- */
1152   -int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
  1196 +int 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 1199 uint32_t totlen, length, old_ofs;
1155   - int rc = -EINVAL;
  1200 + int rc = 0;
1156 1201  
1157 1202 down_write(&c->xattr_sem);
1158   - BUG_ON(!xd->node);
1159   -
1160   - old_ofs = ref_offset(xd->node);
1161   - totlen = ref_totlen(c, c->gcblock, xd->node);
1162   - if (totlen < sizeof(struct jffs2_raw_xattr))
  1203 + if (xd->node != raw)
1163 1204 goto out;
  1205 + if (xd->flags & (JFFS2_XFLAGS_DEAD|JFFS2_XFLAGS_INVALID))
  1206 + goto out;
1164 1207  
1165   - if (!xd->xname) {
1166   - rc = load_xattr_datum(c, xd);
1167   - if (unlikely(rc > 0)) {
1168   - delete_xattr_datum_node(c, xd);
1169   - rc = 0;
1170   - goto out;
1171   - } else if (unlikely(rc < 0))
1172   - goto out;
  1208 + rc = load_xattr_datum(c, xd);
  1209 + if (unlikely(rc)) {
  1210 + rc = (rc > 0) ? 0 : rc;
  1211 + 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 1216 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE);
1175   - if (rc || length < totlen) {
1176   - JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, totlen);
  1217 + if (rc) {
  1218 + JFFS2_WARNING("jffs2_reserve_space_gc()=%d, request=%u\n", rc, totlen);
1177 1219 rc = rc ? rc : -EBADFD;
1178 1220 goto out;
1179 1221 }
1180 1222  
1181 1223  
1182 1224  
1183 1225  
1184 1226  
... ... @@ -1182,27 +1224,32 @@
1182 1224 dbg_xattr("xdatum (xid=%u, version=%u) GC'ed from %#08x to %08x\n",
1183 1225 xd->xid, xd->version, old_ofs, ref_offset(xd->node));
1184 1226 out:
  1227 + if (!rc)
  1228 + jffs2_mark_node_obsolete(c, raw);
1185 1229 up_write(&c->xattr_sem);
1186 1230 return rc;
1187 1231 }
1188 1232  
1189   -
1190   -int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
  1233 +int 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 1236 uint32_t totlen, length, old_ofs;
1193   - int rc = -EINVAL;
  1237 + int rc = 0;
1194 1238  
1195 1239 down_write(&c->xattr_sem);
1196 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 1247 old_ofs = ref_offset(ref->node);
1199 1248 totlen = ref_totlen(c, c->gcblock, ref->node);
1200   - if (totlen != sizeof(struct jffs2_raw_xref))
1201   - goto out;
1202 1249  
1203 1250 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE);
1204   - if (rc || length < totlen) {
1205   - JFFS2_WARNING("%s: jffs2_reserve_space() = %d, request = %u\n",
  1251 + if (rc) {
  1252 + JFFS2_WARNING("%s: jffs2_reserve_space_gc() = %d, request = %u\n",
1206 1253 __FUNCTION__, rc, totlen);
1207 1254 rc = rc ? rc : -EBADFD;
1208 1255 goto out;
... ... @@ -1212,6 +1259,8 @@
1212 1259 dbg_xattr("xref (ino=%u, xid=%u) GC'ed from %#08x to %08x\n",
1213 1260 ref->ic->ino, ref->xd->xid, old_ofs, ref_offset(ref->node));
1214 1261 out:
  1262 + if (!rc)
  1263 + jffs2_mark_node_obsolete(c, raw);
1215 1264 up_write(&c->xattr_sem);
1216 1265 return rc;
1217 1266 }
1218 1267  
1219 1268  
1220 1269  
1221 1270  
... ... @@ -1219,21 +1268,60 @@
1219 1268 int jffs2_verify_xattr(struct jffs2_sb_info *c)
1220 1269 {
1221 1270 struct jffs2_xattr_datum *xd, *_xd;
  1271 + struct jffs2_eraseblock *jeb;
  1272 + struct jffs2_raw_node_ref *raw;
  1273 + uint32_t totlen;
1222 1274 int rc;
1223 1275  
1224 1276 down_write(&c->xattr_sem);
1225 1277 list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) {
1226 1278 rc = do_verify_xattr_datum(c, xd);
1227   - if (rc == 0) {
1228   - list_del_init(&xd->xindex);
1229   - break;
1230   - } else if (rc > 0) {
1231   - list_del_init(&xd->xindex);
1232   - delete_xattr_datum_node(c, xd);
  1279 + if (rc < 0)
  1280 + continue;
  1281 + list_del_init(&xd->xindex);
  1282 + spin_lock(&c->erase_completion_lock);
  1283 + for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
  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 1297 up_write(&c->xattr_sem);
1236   -
1237 1298 return list_empty(&c->xattr_unchecked) ? 1 : 0;
  1299 +}
  1300 +
  1301 +void 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 +
  1311 +void 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);
1238 1326 }
... ... @@ -16,6 +16,8 @@
16 16  
17 17 #define JFFS2_XFLAGS_HOT (0x01) /* This datum is HOT */
18 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  
20 22 struct jffs2_xattr_datum
21 23 {
22 24  
... ... @@ -23,10 +25,10 @@
23 25 struct jffs2_raw_node_ref *node;
24 26 uint8_t class;
25 27 uint8_t flags;
26   - uint16_t xprefix; /* see JFFS2_XATTR_PREFIX_* */
  28 + uint16_t xprefix; /* see JFFS2_XATTR_PREFIX_* */
27 29  
28 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 32 uint32_t xid;
31 33 uint32_t version;
32 34  
... ... @@ -47,6 +49,7 @@
47 49 uint8_t flags; /* Currently unused */
48 50 u16 unused;
49 51  
  52 + uint32_t xseqno;
50 53 union {
51 54 struct jffs2_inode_cache *ic; /* reference to jffs2_inode_cache */
52 55 uint32_t ino; /* only used in scanning/building */
... ... @@ -58,6 +61,12 @@
58 61 struct jffs2_xattr_ref *next; /* chained from ic->xref_list */
59 62 };
60 63  
  64 +#define XREF_DELETE_MARKER (0x00000001)
  65 +static inline int is_xattr_ref_dead(struct jffs2_xattr_ref *ref)
  66 +{
  67 + return ((ref->xseqno & XREF_DELETE_MARKER) != 0);
  68 +}
  69 +
61 70 #ifdef CONFIG_JFFS2_FS_XATTR
62 71  
63 72 extern void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c);
64 73  
... ... @@ -70,9 +79,13 @@
70 79 extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
71 80 extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
72 81  
73   -extern int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd);
74   -extern int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref);
  82 +extern int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd,
  83 + struct jffs2_raw_node_ref *raw);
  84 +extern int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref,
  85 + struct jffs2_raw_node_ref *raw);
75 86 extern int jffs2_verify_xattr(struct jffs2_sb_info *c);
  87 +extern void jffs2_release_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd);
  88 +extern void jffs2_release_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref);
76 89  
77 90 extern int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname,
78 91 char *buffer, size_t size);
include/asm-arm/arch-s3c2410/regs-nand.h
... ... @@ -39,10 +39,19 @@
39 39 #define S3C2440_NFESTAT1 S3C2410_NFREG(0x28)
40 40 #define S3C2440_NFMECC0 S3C2410_NFREG(0x2C)
41 41 #define S3C2440_NFMECC1 S3C2410_NFREG(0x30)
42   -#define S3C2440_NFSECC S3C2410_NFREG(0x34)
  42 +#define S3C2440_NFSECC S3C24E10_NFREG(0x34)
43 43 #define S3C2440_NFSBLK S3C2410_NFREG(0x38)
44 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 55 #define S3C2410_NFCONF_EN (1<<15)
47 56 #define S3C2410_NFCONF_512BYTE (1<<14)
48 57 #define S3C2410_NFCONF_4STEP (1<<13)
... ... @@ -76,6 +85,43 @@
76 85 #define S3C2440_NFSTAT_nCE (1<<1)
77 86 #define S3C2440_NFSTAT_RnB_CHANGE (1<<2)
78 87 #define S3C2440_NFSTAT_ILLEGAL_ACCESS (1<<3)
  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 +
79 125  
80 126 #endif /* __ASM_ARM_REGS_NAND */
include/linux/jffs2.h
... ... @@ -186,6 +186,7 @@
186 186 jint32_t hdr_crc;
187 187 jint32_t ino; /* inode number */
188 188 jint32_t xid; /* XATTR identifier number */
  189 + jint32_t xseqno; /* xref sequencial number */
189 190 jint32_t node_crc;
190 191 } __attribute__((packed));
191 192