Blame view

fs/jffs2/dir.c 22.2 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  /*
   * JFFS2 -- Journalling Flash File System, Version 2.
   *
c00c310ea   David Woodhouse   [JFFS2] Tidy up l...
4
   * Copyright © 2001-2007 Red Hat, Inc.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
7
8
9
   *
   * Created by David Woodhouse <dwmw2@infradead.org>
   *
   * For licensing information, see the file 'LICENCE' in this directory.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
12
13
   */
  
  #include <linux/kernel.h>
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
16
  #include <linux/fs.h>
  #include <linux/crc32.h>
  #include <linux/jffs2.h>
cbb9a5617   David Woodhouse   Move jffs2_fs_i.h...
17
18
  #include "jffs2_fs_i.h"
  #include "jffs2_fs_sb.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
  #include <linux/time.h>
  #include "nodelist.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
23
24
25
26
27
28
29
30
31
  static int jffs2_readdir (struct file *, void *, filldir_t);
  
  static int jffs2_create (struct inode *,struct dentry *,int,
  			 struct nameidata *);
  static struct dentry *jffs2_lookup (struct inode *,struct dentry *,
  				    struct nameidata *);
  static int jffs2_link (struct dentry *,struct inode *,struct dentry *);
  static int jffs2_unlink (struct inode *,struct dentry *);
  static int jffs2_symlink (struct inode *,struct dentry *,const char *);
  static int jffs2_mkdir (struct inode *,struct dentry *,int);
  static int jffs2_rmdir (struct inode *,struct dentry *);
265489f01   David Woodhouse   [JFFS2] Remove co...
32
  static int jffs2_mknod (struct inode *,struct dentry *,int,dev_t);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
34
  static int jffs2_rename (struct inode *, struct dentry *,
                          struct inode *, struct dentry *);
4b6f5d20b   Arjan van de Ven   [PATCH] Make most...
35
  const struct file_operations jffs2_dir_operations =
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
38
39
40
41
  {
  	.read =		generic_read_dir,
  	.readdir =	jffs2_readdir,
  	.ioctl =	jffs2_ioctl,
  	.fsync =	jffs2_fsync
  };
