initial commit with v2.6.9
[linux-2.6.9-moxart.git] / fs / affs / inode.c
blob3142f402e659e72e935efca6493f52c034291168
1 /*
2 * linux/fs/affs/inode.c
4 * (c) 1996 Hans-Joachim Widmaier - Rewritten
6 * (C) 1993 Ray Burr - Modified for Amiga FFS filesystem.
8 * (C) 1992 Eric Youngdale Modified for ISO9660 filesystem.
10 * (C) 1991 Linus Torvalds - minix filesystem
13 #include <asm/div64.h>
14 #include <linux/errno.h>
15 #include <linux/fs.h>
16 #include <linux/slab.h>
17 #include <linux/stat.h>
18 #include <linux/time.h>
19 #include <linux/affs_fs.h>
20 #include <linux/kernel.h>
21 #include <linux/mm.h>
22 #include <linux/string.h>
23 #include <linux/genhd.h>
24 #include <linux/amigaffs.h>
25 #include <linux/major.h>
26 #include <linux/blkdev.h>
27 #include <linux/init.h>
28 #include <linux/smp_lock.h>
29 #include <linux/buffer_head.h>
30 #include <asm/system.h>
31 #include <asm/uaccess.h>
32 #include <linux/module.h>
34 extern struct inode_operations affs_symlink_inode_operations;
35 extern struct timezone sys_tz;
37 void
38 affs_read_inode(struct inode *inode)
40 struct super_block *sb = inode->i_sb;
41 struct affs_sb_info *sbi = AFFS_SB(sb);
42 struct buffer_head *bh;
43 struct affs_head *head;
44 struct affs_tail *tail;
45 u32 block;
46 u32 size;
47 u32 prot;
48 u16 id;
50 pr_debug("AFFS: read_inode(%lu)\n",inode->i_ino);
52 block = inode->i_ino;
53 bh = affs_bread(sb, block);
54 if (!bh) {
55 affs_warning(sb, "read_inode", "Cannot read block %d", block);
56 goto bad_inode;
58 if (affs_checksum_block(sb, bh) || be32_to_cpu(AFFS_HEAD(bh)->ptype) != T_SHORT) {
59 affs_warning(sb,"read_inode",
60 "Checksum or type (ptype=%d) error on inode %d",
61 AFFS_HEAD(bh)->ptype, block);
62 goto bad_inode;
65 head = AFFS_HEAD(bh);
66 tail = AFFS_TAIL(sb, bh);
67 prot = be32_to_cpu(tail->protect);
69 inode->i_size = 0;
70 inode->i_nlink = 1;
71 inode->i_mode = 0;
72 AFFS_I(inode)->i_extcnt = 1;
73 AFFS_I(inode)->i_ext_last = ~1;
74 AFFS_I(inode)->i_protect = prot;
75 AFFS_I(inode)->i_opencnt = 0;
76 AFFS_I(inode)->i_blkcnt = 0;
77 AFFS_I(inode)->i_lc = NULL;
78 AFFS_I(inode)->i_lc_size = 0;
79 AFFS_I(inode)->i_lc_shift = 0;
80 AFFS_I(inode)->i_lc_mask = 0;
81 AFFS_I(inode)->i_ac = NULL;
82 AFFS_I(inode)->i_ext_bh = NULL;
83 AFFS_I(inode)->mmu_private = 0;
84 AFFS_I(inode)->i_lastalloc = 0;
85 AFFS_I(inode)->i_pa_cnt = 0;
87 if (sbi->s_flags & SF_SETMODE)
88 inode->i_mode = sbi->s_mode;
89 else
90 inode->i_mode = prot_to_mode(prot);
92 id = be16_to_cpu(tail->uid);
93 if (id == 0 || sbi->s_flags & SF_SETUID)
94 inode->i_uid = sbi->s_uid;
95 else if (id == 0xFFFF && sbi->s_flags & SF_MUFS)
96 inode->i_uid = 0;
97 else
98 inode->i_uid = id;
100 id = be16_to_cpu(tail->gid);
101 if (id == 0 || sbi->s_flags & SF_SETGID)
102 inode->i_gid = sbi->s_gid;
103 else if (id == 0xFFFF && sbi->s_flags & SF_MUFS)
104 inode->i_gid = 0;
105 else
106 inode->i_gid = id;
108 switch (be32_to_cpu(tail->stype)) {
109 case ST_ROOT:
110 inode->i_uid = sbi->s_uid;
111 inode->i_gid = sbi->s_gid;
112 /* fall through */
113 case ST_USERDIR:
114 if (be32_to_cpu(tail->stype) == ST_USERDIR ||
115 sbi->s_flags & SF_SETMODE) {
116 if (inode->i_mode & S_IRUSR)
117 inode->i_mode |= S_IXUSR;
118 if (inode->i_mode & S_IRGRP)
119 inode->i_mode |= S_IXGRP;
120 if (inode->i_mode & S_IROTH)
121 inode->i_mode |= S_IXOTH;
122 inode->i_mode |= S_IFDIR;
123 } else
124 inode->i_mode = S_IRUGO | S_IXUGO | S_IWUSR | S_IFDIR;
125 if (tail->link_chain)
126 inode->i_nlink = 2;
127 /* Maybe it should be controlled by mount parameter? */
128 //inode->i_mode |= S_ISVTX;
129 inode->i_op = &affs_dir_inode_operations;
130 inode->i_fop = &affs_dir_operations;
131 break;
132 case ST_LINKDIR:
133 #if 0
134 affs_warning(sb, "read_inode", "inode is LINKDIR");
135 goto bad_inode;
136 #else
137 inode->i_mode |= S_IFDIR;
138 inode->i_op = NULL;
139 inode->i_fop = NULL;
140 break;
141 #endif
142 case ST_LINKFILE:
143 affs_warning(sb, "read_inode", "inode is LINKFILE");
144 goto bad_inode;
145 case ST_FILE:
146 size = be32_to_cpu(tail->size);
147 inode->i_mode |= S_IFREG;
148 AFFS_I(inode)->mmu_private = inode->i_size = size;
149 if (inode->i_size) {
150 AFFS_I(inode)->i_blkcnt = (size - 1) /
151 sbi->s_data_blksize + 1;
152 AFFS_I(inode)->i_extcnt = (AFFS_I(inode)->i_blkcnt - 1) /
153 sbi->s_hashsize + 1;
155 if (tail->link_chain)
156 inode->i_nlink = 2;
157 inode->i_mapping->a_ops = (sbi->s_flags & SF_OFS) ? &affs_aops_ofs : &affs_aops;
158 inode->i_op = &affs_file_inode_operations;
159 inode->i_fop = &affs_file_operations;
160 break;
161 case ST_SOFTLINK:
162 inode->i_mode |= S_IFLNK;
163 inode->i_op = &affs_symlink_inode_operations;
164 inode->i_data.a_ops = &affs_symlink_aops;
165 break;
168 inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec
169 = (be32_to_cpu(tail->change.days) * (24 * 60 * 60) +
170 be32_to_cpu(tail->change.mins) * 60 +
171 be32_to_cpu(tail->change.ticks) / 50 +
172 ((8 * 365 + 2) * 24 * 60 * 60)) +
173 sys_tz.tz_minuteswest * 60;
174 inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_atime.tv_nsec = 0;
175 affs_brelse(bh);
176 return;
178 bad_inode:
179 make_bad_inode(inode);
180 affs_brelse(bh);
181 return;
185 affs_write_inode(struct inode *inode, int unused)
187 struct super_block *sb = inode->i_sb;
188 struct buffer_head *bh;
189 struct affs_tail *tail;
190 uid_t uid;
191 gid_t gid;
193 pr_debug("AFFS: write_inode(%lu)\n",inode->i_ino);
195 if (!inode->i_nlink)
196 // possibly free block
197 return 0;
198 bh = affs_bread(sb, inode->i_ino);
199 if (!bh) {
200 affs_error(sb,"write_inode","Cannot read block %lu",inode->i_ino);
201 return -EIO;
203 tail = AFFS_TAIL(sb, bh);
204 if (tail->stype == cpu_to_be32(ST_ROOT)) {
205 secs_to_datestamp(inode->i_mtime.tv_sec,&AFFS_ROOT_TAIL(sb, bh)->root_change);
206 } else {
207 tail->protect = cpu_to_be32(AFFS_I(inode)->i_protect);
208 tail->size = cpu_to_be32(inode->i_size);
209 secs_to_datestamp(inode->i_mtime.tv_sec,&tail->change);
210 if (!(inode->i_ino == AFFS_SB(sb)->s_root_block)) {
211 uid = inode->i_uid;
212 gid = inode->i_gid;
213 if (AFFS_SB(sb)->s_flags & SF_MUFS) {
214 if (inode->i_uid == 0 || inode->i_uid == 0xFFFF)
215 uid = inode->i_uid ^ ~0;
216 if (inode->i_gid == 0 || inode->i_gid == 0xFFFF)
217 gid = inode->i_gid ^ ~0;
219 if (!(AFFS_SB(sb)->s_flags & SF_SETUID))
220 tail->uid = cpu_to_be16(uid);
221 if (!(AFFS_SB(sb)->s_flags & SF_SETGID))
222 tail->gid = cpu_to_be16(gid);
225 affs_fix_checksum(sb, bh);
226 mark_buffer_dirty_inode(bh, inode);
227 affs_brelse(bh);
228 affs_free_prealloc(inode);
229 return 0;
233 affs_notify_change(struct dentry *dentry, struct iattr *attr)
235 struct inode *inode = dentry->d_inode;
236 int error;
238 pr_debug("AFFS: notify_change(%lu,0x%x)\n",inode->i_ino,attr->ia_valid);
240 error = inode_change_ok(inode,attr);
241 if (error)
242 goto out;
244 if (((attr->ia_valid & ATTR_UID) && (AFFS_SB(inode->i_sb)->s_flags & SF_SETUID)) ||
245 ((attr->ia_valid & ATTR_GID) && (AFFS_SB(inode->i_sb)->s_flags & SF_SETGID)) ||
246 ((attr->ia_valid & ATTR_MODE) &&
247 (AFFS_SB(inode->i_sb)->s_flags & (SF_SETMODE | SF_IMMUTABLE)))) {
248 if (!(AFFS_SB(inode->i_sb)->s_flags & SF_QUIET))
249 error = -EPERM;
250 goto out;
253 error = inode_setattr(inode, attr);
254 if (!error && (attr->ia_valid & ATTR_MODE))
255 mode_to_prot(inode);
256 out:
257 return error;
260 void
261 affs_put_inode(struct inode *inode)
263 pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink);
264 affs_free_prealloc(inode);
265 if (atomic_read(&inode->i_count) == 1) {
266 down(&inode->i_sem);
267 if (inode->i_size != AFFS_I(inode)->mmu_private)
268 affs_truncate(inode);
269 up(&inode->i_sem);
273 void
274 affs_delete_inode(struct inode *inode)
276 pr_debug("AFFS: delete_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink);
277 inode->i_size = 0;
278 if (S_ISREG(inode->i_mode))
279 affs_truncate(inode);
280 clear_inode(inode);
281 affs_free_block(inode->i_sb, inode->i_ino);
284 void
285 affs_clear_inode(struct inode *inode)
287 unsigned long cache_page = (unsigned long) AFFS_I(inode)->i_lc;
289 pr_debug("AFFS: clear_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink);
290 if (cache_page) {
291 pr_debug("AFFS: freeing ext cache\n");
292 AFFS_I(inode)->i_lc = NULL;
293 AFFS_I(inode)->i_ac = NULL;
294 free_page(cache_page);
296 affs_brelse(AFFS_I(inode)->i_ext_bh);
297 AFFS_I(inode)->i_ext_last = ~1;
298 AFFS_I(inode)->i_ext_bh = NULL;
301 struct inode *
302 affs_new_inode(struct inode *dir)
304 struct super_block *sb = dir->i_sb;
305 struct inode *inode;
306 u32 block;
307 struct buffer_head *bh;
309 if (!(inode = new_inode(sb)))
310 goto err_inode;
312 if (!(block = affs_alloc_block(dir, dir->i_ino)))
313 goto err_block;
315 bh = affs_getzeroblk(sb, block);
316 if (!bh)
317 goto err_bh;
318 mark_buffer_dirty_inode(bh, inode);
319 affs_brelse(bh);
321 inode->i_uid = current->fsuid;
322 inode->i_gid = current->fsgid;
323 inode->i_ino = block;
324 inode->i_nlink = 1;
325 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
326 AFFS_I(inode)->i_opencnt = 0;
327 AFFS_I(inode)->i_blkcnt = 0;
328 AFFS_I(inode)->i_lc = NULL;
329 AFFS_I(inode)->i_lc_size = 0;
330 AFFS_I(inode)->i_lc_shift = 0;
331 AFFS_I(inode)->i_lc_mask = 0;
332 AFFS_I(inode)->i_ac = NULL;
333 AFFS_I(inode)->i_ext_bh = NULL;
334 AFFS_I(inode)->mmu_private = 0;
335 AFFS_I(inode)->i_protect = 0;
336 AFFS_I(inode)->i_lastalloc = 0;
337 AFFS_I(inode)->i_pa_cnt = 0;
338 AFFS_I(inode)->i_extcnt = 1;
339 AFFS_I(inode)->i_ext_last = ~1;
341 insert_inode_hash(inode);
343 return inode;
345 err_bh:
346 affs_free_block(sb, block);
347 err_block:
348 iput(inode);
349 err_inode:
350 return NULL;
354 * Add an entry to a directory. Create the header block
355 * and insert it into the hash table.
359 affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s32 type)
361 struct super_block *sb = dir->i_sb;
362 struct buffer_head *inode_bh = NULL;
363 struct buffer_head *bh = NULL;
364 u32 block = 0;
365 int retval;
367 pr_debug("AFFS: add_entry(dir=%u, inode=%u, \"%*s\", type=%d)\n", (u32)dir->i_ino,
368 (u32)inode->i_ino, (int)dentry->d_name.len, dentry->d_name.name, type);
370 retval = -EIO;
371 bh = affs_bread(sb, inode->i_ino);
372 if (!bh)
373 goto done;
375 affs_lock_link(inode);
376 switch (type) {
377 case ST_LINKFILE:
378 case ST_LINKDIR:
379 inode_bh = bh;
380 retval = -ENOSPC;
381 block = affs_alloc_block(dir, dir->i_ino);
382 if (!block)
383 goto err;
384 retval = -EIO;
385 bh = affs_getzeroblk(sb, block);
386 if (!bh)
387 goto err;
388 break;
389 default:
390 break;
393 AFFS_HEAD(bh)->ptype = cpu_to_be32(T_SHORT);
394 AFFS_HEAD(bh)->key = cpu_to_be32(bh->b_blocknr);
395 affs_copy_name(AFFS_TAIL(sb, bh)->name, dentry);
396 AFFS_TAIL(sb, bh)->stype = cpu_to_be32(type);
397 AFFS_TAIL(sb, bh)->parent = cpu_to_be32(dir->i_ino);
399 if (inode_bh) {
400 __be32 chain;
401 chain = AFFS_TAIL(sb, inode_bh)->link_chain;
402 AFFS_TAIL(sb, bh)->original = cpu_to_be32(inode->i_ino);
403 AFFS_TAIL(sb, bh)->link_chain = chain;
404 AFFS_TAIL(sb, inode_bh)->link_chain = cpu_to_be32(block);
405 affs_adjust_checksum(inode_bh, block - be32_to_cpu(chain));
406 mark_buffer_dirty_inode(inode_bh, inode);
407 inode->i_nlink = 2;
408 atomic_inc(&inode->i_count);
410 affs_fix_checksum(sb, bh);
411 mark_buffer_dirty_inode(bh, inode);
412 dentry->d_fsdata = (void *)(long)bh->b_blocknr;
414 affs_lock_dir(dir);
415 retval = affs_insert_hash(dir, bh);
416 mark_buffer_dirty_inode(bh, inode);
417 affs_unlock_dir(dir);
418 affs_unlock_link(inode);
420 d_instantiate(dentry, inode);
421 done:
422 affs_brelse(inode_bh);
423 affs_brelse(bh);
424 return retval;
425 err:
426 if (block)
427 affs_free_block(sb, block);
428 affs_unlock_link(inode);
429 goto done;
431 MODULE_LICENSE("GPL");