Whamcloud - gitweb
672b38c3fc722b52733547ae53a80615a60102c6
[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 #include <asm/uaccess.h>
27 #include <asm/system.h>
28
29 #include <linux/errno.h>
30 #include <linux/fs.h>
31 #include <linux/fcntl.h>
32 #include <linux/sched.h>
33 #include <linux/stat.h>
34 #include <linux/locks.h>
35 #include <linux/mm.h>
36 #include <linux/pagemap.h>
37 #include <linux/smp_lock.h>
38
39 #define DEBUG_SUBSYSTEM S_LLITE
40
41 #include <linux/obd_support.h>
42 #include <linux/lustre_lite.h>
43
44 int ll_inode_setattr(struct inode *inode, struct iattr *attr, int do_trunc);
45 extern int ll_setattr(struct dentry *de, struct iattr *attr);
46 extern inline struct obdo * ll_oa_from_inode(struct inode *inode,
47                                              unsigned long valid);
48
49 static int ll_file_open(struct inode *inode, struct file *file)
50 {
51         int rc; 
52         struct ptlrpc_request *req = NULL;
53         struct ll_file_data *fd;
54         struct obdo *oa;
55         struct ll_sb_info *sbi = ll_i2sbi(inode);
56         ENTRY;
57
58         if (file->private_data) 
59                 LBUG();
60
61         fd = kmem_cache_alloc(ll_file_data_slab, SLAB_KERNEL); 
62         if (!fd)
63                 GOTO(out, rc = -ENOMEM);
64         memset(fd, 0, sizeof(*fd));
65
66         rc = mdc_open(&sbi->ll_mds_client, sbi->ll_mds_conn, inode->i_ino,
67                       S_IFREG, file->f_flags, &fd->fd_mdshandle, &req); 
68         fd->fd_req = req;
69         ptlrpc_req_finished(req);
70         if (rc) {
71                 if (rc > 0) 
72                         rc = -rc;
73                 GOTO(out, rc);
74         }
75         if (!fd->fd_mdshandle)
76                 CERROR("mdc_open didn't assign fd_mdshandle\n");
77         
78
79         oa = ll_oa_from_inode(inode, (OBD_MD_FLMODE | OBD_MD_FLID));
80         if (oa == NULL)
81                 LBUG();
82         rc = obd_open(ll_i2obdconn(inode), oa); 
83         obdo_free(oa);
84         if (rc) {
85                 /* XXX: Need to do mdc_close here! */
86                 if (rc > 0) 
87                         rc = -rc;
88                 GOTO(out, rc);
89         }
90
91         file->private_data = fd;
92
93         EXIT; 
94  out:
95         if (rc && fd) {
96                 kmem_cache_free(ll_file_data_slab, fd); 
97                 file->private_data = NULL;
98         }
99
100         return rc;
101 }
102
103 static int ll_file_release(struct inode *inode, struct file *file)
104 {
105         int rc;
106         struct ptlrpc_request *req = NULL;
107         struct ll_file_data *fd;
108         struct obdo *oa;
109         struct ll_sb_info *sbi = ll_i2sbi(inode);
110         struct iattr iattr;
111
112         ENTRY;
113
114         fd = (struct ll_file_data *)file->private_data;
115         if (!fd || !fd->fd_mdshandle) { 
116                 LBUG();
117                 GOTO(out, rc = -EINVAL);
118         }
119
120         oa = ll_oa_from_inode(inode, (OBD_MD_FLMODE | OBD_MD_FLID));
121         if (oa == NULL)
122                 LBUG();
123         rc = obd_close(ll_i2obdconn(inode), oa); 
124         obdo_free(oa);
125         if (rc) { 
126                 if (rc > 0) 
127                         rc = -rc;
128                 GOTO(out, rc);
129         }
130
131         iattr.ia_valid = ATTR_SIZE;
132         iattr.ia_size = inode->i_size;
133         rc = ll_inode_setattr(inode, &iattr, 0);
134         if (rc) {
135                 CERROR("failed - %d.\n", rc);
136                 rc = -EIO;
137         }
138
139         rc = mdc_close(&sbi->ll_mds_client, sbi->ll_mds_conn, inode->i_ino,
140                        S_IFREG, fd->fd_mdshandle, &req);
141         ptlrpc_req_finished(req);
142         if (rc) { 
143                 if (rc > 0) 
144                         rc = -rc;
145                 GOTO(out, rc);
146         }
147         ptlrpc_free_req(fd->fd_req);
148
149         EXIT; 
150
151  out:
152         if (!rc && fd) { 
153                 kmem_cache_free(ll_file_data_slab, fd); 
154                 file->private_data = NULL;
155         }
156         return rc;
157 }
158
159
160 static inline void ll_remove_suid(struct inode *inode)
161 {
162         unsigned int mode;
163
164         /* set S_IGID if S_IXGRP is set, and always set S_ISUID */
165         mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID;
166
167         /* was any of the uid bits set? */
168         mode &= inode->i_mode;
169         if (mode && !capable(CAP_FSETID)) {
170                 inode->i_mode &= ~mode;
171                 // XXX careful here - we cannot change the size
172         }
173 }
174
175
176 /*
177  * Write to a file (through the page cache).
178  */
179 static ssize_t
180 ll_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
181 {
182         ssize_t retval;
183         CDEBUG(D_INFO, "Writing inode %ld, %ld bytes, offset %Ld\n",
184                file->f_dentry->d_inode->i_ino, (long)count, *ppos);
185
186         retval = generic_file_write(file, buf, count, ppos);
187         CDEBUG(D_INFO, "Wrote %ld\n", (long)retval);
188
189         /* update mtime/ctime/atime here, NOT size */
190         if (retval > 0) {
191                 struct iattr attr;
192                 attr.ia_valid = ATTR_MTIME | ATTR_CTIME | ATTR_ATIME;
193                 attr.ia_mtime = attr.ia_ctime = attr.ia_atime =
194                         CURRENT_TIME;
195                 ll_setattr(file->f_dentry, &attr);
196         }
197         EXIT;
198         return retval;
199 }
200
201
202 /* XXX this does not need to do anything for data, it _does_ need to
203    call setattr */ 
204 int ll_fsync(struct file *file, struct dentry *dentry, int data)
205 {
206         return 0;
207 }
208
209 struct file_operations ll_file_operations = {
210         read: generic_file_read,
211         write: ll_file_write,
212         open: ll_file_open,
213         release: ll_file_release,
214         mmap: generic_file_mmap,
215         fsync: NULL
216 };
217
218
219 struct inode_operations ll_file_inode_operations = {
220         truncate: ll_truncate,
221         setattr: ll_setattr
222 };
223