|
|
1.1 root 1: /*
2: * linux/fs/minix/namei.c
3: *
1.1.1.6 root 4: * Copyright (C) 1991, 1992 Linus Torvalds
1.1 root 5: */
6:
7: #include <linux/sched.h>
8: #include <linux/minix_fs.h>
9: #include <linux/kernel.h>
1.1.1.4 root 10: #include <linux/string.h>
11: #include <linux/stat.h>
1.1.1.5 root 12: #include <linux/fcntl.h>
1.1.1.6 root 13: #include <linux/errno.h>
14:
1.1 root 15: #include <asm/segment.h>
16:
17: /*
18: * comment out this line if you want names > MINIX_NAME_LEN chars to be
19: * truncated. Else they will be disallowed.
20: */
21: /* #define NO_TRUNCATE */
22:
23: /*
24: * ok, we cannot use strncmp, as the name is not in our data space.
25: * Thus we'll have to use minix_match. No big problem. Match also makes
26: * some sanity tests.
27: *
28: * NOTE! unlike strncmp, minix_match returns 1 for success, 0 for failure.
29: */
30: static int minix_match(int len,const char * name,struct minix_dir_entry * de)
31: {
32: register int same __asm__("ax");
33:
34: if (!de || !de->inode || len > MINIX_NAME_LEN)
35: return 0;
36: /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
37: if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
38: return 1;
39: if (len < MINIX_NAME_LEN && de->name[len])
40: return 0;
41: __asm__("cld\n\t"
42: "fs ; repe ; cmpsb\n\t"
43: "setz %%al"
44: :"=a" (same)
45: :"0" (0),"S" ((long) name),"D" ((long) de->name),"c" (len)
46: :"cx","di","si");
47: return same;
48: }
49:
50: /*
51: * minix_find_entry()
52: *
53: * finds an entry in the specified directory with the wanted name. It
54: * returns the cache buffer in which the entry was found, and the entry
55: * itself (as a parameter - res_dir). It does NOT read the inode of the
56: * entry - you'll have to do that yourself if you want to.
57: */
58: static struct buffer_head * minix_find_entry(struct inode * dir,
59: const char * name, int namelen, struct minix_dir_entry ** res_dir)
60: {
1.1.1.7 ! root 61: int entries, i;
1.1 root 62: struct buffer_head * bh;
63: struct minix_dir_entry * de;
64:
65: *res_dir = NULL;
66: if (!dir)
67: return NULL;
68: #ifdef NO_TRUNCATE
69: if (namelen > MINIX_NAME_LEN)
70: return NULL;
71: #else
72: if (namelen > MINIX_NAME_LEN)
73: namelen = MINIX_NAME_LEN;
74: #endif
75: entries = dir->i_size / (sizeof (struct minix_dir_entry));
1.1.1.7 ! root 76: bh = minix_bread(dir,0,0);
! 77: if (!bh)
1.1 root 78: return NULL;
79: i = 0;
80: de = (struct minix_dir_entry *) bh->b_data;
81: while (i < entries) {
82: if ((char *)de >= BLOCK_SIZE+bh->b_data) {
83: brelse(bh);
1.1.1.7 ! root 84: bh = minix_bread(dir,i/MINIX_DIR_ENTRIES_PER_BLOCK,0);
! 85: if (!bh) {
1.1 root 86: i += MINIX_DIR_ENTRIES_PER_BLOCK;
87: continue;
88: }
89: de = (struct minix_dir_entry *) bh->b_data;
90: }
91: if (minix_match(namelen,name,de)) {
92: *res_dir = de;
93: return bh;
94: }
95: de++;
96: i++;
97: }
98: brelse(bh);
99: return NULL;
100: }
101:
102: int minix_lookup(struct inode * dir,const char * name, int len,
103: struct inode ** result)
104: {
105: int ino;
106: struct minix_dir_entry * de;
107: struct buffer_head * bh;
108:
109: *result = NULL;
110: if (!dir)
111: return -ENOENT;
112: if (!S_ISDIR(dir->i_mode)) {
113: iput(dir);
114: return -ENOENT;
115: }
116: if (!(bh = minix_find_entry(dir,name,len,&de))) {
117: iput(dir);
118: return -ENOENT;
119: }
120: ino = de->inode;
121: brelse(bh);
122: if (!(*result = iget(dir->i_dev,ino))) {
123: iput(dir);
124: return -EACCES;
125: }
126: iput(dir);
127: return 0;
128: }
129:
130: /*
131: * minix_add_entry()
132: *
133: * adds a file entry to the specified directory, using the same
134: * semantics as minix_find_entry(). It returns NULL if it failed.
135: *
136: * NOTE!! The inode part of 'de' is left at 0 - which means you
137: * may not sleep between calling this and putting something into
138: * the entry, as someone else might have used it while you slept.
139: */
140: static struct buffer_head * minix_add_entry(struct inode * dir,
141: const char * name, int namelen, struct minix_dir_entry ** res_dir)
142: {
1.1.1.7 ! root 143: int i;
1.1 root 144: struct buffer_head * bh;
145: struct minix_dir_entry * de;
146:
147: *res_dir = NULL;
148: if (!dir)
149: return NULL;
150: #ifdef NO_TRUNCATE
151: if (namelen > MINIX_NAME_LEN)
152: return NULL;
153: #else
154: if (namelen > MINIX_NAME_LEN)
155: namelen = MINIX_NAME_LEN;
156: #endif
157: if (!namelen)
158: return NULL;
1.1.1.7 ! root 159: bh = minix_bread(dir,0,0);
! 160: if (!bh)
1.1 root 161: return NULL;
162: i = 0;
163: de = (struct minix_dir_entry *) bh->b_data;
164: while (1) {
165: if ((char *)de >= BLOCK_SIZE+bh->b_data) {
166: brelse(bh);
1.1.1.7 ! root 167: bh = minix_bread(dir,i/MINIX_DIR_ENTRIES_PER_BLOCK,1);
! 168: if (!bh)
1.1 root 169: return NULL;
170: de = (struct minix_dir_entry *) bh->b_data;
171: }
172: if (i*sizeof(struct minix_dir_entry) >= dir->i_size) {
173: de->inode=0;
174: dir->i_size = (i+1)*sizeof(struct minix_dir_entry);
175: dir->i_dirt = 1;
176: dir->i_ctime = CURRENT_TIME;
177: }
178: if (!de->inode) {
179: dir->i_mtime = CURRENT_TIME;
180: for (i=0; i < MINIX_NAME_LEN ; i++)
181: de->name[i]=(i<namelen)?get_fs_byte(name+i):0;
182: bh->b_dirt = 1;
183: *res_dir = de;
184: return bh;
185: }
186: de++;
187: i++;
188: }
189: brelse(bh);
190: return NULL;
191: }
192:
193: int minix_create(struct inode * dir,const char * name, int len, int mode,
194: struct inode ** result)
195: {
196: struct inode * inode;
197: struct buffer_head * bh;
198: struct minix_dir_entry * de;
199:
200: *result = NULL;
201: if (!dir)
202: return -ENOENT;
203: inode = minix_new_inode(dir->i_dev);
204: if (!inode) {
205: iput(dir);
206: return -ENOSPC;
207: }
1.1.1.3 root 208: inode->i_op = &minix_file_inode_operations;
1.1 root 209: inode->i_mode = mode;
210: inode->i_dirt = 1;
211: bh = minix_add_entry(dir,name,len,&de);
212: if (!bh) {
213: inode->i_nlink--;
1.1.1.3 root 214: inode->i_dirt = 1;
1.1 root 215: iput(inode);
216: iput(dir);
217: return -ENOSPC;
218: }
219: de->inode = inode->i_ino;
220: bh->b_dirt = 1;
221: brelse(bh);
222: iput(dir);
223: *result = inode;
224: return 0;
225: }
226:
227: int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rdev)
228: {
229: struct inode * inode;
230: struct buffer_head * bh;
231: struct minix_dir_entry * de;
232:
233: if (!dir)
234: return -ENOENT;
235: bh = minix_find_entry(dir,name,len,&de);
236: if (bh) {
237: brelse(bh);
238: iput(dir);
239: return -EEXIST;
240: }
241: inode = minix_new_inode(dir->i_dev);
242: if (!inode) {
243: iput(dir);
244: return -ENOSPC;
245: }
246: inode->i_uid = current->euid;
247: inode->i_mode = mode;
1.1.1.3 root 248: inode->i_op = NULL;
249: if (S_ISREG(inode->i_mode))
250: inode->i_op = &minix_file_inode_operations;
251: else if (S_ISDIR(inode->i_mode))
252: inode->i_op = &minix_dir_inode_operations;
253: else if (S_ISLNK(inode->i_mode))
254: inode->i_op = &minix_symlink_inode_operations;
255: else if (S_ISCHR(inode->i_mode))
256: inode->i_op = &minix_chrdev_inode_operations;
257: else if (S_ISBLK(inode->i_mode))
258: inode->i_op = &minix_blkdev_inode_operations;
1.1.1.5 root 259: else if (S_ISFIFO(inode->i_mode)) {
260: inode->i_op = &minix_fifo_inode_operations;
261: inode->i_pipe = 1;
1.1.1.7 ! root 262: PIPE_BASE(*inode) = NULL;
1.1.1.5 root 263: PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
1.1.1.7 ! root 264: PIPE_READ_WAIT(*inode) = PIPE_WRITE_WAIT(*inode) = NULL;
1.1.1.5 root 265: PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
266: }
1.1 root 267: if (S_ISBLK(mode) || S_ISCHR(mode))
268: inode->i_rdev = rdev;
269: inode->i_mtime = inode->i_atime = CURRENT_TIME;
270: inode->i_dirt = 1;
271: bh = minix_add_entry(dir,name,len,&de);
272: if (!bh) {
273: inode->i_nlink--;
1.1.1.3 root 274: inode->i_dirt = 1;
1.1 root 275: iput(inode);
276: iput(dir);
277: return -ENOSPC;
278: }
279: de->inode = inode->i_ino;
280: bh->b_dirt = 1;
281: brelse(bh);
282: iput(dir);
283: iput(inode);
284: return 0;
285: }
286:
287: int minix_mkdir(struct inode * dir, const char * name, int len, int mode)
288: {
289: struct inode * inode;
290: struct buffer_head * bh, *dir_block;
291: struct minix_dir_entry * de;
292:
293: bh = minix_find_entry(dir,name,len,&de);
294: if (bh) {
295: brelse(bh);
296: iput(dir);
297: return -EEXIST;
298: }
299: inode = minix_new_inode(dir->i_dev);
300: if (!inode) {
301: iput(dir);
302: return -ENOSPC;
303: }
1.1.1.3 root 304: inode->i_op = &minix_dir_inode_operations;
305: inode->i_size = 2 * sizeof (struct minix_dir_entry);
1.1 root 306: inode->i_mtime = inode->i_atime = CURRENT_TIME;
1.1.1.7 ! root 307: dir_block = minix_bread(inode,0,1);
! 308: if (!dir_block) {
1.1 root 309: iput(dir);
310: inode->i_nlink--;
1.1.1.3 root 311: inode->i_dirt = 1;
1.1 root 312: iput(inode);
313: return -ENOSPC;
314: }
315: de = (struct minix_dir_entry *) dir_block->b_data;
316: de->inode=inode->i_ino;
317: strcpy(de->name,".");
318: de++;
319: de->inode = dir->i_ino;
320: strcpy(de->name,"..");
321: inode->i_nlink = 2;
322: dir_block->b_dirt = 1;
323: brelse(dir_block);
1.1.1.7 ! root 324: inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask);
1.1 root 325: inode->i_dirt = 1;
326: bh = minix_add_entry(dir,name,len,&de);
327: if (!bh) {
328: iput(dir);
329: inode->i_nlink=0;
330: iput(inode);
331: return -ENOSPC;
332: }
333: de->inode = inode->i_ino;
334: bh->b_dirt = 1;
335: dir->i_nlink++;
336: dir->i_dirt = 1;
337: iput(dir);
338: iput(inode);
339: brelse(bh);
340: return 0;
341: }
342:
343: /*
344: * routine to check that the specified directory is empty (for rmdir)
345: */
346: static int empty_dir(struct inode * inode)
347: {
1.1.1.7 ! root 348: int nr, len;
1.1 root 349: struct buffer_head * bh;
350: struct minix_dir_entry * de;
351:
352: len = inode->i_size / sizeof (struct minix_dir_entry);
1.1.1.7 ! root 353: if (len<2 || !(bh = minix_bread(inode,0,0))) {
1.1 root 354: printk("warning - bad directory on dev %04x\n",inode->i_dev);
1.1.1.7 ! root 355: return 1;
1.1 root 356: }
357: de = (struct minix_dir_entry *) bh->b_data;
358: if (de[0].inode != inode->i_ino || !de[1].inode ||
359: strcmp(".",de[0].name) || strcmp("..",de[1].name)) {
360: printk("warning - bad directory on dev %04x\n",inode->i_dev);
1.1.1.7 ! root 361: return 1;
1.1 root 362: }
363: nr = 2;
364: de += 2;
365: while (nr<len) {
366: if ((void *) de >= (void *) (bh->b_data+BLOCK_SIZE)) {
367: brelse(bh);
1.1.1.7 ! root 368: bh = minix_bread(inode,nr/MINIX_DIR_ENTRIES_PER_BLOCK,0);
! 369: if (!bh) {
1.1 root 370: nr += MINIX_DIR_ENTRIES_PER_BLOCK;
371: continue;
372: }
373: de = (struct minix_dir_entry *) bh->b_data;
374: }
375: if (de->inode) {
376: brelse(bh);
377: return 0;
378: }
379: de++;
380: nr++;
381: }
382: brelse(bh);
383: return 1;
384: }
385:
386: int minix_rmdir(struct inode * dir, const char * name, int len)
387: {
388: int retval;
389: struct inode * inode;
390: struct buffer_head * bh;
391: struct minix_dir_entry * de;
392:
393: inode = NULL;
394: bh = minix_find_entry(dir,name,len,&de);
395: retval = -ENOENT;
396: if (!bh)
397: goto end_rmdir;
398: retval = -EPERM;
399: if (!(inode = iget(dir->i_dev, de->inode)))
400: goto end_rmdir;
401: if ((dir->i_mode & S_ISVTX) && current->euid &&
402: inode->i_uid != current->euid)
403: goto end_rmdir;
404: if (inode->i_dev != dir->i_dev)
405: goto end_rmdir;
406: if (inode == dir) /* we may not delete ".", but "../dir" is ok */
407: goto end_rmdir;
408: if (!S_ISDIR(inode->i_mode)) {
409: retval = -ENOTDIR;
410: goto end_rmdir;
411: }
412: if (!empty_dir(inode)) {
413: retval = -ENOTEMPTY;
414: goto end_rmdir;
415: }
416: if (inode->i_count > 1) {
417: retval = -EBUSY;
418: goto end_rmdir;
419: }
420: if (inode->i_nlink != 2)
421: printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
422: de->inode = 0;
423: bh->b_dirt = 1;
424: inode->i_nlink=0;
425: inode->i_dirt=1;
426: dir->i_nlink--;
427: dir->i_ctime = dir->i_mtime = CURRENT_TIME;
428: dir->i_dirt=1;
429: retval = 0;
430: end_rmdir:
431: iput(dir);
432: iput(inode);
433: brelse(bh);
434: return retval;
435: }
436:
437: int minix_unlink(struct inode * dir, const char * name, int len)
438: {
439: int retval;
440: struct inode * inode;
441: struct buffer_head * bh;
442: struct minix_dir_entry * de;
443:
444: retval = -ENOENT;
445: inode = NULL;
446: bh = minix_find_entry(dir,name,len,&de);
447: if (!bh)
448: goto end_unlink;
449: if (!(inode = iget(dir->i_dev, de->inode)))
450: goto end_unlink;
451: retval = -EPERM;
452: if ((dir->i_mode & S_ISVTX) && !suser() &&
453: current->euid != inode->i_uid &&
454: current->euid != dir->i_uid)
455: goto end_unlink;
456: if (S_ISDIR(inode->i_mode))
457: goto end_unlink;
458: if (!inode->i_nlink) {
459: printk("Deleting nonexistent file (%04x:%d), %d\n",
460: inode->i_dev,inode->i_ino,inode->i_nlink);
461: inode->i_nlink=1;
462: }
463: de->inode = 0;
464: bh->b_dirt = 1;
465: inode->i_nlink--;
466: inode->i_dirt = 1;
467: inode->i_ctime = CURRENT_TIME;
468: retval = 0;
469: end_unlink:
470: brelse(bh);
471: iput(inode);
472: iput(dir);
473: return retval;
474: }
475:
476: int minix_symlink(struct inode * dir, const char * name, int len, const char * symname)
477: {
478: struct minix_dir_entry * de;
479: struct inode * inode = NULL;
480: struct buffer_head * bh = NULL, * name_block = NULL;
481: int i;
482: char c;
483:
484: if (!(inode = minix_new_inode(dir->i_dev))) {
485: iput(dir);
486: return -ENOSPC;
487: }
488: inode->i_mode = S_IFLNK | 0777;
1.1.1.3 root 489: inode->i_op = &minix_symlink_inode_operations;
1.1.1.7 ! root 490: name_block = minix_bread(inode,0,1);
! 491: if (!name_block) {
1.1 root 492: iput(dir);
493: inode->i_nlink--;
1.1.1.3 root 494: inode->i_dirt = 1;
1.1 root 495: iput(inode);
496: return -ENOSPC;
497: }
498: i = 0;
499: while (i < 1023 && (c=get_fs_byte(symname++)))
500: name_block->b_data[i++] = c;
501: name_block->b_data[i] = 0;
502: name_block->b_dirt = 1;
503: brelse(name_block);
504: inode->i_size = i;
505: inode->i_dirt = 1;
506: bh = minix_find_entry(dir,name,len,&de);
507: if (bh) {
508: inode->i_nlink--;
1.1.1.3 root 509: inode->i_dirt = 1;
1.1 root 510: iput(inode);
511: brelse(bh);
512: iput(dir);
513: return -EEXIST;
514: }
515: bh = minix_add_entry(dir,name,len,&de);
516: if (!bh) {
517: inode->i_nlink--;
1.1.1.3 root 518: inode->i_dirt = 1;
1.1 root 519: iput(inode);
520: iput(dir);
521: return -ENOSPC;
522: }
523: de->inode = inode->i_ino;
524: bh->b_dirt = 1;
525: brelse(bh);
526: iput(dir);
527: iput(inode);
528: return 0;
529: }
530:
531: int minix_link(struct inode * oldinode, struct inode * dir, const char * name, int len)
532: {
533: struct minix_dir_entry * de;
534: struct buffer_head * bh;
535:
536: if (S_ISDIR(oldinode->i_mode)) {
537: iput(oldinode);
538: iput(dir);
539: return -EPERM;
540: }
541: bh = minix_find_entry(dir,name,len,&de);
542: if (bh) {
543: brelse(bh);
544: iput(dir);
545: iput(oldinode);
546: return -EEXIST;
547: }
548: bh = minix_add_entry(dir,name,len,&de);
549: if (!bh) {
550: iput(dir);
551: iput(oldinode);
552: return -ENOSPC;
553: }
554: de->inode = oldinode->i_ino;
555: bh->b_dirt = 1;
556: brelse(bh);
557: iput(dir);
558: oldinode->i_nlink++;
559: oldinode->i_ctime = CURRENT_TIME;
560: oldinode->i_dirt = 1;
561: iput(oldinode);
562: return 0;
563: }
564:
565: static int subdir(struct inode * new, struct inode * old)
566: {
567: unsigned short fs;
568: int ino;
569: int result;
570:
571: __asm__("mov %%fs,%0":"=r" (fs));
572: __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
573: new->i_count++;
574: result = 0;
575: for (;;) {
576: if (new == old) {
577: result = 1;
578: break;
579: }
580: if (new->i_dev != old->i_dev)
581: break;
582: ino = new->i_ino;
583: if (minix_lookup(new,"..",2,&new))
584: break;
585: if (new->i_ino == ino)
586: break;
587: }
588: iput(new);
589: __asm__("mov %0,%%fs"::"r" (fs));
590: return result;
591: }
592:
593: #define PARENT_INO(buffer) \
594: (((struct minix_dir_entry *) (buffer))[1].inode)
595:
596: #define PARENT_NAME(buffer) \
597: (((struct minix_dir_entry *) (buffer))[1].name)
598:
599: /*
600: * rename uses retrying to avoid race-conditions: at least they should be minimal.
601: * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
602: * checks fail, it tries to restart itself again. Very practical - no changes
603: * are done until we know everything works ok.. and then all the changes can be
604: * done in one fell swoop when we have claimed all the buffers needed.
605: *
606: * Anybody can rename anything with this: the permission checks are left to the
607: * higher-level routines.
608: */
609: static int do_minix_rename(struct inode * old_dir, const char * old_name, int old_len,
610: struct inode * new_dir, const char * new_name, int new_len)
611: {
612: struct inode * old_inode, * new_inode;
613: struct buffer_head * old_bh, * new_bh, * dir_bh;
614: struct minix_dir_entry * old_de, * new_de;
615: int retval;
616:
617: goto start_up;
618: try_again:
619: brelse(old_bh);
620: brelse(new_bh);
621: brelse(dir_bh);
622: iput(old_inode);
623: iput(new_inode);
624: current->counter = 0;
625: schedule();
626: start_up:
627: old_inode = new_inode = NULL;
628: old_bh = new_bh = dir_bh = NULL;
629: old_bh = minix_find_entry(old_dir,old_name,old_len,&old_de);
630: retval = -ENOENT;
631: if (!old_bh)
632: goto end_rename;
633: old_inode = iget(old_dir->i_dev, old_de->inode);
634: if (!old_inode)
635: goto end_rename;
1.1.1.3 root 636: if ((old_dir->i_mode & S_ISVTX) &&
637: current->euid != old_inode->i_uid &&
638: current->euid != old_dir->i_uid && !suser())
639: goto end_rename;
1.1 root 640: new_bh = minix_find_entry(new_dir,new_name,new_len,&new_de);
641: if (new_bh) {
642: new_inode = iget(new_dir->i_dev, new_de->inode);
643: if (!new_inode) {
644: brelse(new_bh);
645: new_bh = NULL;
646: }
647: }
648: if (new_inode == old_inode) {
649: retval = 0;
650: goto end_rename;
651: }
1.1.1.6 root 652: if (S_ISDIR(new_inode->i_mode)) {
653: retval = -EEXIST;
654: goto end_rename;
655: }
1.1 root 656: if (S_ISDIR(old_inode->i_mode)) {
657: retval = -EEXIST;
658: if (new_bh)
659: goto end_rename;
660: retval = -EACCES;
661: if (!permission(old_inode, MAY_WRITE))
662: goto end_rename;
663: retval = -EINVAL;
664: if (subdir(new_dir, old_inode))
665: goto end_rename;
666: retval = -EIO;
1.1.1.7 ! root 667: dir_bh = minix_bread(old_inode,0,0);
! 668: if (!dir_bh)
1.1 root 669: goto end_rename;
670: if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
671: goto end_rename;
672: }
673: if (!new_bh)
674: new_bh = minix_add_entry(new_dir,new_name,new_len,&new_de);
675: retval = -ENOSPC;
676: if (!new_bh)
677: goto end_rename;
678: /* sanity checking before doing the rename - avoid races */
679: if (new_inode && (new_de->inode != new_inode->i_ino))
680: goto try_again;
681: if (new_de->inode && !new_inode)
682: goto try_again;
683: if (old_de->inode != old_inode->i_ino)
684: goto try_again;
685: /* ok, that's it */
686: old_de->inode = 0;
687: new_de->inode = old_inode->i_ino;
1.1.1.3 root 688: if (new_inode) {
1.1 root 689: new_inode->i_nlink--;
1.1.1.3 root 690: new_inode->i_dirt = 1;
691: }
1.1 root 692: old_bh->b_dirt = 1;
693: new_bh->b_dirt = 1;
694: if (dir_bh) {
695: PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
696: dir_bh->b_dirt = 1;
697: old_dir->i_nlink--;
698: new_dir->i_nlink++;
699: old_dir->i_dirt = 1;
700: new_dir->i_dirt = 1;
701: }
702: retval = 0;
703: end_rename:
704: brelse(dir_bh);
705: brelse(old_bh);
706: brelse(new_bh);
707: iput(old_inode);
708: iput(new_inode);
709: iput(old_dir);
710: iput(new_dir);
711: return retval;
712: }
713:
714: /*
715: * Ok, rename also locks out other renames, as they can change the parent of
716: * a directory, and we don't want any races. Other races are checked for by
717: * "do_rename()", which restarts if there are inconsistencies.
718: *
719: * Note that there is no race between different filesystems: it's only within
720: * the same device that races occur: many renames can happen at once, as long
721: * as they are on different partitions.
722: */
723: int minix_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: {
1.1.1.6 root 726: static struct wait_queue * wait = NULL;
1.1 root 727: static int lock = 0;
728: int result;
729:
730: while (lock)
731: sleep_on(&wait);
732: lock = 1;
733: result = do_minix_rename(old_dir, old_name, old_len,
734: new_dir, new_name, new_len);
735: lock = 0;
736: wake_up(&wait);
737: return result;
738: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.