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