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