Whamcloud - gitweb
- move the peter branch changes to the head
[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
34 static int ll_file_open(struct inode *inode, struct file *file)
35 {
36         int rc;
37         struct ptlrpc_request *req = NULL;
38         struct ll_file_data *fd;
39         struct obdo *oa = NULL;
40         struct lov_stripe_md *md = NULL; 
41         struct ll_sb_info *sbi = ll_i2sbi(inode);
42         struct ll_inode_info *lli = ll_i2info(inode);
43         ENTRY;
44
45         if (file->private_data)
46                 LBUG();
47
48         /*  delayed create of object (intent created inode) */
49         /*  XXX object needs to be cleaned up if mdc_open fails */
50         /*  XXX error handling appropriate here? */
51         if (lli->lli_smd == NULL || lli->lli_smd->lmd_object_id == 0) {
52                 struct client_obd *mdc = sbi2mdc(ll_s2sbi(inode->i_sb));
53                 struct inode * inode = file->f_dentry->d_inode;
54
55                 lli->lli_smd = NULL; 
56                 oa =  obdo_alloc();
57                 if (!oa) { 
58                         RETURN(-ENOMEM);
59                 }
60                 oa->o_valid = OBD_MD_FLMODE;
61                 oa->o_mode = S_IFREG | 0600;
62                 oa->o_easize = mdc->cl_max_mdsize;
63                 rc = obd_create(ll_i2obdconn(inode), oa, &lli->lli_smd);
64                 if (rc)
65                         RETURN(rc);
66                 md = lli->lli_smd;
67                 lli->lli_flags &= ~OBD_FL_CREATEONOPEN;
68         }
69
70         fd = kmem_cache_alloc(ll_file_data_slab, SLAB_KERNEL);
71         if (!fd)
72                 GOTO(out, rc = -ENOMEM);
73         memset(fd, 0, sizeof(*fd));
74
75         rc = mdc_open(&sbi->ll_mdc_conn, inode->i_ino, S_IFREG | inode->i_mode,
76                       file->f_flags, md,
77                       (__u64)(unsigned long)file, &fd->fd_mdshandle, &req);
78         fd->fd_req = req;
79         ptlrpc_req_finished(req);
80         if (rc)
81                 GOTO(out_req, -abs(rc));
82         if (!fd->fd_mdshandle) {
83                 CERROR("mdc_open didn't assign fd_mdshandle\n");
84                 /* XXX handle this how, abort or is it non-fatal? */
85         }
86         if (!fd->fd_mdshandle)
87                 CERROR("mdc_open didn't assign fd_mdshandle\n");
88
89         if (oa == NULL) {
90                 oa =  obdo_alloc();
91                 if (!oa)
92                         GOTO(out_mdc, rc = -EINVAL);
93         }
94         oa->o_id = lli->lli_smd->lmd_object_id;
95         oa->o_mode = S_IFREG | inode->i_mode;
96         rc = obd_open(ll_i2obdconn(inode), oa, lli->lli_smd);
97         obdo_free(oa);
98         oa = NULL;
99
100         if (rc)
101                 GOTO(out_mdc, rc = -abs(rc));
102
103         file->private_data = fd;
104
105         EXIT;
106
107         return 0;
108 out_mdc:
109         mdc_close(&sbi->ll_mdc_conn, inode->i_ino,
110                   S_IFREG, fd->fd_mdshandle, &req);
111 out_req:
112         ptlrpc_free_req(req);
113 //out_fd:
114         if (oa)
115                 obdo_free(oa);
116         kmem_cache_free(ll_file_data_slab, fd);
117         file->private_data = NULL;
118 out:
119         return rc;
120 }
121
122 static int ll_file_release(struct inode *inode, struct file *file)
123 {
124         int rc;
125         struct ptlrpc_request *req = NULL;
126         struct ll_file_data *fd;
127         struct obdo *oa;
128         struct ll_sb_info *sbi = ll_i2sbi(inode);
129         struct ll_inode_info *lli = ll_i2info(inode);
130
131         ENTRY;
132
133         fd = (struct ll_file_data *)file->private_data;
134         if (!fd || !fd->fd_mdshandle) {
135                 LBUG();
136                 GOTO(out, rc = -EINVAL);
137         }
138
139         oa = obdo_alloc();
140         if (oa == NULL) {
141                 LBUG();
142                 GOTO(out_fd, rc = -ENOENT);
143         }
144         rc = obd_close(ll_i2obdconn(inode), oa, lli->lli_smd);
145         obdo_free(oa); 
146         if (rc)
147                 GOTO(out_fd, abs(rc));
148
149         if (file->f_mode & FMODE_WRITE) {
150                 struct iattr attr;
151                 attr.ia_valid = ATTR_MTIME | ATTR_CTIME | ATTR_ATIME | ATTR_SIZE;
152                 attr.ia_mtime = inode->i_mtime;
153                 attr.ia_ctime = inode->i_ctime;
154                 attr.ia_atime = inode->i_atime;
155                 attr.ia_size = inode->i_size;
156
157                 /* XXX: this introduces a small race that we should evaluate */
158                 rc = ll_inode_setattr(inode, &attr, 0);
159                 if (rc) {
160                         CERROR("failed - %d.\n", rc);
161                         rc = -EIO; /* XXX - GOTO(out)? -phil */
162                 }
163         }
164
165         rc = mdc_close(&sbi->ll_mdc_conn, inode->i_ino,
166                        S_IFREG, fd->fd_mdshandle, &req);
167         ptlrpc_req_finished(req);
168         if (rc) {
169                 if (rc > 0)
170                         rc = -rc;
171                 GOTO(out, rc);
172         }
173         ptlrpc_free_req(fd->fd_req);
174
175         EXIT;
176
177 out_fd:
178         kmem_cache_free(ll_file_data_slab, fd);
179         file->private_data = NULL;
180 out:
181         return rc;
182 }
183
184
185 static inline void ll_remove_suid(struct inode *inode)
186 {
187         unsigned int mode;
188
189         /* set S_IGID if S_IXGRP is set, and always set S_ISUID */
190         mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID;
191
192         /* was any of the uid bits set? */
193         mode &= inode->i_mode;
194         if (mode && !capable(CAP_FSETID)) {
195                 inode->i_mode &= ~mode;
196                 // XXX careful here - we cannot change the size
197         }
198 }
199
200 static void ll_update_atime(struct inode *inode)
201 {
202         struct iattr attr;
203
204         attr.ia_atime = CURRENT_TIME;
205         attr.ia_valid = ATTR_ATIME;
206
207         if (inode->i_atime == attr.ia_atime) return;
208         if (IS_RDONLY(inode)) return;
209         if (IS_NOATIME(inode)) return;
210
211         /* ll_inode_setattr() sets inode->i_atime from attr.ia_atime */
212         ll_inode_setattr(inode, &attr, 0);
213 }
214
215 static int ll_lock_callback(struct lustre_handle *lockh,
216                             struct ldlm_lock_desc *new,
217                             void *data, __u32 data_len,
218                             struct ptlrpc_request **reqp)
219 {
220         struct inode *inode = data;
221         ENTRY;
222
223         if (new == NULL) {
224                 /* Completion AST.  Do nothing. */
225                 RETURN(0);
226         }
227
228         if (data_len != sizeof(struct inode))
229                 LBUG();
230
231         /* FIXME: do something better than throwing away everything */
232         if (inode == NULL)
233                 LBUG();
234         down(&inode->i_sem);
235         CDEBUG(D_INODE, "invalidating obdo/inode %ld\n", inode->i_ino);
236         invalidate_inode_pages(inode);
237         up(&inode->i_sem);
238
239         if (ldlm_cli_cancel(lockh) < 0)
240                 LBUG();
241         RETURN(0);
242 }
243
244 static ssize_t ll_file_read(struct file *filp, char *buf, size_t count,
245                             loff_t *ppos)
246 {
247         struct ll_file_data *fd = (struct ll_file_data *)filp->private_data;
248         struct inode *inode = filp->f_dentry->d_inode;
249         struct ll_sb_info *sbi = ll_i2sbi(inode);
250         struct ldlm_extent extent;
251         struct lustre_handle lockh;
252         __u64 res_id[RES_NAME_SIZE] = {inode->i_ino};
253         int flags = 0;
254         ldlm_error_t err;
255         ssize_t retval;
256         ENTRY;
257
258         if (!(fd->fd_flags & LL_FILE_IGNORE_LOCK)) {
259                 extent.start = *ppos;
260                 extent.end = *ppos + count;
261                 CDEBUG(D_INFO, "Locking inode %ld, start %Lu end %Lu\n",
262                        inode->i_ino, extent.start, extent.end);
263
264                 err = obd_enqueue(&sbi->ll_osc_conn, NULL, res_id, LDLM_EXTENT,
265                                   &extent, sizeof(extent), LCK_PR, &flags,
266                                   ll_lock_callback, inode, sizeof(*inode),
267                                   &lockh);
268                 if (err != ELDLM_OK) {
269                         CERROR("lock enqueue: err: %d\n", err);
270                         RETURN(err);
271                 }
272                 ldlm_lock_dump((void *)(unsigned long)lockh.addr);
273         }
274
275         CDEBUG(D_INFO, "Reading inode %ld, %d bytes, offset %Ld\n",
276                inode->i_ino, count, *ppos);
277         retval = generic_file_read(filp, buf, count, ppos);
278
279         if (retval > 0)
280                 ll_update_atime(inode);
281
282         if (!(fd->fd_flags & LL_FILE_IGNORE_LOCK)) {
283                 err = obd_cancel(&sbi->ll_osc_conn, LCK_PR, &lockh);
284                 if (err != ELDLM_OK) {
285                         CERROR("lock cancel: err: %d\n", err);
286                         RETURN(err);
287                 }
288         }
289
290         RETURN(retval);
291 }
292
293 /*
294  * Write to a file (through the page cache).
295  */
296 static ssize_t
297 ll_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
298 {
299         struct ll_file_data *fd = (struct ll_file_data *)file->private_data;
300         struct inode *inode = file->f_dentry->d_inode;
301         struct ll_sb_info *sbi = ll_i2sbi(inode);
302         struct ldlm_extent extent;
303         struct lustre_handle lockh;
304         __u64 res_id[RES_NAME_SIZE] = {inode->i_ino};
305         int flags = 0;
306         ldlm_error_t err;
307         ssize_t retval;
308         ENTRY;
309
310         if (!(fd->fd_flags & LL_FILE_IGNORE_LOCK)) {
311                 /* FIXME: this should check whether O_APPEND is set and adjust
312                  * extent.start accordingly */
313                 extent.start = *ppos;
314                 extent.end = *ppos + count;
315                 CDEBUG(D_INFO, "Locking inode %ld, start %Lu end %Lu\n",
316                        inode->i_ino, extent.start, extent.end);
317
318                 err = obd_enqueue(&sbi->ll_osc_conn, NULL, res_id, LDLM_EXTENT,
319                                   &extent, sizeof(extent), LCK_PW, &flags,
320                                   ll_lock_callback, inode, sizeof(*inode),
321                                   &lockh);
322                 if (err != ELDLM_OK) {
323                         CERROR("lock enqueue: err: %d\n", err);
324                         RETURN(err);
325                 }
326                 ldlm_lock_dump((void *)(unsigned long)lockh.addr);
327         }
328
329         CDEBUG(D_INFO, "Writing inode %ld, %ld bytes, offset %Ld\n",
330                inode->i_ino, (long)count, *ppos);
331
332         retval = generic_file_write(file, buf, count, ppos);
333
334         if (!(fd->fd_flags & LL_FILE_IGNORE_LOCK)) {
335                 err = obd_cancel(&sbi->ll_osc_conn, LCK_PW, &lockh);
336                 if (err != ELDLM_OK) {
337                         CERROR("lock cancel: err: %d\n", err);
338                         RETURN(err);
339                 }
340         }
341
342         RETURN(retval);
343 }
344
345 int ll_file_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
346                   unsigned long arg)
347 {
348         struct ll_file_data *fd = (struct ll_file_data *)file->private_data;
349         int flags;
350
351         switch(cmd) {
352         case LL_IOC_GETFLAGS:
353                 /* Get the current value of the file flags */
354                 return put_user(fd->fd_flags, (int *)arg);
355         case LL_IOC_SETFLAGS:
356         case LL_IOC_CLRFLAGS:
357                 /* Set or clear specific file flags */
358                 /* XXX This probably needs checks to ensure the flags are
359                  *     not abused, and to handle any flag side effects.
360                  */
361                 if (get_user(flags, (int *) arg))
362                         return -EFAULT;
363
364                 if (cmd == LL_IOC_SETFLAGS)
365                         fd->fd_flags |= flags;
366                 else
367                         fd->fd_flags &= ~flags;
368                 return 0;
369
370         /* We need to special case any other ioctls we want to handle,
371          * to send them to the MDS/OST as appropriate and to properly
372          * network encode the arg field.
373         case EXT2_IOC_GETFLAGS:
374         case EXT2_IOC_SETFLAGS:
375         case EXT2_IOC_GETVERSION_OLD:
376         case EXT2_IOC_GETVERSION_NEW:
377         case EXT2_IOC_SETVERSION_OLD:
378         case EXT2_IOC_SETVERSION_NEW:
379         */
380         default:
381                 return -ENOTTY;
382         }
383 }
384
385 /* XXX this does not need to do anything for data, it _does_ need to
386    call setattr */
387 int ll_fsync(struct file *file, struct dentry *dentry, int data)
388 {
389         return 0;
390 }
391
392 struct file_operations ll_file_operations = {
393         read:           ll_file_read,
394         write:          ll_file_write,
395         ioctl:          ll_file_ioctl,
396         open:           ll_file_open,
397         release:        ll_file_release,
398         mmap:           generic_file_mmap,
399         fsync:          NULL
400 };
401
402 struct inode_operations ll_file_inode_operations = {
403         truncate: ll_truncate,
404         setattr: ll_setattr
405 };