]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - fs/affs/inode.c
Merge branches 'pm-domains', 'pm-avs' and 'powercap'
[karo-tx-linux.git] / fs / affs / inode.c
1 /*
2  *  linux/fs/affs/inode.c
3  *
4  *  (c) 1996  Hans-Joachim Widmaier - Rewritten
5  *
6  *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem.
7  *
8  *  (C) 1992  Eric Youngdale Modified for ISO9660 filesystem.
9  *
10  *  (C) 1991  Linus Torvalds - minix filesystem
11  */
12 #include <linux/sched.h>
13 #include <linux/cred.h>
14 #include <linux/gfp.h>
15 #include "affs.h"
16
17 struct inode *affs_iget(struct super_block *sb, unsigned long ino)
18 {
19         struct affs_sb_info     *sbi = AFFS_SB(sb);
20         struct buffer_head      *bh;
21         struct affs_tail        *tail;
22         struct inode            *inode;
23         u32                      block;
24         u32                      size;
25         u32                      prot;
26         u16                      id;
27
28         inode = iget_locked(sb, ino);
29         if (!inode)
30                 return ERR_PTR(-ENOMEM);
31         if (!(inode->i_state & I_NEW))
32                 return inode;
33
34         pr_debug("affs_iget(%lu)\n", inode->i_ino);
35
36         block = inode->i_ino;
37         bh = affs_bread(sb, block);
38         if (!bh) {
39                 affs_warning(sb, "read_inode", "Cannot read block %d", block);
40                 goto bad_inode;
41         }
42         if (affs_checksum_block(sb, bh) || be32_to_cpu(AFFS_HEAD(bh)->ptype) != T_SHORT) {
43                 affs_warning(sb,"read_inode",
44                            "Checksum or type (ptype=%d) error on inode %d",
45                            AFFS_HEAD(bh)->ptype, block);
46                 goto bad_inode;
47         }
48
49         tail = AFFS_TAIL(sb, bh);
50         prot = be32_to_cpu(tail->protect);
51
52         inode->i_size = 0;
53         set_nlink(inode, 1);
54         inode->i_mode = 0;
55         AFFS_I(inode)->i_extcnt = 1;
56         AFFS_I(inode)->i_ext_last = ~1;
57         AFFS_I(inode)->i_protect = prot;
58         atomic_set(&AFFS_I(inode)->i_opencnt, 0);
59         AFFS_I(inode)->i_blkcnt = 0;
60         AFFS_I(inode)->i_lc = NULL;
61         AFFS_I(inode)->i_lc_size = 0;
62         AFFS_I(inode)->i_lc_shift = 0;
63         AFFS_I(inode)->i_lc_mask = 0;
64         AFFS_I(inode)->i_ac = NULL;
65         AFFS_I(inode)->i_ext_bh = NULL;
66         AFFS_I(inode)->mmu_private = 0;
67         AFFS_I(inode)->i_lastalloc = 0;
68         AFFS_I(inode)->i_pa_cnt = 0;
69
70         if (affs_test_opt(sbi->s_flags, SF_SETMODE))
71                 inode->i_mode = sbi->s_mode;
72         else
73                 inode->i_mode = affs_prot_to_mode(prot);
74
75         id = be16_to_cpu(tail->uid);
76         if (id == 0 || affs_test_opt(sbi->s_flags, SF_SETUID))
77                 inode->i_uid = sbi->s_uid;
78         else if (id == 0xFFFF && affs_test_opt(sbi->s_flags, SF_MUFS))
79                 i_uid_write(inode, 0);
80         else
81                 i_uid_write(inode, id);
82
83         id = be16_to_cpu(tail->gid);
84         if (id == 0 || affs_test_opt(sbi->s_flags, SF_SETGID))
85                 inode->i_gid = sbi->s_gid;
86         else if (id == 0xFFFF && affs_test_opt(sbi->s_flags, SF_MUFS))
87                 i_gid_write(inode, 0);
88         else
89                 i_gid_write(inode, id);
90
91         switch (be32_to_cpu(tail->stype)) {
92         case ST_ROOT:
93                 inode->i_uid = sbi->s_uid;
94                 inode->i_gid = sbi->s_gid;
95                 /* fall through */
96         case ST_USERDIR:
97                 if (be32_to_cpu(tail->stype) == ST_USERDIR ||
98                     affs_test_opt(sbi->s_flags, SF_SETMODE)) {
99                         if (inode->i_mode & S_IRUSR)
100                                 inode->i_mode |= S_IXUSR;
101                         if (inode->i_mode & S_IRGRP)
102                                 inode->i_mode |= S_IXGRP;
103                         if (inode->i_mode & S_IROTH)
104                                 inode->i_mode |= S_IXOTH;
105                         inode->i_mode |= S_IFDIR;
106                 } else
107                         inode->i_mode = S_IRUGO | S_IXUGO | S_IWUSR | S_IFDIR;
108                 /* Maybe it should be controlled by mount parameter? */
109                 //inode->i_mode |= S_ISVTX;
110                 inode->i_op = &affs_dir_inode_operations;
111                 inode->i_fop = &affs_dir_operations;
112                 break;
113         case ST_LINKDIR:
114 #if 0
115                 affs_warning(sb, "read_inode", "inode is LINKDIR");
116                 goto bad_inode;
117 #else
118                 inode->i_mode |= S_IFDIR;
119                 /* ... and leave ->i_op and ->i_fop pointing to empty */
120                 break;
121 #endif
122         case ST_LINKFILE:
123                 affs_warning(sb, "read_inode", "inode is LINKFILE");
124                 goto bad_inode;
125         case ST_FILE:
126                 size = be32_to_cpu(tail->size);
127                 inode->i_mode |= S_IFREG;
128                 AFFS_I(inode)->mmu_private = inode->i_size = size;
129                 if (inode->i_size) {
130                         AFFS_I(inode)->i_blkcnt = (size - 1) /
131                                                sbi->s_data_blksize + 1;
132                         AFFS_I(inode)->i_extcnt = (AFFS_I(inode)->i_blkcnt - 1) /
133                                                sbi->s_hashsize + 1;
134                 }
135                 if (tail->link_chain)
136                         set_nlink(inode, 2);
137                 inode->i_mapping->a_ops = affs_test_opt(sbi->s_flags, SF_OFS) ?
138                                           &affs_aops_ofs : &affs_aops;
139                 inode->i_op = &affs_file_inode_operations;
140                 inode->i_fop = &affs_file_operations;
141                 break;
142         case ST_SOFTLINK:
143                 inode->i_size = strlen((char *)AFFS_HEAD(bh)->table);
144                 inode->i_mode |= S_IFLNK;
145                 inode_nohighmem(inode);
146                 inode->i_op = &affs_symlink_inode_operations;
147                 inode->i_data.a_ops = &affs_symlink_aops;
148                 break;
149         }
150
151         inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec
152                        = (be32_to_cpu(tail->change.days) * (24 * 60 * 60) +
153                          be32_to_cpu(tail->change.mins) * 60 +
154                          be32_to_cpu(tail->change.ticks) / 50 +
155                          ((8 * 365 + 2) * 24 * 60 * 60)) +
156                          sys_tz.tz_minuteswest * 60;
157         inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_atime.tv_nsec = 0;
158         affs_brelse(bh);
159         unlock_new_inode(inode);
160         return inode;
161
162 bad_inode:
163         affs_brelse(bh);
164         iget_failed(inode);
165         return ERR_PTR(-EIO);
166 }
167
168 int
169 affs_write_inode(struct inode *inode, struct writeback_control *wbc)
170 {
171         struct super_block      *sb = inode->i_sb;
172         struct buffer_head      *bh;
173         struct affs_tail        *tail;
174         uid_t                    uid;
175         gid_t                    gid;
176
177         pr_debug("write_inode(%lu)\n", inode->i_ino);
178
179         if (!inode->i_nlink)
180                 // possibly free block
181                 return 0;
182         bh = affs_bread(sb, inode->i_ino);
183         if (!bh) {
184                 affs_error(sb,"write_inode","Cannot read block %lu",inode->i_ino);
185                 return -EIO;
186         }
187         tail = AFFS_TAIL(sb, bh);
188         if (tail->stype == cpu_to_be32(ST_ROOT)) {
189                 affs_secs_to_datestamp(inode->i_mtime.tv_sec,
190                                        &AFFS_ROOT_TAIL(sb, bh)->root_change);
191         } else {
192                 tail->protect = cpu_to_be32(AFFS_I(inode)->i_protect);
193                 tail->size = cpu_to_be32(inode->i_size);
194                 affs_secs_to_datestamp(inode->i_mtime.tv_sec, &tail->change);
195                 if (!(inode->i_ino == AFFS_SB(sb)->s_root_block)) {
196                         uid = i_uid_read(inode);
197                         gid = i_gid_read(inode);
198                         if (affs_test_opt(AFFS_SB(sb)->s_flags, SF_MUFS)) {
199                                 if (uid == 0 || uid == 0xFFFF)
200                                         uid = uid ^ ~0;
201                                 if (gid == 0 || gid == 0xFFFF)
202                                         gid = gid ^ ~0;
203                         }
204                         if (!affs_test_opt(AFFS_SB(sb)->s_flags, SF_SETUID))
205                                 tail->uid = cpu_to_be16(uid);
206                         if (!affs_test_opt(AFFS_SB(sb)->s_flags, SF_SETGID))
207                                 tail->gid = cpu_to_be16(gid);
208                 }
209         }
210         affs_fix_checksum(sb, bh);
211         mark_buffer_dirty_inode(bh, inode);
212         affs_brelse(bh);
213         affs_free_prealloc(inode);
214         return 0;
215 }
216
217 int
218 affs_notify_change(struct dentry *dentry, struct iattr *attr)
219 {
220         struct inode *inode = d_inode(dentry);
221         int error;
222
223         pr_debug("notify_change(%lu,0x%x)\n", inode->i_ino, attr->ia_valid);
224
225         error = setattr_prepare(dentry, attr);
226         if (error)
227                 goto out;
228
229         if (((attr->ia_valid & ATTR_UID) &&
230               affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_SETUID)) ||
231             ((attr->ia_valid & ATTR_GID) &&
232               affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_SETGID)) ||
233             ((attr->ia_valid & ATTR_MODE) &&
234              (AFFS_SB(inode->i_sb)->s_flags &
235               (AFFS_MOUNT_SF_SETMODE | AFFS_MOUNT_SF_IMMUTABLE)))) {
236                 if (!affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_QUIET))
237                         error = -EPERM;
238                 goto out;
239         }
240
241         if ((attr->ia_valid & ATTR_SIZE) &&
242             attr->ia_size != i_size_read(inode)) {
243                 error = inode_newsize_ok(inode, attr->ia_size);
244                 if (error)
245                         return error;
246
247                 truncate_setsize(inode, attr->ia_size);
248                 affs_truncate(inode);
249         }
250
251         setattr_copy(inode, attr);
252         mark_inode_dirty(inode);
253
254         if (attr->ia_valid & ATTR_MODE)
255                 affs_mode_to_prot(inode);
256 out:
257         return error;
258 }
259
260 void
261 affs_evict_inode(struct inode *inode)
262 {
263         unsigned long cache_page;
264         pr_debug("evict_inode(ino=%lu, nlink=%u)\n",
265                  inode->i_ino, inode->i_nlink);
266         truncate_inode_pages_final(&inode->i_data);
267
268         if (!inode->i_nlink) {
269                 inode->i_size = 0;
270                 affs_truncate(inode);
271         }
272
273         invalidate_inode_buffers(inode);
274         clear_inode(inode);
275         affs_free_prealloc(inode);
276         cache_page = (unsigned long)AFFS_I(inode)->i_lc;
277         if (cache_page) {
278                 pr_debug("freeing ext cache\n");
279                 AFFS_I(inode)->i_lc = NULL;
280                 AFFS_I(inode)->i_ac = NULL;
281                 free_page(cache_page);
282         }
283         affs_brelse(AFFS_I(inode)->i_ext_bh);
284         AFFS_I(inode)->i_ext_last = ~1;
285         AFFS_I(inode)->i_ext_bh = NULL;
286
287         if (!inode->i_nlink)
288                 affs_free_block(inode->i_sb, inode->i_ino);
289 }
290
291 struct inode *
292 affs_new_inode(struct inode *dir)
293 {
294         struct super_block      *sb = dir->i_sb;
295         struct inode            *inode;
296         u32                      block;
297         struct buffer_head      *bh;
298
299         if (!(inode = new_inode(sb)))
300                 goto err_inode;
301
302         if (!(block = affs_alloc_block(dir, dir->i_ino)))
303                 goto err_block;
304
305         bh = affs_getzeroblk(sb, block);
306         if (!bh)
307                 goto err_bh;
308         mark_buffer_dirty_inode(bh, inode);
309         affs_brelse(bh);
310
311         inode->i_uid     = current_fsuid();
312         inode->i_gid     = current_fsgid();
313         inode->i_ino     = block;
314         set_nlink(inode, 1);
315         inode->i_mtime   = inode->i_atime = inode->i_ctime = current_time(inode);
316         atomic_set(&AFFS_I(inode)->i_opencnt, 0);
317         AFFS_I(inode)->i_blkcnt = 0;
318         AFFS_I(inode)->i_lc = NULL;
319         AFFS_I(inode)->i_lc_size = 0;
320         AFFS_I(inode)->i_lc_shift = 0;
321         AFFS_I(inode)->i_lc_mask = 0;
322         AFFS_I(inode)->i_ac = NULL;
323         AFFS_I(inode)->i_ext_bh = NULL;
324         AFFS_I(inode)->mmu_private = 0;
325         AFFS_I(inode)->i_protect = 0;
326         AFFS_I(inode)->i_lastalloc = 0;
327         AFFS_I(inode)->i_pa_cnt = 0;
328         AFFS_I(inode)->i_extcnt = 1;
329         AFFS_I(inode)->i_ext_last = ~1;
330
331         insert_inode_hash(inode);
332
333         return inode;
334
335 err_bh:
336         affs_free_block(sb, block);
337 err_block:
338         iput(inode);
339 err_inode:
340         return NULL;
341 }
342
343 /*
344  * Add an entry to a directory. Create the header block
345  * and insert it into the hash table.
346  */
347
348 int
349 affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s32 type)
350 {
351         struct super_block *sb = dir->i_sb;
352         struct buffer_head *inode_bh = NULL;
353         struct buffer_head *bh;
354         u32 block = 0;
355         int retval;
356
357         pr_debug("%s(dir=%lu, inode=%lu, \"%pd\", type=%d)\n", __func__,
358                  dir->i_ino, inode->i_ino, dentry, type);
359
360         retval = -EIO;
361         bh = affs_bread(sb, inode->i_ino);
362         if (!bh)
363                 goto done;
364
365         affs_lock_link(inode);
366         switch (type) {
367         case ST_LINKFILE:
368         case ST_LINKDIR:
369                 retval = -ENOSPC;
370                 block = affs_alloc_block(dir, dir->i_ino);
371                 if (!block)
372                         goto err;
373                 retval = -EIO;
374                 inode_bh = bh;
375                 bh = affs_getzeroblk(sb, block);
376                 if (!bh)
377                         goto err;
378                 break;
379         default:
380                 break;
381         }
382
383         AFFS_HEAD(bh)->ptype = cpu_to_be32(T_SHORT);
384         AFFS_HEAD(bh)->key = cpu_to_be32(bh->b_blocknr);
385         affs_copy_name(AFFS_TAIL(sb, bh)->name, dentry);
386         AFFS_TAIL(sb, bh)->stype = cpu_to_be32(type);
387         AFFS_TAIL(sb, bh)->parent = cpu_to_be32(dir->i_ino);
388
389         if (inode_bh) {
390                 __be32 chain;
391                 chain = AFFS_TAIL(sb, inode_bh)->link_chain;
392                 AFFS_TAIL(sb, bh)->original = cpu_to_be32(inode->i_ino);
393                 AFFS_TAIL(sb, bh)->link_chain = chain;
394                 AFFS_TAIL(sb, inode_bh)->link_chain = cpu_to_be32(block);
395                 affs_adjust_checksum(inode_bh, block - be32_to_cpu(chain));
396                 mark_buffer_dirty_inode(inode_bh, inode);
397                 set_nlink(inode, 2);
398                 ihold(inode);
399         }
400         affs_fix_checksum(sb, bh);
401         mark_buffer_dirty_inode(bh, inode);
402         dentry->d_fsdata = (void *)(long)bh->b_blocknr;
403
404         affs_lock_dir(dir);
405         retval = affs_insert_hash(dir, bh);
406         mark_buffer_dirty_inode(bh, inode);
407         affs_unlock_dir(dir);
408         affs_unlock_link(inode);
409
410         d_instantiate(dentry, inode);
411 done:
412         affs_brelse(inode_bh);
413         affs_brelse(bh);
414         return retval;
415 err:
416         if (block)
417                 affs_free_block(sb, block);
418         affs_unlock_link(inode);
419         goto done;
420 }