Mercurial > ecos
annotate packages/fs/jffs2/current/src/write.c @ 3292:7f8e529b4d82 default tip
Fix FREESCALE_EDMA_NBYTES_MLOFFYES_MLOFF() so it works with negative offsets.
| author | vae |
|---|---|
| date | Wed, 29 Apr 2015 23:31:48 +0000 |
| parents | 5bcbb50b501e |
| children |
| rev | line source |
|---|---|
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
1 /* |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
2 * JFFS2 -- Journalling Flash File System, Version 2. |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
3 * |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
4 * Copyright (C) 2001-2003 Red Hat, Inc. |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
5 * |
| 1881 | 6 * Created by David Woodhouse <dwmw2@infradead.org> |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
7 * |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
8 * For licensing information, see the file 'LICENCE' in this directory. |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
9 * |
| 2042 | 10 * $Id: write.c,v 1.94 2005/07/20 15:50:51 dedekind Exp $ |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
11 * |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
12 */ |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
13 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
14 #include <linux/kernel.h> |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
15 #include <linux/fs.h> |
| 570 | 16 #include <linux/crc32.h> |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
17 #include <linux/slab.h> |
| 570 | 18 #include <linux/pagemap.h> |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
19 #include <linux/mtd/mtd.h> |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
20 #include "nodelist.h" |
| 1713 | 21 #include "compr.h" |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
22 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
23 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
24 int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri) |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
25 { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
26 struct jffs2_inode_cache *ic; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
27 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
28 ic = jffs2_alloc_inode_cache(); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
29 if (!ic) { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
30 return -ENOMEM; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
31 } |
| 570 | 32 |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
33 memset(ic, 0, sizeof(*ic)); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
34 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
35 f->inocache = ic; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
36 f->inocache->nlink = 1; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
37 f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; |
| 570 | 38 f->inocache->state = INO_STATE_PRESENT; |
| 39 | |
| 2042 | 40 |
| 41 jffs2_add_ino_cache(c, f->inocache); | |
| 42 D1(printk(KERN_DEBUG "jffs2_do_new_inode(): Assigned ino# %d\n", f->inocache->ino)); | |
| 570 | 43 ri->ino = cpu_to_je32(f->inocache->ino); |
| 44 | |
| 45 ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); | |
| 46 ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); | |
| 47 ri->totlen = cpu_to_je32(PAD(sizeof(*ri))); | |
| 48 ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); | |
| 49 ri->mode = cpu_to_jemode(mode); | |
| 50 | |
| 51 f->highest_version = 1; | |
| 52 ri->version = cpu_to_je32(f->highest_version); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
53 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
54 return 0; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
55 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
56 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
57 /* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it, |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
58 write it to the flash, link it into the existing inode/fragment list */ |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
59 |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
60 struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode) |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
61 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
62 { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
63 struct jffs2_raw_node_ref *raw; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
64 struct jffs2_full_dnode *fn; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
65 size_t retlen; |
| 1713 | 66 struct kvec vecs[2]; |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
67 int ret; |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
68 int retried = 0; |
| 570 | 69 unsigned long cnt = 2; |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
70 |
| 570 | 71 D1(if(je32_to_cpu(ri->hdr_crc) != crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)) { |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
72 printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dnode()\n"); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
73 BUG(); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
74 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
75 ); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
76 vecs[0].iov_base = ri; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
77 vecs[0].iov_len = sizeof(*ri); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
78 vecs[1].iov_base = (unsigned char *)data; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
79 vecs[1].iov_len = datalen; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
80 |
| 2042 | 81 jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
82 |
| 570 | 83 if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) { |
| 84 printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n", je32_to_cpu(ri->totlen), sizeof(*ri), datalen); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
85 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
86 raw = jffs2_alloc_raw_node_ref(); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
87 if (!raw) |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
88 return ERR_PTR(-ENOMEM); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
89 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
90 fn = jffs2_alloc_full_dnode(); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
91 if (!fn) { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
92 jffs2_free_raw_node_ref(raw); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
93 return ERR_PTR(-ENOMEM); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
94 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
95 |
| 570 | 96 fn->ofs = je32_to_cpu(ri->offset); |
| 97 fn->size = je32_to_cpu(ri->dsize); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
98 fn->frags = 0; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
99 |
| 570 | 100 /* check number of valid vecs */ |
| 101 if (!datalen || !data) | |
| 102 cnt = 1; | |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
103 retry: |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
104 fn->raw = raw; |
| 570 | 105 |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
106 raw->flash_offset = flash_ofs; |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
107 raw->__totlen = PAD(sizeof(*ri)+datalen); |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
108 raw->next_phys = NULL; |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
109 |
| 2042 | 110 if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(ri->version) < f->highest_version)) { |
| 111 BUG_ON(!retried); | |
| 112 D1(printk(KERN_DEBUG "jffs2_write_dnode : dnode_version %d, " | |
| 113 "highest version %d -> updating dnode\n", | |
| 114 je32_to_cpu(ri->version), f->highest_version)); | |
| 115 ri->version = cpu_to_je32(++f->highest_version); | |
| 116 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); | |
| 117 } | |
| 118 | |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
119 ret = jffs2_flash_writev(c, vecs, cnt, flash_ofs, &retlen, |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
120 (alloc_mode==ALLOC_GC)?0:f->inocache->ino); |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
121 |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
122 if (ret || (retlen != sizeof(*ri) + datalen)) { |
| 570 | 123 printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
124 sizeof(*ri)+datalen, flash_ofs, ret, retlen); |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
125 |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
126 /* Mark the space as dirtied */ |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
127 if (retlen) { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
128 /* Doesn't belong to any inode */ |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
129 raw->next_in_ino = NULL; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
130 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
131 /* Don't change raw->size to match retlen. We may have |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
132 written the node header already, and only the data will |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
133 seem corrupted, in which case the scan would skip over |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
134 any node we write before the original intended end of |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
135 this node */ |
| 570 | 136 raw->flash_offset |= REF_OBSOLETE; |
| 137 jffs2_add_physical_node_ref(c, raw); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
138 jffs2_mark_node_obsolete(c, raw); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
139 } else { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
140 printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
141 jffs2_free_raw_node_ref(raw); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
142 } |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
143 if (!retried && alloc_mode != ALLOC_NORETRY && (raw = jffs2_alloc_raw_node_ref())) { |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
144 /* Try to reallocate space and retry */ |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
145 uint32_t dummy; |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
146 struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
147 |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
148 retried = 1; |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
149 |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
150 D1(printk(KERN_DEBUG "Retrying failed write.\n")); |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
151 |
| 2042 | 152 jffs2_dbg_acct_sanity_check(c,jeb); |
| 153 jffs2_dbg_acct_paranoia_check(c, jeb); | |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
154 |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
155 if (alloc_mode == ALLOC_GC) { |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
156 ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &flash_ofs, &dummy); |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
157 } else { |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
158 /* Locking pain */ |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
159 up(&f->sem); |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
160 jffs2_complete_reservation(c); |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
161 |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
162 ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &flash_ofs, &dummy, alloc_mode); |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
163 down(&f->sem); |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
164 } |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
165 |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
166 if (!ret) { |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
167 D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs)); |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
168 |
| 2042 | 169 jffs2_dbg_acct_sanity_check(c,jeb); |
| 170 jffs2_dbg_acct_paranoia_check(c, jeb); | |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
171 |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
172 goto retry; |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
173 } |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
174 D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
175 jffs2_free_raw_node_ref(raw); |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
176 } |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
177 /* Release the full_dnode which is now useless, and return */ |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
178 jffs2_free_full_dnode(fn); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
179 return ERR_PTR(ret?ret:-EIO); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
180 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
181 /* Mark the space used */ |
| 570 | 182 /* If node covers at least a whole page, or if it starts at the |
| 183 beginning of a page and runs to the end of the file, or if | |
| 184 it's a hole node, mark it REF_PRISTINE, else REF_NORMAL. | |
| 185 */ | |
| 186 if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) || | |
| 187 ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) && | |
| 188 (je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) == je32_to_cpu(ri->isize)))) { | |
| 189 raw->flash_offset |= REF_PRISTINE; | |
| 190 } else { | |
| 191 raw->flash_offset |= REF_NORMAL; | |
| 192 } | |
| 193 jffs2_add_physical_node_ref(c, raw); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
194 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
195 /* Link into per-inode list */ |
| 1881 | 196 spin_lock(&c->erase_completion_lock); |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
197 raw->next_in_ino = f->inocache->nodes; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
198 f->inocache->nodes = raw; |
| 1881 | 199 spin_unlock(&c->erase_completion_lock); |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
200 |
| 570 | 201 D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n", |
| 202 flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize), | |
| 203 je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc), | |
| 204 je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen))); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
205 |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
206 if (retried) { |
| 2042 | 207 jffs2_dbg_acct_sanity_check(c,NULL); |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
208 } |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
209 |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
210 return fn; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
211 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
212 |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
213 struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode) |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
214 { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
215 struct jffs2_raw_node_ref *raw; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
216 struct jffs2_full_dirent *fd; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
217 size_t retlen; |
| 1713 | 218 struct kvec vecs[2]; |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
219 int retried = 0; |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
220 int ret; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
221 |
| 570 | 222 D1(printk(KERN_DEBUG "jffs2_write_dirent(ino #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x)\n", |
| 223 je32_to_cpu(rd->pino), name, name, je32_to_cpu(rd->ino), | |
| 224 je32_to_cpu(rd->name_crc))); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
225 |
| 570 | 226 D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) { |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
227 printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n"); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
228 BUG(); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
229 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
230 ); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
231 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
232 vecs[0].iov_base = rd; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
233 vecs[0].iov_len = sizeof(*rd); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
234 vecs[1].iov_base = (unsigned char *)name; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
235 vecs[1].iov_len = namelen; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
236 |
| 2042 | 237 jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); |
| 238 | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
239 raw = jffs2_alloc_raw_node_ref(); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
240 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
241 if (!raw) |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
242 return ERR_PTR(-ENOMEM); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
243 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
244 fd = jffs2_alloc_full_dirent(namelen+1); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
245 if (!fd) { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
246 jffs2_free_raw_node_ref(raw); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
247 return ERR_PTR(-ENOMEM); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
248 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
249 |
| 570 | 250 fd->version = je32_to_cpu(rd->version); |
| 251 fd->ino = je32_to_cpu(rd->ino); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
252 fd->nhash = full_name_hash(name, strlen(name)); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
253 fd->type = rd->type; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
254 memcpy(fd->name, name, namelen); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
255 fd->name[namelen]=0; |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
256 |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
257 retry: |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
258 fd->raw = raw; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
259 |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
260 raw->flash_offset = flash_ofs; |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
261 raw->__totlen = PAD(sizeof(*rd)+namelen); |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
262 raw->next_phys = NULL; |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
263 |
| 2042 | 264 if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) { |
| 265 BUG_ON(!retried); | |
| 266 D1(printk(KERN_DEBUG "jffs2_write_dirent : dirent_version %d, " | |
| 267 "highest version %d -> updating dirent\n", | |
| 268 je32_to_cpu(rd->version), f->highest_version)); | |
| 269 rd->version = cpu_to_je32(++f->highest_version); | |
| 270 fd->version = je32_to_cpu(rd->version); | |
| 271 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); | |
| 272 } | |
| 273 | |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
274 ret = jffs2_flash_writev(c, vecs, 2, flash_ofs, &retlen, |
| 1500 | 275 (alloc_mode==ALLOC_GC)?0:je32_to_cpu(rd->pino)); |
| 570 | 276 if (ret || (retlen != sizeof(*rd) + namelen)) { |
| 277 printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
278 sizeof(*rd)+namelen, flash_ofs, ret, retlen); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
279 /* Mark the space as dirtied */ |
| 570 | 280 if (retlen) { |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
281 raw->next_in_ino = NULL; |
| 570 | 282 raw->flash_offset |= REF_OBSOLETE; |
| 283 jffs2_add_physical_node_ref(c, raw); | |
| 284 jffs2_mark_node_obsolete(c, raw); | |
| 285 } else { | |
| 286 printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); | |
| 287 jffs2_free_raw_node_ref(raw); | |
| 288 } | |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
289 if (!retried && (raw = jffs2_alloc_raw_node_ref())) { |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
290 /* Try to reallocate space and retry */ |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
291 uint32_t dummy; |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
292 struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
293 |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
294 retried = 1; |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
295 |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
296 D1(printk(KERN_DEBUG "Retrying failed write.\n")); |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
297 |
| 2042 | 298 jffs2_dbg_acct_sanity_check(c,jeb); |
| 299 jffs2_dbg_acct_paranoia_check(c, jeb); | |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
300 |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
301 if (alloc_mode == ALLOC_GC) { |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
302 ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &flash_ofs, &dummy); |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
303 } else { |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
304 /* Locking pain */ |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
305 up(&f->sem); |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
306 jffs2_complete_reservation(c); |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
307 |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
308 ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &flash_ofs, &dummy, alloc_mode); |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
309 down(&f->sem); |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
310 } |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
311 |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
312 if (!ret) { |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
313 D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs)); |
| 2042 | 314 jffs2_dbg_acct_sanity_check(c,jeb); |
| 315 jffs2_dbg_acct_paranoia_check(c, jeb); | |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
316 goto retry; |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
317 } |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
318 D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
319 jffs2_free_raw_node_ref(raw); |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
320 } |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
321 /* Release the full_dnode which is now useless, and return */ |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
322 jffs2_free_full_dirent(fd); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
323 return ERR_PTR(ret?ret:-EIO); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
324 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
325 /* Mark the space used */ |
| 570 | 326 raw->flash_offset |= REF_PRISTINE; |
| 327 jffs2_add_physical_node_ref(c, raw); | |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
328 |
| 1881 | 329 spin_lock(&c->erase_completion_lock); |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
330 raw->next_in_ino = f->inocache->nodes; |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
331 f->inocache->nodes = raw; |
| 1881 | 332 spin_unlock(&c->erase_completion_lock); |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
333 |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
334 if (retried) { |
| 2042 | 335 jffs2_dbg_acct_sanity_check(c,NULL); |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
336 } |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
337 |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
338 return fd; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
339 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
340 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
341 /* The OS-specific code fills in the metadata in the jffs2_raw_inode for us, so that |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
342 we don't have to go digging in struct inode or its equivalent. It should set: |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
343 mode, uid, gid, (starting)isize, atime, ctime, mtime */ |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
344 int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
345 struct jffs2_raw_inode *ri, unsigned char *buf, |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
346 uint32_t offset, uint32_t writelen, uint32_t *retlen) |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
347 { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
348 int ret = 0; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
349 uint32_t writtenlen = 0; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
350 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
351 D1(printk(KERN_DEBUG "jffs2_write_inode_range(): Ino #%u, ofs 0x%x, len 0x%x\n", |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
352 f->inocache->ino, offset, writelen)); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
353 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
354 while(writelen) { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
355 struct jffs2_full_dnode *fn; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
356 unsigned char *comprbuf = NULL; |
| 1713 | 357 uint16_t comprtype = JFFS2_COMPR_NONE; |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
358 uint32_t phys_ofs, alloclen; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
359 uint32_t datalen, cdatalen; |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
360 int retried = 0; |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
361 |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
362 retry: |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
363 D2(printk(KERN_DEBUG "jffs2_commit_write() loop: 0x%x to write to 0x%x\n", writelen, offset)); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
364 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
365 ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, &alloclen, ALLOC_NORMAL); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
366 if (ret) { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
367 D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret)); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
368 break; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
369 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
370 down(&f->sem); |
| 1443 | 371 datalen = min_t(uint32_t, writelen, PAGE_CACHE_SIZE - (offset & (PAGE_CACHE_SIZE-1))); |
| 372 cdatalen = min_t(uint32_t, alloclen - sizeof(*ri), datalen); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
373 |
| 1562 | 374 comprtype = jffs2_compress(c, f, buf, &comprbuf, &datalen, &cdatalen); |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
375 |
| 570 | 376 ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
| 377 ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); | |
| 378 ri->totlen = cpu_to_je32(sizeof(*ri) + cdatalen); | |
| 379 ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
380 |
| 570 | 381 ri->ino = cpu_to_je32(f->inocache->ino); |
| 382 ri->version = cpu_to_je32(++f->highest_version); | |
| 383 ri->isize = cpu_to_je32(max(je32_to_cpu(ri->isize), offset + datalen)); | |
| 384 ri->offset = cpu_to_je32(offset); | |
| 385 ri->csize = cpu_to_je32(cdatalen); | |
| 386 ri->dsize = cpu_to_je32(datalen); | |
| 1713 | 387 ri->compr = comprtype & 0xff; |
| 388 ri->usercompr = (comprtype >> 8 ) & 0xff; | |
| 570 | 389 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); |
| 390 ri->data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen)); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
391 |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
392 fn = jffs2_write_dnode(c, f, ri, comprbuf, cdatalen, phys_ofs, ALLOC_NORETRY); |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
393 |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
394 jffs2_free_comprbuf(comprbuf, buf); |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
395 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
396 if (IS_ERR(fn)) { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
397 ret = PTR_ERR(fn); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
398 up(&f->sem); |
| 570 | 399 jffs2_complete_reservation(c); |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
400 if (!retried) { |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
401 /* Write error to be retried */ |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
402 retried = 1; |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
403 D1(printk(KERN_DEBUG "Retrying node write in jffs2_write_inode_range()\n")); |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
404 goto retry; |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
405 } |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
406 break; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
407 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
408 ret = jffs2_add_full_dnode_to_inode(c, f, fn); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
409 if (f->metadata) { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
410 jffs2_mark_node_obsolete(c, f->metadata->raw); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
411 jffs2_free_full_dnode(f->metadata); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
412 f->metadata = NULL; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
413 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
414 if (ret) { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
415 /* Eep */ |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
416 D1(printk(KERN_DEBUG "Eep. add_full_dnode_to_inode() failed in commit_write, returned %d\n", ret)); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
417 jffs2_mark_node_obsolete(c, fn->raw); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
418 jffs2_free_full_dnode(fn); |
| 570 | 419 |
| 420 up(&f->sem); | |
| 421 jffs2_complete_reservation(c); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
422 break; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
423 } |
| 570 | 424 up(&f->sem); |
| 425 jffs2_complete_reservation(c); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
426 if (!datalen) { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
427 printk(KERN_WARNING "Eep. We didn't actually write any data in jffs2_write_inode_range()\n"); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
428 ret = -EIO; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
429 break; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
430 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
431 D1(printk(KERN_DEBUG "increasing writtenlen by %d\n", datalen)); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
432 writtenlen += datalen; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
433 offset += datalen; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
434 writelen -= datalen; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
435 buf += datalen; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
436 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
437 *retlen = writtenlen; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
438 return ret; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
439 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
440 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
441 int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const char *name, int namelen) |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
442 { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
443 struct jffs2_raw_dirent *rd; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
444 struct jffs2_full_dnode *fn; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
445 struct jffs2_full_dirent *fd; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
446 uint32_t alloclen, phys_ofs; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
447 int ret; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
448 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
449 /* Try to reserve enough space for both node and dirent. |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
450 * Just the node will do for now, though |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
451 */ |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
452 ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
453 D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen)); |
| 570 | 454 if (ret) { |
| 455 up(&f->sem); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
456 return ret; |
| 570 | 457 } |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
458 |
| 570 | 459 ri->data_crc = cpu_to_je32(0); |
| 460 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
461 |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
462 fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL); |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
463 |
| 570 | 464 D1(printk(KERN_DEBUG "jffs2_do_create created file with mode 0x%x\n", |
| 465 jemode_to_cpu(ri->mode))); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
466 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
467 if (IS_ERR(fn)) { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
468 D1(printk(KERN_DEBUG "jffs2_write_dnode() failed\n")); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
469 /* Eeek. Wave bye bye */ |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
470 up(&f->sem); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
471 jffs2_complete_reservation(c); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
472 return PTR_ERR(fn); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
473 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
474 /* No data here. Only a metadata node, which will be |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
475 obsoleted by the first data write |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
476 */ |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
477 f->metadata = fn; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
478 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
479 up(&f->sem); |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
480 jffs2_complete_reservation(c); |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
481 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
482 |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
483 if (ret) { |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
484 /* Eep. */ |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
485 D1(printk(KERN_DEBUG "jffs2_reserve_space() for dirent failed\n")); |
|
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
486 return ret; |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
487 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
488 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
489 rd = jffs2_alloc_raw_dirent(); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
490 if (!rd) { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
491 /* Argh. Now we treat it like a normal delete */ |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
492 jffs2_complete_reservation(c); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
493 return -ENOMEM; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
494 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
495 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
496 down(&dir_f->sem); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
497 |
| 570 | 498 rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
| 499 rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); | |
| 500 rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); | |
| 501 rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
502 |
| 570 | 503 rd->pino = cpu_to_je32(dir_f->inocache->ino); |
| 504 rd->version = cpu_to_je32(++dir_f->highest_version); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
505 rd->ino = ri->ino; |
| 570 | 506 rd->mctime = ri->ctime; |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
507 rd->nsize = namelen; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
508 rd->type = DT_REG; |
| 570 | 509 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); |
| 510 rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
511 |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
512 fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL); |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
513 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
514 jffs2_free_raw_dirent(rd); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
515 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
516 if (IS_ERR(fd)) { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
517 /* dirent failed to write. Delete the inode normally |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
518 as if it were the final unlink() */ |
| 570 | 519 jffs2_complete_reservation(c); |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
520 up(&dir_f->sem); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
521 return PTR_ERR(fd); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
522 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
523 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
524 /* Link the fd into the inode's list, obsoleting an old |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
525 one if necessary. */ |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
526 jffs2_add_fd_to_list(c, fd, &dir_f->dents); |
| 570 | 527 |
| 528 jffs2_complete_reservation(c); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
529 up(&dir_f->sem); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
530 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
531 return 0; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
532 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
533 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
534 |
| 570 | 535 int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, |
| 536 const char *name, int namelen, struct jffs2_inode_info *dead_f) | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
537 { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
538 struct jffs2_raw_dirent *rd; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
539 struct jffs2_full_dirent *fd; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
540 uint32_t alloclen, phys_ofs; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
541 int ret; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
542 |
| 1562 | 543 if (1 /* alternative branch needs testing */ || |
| 544 !jffs2_can_mark_obsolete(c)) { | |
| 545 /* We can't mark stuff obsolete on the medium. We need to write a deletion dirent */ | |
| 546 | |
| 547 rd = jffs2_alloc_raw_dirent(); | |
| 548 if (!rd) | |
| 549 return -ENOMEM; | |
| 550 | |
| 551 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_DELETION); | |
| 552 if (ret) { | |
| 553 jffs2_free_raw_dirent(rd); | |
| 554 return ret; | |
| 555 } | |
| 556 | |
| 557 down(&dir_f->sem); | |
| 558 | |
| 559 /* Build a deletion node */ | |
| 560 rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); | |
| 561 rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); | |
| 562 rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); | |
| 563 rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); | |
| 564 | |
| 565 rd->pino = cpu_to_je32(dir_f->inocache->ino); | |
| 566 rd->version = cpu_to_je32(++dir_f->highest_version); | |
| 567 rd->ino = cpu_to_je32(0); | |
| 568 rd->mctime = cpu_to_je32(get_seconds()); | |
| 569 rd->nsize = namelen; | |
| 570 rd->type = DT_UNKNOWN; | |
| 571 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); | |
| 572 rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
573 |
| 1562 | 574 fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_DELETION); |
| 575 | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
576 jffs2_free_raw_dirent(rd); |
| 1562 | 577 |
| 578 if (IS_ERR(fd)) { | |
| 579 jffs2_complete_reservation(c); | |
| 580 up(&dir_f->sem); | |
| 581 return PTR_ERR(fd); | |
| 582 } | |
| 583 | |
| 584 /* File it. This will mark the old one obsolete. */ | |
| 585 jffs2_add_fd_to_list(c, fd, &dir_f->dents); | |
| 586 up(&dir_f->sem); | |
| 587 } else { | |
| 588 struct jffs2_full_dirent **prev = &dir_f->dents; | |
| 589 uint32_t nhash = full_name_hash(name, namelen); | |
| 590 | |
| 591 down(&dir_f->sem); | |
| 592 | |
| 593 while ((*prev) && (*prev)->nhash <= nhash) { | |
| 594 if ((*prev)->nhash == nhash && | |
| 595 !memcmp((*prev)->name, name, namelen) && | |
| 596 !(*prev)->name[namelen]) { | |
| 597 struct jffs2_full_dirent *this = *prev; | |
| 598 | |
| 599 D1(printk(KERN_DEBUG "Marking old dirent node (ino #%u) @%08x obsolete\n", | |
| 600 this->ino, ref_offset(this->raw))); | |
| 601 | |
| 602 *prev = this->next; | |
| 603 jffs2_mark_node_obsolete(c, (this->raw)); | |
| 604 jffs2_free_full_dirent(this); | |
| 605 break; | |
| 606 } | |
| 607 prev = &((*prev)->next); | |
| 608 } | |
| 609 up(&dir_f->sem); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
610 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
611 |
| 570 | 612 /* dead_f is NULL if this was a rename not a real unlink */ |
| 613 /* Also catch the !f->inocache case, where there was a dirent | |
| 614 pointing to an inode which didn't exist. */ | |
| 615 if (dead_f && dead_f->inocache) { | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
616 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
617 down(&dead_f->sem); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
618 |
| 2042 | 619 if (S_ISDIR(OFNI_EDONI_2SFFJ(dead_f)->i_mode)) { |
| 620 while (dead_f->dents) { | |
| 621 /* There can be only deleted ones */ | |
| 622 fd = dead_f->dents; | |
| 623 | |
| 624 dead_f->dents = fd->next; | |
| 625 | |
| 626 if (fd->ino) { | |
| 627 printk(KERN_WARNING "Deleting inode #%u with active dentry \"%s\"->ino #%u\n", | |
| 628 dead_f->inocache->ino, fd->name, fd->ino); | |
| 629 } else { | |
| 630 D1(printk(KERN_DEBUG "Removing deletion dirent for \"%s\" from dir ino #%u\n", | |
| 631 fd->name, dead_f->inocache->ino)); | |
| 632 } | |
| 633 jffs2_mark_node_obsolete(c, fd->raw); | |
| 634 jffs2_free_full_dirent(fd); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
635 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
636 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
637 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
638 dead_f->inocache->nlink--; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
639 /* NB: Caller must set inode nlink if appropriate */ |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
640 up(&dead_f->sem); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
641 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
642 |
| 570 | 643 jffs2_complete_reservation(c); |
| 644 | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
645 return 0; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
646 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
647 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
648 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
649 int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen) |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
650 { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
651 struct jffs2_raw_dirent *rd; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
652 struct jffs2_full_dirent *fd; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
653 uint32_t alloclen, phys_ofs; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
654 int ret; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
655 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
656 rd = jffs2_alloc_raw_dirent(); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
657 if (!rd) |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
658 return -ENOMEM; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
659 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
660 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
661 if (ret) { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
662 jffs2_free_raw_dirent(rd); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
663 return ret; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
664 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
665 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
666 down(&dir_f->sem); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
667 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
668 /* Build a deletion node */ |
| 570 | 669 rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
| 670 rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); | |
| 671 rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); | |
| 672 rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
673 |
| 570 | 674 rd->pino = cpu_to_je32(dir_f->inocache->ino); |
| 675 rd->version = cpu_to_je32(++dir_f->highest_version); | |
| 676 rd->ino = cpu_to_je32(ino); | |
| 677 rd->mctime = cpu_to_je32(get_seconds()); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
678 rd->nsize = namelen; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
679 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
680 rd->type = type; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
681 |
| 570 | 682 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); |
| 683 rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
684 |
|
1372
121121d3d18f
Merge changes from David Woodhouse (bring up to date with MTD project)
gthomas
parents:
570
diff
changeset
|
685 fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL); |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
686 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
687 jffs2_free_raw_dirent(rd); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
688 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
689 if (IS_ERR(fd)) { |
| 570 | 690 jffs2_complete_reservation(c); |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
691 up(&dir_f->sem); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
692 return PTR_ERR(fd); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
693 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
694 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
695 /* File it. This will mark the old one obsolete. */ |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
696 jffs2_add_fd_to_list(c, fd, &dir_f->dents); |
| 570 | 697 |
| 698 jffs2_complete_reservation(c); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
699 up(&dir_f->sem); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
700 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
701 return 0; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
702 } |
