Blame view
fs/ufs/namei.c
7.67 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 |
/* * linux/fs/ufs/namei.c * |
b71034e5e [PATCH] ufs: dire... |
4 5 6 |
* Migration to usage of "page cache" on May 2006 by * Evgeniy Dushistov <dushistov@mail.ru> based on ext2 code base. * |
1da177e4c Linux-2.6.12-rc2 |
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 |
* Copyright (C) 1998 * Daniel Pirkl <daniel.pirkl@email.cz> * Charles University, Faculty of Mathematics and Physics * * from * * linux/fs/ext2/namei.c * * 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/time.h> #include <linux/fs.h> |
1da177e4c Linux-2.6.12-rc2 |
32 |
#include <linux/smp_lock.h> |
e54205988 drop linux/ufs_fs... |
33 34 |
#include "ufs_fs.h" |
bcd6d4ecf ufs: move non-lay... |
35 |
#include "ufs.h" |
1da177e4c Linux-2.6.12-rc2 |
36 |
#include "util.h" |
1da177e4c Linux-2.6.12-rc2 |
37 38 39 40 41 42 43 |
static inline int ufs_add_nondir(struct dentry *dentry, struct inode *inode) { int err = ufs_add_link(dentry, inode); if (!err) { d_instantiate(dentry, inode); return 0; } |
3257545e4 [PATCH] ufs: swit... |
44 |
inode_dec_link_count(inode); |
1da177e4c Linux-2.6.12-rc2 |
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
iput(inode); return err; } static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd) { struct inode * inode = NULL; ino_t ino; if (dentry->d_name.len > UFS_MAXNAMLEN) return ERR_PTR(-ENAMETOOLONG); lock_kernel(); ino = ufs_inode_by_name(dir, dentry); if (ino) { |
b55c460da iget: stop UFS fr... |
60 61 |
inode = ufs_iget(dir->i_sb, ino); if (IS_ERR(inode)) { |
1da177e4c Linux-2.6.12-rc2 |
62 |
unlock_kernel(); |
b55c460da iget: stop UFS fr... |
63 |
return ERR_CAST(inode); |
1da177e4c Linux-2.6.12-rc2 |
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
} } unlock_kernel(); d_add(dentry, inode); return NULL; } /* * 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 ufs_create (struct inode * dir, struct dentry * dentry, int mode, struct nameidata *nd) { |
abf5d15fd [PATCH] ufs: easy... |
82 83 84 85 86 87 88 |
struct inode *inode; int err; UFSD("BEGIN "); inode = ufs_new_inode(dir, mode); err = PTR_ERR(inode); |
1da177e4c Linux-2.6.12-rc2 |
89 90 91 92 93 94 95 96 97 |
if (!IS_ERR(inode)) { inode->i_op = &ufs_file_inode_operations; inode->i_fop = &ufs_file_operations; inode->i_mapping->a_ops = &ufs_aops; mark_inode_dirty(inode); lock_kernel(); err = ufs_add_nondir(dentry, inode); unlock_kernel(); } |
abf5d15fd [PATCH] ufs: easy... |
98 99 |
UFSD("END: err=%d ", err); |
1da177e4c Linux-2.6.12-rc2 |
100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
return err; } static int ufs_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t rdev) { struct inode *inode; int err; if (!old_valid_dev(rdev)) return -EINVAL; inode = ufs_new_inode(dir, mode); err = PTR_ERR(inode); if (!IS_ERR(inode)) { init_special_inode(inode, mode, rdev); |
1da177e4c Linux-2.6.12-rc2 |
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
ufs_set_inode_dev(inode->i_sb, UFS_I(inode), rdev); mark_inode_dirty(inode); lock_kernel(); err = ufs_add_nondir(dentry, inode); unlock_kernel(); } return err; } static int ufs_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) |
344fe7866 [PATCH] ufs: remo... |
132 |
goto out_notlocked; |
1da177e4c Linux-2.6.12-rc2 |
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
lock_kernel(); inode = ufs_new_inode(dir, S_IFLNK | S_IRWXUGO); err = PTR_ERR(inode); if (IS_ERR(inode)) goto out; if (l > UFS_SB(sb)->s_uspi->s_maxsymlinklen) { /* slow symlink */ inode->i_op = &page_symlink_inode_operations; inode->i_mapping->a_ops = &ufs_aops; err = page_symlink(inode, symname, l); if (err) goto out_fail; } else { /* fast symlink */ inode->i_op = &ufs_fast_symlink_inode_operations; |
723be1f30 ufs: copy symlink... |
150 |
memcpy(UFS_I(inode)->i_u1.i_symlink, symname, l); |
1da177e4c Linux-2.6.12-rc2 |
151 152 153 154 155 156 157 |
inode->i_size = l-1; } mark_inode_dirty(inode); err = ufs_add_nondir(dentry, inode); out: unlock_kernel(); |
344fe7866 [PATCH] ufs: remo... |
158 |
out_notlocked: |
1da177e4c Linux-2.6.12-rc2 |
159 160 161 |
return err; out_fail: |
3257545e4 [PATCH] ufs: swit... |
162 |
inode_dec_link_count(inode); |
1da177e4c Linux-2.6.12-rc2 |
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
iput(inode); goto out; } static int ufs_link (struct dentry * old_dentry, struct inode * dir, struct dentry *dentry) { struct inode *inode = old_dentry->d_inode; int error; lock_kernel(); if (inode->i_nlink >= UFS_LINK_MAX) { unlock_kernel(); return -EMLINK; } inode->i_ctime = CURRENT_TIME_SEC; |
3257545e4 [PATCH] ufs: swit... |
180 |
inode_inc_link_count(inode); |
1da177e4c Linux-2.6.12-rc2 |
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
atomic_inc(&inode->i_count); error = ufs_add_nondir(dentry, inode); unlock_kernel(); return error; } static int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode) { struct inode * inode; int err = -EMLINK; if (dir->i_nlink >= UFS_LINK_MAX) goto out; lock_kernel(); |
3257545e4 [PATCH] ufs: swit... |
197 |
inode_inc_link_count(dir); |
1da177e4c Linux-2.6.12-rc2 |
198 199 200 201 202 203 204 205 |
inode = ufs_new_inode(dir, S_IFDIR|mode); err = PTR_ERR(inode); if (IS_ERR(inode)) goto out_dir; inode->i_op = &ufs_dir_inode_operations; inode->i_fop = &ufs_dir_operations; |
826843a34 [PATCH] ufs: dire... |
206 |
inode->i_mapping->a_ops = &ufs_aops; |
1da177e4c Linux-2.6.12-rc2 |
207 |
|
3257545e4 [PATCH] ufs: swit... |
208 |
inode_inc_link_count(inode); |
1da177e4c Linux-2.6.12-rc2 |
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
err = ufs_make_empty(inode, dir); if (err) goto out_fail; err = ufs_add_link(dentry, inode); if (err) goto out_fail; unlock_kernel(); d_instantiate(dentry, inode); out: return err; out_fail: |
3257545e4 [PATCH] ufs: swit... |
224 225 |
inode_dec_link_count(inode); inode_dec_link_count(inode); |
1da177e4c Linux-2.6.12-rc2 |
226 227 |
iput (inode); out_dir: |
3257545e4 [PATCH] ufs: swit... |
228 |
inode_dec_link_count(dir); |
1da177e4c Linux-2.6.12-rc2 |
229 230 231 |
unlock_kernel(); goto out; } |
b71034e5e [PATCH] ufs: dire... |
232 |
static int ufs_unlink(struct inode *dir, struct dentry *dentry) |
1da177e4c Linux-2.6.12-rc2 |
233 234 |
{ struct inode * inode = dentry->d_inode; |
b71034e5e [PATCH] ufs: dire... |
235 236 |
struct ufs_dir_entry *de; struct page *page; |
1da177e4c Linux-2.6.12-rc2 |
237 |
int err = -ENOENT; |
b71034e5e [PATCH] ufs: dire... |
238 |
de = ufs_find_entry(dir, dentry, &page); |
1da177e4c Linux-2.6.12-rc2 |
239 240 |
if (!de) goto out; |
b71034e5e [PATCH] ufs: dire... |
241 |
err = ufs_delete_entry(dir, de, page); |
1da177e4c Linux-2.6.12-rc2 |
242 243 244 245 |
if (err) goto out; inode->i_ctime = dir->i_ctime; |
3257545e4 [PATCH] ufs: swit... |
246 |
inode_dec_link_count(inode); |
1da177e4c Linux-2.6.12-rc2 |
247 248 |
err = 0; out: |
1da177e4c Linux-2.6.12-rc2 |
249 250 251 252 253 254 255 256 257 258 259 260 261 |
return err; } static int ufs_rmdir (struct inode * dir, struct dentry *dentry) { struct inode * inode = dentry->d_inode; int err= -ENOTEMPTY; lock_kernel(); if (ufs_empty_dir (inode)) { err = ufs_unlink(dir, dentry); if (!err) { inode->i_size = 0; |
3257545e4 [PATCH] ufs: swit... |
262 263 |
inode_dec_link_count(inode); inode_dec_link_count(dir); |
1da177e4c Linux-2.6.12-rc2 |
264 265 266 267 268 |
} } unlock_kernel(); return err; } |
b71034e5e [PATCH] ufs: dire... |
269 270 |
static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) |
1da177e4c Linux-2.6.12-rc2 |
271 272 273 |
{ struct inode *old_inode = old_dentry->d_inode; struct inode *new_inode = new_dentry->d_inode; |
b71034e5e [PATCH] ufs: dire... |
274 275 276 |
struct page *dir_page = NULL; struct ufs_dir_entry * dir_de = NULL; struct page *old_page; |
1da177e4c Linux-2.6.12-rc2 |
277 278 |
struct ufs_dir_entry *old_de; int err = -ENOENT; |
b71034e5e [PATCH] ufs: dire... |
279 |
old_de = ufs_find_entry(old_dir, old_dentry, &old_page); |
1da177e4c Linux-2.6.12-rc2 |
280 281 282 283 284 |
if (!old_de) goto out; if (S_ISDIR(old_inode->i_mode)) { err = -EIO; |
b71034e5e [PATCH] ufs: dire... |
285 |
dir_de = ufs_dotdot(old_inode, &dir_page); |
1da177e4c Linux-2.6.12-rc2 |
286 287 288 289 290 |
if (!dir_de) goto out_old; } if (new_inode) { |
b71034e5e [PATCH] ufs: dire... |
291 |
struct page *new_page; |
1da177e4c Linux-2.6.12-rc2 |
292 293 294 |
struct ufs_dir_entry *new_de; err = -ENOTEMPTY; |
b71034e5e [PATCH] ufs: dire... |
295 |
if (dir_de && !ufs_empty_dir(new_inode)) |
1da177e4c Linux-2.6.12-rc2 |
296 |
goto out_dir; |
b71034e5e [PATCH] ufs: dire... |
297 |
|
1da177e4c Linux-2.6.12-rc2 |
298 |
err = -ENOENT; |
b71034e5e [PATCH] ufs: dire... |
299 |
new_de = ufs_find_entry(new_dir, new_dentry, &new_page); |
1da177e4c Linux-2.6.12-rc2 |
300 301 |
if (!new_de) goto out_dir; |
3257545e4 [PATCH] ufs: swit... |
302 |
inode_inc_link_count(old_inode); |
b71034e5e [PATCH] ufs: dire... |
303 |
ufs_set_link(new_dir, new_de, new_page, old_inode); |
1da177e4c Linux-2.6.12-rc2 |
304 305 |
new_inode->i_ctime = CURRENT_TIME_SEC; if (dir_de) |
9a53c3a78 [PATCH] r/o bind ... |
306 |
drop_nlink(new_inode); |
3257545e4 [PATCH] ufs: swit... |
307 |
inode_dec_link_count(new_inode); |
1da177e4c Linux-2.6.12-rc2 |
308 309 310 311 312 313 |
} else { if (dir_de) { err = -EMLINK; if (new_dir->i_nlink >= UFS_LINK_MAX) goto out_dir; } |
3257545e4 [PATCH] ufs: swit... |
314 |
inode_inc_link_count(old_inode); |
1da177e4c Linux-2.6.12-rc2 |
315 316 |
err = ufs_add_link(new_dentry, old_inode); if (err) { |
3257545e4 [PATCH] ufs: swit... |
317 |
inode_dec_link_count(old_inode); |
1da177e4c Linux-2.6.12-rc2 |
318 319 320 |
goto out_dir; } if (dir_de) |
3257545e4 [PATCH] ufs: swit... |
321 |
inode_inc_link_count(new_dir); |
1da177e4c Linux-2.6.12-rc2 |
322 |
} |
b71034e5e [PATCH] ufs: dire... |
323 324 325 326 327 328 |
/* * Like most other Unix systems, set the ctime for inodes on a * rename. * inode_dec_link_count() will mark the inode dirty. */ old_inode->i_ctime = CURRENT_TIME_SEC; |
1da177e4c Linux-2.6.12-rc2 |
329 |
|
b71034e5e [PATCH] ufs: dire... |
330 |
ufs_delete_entry(old_dir, old_de, old_page); |
3257545e4 [PATCH] ufs: swit... |
331 |
inode_dec_link_count(old_inode); |
1da177e4c Linux-2.6.12-rc2 |
332 333 |
if (dir_de) { |
b71034e5e [PATCH] ufs: dire... |
334 |
ufs_set_link(old_inode, dir_de, dir_page, new_dir); |
3257545e4 [PATCH] ufs: swit... |
335 |
inode_dec_link_count(old_dir); |
1da177e4c Linux-2.6.12-rc2 |
336 |
} |
1da177e4c Linux-2.6.12-rc2 |
337 |
return 0; |
b71034e5e [PATCH] ufs: dire... |
338 |
|
1da177e4c Linux-2.6.12-rc2 |
339 |
out_dir: |
b71034e5e [PATCH] ufs: dire... |
340 341 342 343 |
if (dir_de) { kunmap(dir_page); page_cache_release(dir_page); } |
1da177e4c Linux-2.6.12-rc2 |
344 |
out_old: |
b71034e5e [PATCH] ufs: dire... |
345 346 |
kunmap(old_page); page_cache_release(old_page); |
1da177e4c Linux-2.6.12-rc2 |
347 |
out: |
1da177e4c Linux-2.6.12-rc2 |
348 349 |
return err; } |
c5ef1c42c [PATCH] mark stru... |
350 |
const struct inode_operations ufs_dir_inode_operations = { |
1da177e4c Linux-2.6.12-rc2 |
351 352 353 354 355 356 357 358 359 360 |
.create = ufs_create, .lookup = ufs_lookup, .link = ufs_link, .unlink = ufs_unlink, .symlink = ufs_symlink, .mkdir = ufs_mkdir, .rmdir = ufs_rmdir, .mknod = ufs_mknod, .rename = ufs_rename, }; |