Whamcloud - gitweb
562218dd73a41feb060f597e976bd00bf8de63b9
[fs/lustre-release.git] / lustre / llite / file.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  linux/fs/ext2/file.c
5  *
6  * This code is issued under the GNU General Public License.
7  * See the file COPYING in this distribution
8  *
9  * Copyright (C) 1992, 1993, 1994, 1995
10  * Remy Card (card@masi.ibp.fr)
11  * Laboratoire MASI - Institut Blaise Pascal
12  * Universite Pierre et Marie Curie (Paris VI)
13  *
14  *  from
15  *
16  *  linux/fs/minix/file.c
17  *
18  *  Copyright (C) 1991, 1992  Linus Torvalds
19  *
20  *  ext2 fs regular file handling primitives
21  *
22  *  64-bit file support on 64-bit platforms by Jakub Jelinek
23  *      (jj@sunsite.ms.mff.cuni.cz)
24  */
25
26 #define DEBUG_SUBSYSTEM S_LLITE
27
28 #include <linux/lustre_dlm.h>
29 #include <linux/lustre_lite.h>
30
31 int ll_inode_setattr(struct inode *inode, struct iattr *attr, int do_trunc);
32 extern int ll_setattr(struct dentry *de, struct iattr *attr);
33 extern inline struct obdo * ll_oa_from_inode(struct inode *inode,
34                                              unsigned long valid);
35
36 static int ll_file_open(struct inode *inode, struct file *file)
37 {
38         int rc;
39         struct ptlrpc_request *req = NULL;
40         struct ll_file_data *fd;
41         struct obdo *oa;
42         struct ll_sb_info *sbi = ll_i2sbi(inode);
43         ENTRY;
44
45         if (file->private_data)
46                 LBUG();
47
48         fd = kmem_cache_alloc(ll_file_data_slab, SLAB_KERNEL);
49         if (!fd)
50                 GOTO(out, rc = -ENOMEM);
51         memset(fd, 0, sizeof(*fd));
52
53         rc = mdc_open(&sbi->ll_mds_client, sbi->ll_mds_conn, inode->i_ino,
54                       S_IFREG, file->f_flags, (__u64)(unsigned long)file, 
55                       &fd->fd_mdshandle, &req); 
56         fd->fd_req = req;
57         ptlrpc_req_finished(req);
58         if (rc) {
59                 if (rc > 0) 
60                         rc = -rc;
61                 GOTO(out, rc);
62         }
63         if (!fd->fd_mdshandle)
64                 CERROR("mdc_open didn't assign fd_mdshandle\n");
65         
66
67         oa = ll_oa_from_inode(inode, (OBD_MD_FLMODE | OBD_MD_FLID));
68         if (oa == NULL)
69                 LBUG();
70         rc = obd_open(ll_i2obdconn(inode), oa);
71         obdo_free(oa);
72         if (rc) {
73                 /* XXX: Need to do mdc_close here! */
74                 GOTO(out, rc = abs(rc));
75         }
76
77         file->private_data = fd;
78
79         EXIT;
80  out:
81         if (rc && fd) {
82                 kmem_cache_free(ll_file_data_slab, fd);
83                 file->private_data = NULL;
84         }
85
86         return rc;
87 }
88
89 static int ll_file_release(struct inode *inode, struct file *file)
90 {
91         int rc;
92         struct ptlrpc_request *req = NULL;
93         struct ll_file_data *fd;
94         struct obdo *oa;
95         struct ll_sb_info *sbi = ll_i2sbi(inode);
96
97         ENTRY;
98
99         fd = (struct ll_file_data *)file->private_data;
100         if (!fd || !fd->fd_mdshandle) {
101                 LBUG();
102                 GOTO(out, rc = -EINVAL);
103         }
104
105         oa = ll_oa_from_inode(inode, (OBD_MD_FLMODE | OBD_MD_FLID));
106         if (oa == NULL)
107                 LBUG();
108         rc = obd_close(ll_i2obdconn(inode), oa);
109         obdo_free(oa);
110         if (rc)
111                 GOTO(out, abs(rc));
112
113         if (file->f_flags & O_WRONLY) {
114                 struct iattr attr;
115                 attr.ia_valid = ATTR_MTIME | ATTR_CTIME | ATTR_ATIME | ATTR_SIZE;
116                 attr.ia_mtime = inode->i_mtime;
117                 attr.ia_ctime = inode->i_ctime;
118                 attr.ia_atime = inode->i_atime;
119                 attr.ia_size = inode->i_size;
120
121                 /* XXX: this introduces a small race that we should evaluate */
122                 rc = ll_inode_setattr(inode, &attr, 0);
123                 if (rc) {
124                         CERROR("failed - %d.\n", rc);
125                         rc = -EIO; /* XXX - GOTO(out)? -phil */
126                 }
127         }
128
129         rc = mdc_close(&sbi->ll_mds_client, sbi->ll_mds_conn, inode->i_ino,
130                        S_IFREG, fd->fd_mdshandle, &req);
131         ptlrpc_req_finished(req);
132         if (rc) { 
133                 if (rc > 0) 
134                         rc = -rc;
135                 GOTO(out, rc);
136         }
137         ptlrpc_free_req(fd->fd_req);
138
139         EXIT; 
140
141  out:
142         if (!rc && fd) {
143                 kmem_cache_free(ll_file_data_slab, fd);
144                 file->private_data = NULL;
145         }
146         return rc;
147 }
148
149
150 static inline void ll_remove_suid(struct inode *inode)
151 {
152         unsigned int mode;
153
154         /* set S_IGID if S_IXGRP is set, and always set S_ISUID */
155         mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID;
156
157         /* was any of the uid bits set? */
158         mode &= inode->i_mode;
159         if (mode && !capable(CAP_FSETID)) {
160                 inode->i_mode &= ~mode;
161                 // XXX careful here - we cannot change the size
162         }
163 }
164
165 static ssize_t ll_file_read(struct file *filp, char *buf, size_t count,
166                             loff_t *ppos)
167 {
168         struct inode *inode = filp->f_dentry->d_inode;
169         struct ll_sb_info *sbi = ll_i2sbi(inode);
170         struct ldlm_extent extent;
171         struct ldlm_handle lockh;
172         __u64 res_id[RES_NAME_SIZE] = {inode->i_ino};
173         int flags = 0;
174         ldlm_error_t err;
175         ssize_t retval;
176         ENTRY;
177
178         extent.start = *ppos;
179         extent.end = *ppos + count;
180         CDEBUG(D_INFO, "Locking inode %ld, start %Lu end %Lu\n",
181                inode->i_ino, extent.start, extent.end);
182
183         err = obd_enqueue(&sbi->ll_conn, sbi->ll_namespace, NULL, res_id,
184                           LDLM_EXTENT, &extent, LCK_PR, &flags, inode,
185                           sizeof(*inode), &lockh);
186         if (err != ELDLM_OK)
187                 CERROR("lock enqueue: err: %d\n", err);
188         ldlm_lock_dump((void *)(unsigned long)lockh.addr);
189
190         CDEBUG(D_INFO, "Reading inode %ld, %d bytes, offset %Ld\n",
191                inode->i_ino, count, *ppos);
192         retval = generic_file_read(filp, buf, count, ppos);
193         if (retval > 0) {
194                 struct iattr attr;
195                 attr.ia_valid = ATTR_ATIME;
196                 attr.ia_atime = CURRENT_TIME;
197                 ll_setattr(filp->f_dentry, &attr);
198         }
199
200         err = obd_cancel(&sbi->ll_conn, LCK_PR, &lockh);
201         if (err != ELDLM_OK)
202                 CERROR("lock cancel: err: %d\n", err);
203
204         RETURN(retval);
205 }
206
207 /*
208  * Write to a file (through the page cache).
209  */
210 static ssize_t
211 ll_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
212 {
213         struct inode *inode = file->f_dentry->d_inode;
214         struct ll_sb_info *sbi = ll_i2sbi(inode);
215         struct ldlm_extent extent;
216         struct ldlm_handle lockh;
217         __u64 res_id[RES_NAME_SIZE] = {inode->i_ino};
218         int flags = 0;
219         ldlm_error_t err;
220         ssize_t retval;
221         ENTRY;
222
223         extent.start = *ppos;
224         extent.end = *ppos + count;
225         CDEBUG(D_INFO, "Locking inode %ld, start %Lu end %Lu\n",
226                inode->i_ino, extent.start, extent.end);
227
228         err = obd_enqueue(&sbi->ll_conn, sbi->ll_namespace, NULL, res_id,
229                           LDLM_EXTENT, &extent, LCK_PW, &flags, inode,
230                           sizeof(*inode), &lockh);
231         if (err != ELDLM_OK)
232                 CERROR("lock enqueue: err: %d\n", err);
233         ldlm_lock_dump((void *)(unsigned long)lockh.addr);
234
235         CDEBUG(D_INFO, "Writing inode %ld, %ld bytes, offset %Ld\n",
236                inode->i_ino, (long)count, *ppos);
237
238         retval = generic_file_write(file, buf, count, ppos);
239
240         err = obd_cancel(&sbi->ll_conn, LCK_PW, &lockh);
241         if (err != ELDLM_OK)
242                 CERROR("lock cancel: err: %d\n", err);
243
244         RETURN(retval);
245 }
246
247 /* XXX this does not need to do anything for data, it _does_ need to
248    call setattr */
249 int ll_fsync(struct file *file, struct dentry *dentry, int data)
250 {
251         return 0;
252 }
253
254 struct file_operations ll_file_operations = {
255         read: ll_file_read,
256         write: ll_file_write,
257         open: ll_file_open,
258         release: ll_file_release,
259         mmap: generic_file_mmap,
260         fsync: NULL
261 };
262
263 struct inode_operations ll_file_inode_operations = {
264         truncate: ll_truncate,
265         setattr: ll_setattr
266 };