92e1d5be9   Arjan van de Ven   [PATCH] mark stru...
42
  const struct inode_operations jffs2_dir_inode_operations =
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
  {
265489f01   David Woodhouse   [JFFS2] Remove co...
44
45
  	.create =	jffs2_create,
  	.lookup =	jffs2_lookup,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
48
49
50
51
52
  	.link =		jffs2_link,
  	.unlink =	jffs2_unlink,
  	.symlink =	jffs2_symlink,
  	.mkdir =	jffs2_mkdir,
  	.rmdir =	jffs2_rmdir,
  	.mknod =	jffs2_mknod,
  	.rename =	jffs2_rename,
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
53
  	.permission =	jffs2_permission,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
  	.setattr =	jffs2_setattr,
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
55
56
57
58
  	.setxattr =	jffs2_setxattr,
  	.getxattr =	jffs2_getxattr,
  	.listxattr =	jffs2_listxattr,
  	.removexattr =	jffs2_removexattr
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
61
62
63
64
  };
  
  /***********************************************************************/
  
  
  /* We keep the dirent list sorted in increasing order of name hash,
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
65
     and we use the same hash function as the dentries. Makes this
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
68
69
70
71
72
73
74
75
76
77
78
     nice and simple
  */
  static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target,
  				   struct nameidata *nd)
  {
  	struct jffs2_inode_info *dir_f;
  	struct jffs2_sb_info *c;
  	struct jffs2_full_dirent *fd = NULL, *fd_list;
  	uint32_t ino = 0;
  	struct inode *inode = NULL;
  
  	D1(printk(KERN_DEBUG "jffs2_lookup()
  "));
373d5e718   Richard Purdie   JFFS2: Return an ...
79
80
  	if (target->d_name.len > JFFS2_MAX_NAME_LEN)
  		return ERR_PTR(-ENAMETOOLONG);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
82
83
84
85
86
87
  	dir_f = JFFS2_INODE_INFO(dir_i);
  	c = JFFS2_SB_INFO(dir_i->i_sb);
  
  	down(&dir_f->sem);
  
  	/* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */
  	for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= target->d_name.hash; fd_list = fd_list->next) {
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
88
  		if (fd_list->nhash == target->d_name.hash &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
  		    (!fd || fd_list->version > fd->version) &&
  		    strlen(fd_list->name) == target->d_name.len &&
  		    !strncmp(fd_list->name, target->d_name.name, target->d_name.len)) {
  			fd = fd_list;
  		}
  	}
  	if (fd)
  		ino = fd->ino;
  	up(&dir_f->sem);
  	if (ino) {
  		inode = iget(dir_i->i_sb, ino);
  		if (!inode) {
  			printk(KERN_WARNING "iget() failed for ino #%u
  ", ino);
  			return (ERR_PTR(-EIO));
  		}
  	}
  
  	d_add(target, inode);
  
  	return NULL;
  }
  
  /***********************************************************************/
  
  
  static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
  {
  	struct jffs2_inode_info *f;
  	struct jffs2_sb_info *c;
ec2e203c8   Josef Sipek   [PATCH] struct pa...
119
  	struct inode *inode = filp->f_path.dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
121
  	struct jffs2_full_dirent *fd;
  	unsigned long offset, curofs;
ec2e203c8   Josef Sipek   [PATCH] struct pa...
122
123
  	D1(printk(KERN_DEBUG "jffs2_readdir() for dir_i #%lu
  ", filp->f_path.dentry->d_inode->i_ino));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
125
126
127
128
129
130
131
132
133
134
135
136
137
  
  	f = JFFS2_INODE_INFO(inode);
  	c = JFFS2_SB_INFO(inode->i_sb);
  
  	offset = filp->f_pos;
  
  	if (offset == 0) {
  		D1(printk(KERN_DEBUG "Dirent 0: \".\", ino #%lu
  ", inode->i_ino));
  		if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0)
  			goto out;
  		offset++;
  	}
  	if (offset == 1) {
ec2e203c8   Josef Sipek   [PATCH] struct pa...
138
  		unsigned long pino = parent_ino(filp->f_path.dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
140
141
142
143
144
145
146
147
148
149
150
151
152
  		D1(printk(KERN_DEBUG "Dirent 1: \"..\", ino #%lu
  ", pino));
  		if (filldir(dirent, "..", 2, 1, pino, DT_DIR) < 0)
  			goto out;
  		offset++;
  	}
  
  	curofs=1;
  	down(&f->sem);
  	for (fd = f->dents; fd; fd = fd->next) {
  
  		curofs++;
  		/* First loop: curofs = 2; offset = 2 */
  		if (curofs < offset) {
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
153
154
  			D2(printk(KERN_DEBUG "Skipping dirent: \"%s\", ino #%u, type %d, because curofs %ld < offset %ld
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
  				  fd->name, fd->ino, fd->type, curofs, offset));
  			continue;
  		}
  		if (!fd->ino) {
  			D2(printk(KERN_DEBUG "Skipping deletion dirent \"%s\"
  ", fd->name));
  			offset++;
  			continue;
  		}
  		D2(printk(KERN_DEBUG "Dirent %ld: \"%s\", ino #%u, type %d
  ", offset, fd->name, fd->ino, fd->type));
  		if (filldir(dirent, fd->name, strlen(fd->name), offset, fd->ino, fd->type) < 0)
  			break;
  		offset++;
  	}
  	up(&f->sem);
   out:
  	filp->f_pos = offset;
  	return 0;
  }
  
  /***********************************************************************/
  
  
  static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
  			struct nameidata *nd)
  {
  	struct jffs2_raw_inode *ri;
  	struct jffs2_inode_info *f, *dir_f;
  	struct jffs2_sb_info *c;
  	struct inode *inode;
  	int ret;
  
  	ri = jffs2_alloc_raw_inode();
  	if (!ri)
  		return -ENOMEM;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
191

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
  	c = JFFS2_SB_INFO(dir_i->i_sb);
  
  	D1(printk(KERN_DEBUG "jffs2_create()
  "));
  
  	inode = jffs2_new_inode(dir_i, mode, ri);
  
  	if (IS_ERR(inode)) {
  		D1(printk(KERN_DEBUG "jffs2_new_inode() failed
  "));
  		jffs2_free_raw_inode(ri);
  		return PTR_ERR(inode);
  	}
  
  	inode->i_op = &jffs2_file_inode_operations;
  	inode->i_fop = &jffs2_file_operations;
  	inode->i_mapping->a_ops = &jffs2_file_address_operations;
  	inode->i_mapping->nrpages = 0;
  
  	f = JFFS2_INODE_INFO(inode);
  	dir_f = JFFS2_INODE_INFO(dir_i);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
213
  	ret = jffs2_do_create(c, dir_f, f, ri,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
  			      dentry->d_name.name, dentry->d_name.len);
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
215
216
217
218
219
220
221
222
223
  	if (ret)
  		goto fail;
  
  	ret = jffs2_init_security(inode, dir_i);
  	if (ret)
  		goto fail;
  	ret = jffs2_init_acl(inode, dir_i);
  	if (ret)
  		goto fail;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
225
226
227
228
229
230
231
232
233
  
  	dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime));
  
  	jffs2_free_raw_inode(ri);
  	d_instantiate(dentry, inode);
  
  	D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld
  ",
  		  inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink, inode->i_mapping->nrpages));
  	return 0;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
234
235
236
237
238
239
  
   fail:
  	make_bad_inode(inode);
  	iput(inode);
  	jffs2_free_raw_inode(ri);
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
241
242
243
244
245
246
247
248
249
250
  }
  
  /***********************************************************************/
  
  
  static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry)
  {
  	struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb);
  	struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
  	struct jffs2_inode_info *dead_f = JFFS2_INODE_INFO(dentry->d_inode);
  	int ret;
3a69e0cd2   Artem B. Bityutskiy   [JFFS2] Fix JFFS2...
251
  	uint32_t now = get_seconds();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252

182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
253
  	ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name,
3a69e0cd2   Artem B. Bityutskiy   [JFFS2] Fix JFFS2...
254
  			      dentry->d_name.len, dead_f, now);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
256
  	if (dead_f->inocache)
  		dentry->d_inode->i_nlink = dead_f->inocache->nlink;
3a69e0cd2   Artem B. Bityutskiy   [JFFS2] Fix JFFS2...
257
258
  	if (!ret)
  		dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
260
261
262
263
264
265
266
267
268
269
270
  	return ret;
  }
  /***********************************************************************/
  
  
  static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct dentry *dentry)
  {
  	struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dentry->d_inode->i_sb);
  	struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode);
  	struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
  	int ret;
  	uint8_t type;
3a69e0cd2   Artem B. Bityutskiy   [JFFS2] Fix JFFS2...
271
  	uint32_t now;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272
273
274
275
276
277
278
279
280
281
282
  
  	/* Don't let people make hard links to bad inodes. */
  	if (!f->inocache)
  		return -EIO;
  
  	if (S_ISDIR(old_dentry->d_inode->i_mode))
  		return -EPERM;
  
  	/* XXX: This is ugly */
  	type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12;
  	if (!type) type = DT_REG;
3a69e0cd2   Artem B. Bityutskiy   [JFFS2] Fix JFFS2...
283
284
  	now = get_seconds();
  	ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, dentry->d_name.name, dentry->d_name.len, now);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
286
287
288
289
290
  
  	if (!ret) {
  		down(&f->sem);
  		old_dentry->d_inode->i_nlink = ++f->inocache->nlink;
  		up(&f->sem);
  		d_instantiate(dentry, old_dentry->d_inode);
3a69e0cd2   Artem B. Bityutskiy   [JFFS2] Fix JFFS2...
291
  		dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
  		atomic_inc(&old_dentry->d_inode->i_count);
  	}
  	return ret;
  }
  
  /***********************************************************************/
  
  static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char *target)
  {
  	struct jffs2_inode_info *f, *dir_f;
  	struct jffs2_sb_info *c;
  	struct inode *inode;
  	struct jffs2_raw_inode *ri;
  	struct jffs2_raw_dirent *rd;
  	struct jffs2_full_dnode *fn;
  	struct jffs2_full_dirent *fd;
  	int namelen;
9fe4854cd   David Woodhouse   [JFFS2] Remove fl...
309
  	uint32_t alloclen;
32f1a95d5   Artem B. Bityuckiy   [JFFS2] Add symli...
310
  	int ret, targetlen = strlen(target);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311
312
313
  
  	/* FIXME: If you care. We'd need to use frags for the target
  	   if it grows much more than this */
32f1a95d5   Artem B. Bityuckiy   [JFFS2] Add symli...
314
  	if (targetlen > 254)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
316
317
318
319
320
  		return -EINVAL;
  
  	ri = jffs2_alloc_raw_inode();
  
  	if (!ri)
  		return -ENOMEM;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
321

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
  	c = JFFS2_SB_INFO(dir_i->i_sb);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
323
324
325
  
  	/* Try to reserve enough space for both node and dirent.
  	 * Just the node will do for now, though
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
326
327
  	 */
  	namelen = dentry->d_name.len;
9fe4854cd   David Woodhouse   [JFFS2] Remove fl...
328
329
  	ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &alloclen,
  				  ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
  
  	if (ret) {
  		jffs2_free_raw_inode(ri);
  		return ret;
  	}
  
  	inode = jffs2_new_inode(dir_i, S_IFLNK | S_IRWXUGO, ri);
  
  	if (IS_ERR(inode)) {
  		jffs2_free_raw_inode(ri);
  		jffs2_complete_reservation(c);
  		return PTR_ERR(inode);
  	}
  
  	inode->i_op = &jffs2_symlink_inode_operations;
  
  	f = JFFS2_INODE_INFO(inode);
32f1a95d5   Artem B. Bityuckiy   [JFFS2] Add symli...
347
  	inode->i_size = targetlen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
349
350
351
352
  	ri->isize = ri->dsize = ri->csize = cpu_to_je32(inode->i_size);
  	ri->totlen = cpu_to_je32(sizeof(*ri) + inode->i_size);
  	ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
  
  	ri->compr = JFFS2_COMPR_NONE;
32f1a95d5   Artem B. Bityuckiy   [JFFS2] Add symli...
353
  	ri->data_crc = cpu_to_je32(crc32(0, target, targetlen));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
354
  	ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
355

9fe4854cd   David Woodhouse   [JFFS2] Remove fl...
356
  	fn = jffs2_write_dnode(c, f, ri, target, targetlen, ALLOC_NORMAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357
358
359
360
361
362
363
364
365
366
  
  	jffs2_free_raw_inode(ri);
  
  	if (IS_ERR(fn)) {
  		/* Eeek. Wave bye bye */
  		up(&f->sem);
  		jffs2_complete_reservation(c);
  		jffs2_clear_inode(inode);
  		return PTR_ERR(fn);
  	}
32f1a95d5   Artem B. Bityuckiy   [JFFS2] Add symli...
367

2b79adcca   Artem B. Bityutskiy   [JFFS2] Use f->ta...
368
369
370
  	/* We use f->target field to store the target path. */
  	f->target = kmalloc(targetlen + 1, GFP_KERNEL);
  	if (!f->target) {
32f1a95d5   Artem B. Bityuckiy   [JFFS2] Add symli...
371
372
373
374
375
376
377
  		printk(KERN_WARNING "Can't allocate %d bytes of memory
  ", targetlen + 1);
  		up(&f->sem);
  		jffs2_complete_reservation(c);
  		jffs2_clear_inode(inode);
  		return -ENOMEM;
  	}
2b79adcca   Artem B. Bityutskiy   [JFFS2] Use f->ta...
378
379
380
  	memcpy(f->target, target, targetlen + 1);
  	D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached
  ", (char *)f->target));
32f1a95d5   Artem B. Bityuckiy   [JFFS2] Add symli...
381

182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
382
  	/* No data here. Only a metadata node, which will be
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
383
384
385
386
387
388
  	   obsoleted by the first data write
  	*/
  	f->metadata = fn;
  	up(&f->sem);
  
  	jffs2_complete_reservation(c);
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
389
390
391
392
393
394
395
396
397
398
399
  
  	ret = jffs2_init_security(inode, dir_i);
  	if (ret) {
  		jffs2_clear_inode(inode);
  		return ret;
  	}
  	ret = jffs2_init_acl(inode, dir_i);
  	if (ret) {
  		jffs2_clear_inode(inode);
  		return ret;
  	}
9fe4854cd   David Woodhouse   [JFFS2] Remove fl...
400
401
  	ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
  				  ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
  	if (ret) {
  		/* Eep. */
  		jffs2_clear_inode(inode);
  		return ret;
  	}
  
  	rd = jffs2_alloc_raw_dirent();
  	if (!rd) {
  		/* Argh. Now we treat it like a normal delete */
  		jffs2_complete_reservation(c);
  		jffs2_clear_inode(inode);
  		return -ENOMEM;
  	}
  
  	dir_f = JFFS2_INODE_INFO(dir_i);
  	down(&dir_f->sem);
  
  	rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
  	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
  	rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
  	rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
  
  	rd->pino = cpu_to_je32(dir_i->i_ino);
  	rd->version = cpu_to_je32(++dir_f->highest_version);
  	rd->ino = cpu_to_je32(inode->i_ino);
  	rd->mctime = cpu_to_je32(get_seconds());
  	rd->nsize = namelen;
  	rd->type = DT_LNK;
  	rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
  	rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen));
9fe4854cd   David Woodhouse   [JFFS2] Remove fl...
432
  	fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
434
  
  	if (IS_ERR(fd)) {
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
435
  		/* dirent failed to write. Delete the inode normally
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
  		   as if it were the final unlink() */
  		jffs2_complete_reservation(c);
  		jffs2_free_raw_dirent(rd);
  		up(&dir_f->sem);
  		jffs2_clear_inode(inode);
  		return PTR_ERR(fd);
  	}
  
  	dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
  
  	jffs2_free_raw_dirent(rd);
  
  	/* Link the fd into the inode's list, obsoleting an old
  	   one if necessary. */
  	jffs2_add_fd_to_list(c, fd, &dir_f->dents);
  
  	up(&dir_f->sem);
  	jffs2_complete_reservation(c);
  
  	d_instantiate(dentry, inode);
  	return 0;
  }
  
  
  static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
  {
  	struct jffs2_inode_info *f, *dir_f;
  	struct jffs2_sb_info *c;
  	struct inode *inode;
  	struct jffs2_raw_inode *ri;
  	struct jffs2_raw_dirent *rd;
  	struct jffs2_full_dnode *fn;
  	struct jffs2_full_dirent *fd;
  	int namelen;
9fe4854cd   David Woodhouse   [JFFS2] Remove fl...
470
  	uint32_t alloclen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
471
472
473
474
475
476
477
  	int ret;
  
  	mode |= S_IFDIR;
  
  	ri = jffs2_alloc_raw_inode();
  	if (!ri)
  		return -ENOMEM;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
478

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
479
  	c = JFFS2_SB_INFO(dir_i->i_sb);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
480
481
  	/* Try to reserve enough space for both node and dirent.
  	 * Just the node will do for now, though
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
483
  	 */
  	namelen = dentry->d_name.len;
9fe4854cd   David Woodhouse   [JFFS2] Remove fl...
484
485
  	ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL,
  				  JFFS2_SUMMARY_INODE_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
  
  	if (ret) {
  		jffs2_free_raw_inode(ri);
  		return ret;
  	}
  
  	inode = jffs2_new_inode(dir_i, mode, ri);
  
  	if (IS_ERR(inode)) {
  		jffs2_free_raw_inode(ri);
  		jffs2_complete_reservation(c);
  		return PTR_ERR(inode);
  	}
  
  	inode->i_op = &jffs2_dir_inode_operations;
  	inode->i_fop = &jffs2_dir_operations;
  	/* Directories get nlink 2 at start */
  	inode->i_nlink = 2;
  
  	f = JFFS2_INODE_INFO(inode);
  
  	ri->data_crc = cpu_to_je32(0);
  	ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
509

9fe4854cd   David Woodhouse   [JFFS2] Remove fl...
510
  	fn = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
512
513
514
515
516
517
518
519
520
  
  	jffs2_free_raw_inode(ri);
  
  	if (IS_ERR(fn)) {
  		/* Eeek. Wave bye bye */
  		up(&f->sem);
  		jffs2_complete_reservation(c);
  		jffs2_clear_inode(inode);
  		return PTR_ERR(fn);
  	}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
521
  	/* No data here. Only a metadata node, which will be
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522
523
524
525
526
527
  	   obsoleted by the first data write
  	*/
  	f->metadata = fn;
  	up(&f->sem);
  
  	jffs2_complete_reservation(c);
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
528
529
530
531
532
533
534
535
536
537
538
  
  	ret = jffs2_init_security(inode, dir_i);
  	if (ret) {
  		jffs2_clear_inode(inode);
  		return ret;
  	}
  	ret = jffs2_init_acl(inode, dir_i);
  	if (ret) {
  		jffs2_clear_inode(inode);
  		return ret;
  	}
9fe4854cd   David Woodhouse   [JFFS2] Remove fl...
539
540
  	ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
  				  ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541
542
543
544
545
  	if (ret) {
  		/* Eep. */
  		jffs2_clear_inode(inode);
  		return ret;
  	}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
546

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
  	rd = jffs2_alloc_raw_dirent();
  	if (!rd) {
  		/* Argh. Now we treat it like a normal delete */
  		jffs2_complete_reservation(c);
  		jffs2_clear_inode(inode);
  		return -ENOMEM;
  	}
  
  	dir_f = JFFS2_INODE_INFO(dir_i);
  	down(&dir_f->sem);
  
  	rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
  	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
  	rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
  	rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
  
  	rd->pino = cpu_to_je32(dir_i->i_ino);
  	rd->version = cpu_to_je32(++dir_f->highest_version);
  	rd->ino = cpu_to_je32(inode->i_ino);
  	rd->mctime = cpu_to_je32(get_seconds());
  	rd->nsize = namelen;
  	rd->type = DT_DIR;
  	rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
  	rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen));
9fe4854cd   David Woodhouse   [JFFS2] Remove fl...
571
  	fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
572

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
573
  	if (IS_ERR(fd)) {
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
574
  		/* dirent failed to write. Delete the inode normally
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575
576
577
578
579
580
581
582
583
  		   as if it were the final unlink() */
  		jffs2_complete_reservation(c);
  		jffs2_free_raw_dirent(rd);
  		up(&dir_f->sem);
  		jffs2_clear_inode(inode);
  		return PTR_ERR(fd);
  	}
  
  	dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
d8c76e6f4   Dave Hansen   [PATCH] r/o bind ...
584
  	inc_nlink(dir_i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
  
  	jffs2_free_raw_dirent(rd);
  
  	/* Link the fd into the inode's list, obsoleting an old
  	   one if necessary. */
  	jffs2_add_fd_to_list(c, fd, &dir_f->dents);
  
  	up(&dir_f->sem);
  	jffs2_complete_reservation(c);
  
  	d_instantiate(dentry, inode);
  	return 0;
  }
  
  static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry)
  {
  	struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode);
  	struct jffs2_full_dirent *fd;
  	int ret;
  
  	for (fd = f->dents ; fd; fd = fd->next) {
  		if (fd->ino)
  			return -ENOTEMPTY;
  	}
  	ret = jffs2_unlink(dir_i, dentry);
  	if (!ret)
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
611
  		drop_nlink(dir_i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
612
613
  	return ret;
  }
265489f01   David Woodhouse   [JFFS2] Remove co...
614
  static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, dev_t rdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
615
616
617
618
619
620
621
622
623
  {
  	struct jffs2_inode_info *f, *dir_f;
  	struct jffs2_sb_info *c;
  	struct inode *inode;
  	struct jffs2_raw_inode *ri;
  	struct jffs2_raw_dirent *rd;
  	struct jffs2_full_dnode *fn;
  	struct jffs2_full_dirent *fd;
  	int namelen;
aef9ab478   David Woodhouse   [JFFS2] Support n...
624
  	union jffs2_device_node dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
625
  	int devlen = 0;
9fe4854cd   David Woodhouse   [JFFS2] Remove fl...
626
  	uint32_t alloclen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627
  	int ret;
aef9ab478   David Woodhouse   [JFFS2] Support n...
628
  	if (!new_valid_dev(rdev))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
629
630
631
632
633
  		return -EINVAL;
  
  	ri = jffs2_alloc_raw_inode();
  	if (!ri)
  		return -ENOMEM;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
634

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
635
  	c = JFFS2_SB_INFO(dir_i->i_sb);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
636

aef9ab478   David Woodhouse   [JFFS2] Support n...
637
638
  	if (S_ISBLK(mode) || S_ISCHR(mode))
  		devlen = jffs2_encode_dev(&dev, rdev);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
639
640
641
  
  	/* Try to reserve enough space for both node and dirent.
  	 * Just the node will do for now, though
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
642
643
  	 */
  	namelen = dentry->d_name.len;
9fe4854cd   David Woodhouse   [JFFS2] Remove fl...
644
  	ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &alloclen,
aef9ab478   David Woodhouse   [JFFS2] Support n...
645
  				  ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
  
  	if (ret) {
  		jffs2_free_raw_inode(ri);
  		return ret;
  	}
  
  	inode = jffs2_new_inode(dir_i, mode, ri);
  
  	if (IS_ERR(inode)) {
  		jffs2_free_raw_inode(ri);
  		jffs2_complete_reservation(c);
  		return PTR_ERR(inode);
  	}
  	inode->i_op = &jffs2_file_inode_operations;
  	init_special_inode(inode, inode->i_mode, rdev);
  
  	f = JFFS2_INODE_INFO(inode);
  
  	ri->dsize = ri->csize = cpu_to_je32(devlen);
  	ri->totlen = cpu_to_je32(sizeof(*ri) + devlen);
  	ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
  
  	ri->compr = JFFS2_COMPR_NONE;
  	ri->data_crc = cpu_to_je32(crc32(0, &dev, devlen));
  	ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
671

9fe4854cd   David Woodhouse   [JFFS2] Remove fl...
672
  	fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, ALLOC_NORMAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
673
674
675
676
677
678
679
680
681
682
  
  	jffs2_free_raw_inode(ri);
  
  	if (IS_ERR(fn)) {
  		/* Eeek. Wave bye bye */
  		up(&f->sem);
  		jffs2_complete_reservation(c);
  		jffs2_clear_inode(inode);
  		return PTR_ERR(fn);
  	}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
683
  	/* No data here. Only a metadata node, which will be
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
684
685
686
687
688
689
  	   obsoleted by the first data write
  	*/
  	f->metadata = fn;
  	up(&f->sem);
  
  	jffs2_complete_reservation(c);
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
690
691
692
693
694
695
696
697
698
699
700
  
  	ret = jffs2_init_security(inode, dir_i);
  	if (ret) {
  		jffs2_clear_inode(inode);
  		return ret;
  	}
  	ret = jffs2_init_acl(inode, dir_i);
  	if (ret) {
  		jffs2_clear_inode(inode);
  		return ret;
  	}
9fe4854cd   David Woodhouse   [JFFS2] Remove fl...
701
702
  	ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
  				  ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
  	if (ret) {
  		/* Eep. */
  		jffs2_clear_inode(inode);
  		return ret;
  	}
  
  	rd = jffs2_alloc_raw_dirent();
  	if (!rd) {
  		/* Argh. Now we treat it like a normal delete */
  		jffs2_complete_reservation(c);
  		jffs2_clear_inode(inode);
  		return -ENOMEM;
  	}
  
  	dir_f = JFFS2_INODE_INFO(dir_i);
  	down(&dir_f->sem);
  
  	rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
  	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
  	rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
  	rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
  
  	rd->pino = cpu_to_je32(dir_i->i_ino);
  	rd->version = cpu_to_je32(++dir_f->highest_version);
  	rd->ino = cpu_to_je32(inode->i_ino);
  	rd->mctime = cpu_to_je32(get_seconds());
  	rd->nsize = namelen;
  
  	/* XXX: This is ugly. */
  	rd->type = (mode & S_IFMT) >> 12;
  
  	rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
  	rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen));
