+- add patches.fixes/linux-post-2.6.3-20040220
[linux-flexiantxendom0-3.2.10.git] / fs / jfs / namei.c
1 /*
2  *   Copyright (C) International Business Machines Corp., 2000-2003
3  *   Portions Copyright (C) Christoph Hellwig, 2001-2002
4  *
5  *   This program is free software;  you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation; either version 2 of the License, or 
8  *   (at your option) any later version.
9  * 
10  *   This program is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13  *   the GNU General Public License for more details.
14  *
15  *   You should have received a copy of the GNU General Public License
16  *   along with this program;  if not, write to the Free Software 
17  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */
19
20 #include <linux/fs.h>
21 #include "jfs_incore.h"
22 #include "jfs_superblock.h"
23 #include "jfs_inode.h"
24 #include "jfs_dinode.h"
25 #include "jfs_dmap.h"
26 #include "jfs_unicode.h"
27 #include "jfs_metapage.h"
28 #include "jfs_xattr.h"
29 #include "jfs_acl.h"
30 #include "jfs_debug.h"
31
32 extern struct inode_operations jfs_file_inode_operations;
33 extern struct inode_operations jfs_symlink_inode_operations;
34 extern struct file_operations jfs_file_operations;
35 extern struct address_space_operations jfs_aops;
36
37 extern int jfs_fsync(struct file *, struct dentry *, int);
38 extern void jfs_truncate_nolock(struct inode *, loff_t);
39 extern int jfs_init_acl(struct inode *, struct inode *);
40
41 /*
42  * forward references
43  */
44 struct inode_operations jfs_dir_inode_operations;
45 struct file_operations jfs_dir_operations;
46
47 s64 commitZeroLink(tid_t, struct inode *);
48
49 /*
50  * NAME:        jfs_create(dip, dentry, mode)
51  *
52  * FUNCTION:    create a regular file in the parent directory <dip>
53  *              with name = <from dentry> and mode = <mode>
54  *
55  * PARAMETER:   dip     - parent directory vnode
56  *              dentry  - dentry of new file
57  *              mode    - create mode (rwxrwxrwx).
58  *              nd- nd struct
59  *
60  * RETURN:      Errors from subroutines
61  *
62  */
63 int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
64                 struct nameidata *nd)
65 {
66         int rc = 0;
67         tid_t tid;              /* transaction id */
68         struct inode *ip = NULL;        /* child directory inode */
69         ino_t ino;
70         struct component_name dname;    /* child directory name */
71         struct btstack btstack;
72         struct inode *iplist[2];
73         struct tblock *tblk;
74
75         jfs_info("jfs_create: dip:0x%p name:%s", dip, dentry->d_name.name);
76
77         /*
78          * search parent directory for entry/freespace
79          * (dtSearch() returns parent directory page pinned)
80          */
81         if ((rc = get_UCSname(&dname, dentry)))
82                 goto out1;
83
84         /*
85          * Either iAlloc() or txBegin() may block.  Deadlock can occur if we
86          * block there while holding dtree page, so we allocate the inode &
87          * begin the transaction before we search the directory.
88          */
89         ip = ialloc(dip, mode);
90         if (ip == NULL) {
91                 rc = -ENOSPC;
92                 goto out2;
93         }
94
95         tid = txBegin(dip->i_sb, 0);
96
97         down(&JFS_IP(dip)->commit_sem);
98         down(&JFS_IP(ip)->commit_sem);
99
100         if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) {
101                 jfs_err("jfs_create: dtSearch returned %d", rc);
102                 goto out3;
103         }
104
105         tblk = tid_to_tblock(tid);
106         tblk->xflag |= COMMIT_CREATE;
107         tblk->ip = ip;
108
109         iplist[0] = dip;
110         iplist[1] = ip;
111
112         /*
113          * initialize the child XAD tree root in-line in inode
114          */
115         xtInitRoot(tid, ip);
116
117         /*
118          * create entry in parent directory for child directory
119          * (dtInsert() releases parent directory page)
120          */
121         ino = ip->i_ino;
122         if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {
123                 jfs_err("jfs_create: dtInsert returned %d", rc);
124                 if (rc == -EIO)
125                         txAbort(tid, 1);        /* Marks Filesystem dirty */
126                 else
127                         txAbort(tid, 0);        /* Filesystem full */
128                 goto out3;
129         }
130
131         ip->i_op = &jfs_file_inode_operations;
132         ip->i_fop = &jfs_file_operations;
133         ip->i_mapping->a_ops = &jfs_aops;
134
135         insert_inode_hash(ip);
136         mark_inode_dirty(ip);
137         d_instantiate(dentry, ip);
138
139         dip->i_ctime = dip->i_mtime = CURRENT_TIME;
140
141         mark_inode_dirty(dip);
142
143         rc = txCommit(tid, 2, &iplist[0], 0);
144
145       out3:
146         txEnd(tid);
147         up(&JFS_IP(dip)->commit_sem);
148         up(&JFS_IP(ip)->commit_sem);
149         if (rc) {
150                 ip->i_nlink = 0;
151                 iput(ip);
152         }
153
154       out2:
155         free_UCSname(&dname);
156
157 #ifdef CONFIG_JFS_POSIX_ACL
158         if (rc == 0)
159                 jfs_init_acl(ip, dip);
160 #endif
161
162       out1:
163
164         jfs_info("jfs_create: rc:%d", rc);
165         return rc;
166 }
167
168
169 /*
170  * NAME:        jfs_mkdir(dip, dentry, mode)
171  *
172  * FUNCTION:    create a child directory in the parent directory <dip>
173  *              with name = <from dentry> and mode = <mode>
174  *
175  * PARAMETER:   dip     - parent directory vnode
176  *              dentry  - dentry of child directory
177  *              mode    - create mode (rwxrwxrwx).
178  *
179  * RETURN:      Errors from subroutines
180  *
181  * note:
182  * EACCESS: user needs search+write permission on the parent directory
183  */
184 int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
185 {
186         int rc = 0;
187         tid_t tid;              /* transaction id */
188         struct inode *ip = NULL;        /* child directory inode */
189         ino_t ino;
190         struct component_name dname;    /* child directory name */
191         struct btstack btstack;
192         struct inode *iplist[2];
193         struct tblock *tblk;
194
195         jfs_info("jfs_mkdir: dip:0x%p name:%s", dip, dentry->d_name.name);
196
197         /* link count overflow on parent directory ? */
198         if (dip->i_nlink == JFS_LINK_MAX) {
199                 rc = -EMLINK;
200                 goto out1;
201         }
202
203         /*
204          * search parent directory for entry/freespace
205          * (dtSearch() returns parent directory page pinned)
206          */
207         if ((rc = get_UCSname(&dname, dentry)))
208                 goto out1;
209
210         /*
211          * Either iAlloc() or txBegin() may block.  Deadlock can occur if we
212          * block there while holding dtree page, so we allocate the inode &
213          * begin the transaction before we search the directory.
214          */
215         ip = ialloc(dip, S_IFDIR | mode);
216         if (ip == NULL) {
217                 rc = -ENOSPC;
218                 goto out2;
219         }
220
221         tid = txBegin(dip->i_sb, 0);
222
223         down(&JFS_IP(dip)->commit_sem);
224         down(&JFS_IP(ip)->commit_sem);
225
226         if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) {
227                 jfs_err("jfs_mkdir: dtSearch returned %d", rc);
228                 goto out3;
229         }
230
231         tblk = tid_to_tblock(tid);
232         tblk->xflag |= COMMIT_CREATE;
233         tblk->ip = ip;
234
235         iplist[0] = dip;
236         iplist[1] = ip;
237
238         /*
239          * initialize the child directory in-line in inode
240          */
241         dtInitRoot(tid, ip, dip->i_ino);
242
243         /*
244          * create entry in parent directory for child directory
245          * (dtInsert() releases parent directory page)
246          */
247         ino = ip->i_ino;
248         if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {
249                 jfs_err("jfs_mkdir: dtInsert returned %d", rc);
250
251                 if (rc == -EIO)
252                         txAbort(tid, 1);        /* Marks Filesystem dirty */
253                 else
254                         txAbort(tid, 0);        /* Filesystem full */
255                 goto out3;
256         }
257
258         ip->i_nlink = 2;        /* for '.' */
259         ip->i_op = &jfs_dir_inode_operations;
260         ip->i_fop = &jfs_dir_operations;
261         ip->i_mapping->a_ops = &jfs_aops;
262         mapping_set_gfp_mask(ip->i_mapping, GFP_NOFS);
263
264         insert_inode_hash(ip);
265         mark_inode_dirty(ip);
266         d_instantiate(dentry, ip);
267
268         /* update parent directory inode */
269         dip->i_nlink++;         /* for '..' from child directory */
270         dip->i_ctime = dip->i_mtime = CURRENT_TIME;
271         mark_inode_dirty(dip);
272
273         rc = txCommit(tid, 2, &iplist[0], 0);
274
275       out3:
276         txEnd(tid);
277         up(&JFS_IP(dip)->commit_sem);
278         up(&JFS_IP(ip)->commit_sem);
279         if (rc) {
280                 ip->i_nlink = 0;
281                 iput(ip);
282         }
283
284       out2:
285         free_UCSname(&dname);
286
287 #ifdef CONFIG_JFS_POSIX_ACL
288         if (rc == 0)
289                 jfs_init_acl(ip, dip);
290 #endif
291
292       out1:
293
294         jfs_info("jfs_mkdir: rc:%d", rc);
295         return rc;
296 }
297
298 /*
299  * NAME:        jfs_rmdir(dip, dentry)
300  *
301  * FUNCTION:    remove a link to child directory
302  *
303  * PARAMETER:   dip     - parent inode
304  *              dentry  - child directory dentry
305  *
306  * RETURN:      -EINVAL - if name is . or ..
307  *              -EINVAL  - if . or .. exist but are invalid.
308  *              errors from subroutines
309  *
310  * note:
311  * if other threads have the directory open when the last link 
312  * is removed, the "." and ".." entries, if present, are removed before 
313  * rmdir() returns and no new entries may be created in the directory, 
314  * but the directory is not removed until the last reference to 
315  * the directory is released (cf.unlink() of regular file).
316  */
317 int jfs_rmdir(struct inode *dip, struct dentry *dentry)
318 {
319         int rc;
320         tid_t tid;              /* transaction id */
321         struct inode *ip = dentry->d_inode;
322         ino_t ino;
323         struct component_name dname;
324         struct inode *iplist[2];
325         struct tblock *tblk;
326
327         jfs_info("jfs_rmdir: dip:0x%p name:%s", dip, dentry->d_name.name);
328
329         /* directory must be empty to be removed */
330         if (!dtEmpty(ip)) {
331                 rc = -ENOTEMPTY;
332                 goto out;
333         }
334
335         if ((rc = get_UCSname(&dname, dentry))) {
336                 goto out;
337         }
338
339         tid = txBegin(dip->i_sb, 0);
340
341         down(&JFS_IP(dip)->commit_sem);
342         down(&JFS_IP(ip)->commit_sem);
343
344         iplist[0] = dip;
345         iplist[1] = ip;
346
347         tblk = tid_to_tblock(tid);
348         tblk->xflag |= COMMIT_DELETE;
349         tblk->ip = ip;
350
351         /*
352          * delete the entry of target directory from parent directory
353          */
354         ino = ip->i_ino;
355         if ((rc = dtDelete(tid, dip, &dname, &ino, JFS_REMOVE))) {
356                 jfs_err("jfs_rmdir: dtDelete returned %d", rc);
357                 if (rc == -EIO)
358                         txAbort(tid, 1);
359                 txEnd(tid);
360                 up(&JFS_IP(dip)->commit_sem);
361                 up(&JFS_IP(ip)->commit_sem);
362
363                 goto out2;
364         }
365
366         /* update parent directory's link count corresponding
367          * to ".." entry of the target directory deleted
368          */
369         dip->i_nlink--;
370         dip->i_ctime = dip->i_mtime = CURRENT_TIME;
371         mark_inode_dirty(dip);
372
373         /*
374          * OS/2 could have created EA and/or ACL
375          */
376         /* free EA from both persistent and working map */
377         if (JFS_IP(ip)->ea.flag & DXD_EXTENT) {
378                 /* free EA pages */
379                 txEA(tid, ip, &JFS_IP(ip)->ea, NULL);
380         }
381         JFS_IP(ip)->ea.flag = 0;
382
383         /* free ACL from both persistent and working map */
384         if (JFS_IP(ip)->acl.flag & DXD_EXTENT) {
385                 /* free ACL pages */
386                 txEA(tid, ip, &JFS_IP(ip)->acl, NULL);
387         }
388         JFS_IP(ip)->acl.flag = 0;
389
390         /* mark the target directory as deleted */
391         ip->i_nlink = 0;
392         mark_inode_dirty(ip);
393
394         rc = txCommit(tid, 2, &iplist[0], 0);
395
396         txEnd(tid);
397
398         up(&JFS_IP(dip)->commit_sem);
399         up(&JFS_IP(ip)->commit_sem);
400
401         /*
402          * Truncating the directory index table is not guaranteed.  It
403          * may need to be done iteratively
404          */
405         if (test_cflag(COMMIT_Stale, dip)) {
406                 if (dip->i_size > 1)
407                         jfs_truncate_nolock(dip, 0);
408
409                 clear_cflag(COMMIT_Stale, dip);
410         }
411
412       out2:
413         free_UCSname(&dname);
414
415       out:
416         jfs_info("jfs_rmdir: rc:%d", rc);
417         return rc;
418 }
419
420 /*
421  * NAME:        jfs_unlink(dip, dentry)
422  *
423  * FUNCTION:    remove a link to object <vp> named by <name> 
424  *              from parent directory <dvp>
425  *
426  * PARAMETER:   dip     - inode of parent directory
427  *              dentry  - dentry of object to be removed
428  *
429  * RETURN:      errors from subroutines
430  *
431  * note:
432  * temporary file: if one or more processes have the file open
433  * when the last link is removed, the link will be removed before
434  * unlink() returns, but the removal of the file contents will be
435  * postponed until all references to the files are closed.
436  *
437  * JFS does NOT support unlink() on directories.
438  *
439  */
440 int jfs_unlink(struct inode *dip, struct dentry *dentry)
441 {
442         int rc;
443         tid_t tid;              /* transaction id */
444         struct inode *ip = dentry->d_inode;
445         ino_t ino;
446         struct component_name dname;    /* object name */
447         struct inode *iplist[2];
448         struct tblock *tblk;
449         s64 new_size = 0;
450         int commit_flag;
451
452         jfs_info("jfs_unlink: dip:0x%p name:%s", dip, dentry->d_name.name);
453
454         if ((rc = get_UCSname(&dname, dentry)))
455                 goto out;
456
457         IWRITE_LOCK(ip);
458
459         tid = txBegin(dip->i_sb, 0);
460
461         down(&JFS_IP(dip)->commit_sem);
462         down(&JFS_IP(ip)->commit_sem);
463
464         iplist[0] = dip;
465         iplist[1] = ip;
466
467         /*
468          * delete the entry of target file from parent directory
469          */
470         ino = ip->i_ino;
471         if ((rc = dtDelete(tid, dip, &dname, &ino, JFS_REMOVE))) {
472                 jfs_err("jfs_unlink: dtDelete returned %d", rc);
473                 if (rc == -EIO)
474                         txAbort(tid, 1);        /* Marks FS Dirty */
475                 txEnd(tid);
476                 up(&JFS_IP(dip)->commit_sem);
477                 up(&JFS_IP(ip)->commit_sem);
478                 IWRITE_UNLOCK(ip);
479                 goto out1;
480         }
481
482         ASSERT(ip->i_nlink);
483
484         ip->i_ctime = dip->i_ctime = dip->i_mtime = CURRENT_TIME;
485         mark_inode_dirty(dip);
486
487         /* update target's inode */
488         ip->i_nlink--;
489         mark_inode_dirty(ip);
490
491         /*
492          *      commit zero link count object
493          */
494         if (ip->i_nlink == 0) {
495                 assert(!test_cflag(COMMIT_Nolink, ip));
496                 /* free block resources */
497                 if ((new_size = commitZeroLink(tid, ip)) < 0) {
498                         txAbort(tid, 1);        /* Marks FS Dirty */
499                         txEnd(tid);
500                         up(&JFS_IP(dip)->commit_sem);
501                         up(&JFS_IP(ip)->commit_sem);
502                         IWRITE_UNLOCK(ip);
503                         rc = new_size;
504                         goto out1;
505                 }
506                 tblk = tid_to_tblock(tid);
507                 tblk->xflag |= COMMIT_DELETE;
508                 tblk->ip = ip;
509         }
510
511         /*
512          * Incomplete truncate of file data can
513          * result in timing problems unless we synchronously commit the
514          * transaction.
515          */
516         if (new_size)
517                 commit_flag = COMMIT_SYNC;
518         else
519                 commit_flag = 0;
520
521         /*
522          * If xtTruncate was incomplete, commit synchronously to avoid
523          * timing complications
524          */
525         rc = txCommit(tid, 2, &iplist[0], commit_flag);
526
527         txEnd(tid);
528
529         up(&JFS_IP(dip)->commit_sem);
530         up(&JFS_IP(ip)->commit_sem);
531
532
533         while (new_size && (rc == 0)) {
534                 tid = txBegin(dip->i_sb, 0);
535                 down(&JFS_IP(ip)->commit_sem);
536                 new_size = xtTruncate_pmap(tid, ip, new_size);
537                 if (new_size < 0) {
538                         txAbort(tid, 1);        /* Marks FS Dirty */
539                         rc = new_size;
540                 } else
541                         rc = txCommit(tid, 2, &iplist[0], COMMIT_SYNC);
542                 txEnd(tid);
543                 up(&JFS_IP(ip)->commit_sem);
544         }
545
546         if (ip->i_nlink == 0)
547                 set_cflag(COMMIT_Nolink, ip);
548
549         IWRITE_UNLOCK(ip);
550
551         /*
552          * Truncating the directory index table is not guaranteed.  It
553          * may need to be done iteratively
554          */
555         if (test_cflag(COMMIT_Stale, dip)) {
556                 if (dip->i_size > 1)
557                         jfs_truncate_nolock(dip, 0);
558
559                 clear_cflag(COMMIT_Stale, dip);
560         }
561
562       out1:
563         free_UCSname(&dname);
564       out:
565         jfs_info("jfs_unlink: rc:%d", rc);
566         return rc;
567 }
568
569 /*
570  * NAME:        commitZeroLink()
571  *
572  * FUNCTION:    for non-directory, called by jfs_remove(),
573  *              truncate a regular file, directory or symbolic
574  *              link to zero length. return 0 if type is not 
575  *              one of these.
576  *
577  *              if the file is currently associated with a VM segment
578  *              only permanent disk and inode map resources are freed,
579  *              and neither the inode nor indirect blocks are modified
580  *              so that the resources can be later freed in the work
581  *              map by ctrunc1.
582  *              if there is no VM segment on entry, the resources are
583  *              freed in both work and permanent map.
584  *              (? for temporary file - memory object is cached even 
585  *              after no reference:
586  *              reference count > 0 -   )
587  *
588  * PARAMETERS:  cd      - pointer to commit data structure.
589  *                        current inode is the one to truncate.
590  *
591  * RETURN:      Errors from subroutines
592  */
593 s64 commitZeroLink(tid_t tid, struct inode *ip)
594 {
595         int filetype;
596         struct tblock *tblk;
597
598         jfs_info("commitZeroLink: tid = %d, ip = 0x%p", tid, ip);
599
600         filetype = ip->i_mode & S_IFMT;
601         switch (filetype) {
602         case S_IFREG:
603                 break;
604         case S_IFLNK:
605                 /* fast symbolic link */
606                 if (ip->i_size < IDATASIZE) {
607                         ip->i_size = 0;
608                         return 0;
609                 }
610                 break;
611         default:
612                 assert(filetype != S_IFDIR);
613                 return 0;
614         }
615
616         set_cflag(COMMIT_Freewmap, ip);
617
618         /* mark transaction of block map update type */
619         tblk = tid_to_tblock(tid);
620         tblk->xflag |= COMMIT_PMAP;
621
622         /*
623          * free EA
624          */
625         if (JFS_IP(ip)->ea.flag & DXD_EXTENT)
626                 /* acquire maplock on EA to be freed from block map */
627                 txEA(tid, ip, &JFS_IP(ip)->ea, NULL);
628
629         /*
630          * free ACL
631          */
632         if (JFS_IP(ip)->acl.flag & DXD_EXTENT)
633                 /* acquire maplock on EA to be freed from block map */
634                 txEA(tid, ip, &JFS_IP(ip)->acl, NULL);
635
636         /*
637          * free xtree/data (truncate to zero length):
638          * free xtree/data pages from cache if COMMIT_PWMAP, 
639          * free xtree/data blocks from persistent block map, and
640          * free xtree/data blocks from working block map if COMMIT_PWMAP;
641          */
642         if (ip->i_size)
643                 return xtTruncate_pmap(tid, ip, 0);
644
645         return 0;
646 }
647
648
649 /*
650  * NAME:        freeZeroLink()
651  *
652  * FUNCTION:    for non-directory, called by iClose(),
653  *              free resources of a file from cache and WORKING map 
654  *              for a file previously committed with zero link count
655  *              while associated with a pager object,
656  *
657  * PARAMETER:   ip      - pointer to inode of file.
658  *
659  * RETURN:      0 -ok
660  */
661 int freeZeroLink(struct inode *ip)
662 {
663         int rc = 0;
664         int type;
665
666         jfs_info("freeZeroLink: ip = 0x%p", ip);
667
668         /* return if not reg or symbolic link or if size is
669          * already ok.
670          */
671         type = ip->i_mode & S_IFMT;
672
673         switch (type) {
674         case S_IFREG:
675                 break;
676         case S_IFLNK:
677                 /* if its contained in inode nothing to do */
678                 if (ip->i_size < IDATASIZE)
679                         return 0;
680                 break;
681         default:
682                 return 0;
683         }
684
685         /*
686          * free EA
687          */
688         if (JFS_IP(ip)->ea.flag & DXD_EXTENT) {
689                 s64 xaddr = addressDXD(&JFS_IP(ip)->ea);
690                 int xlen = lengthDXD(&JFS_IP(ip)->ea);
691                 struct maplock maplock; /* maplock for COMMIT_WMAP */
692                 struct pxd_lock *pxdlock;       /* maplock for COMMIT_WMAP */
693
694                 /* free EA pages from cache */
695                 invalidate_dxd_metapages(ip, JFS_IP(ip)->ea);
696
697                 /* free EA extent from working block map */
698                 maplock.index = 1;
699                 pxdlock = (struct pxd_lock *) & maplock;
700                 pxdlock->flag = mlckFREEPXD;
701                 PXDaddress(&pxdlock->pxd, xaddr);
702                 PXDlength(&pxdlock->pxd, xlen);
703                 txFreeMap(ip, pxdlock, 0, COMMIT_WMAP);
704         }
705
706         /*
707          * free ACL
708          */
709         if (JFS_IP(ip)->acl.flag & DXD_EXTENT) {
710                 s64 xaddr = addressDXD(&JFS_IP(ip)->acl);
711                 int xlen = lengthDXD(&JFS_IP(ip)->acl);
712                 struct maplock maplock; /* maplock for COMMIT_WMAP */
713                 struct pxd_lock *pxdlock;       /* maplock for COMMIT_WMAP */
714
715                 invalidate_dxd_metapages(ip, JFS_IP(ip)->acl);
716
717                 /* free ACL extent from working block map */
718                 maplock.index = 1;
719                 pxdlock = (struct pxd_lock *) & maplock;
720                 pxdlock->flag = mlckFREEPXD;
721                 PXDaddress(&pxdlock->pxd, xaddr);
722                 PXDlength(&pxdlock->pxd, xlen);
723                 txFreeMap(ip, pxdlock, 0, COMMIT_WMAP);
724         }
725
726         /*
727          * free xtree/data (truncate to zero length):
728          * free xtree/data pages from cache, and
729          * free xtree/data blocks from working block map;
730          */
731         if (ip->i_size)
732                 rc = xtTruncate(0, ip, 0, COMMIT_WMAP);
733
734         return rc;
735 }
736
737 /*
738  * NAME:        jfs_link(vp, dvp, name, crp)
739  *
740  * FUNCTION:    create a link to <vp> by the name = <name>
741  *              in the parent directory <dvp>
742  *
743  * PARAMETER:   vp      - target object
744  *              dvp     - parent directory of new link
745  *              name    - name of new link to target object
746  *              crp     - credential
747  *
748  * RETURN:      Errors from subroutines
749  *
750  * note:
751  * JFS does NOT support link() on directories (to prevent circular
752  * path in the directory hierarchy);
753  * EPERM: the target object is a directory, and either the caller
754  * does not have appropriate privileges or the implementation prohibits
755  * using link() on directories [XPG4.2].
756  *
757  * JFS does NOT support links between file systems:
758  * EXDEV: target object and new link are on different file systems and
759  * implementation does not support links between file systems [XPG4.2].
760  */
761 int jfs_link(struct dentry *old_dentry,
762              struct inode *dir, struct dentry *dentry)
763 {
764         int rc;
765         tid_t tid;
766         struct inode *ip = old_dentry->d_inode;
767         ino_t ino;
768         struct component_name dname;
769         struct btstack btstack;
770         struct inode *iplist[2];
771
772         jfs_info("jfs_link: %s %s", old_dentry->d_name.name,
773                  dentry->d_name.name);
774
775         if (ip->i_nlink == JFS_LINK_MAX)
776                 return -EMLINK;
777
778         if (ip->i_nlink == 0)
779                 return -ENOENT;
780
781         tid = txBegin(ip->i_sb, 0);
782
783         down(&JFS_IP(dir)->commit_sem);
784         down(&JFS_IP(ip)->commit_sem);
785
786         /*
787          * scan parent directory for entry/freespace
788          */
789         if ((rc = get_UCSname(&dname, dentry)))
790                 goto out;
791
792         if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE)))
793                 goto out;
794
795         /*
796          * create entry for new link in parent directory
797          */
798         ino = ip->i_ino;
799         if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack)))
800                 goto out;
801
802         /* update object inode */
803         ip->i_nlink++;          /* for new link */
804         ip->i_ctime = CURRENT_TIME;
805         mark_inode_dirty(dir);
806         atomic_inc(&ip->i_count);
807         d_instantiate(dentry, ip);
808
809         iplist[0] = ip;
810         iplist[1] = dir;
811         rc = txCommit(tid, 2, &iplist[0], 0);
812
813       out:
814         txEnd(tid);
815
816         up(&JFS_IP(dir)->commit_sem);
817         up(&JFS_IP(ip)->commit_sem);
818
819         jfs_info("jfs_link: rc:%d", rc);
820         return rc;
821 }
822
823 /*
824  * NAME:        jfs_symlink(dip, dentry, name)
825  *
826  * FUNCTION:    creates a symbolic link to <symlink> by name <name>
827  *                      in directory <dip>
828  *
829  * PARAMETER:   dip         - parent directory vnode
830  *                      dentry  - dentry of symbolic link
831  *                      name    - the path name of the existing object 
832  *                                    that will be the source of the link
833  *
834  * RETURN:      errors from subroutines
835  *
836  * note:
837  * ENAMETOOLONG: pathname resolution of a symbolic link produced
838  * an intermediate result whose length exceeds PATH_MAX [XPG4.2]
839 */
840
841 int jfs_symlink(struct inode *dip, struct dentry *dentry, const char *name)
842 {
843         int rc;
844         tid_t tid;
845         ino_t ino = 0;
846         struct component_name dname;
847         int ssize;              /* source pathname size */
848         struct btstack btstack;
849         struct inode *ip = dentry->d_inode;
850         unchar *i_fastsymlink;
851         s64 xlen = 0;
852         int bmask = 0, xsize;
853         s64 xaddr;
854         struct metapage *mp;
855         struct super_block *sb;
856         struct tblock *tblk;
857
858         struct inode *iplist[2];
859
860         jfs_info("jfs_symlink: dip:0x%p name:%s", dip, name);
861
862         ssize = strlen(name) + 1;
863
864         /*
865          * search parent directory for entry/freespace
866          * (dtSearch() returns parent directory page pinned)
867          */
868
869         if ((rc = get_UCSname(&dname, dentry)))
870                 goto out1;
871
872         /*
873          * allocate on-disk/in-memory inode for symbolic link:
874          * (iAlloc() returns new, locked inode)
875          */
876         ip = ialloc(dip, S_IFLNK | 0777);
877         if (ip == NULL) {
878                 rc = -ENOSPC;
879                 goto out2;
880         }
881
882         tid = txBegin(dip->i_sb, 0);
883
884         down(&JFS_IP(dip)->commit_sem);
885         down(&JFS_IP(ip)->commit_sem);
886
887         if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE)))
888                 goto out3;
889
890         tblk = tid_to_tblock(tid);
891         tblk->xflag |= COMMIT_CREATE;
892         tblk->ip = ip;
893
894         /*
895          * create entry for symbolic link in parent directory
896          */
897
898         ino = ip->i_ino;
899
900
901
902         if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {
903                 jfs_err("jfs_symlink: dtInsert returned %d", rc);
904                 /* discard ne inode */
905                 goto out3;
906
907         }
908
909         /* fix symlink access permission
910          * (dir_create() ANDs in the u.u_cmask, 
911          * but symlinks really need to be 777 access)
912          */
913         ip->i_mode |= 0777;
914
915         /*
916            *       write symbolic link target path name
917          */
918         xtInitRoot(tid, ip);
919
920         /*
921          * write source path name inline in on-disk inode (fast symbolic link)
922          */
923
924         if (ssize <= IDATASIZE) {
925                 ip->i_op = &jfs_symlink_inode_operations;
926
927                 i_fastsymlink = JFS_IP(ip)->i_inline;
928                 memcpy(i_fastsymlink, name, ssize);
929                 ip->i_size = ssize - 1;
930
931                 /*
932                  * if symlink is > 128 bytes, we don't have the space to
933                  * store inline extended attributes
934                  */
935                 if (ssize > sizeof (JFS_IP(ip)->i_inline))
936                         JFS_IP(ip)->mode2 &= ~INLINEEA;
937
938                 jfs_info("jfs_symlink: fast symlink added  ssize:%d name:%s ",
939                          ssize, name);
940         }
941         /*
942          * write source path name in a single extent
943          */
944         else {
945                 jfs_info("jfs_symlink: allocate extent ip:0x%p", ip);
946
947                 ip->i_op = &page_symlink_inode_operations;
948                 ip->i_mapping->a_ops = &jfs_aops;
949
950                 /*
951                  * even though the data of symlink object (source 
952                  * path name) is treated as non-journaled user data,
953                  * it is read/written thru buffer cache for performance.
954                  */
955                 sb = ip->i_sb;
956                 bmask = JFS_SBI(sb)->bsize - 1;
957                 xsize = (ssize + bmask) & ~bmask;
958                 xaddr = 0;
959                 xlen = xsize >> JFS_SBI(sb)->l2bsize;
960                 if ((rc = xtInsert(tid, ip, 0, 0, xlen, &xaddr, 0)) == 0) {
961                         ip->i_size = ssize - 1;
962                         while (ssize) {
963                                 int copy_size = min(ssize, PSIZE);
964
965                                 mp = get_metapage(ip, xaddr, PSIZE, 1);
966
967                                 if (mp == NULL) {
968                                         dtDelete(tid, dip, &dname, &ino,
969                                                  JFS_REMOVE);
970                                         rc = -EIO;
971                                         goto out3;
972                                 }
973                                 memcpy(mp->data, name, copy_size);
974                                 flush_metapage(mp);
975 #if 0
976                                 set_buffer_uptodate(bp);
977                                 mark_buffer_dirty(bp, 1);
978                                 if (IS_SYNC(dip))
979                                         sync_dirty_buffer(bp);
980                                 brelse(bp);
981 #endif                          /* 0 */
982                                 ssize -= copy_size;
983                                 xaddr += JFS_SBI(sb)->nbperpage;
984                         }
985                         ip->i_blocks = LBLK2PBLK(sb, xlen);
986                 } else {
987                         dtDelete(tid, dip, &dname, &ino, JFS_REMOVE);
988                         rc = -ENOSPC;
989                         goto out3;
990                 }
991         }
992
993         insert_inode_hash(ip);
994         mark_inode_dirty(ip);
995         d_instantiate(dentry, ip);
996
997         /*
998          * commit update of parent directory and link object
999          *
1000          * if extent allocation failed (ENOSPC),
1001          * the parent inode is committed regardless to avoid
1002          * backing out parent directory update (by dtInsert())
1003          * and subsequent dtDelete() which is harmless wrt 
1004          * integrity concern.  
1005          * the symlink inode will be freed by iput() at exit
1006          * as it has a zero link count (by dtDelete()) and 
1007          * no permanant resources. 
1008          */
1009
1010         iplist[0] = dip;
1011         if (rc == 0) {
1012                 iplist[1] = ip;
1013                 rc = txCommit(tid, 2, &iplist[0], 0);
1014         } else
1015                 rc = txCommit(tid, 1, &iplist[0], 0);
1016
1017       out3:
1018         txEnd(tid);
1019         up(&JFS_IP(dip)->commit_sem);
1020         up(&JFS_IP(ip)->commit_sem);
1021         if (rc) {
1022                 ip->i_nlink = 0;
1023                 iput(ip);
1024         }
1025
1026       out2:
1027         free_UCSname(&dname);
1028
1029 #ifdef CONFIG_JFS_POSIX_ACL
1030         if (rc == 0)
1031                 jfs_init_acl(ip, dip);
1032 #endif
1033
1034       out1:
1035         jfs_info("jfs_symlink: rc:%d", rc);
1036         return rc;
1037 }
1038
1039
1040 /*
1041  * NAME:        jfs_rename
1042  *
1043  * FUNCTION:    rename a file or directory
1044  */
1045 int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
1046                struct inode *new_dir, struct dentry *new_dentry)
1047 {
1048         struct btstack btstack;
1049         ino_t ino;
1050         struct component_name new_dname;
1051         struct inode *new_ip;
1052         struct component_name old_dname;
1053         struct inode *old_ip;
1054         int rc;
1055         tid_t tid;
1056         struct tlock *tlck;
1057         struct dt_lock *dtlck;
1058         struct lv *lv;
1059         int ipcount;
1060         struct inode *iplist[4];
1061         struct tblock *tblk;
1062         s64 new_size = 0;
1063         int commit_flag;
1064
1065
1066         jfs_info("jfs_rename: %s %s", old_dentry->d_name.name,
1067                  new_dentry->d_name.name);
1068
1069         old_ip = old_dentry->d_inode;
1070         new_ip = new_dentry->d_inode;
1071
1072         if ((rc = get_UCSname(&old_dname, old_dentry)))
1073                 goto out1;
1074
1075         if ((rc = get_UCSname(&new_dname, new_dentry)))
1076                 goto out2;
1077
1078         /*
1079          * Make sure source inode number is what we think it is
1080          */
1081         rc = dtSearch(old_dir, &old_dname, &ino, &btstack, JFS_LOOKUP);
1082         if (rc || (ino != old_ip->i_ino)) {
1083                 rc = -ENOENT;
1084                 goto out3;
1085         }
1086
1087         /*
1088          * Make sure dest inode number (if any) is what we think it is
1089          */
1090         rc = dtSearch(new_dir, &new_dname, &ino, &btstack, JFS_LOOKUP);
1091         if (rc == 0) {
1092                 if ((new_ip == 0) || (ino != new_ip->i_ino)) {
1093                         rc = -ESTALE;
1094                         goto out3;
1095                 }
1096         } else if (rc != -ENOENT)
1097                 goto out3;
1098         else if (new_ip) {
1099                 /* no entry exists, but one was expected */
1100                 rc = -ESTALE;
1101                 goto out3;
1102         }
1103
1104         if (S_ISDIR(old_ip->i_mode)) {
1105                 if (new_ip) {
1106                         if (!dtEmpty(new_ip)) {
1107                                 rc = -ENOTEMPTY;
1108                                 goto out3;
1109                         }
1110                 } else if ((new_dir != old_dir) &&
1111                            (new_dir->i_nlink == JFS_LINK_MAX)) {
1112                         rc = -EMLINK;
1113                         goto out3;
1114                 }
1115         } else if (new_ip)
1116                 IWRITE_LOCK(new_ip);
1117
1118         /*
1119          * The real work starts here
1120          */
1121         tid = txBegin(new_dir->i_sb, 0);
1122
1123         down(&JFS_IP(new_dir)->commit_sem);
1124         down(&JFS_IP(old_ip)->commit_sem);
1125         if (old_dir != new_dir)
1126                 down(&JFS_IP(old_dir)->commit_sem);
1127
1128         if (new_ip) {
1129                 down(&JFS_IP(new_ip)->commit_sem);
1130                 /*
1131                  * Change existing directory entry to new inode number
1132                  */
1133                 ino = new_ip->i_ino;
1134                 rc = dtModify(tid, new_dir, &new_dname, &ino,
1135                               old_ip->i_ino, JFS_RENAME);
1136                 if (rc)
1137                         goto out4;
1138                 new_ip->i_nlink--;
1139                 if (S_ISDIR(new_ip->i_mode)) {
1140                         new_ip->i_nlink--;
1141                         if (new_ip->i_nlink) {
1142                                 up(&JFS_IP(new_dir)->commit_sem);
1143                                 up(&JFS_IP(old_ip)->commit_sem);
1144                                 if (old_dir != new_dir)
1145                                         up(&JFS_IP(old_dir)->commit_sem);
1146                                 if (!S_ISDIR(old_ip->i_mode) && new_ip)
1147                                         IWRITE_UNLOCK(new_ip);
1148                                 jfs_error(new_ip->i_sb,
1149                                           "jfs_rename: new_ip->i_nlink != 0");
1150                                 return -EIO;
1151                         }
1152                         tblk = tid_to_tblock(tid);
1153                         tblk->xflag |= COMMIT_DELETE;
1154                         tblk->ip = new_ip;
1155                 } else if (new_ip->i_nlink == 0) {
1156                         assert(!test_cflag(COMMIT_Nolink, new_ip));
1157                         /* free block resources */
1158                         if ((new_size = commitZeroLink(tid, new_ip)) < 0) {
1159                                 txAbort(tid, 1);        /* Marks FS Dirty */
1160                                 rc = new_size;          
1161                                 goto out4;
1162                         }
1163                         tblk = tid_to_tblock(tid);
1164                         tblk->xflag |= COMMIT_DELETE;
1165                         tblk->ip = new_ip;
1166                 } else {
1167                         new_ip->i_ctime = CURRENT_TIME;
1168                         mark_inode_dirty(new_ip);
1169                 }
1170         } else {
1171                 /*
1172                  * Add new directory entry
1173                  */
1174                 rc = dtSearch(new_dir, &new_dname, &ino, &btstack,
1175                               JFS_CREATE);
1176                 if (rc) {
1177                         jfs_err("jfs_rename didn't expect dtSearch to fail "
1178                                 "w/rc = %d", rc);
1179                         goto out4;
1180                 }
1181
1182                 ino = old_ip->i_ino;
1183                 rc = dtInsert(tid, new_dir, &new_dname, &ino, &btstack);
1184                 if (rc) {
1185                         jfs_err("jfs_rename: dtInsert failed w/rc = %d",
1186                                 rc);
1187                         goto out4;
1188                 }
1189                 if (S_ISDIR(old_ip->i_mode))
1190                         new_dir->i_nlink++;
1191         }
1192         /*
1193          * Remove old directory entry
1194          */
1195
1196         ino = old_ip->i_ino;
1197         rc = dtDelete(tid, old_dir, &old_dname, &ino, JFS_REMOVE);
1198         if (rc) {
1199                 jfs_err("jfs_rename did not expect dtDelete to return rc = %d",
1200                         rc);
1201                 txAbort(tid, 1);        /* Marks Filesystem dirty */
1202                 goto out4;
1203         }
1204         if (S_ISDIR(old_ip->i_mode)) {
1205                 old_dir->i_nlink--;
1206                 if (old_dir != new_dir) {
1207                         /*
1208                          * Change inode number of parent for moved directory
1209                          */
1210
1211                         JFS_IP(old_ip)->i_dtroot.header.idotdot =
1212                                 cpu_to_le32(new_dir->i_ino);
1213
1214                         /* Linelock header of dtree */
1215                         tlck = txLock(tid, old_ip,
1216                                     (struct metapage *) &JFS_IP(old_ip)->bxflag,
1217                                       tlckDTREE | tlckBTROOT);
1218                         dtlck = (struct dt_lock *) & tlck->lock;
1219                         ASSERT(dtlck->index == 0);
1220                         lv = & dtlck->lv[0];
1221                         lv->offset = 0;
1222                         lv->length = 1;
1223                         dtlck->index++;
1224                 }
1225         }
1226
1227         /*
1228          * Update ctime on changed/moved inodes & mark dirty
1229          */
1230         old_ip->i_ctime = CURRENT_TIME;
1231         mark_inode_dirty(old_ip);
1232
1233         new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME;
1234         mark_inode_dirty(new_dir);
1235
1236         /* Build list of inodes modified by this transaction */
1237         ipcount = 0;
1238         iplist[ipcount++] = old_ip;
1239         if (new_ip)
1240                 iplist[ipcount++] = new_ip;
1241         iplist[ipcount++] = old_dir;
1242
1243         if (old_dir != new_dir) {
1244                 iplist[ipcount++] = new_dir;
1245                 old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
1246                 mark_inode_dirty(old_dir);
1247         }
1248
1249         /*
1250          * Incomplete truncate of file data can
1251          * result in timing problems unless we synchronously commit the
1252          * transaction.
1253          */
1254         if (new_size)
1255                 commit_flag = COMMIT_SYNC;
1256         else
1257                 commit_flag = 0;
1258
1259         rc = txCommit(tid, ipcount, iplist, commit_flag);
1260
1261       out4:
1262         txEnd(tid);
1263
1264         up(&JFS_IP(new_dir)->commit_sem);
1265         up(&JFS_IP(old_ip)->commit_sem);
1266         if (old_dir != new_dir)
1267                 up(&JFS_IP(old_dir)->commit_sem);
1268         if (new_ip)
1269                 up(&JFS_IP(new_ip)->commit_sem);
1270
1271         while (new_size && (rc == 0)) {
1272                 tid = txBegin(new_ip->i_sb, 0);
1273                 down(&JFS_IP(new_ip)->commit_sem);
1274                 new_size = xtTruncate_pmap(tid, new_ip, new_size);
1275                 if (new_size < 0) {
1276                         txAbort(tid, 1);
1277                         rc = new_size;          
1278                 } else
1279                         rc = txCommit(tid, 1, &new_ip, COMMIT_SYNC);
1280                 txEnd(tid);
1281                 up(&JFS_IP(new_ip)->commit_sem);
1282         }
1283         if (new_ip && (new_ip->i_nlink == 0))
1284                 set_cflag(COMMIT_Nolink, new_ip);
1285       out3:
1286         free_UCSname(&new_dname);
1287       out2:
1288         free_UCSname(&old_dname);
1289       out1:
1290         if (new_ip && !S_ISDIR(new_ip->i_mode))
1291                 IWRITE_UNLOCK(new_ip);
1292         /*
1293          * Truncating the directory index table is not guaranteed.  It
1294          * may need to be done iteratively
1295          */
1296         if (test_cflag(COMMIT_Stale, old_dir)) {
1297                 if (old_dir->i_size > 1)
1298                         jfs_truncate_nolock(old_dir, 0);
1299
1300                 clear_cflag(COMMIT_Stale, old_dir);
1301         }
1302
1303         jfs_info("jfs_rename: returning %d", rc);
1304         return rc;
1305 }
1306
1307
1308 /*
1309  * NAME:        jfs_mknod
1310  *
1311  * FUNCTION:    Create a special file (device)
1312  */
1313 int jfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
1314 {
1315         struct jfs_inode_info *jfs_ip;
1316         struct btstack btstack;
1317         struct component_name dname;
1318         ino_t ino;
1319         struct inode *ip;
1320         struct inode *iplist[2];
1321         int rc;
1322         tid_t tid;
1323         struct tblock *tblk;
1324
1325         if (!new_valid_dev(rdev))
1326                 return -EINVAL;
1327
1328         jfs_info("jfs_mknod: %s", dentry->d_name.name);
1329
1330         if ((rc = get_UCSname(&dname, dentry)))
1331                 goto out;
1332
1333         ip = ialloc(dir, mode);
1334         if (ip == NULL) {
1335                 rc = -ENOSPC;
1336                 goto out1;
1337         }
1338         jfs_ip = JFS_IP(ip);
1339
1340         tid = txBegin(dir->i_sb, 0);
1341
1342         down(&JFS_IP(dir)->commit_sem);
1343         down(&JFS_IP(ip)->commit_sem);
1344
1345         if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE)))
1346                 goto out3;
1347
1348         tblk = tid_to_tblock(tid);
1349         tblk->xflag |= COMMIT_CREATE;
1350         tblk->ip = ip;
1351
1352         ino = ip->i_ino;
1353         if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack)))
1354                 goto out3;
1355
1356         ip->i_op = &jfs_file_inode_operations;
1357         jfs_ip->dev = new_encode_dev(rdev);
1358         init_special_inode(ip, ip->i_mode, rdev);
1359
1360         insert_inode_hash(ip);
1361         mark_inode_dirty(ip);
1362         d_instantiate(dentry, ip);
1363
1364         dir->i_ctime = dir->i_mtime = CURRENT_TIME;
1365
1366         mark_inode_dirty(dir);
1367
1368         iplist[0] = dir;
1369         iplist[1] = ip;
1370         rc = txCommit(tid, 2, iplist, 0);
1371
1372       out3:
1373         txEnd(tid);
1374         up(&JFS_IP(ip)->commit_sem);
1375         up(&JFS_IP(dir)->commit_sem);
1376         if (rc) {
1377                 ip->i_nlink = 0;
1378                 iput(ip);
1379         }
1380
1381       out1:
1382         free_UCSname(&dname);
1383
1384 #ifdef CONFIG_JFS_POSIX_ACL
1385         if (rc == 0)
1386                 jfs_init_acl(ip, dir);
1387 #endif
1388
1389       out:
1390         jfs_info("jfs_mknod: returning %d", rc);
1391         return rc;
1392 }
1393
1394 static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struct nameidata *nd)
1395 {
1396         struct btstack btstack;
1397         ino_t inum;
1398         struct inode *ip;
1399         struct component_name key;
1400         const char *name = dentry->d_name.name;
1401         int len = dentry->d_name.len;
1402         int rc;
1403
1404         jfs_info("jfs_lookup: name = %s", name);
1405
1406
1407         if ((name[0] == '.') && (len == 1))
1408                 inum = dip->i_ino;
1409         else if (strcmp(name, "..") == 0)
1410                 inum = PARENT(dip);
1411         else {
1412                 if ((rc = get_UCSname(&key, dentry)))
1413                         return ERR_PTR(rc);
1414                 rc = dtSearch(dip, &key, &inum, &btstack, JFS_LOOKUP);
1415                 free_UCSname(&key);
1416                 if (rc == -ENOENT) {
1417                         d_add(dentry, NULL);
1418                         return ERR_PTR(0);
1419                 } else if (rc) {
1420                         jfs_err("jfs_lookup: dtSearch returned %d", rc);
1421                         return ERR_PTR(rc);
1422                 }
1423         }
1424
1425         ip = iget(dip->i_sb, inum);
1426         if (ip == NULL || is_bad_inode(ip)) {
1427                 jfs_err("jfs_lookup: iget failed on inum %d", (uint) inum);
1428                 if (ip)
1429                         iput(ip);
1430                 return ERR_PTR(-EACCES);
1431         }
1432
1433         return d_splice_alias(ip, dentry);
1434 }
1435
1436 struct dentry *jfs_get_parent(struct dentry *dentry)
1437 {
1438         struct super_block *sb = dentry->d_inode->i_sb;
1439         struct dentry *parent = ERR_PTR(-ENOENT);
1440         struct inode *inode;
1441         unsigned long parent_ino;
1442
1443         parent_ino =
1444                 le32_to_cpu(JFS_IP(dentry->d_inode)->i_dtroot.header.idotdot);
1445         inode = iget(sb, parent_ino);
1446         if (inode) {
1447                 if (is_bad_inode(inode)) {
1448                         iput(inode);
1449                         parent = ERR_PTR(-EACCES);
1450                 } else {
1451                         parent = d_alloc_anon(inode);
1452                         if (!parent) {
1453                                 parent = ERR_PTR(-ENOMEM);
1454                                 iput(inode);
1455                         }
1456                 }
1457         }
1458
1459         return parent;
1460 }
1461
1462 struct inode_operations jfs_dir_inode_operations = {
1463         .create         = jfs_create,
1464         .lookup         = jfs_lookup,
1465         .link           = jfs_link,
1466         .unlink         = jfs_unlink,
1467         .symlink        = jfs_symlink,
1468         .mkdir          = jfs_mkdir,
1469         .rmdir          = jfs_rmdir,
1470         .mknod          = jfs_mknod,
1471         .rename         = jfs_rename,
1472         .setxattr       = jfs_setxattr,
1473         .getxattr       = jfs_getxattr,
1474         .listxattr      = jfs_listxattr,
1475         .removexattr    = jfs_removexattr,
1476 #ifdef CONFIG_JFS_POSIX_ACL
1477         .setattr        = jfs_setattr,
1478         .permission     = jfs_permission,
1479 #endif
1480 };
1481
1482 struct file_operations jfs_dir_operations = {
1483         .read           = generic_read_dir,
1484         .readdir        = jfs_readdir,
1485         .fsync          = jfs_fsync,
1486 };