1 |
199 |
simons |
/*
|
2 |
|
|
* linux/fs/ufs/ufs_inode.c
|
3 |
|
|
*
|
4 |
|
|
* Copyright (C) 1996
|
5 |
|
|
* Adrian Rodriguez (adrian@franklins-tower.rutgers.edu)
|
6 |
|
|
* Laboratory for Computer Science Research Computing Facility
|
7 |
|
|
* Rutgers, The State University of New Jersey
|
8 |
|
|
*
|
9 |
|
|
* $Id: ufs_inode.c,v 1.1.1.1 2001-09-10 07:44:40 simons Exp $
|
10 |
|
|
*
|
11 |
|
|
*/
|
12 |
|
|
|
13 |
|
|
#include <linux/fs.h>
|
14 |
|
|
#include <linux/ufs_fs.h>
|
15 |
|
|
#include <linux/sched.h>
|
16 |
|
|
|
17 |
|
|
extern struct inode_operations ufs_file_inode_operations;
|
18 |
|
|
extern struct inode_operations ufs_dir_inode_operations;
|
19 |
|
|
extern struct inode_operations ufs_symlink_inode_operations;
|
20 |
|
|
extern struct file_operations ufs_file_operations;
|
21 |
|
|
extern struct file_operations ufs_dir_operations;
|
22 |
|
|
extern struct file_operations ufs_symlink_operations;
|
23 |
|
|
|
24 |
|
|
void ufs_print_inode(struct inode * inode)
|
25 |
|
|
{
|
26 |
|
|
printk("ino %lu mode 0%6.6o lk %d uid %d gid %d sz %lu blks %lu cnt %lu\n",
|
27 |
|
|
inode->i_ino, inode->i_mode, inode->i_nlink, inode->i_uid, inode->i_gid, inode->i_size, inode->i_blocks, inode->i_count);
|
28 |
|
|
printk(" db <0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x>\n",
|
29 |
|
|
inode->u.ufs_i.ui_db[0], inode->u.ufs_i.ui_db[1],
|
30 |
|
|
inode->u.ufs_i.ui_db[2], inode->u.ufs_i.ui_db[3],
|
31 |
|
|
inode->u.ufs_i.ui_db[4], inode->u.ufs_i.ui_db[5],
|
32 |
|
|
inode->u.ufs_i.ui_db[6], inode->u.ufs_i.ui_db[7],
|
33 |
|
|
inode->u.ufs_i.ui_db[8], inode->u.ufs_i.ui_db[9],
|
34 |
|
|
inode->u.ufs_i.ui_db[10], inode->u.ufs_i.ui_db[11]);
|
35 |
|
|
printk(" gen 0x%8.8x ib <0x%x 0x%x 0x%x>\n",
|
36 |
|
|
inode->u.ufs_i.ui_gen, inode->u.ufs_i.ui_ib[0],
|
37 |
|
|
inode->u.ufs_i.ui_ib[1], inode->u.ufs_i.ui_ib[2]);
|
38 |
|
|
}
|
39 |
|
|
|
40 |
|
|
/* XXX - ufs_read_inode is a mess */
|
41 |
|
|
void ufs_read_inode(struct inode * inode)
|
42 |
|
|
{
|
43 |
|
|
struct super_block * sb;
|
44 |
|
|
struct ufs_inode * ufsip;
|
45 |
|
|
struct buffer_head * bh;
|
46 |
|
|
|
47 |
|
|
sb = inode->i_sb;
|
48 |
|
|
|
49 |
|
|
if (ufs_ino_ok(inode)) {
|
50 |
|
|
printk("ufs_read_inode: bad inum %lu", inode->i_ino);
|
51 |
|
|
|
52 |
|
|
return;
|
53 |
|
|
}
|
54 |
|
|
|
55 |
|
|
#if 0
|
56 |
|
|
printk("ufs_read_inode: ino %lu cg %u cgino %u ipg %u inopb %u\n",
|
57 |
|
|
inode->i_ino, ufs_ino2cg(inode),
|
58 |
|
|
(inode->i_ino%sb->u.ufs_sb.s_inopb),
|
59 |
|
|
sb->u.ufs_sb.s_ipg, sb->u.ufs_sb.s_inopb);
|
60 |
|
|
#endif
|
61 |
|
|
bh = bread(inode->i_dev,
|
62 |
|
|
ufs_cgimin(inode->i_sb, ufs_ino2cg(inode)) +
|
63 |
|
|
(inode->i_ino%sb->u.ufs_sb.s_ipg)/(sb->u.ufs_sb.s_inopb/sb->u.ufs_sb.s_fsfrag),
|
64 |
|
|
BLOCK_SIZE);
|
65 |
|
|
if (!bh) {
|
66 |
|
|
printk("ufs_read_inode: can't read inode %lu from dev %d/%d",
|
67 |
|
|
inode->i_ino, MAJOR(inode->i_dev), MINOR(inode->i_dev));
|
68 |
|
|
return;
|
69 |
|
|
}
|
70 |
|
|
|
71 |
|
|
ufsip = (struct ufs_inode *)bh->b_data;
|
72 |
|
|
ufsip += (inode->i_ino%(sb->u.ufs_sb.s_inopb/sb->u.ufs_sb.s_fsfrag));
|
73 |
|
|
|
74 |
|
|
/*
|
75 |
|
|
* Copy data to the in-core inode.
|
76 |
|
|
*/
|
77 |
|
|
inode->i_mode = ufsip->ui_mode;
|
78 |
|
|
inode->i_nlink = ufsip->ui_nlink;
|
79 |
|
|
if (inode->i_nlink == 0) {
|
80 |
|
|
/* XXX */
|
81 |
|
|
printk("ufs_read_inode: zero nlink ino %lu dev %u/%u\n",
|
82 |
|
|
inode->i_ino, MAJOR(inode->i_dev), MINOR(inode->i_dev));
|
83 |
|
|
inode->i_nlink = 1;
|
84 |
|
|
printk("ufs_read_inode: fishy ino %lu pblk %lu dev %u/%u\n",
|
85 |
|
|
inode->i_ino,
|
86 |
|
|
ufs_cgimin(inode->i_sb, ufs_ino2cg(inode)) +
|
87 |
|
|
(inode->i_ino%sb->u.ufs_sb.s_ipg)/sb->u.ufs_sb.s_inopb,
|
88 |
|
|
MAJOR(inode->i_dev), MINOR(inode->i_dev));
|
89 |
|
|
}
|
90 |
|
|
/* XXX - debugging */
|
91 |
|
|
if (ufsip->ui_gen == 0) {
|
92 |
|
|
printk("ufs_read_inode: zero gen ino %lu pblk %lu dev %u/%u\n",
|
93 |
|
|
inode->i_ino,
|
94 |
|
|
ufs_cgimin(inode->i_sb, ufs_ino2cg(inode)) +
|
95 |
|
|
(inode->i_ino%sb->u.ufs_sb.s_ipg)/sb->u.ufs_sb.s_inopb,
|
96 |
|
|
MAJOR(inode->i_dev), MINOR(inode->i_dev));
|
97 |
|
|
}
|
98 |
|
|
/*
|
99 |
|
|
* Since Linux currently only has 16-bit uid_t and gid_t, we can't
|
100 |
|
|
* really support EFTs. For the moment, we use 0 as the uid and gid
|
101 |
|
|
* if an inode has a uid or gid that won't fit in 16 bits. This way
|
102 |
|
|
* random users can't get at these files, since they get dynamically
|
103 |
|
|
* "chown()ed" to root.
|
104 |
|
|
*/
|
105 |
|
|
if (ufsip->ui_suid == UFS_USEEFT) {
|
106 |
|
|
/* EFT */
|
107 |
|
|
inode->i_uid = 0;
|
108 |
|
|
printk("ufs_read_inode: EFT uid %u ino %lu dev %u/%u, using %u\n",
|
109 |
|
|
ufsip->ui_uid, inode->i_ino, MAJOR(inode->i_dev), MINOR(inode->i_dev),
|
110 |
|
|
inode->i_uid);
|
111 |
|
|
} else {
|
112 |
|
|
inode->i_uid = ufsip->ui_suid;
|
113 |
|
|
}
|
114 |
|
|
if (ufsip->ui_suid == UFS_USEEFT) {
|
115 |
|
|
/* EFT */
|
116 |
|
|
inode->i_uid = 0;
|
117 |
|
|
printk("ufs_read_inode: EFT gid %u ino %lu dev %u/%u, using %u\n",
|
118 |
|
|
ufsip->ui_gid, inode->i_ino, MAJOR(inode->i_dev), MINOR(inode->i_dev),
|
119 |
|
|
inode->i_gid);
|
120 |
|
|
} else {
|
121 |
|
|
inode->i_gid = ufsip->ui_sgid;
|
122 |
|
|
}
|
123 |
|
|
|
124 |
|
|
/*
|
125 |
|
|
* Linux i_size is 32 bits, so some files on a UFS filesystem may not
|
126 |
|
|
* be readable. I let people access the first 32 bits worth of them.
|
127 |
|
|
* for the rw code, we may want to mark these inodes as read-only.
|
128 |
|
|
* XXX - bug Linus to make i_size a __u64 instead of a __u32.
|
129 |
|
|
*/
|
130 |
|
|
inode->u.ufs_i.ui_size = ((__u64)(ufsip->ui_size.val[0])<<32) | (__u64)(ufsip->ui_size.val[1]);
|
131 |
|
|
inode->i_size = ufsip->ui_size.val[1]; /* XXX - endianity */
|
132 |
|
|
if (ufsip->ui_size.val[0] != 0) {
|
133 |
|
|
inode->i_size = 0xffffffff;
|
134 |
|
|
printk("ufs_read_inode: file too big ino %lu dev %u/%u, faking size\n",
|
135 |
|
|
inode->i_ino, MAJOR(inode->i_dev), MINOR(inode->i_dev));
|
136 |
|
|
}
|
137 |
|
|
/*
|
138 |
|
|
* Linux doesn't keep tv_usec around in the kernel, so we discard it.
|
139 |
|
|
* XXX - I'm not sure what I should do about writing things. I may
|
140 |
|
|
* want to keep this data, but for the moment I think I'll just write
|
141 |
|
|
* zeros for these fields when writing out inodes.
|
142 |
|
|
*/
|
143 |
|
|
inode->i_atime = ufsip->ui_atime.tv_sec;
|
144 |
|
|
inode->i_mtime = ufsip->ui_mtime.tv_sec;
|
145 |
|
|
inode->i_ctime = ufsip->ui_ctime.tv_sec;
|
146 |
|
|
inode->i_blksize = sb->u.ufs_sb.s_fsize;
|
147 |
|
|
inode->i_blocks = ufsip->ui_blocks;
|
148 |
|
|
inode->i_version = ++event; /* see linux/kernel/sched.c */
|
149 |
|
|
|
150 |
|
|
if (S_ISREG(inode->i_mode)) {
|
151 |
|
|
inode->i_op = &ufs_file_inode_operations;
|
152 |
|
|
} else if (S_ISDIR(inode->i_mode)) {
|
153 |
|
|
inode->i_op = &ufs_dir_inode_operations;
|
154 |
|
|
} else if (S_ISLNK(inode->i_mode)) {
|
155 |
|
|
inode->i_op = &ufs_symlink_inode_operations;
|
156 |
|
|
} else if (S_ISCHR(inode->i_mode)) {
|
157 |
|
|
inode->i_op = &chrdev_inode_operations;
|
158 |
|
|
} else if (S_ISBLK(inode->i_mode)) {
|
159 |
|
|
inode->i_op = &blkdev_inode_operations;
|
160 |
|
|
} else if (S_ISFIFO(inode->i_mode)) {
|
161 |
|
|
init_fifo(inode);
|
162 |
|
|
} else {
|
163 |
|
|
printk("ufs_read_inode: unknown file type 0%o ino %lu dev %d/%d\n",
|
164 |
|
|
inode->i_mode, inode->i_ino, MAJOR(inode->i_dev),
|
165 |
|
|
MINOR(inode->i_dev));
|
166 |
|
|
/* XXX - debugging */
|
167 |
|
|
ufs_print_inode(inode);
|
168 |
|
|
inode->i_op = &ufs_file_inode_operations;
|
169 |
|
|
}
|
170 |
|
|
|
171 |
|
|
/*
|
172 |
|
|
* ufs_read_super makes sure that UFS_NDADDR and UFS_NINDIR are sane.
|
173 |
|
|
*/
|
174 |
|
|
if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
|
175 |
|
|
S_ISLNK(inode->i_mode)) {
|
176 |
|
|
int i;
|
177 |
|
|
|
178 |
|
|
for (i = 0; i < UFS_NDADDR; i++) {
|
179 |
|
|
inode->u.ufs_i.ui_db[i] = ufsip->ui_db[i];
|
180 |
|
|
}
|
181 |
|
|
for (i = 0; i < UFS_NINDIR; i++) {
|
182 |
|
|
inode->u.ufs_i.ui_ib[i] = ufsip->ui_ib[i];
|
183 |
|
|
}
|
184 |
|
|
}
|
185 |
|
|
|
186 |
|
|
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
|
187 |
|
|
/* XXX - should be ui_db[1] on little endian ufs filesystems */
|
188 |
|
|
inode->i_rdev = to_kdev_t(ufsip->ui_db[0]);
|
189 |
|
|
}
|
190 |
|
|
|
191 |
|
|
/* XXX - implement fast and slow symlinks */
|
192 |
|
|
|
193 |
|
|
inode->u.ufs_i.ui_flags = ufsip->ui_flags;
|
194 |
|
|
inode->u.ufs_i.ui_gen = ufsip->ui_gen; /* XXX - is this i_version? */
|
195 |
|
|
inode->u.ufs_i.ui_shadow = ufsip->ui_shadow; /* XXX */
|
196 |
|
|
inode->u.ufs_i.ui_uid = ufsip->ui_uid;
|
197 |
|
|
inode->u.ufs_i.ui_gid = ufsip->ui_gid;
|
198 |
|
|
inode->u.ufs_i.ui_oeftflag = ufsip->ui_oeftflag;
|
199 |
|
|
|
200 |
|
|
brelse(bh);
|
201 |
|
|
|
202 |
|
|
if (inode->i_sb->u.ufs_sb.s_flags & (UFS_DEBUG|UFS_DEBUG_INODE)) {
|
203 |
|
|
ufs_print_inode(inode);
|
204 |
|
|
}
|
205 |
|
|
|
206 |
|
|
return;
|
207 |
|
|
}
|
208 |
|
|
|
209 |
|
|
void ufs_put_inode (struct inode * inode)
|
210 |
|
|
{
|
211 |
|
|
if (inode->i_nlink)
|
212 |
|
|
return;
|
213 |
|
|
|
214 |
|
|
printk("ufs_put_inode: nlink == 0 for inum %lu on dev %d/%d\n",
|
215 |
|
|
inode->i_ino, MAJOR(inode->i_dev), MINOR(inode->i_dev));
|
216 |
|
|
ufs_print_inode(inode);
|
217 |
|
|
panic("ufs_put_inode: fs is read only, and nlink == 0");
|
218 |
|
|
|
219 |
|
|
/* XXX - this code goes here eventually
|
220 |
|
|
inode->i_size = 0;
|
221 |
|
|
if (inode->i_blocks)
|
222 |
|
|
ufs_truncate(inode);
|
223 |
|
|
ufs_free_inode(inode);
|
224 |
|
|
*/
|
225 |
|
|
|
226 |
|
|
return;
|
227 |
|
|
}
|
228 |
|
|
|
229 |
|
|
/*
|
230 |
|
|
* Local Variables: ***
|
231 |
|
|
* c-indent-level: 8 ***
|
232 |
|
|
* c-continued-statement-offset: 8 ***
|
233 |
|
|
* c-brace-offset: -8 ***
|
234 |
|
|
* c-argdecl-indent: 0 ***
|
235 |
|
|
* c-label-offset: -8 ***
|
236 |
|
|
* End: ***
|
237 |
|
|
*/
|