9fe4854cd   David Woodhouse   [JFFS2] Remove fl...
736
  	fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
737

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
738
  	if (IS_ERR(fd)) {
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
739
  		/* dirent failed to write. Delete the inode normally
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
  		   as if it were the final unlink() */
  		jffs2_complete_reservation(c);
  		jffs2_free_raw_dirent(rd);
  		up(&dir_f->sem);
  		jffs2_clear_inode(inode);
  		return PTR_ERR(fd);
  	}
  
  	dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
  
  	jffs2_free_raw_dirent(rd);
  
  	/* Link the fd into the inode's list, obsoleting an old
  	   one if necessary. */
  	jffs2_add_fd_to_list(c, fd, &dir_f->dents);
  
  	up(&dir_f->sem);
  	jffs2_complete_reservation(c);
  
  	d_instantiate(dentry, inode);
  
  	return 0;
  }
  
  static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
                          struct inode *new_dir_i, struct dentry *new_dentry)
  {
  	int ret;
  	struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb);
  	struct jffs2_inode_info *victim_f = NULL;
  	uint8_t type;
3a69e0cd2   Artem B. Bityutskiy   [JFFS2] Fix JFFS2...
771
  	uint32_t now;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
772

182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
773
  	/* The VFS will check for us and prevent trying to rename a
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
  	 * file over a directory and vice versa, but if it's a directory,
  	 * the VFS can't check whether the victim is empty. The filesystem
  	 * needs to do that for itself.
  	 */
  	if (new_dentry->d_inode) {
  		victim_f = JFFS2_INODE_INFO(new_dentry->d_inode);
  		if (S_ISDIR(new_dentry->d_inode->i_mode)) {
  			struct jffs2_full_dirent *fd;
  
  			down(&victim_f->sem);
  			for (fd = victim_f->dents; fd; fd = fd->next) {
  				if (fd->ino) {
  					up(&victim_f->sem);
  					return -ENOTEMPTY;
  				}
  			}
  			up(&victim_f->sem);
  		}
  	}
  
  	/* XXX: We probably ought to alloc enough space for
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
795
  	   both nodes at the same time. Writing the new link,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
796
797
798
799
  	   then getting -ENOSPC, is quite bad :)
  	*/
  
  	/* Make a hard link */
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
800

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
801
802
803
  	/* XXX: This is ugly */
  	type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12;
  	if (!type) type = DT_REG;
