File: /usr/src/linux/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 = bread(sys_mdb->s_dev, block, HFS_SECTOR_SIZE);
45     	} else {
46     		tmp = getblk(sys_mdb->s_dev, block, HFS_SECTOR_SIZE);
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     }
110