fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / fs / hfs / inode.c
index 6c869f3..5cb7f8f 100644 (file)
  */
 
 #include <linux/pagemap.h>
-#include <linux/version.h>
 #include <linux/mpage.h>
 
 #include "hfs_fs.h"
 #include "btree.h"
 
+static const struct file_operations hfs_file_operations;
+static struct inode_operations hfs_file_inode_operations;
+
 /*================ Variable-like macros ================*/
 
 #define HFS_VALID_MODE_BITS  (S_IFREG | S_IFDIR | S_IRWXUGO)
@@ -43,7 +45,7 @@ static sector_t hfs_bmap(struct address_space *mapping, sector_t block)
        return generic_block_bmap(mapping, block, hfs_get_block);
 }
 
-int hfs_releasepage(struct page *page, int mask)
+static int hfs_releasepage(struct page *page, gfp_t mask)
 {
        struct inode *inode = page->mapping->host;
        struct super_block *sb = inode->i_sb;
@@ -71,12 +73,6 @@ int hfs_releasepage(struct page *page, int mask)
                        ;
                else if (atomic_read(&node->refcnt))
                        res = 0;
-               else for (i = 0; i < tree->pages_per_bnode; i++) {
-                       if (PageActive(node->page[i])) {
-                               res = 0;
-                               break;
-                       }
-               }
                if (res && node) {
                        hfs_bnode_unhash(node);
                        hfs_bnode_free(node);
@@ -99,29 +95,17 @@ int hfs_releasepage(struct page *page, int mask)
                } while (--i && nidx < tree->node_count);
                spin_unlock(&tree->hash_lock);
        }
