Blame view
fs/ext2/namei.c
9.5 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); |
a9049376e make d_splice_ali... |
69 70 71 72 73 |
if (inode == ERR_PTR(-ESTALE)) { ext2_error(dir->i_sb, __func__, "deleted inode referenced: %lu", (unsigned long) ino); return ERR_PTR(-EIO); |
4d6c13f87 ext2: return -EIO... |
74 |
} |
1da177e4c Linux-2.6.12-rc2 |
75 |
} |
082a05c6f [PATCH] ext2: rem... |
76 |
return d_splice_alias(inode, dentry); |
1da177e4c Linux-2.6.12-rc2 |
77 78 79 80 |
} struct dentry *ext2_get_parent(struct dentry *child) { |
a9885444f [PATCH] get rid o... |
81 82 |
struct qstr dotdot = {.name = "..", .len = 2}; unsigned long ino = ext2_inode_by_name(child->d_inode, &dotdot); |
1da177e4c Linux-2.6.12-rc2 |
83 84 |
if (!ino) return ERR_PTR(-ENOENT); |
440037287 [PATCH] switch al... |
85 |
return d_obtain_alias(ext2_iget(child->d_inode->i_sb, ino)); |
1da177e4c Linux-2.6.12-rc2 |
86 87 88 89 90 91 92 93 94 95 |
} /* * 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(). */ |
4acdaf27e switch ->create()... |
96 |
static int ext2_create (struct inode * dir, struct dentry * dentry, umode_t mode, struct nameidata *nd) |
1da177e4c Linux-2.6.12-rc2 |
97 |
{ |
907f4554e dquot: move dquot... |
98 |
struct inode *inode; |
871a29315 dquot: cleanup dq... |
99 |
dquot_initialize(dir); |
907f4554e dquot: move dquot... |
100 |
|
2a7dba391 fs/vfs/security: ... |
101 |
inode = ext2_new_inode(dir, mode, &dentry->d_name); |
907f4554e dquot: move dquot... |
102 103 104 105 106 107 108 109 110 111 112 113 114 |
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 |
115 |
} |
907f4554e dquot: move dquot... |
116 117 |
mark_inode_dirty(inode); return ext2_add_nondir(dentry, inode); |
1da177e4c Linux-2.6.12-rc2 |
118 |
} |
1a67aafb5 switch ->mknod() ... |
119 |
static int ext2_mknod (struct inode * dir, struct dentry *dentry, umode_t mode, dev_t rdev) |
1da177e4c Linux-2.6.12-rc2 |
120 121 122 123 124 125 |
{ struct inode * inode; int err; if (!new_valid_dev(rdev)) return -EINVAL; |
871a29315 dquot: cleanup dq... |
126 |
dquot_initialize(dir); |
907f4554e dquot: move dquot... |
127 |
|
2a7dba391 fs/vfs/security: ... |
128 |
inode = ext2_new_inode (dir, mode, &dentry->d_name); |
1da177e4c Linux-2.6.12-rc2 |
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
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... |
151 |
dquot_initialize(dir); |
907f4554e dquot: move dquot... |
152 |
|
2a7dba391 fs/vfs/security: ... |
153 |
inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO, &dentry->d_name); |
1da177e4c Linux-2.6.12-rc2 |
154 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 |
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... |
181 |
inode_dec_link_count(inode); |
41080b5a2 nfsd race fixes: ... |
182 |
unlock_new_inode(inode); |
1da177e4c Linux-2.6.12-rc2 |
183 184 185 186 187 188 189 190 |
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: ... |
191 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
192 193 194 |
if (inode->i_nlink >= EXT2_LINK_MAX) return -EMLINK; |
871a29315 dquot: cleanup dq... |
195 |
dquot_initialize(dir); |
907f4554e dquot: move dquot... |
196 |
|
1da177e4c Linux-2.6.12-rc2 |
197 |
inode->i_ctime = CURRENT_TIME_SEC; |
a513b035e [PATCH] ext2: swi... |
198 |
inode_inc_link_count(inode); |
7de9c6ee3 new helper: ihold() |
199 |
ihold(inode); |
1da177e4c Linux-2.6.12-rc2 |
200 |
|
41080b5a2 nfsd race fixes: ... |
201 202 203 204 205 206 207 208 |
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 |
209 |
} |
18bb1db3e switch vfs_mkdir(... |
210 |
static int ext2_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode) |
1da177e4c Linux-2.6.12-rc2 |
211 212 213 214 215 216 |
{ struct inode * inode; int err = -EMLINK; if (dir->i_nlink >= EXT2_LINK_MAX) goto out; |
871a29315 dquot: cleanup dq... |
217 |
dquot_initialize(dir); |
907f4554e dquot: move dquot... |
218 |
|
a513b035e [PATCH] ext2: swi... |
219 |
inode_inc_link_count(dir); |
1da177e4c Linux-2.6.12-rc2 |
220 |
|
2a7dba391 fs/vfs/security: ... |
221 |
inode = ext2_new_inode(dir, S_IFDIR | mode, &dentry->d_name); |
1da177e4c Linux-2.6.12-rc2 |
222 223 224 225 226 227 228 229 230 231 |
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... |
232 |
inode_inc_link_count(inode); |
1da177e4c Linux-2.6.12-rc2 |
233 234 235 236 237 238 239 240 241 242 |
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: ... |
243 |
unlock_new_inode(inode); |
1da177e4c Linux-2.6.12-rc2 |
244 245 246 247 |
out: return err; out_fail: |
a513b035e [PATCH] ext2: swi... |
248 249 |
inode_dec_link_count(inode); inode_dec_link_count(inode); |
41080b5a2 nfsd race fixes: ... |
250 |
unlock_new_inode(inode); |
1da177e4c Linux-2.6.12-rc2 |
251 252 |
iput(inode); out_dir: |
a513b035e [PATCH] ext2: swi... |
253 |
inode_dec_link_count(dir); |
1da177e4c Linux-2.6.12-rc2 |
254 255 256 257 258 259 260 261 262 |
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... |
263 |
dquot_initialize(dir); |
907f4554e dquot: move dquot... |
264 |
|
a9885444f [PATCH] get rid o... |
265 |
de = ext2_find_entry (dir, &dentry->d_name, &page); |
1da177e4c Linux-2.6.12-rc2 |
266 267 268 269 270 271 272 273 |
if (!de) goto out; err = ext2_delete_entry (de, page); if (err) goto out; inode->i_ctime = dir->i_ctime; |
a513b035e [PATCH] ext2: swi... |
274 |
inode_dec_link_count(inode); |
1da177e4c Linux-2.6.12-rc2 |
275 276 277 278 279 280 281 282 283 284 285 286 287 288 |
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... |
289 290 |
inode_dec_link_count(inode); inode_dec_link_count(dir); |
1da177e4c Linux-2.6.12-rc2 |
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 |
} } 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... |
306 307 |
dquot_initialize(old_dir); dquot_initialize(new_dir); |
907f4554e dquot: move dquot... |
308 |
|
a9885444f [PATCH] get rid o... |
309 |
old_de = ext2_find_entry (old_dir, &old_dentry->d_name, &old_page); |
1da177e4c Linux-2.6.12-rc2 |
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
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... |
329 |
new_de = ext2_find_entry (new_dir, &new_dentry->d_name, &new_page); |
1da177e4c Linux-2.6.12-rc2 |
330 331 |
if (!new_de) goto out_dir; |
39fe7557b ext2: Do not upda... |
332 |
ext2_set_link(new_dir, new_de, new_page, old_inode, 1); |
1da177e4c Linux-2.6.12-rc2 |
333 334 |
new_inode->i_ctime = CURRENT_TIME_SEC; if (dir_de) |
9a53c3a78 [PATCH] r/o bind ... |
335 |
drop_nlink(new_inode); |
a513b035e [PATCH] ext2: swi... |
336 |
inode_dec_link_count(new_inode); |
1da177e4c Linux-2.6.12-rc2 |
337 338 339 340 341 342 |
} else { if (dir_de) { err = -EMLINK; if (new_dir->i_nlink >= EXT2_LINK_MAX) goto out_dir; } |
1da177e4c Linux-2.6.12-rc2 |
343 |
err = ext2_add_link(new_dentry, old_inode); |
e8a80c6f7 ext2: Fix link co... |
344 |
if (err) |
1da177e4c Linux-2.6.12-rc2 |
345 |
goto out_dir; |
1da177e4c Linux-2.6.12-rc2 |
346 |
if (dir_de) |
a513b035e [PATCH] ext2: swi... |
347 |
inode_inc_link_count(new_dir); |
1da177e4c Linux-2.6.12-rc2 |
348 349 350 351 352 |
} /* * Like most other Unix systems, set the ctime for inodes on a * rename. |
1da177e4c Linux-2.6.12-rc2 |
353 354 |
*/ old_inode->i_ctime = CURRENT_TIME_SEC; |
e8a80c6f7 ext2: Fix link co... |
355 |
mark_inode_dirty(old_inode); |
1da177e4c Linux-2.6.12-rc2 |
356 357 |
ext2_delete_entry (old_de, old_page); |
1da177e4c Linux-2.6.12-rc2 |
358 359 |
if (dir_de) { |
39fe7557b ext2: Do not upda... |
360 361 |
if (old_dir != new_dir) ext2_set_link(old_inode, dir_de, dir_page, new_dir, 0); |
9de6886ec ext2: fix unbalan... |
362 363 364 365 |
else { kunmap(dir_page); page_cache_release(dir_page); } |
a513b035e [PATCH] ext2: swi... |
366 |
inode_dec_link_count(old_dir); |
1da177e4c Linux-2.6.12-rc2 |
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 |
} 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... |
382 |
const struct inode_operations ext2_dir_inode_operations = { |
1da177e4c Linux-2.6.12-rc2 |
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 |
.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, |
4e34e719e fs: take the ACL ... |
399 |
.get_acl = ext2_get_acl, |
1da177e4c Linux-2.6.12-rc2 |
400 |
}; |
754661f14 [PATCH] mark stru... |
401 |
const struct inode_operations ext2_special_inode_operations = { |
1da177e4c Linux-2.6.12-rc2 |
402 403 404 405 406 407 408 |
#ifdef CONFIG_EXT2_FS_XATTR .setxattr = generic_setxattr, .getxattr = generic_getxattr, .listxattr = ext2_listxattr, .removexattr = generic_removexattr, #endif .setattr = ext2_setattr, |
4e34e719e fs: take the ACL ... |
409 |
.get_acl = ext2_get_acl, |
1da177e4c Linux-2.6.12-rc2 |
410 |
}; |