This source file includes following definitions.
- ext_match
- ext_find_entry
- ext_lookup
- ext_add_entry
- ext_create
- ext_mknod
- ext_mkdir
- empty_dir
- ext_merge_entries
- ext_rmdir
- ext_unlink
- ext_symlink
- ext_link
- subdir
- do_ext_rename
- ext_rename
1
2
3
4
5
6
7
8
9
10
11
12
13 #include <linux/sched.h>
14 #include <linux/ext_fs.h>
15 #include <linux/kernel.h>
16 #include <linux/string.h>
17 #include <linux/stat.h>
18 #include <linux/fcntl.h>
19 #include <linux/errno.h>
20
21 #include <asm/segment.h>
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 #define EXT_DIR_PAD 8
38
39
40
41
42
43
44
45
46
47 #define EXT_DIR_MIN_SIZE 12
48
49
50
51
52
53
54
55
56 static int ext_match(int len,const char * name,struct ext_dir_entry * de)
57 {
58 register int same __asm__("ax");
59
60 if (!de || !de->inode || len > EXT_NAME_LEN)
61 return 0;
62
63 if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
64 return 1;
65 if (len < EXT_NAME_LEN && len != de->name_len)
66 return 0;
67 __asm__("cld\n\t"
68 "fs ; repe ; cmpsb\n\t"
69 "setz %%al"
70 :"=a" (same)
71 :"0" (0),"S" ((long) name),"D" ((long) de->name),"c" (len)
72 :"cx","di","si");
73 return same;
74 }
75
76
77
78
79
80
81
82
83
84
85
86
87 static struct buffer_head * ext_find_entry(struct inode * dir,
88 const char * name, int namelen, struct ext_dir_entry ** res_dir,
89 struct ext_dir_entry ** prev_dir, struct ext_dir_entry ** next_dir)
90 {
91 long offset;
92 struct buffer_head * bh;
93 struct ext_dir_entry * de;
94
95 *res_dir = NULL;
96 if (!dir)
97 return NULL;
98 #ifdef NO_TRUNCATE
99 if (namelen > EXT_NAME_LEN)
100 return NULL;
101 #else
102 if (namelen > EXT_NAME_LEN)
103 namelen = EXT_NAME_LEN;
104 #endif
105 bh = ext_bread(dir,0,0);
106 if (!bh)
107 return NULL;
108 if (prev_dir)
109 *prev_dir = NULL;
110 if (next_dir)
111 *next_dir = NULL;
112 offset = 0;
113 de = (struct ext_dir_entry *) bh->b_data;
114 while (offset < dir->i_size) {
115 if ((char *)de >= BLOCK_SIZE+bh->b_data) {
116 brelse(bh);
117 bh = NULL;
118 bh = ext_bread(dir,offset>>BLOCK_SIZE_BITS,0);
119 if (!bh)
120 continue;
121 de = (struct ext_dir_entry *) bh->b_data;
122 if (prev_dir)
123 *prev_dir = NULL;
124 }
125 if (ext_match(namelen,name,de)) {
126 *res_dir = de;
127 if (next_dir)
128 if (offset + de->rec_len < dir->i_size)
129 *next_dir = (struct ext_dir_entry *)
130 ((char *) de + de->rec_len);
131 else
132 *next_dir = NULL;
133 return bh;
134 }
135 offset += de->rec_len;
136 if (prev_dir)
137 *prev_dir = de;
138 de = (struct ext_dir_entry *) ((char *) de + de->rec_len);
139 }
140 brelse(bh);
141 return NULL;
142 }
143
144 int ext_lookup(struct inode * dir,const char * name, int len,
145 struct inode ** result)
146 {
147 int ino;
148 struct ext_dir_entry * de;
149 struct buffer_head * bh;
150
151 *result = NULL;
152 if (!dir)
153 return -ENOENT;
154 if (!S_ISDIR(dir->i_mode)) {
155 iput(dir);
156 return -ENOENT;
157 }
158 if (!(bh = ext_find_entry(dir,name,len,&de,NULL,NULL))) {
159 iput(dir);
160 return -ENOENT;
161 }
162 ino = de->inode;
163 brelse(bh);
164 if (!(*result = iget(dir->i_dev,ino))) {
165 iput(dir);
166 return -EACCES;
167 }
168 iput(dir);
169 return 0;
170 }
171
172
173
174
175
176
177
178
179
180
181
182 static struct buffer_head * ext_add_entry(struct inode * dir,
183 const char * name, int namelen, struct ext_dir_entry ** res_dir)
184 {
185 int i;
186 long offset;
187 unsigned short rec_len;
188 struct buffer_head * bh;
189 struct ext_dir_entry * de, * de1;
190
191 *res_dir = NULL;
192 if (!dir)
193 return NULL;
194 #ifdef NO_TRUNCATE
195 if (namelen > EXT_NAME_LEN)
196 return NULL;
197 #else
198 if (namelen > EXT_NAME_LEN)
199 namelen = EXT_NAME_LEN;
200 #endif
201 if (!namelen)
202 return NULL;
203 bh = ext_bread(dir,0,0);
204 if (!bh)
205 return NULL;
206 rec_len = ((8 + namelen + EXT_DIR_PAD - 1) / EXT_DIR_PAD) * EXT_DIR_PAD;
207 offset = 0;
208 de = (struct ext_dir_entry *) bh->b_data;
209 while (1) {
210 if ((char *)de >= BLOCK_SIZE+bh->b_data && offset < dir->i_size) {
211 #ifdef EXTFS_DEBUG
212 printk ("ext_add_entry: skipping to next block\n");
213 #endif
214 brelse(bh);
215 bh = NULL;
216 bh = ext_bread(dir,offset>>BLOCK_SIZE_BITS,1);
217 if (!bh)
218 return NULL;
219 de = (struct ext_dir_entry *) bh->b_data;
220 }
221 if (offset >= dir->i_size) {
222
223 if (offset % BLOCK_SIZE == 0
224 || (BLOCK_SIZE - (offset % BLOCK_SIZE)) < rec_len) {
225 if ((offset % BLOCK_SIZE) != 0) {
226
227
228
229 de->inode = 0;
230 de->rec_len = BLOCK_SIZE
231 - (offset & (BLOCK_SIZE - 1));
232 de->name_len = 0;
233 offset += de->rec_len;
234 dir->i_size += de->rec_len;
235 dir->i_dirt = 1;
236 dir->i_ctime = CURRENT_TIME;
237 bh->b_dirt = 1;
238 }
239 brelse (bh);
240 bh = NULL;
241 #ifdef EXTFS_DEBUG
242 printk ("ext_add_entry : creating next block\n");
243 #endif
244 bh = ext_bread(dir,offset>>BLOCK_SIZE_BITS,1);
245 if (!bh)
246 return NULL;
247 de = (struct ext_dir_entry *) bh->b_data;
248 }
249
250 de->inode=0;
251 de->rec_len = rec_len;
252 dir->i_size += de->rec_len;
253 dir->i_dirt = 1;
254 dir->i_ctime = CURRENT_TIME;
255 }
256 if (!de->inode && de->rec_len >= rec_len) {
257 if (de->rec_len > rec_len
258 && de->rec_len - rec_len >= EXT_DIR_MIN_SIZE) {
259
260
261
262
263 de1 = (struct ext_dir_entry *) ((char *) de + rec_len);
264 de1->inode = 0;
265 de1->rec_len = de->rec_len - rec_len;
266 de1->name_len = 0;
267 de->rec_len = rec_len;
268 }
269 dir->i_mtime = CURRENT_TIME;
270 de->name_len = namelen;
271 for (i=0; i < namelen ; i++)
272 de->name[i]=get_fs_byte(name+i);
273 bh->b_dirt = 1;
274 *res_dir = de;
275 return bh;
276 }
277 offset += de->rec_len;
278 de = (struct ext_dir_entry *) ((char *) de + de->rec_len);
279 }
280 brelse(bh);
281 return NULL;
282 }
283
284 int ext_create(struct inode * dir,const char * name, int len, int mode,
285 struct inode ** result)
286 {
287 struct inode * inode;
288 struct buffer_head * bh;
289 struct ext_dir_entry * de;
290
291 *result = NULL;
292 if (!dir)
293 return -ENOENT;
294 inode = ext_new_inode(dir->i_dev);
295 if (!inode) {
296 iput(dir);
297 return -ENOSPC;
298 }
299 inode->i_op = &ext_file_inode_operations;
300 inode->i_mode = mode;
301 inode->i_dirt = 1;
302 bh = ext_add_entry(dir,name,len,&de);
303 if (!bh) {
304 inode->i_nlink--;
305 inode->i_dirt = 1;
306 iput(inode);
307 iput(dir);
308 return -ENOSPC;
309 }
310 de->inode = inode->i_ino;
311 bh->b_dirt = 1;
312 brelse(bh);
313 iput(dir);
314 *result = inode;
315 return 0;
316 }
317
318 int ext_mknod(struct inode * dir, const char * name, int len, int mode, int rdev)
319 {
320 struct inode * inode;
321 struct buffer_head * bh;
322 struct ext_dir_entry * de;
323
324 if (!dir)
325 return -ENOENT;
326 bh = ext_find_entry(dir,name,len,&de,NULL,NULL);
327 if (bh) {
328 brelse(bh);
329 iput(dir);
330 return -EEXIST;
331 }
332 inode = ext_new_inode(dir->i_dev);
333 if (!inode) {
334 iput(dir);
335 return -ENOSPC;
336 }
337 inode->i_uid = current->euid;
338 inode->i_mode = mode;
339 inode->i_op = NULL;
340 if (S_ISREG(inode->i_mode))
341 inode->i_op = &ext_file_inode_operations;
342 else if (S_ISDIR(inode->i_mode))
343 inode->i_op = &ext_dir_inode_operations;
344 else if (S_ISLNK(inode->i_mode))
345 inode->i_op = &ext_symlink_inode_operations;
346 else if (S_ISCHR(inode->i_mode))
347 inode->i_op = &ext_chrdev_inode_operations;
348 else if (S_ISBLK(inode->i_mode))
349 inode->i_op = &ext_blkdev_inode_operations;
350 else if (S_ISFIFO(inode->i_mode)) {
351 inode->i_op = &ext_fifo_inode_operations;
352 inode->i_pipe = 1;
353 PIPE_BASE(*inode) = NULL;
354 PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
355 PIPE_READ_WAIT(*inode) = PIPE_WRITE_WAIT(*inode) = NULL;
356 PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
357 }
358 if (S_ISBLK(mode) || S_ISCHR(mode))
359 inode->i_rdev = rdev;
360 inode->i_mtime = inode->i_atime = CURRENT_TIME;
361 inode->i_dirt = 1;
362 bh = ext_add_entry(dir,name,len,&de);
363 if (!bh) {
364 inode->i_nlink--;
365 inode->i_dirt = 1;
366 iput(inode);
367 iput(dir);
368 return -ENOSPC;
369 }
370 de->inode = inode->i_ino;
371 bh->b_dirt = 1;
372 brelse(bh);
373 iput(dir);
374 iput(inode);
375 return 0;
376 }
377
378 int ext_mkdir(struct inode * dir, const char * name, int len, int mode)
379 {
380 struct inode * inode;
381 struct buffer_head * bh, *dir_block;
382 struct ext_dir_entry * de;
383
384 bh = ext_find_entry(dir,name,len,&de,NULL,NULL);
385 if (bh) {
386 brelse(bh);
387 iput(dir);
388 return -EEXIST;
389 }
390 inode = ext_new_inode(dir->i_dev);
391 if (!inode) {
392 iput(dir);
393 return -ENOSPC;
394 }
395 inode->i_op = &ext_dir_inode_operations;
396 inode->i_size = 2 * 16;
397
398
399
400
401 inode->i_mtime = inode->i_atime = CURRENT_TIME;
402 dir_block = ext_bread(inode,0,1);
403 if (!dir_block) {
404 iput(dir);
405 inode->i_nlink--;
406 inode->i_dirt = 1;
407 iput(inode);
408 return -ENOSPC;
409 }
410 de = (struct ext_dir_entry *) dir_block->b_data;
411 de->inode=inode->i_ino;
412 de->rec_len=16;
413 de->name_len=1;
414 strcpy(de->name,".");
415 de = (struct ext_dir_entry *) ((char *) de + de->rec_len);
416 de->inode = dir->i_ino;
417 de->rec_len=16;
418 de->name_len=2;
419 strcpy(de->name,"..");
420 inode->i_nlink = 2;
421 dir_block->b_dirt = 1;
422 brelse(dir_block);
423 inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask);
424 inode->i_dirt = 1;
425 bh = ext_add_entry(dir,name,len,&de);
426 if (!bh) {
427 iput(dir);
428 inode->i_nlink=0;
429 iput(inode);
430 return -ENOSPC;
431 }
432 de->inode = inode->i_ino;
433 bh->b_dirt = 1;
434 dir->i_nlink++;
435 dir->i_dirt = 1;
436 iput(dir);
437 iput(inode);
438 brelse(bh);
439 return 0;
440 }
441
442
443
444
445 static int empty_dir(struct inode * inode)
446 {
447 unsigned long offset;
448 struct buffer_head * bh;
449 struct ext_dir_entry * de, * de1;
450
451 if (inode->i_size < 2 * 12 || !(bh = ext_bread(inode,0,0))) {
452 printk("warning - bad directory on dev %04x\n",inode->i_dev);
453 return 1;
454 }
455 de = (struct ext_dir_entry *) bh->b_data;
456 de1 = (struct ext_dir_entry *) ((char *) de + de->rec_len);
457 if (de->inode != inode->i_ino || !de1->inode ||
458 strcmp(".",de->name) || strcmp("..",de1->name)) {
459 printk("warning - bad directory on dev %04x\n",inode->i_dev);
460 return 1;
461 }
462 offset = de->rec_len + de1->rec_len;
463 de = (struct ext_dir_entry *) ((char *) de1 + de1->rec_len);
464 while (offset < inode->i_size ) {
465 if ((void *) de >= (void *) (bh->b_data+BLOCK_SIZE)) {
466 brelse(bh);
467 bh = ext_bread(inode, offset >> BLOCK_SIZE_BITS,1);
468 if (!bh) {
469 offset += BLOCK_SIZE;
470 continue;
471 }
472 de = (struct ext_dir_entry *) bh->b_data;
473 }
474 if (de->inode) {
475 brelse(bh);
476 return 0;
477 }
478 offset += de->rec_len;
479 de = (struct ext_dir_entry *) ((char *) de + de->rec_len);
480 }
481 brelse(bh);
482 return 1;
483 }
484
485 static inline void ext_merge_entries (struct ext_dir_entry * de,
486 struct ext_dir_entry * pde, struct ext_dir_entry * nde)
487 {
488 if (! nde->inode)
489 de->rec_len += nde->rec_len;
490 if (! pde->inode)
491 pde->rec_len += de->rec_len;
492 }
493
494 int ext_rmdir(struct inode * dir, const char * name, int len)
495 {
496 int retval;
497 struct inode * inode;
498 struct buffer_head * bh;
499 struct ext_dir_entry * de, * pde, * nde;
500
501 inode = NULL;
502 bh = ext_find_entry(dir,name,len,&de,&pde,&nde);
503 retval = -ENOENT;
504 if (!bh)
505 goto end_rmdir;
506 retval = -EPERM;
507 if (!(inode = iget(dir->i_dev, de->inode)))
508 goto end_rmdir;
509 if ((dir->i_mode & S_ISVTX) && current->euid &&
510 inode->i_uid != current->euid)
511 goto end_rmdir;
512 if (inode->i_dev != dir->i_dev)
513 goto end_rmdir;
514 if (inode == dir)
515 goto end_rmdir;
516 if (!S_ISDIR(inode->i_mode)) {
517 retval = -ENOTDIR;
518 goto end_rmdir;
519 }
520 if (!empty_dir(inode)) {
521 retval = -ENOTEMPTY;
522 goto end_rmdir;
523 }
524 if (inode->i_count > 1) {
525 retval = -EBUSY;
526 goto end_rmdir;
527 }
528 if (inode->i_nlink != 2)
529 printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
530 de->inode = 0;
531 de->name_len = 0;
532 ext_merge_entries (de, pde, nde);
533 bh->b_dirt = 1;
534 inode->i_nlink=0;
535 inode->i_dirt=1;
536 dir->i_nlink--;
537 dir->i_ctime = dir->i_mtime = CURRENT_TIME;
538 dir->i_dirt=1;
539 retval = 0;
540 end_rmdir:
541 iput(dir);
542 iput(inode);
543 brelse(bh);
544 return retval;
545 }
546
547 int ext_unlink(struct inode * dir, const char * name, int len)
548 {
549 int retval;
550 struct inode * inode;
551 struct buffer_head * bh;
552 struct ext_dir_entry * de, * pde, * nde;
553
554 retval = -ENOENT;
555 inode = NULL;
556 bh = ext_find_entry(dir,name,len,&de,&pde,&nde);
557 if (!bh)
558 goto end_unlink;
559 if (!(inode = iget(dir->i_dev, de->inode)))
560 goto end_unlink;
561 retval = -EPERM;
562 if ((dir->i_mode & S_ISVTX) && !suser() &&
563 current->euid != inode->i_uid &&
564 current->euid != dir->i_uid)
565 goto end_unlink;
566 if (S_ISDIR(inode->i_mode))
567 goto end_unlink;
568 if (!inode->i_nlink) {
569 printk("Deleting nonexistent file (%04x:%d), %d\n",
570 inode->i_dev,inode->i_ino,inode->i_nlink);
571 inode->i_nlink=1;
572 }
573 de->inode = 0;
574 de->name_len = 0;
575 ext_merge_entries (de, pde, nde);
576 bh->b_dirt = 1;
577 inode->i_nlink--;
578 inode->i_dirt = 1;
579 inode->i_ctime = CURRENT_TIME;
580 retval = 0;
581 end_unlink:
582 brelse(bh);
583 iput(inode);
584 iput(dir);
585 return retval;
586 }
587
588 int ext_symlink(struct inode * dir, const char * name, int len, const char * symname)
589 {
590 struct ext_dir_entry * de;
591 struct inode * inode = NULL;
592 struct buffer_head * bh = NULL, * name_block = NULL;
593 int i;
594 char c;
595
596 if (!(inode = ext_new_inode(dir->i_dev))) {
597 iput(dir);
598 return -ENOSPC;
599 }
600 inode->i_mode = S_IFLNK | 0777;
601 inode->i_op = &ext_symlink_inode_operations;
602 name_block = ext_bread(inode,0,1);
603 if (!name_block) {
604 iput(dir);
605 inode->i_nlink--;
606 inode->i_dirt = 1;
607 iput(inode);
608 return -ENOSPC;
609 }
610 i = 0;
611 while (i < 1023 && (c=get_fs_byte(symname++)))
612 name_block->b_data[i++] = c;
613 name_block->b_data[i] = 0;
614 name_block->b_dirt = 1;
615 brelse(name_block);
616 inode->i_size = i;
617 inode->i_dirt = 1;
618 bh = ext_find_entry(dir,name,len,&de,NULL,NULL);
619 if (bh) {
620 inode->i_nlink--;
621 inode->i_dirt = 1;
622 iput(inode);
623 brelse(bh);
624 iput(dir);
625 return -EEXIST;
626 }
627 bh = ext_add_entry(dir,name,len,&de);
628 if (!bh) {
629 inode->i_nlink--;
630 inode->i_dirt = 1;
631 iput(inode);
632 iput(dir);
633 return -ENOSPC;
634 }
635 de->inode = inode->i_ino;
636 bh->b_dirt = 1;
637 brelse(bh);
638 iput(dir);
639 iput(inode);
640 return 0;
641 }
642
643 int ext_link(struct inode * oldinode, struct inode * dir, const char * name, int len)
644 {
645 struct ext_dir_entry * de;
646 struct buffer_head * bh;
647
648 if (S_ISDIR(oldinode->i_mode)) {
649 iput(oldinode);
650 iput(dir);
651 return -EPERM;
652 }
653 bh = ext_find_entry(dir,name,len,&de,NULL,NULL);
654 if (bh) {
655 brelse(bh);
656 iput(dir);
657 iput(oldinode);
658 return -EEXIST;
659 }
660 bh = ext_add_entry(dir,name,len,&de);
661 if (!bh) {
662 iput(dir);
663 iput(oldinode);
664 return -ENOSPC;
665 }
666 de->inode = oldinode->i_ino;
667 bh->b_dirt = 1;
668 brelse(bh);
669 iput(dir);
670 oldinode->i_nlink++;
671 oldinode->i_ctime = CURRENT_TIME;
672 oldinode->i_dirt = 1;
673 iput(oldinode);
674 return 0;
675 }
676
677 static int subdir(struct inode * new, struct inode * old)
678 {
679 unsigned short fs;
680 int ino;
681 int result;
682
683 __asm__("mov %%fs,%0":"=r" (fs));
684 __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
685 new->i_count++;
686 result = 0;
687 for (;;) {
688 if (new == old) {
689 result = 1;
690 break;
691 }
692 if (new->i_dev != old->i_dev)
693 break;
694 ino = new->i_ino;
695 if (ext_lookup(new,"..",2,&new))
696 break;
697 if (new->i_ino == ino)
698 break;
699 }
700 iput(new);
701 __asm__("mov %0,%%fs"::"r" (fs));
702 return result;
703 }
704
705 #define PARENT_INO(buffer) \
706 ((struct ext_dir_entry *) ((char *) buffer + \
707 ((struct ext_dir_entry *) buffer)->rec_len))->inode
708
709 #define PARENT_NAME(buffer) \
710 ((struct ext_dir_entry *) ((char *) buffer + \
711 ((struct ext_dir_entry *) buffer)->rec_len))->name
712
713
714
715
716
717
718
719
720
721
722
723 static int do_ext_rename(struct inode * old_dir, const char * old_name, int old_len,
724 struct inode * new_dir, const char * new_name, int new_len)
725 {
726 struct inode * old_inode, * new_inode;
727 struct buffer_head * old_bh, * new_bh, * dir_bh;
728 struct ext_dir_entry * old_de, * new_de, * pde, * nde;
729 int retval;
730
731 goto start_up;
732 try_again:
733 brelse(old_bh);
734 brelse(new_bh);
735 brelse(dir_bh);
736 iput(old_inode);
737 iput(new_inode);
738 current->counter = 0;
739 schedule();
740 start_up:
741 old_inode = new_inode = NULL;
742 old_bh = new_bh = dir_bh = NULL;
743 old_bh = ext_find_entry(old_dir,old_name,old_len,&old_de,&pde,&nde);
744 retval = -ENOENT;
745 if (!old_bh)
746 goto end_rename;
747 old_inode = iget(old_dir->i_dev, old_de->inode);
748 if (!old_inode)
749 goto end_rename;
750 if ((old_dir->i_mode & S_ISVTX) &&
751 current->euid != old_inode->i_uid &&
752 current->euid != old_dir->i_uid && !suser())
753 goto end_rename;
754 new_bh = ext_find_entry(new_dir,new_name,new_len,&new_de,NULL,NULL);
755 if (new_bh) {
756 new_inode = iget(new_dir->i_dev, new_de->inode);
757 if (!new_inode) {
758 brelse(new_bh);
759 new_bh = NULL;
760 }
761 }
762 if (new_inode == old_inode) {
763 retval = 0;
764 goto end_rename;
765 }
766 if (S_ISDIR(new_inode->i_mode)) {
767 retval = -EEXIST;
768 goto end_rename;
769 }
770 if (S_ISDIR(old_inode->i_mode)) {
771 retval = -EEXIST;
772 if (new_bh)
773 goto end_rename;
774 retval = -EACCES;
775 if (!permission(old_inode, MAY_WRITE))
776 goto end_rename;
777 retval = -EINVAL;
778 if (subdir(new_dir, old_inode))
779 goto end_rename;
780 retval = -EIO;
781 dir_bh = ext_bread(old_inode,0,0);
782 if (!dir_bh)
783 goto end_rename;
784 if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
785 goto end_rename;
786 }
787 if (!new_bh)
788 new_bh = ext_add_entry(new_dir,new_name,new_len,&new_de);
789 retval = -ENOSPC;
790 if (!new_bh)
791 goto end_rename;
792
793 if (new_inode && (new_de->inode != new_inode->i_ino))
794 goto try_again;
795 if (new_de->inode && !new_inode)
796 goto try_again;
797 if (old_de->inode != old_inode->i_ino)
798 goto try_again;
799
800 old_de->inode = 0;
801 old_de->name_len = 0;
802 new_de->inode = old_inode->i_ino;
803 ext_merge_entries (old_de, pde, nde);
804 if (new_inode) {
805 new_inode->i_nlink--;
806 new_inode->i_dirt = 1;
807 }
808 old_bh->b_dirt = 1;
809 new_bh->b_dirt = 1;
810 if (dir_bh) {
811 PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
812 dir_bh->b_dirt = 1;
813 old_dir->i_nlink--;
814 new_dir->i_nlink++;
815 old_dir->i_dirt = 1;
816 new_dir->i_dirt = 1;
817 }
818 retval = 0;
819 end_rename:
820 brelse(dir_bh);
821 brelse(old_bh);
822 brelse(new_bh);
823 iput(old_inode);
824 iput(new_inode);
825 iput(old_dir);
826 iput(new_dir);
827 return retval;
828 }
829
830
831
832
833
834
835
836
837
838
839 int ext_rename(struct inode * old_dir, const char * old_name, int old_len,
840 struct inode * new_dir, const char * new_name, int new_len)
841 {
842 static struct wait_queue * wait = NULL;
843 static int lock = 0;
844 int result;
845
846 while (lock)
847 sleep_on(&wait);
848 lock = 1;
849 result = do_ext_rename(old_dir, old_name, old_len,
850 new_dir, new_name, new_len);
851 lock = 0;
852 wake_up(&wait);
853 return result;
854 }