aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ufs/namei.c
diff options
context:
space:
mode:
authorEvgeniy Dushistov <dushistov@mail.ru>2006-06-25 08:47:22 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-25 13:01:02 -0400
commitb71034e5e67d1577424cebe7bbb7d0ce134a4cd8 (patch)
tree4e4ffe95db731bbdc81d086d2b4462b3ab5867c2 /fs/ufs/namei.c
parent826843a347cc8fd596a4c73d3fbdf04a1f130b8a (diff)
[PATCH] ufs: directory and page cache: from blocks to pages
Change function in fs/ufs/dir.c and fs/ufs/namei.c to work with pages instead of straight work with blocks. It fixed such bugs: * for i in `seq 1 1000`; do touch $i; done - crash system * mkdir create directory without "." and ".." entries Signed-off-by: Evgeniy Dushistov <dushistov@mail.ru> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/ufs/namei.c')
-rw-r--r--fs/ufs/namei.c62
1 files changed, 35 insertions, 27 deletions
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c
index 51f702700308..364bb92b0917 100644
--- a/fs/ufs/namei.c
+++ b/fs/ufs/namei.c
@@ -1,6 +1,9 @@
1/* 1/*
2 * linux/fs/ufs/namei.c 2 * linux/fs/ufs/namei.c
3 * 3 *
4 * Migration to usage of "page cache" on May 2006 by
5 * Evgeniy Dushistov <dushistov@mail.ru> based on ext2 code base.
6 *
4 * Copyright (C) 1998 7 * Copyright (C) 1998
5 * Daniel Pirkl <daniel.pirkl@email.cz> 8 * Daniel Pirkl <daniel.pirkl@email.cz>
6 * Charles University, Faculty of Mathematics and Physics 9 * Charles University, Faculty of Mathematics and Physics
@@ -28,7 +31,6 @@
28#include <linux/fs.h> 31#include <linux/fs.h>
29#include <linux/ufs_fs.h> 32#include <linux/ufs_fs.h>
30#include <linux/smp_lock.h> 33#include <linux/smp_lock.h>
31#include <linux/buffer_head.h>
32#include "swab.h" /* will go away - see comment in mknod() */ 34#include "swab.h" /* will go away - see comment in mknod() */
33#include "util.h" 35#include "util.h"
34 36
@@ -232,19 +234,18 @@ out_dir:
232 goto out; 234 goto out;
233} 235}
234 236
235static int ufs_unlink(struct inode * dir, struct dentry *dentry) 237static int ufs_unlink(struct inode *dir, struct dentry *dentry)
236{ 238{
237 struct inode * inode = dentry->d_inode; 239 struct inode * inode = dentry->d_inode;
238 struct buffer_head * bh; 240 struct ufs_dir_entry *de;
239 struct ufs_dir_entry * de; 241 struct page *page;
240 int err = -ENOENT; 242 int err = -ENOENT;
241 243
242 lock_kernel(); 244 de = ufs_find_entry(dir, dentry, &page);
243 de = ufs_find_entry (dentry, &bh);
244 if (!de) 245 if (!de)
245 goto out; 246 goto out;
246 247
247 err = ufs_delete_entry (dir, de, bh); 248 err = ufs_delete_entry(dir, de, page);
248 if (err) 249 if (err)
249 goto out; 250 goto out;
250 251
@@ -252,7 +253,6 @@ static int ufs_unlink(struct inode * dir, struct dentry *dentry)
252 inode_dec_link_count(inode); 253 inode_dec_link_count(inode);
253 err = 0; 254 err = 0;
254out: 255out:
255 unlock_kernel();
256 return err; 256 return err;
257} 257}
258 258
@@ -274,42 +274,42 @@ static int ufs_rmdir (struct inode * dir, struct dentry *dentry)
274 return err; 274 return err;
275} 275}
276 276
277static int ufs_rename (struct inode * old_dir, struct dentry * old_dentry, 277static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry,
278 struct inode * new_dir, struct dentry * new_dentry ) 278 struct inode *new_dir, struct dentry *new_dentry)
279{ 279{
280 struct inode *old_inode = old_dentry->d_inode; 280 struct inode *old_inode = old_dentry->d_inode;
281 struct inode *new_inode = new_dentry->d_inode; 281 struct inode *new_inode = new_dentry->d_inode;
282 struct buffer_head *dir_bh = NULL; 282 struct page *dir_page = NULL;
283 struct ufs_dir_entry *dir_de = NULL; 283 struct ufs_dir_entry * dir_de = NULL;
284 struct buffer_head *old_bh; 284 struct page *old_page;
285 struct ufs_dir_entry *old_de; 285 struct ufs_dir_entry *old_de;
286 int err = -ENOENT; 286 int err = -ENOENT;
287 287
288 lock_kernel(); 288 old_de = ufs_find_entry(old_dir, old_dentry, &old_page);
289 old_de = ufs_find_entry (old_dentry, &old_bh);
290 if (!old_de) 289 if (!old_de)
291 goto out; 290 goto out;
292 291
293 if (S_ISDIR(old_inode->i_mode)) { 292 if (S_ISDIR(old_inode->i_mode)) {
294 err = -EIO; 293 err = -EIO;
295 dir_de = ufs_dotdot(old_inode, &dir_bh); 294 dir_de = ufs_dotdot(old_inode, &dir_page);
296 if (!dir_de) 295 if (!dir_de)
297 goto out_old; 296 goto out_old;
298 } 297 }
299 298
300 if (new_inode) { 299 if (new_inode) {
301 struct buffer_head *new_bh; 300 struct page *new_page;
302 struct ufs_dir_entry *new_de; 301 struct ufs_dir_entry *new_de;
303 302
304 err = -ENOTEMPTY; 303 err = -ENOTEMPTY;
305 if (dir_de && !ufs_empty_dir (new_inode)) 304 if (dir_de && !ufs_empty_dir(new_inode))
306 goto out_dir; 305 goto out_dir;
306
307 err = -ENOENT; 307 err = -ENOENT;
308 new_de = ufs_find_entry (new_dentry, &new_bh); 308 new_de = ufs_find_entry(new_dir, new_dentry, &new_page);
309 if (!new_de) 309 if (!new_de)
310 goto out_dir; 310 goto out_dir;
311 inode_inc_link_count(old_inode); 311 inode_inc_link_count(old_inode);
312 ufs_set_link(new_dir, new_de, new_bh, old_inode); 312 ufs_set_link(new_dir, new_de, new_page, old_inode);
313 new_inode->i_ctime = CURRENT_TIME_SEC; 313 new_inode->i_ctime = CURRENT_TIME_SEC;
314 if (dir_de) 314 if (dir_de)
315 new_inode->i_nlink--; 315 new_inode->i_nlink--;
@@ -330,24 +330,32 @@ static int ufs_rename (struct inode * old_dir, struct dentry * old_dentry,
330 inode_inc_link_count(new_dir); 330 inode_inc_link_count(new_dir);
331 } 331 }
332 332
333 ufs_delete_entry (old_dir, old_de, old_bh); 333 /*
334 * Like most other Unix systems, set the ctime for inodes on a
335 * rename.
336 * inode_dec_link_count() will mark the inode dirty.
337 */
338 old_inode->i_ctime = CURRENT_TIME_SEC;
334 339
340 ufs_delete_entry(old_dir, old_de, old_page);
335 inode_dec_link_count(old_inode); 341 inode_dec_link_count(old_inode);
336 342
337 if (dir_de) { 343 if (dir_de) {
338 ufs_set_link(old_inode, dir_de, dir_bh, new_dir); 344 ufs_set_link(old_inode, dir_de, dir_page, new_dir);
339 inode_dec_link_count(old_dir); 345 inode_dec_link_count(old_dir);
340 } 346 }
341 unlock_kernel();
342 return 0; 347 return 0;
343 348
349
344out_dir: 350out_dir:
345 if (dir_de) 351 if (dir_de) {
346 brelse(dir_bh); 352 kunmap(dir_page);
353 page_cache_release(dir_page);
354 }
347out_old: 355out_old:
348 brelse (old_bh); 356 kunmap(old_page);
357 page_cache_release(old_page);
349out: 358out:
350 unlock_kernel();
351 return err; 359 return err;
352} 360}
353 361