exofs: file and file_inode operations
[linux-2.6.git] / fs / exofs / inode.c
1 /*
2  * Copyright (C) 2005, 2006
3  * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com)
4  * Copyright (C) 2005, 2006
5  * International Business Machines
6  * Copyright (C) 2008, 2009
7  * Boaz Harrosh <bharrosh@panasas.com>
8  *
9  * Copyrights for code taken from ext2:
10  *     Copyright (C) 1992, 1993, 1994, 1995
11  *     Remy Card (card@masi.ibp.fr)
12  *     Laboratoire MASI - Institut Blaise Pascal
13  *     Universite Pierre et Marie Curie (Paris VI)
14  *     from
15  *     linux/fs/minix/inode.c
16  *     Copyright (C) 1991, 1992  Linus Torvalds
17  *
18  * This file is part of exofs.
19  *
20  * exofs is free software; you can redistribute it and/or modify
21  * it under the terms of the GNU General Public License as published by
22  * the Free Software Foundation.  Since it is based on ext2, and the only
23  * valid version of GPL for the Linux kernel is version 2, the only valid
24  * version of GPL for exofs is version 2.
25  *
26  * exofs is distributed in the hope that it will be useful,
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
29  * GNU General Public License for more details.
30  *
31  * You should have received a copy of the GNU General Public License
32  * along with exofs; if not, write to the Free Software
33  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
34  */
35
36 #include <linux/writeback.h>
37 #include <linux/buffer_head.h>
38
39 #include "exofs.h"
40
41 #ifdef CONFIG_EXOFS_DEBUG
42 #  define EXOFS_DEBUG_OBJ_ISIZE 1
43 #endif
44
45 /******************************************************************************
46  * INODE OPERATIONS
47  *****************************************************************************/
48
49 /*
50  * Test whether an inode is a fast symlink.
51  */
52 static inline int exofs_inode_is_fast_symlink(struct inode *inode)
53 {
54         struct exofs_i_info *oi = exofs_i(inode);
55
56         return S_ISLNK(inode->i_mode) && (oi->i_data[0] != 0);
57 }
58
59 /*
60  * get_block_t - Fill in a buffer_head
61  * An OSD takes care of block allocation so we just fake an allocation by
62  * putting in the inode's sector_t in the buffer_head.
63  * TODO: What about the case of create==0 and @iblock does not exist in the
64  * object?
65  */
66 static int exofs_get_block(struct inode *inode, sector_t iblock,
67                     struct buffer_head *bh_result, int create)
68 {
69         map_bh(bh_result, inode->i_sb, iblock);
70         return 0;
71 }
72
73 const struct osd_attr g_attr_logical_length = ATTR_DEF(
74         OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8);
75
76 /*
77  * Truncate a file to the specified size - all we have to do is set the size
78  * attribute.  We make sure the object exists first.
79  */
80 void exofs_truncate(struct inode *inode)
81 {
82         struct exofs_sb_info *sbi = inode->i_sb->s_fs_info;
83         struct exofs_i_info *oi = exofs_i(inode);
84         struct osd_obj_id obj = {sbi->s_pid, inode->i_ino + EXOFS_OBJ_OFF};
85         struct osd_request *or;
86         struct osd_attr attr;
87         loff_t isize = i_size_read(inode);
88         __be64 newsize;
89         int ret;
90
91         if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
92              || S_ISLNK(inode->i_mode)))
93                 return;
94         if (exofs_inode_is_fast_symlink(inode))
95                 return;
96         if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
97                 return;
98         inode->i_mtime = inode->i_ctime = CURRENT_TIME;
99
100         nobh_truncate_page(inode->i_mapping, isize, exofs_get_block);
101
102         or = osd_start_request(sbi->s_dev, GFP_KERNEL);
103         if (unlikely(!or)) {
104                 EXOFS_ERR("ERROR: exofs_truncate: osd_start_request failed\n");
105                 goto fail;
106         }
107
108         osd_req_set_attributes(or, &obj);
109
110         newsize = cpu_to_be64((u64)isize);
111         attr = g_attr_logical_length;
112         attr.val_ptr = &newsize;
113         osd_req_add_set_attr_list(or, &attr, 1);
114
115         /* if we are about to truncate an object, and it hasn't been
116          * created yet, wait
117          */
118         if (unlikely(wait_obj_created(oi)))
119                 goto fail;
120
121         ret = exofs_sync_op(or, sbi->s_timeout, oi->i_cred);
122         osd_end_request(or);
123         if (ret)
124                 goto fail;
125
126 out:
127         mark_inode_dirty(inode);
128         return;
129 fail:
130         make_bad_inode(inode);
131         goto out;
132 }
133
134 /*
135  * Set inode attributes - just call generic functions.
136  */
137 int exofs_setattr(struct dentry *dentry, struct iattr *iattr)
138 {
139         struct inode *inode = dentry->d_inode;
140         int error;
141
142         error = inode_change_ok(inode, iattr);
143         if (error)
144                 return error;
145
146         error = inode_setattr(inode, iattr);
147         return error;
148 }