Blame view
fs/jffs2/dir.c
23.2 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 |
/* * JFFS2 -- Journalling Flash File System, Version 2. * |
c00c310ea [JFFS2] Tidy up l... |
4 |
* Copyright © 2001-2007 Red Hat, Inc. |
1da177e4c 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 Linux-2.6.12-rc2 |
10 11 12 13 |
*/ #include <linux/kernel.h> #include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
14 15 16 |
#include <linux/fs.h> #include <linux/crc32.h> #include <linux/jffs2.h> |
cbb9a5617 Move jffs2_fs_i.h... |
17 18 |
#include "jffs2_fs_i.h" #include "jffs2_fs_sb.h" |
1da177e4c Linux-2.6.12-rc2 |
19 20 |
#include <linux/time.h> #include "nodelist.h" |
1da177e4c 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 [JFFS2] Remove co... |
32 |
static int jffs2_mknod (struct inode *,struct dentry *,int,dev_t); |
1da177e4c Linux-2.6.12-rc2 |
33 |
static int jffs2_rename (struct inode *, struct dentry *, |
ef53cb02f [JFFS2] Whitespac... |
34 |
struct inode *, struct dentry *); |
1da177e4c Linux-2.6.12-rc2 |
35 |
|
4b6f5d20b [PATCH] Make most... |
36 |
const struct file_operations jffs2_dir_operations = |
1da177e4c Linux-2.6.12-rc2 |
37 38 39 |
{ .read = generic_read_dir, .readdir = jffs2_readdir, |
0533400b7 [JFFS2] Use .unlo... |
40 |
.unlocked_ioctl=jffs2_ioctl, |
3222a3e55 [PATCH] fix ->lls... |
41 42 |
.fsync = jffs2_fsync, .llseek = generic_file_llseek, |
1da177e4c Linux-2.6.12-rc2 |
43 |
}; |
92e1d5be9 [PATCH] mark stru... |
44 |
const struct inode_operations jffs2_dir_inode_operations = |
1da177e4c Linux-2.6.12-rc2 |
45 |
{ |
265489f01 [JFFS2] Remove co... |
46 47 |
.create = jffs2_create, .lookup = jffs2_lookup, |
1da177e4c Linux-2.6.12-rc2 |
48 49 50 51 52 53 54 |
.link = jffs2_link, .unlink = jffs2_unlink, .symlink = jffs2_symlink, .mkdir = jffs2_mkdir, .rmdir = jffs2_rmdir, .mknod = jffs2_mknod, .rename = jffs2_rename, |
aa98d7cf5 [JFFS2][XATTR] XA... |
55 |
.permission = jffs2_permission, |
1da177e4c Linux-2.6.12-rc2 |
56 |
.setattr = jffs2_setattr, |
aa98d7cf5 [JFFS2][XATTR] XA... |
57 58 59 60 |
.setxattr = jffs2_setxattr, .getxattr = jffs2_getxattr, .listxattr = jffs2_listxattr, .removexattr = jffs2_removexattr |
1da177e4c Linux-2.6.12-rc2 |
61 62 63 64 65 66 |
}; /***********************************************************************/ /* We keep the dirent list sorted in increasing order of name hash, |
182ec4eee [JFFS2] Clean up ... |
67 |
and we use the same hash function as the dentries. Makes this |
1da177e4c Linux-2.6.12-rc2 |
68 69 70 71 72 73 74 75 76 77 78 79 80 |
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 JFFS2: Return an ... |
81 82 |
if (target->d_name.len > JFFS2_MAX_NAME_LEN) return ERR_PTR(-ENAMETOOLONG); |
1da177e4c Linux-2.6.12-rc2 |
83 84 |
dir_f = JFFS2_INODE_INFO(dir_i); c = JFFS2_SB_INFO(dir_i->i_sb); |
ced220703 [JFFS2] semaphore... |
85 |
mutex_lock(&dir_f->sem); |
1da177e4c Linux-2.6.12-rc2 |
86 87 88 |
/* 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 [JFFS2] Clean up ... |
89 |
if (fd_list->nhash == target->d_name.hash && |
1da177e4c Linux-2.6.12-rc2 |
90 91 92 93 94 95 96 97 |
(!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; |
ced220703 [JFFS2] semaphore... |
98 |
mutex_unlock(&dir_f->sem); |
1da177e4c Linux-2.6.12-rc2 |
99 |
if (ino) { |
5451f79f5 iget: stop JFFS2 ... |
100 101 |
inode = jffs2_iget(dir_i->i_sb, ino); if (IS_ERR(inode)) { |
1da177e4c Linux-2.6.12-rc2 |
102 103 |
printk(KERN_WARNING "iget() failed for ino #%u ", ino); |
5451f79f5 iget: stop JFFS2 ... |
104 |
return ERR_CAST(inode); |
1da177e4c Linux-2.6.12-rc2 |
105 106 |
} } |
8966c5e0f [JFFS2] Use d_spl... |
107 |
return d_splice_alias(inode, target); |
1da177e4c Linux-2.6.12-rc2 |
108 109 110 111 112 113 114 115 116 |
} /***********************************************************************/ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir) { struct jffs2_inode_info *f; struct jffs2_sb_info *c; |
ec2e203c8 [PATCH] struct pa... |
117 |
struct inode *inode = filp->f_path.dentry->d_inode; |
1da177e4c Linux-2.6.12-rc2 |
118 119 |
struct jffs2_full_dirent *fd; unsigned long offset, curofs; |
ec2e203c8 [PATCH] struct pa... |
120 121 |
D1(printk(KERN_DEBUG "jffs2_readdir() for dir_i #%lu ", filp->f_path.dentry->d_inode->i_ino)); |
1da177e4c Linux-2.6.12-rc2 |
122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
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 [PATCH] struct pa... |
136 |
unsigned long pino = parent_ino(filp->f_path.dentry); |
1da177e4c Linux-2.6.12-rc2 |
137 138 139 140 141 142 143 144 |
D1(printk(KERN_DEBUG "Dirent 1: \"..\", ino #%lu ", pino)); if (filldir(dirent, "..", 2, 1, pino, DT_DIR) < 0) goto out; offset++; } curofs=1; |
ced220703 [JFFS2] semaphore... |
145 |
mutex_lock(&f->sem); |
1da177e4c Linux-2.6.12-rc2 |
146 147 148 149 150 |
for (fd = f->dents; fd; fd = fd->next) { curofs++; /* First loop: curofs = 2; offset = 2 */ if (curofs < offset) { |
182ec4eee [JFFS2] Clean up ... |
151 152 |
D2(printk(KERN_DEBUG "Skipping dirent: \"%s\", ino #%u, type %d, because curofs %ld < offset %ld ", |
1da177e4c Linux-2.6.12-rc2 |
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
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++; } |
ced220703 [JFFS2] semaphore... |
168 |
mutex_unlock(&f->sem); |
1da177e4c Linux-2.6.12-rc2 |
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
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 [JFFS2] Clean up ... |
189 |
|
1da177e4c Linux-2.6.12-rc2 |
190 191 192 193 |
c = JFFS2_SB_INFO(dir_i->i_sb); D1(printk(KERN_DEBUG "jffs2_create() ")); |
cfc8dc6f6 [JFFS2] Tidy up f... |
194 |
inode = jffs2_new_inode(dir_i, mode, ri); |
1da177e4c Linux-2.6.12-rc2 |
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
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); |
590fe34c4 [JFFS2] Quiet loc... |
210 211 212 213 214 215 |
/* jffs2_do_create() will want to lock it, _after_ reserving space and taking c-alloc_sem. If we keep it locked here, lockdep gets unhappy (although it's a false positive; nothing else will be looking at this inode yet so there's no chance of AB-BA deadlock involving its f->sem). */ mutex_unlock(&f->sem); |
182ec4eee [JFFS2] Clean up ... |
216 |
ret = jffs2_do_create(c, dir_f, f, ri, |
1da177e4c Linux-2.6.12-rc2 |
217 |
dentry->d_name.name, dentry->d_name.len); |
aa98d7cf5 [JFFS2][XATTR] XA... |
218 219 |
if (ret) goto fail; |
1da177e4c Linux-2.6.12-rc2 |
220 221 222 223 224 225 226 227 |
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 ", |
27c72b040 [JFFS2] Track par... |
228 229 |
inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->pino_nlink, inode->i_mapping->nrpages)); |
1da177e4c Linux-2.6.12-rc2 |
230 |
return 0; |
aa98d7cf5 [JFFS2][XATTR] XA... |
231 232 233 234 235 236 |
fail: make_bad_inode(inode); iput(inode); jffs2_free_raw_inode(ri); return ret; |
1da177e4c Linux-2.6.12-rc2 |
237 238 239 240 241 242 243 244 245 246 247 |
} /***********************************************************************/ 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 [JFFS2] Fix JFFS2... |
248 |
uint32_t now = get_seconds(); |
1da177e4c Linux-2.6.12-rc2 |
249 |
|
182ec4eee [JFFS2] Clean up ... |
250 |
ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, |
3a69e0cd2 [JFFS2] Fix JFFS2... |
251 |
dentry->d_name.len, dead_f, now); |
1da177e4c Linux-2.6.12-rc2 |
252 |
if (dead_f->inocache) |
27c72b040 [JFFS2] Track par... |
253 |
dentry->d_inode->i_nlink = dead_f->inocache->pino_nlink; |
3a69e0cd2 [JFFS2] Fix JFFS2... |
254 255 |
if (!ret) dir_i->i_mtime = dir_i->i_ctime = ITIME(now); |
1da177e4c Linux-2.6.12-rc2 |
256 257 258 259 260 261 262 263 264 265 266 267 |
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 [JFFS2] Fix JFFS2... |
268 |
uint32_t now; |
1da177e4c Linux-2.6.12-rc2 |
269 270 271 272 273 274 275 276 277 278 279 |
/* 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 [JFFS2] Fix JFFS2... |
280 281 |
now = get_seconds(); ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, dentry->d_name.name, dentry->d_name.len, now); |
1da177e4c Linux-2.6.12-rc2 |
282 283 |
if (!ret) { |
ced220703 [JFFS2] semaphore... |
284 |
mutex_lock(&f->sem); |
27c72b040 [JFFS2] Track par... |
285 |
old_dentry->d_inode->i_nlink = ++f->inocache->pino_nlink; |
ced220703 [JFFS2] semaphore... |
286 |
mutex_unlock(&f->sem); |
1da177e4c Linux-2.6.12-rc2 |
287 |
d_instantiate(dentry, old_dentry->d_inode); |
3a69e0cd2 [JFFS2] Fix JFFS2... |
288 |
dir_i->i_mtime = dir_i->i_ctime = ITIME(now); |
1da177e4c Linux-2.6.12-rc2 |
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 |
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 [JFFS2] Remove fl... |
306 |
uint32_t alloclen; |
32f1a95d5 [JFFS2] Add symli... |
307 |
int ret, targetlen = strlen(target); |
1da177e4c Linux-2.6.12-rc2 |
308 309 310 |
/* FIXME: If you care. We'd need to use frags for the target if it grows much more than this */ |
32f1a95d5 [JFFS2] Add symli... |
311 |
if (targetlen > 254) |
bde86fec7 [JFFS2] Correct s... |
312 |
return -ENAMETOOLONG; |
1da177e4c Linux-2.6.12-rc2 |
313 314 315 316 317 |
ri = jffs2_alloc_raw_inode(); if (!ri) return -ENOMEM; |
182ec4eee [JFFS2] Clean up ... |
318 |
|
1da177e4c Linux-2.6.12-rc2 |
319 |
c = JFFS2_SB_INFO(dir_i->i_sb); |
182ec4eee [JFFS2] Clean up ... |
320 321 322 |
/* Try to reserve enough space for both node and dirent. * Just the node will do for now, though |
1da177e4c Linux-2.6.12-rc2 |
323 324 |
*/ namelen = dentry->d_name.len; |
9fe4854cd [JFFS2] Remove fl... |
325 326 |
ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); |
1da177e4c Linux-2.6.12-rc2 |
327 328 329 330 331 |
if (ret) { jffs2_free_raw_inode(ri); return ret; } |
cfc8dc6f6 [JFFS2] Tidy up f... |
332 |
inode = jffs2_new_inode(dir_i, S_IFLNK | S_IRWXUGO, ri); |
1da177e4c Linux-2.6.12-rc2 |
333 334 335 336 337 338 339 340 341 342 |
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 [JFFS2] Add symli... |
343 |
inode->i_size = targetlen; |
1da177e4c Linux-2.6.12-rc2 |
344 345 346 347 348 |
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 [JFFS2] Add symli... |
349 |
ri->data_crc = cpu_to_je32(crc32(0, target, targetlen)); |
1da177e4c Linux-2.6.12-rc2 |
350 |
ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); |
182ec4eee [JFFS2] Clean up ... |
351 |
|
9fe4854cd [JFFS2] Remove fl... |
352 |
fn = jffs2_write_dnode(c, f, ri, target, targetlen, ALLOC_NORMAL); |
1da177e4c Linux-2.6.12-rc2 |
353 354 355 356 357 |
jffs2_free_raw_inode(ri); if (IS_ERR(fn)) { /* Eeek. Wave bye bye */ |
ced220703 [JFFS2] semaphore... |
358 |
mutex_unlock(&f->sem); |
1da177e4c Linux-2.6.12-rc2 |
359 360 361 362 |
jffs2_complete_reservation(c); jffs2_clear_inode(inode); return PTR_ERR(fn); } |
32f1a95d5 [JFFS2] Add symli... |
363 |
|
2b79adcca [JFFS2] Use f->ta... |
364 365 366 |
/* We use f->target field to store the target path. */ f->target = kmalloc(targetlen + 1, GFP_KERNEL); if (!f->target) { |
32f1a95d5 [JFFS2] Add symli... |
367 368 |
printk(KERN_WARNING "Can't allocate %d bytes of memory ", targetlen + 1); |
ced220703 [JFFS2] semaphore... |
369 |
mutex_unlock(&f->sem); |
32f1a95d5 [JFFS2] Add symli... |
370 371 372 373 |
jffs2_complete_reservation(c); jffs2_clear_inode(inode); return -ENOMEM; } |
2b79adcca [JFFS2] Use f->ta... |
374 375 376 |
memcpy(f->target, target, targetlen + 1); D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached ", (char *)f->target)); |
32f1a95d5 [JFFS2] Add symli... |
377 |
|
182ec4eee [JFFS2] Clean up ... |
378 |
/* No data here. Only a metadata node, which will be |
1da177e4c Linux-2.6.12-rc2 |
379 380 381 |
obsoleted by the first data write */ f->metadata = fn; |
ced220703 [JFFS2] semaphore... |
382 |
mutex_unlock(&f->sem); |
1da177e4c Linux-2.6.12-rc2 |
383 384 |
jffs2_complete_reservation(c); |
aa98d7cf5 [JFFS2][XATTR] XA... |
385 386 387 388 389 390 |
ret = jffs2_init_security(inode, dir_i); if (ret) { jffs2_clear_inode(inode); return ret; } |
cfc8dc6f6 [JFFS2] Tidy up f... |
391 |
ret = jffs2_init_acl_post(inode); |
aa98d7cf5 [JFFS2][XATTR] XA... |
392 393 394 395 |
if (ret) { jffs2_clear_inode(inode); return ret; } |
9fe4854cd [JFFS2] Remove fl... |
396 397 |
ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); |
1da177e4c Linux-2.6.12-rc2 |
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 |
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); |
ced220703 [JFFS2] semaphore... |
413 |
mutex_lock(&dir_f->sem); |
1da177e4c Linux-2.6.12-rc2 |
414 415 416 417 418 419 420 421 422 423 424 425 426 427 |
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 [JFFS2] Remove fl... |
428 |
fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL); |
1da177e4c Linux-2.6.12-rc2 |
429 430 |
if (IS_ERR(fd)) { |
182ec4eee [JFFS2] Clean up ... |
431 |
/* dirent failed to write. Delete the inode normally |
1da177e4c Linux-2.6.12-rc2 |
432 433 434 |
as if it were the final unlink() */ jffs2_complete_reservation(c); jffs2_free_raw_dirent(rd); |
ced220703 [JFFS2] semaphore... |
435 |
mutex_unlock(&dir_f->sem); |
1da177e4c Linux-2.6.12-rc2 |
436 437 438 439 440 441 442 443 444 445 446 |
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); |
ced220703 [JFFS2] semaphore... |
447 |
mutex_unlock(&dir_f->sem); |
1da177e4c Linux-2.6.12-rc2 |
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 |
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 [JFFS2] Remove fl... |
465 |
uint32_t alloclen; |
1da177e4c Linux-2.6.12-rc2 |
466 467 468 469 470 471 472 |
int ret; mode |= S_IFDIR; ri = jffs2_alloc_raw_inode(); if (!ri) return -ENOMEM; |
182ec4eee [JFFS2] Clean up ... |
473 |
|
1da177e4c Linux-2.6.12-rc2 |
474 |
c = JFFS2_SB_INFO(dir_i->i_sb); |
182ec4eee [JFFS2] Clean up ... |
475 476 |
/* Try to reserve enough space for both node and dirent. * Just the node will do for now, though |
1da177e4c Linux-2.6.12-rc2 |
477 478 |
*/ namelen = dentry->d_name.len; |
9fe4854cd [JFFS2] Remove fl... |
479 480 |
ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); |
1da177e4c Linux-2.6.12-rc2 |
481 482 483 484 485 |
if (ret) { jffs2_free_raw_inode(ri); return ret; } |
cfc8dc6f6 [JFFS2] Tidy up f... |
486 |
inode = jffs2_new_inode(dir_i, mode, ri); |
1da177e4c Linux-2.6.12-rc2 |
487 488 489 490 491 492 493 494 495 |
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; |
1da177e4c Linux-2.6.12-rc2 |
496 497 |
f = JFFS2_INODE_INFO(inode); |
27c72b040 [JFFS2] Track par... |
498 499 500 501 |
/* Directories get nlink 2 at start */ inode->i_nlink = 2; /* but ic->pino_nlink is the parent ino# */ f->inocache->pino_nlink = dir_i->i_ino; |
1da177e4c Linux-2.6.12-rc2 |
502 503 |
ri->data_crc = cpu_to_je32(0); ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); |
182ec4eee [JFFS2] Clean up ... |
504 |
|
9fe4854cd [JFFS2] Remove fl... |
505 |
fn = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL); |
1da177e4c Linux-2.6.12-rc2 |
506 507 508 509 510 |
jffs2_free_raw_inode(ri); if (IS_ERR(fn)) { /* Eeek. Wave bye bye */ |
ced220703 [JFFS2] semaphore... |
511 |
mutex_unlock(&f->sem); |
1da177e4c Linux-2.6.12-rc2 |
512 513 514 515 |
jffs2_complete_reservation(c); jffs2_clear_inode(inode); return PTR_ERR(fn); } |
182ec4eee [JFFS2] Clean up ... |
516 |
/* No data here. Only a metadata node, which will be |
1da177e4c Linux-2.6.12-rc2 |
517 518 519 |
obsoleted by the first data write */ f->metadata = fn; |
ced220703 [JFFS2] semaphore... |
520 |
mutex_unlock(&f->sem); |
1da177e4c Linux-2.6.12-rc2 |
521 522 |
jffs2_complete_reservation(c); |
aa98d7cf5 [JFFS2][XATTR] XA... |
523 524 525 526 527 528 |
ret = jffs2_init_security(inode, dir_i); if (ret) { jffs2_clear_inode(inode); return ret; } |
cfc8dc6f6 [JFFS2] Tidy up f... |
529 |
ret = jffs2_init_acl_post(inode); |
aa98d7cf5 [JFFS2][XATTR] XA... |
530 531 532 533 |
if (ret) { jffs2_clear_inode(inode); return ret; } |
9fe4854cd [JFFS2] Remove fl... |
534 535 |
ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); |
1da177e4c Linux-2.6.12-rc2 |
536 537 538 539 540 |
if (ret) { /* Eep. */ jffs2_clear_inode(inode); return ret; } |
182ec4eee [JFFS2] Clean up ... |
541 |
|
1da177e4c Linux-2.6.12-rc2 |
542 543 544 545 546 547 548 549 550 |
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); |
ced220703 [JFFS2] semaphore... |
551 |
mutex_lock(&dir_f->sem); |
1da177e4c Linux-2.6.12-rc2 |
552 553 554 555 556 557 558 559 560 561 562 563 564 565 |
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 [JFFS2] Remove fl... |
566 |
fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL); |
182ec4eee [JFFS2] Clean up ... |
567 |
|
1da177e4c Linux-2.6.12-rc2 |
568 |
if (IS_ERR(fd)) { |
182ec4eee [JFFS2] Clean up ... |
569 |
/* dirent failed to write. Delete the inode normally |
1da177e4c Linux-2.6.12-rc2 |
570 571 572 |
as if it were the final unlink() */ jffs2_complete_reservation(c); jffs2_free_raw_dirent(rd); |
ced220703 [JFFS2] semaphore... |
573 |
mutex_unlock(&dir_f->sem); |
1da177e4c Linux-2.6.12-rc2 |
574 575 576 577 578 |
jffs2_clear_inode(inode); return PTR_ERR(fd); } dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime)); |
d8c76e6f4 [PATCH] r/o bind ... |
579 |
inc_nlink(dir_i); |
1da177e4c Linux-2.6.12-rc2 |
580 581 582 583 584 585 |
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); |
ced220703 [JFFS2] semaphore... |
586 |
mutex_unlock(&dir_f->sem); |
1da177e4c Linux-2.6.12-rc2 |
587 588 589 590 591 592 593 594 |
jffs2_complete_reservation(c); d_instantiate(dentry, inode); return 0; } static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry) { |
27c72b040 [JFFS2] Track par... |
595 596 |
struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb); struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); |
1da177e4c Linux-2.6.12-rc2 |
597 598 599 |
struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode); struct jffs2_full_dirent *fd; int ret; |
27c72b040 [JFFS2] Track par... |
600 |
uint32_t now = get_seconds(); |
1da177e4c Linux-2.6.12-rc2 |
601 602 603 604 605 |
for (fd = f->dents ; fd; fd = fd->next) { if (fd->ino) return -ENOTEMPTY; } |
27c72b040 [JFFS2] Track par... |
606 607 608 609 610 611 |
ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, dentry->d_name.len, f, now); if (!ret) { dir_i->i_mtime = dir_i->i_ctime = ITIME(now); clear_nlink(dentry->d_inode); |
9a53c3a78 [PATCH] r/o bind ... |
612 |
drop_nlink(dir_i); |
27c72b040 [JFFS2] Track par... |
613 |
} |
1da177e4c Linux-2.6.12-rc2 |
614 615 |
return ret; } |
265489f01 [JFFS2] Remove co... |
616 |
static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, dev_t rdev) |
1da177e4c Linux-2.6.12-rc2 |
617 618 619 620 621 622 623 624 625 |
{ 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 [JFFS2] Support n... |
626 |
union jffs2_device_node dev; |
1da177e4c Linux-2.6.12-rc2 |
627 |
int devlen = 0; |
9fe4854cd [JFFS2] Remove fl... |
628 |
uint32_t alloclen; |
1da177e4c Linux-2.6.12-rc2 |
629 |
int ret; |
aef9ab478 [JFFS2] Support n... |
630 |
if (!new_valid_dev(rdev)) |
1da177e4c Linux-2.6.12-rc2 |
631 632 633 634 635 |
return -EINVAL; ri = jffs2_alloc_raw_inode(); if (!ri) return -ENOMEM; |
182ec4eee [JFFS2] Clean up ... |
636 |
|
1da177e4c Linux-2.6.12-rc2 |
637 |
c = JFFS2_SB_INFO(dir_i->i_sb); |
182ec4eee [JFFS2] Clean up ... |
638 |
|
aef9ab478 [JFFS2] Support n... |
639 640 |
if (S_ISBLK(mode) || S_ISCHR(mode)) devlen = jffs2_encode_dev(&dev, rdev); |
182ec4eee [JFFS2] Clean up ... |
641 642 643 |
/* Try to reserve enough space for both node and dirent. * Just the node will do for now, though |
1da177e4c Linux-2.6.12-rc2 |
644 645 |
*/ namelen = dentry->d_name.len; |
9fe4854cd [JFFS2] Remove fl... |
646 |
ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &alloclen, |
aef9ab478 [JFFS2] Support n... |
647 |
ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); |
1da177e4c Linux-2.6.12-rc2 |
648 649 650 651 652 |
if (ret) { jffs2_free_raw_inode(ri); return ret; } |
cfc8dc6f6 [JFFS2] Tidy up f... |
653 |
inode = jffs2_new_inode(dir_i, mode, ri); |
1da177e4c Linux-2.6.12-rc2 |
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 |
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 [JFFS2] Clean up ... |
672 |
|
9fe4854cd [JFFS2] Remove fl... |
673 |
fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, ALLOC_NORMAL); |
1da177e4c Linux-2.6.12-rc2 |
674 675 676 677 678 |
jffs2_free_raw_inode(ri); if (IS_ERR(fn)) { /* Eeek. Wave bye bye */ |
ced220703 [JFFS2] semaphore... |
679 |
mutex_unlock(&f->sem); |
1da177e4c Linux-2.6.12-rc2 |
680 681 682 683 |
jffs2_complete_reservation(c); jffs2_clear_inode(inode); return PTR_ERR(fn); } |
182ec4eee [JFFS2] Clean up ... |
684 |
/* No data here. Only a metadata node, which will be |
1da177e4c Linux-2.6.12-rc2 |
685 686 687 |
obsoleted by the first data write */ f->metadata = fn; |
ced220703 [JFFS2] semaphore... |
688 |
mutex_unlock(&f->sem); |
1da177e4c Linux-2.6.12-rc2 |
689 690 |
jffs2_complete_reservation(c); |
aa98d7cf5 [JFFS2][XATTR] XA... |
691 692 693 694 695 696 |
ret = jffs2_init_security(inode, dir_i); if (ret) { jffs2_clear_inode(inode); return ret; } |
cfc8dc6f6 [JFFS2] Tidy up f... |
697 |
ret = jffs2_init_acl_post(inode); |
aa98d7cf5 [JFFS2][XATTR] XA... |
698 699 700 701 |
if (ret) { jffs2_clear_inode(inode); return ret; } |
9fe4854cd [JFFS2] Remove fl... |
702 703 |
ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); |
1da177e4c Linux-2.6.12-rc2 |
704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 |
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); |
ced220703 [JFFS2] semaphore... |
719 |
mutex_lock(&dir_f->sem); |
1da177e4c Linux-2.6.12-rc2 |
720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 |
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 [JFFS2] Remove fl... |
737 |
fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL); |
182ec4eee [JFFS2] Clean up ... |
738 |
|
1da177e4c Linux-2.6.12-rc2 |
739 |
if (IS_ERR(fd)) { |
182ec4eee [JFFS2] Clean up ... |
740 |
/* dirent failed to write. Delete the inode normally |
1da177e4c Linux-2.6.12-rc2 |
741 742 743 |
as if it were the final unlink() */ jffs2_complete_reservation(c); jffs2_free_raw_dirent(rd); |
ced220703 [JFFS2] semaphore... |
744 |
mutex_unlock(&dir_f->sem); |
1da177e4c Linux-2.6.12-rc2 |
745 746 747 748 749 750 751 752 753 754 755 |
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); |
ced220703 [JFFS2] semaphore... |
756 |
mutex_unlock(&dir_f->sem); |
1da177e4c Linux-2.6.12-rc2 |
757 758 759 760 761 762 763 764 |
jffs2_complete_reservation(c); d_instantiate(dentry, inode); return 0; } static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, |
ef53cb02f [JFFS2] Whitespac... |
765 |
struct inode *new_dir_i, struct dentry *new_dentry) |
1da177e4c Linux-2.6.12-rc2 |
766 767 768 769 770 |
{ 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 [JFFS2] Fix JFFS2... |
771 |
uint32_t now; |
1da177e4c Linux-2.6.12-rc2 |
772 |
|
182ec4eee [JFFS2] Clean up ... |
773 |
/* The VFS will check for us and prevent trying to rename a |
1da177e4c Linux-2.6.12-rc2 |
774 775 776 777 778 779 780 781 |
* 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; |
ced220703 [JFFS2] semaphore... |
782 |
mutex_lock(&victim_f->sem); |
1da177e4c Linux-2.6.12-rc2 |
783 784 |
for (fd = victim_f->dents; fd; fd = fd->next) { if (fd->ino) { |
ced220703 [JFFS2] semaphore... |
785 |
mutex_unlock(&victim_f->sem); |
1da177e4c Linux-2.6.12-rc2 |
786 787 788 |
return -ENOTEMPTY; } } |
ced220703 [JFFS2] semaphore... |
789 |
mutex_unlock(&victim_f->sem); |
1da177e4c Linux-2.6.12-rc2 |
790 791 792 793 |
} } /* XXX: We probably ought to alloc enough space for |
182ec4eee [JFFS2] Clean up ... |
794 |
both nodes at the same time. Writing the new link, |
1da177e4c Linux-2.6.12-rc2 |
795 796 797 798 |
then getting -ENOSPC, is quite bad :) */ /* Make a hard link */ |
182ec4eee [JFFS2] Clean up ... |
799 |
|
1da177e4c Linux-2.6.12-rc2 |
800 801 802 |
/* XXX: This is ugly */ type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12; if (!type) type = DT_REG; |
3a69e0cd2 [JFFS2] Fix JFFS2... |
803 |
now = get_seconds(); |
182ec4eee [JFFS2] Clean up ... |
804 |
ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i), |
1da177e4c Linux-2.6.12-rc2 |
805 |
old_dentry->d_inode->i_ino, type, |
3a69e0cd2 [JFFS2] Fix JFFS2... |
806 |
new_dentry->d_name.name, new_dentry->d_name.len, now); |
1da177e4c Linux-2.6.12-rc2 |
807 808 809 810 811 812 |
if (ret) return ret; if (victim_f) { /* There was a victim. Kill it off nicely */ |
9a53c3a78 [PATCH] r/o bind ... |
813 |
drop_nlink(new_dentry->d_inode); |
1da177e4c Linux-2.6.12-rc2 |
814 815 816 |
/* Don't oops if the victim was a dirent pointing to an inode which didn't exist. */ if (victim_f->inocache) { |
ced220703 [JFFS2] semaphore... |
817 |
mutex_lock(&victim_f->sem); |
27c72b040 [JFFS2] Track par... |
818 819 820 821 |
if (S_ISDIR(new_dentry->d_inode->i_mode)) victim_f->inocache->pino_nlink = 0; else victim_f->inocache->pino_nlink--; |
ced220703 [JFFS2] semaphore... |
822 |
mutex_unlock(&victim_f->sem); |
1da177e4c Linux-2.6.12-rc2 |
823 824 |
} } |
182ec4eee [JFFS2] Clean up ... |
825 |
/* If it was a directory we moved, and there was no victim, |
1da177e4c Linux-2.6.12-rc2 |
826 827 |
increase i_nlink on its new parent */ if (S_ISDIR(old_dentry->d_inode->i_mode) && !victim_f) |
d8c76e6f4 [PATCH] r/o bind ... |
828 |
inc_nlink(new_dir_i); |
1da177e4c Linux-2.6.12-rc2 |
829 830 |
/* Unlink the original */ |
182ec4eee [JFFS2] Clean up ... |
831 |
ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), |
3a69e0cd2 [JFFS2] Fix JFFS2... |
832 |
old_dentry->d_name.name, old_dentry->d_name.len, NULL, now); |
1da177e4c Linux-2.6.12-rc2 |
833 834 835 836 837 838 |
/* 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); |
ced220703 [JFFS2] semaphore... |
839 |
mutex_lock(&f->sem); |
d8c76e6f4 [PATCH] r/o bind ... |
840 |
inc_nlink(old_dentry->d_inode); |
27c72b040 [JFFS2] Track par... |
841 842 |
if (f->inocache && !S_ISDIR(old_dentry->d_inode->i_mode)) f->inocache->pino_nlink++; |
ced220703 [JFFS2] semaphore... |
843 |
mutex_unlock(&f->sem); |
1da177e4c Linux-2.6.12-rc2 |
844 845 846 847 848 849 |
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 [JFFS2] Fix JFFS2... |
850 |
new_dir_i->i_mtime = new_dir_i->i_ctime = ITIME(now); |
1da177e4c Linux-2.6.12-rc2 |
851 852 853 854 |
return ret; } if (S_ISDIR(old_dentry->d_inode->i_mode)) |
9a53c3a78 [PATCH] r/o bind ... |
855 |
drop_nlink(old_dir_i); |
1da177e4c Linux-2.6.12-rc2 |
856 |
|
3a69e0cd2 [JFFS2] Fix JFFS2... |
857 |
new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = ITIME(now); |
1da177e4c Linux-2.6.12-rc2 |
858 859 |
return 0; } |