vserver 2.0 rc7
[linux-2.6.git] / fs / hfsplus / inode.c
index 5dc9bdb..d564270 100644 (file)
@@ -40,7 +40,7 @@ static sector_t hfsplus_bmap(struct address_space *mapping, sector_t block)
        return generic_block_bmap(mapping, block, hfsplus_get_block);
 }
 
-int hfsplus_releasepage(struct page *page, int mask)
+static int hfsplus_releasepage(struct page *page, int mask)
 {
        struct inode *inode = page->mapping->host;
        struct super_block *sb = inode->i_sb;
@@ -71,12 +71,6 @@ int hfsplus_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);
@@ -100,7 +94,7 @@ int hfsplus_releasepage(struct page *page, int mask)
                spin_unlock(&tree->hash_lock);
        }
        //printk("releasepage: %lu,%x = %d\n", page->index, mask, res);
-       return res;
+       return res ? try_to_free_buffers(page) : 0;
 }
 
 static int hfsplus_get_blocks(struct inode *inode, sector_t iblock, unsigned long max_blocks,
@@ -260,7 +254,7 @@ static int hfsplus_permission(struct inode *inode, int mask, struct nameidata *n
         */
        if (S_ISREG(inode->i_mode) && mask & MAY_EXEC && !(inode->i_mode & 0111))
                return 0;
-       return vfs_permission(inode, mask);
+       return generic_permission(inode, mask, NULL);
 }
 
 
@@ -297,17 +291,21 @@ static int hfsplus_file_release(struct inode *inode, struct file *file)
 extern struct inode_operations hfsplus_dir_inode_operations;
 extern struct file_operations hfsplus_dir_operations;
 
-struct inode_operations hfsplus_file_inode_operations = {
+static struct inode_operations hfsplus_file_inode_operations = {
        .lookup         = hfsplus_file_lookup,
        .truncate       = hfsplus_file_truncate,
        .permission     = hfsplus_permission,
+       .setxattr       = hfsplus_setxattr,
+       .getxattr       = hfsplus_getxattr,
+       .listxattr      = hfsplus_listxattr,
 };
 
-struct file_operations hfsplus_file_operations = {
+static struct file_operations hfsplus_file_operations = {
        .llseek         = generic_file_llseek,
        .read           = generic_file_read,
        .write          = generic_file_write,
        .mmap           = generic_file_mmap,
+       .sendfile       = generic_file_sendfile,
        .fsync          = file_fsync,
        .open           = hfsplus_file_open,
        .release        = hfsplus_file_release,
@@ -330,7 +328,8 @@ struct inode *hfsplus_new_inode(struct super_block *sb, int 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;
+       inode->i_blksize = HFSPLUS_SB(sb).alloc_blksz;
        INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
        init_MUTEX(&HFSPLUS_I(inode).extents_lock);
        atomic_set(&HFSPLUS_I(inode).opencnt, 0);
@@ -342,6 +341,7 @@ struct inode *hfsplus_new_inode(struct super_block *sb, int mode)
        HFSPLUS_I(inode).cached_start = 0;
        HFSPLUS_I(inode).cached_blocks = 0;
        HFSPLUS_I(inode).phys_size = 0;
+       HFSPLUS_I(inode).fs_blocks = 0;
        HFSPLUS_I(inode).rsrc_inode = NULL;
        if (S_ISDIR(inode->i_mode)) {
                inode->i_size = 2;
@@ -407,7 +407,8 @@ void hfsplus_inode_read_fork(struct inode *inode, struct hfsplus_fork_raw *fork)
 
        HFSPLUS_I(inode).alloc_blocks = be32_to_cpu(fork->total_blocks);
        inode->i_size = HFSPLUS_I(inode).phys_size = be64_to_cpu(fork->total_size);
-       inode->i_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+       HFSPLUS_I(inode).fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+       inode_set_bytes(inode, HFSPLUS_I(inode).fs_blocks << sb->s_blocksize_bits);
        HFSPLUS_I(inode).clump_blocks = be32_to_cpu(fork->clump_size) >> HFSPLUS_SB(sb).alloc_blksz_shift;
        if (!HFSPLUS_I(inode).clump_blocks)
                HFSPLUS_I(inode).clump_blocks = HFSPLUS_IS_RSRC(inode) ? HFSPLUS_SB(sb).rsrc_clump_blocks :
@@ -431,7 +432,7 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
        type = hfs_bnode_read_u16(fd->bnode, fd->entryoffset);
 
        HFSPLUS_I(inode).dev = 0;
-       inode->i_blksize = PAGE_SIZE; /* Doesn't seem to be useful... */
+       inode->i_blksize = HFSPLUS_SB(inode->i_sb).alloc_blksz;
        if (type == HFSPLUS_FOLDER) {
                struct hfsplus_cat_folder *folder = &entry.folder;
 
@@ -445,7 +446,7 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
                inode->i_atime = hfsp_mt2ut(folder->access_date);
                inode->i_mtime = hfsp_mt2ut(folder->content_mod_date);
                inode->i_ctime = inode->i_mtime;
-               inode->i_blocks = 0;
+               HFSPLUS_I(inode).fs_blocks = 0;
                inode->i_op = &hfsplus_dir_inode_operations;
                inode->i_fop = &hfsplus_dir_operations;
        } else if (type == HFSPLUS_FILE) {
@@ -483,28 +484,27 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
        return res;
 }
 
-void hfsplus_cat_write_inode(struct inode *inode)
+int hfsplus_cat_write_inode(struct inode *inode)
 {
+       struct inode *main_inode = inode;
        struct hfs_find_data fd;
        hfsplus_cat_entry entry;
 
-       if (HFSPLUS_IS_RSRC(inode)) {
-               mark_inode_dirty(HFSPLUS_I(inode).rsrc_inode);
-               return;
-       }
+       if (HFSPLUS_IS_RSRC(inode))
+               main_inode = HFSPLUS_I(inode).rsrc_inode;
 
-       if (!inode->i_nlink)
-               return;
+       if (!main_inode->i_nlink)
+               return 0;
 
-       if (hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd))
+       if (hfs_find_init(HFSPLUS_SB(main_inode->i_sb).cat_tree, &fd))
                /* panic? */
-               return;
+               return -EIO;
 
-       if (hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd))
+       if (hfsplus_find_cat(main_inode->i_sb, main_inode->i_ino, &fd))
                /* panic? */
                goto out;
 
-       if (S_ISDIR(inode->i_mode)) {
+       if (S_ISDIR(main_inode->i_mode)) {
                struct hfsplus_cat_folder *folder = &entry.folder;
 
                if (fd.entrylength < sizeof(struct hfsplus_cat_folder))
@@ -519,6 +519,13 @@ void hfsplus_cat_write_inode(struct inode *inode)
                folder->valence = cpu_to_be32(inode->i_size - 2);
                hfs_bnode_write(fd.bnode, &entry, fd.entryoffset,
                                         sizeof(struct hfsplus_cat_folder));
+       } else if (HFSPLUS_IS_RSRC(inode)) {
+               struct hfsplus_cat_file *file = &entry.file;
+               hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
+                              sizeof(struct hfsplus_cat_file));
+               hfsplus_inode_write_fork(inode, &file->rsrc_fork);
+               hfs_bnode_write(fd.bnode, &entry, fd.entryoffset,
+                               sizeof(struct hfsplus_cat_file));
        } else {
                struct hfsplus_cat_file *file = &entry.file;
 
@@ -527,8 +534,6 @@ void hfsplus_cat_write_inode(struct inode *inode)
                hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
                                        sizeof(struct hfsplus_cat_file));
                hfsplus_inode_write_fork(inode, &file->data_fork);
-               if (HFSPLUS_I(inode).rsrc_inode)
-                       hfsplus_inode_write_fork(HFSPLUS_I(inode).rsrc_inode, &file->rsrc_fork);
                if (S_ISREG(inode->i_mode))
                        HFSPLUS_I(inode).dev = inode->i_nlink;
                if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
@@ -546,4 +551,5 @@ void hfsplus_cat_write_inode(struct inode *inode)
        }
 out:
        hfs_find_exit(&fd);
+       return 0;
 }