3a69e0cd2   Artem B. Bityutskiy   [JFFS2] Fix JFFS2...
804
  	now = get_seconds();
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
805
  	ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
806
  			    old_dentry->d_inode->i_ino, type,
3a69e0cd2   Artem B. Bityutskiy   [JFFS2] Fix JFFS2...
807
  			    new_dentry->d_name.name, new_dentry->d_name.len, now);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
808
809
810
811
812
813
  
  	if (ret)
  		return ret;
  
  	if (victim_f) {
  		/* There was a victim. Kill it off nicely */
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
814
  		drop_nlink(new_dentry->d_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
815
816
817
818
819
820
821
822
  		/* Don't oops if the victim was a dirent pointing to an
  		   inode which didn't exist. */
  		if (victim_f->inocache) {
  			down(&victim_f->sem);
  			victim_f->inocache->nlink--;
  			up(&victim_f->sem);
  		}
  	}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
823
  	/* If it was a directory we moved, and there was no victim,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824
825
  	   increase i_nlink on its new parent */
  	if (S_ISDIR(old_dentry->d_inode->i_mode) && !victim_f)
d8c76e6f4   Dave Hansen   [PATCH] r/o bind ...
826
  		inc_nlink(new_dir_i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
827
828
  
  	/* Unlink the original */
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
829
  	ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i),
3a69e0cd2   Artem B. Bityutskiy   [JFFS2] Fix JFFS2...
830
  			      old_dentry->d_name.name, old_dentry->d_name.len, NULL, now);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
831
832
833
834
835
836
837
  
  	/* We don't touch inode->i_nlink */
  
  	if (ret) {
  		/* Oh shit. We really ought to make a single node which can do both atomically */
  		struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode);
  		down(&f->sem);
d8c76e6f4   Dave Hansen   [PATCH] r/o bind ...
838
  		inc_nlink(old_dentry->d_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
839
840
841
842
843
844
845
846
847
  		if (f->inocache)
  			f->inocache->nlink++;
  		up(&f->sem);
  
  		printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link
  ", ret);
  		/* Might as well let the VFS know */
  		d_instantiate(new_dentry, old_dentry->d_inode);
  		atomic_inc(&old_dentry->d_inode->i_count);
3a69e0cd2   Artem B. Bityutskiy   [JFFS2] Fix JFFS2...
848
  		new_dir_i->i_mtime = new_dir_i->i_ctime = ITIME(now);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
849
850
851
852
  		return ret;
  	}
  
  	if (S_ISDIR(old_dentry->d_inode->i_mode))
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
853
  		drop_nlink(old_dir_i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
854

3a69e0cd2   Artem B. Bityutskiy   [JFFS2] Fix JFFS2...
855
  	new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = ITIME(now);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
856
857
  	return 0;
  }