Blame view
fs/ext2/namei.c
9.57 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
/* * linux/fs/ext2/namei.c * * Rewrite to pagecache. Almost all code had been changed, so blame me * if the things go wrong. Please, send bug reports to * viro@parcelfarce.linux.theplanet.co.uk * * Stuff here is basically a glue between the VFS and generic UNIXish * filesystem that keeps everything in pagecache. All knowledge of the * directory layout is in fs/ext2/dir.c - it turned out to be easily separatable * and it's easier to debug that way. In principle we might want to * generalize that a bit and turn it into a library. Or not. * * The only non-static object here is ext2_dir_inode_operations. * * TODO: get rid of kmap() use, add readahead. * * Copyright (C) 1992, 1993, 1994, 1995 * Remy Card (card@masi.ibp.fr) * Laboratoire MASI - Institut Blaise Pascal * Universite Pierre et Marie Curie (Paris VI) * * from * * linux/fs/minix/namei.c * * Copyright (C) 1991, 1992 Linus Torvalds * * Big-endian to little-endian byte-swapping/bitmaps by * David S. Miller (davem@caip.rutgers.edu), 1995 */ #include <linux/pagemap.h> |
907f4554e dquot: move dquot... |
34 |
#include <linux/quotaops.h> |
1da177e4c Linux-2.6.12-rc2 |
35 36 37 |
#include "ext2.h" #include "xattr.h" #include "acl.h" |
6d79125bb [PATCH] xip: ext2... |
38 |
#include "xip.h" |
1da177e4c Linux-2.6.12-rc2 |
39 |
|
1da177e4c Linux-2.6.12-rc2 |
40 41 42 43 44 |
static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode) { int err = ext2_add_link(dentry, inode); if (!err) { d_instantiate(dentry, inode); |
41080b5a2 nfsd race fixes: ... |
45 |
unlock_new_inode(inode); |
1da177e4c Linux-2.6.12-rc2 |
46 47 |
return 0; } |
a513b035e [PATCH] ext2: swi... |
48 |
inode_dec_link_count(inode); |
41080b5a2 nfsd race fixes: ... |
49 |
unlock_new_inode(inode); |
1da177e4c Linux-2.6.12-rc2 |
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
iput(inode); return err; } /* * Methods themselves. */ static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd) { struct inode * inode; ino_t ino; if (dentry->d_name.len > EXT2_NAME_LEN) return ERR_PTR(-ENAMETOOLONG); |
a9885444f [PATCH] get rid o... |
65 |
ino = ext2_inode_by_name(dir, &dentry->d_name); |
1da177e4c Linux-2.6.12-rc2 |
66 67 |
inode = NULL; if (ino) { |
52fcf7032 iget: stop EXT2 f... |
68 |
inode = ext2_iget(dir->i_sb, ino); |
0ed0cca7a ext2: Remove redu... |
69 |
if (IS_ERR(inode)) { |
4d6c13f87 ext2: return -EIO... |
70 71 72 |
if (PTR_ERR(inode) == -ESTALE) { ext2_error(dir->i_sb, __func__, "deleted inode referenced: %lu", |
a4255e4c1 ext2: fix format ... |
73 |
(unsigned long) ino); |
4d6c13f87 ext2: return -EIO... |
74 75 76 77 78 |
return ERR_PTR(-EIO); } else { return ERR_CAST(inode); } } |
1da177e4c Linux-2.6.12-rc2 |
79 |
} |
082a05c6f [PATCH] ext2: rem... |
80 |
return d_splice_alias(inode, dentry); |
1da177e4c Linux-2.6.12-rc2 |
81 82 83 84 |
} struct dentry *ext2_get_parent(struct dentry *child) { |
a9885444f [PATCH] get rid o... |
85 86 |
struct qstr dotdot = {.name = "..", .len = 2}; unsigned long ino = ext2_inode_by_name(child->d_inode, &dotdot); |
1da177e4c Linux-2.6.12-rc2 |
87 88 |
if (!ino) return ERR_PTR(-ENOENT); |
440037287 [PATCH] switch al... |
89 |
return d_obtain_alias(ext2_iget(child->d_inode->i_sb, ino)); |
1da177e4c Linux-2.6.12-rc2 |
90 91 92 93 94 95 96 97 98 99 100 101 |
} /* * By the time this is called, we already have created * the directory cache entry for the new file, but it * is so far negative - it has no inode. * * If the create succeeds, we fill in the inode information * with d_instantiate(). */ static int ext2_create (struct inode * dir, struct dentry * dentry, int mode, struct nameidata *nd) { |
907f4554e dquot: move dquot... |
102 |
struct inode *inode; |
871a29315 dquot: cleanup dq... |
103 |
dquot_initialize(dir); |
907f4554e dquot: move dquot... |
104 |
|
2a7dba391 fs/vfs/security: ... |
105 |
inode = ext2_new_inode(dir, mode, &dentry->d_name); |
907f4554e dquot: move dquot... |
106 107 108 109 110 111 112 113 114 115 116 117 118 |
if (IS_ERR(inode)) return PTR_ERR(inode); inode->i_op = &ext2_file_inode_operations; if (ext2_use_xip(inode->i_sb)) { inode->i_mapping->a_ops = &ext2_aops_xip; inode->i_fop = &ext2_xip_file_operations; } else if (test_opt(inode->i_sb, NOBH)) { inode->i_mapping->a_ops = &ext2_nobh_aops; inode->i_fop = &ext2_file_operations; } else { inode->i_mapping->a_ops = &ext2_aops; inode->i_fop = &ext2_file_operations; |
1da177e4c Linux-2.6.12-rc2 |
119 |
} |
907f4554e dquot: move dquot... |
120 121 |
mark_inode_dirty(inode); return ext2_add_nondir(dentry, inode); |
1da177e4c Linux-2.6.12-rc2 |
122 123 124 125 126 127 128 129 130 |
} static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t rdev) { struct inode * inode; int err; if (!new_valid_dev(rdev)) return -EINVAL; |
871a29315 dquot: cleanup dq... |
131 |
dquot_initialize(dir); |
907f4554e dquot: move dquot... |
132 |
|
2a7dba391 fs/vfs/security: ... |
133 |
inode = ext2_new_inode (dir, mode, &dentry->d_name); |
1da177e4c Linux-2.6.12-rc2 |
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
err = PTR_ERR(inode); if (!IS_ERR(inode)) { init_special_inode(inode, inode->i_mode, rdev); #ifdef CONFIG_EXT2_FS_XATTR inode->i_op = &ext2_special_inode_operations; #endif mark_inode_dirty(inode); err = ext2_add_nondir(dentry, inode); } return err; } static int ext2_symlink (struct inode * dir, struct dentry * dentry, const char * symname) { struct super_block * sb = dir->i_sb; int err = -ENAMETOOLONG; unsigned l = strlen(symname)+1; struct inode * inode; if (l > sb->s_blocksize) goto out; |
871a29315 dquot: cleanup dq... |
156 |
dquot_initialize(dir); |
907f4554e dquot: move dquot... |
157 |
|
2a7dba391 fs/vfs/security: ... |
158 |
inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO, &dentry->d_name); |
1da177e4c Linux-2.6.12-rc2 |
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 |
err = PTR_ERR(inode); if (IS_ERR(inode)) goto out; if (l > sizeof (EXT2_I(inode)->i_data)) { /* slow symlink */ inode->i_op = &ext2_symlink_inode_operations; if (test_opt(inode->i_sb, NOBH)) inode->i_mapping->a_ops = &ext2_nobh_aops; else inode->i_mapping->a_ops = &ext2_aops; err = page_symlink(inode, symname, l); if (err) goto out_fail; } else { /* fast symlink */ inode->i_op = &ext2_fast_symlink_inode_operations; memcpy((char*)(EXT2_I(inode)->i_data),symname,l); inode->i_size = l-1; } mark_inode_dirty(inode); err = ext2_add_nondir(dentry, inode); out: return err; out_fail: |
a513b035e [PATCH] ext2: swi... |
186 |
inode_dec_link_count(inode); |
41080b5a2 nfsd race fixes: ... |
187 |
unlock_new_inode(inode); |
1da177e4c Linux-2.6.12-rc2 |
188 189 190 191 192 193 194 195 |
iput (inode); goto out; } static int ext2_link (struct dentry * old_dentry, struct inode * dir, struct dentry *dentry) { struct inode *inode = old_dentry->d_inode; |
41080b5a2 nfsd race fixes: ... |
196 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
197 198 199 |
if (inode->i_nlink >= EXT2_LINK_MAX) return -EMLINK; |
871a29315 dquot: cleanup dq... |
200 |
dquot_initialize(dir); |
907f4554e dquot: move dquot... |
201 |
|
1da177e4c Linux-2.6.12-rc2 |
202 |
inode->i_ctime = CURRENT_TIME_SEC; |
a513b035e [PATCH] ext2: swi... |
203 |
inode_inc_link_count(inode); |
7de9c6ee3 new helper: ihold() |
204 |
ihold(inode); |
1da177e4c Linux-2.6.12-rc2 |
205 |
|
41080b5a2 nfsd race fixes: ... |
206 207 208 209 210 211 212 213 |
err = ext2_add_link(dentry, inode); if (!err) { d_instantiate(dentry, inode); return 0; } inode_dec_link_count(inode); iput(inode); return err; |
1da177e4c Linux-2.6.12-rc2 |
214 215 216 217 218 219 220 221 222 |
} static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode) { struct inode * inode; int err = -EMLINK; if (dir->i_nlink >= EXT2_LINK_MAX) goto out; |
871a29315 dquot: cleanup dq... |
223 |
dquot_initialize(dir); |
907f4554e dquot: move dquot... |
224 |
|
a513b035e [PATCH] ext2: swi... |
225 |
inode_inc_link_count(dir); |
1da177e4c Linux-2.6.12-rc2 |
226 |
|
2a7dba391 fs/vfs/security: ... |
227 |
inode = ext2_new_inode(dir, S_IFDIR | mode, &dentry->d_name); |
1da177e4c Linux-2.6.12-rc2 |
228 229 230 231 232 233 234 235 236 237 |
err = PTR_ERR(inode); if (IS_ERR(inode)) goto out_dir; inode->i_op = &ext2_dir_inode_operations; inode->i_fop = &ext2_dir_operations; if (test_opt(inode->i_sb, NOBH)) inode->i_mapping->a_ops = &ext2_nobh_aops; else inode->i_mapping->a_ops = &ext2_aops; |
a513b035e [PATCH] ext2: swi... |
238 |
inode_inc_link_count(inode); |
1da177e4c Linux-2.6.12-rc2 |
239 240 241 242 243 244 245 246 247 248 |
err = ext2_make_empty(inode, dir); if (err) goto out_fail; err = ext2_add_link(dentry, inode); if (err) goto out_fail; d_instantiate(dentry, inode); |
41080b5a2 nfsd race fixes: ... |
249 |
unlock_new_inode(inode); |
1da177e4c Linux-2.6.12-rc2 |
250 251 252 253 |
out: return err; out_fail: |
a513b035e [PATCH] ext2: swi... |
254 255 |
inode_dec_link_count(inode); inode_dec_link_count(inode); |
41080b5a2 nfsd race fixes: ... |
256 |
unlock_new_inode(inode); |
1da177e4c Linux-2.6.12-rc2 |
257 258 |
iput(inode); out_dir: |
a513b035e [PATCH] ext2: swi... |
259 |
inode_dec_link_count(dir); |
1da177e4c Linux-2.6.12-rc2 |
260 261 262 263 264 265 266 267 268 |
goto out; } static int ext2_unlink(struct inode * dir, struct dentry *dentry) { struct inode * inode = dentry->d_inode; struct ext2_dir_entry_2 * de; struct page * page; int err = -ENOENT; |
871a29315 dquot: cleanup dq... |
269 |
dquot_initialize(dir); |
907f4554e dquot: move dquot... |
270 |
|
a9885444f [PATCH] get rid o... |
271 |
de = ext2_find_entry (dir, &dentry->d_name, &page); |
1da177e4c Linux-2.6.12-rc2 |
272 273 274 275 276 277 278 279 |
if (!de) goto out; err = ext2_delete_entry (de, page); if (err) goto out; inode->i_ctime = dir->i_ctime; |
a513b035e [PATCH] ext2: swi... |
280 |
inode_dec_link_count(inode); |
1da177e4c Linux-2.6.12-rc2 |
281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
err = 0; out: return err; } static int ext2_rmdir (struct inode * dir, struct dentry *dentry) { struct inode * inode = dentry->d_inode; int err = -ENOTEMPTY; if (ext2_empty_dir(inode)) { err = ext2_unlink(dir, dentry); if (!err) { inode->i_size = 0; |
a513b035e [PATCH] ext2: swi... |
295 296 |
inode_dec_link_count(inode); inode_dec_link_count(dir); |
1da177e4c Linux-2.6.12-rc2 |
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
} } return err; } static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry, struct inode * new_dir, struct dentry * new_dentry ) { struct inode * old_inode = old_dentry->d_inode; struct inode * new_inode = new_dentry->d_inode; struct page * dir_page = NULL; struct ext2_dir_entry_2 * dir_de = NULL; struct page * old_page; struct ext2_dir_entry_2 * old_de; int err = -ENOENT; |
871a29315 dquot: cleanup dq... |
312 313 |
dquot_initialize(old_dir); dquot_initialize(new_dir); |
907f4554e dquot: move dquot... |
314 |
|
a9885444f [PATCH] get rid o... |
315 |
old_de = ext2_find_entry (old_dir, &old_dentry->d_name, &old_page); |
1da177e4c Linux-2.6.12-rc2 |
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 |
if (!old_de) goto out; if (S_ISDIR(old_inode->i_mode)) { err = -EIO; dir_de = ext2_dotdot(old_inode, &dir_page); if (!dir_de) goto out_old; } if (new_inode) { struct page *new_page; struct ext2_dir_entry_2 *new_de; err = -ENOTEMPTY; if (dir_de && !ext2_empty_dir (new_inode)) goto out_dir; err = -ENOENT; |
a9885444f [PATCH] get rid o... |
335 |
new_de = ext2_find_entry (new_dir, &new_dentry->d_name, &new_page); |
1da177e4c Linux-2.6.12-rc2 |
336 337 |
if (!new_de) goto out_dir; |
39fe7557b ext2: Do not upda... |
338 |
ext2_set_link(new_dir, new_de, new_page, old_inode, 1); |
1da177e4c Linux-2.6.12-rc2 |
339 340 |
new_inode->i_ctime = CURRENT_TIME_SEC; if (dir_de) |
9a53c3a78 [PATCH] r/o bind ... |
341 |
drop_nlink(new_inode); |
a513b035e [PATCH] ext2: swi... |
342 |
inode_dec_link_count(new_inode); |
1da177e4c Linux-2.6.12-rc2 |
343 344 345 346 347 348 |
} else { if (dir_de) { err = -EMLINK; if (new_dir->i_nlink >= EXT2_LINK_MAX) goto out_dir; } |
1da177e4c Linux-2.6.12-rc2 |
349 |
err = ext2_add_link(new_dentry, old_inode); |
e8a80c6f7 ext2: Fix link co... |
350 |
if (err) |
1da177e4c Linux-2.6.12-rc2 |
351 |
goto out_dir; |
1da177e4c Linux-2.6.12-rc2 |
352 |
if (dir_de) |
a513b035e [PATCH] ext2: swi... |
353 |
inode_inc_link_count(new_dir); |
1da177e4c Linux-2.6.12-rc2 |
354 355 356 357 358 |
} /* * Like most other Unix systems, set the ctime for inodes on a * rename. |
1da177e4c Linux-2.6.12-rc2 |
359 360 |
*/ old_inode->i_ctime = CURRENT_TIME_SEC; |
e8a80c6f7 ext2: Fix link co... |
361 |
mark_inode_dirty(old_inode); |
1da177e4c Linux-2.6.12-rc2 |
362 363 |
ext2_delete_entry (old_de, old_page); |
1da177e4c Linux-2.6.12-rc2 |
364 365 |
if (dir_de) { |
39fe7557b ext2: Do not upda... |
366 367 |
if (old_dir != new_dir) ext2_set_link(old_inode, dir_de, dir_page, new_dir, 0); |
9de6886ec ext2: fix unbalan... |
368 369 370 371 |
else { kunmap(dir_page); page_cache_release(dir_page); } |
a513b035e [PATCH] ext2: swi... |
372 |
inode_dec_link_count(old_dir); |
1da177e4c Linux-2.6.12-rc2 |
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 |
} return 0; out_dir: if (dir_de) { kunmap(dir_page); page_cache_release(dir_page); } out_old: kunmap(old_page); page_cache_release(old_page); out: return err; } |
754661f14 [PATCH] mark stru... |
388 |
const struct inode_operations ext2_dir_inode_operations = { |
1da177e4c Linux-2.6.12-rc2 |
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 |
.create = ext2_create, .lookup = ext2_lookup, .link = ext2_link, .unlink = ext2_unlink, .symlink = ext2_symlink, .mkdir = ext2_mkdir, .rmdir = ext2_rmdir, .mknod = ext2_mknod, .rename = ext2_rename, #ifdef CONFIG_EXT2_FS_XATTR .setxattr = generic_setxattr, .getxattr = generic_getxattr, .listxattr = ext2_listxattr, .removexattr = generic_removexattr, #endif .setattr = ext2_setattr, |
1d5ccd1c4 ext[234]: move ov... |
405 |
.check_acl = ext2_check_acl, |
1da177e4c Linux-2.6.12-rc2 |
406 |
}; |
754661f14 [PATCH] mark stru... |
407 |
const struct inode_operations ext2_special_inode_operations = { |
1da177e4c Linux-2.6.12-rc2 |
408 409 410 411 412 413 414 |
#ifdef CONFIG_EXT2_FS_XATTR .setxattr = generic_setxattr, .getxattr = generic_getxattr, .listxattr = ext2_listxattr, .removexattr = generic_removexattr, #endif .setattr = ext2_setattr, |
1d5ccd1c4 ext[234]: move ov... |
415 |
.check_acl = ext2_check_acl, |
1da177e4c Linux-2.6.12-rc2 |
416 |
}; |