-       //printk("releasepage: %lu,%x = %d\n", page->index, mask, res);
-       return res;
-}
-
-static int hfs_get_blocks(struct inode *inode, sector_t iblock, unsigned long max_blocks,
-                         struct buffer_head *bh_result, int create)
-{
-       int ret;
-
-       ret = hfs_get_block(inode, iblock, bh_result, create);
-       if (!ret)
-               bh_result->b_size = (1 << inode->i_blkbits);
-       return ret;
+       return res ? try_to_free_buffers(page) : 0;
 }
 
 static ssize_t hfs_direct_IO(int rw, struct kiocb *iocb,
                const struct iovec *iov, loff_t offset, unsigned long nr_segs)
 {
        struct file *file = iocb->ki_filp;
-       struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
+       struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host;
 
        return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
-                                 offset, nr_segs, hfs_get_blocks, NULL);
+                                 offset, nr_segs, hfs_get_block, NULL);
 }
 
 static int hfs_writepages(struct address_space *mapping,
@@ -130,7 +114,7 @@ static int hfs_writepages(struct address_space *mapping,
        return mpage_writepages(mapping, wbc, hfs_get_block);
 }
 
-struct address_space_operations hfs_btree_aops = {
+const struct address_space_operations hfs_btree_aops = {
        .readpage       = hfs_readpage,
        .writepage      = hfs_writepage,
        .sync_page      = block_sync_page,
@@ -140,7 +124,7 @@ struct address_space_operations hfs_btree_aops = {
        .releasepage    = hfs_releasepage,
 };
 
-struct address_space_operations hfs_aops = {
+const struct address_space_operations hfs_aops = {
        .readpage       = hfs_readpage,
        .writepage      = hfs_writepage,
        .sync_page      = block_sync_page,
@@ -163,23 +147,26 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode)
 
        init_MUTEX(&HFS_I(inode)->extents_lock);
        INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list);
-       hfs_cat_build_key((btree_key *)&HFS_I(inode)->cat_key, dir->i_ino, name);
+       hfs_cat_build_key(sb, (btree_key *)&HFS_I(inode)->cat_key, dir->i_ino, name);
        inode->i_ino = HFS_SB(sb)->next_id++;
        inode->i_mode = mode;
        inode->i_uid = current->fsuid;
        inode->i_gid = current->fsgid;
        inode->i_nlink = 1;
-       inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+       inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
        HFS_I(inode)->flags = 0;
        HFS_I(inode)->rsrc_inode = NULL;
-       if (S_ISDIR(inode->i_mode)) {
+       HFS_I(inode)->fs_blocks = 0;
+       if (S_ISDIR(mode)) {
                inode->i_size = 2;
                HFS_SB(sb)->folder_count++;
                if (dir->i_ino == HFS_ROOT_CNID)
                        HFS_SB(sb)->root_dirs++;
                inode->i_op = &hfs_dir_inode_operations;
                inode->i_fop = &hfs_dir_operations;
-       } else if (S_ISREG(inode->i_mode)) {
+               inode->i_mode |= S_IRWXUGO;
+               inode->i_mode &= ~HFS_SB(inode->i_sb)->s_dir_umask;
+       } else if (S_ISREG(mode)) {
                HFS_I(inode)->clump_blocks = HFS_SB(sb)->clumpablks;
                HFS_SB(sb)->file_count++;
                if (dir->i_ino == HFS_ROOT_CNID)
@@ -187,6 +174,10 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode)
                inode->i_op = &hfs_file_inode_operations;
                inode->i_fop = &hfs_file_operations;
                inode->i_mapping->a_ops = &hfs_aops;
+               inode->i_mode |= S_IRUGO|S_IXUGO;
+               if (mode & S_IWUSR)
+                       inode->i_mode |= S_IWUGO;
+               inode->i_mode &= ~HFS_SB(inode->i_sb)->s_file_umask;
                HFS_I(inode)->phys_size = 0;
                HFS_I(inode)->alloc_blocks = 0;
                HFS_I(inode)->first_blocks = 0;
@@ -243,7 +234,8 @@ void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext,
        HFS_I(inode)->first_blocks = count;
 
        inode->i_size = HFS_I(inode)->phys_size = log_size;
-       inode->i_blocks = (log_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+       HFS_I(inode)->fs_blocks = (log_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+       inode_set_bytes(inode, HFS_I(inode)->fs_blocks << sb->s_blocksize_bits);
        HFS_I(inode)->alloc_blocks = be32_to_cpu(phys_size) /
                                     HFS_SB(sb)->alloc_blksz;
        HFS_I(inode)->clump_blocks = clump_size / HFS_SB(sb)->alloc_blksz;
@@ -256,7 +248,7 @@ struct hfs_iget_data {
        hfs_cat_rec *rec;
 };
 
-int hfs_test_inode(struct inode *inode, void *data)
+static int hfs_test_inode(struct inode *inode, void *data)
 {
        struct hfs_iget_data *idata = data;
        hfs_cat_rec *rec;
@@ -276,7 +268,7 @@ int hfs_test_inode(struct inode *inode, void *data)
 /*
  * hfs_read_inode
  */
-int hfs_read_inode(struct inode *inode, void *data)
+static int hfs_read_inode(struct inode *inode, void *data)
 {
        struct hfs_iget_data *idata = data;
        struct hfs_sb_info *hsb = HFS_SB(inode->i_sb);
@@ -313,22 +305,21 @@ int hfs_read_inode(struct inode *inode, void *data)
                inode->i_mode = S_IRUGO | S_IXUGO;
                if (!(rec->file.Flags & HFS_FIL_LOCK))
                        inode->i_mode |= S_IWUGO;
-               inode->i_mode &= hsb->s_file_umask;
+               inode->i_mode &= ~hsb->s_file_umask;
                inode->i_mode |= S_IFREG;
                inode->i_ctime = inode->i_atime = inode->i_mtime =
                                hfs_m_to_utime(rec->file.MdDat);
                inode->i_op = &hfs_file_inode_operations;
                inode->i_fop = &hfs_file_operations;
                inode->i_mapping->a_ops = &hfs_aops;
-               HFS_I(inode)->phys_size = inode->i_size;
                break;
        case HFS_CDR_DIR:
                inode->i_ino = be32_to_cpu(rec->dir.DirID);
-               inode->i_blocks = 0;
                inode->i_size = be16_to_cpu(rec->dir.Val) + 2;
-               inode->i_mode = S_IFDIR | (S_IRWXUGO & hsb->s_dir_umask);
+               HFS_I(inode)->fs_blocks = 0;
+               inode->i_mode = S_IFDIR | (S_IRWXUGO & ~hsb->s_dir_umask);
                inode->i_ctime = inode->i_atime = inode->i_mtime =
-                               hfs_m_to_utime(rec->file.MdDat);
+                               hfs_m_to_utime(rec->dir.MdDat);
                inode->i_op = &hfs_dir_inode_operations;
                inode->i_fop = &hfs_dir_operations;
                break;
@@ -383,6 +374,7 @@ void hfs_inode_write_fork(struct inode *inode, struct hfs_extent *ext,
 
 int hfs_write_inode(struct inode *inode, int unused)
 {
+       struct inode *main_inode = inode;
        struct hfs_find_data fd;
        hfs_cat_rec rec;
 
@@ -405,24 +397,22 @@ int hfs_write_inode(struct inode *inode, int unused)
                }
        }
 
-       if (HFS_IS_RSRC(inode)) {
-               mark_inode_dirty(HFS_I(inode)->rsrc_inode);
-               return 0;
-       }
+       if (HFS_IS_RSRC(inode))
+               main_inode = HFS_I(inode)->rsrc_inode;
 
-       if (!inode->i_nlink)
+       if (!main_inode->i_nlink)
                return 0;
 
-       if (hfs_find_init(HFS_SB(inode->i_sb)->cat_tree, &fd))
+       if (hfs_find_init(HFS_SB(main_inode->i_sb)->cat_tree, &fd))
                /* panic? */
                return -EIO;
 
-       fd.search_key->cat = HFS_I(inode)->cat_key;
+       fd.search_key->cat = HFS_I(main_inode)->cat_key;
        if (hfs_brec_find(&fd))
                /* panic? */
                goto out;
 
-       if (S_ISDIR(inode->i_mode)) {
+       if (S_ISDIR(main_inode->i_mode)) {
                if (fd.entrylength < sizeof(struct hfs_cat_dir))
                        /* panic? */;
                hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
@@ -436,6 +426,13 @@ int hfs_write_inode(struct inode *inode, int unused)
 
                hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
                            sizeof(struct hfs_cat_dir));
+       } else if (HFS_IS_RSRC(inode)) {
+               hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
+                              sizeof(struct hfs_cat_file));
+               hfs_inode_write_fork(inode, rec.file.RExtRec,
+                                    &rec.file.RLgLen, &rec.file.RPyLen);
+               hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
+                               sizeof(struct hfs_cat_file));
        } else {
                if (fd.entrylength < sizeof(struct hfs_cat_file))
                        /* panic? */;
@@ -450,9 +447,6 @@ int hfs_write_inode(struct inode *inode, int unused)
                else
                        rec.file.Flags |= HFS_FIL_LOCK;
                hfs_inode_write_fork(inode, rec.file.ExtRec, &rec.file.LgLen, &rec.file.PyLen);
-               if (HFS_I(inode)->rsrc_inode)
-                       hfs_inode_write_fork(HFS_I(inode)->rsrc_inode, rec.file.RExtRec,
-                                            &rec.file.RLgLen, &rec.file.RPyLen);
                rec.file.MdDat = hfs_u_to_mtime(inode->i_mtime);
 
                hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
@@ -517,7 +511,7 @@ static int hfs_permission(struct inode *inode, int mask,
 {
        if (S_ISREG(inode->i_mode) && mask & MAY_EXEC)
                return 0;
-       return vfs_permission(inode, mask);
+       return generic_permission(inode, mask, NULL);
 }
 
 static int hfs_file_open(struct inode *inode, struct file *file)
@@ -539,13 +533,13 @@ static int hfs_file_release(struct inode *inode, struct file *file)
        if (atomic_read(&file->f_count) != 0)
                return 0;
        if (atomic_dec_and_test(&HFS_I(inode)->opencnt)) {
-               down(&inode->i_sem);
+               mutex_lock(&inode->i_mutex);
                hfs_file_truncate(inode);
                //if (inode->i_flags & S_DEAD) {
                //      hfs_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL);
                //      hfs_delete_inode(inode);
                //}
-               up(&inode->i_sem);
+               mutex_unlock(&inode->i_mutex);
        }
        return 0;
 }
@@ -605,10 +599,12 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr)
 }
 
 
-struct file_operations hfs_file_operations = {
+static const struct file_operations hfs_file_operations = {
        .llseek         = generic_file_llseek,
-       .read           = generic_file_read,
-       .write          = generic_file_write,
+       .read           = do_sync_read,
+       .aio_read       = generic_file_aio_read,
+       .write          = do_sync_write,
+       .aio_write      = generic_file_aio_write,
        .mmap           = generic_file_mmap,
        .sendfile       = generic_file_sendfile,
        .fsync          = file_fsync,
@@ -616,9 +612,12 @@ struct file_operations hfs_file_operations = {
        .release        = hfs_file_release,
 };
 
-struct inode_operations hfs_file_inode_operations = {
+static struct inode_operations hfs_file_inode_operations = {
        .lookup         = hfs_file_lookup,
        .truncate       = hfs_file_truncate,
        .setattr        = hfs_inode_setattr,
        .permission     = hfs_permission,
+       .setxattr       = hfs_setxattr,
+       .getxattr       = hfs_getxattr,
+       .listxattr      = hfs_listxattr,
 };