import of ftp.dlink.com/GPL/DSMG-600_reB/ppclinux.tar.gz
[linux-2.4.21-pre4.git] / fs / hfs / sysdep.c
1 /*
2  * linux/fs/hfs/sysdep.c
3  *
4  * Copyright (C) 1996  Paul H. Hargrove
5  * This file may be distributed under the terms of the GNU General Public License.
6  *
7  * This file contains the code to do various system dependent things.
8  *
9  * "XXX" in a comment is a note to myself to consider changing something.
10  *
11  * In function preconditions the term "valid" applied to a pointer to
12  * a structure means that the pointer is non-NULL and the structure it
13  * points to has all fields initialized to consistent values.
14  */
15
16 #include "hfs.h"
17 #include <linux/hfs_fs_sb.h>
18 #include <linux/hfs_fs_i.h>
19 #include <linux/hfs_fs.h>
20 #include <linux/smp_lock.h>
21
22 static int hfs_revalidate_dentry(struct dentry *, int);
23 static int hfs_hash_dentry(struct dentry *, struct qstr *);
24 static int hfs_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
25 static void hfs_dentry_iput(struct dentry *, struct inode *);
26 struct dentry_operations hfs_dentry_operations =
27 {
28         d_revalidate:   hfs_revalidate_dentry,  
29         d_hash:         hfs_hash_dentry,
30         d_compare:      hfs_compare_dentry,
31         d_iput:         hfs_dentry_iput,
32 };
33
34 /*
35  * hfs_buffer_get()
36  *
37  * Return a buffer for the 'block'th block of the media.
38  * If ('read'==0) then the buffer is not read from disk.
39  */
40 hfs_buffer hfs_buffer_get(hfs_sysmdb sys_mdb, int block, int read) {
41         hfs_buffer tmp = HFS_BAD_BUFFER;
42
43         if (read) {
44                 tmp = sb_bread(sys_mdb, block);
45         } else {
46                 tmp = sb_getblk(sys_mdb, block);
47                 if (tmp) {
48                         mark_buffer_uptodate(tmp, 1);
49                 }
50         }
51         if (!tmp) {
52                 hfs_error("hfs_fs: unable to read block 0x%08x from dev %s\n",
53                           block, hfs_mdb_name(sys_mdb));
54         }
55
56         return tmp;
57 }
58
59 /* dentry case-handling: just lowercase everything */
60
61 /* hfs_strhash now uses the same hashing function as the dcache. */
62 static int hfs_hash_dentry(struct dentry *dentry, struct qstr *this)
63 {
64         if (this->len > HFS_NAMELEN)
65                 return 0;
66         
67         this->hash = hfs_strhash(this->name, this->len);
68         return 0;
69 }
70
71 /* return 1 on failure and 0 on success */
72 static int hfs_compare_dentry(struct dentry *dentry, struct qstr *a, 
73                               struct qstr *b)
74 {
75         if (a->len != b->len) return 1;
76
77         if (a->len > HFS_NAMELEN)
78           return 1;
79
80         return !hfs_streq(a->name, a->len, b->name, b->len);
81 }
82
83 static void hfs_dentry_iput(struct dentry *dentry, struct inode *inode)
84 {
85         struct hfs_cat_entry *entry = HFS_I(inode)->entry;
86
87         lock_kernel();
88         entry->sys_entry[HFS_ITYPE_TO_INT(HFS_ITYPE(inode->i_ino))] = NULL;
89         unlock_kernel();
90         iput(inode);
91 }
92
93 static int hfs_revalidate_dentry(struct dentry *dentry, int flags)
94 {
95         struct inode *inode = dentry->d_inode;
96         int diff;
97
98         /* fix up inode on a timezone change */
99         lock_kernel();
100         if (inode && 
101             (diff = (hfs_to_utc(0) - HFS_I(inode)->tz_secondswest))) {
102                 inode->i_ctime += diff;
103                 inode->i_atime += diff;
104                 inode->i_mtime += diff;
105                 HFS_I(inode)->tz_secondswest += diff;
106         }
107         unlock_kernel();
108         return 1;
109 }