Whamcloud - gitweb
LU-4629 osc: remove constant checks
[fs/lustre-release.git] / lustre / liblustre / rw.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2011, 2013, Intel Corporation.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/liblustre/rw.c
37  *
38  * Lustre Light block IO
39  */
40
41 #define DEBUG_SUBSYSTEM S_LLITE
42
43 #include <assert.h>
44 #include <errno.h>
45 #include <fcntl.h>
46 #include <stddef.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <time.h>
50 #include <sys/stat.h>
51 #include <sys/types.h>
52 #include <sys/uio.h>
53 #include <libcfs/libcfs.h>
54 #include <lustre/lustre_idl.h>
55 #include <liblustre.h>
56 #include <cl_object.h>
57 #include <lclient.h>
58 #include <lustre_dlm.h>
59 #include <obd.h>
60 #include <obd_class.h>
61 #include <obd_support.h>
62 #include "llite_lib.h"
63
64 int llu_merge_lvb(const struct lu_env *env, struct inode *inode)
65 {
66         struct llu_inode_info *lli = llu_i2info(inode);
67         struct cl_object *obj = lli->lli_clob;
68         struct intnl_stat *st = llu_i2stat(inode);
69         struct cl_attr *attr = ccc_env_thread_attr(env);
70         struct ost_lvb lvb;
71         int rc;
72         ENTRY;
73
74         /* merge timestamps the most recently obtained from mds with
75            timestamps obtained from osts */
76         LTIME_S(inode->i_atime) = lli->lli_lvb.lvb_atime;
77         LTIME_S(inode->i_mtime) = lli->lli_lvb.lvb_mtime;
78         LTIME_S(inode->i_ctime) = lli->lli_lvb.lvb_ctime;
79
80         inode_init_lvb(inode, &lvb);
81
82         cl_object_attr_lock(obj);
83         rc = cl_object_attr_get(env, obj, attr);
84         cl_object_attr_unlock(obj);
85         if (rc == 0) {
86                 if (lvb.lvb_atime < attr->cat_atime)
87                         lvb.lvb_atime = attr->cat_atime;
88                 if (lvb.lvb_ctime < attr->cat_ctime)
89                         lvb.lvb_ctime = attr->cat_ctime;
90                 if (lvb.lvb_mtime < attr->cat_mtime)
91                         lvb.lvb_mtime = attr->cat_mtime;
92
93                 st->st_size = lvb.lvb_size;
94                 st->st_blocks = lvb.lvb_blocks;
95                 st->st_mtime = lvb.lvb_mtime;
96                 st->st_atime = lvb.lvb_atime;
97                 st->st_ctime = lvb.lvb_ctime;
98         }
99
100         RETURN(rc);
101 }
102
103 static
104 ssize_t llu_file_prwv(const struct iovec *iovec, int iovlen,
105                         _SYSIO_OFF_T pos, ssize_t len,
106                         void *private)
107 {
108         struct llu_io_session *session = (struct llu_io_session *) private;
109         struct inode *inode = session->lis_inode;
110         struct llu_inode_info *lli = llu_i2info(inode);
111         int err;
112         struct lu_env *env;
113         struct cl_io  *io;
114         struct slp_io *sio;
115         int refcheck;
116         ENTRY;
117
118         /* in a large iov read/write we'll be repeatedly called.
119          * so give a chance to answer cancel ast here
120          */
121         liblustre_wait_event(0);
122
123         if (len == 0 || iovlen == 0)
124                 RETURN(0);
125
126         if (pos + len > lli->lli_maxbytes)
127                 RETURN(-ERANGE);
128
129         env = cl_env_get(&refcheck);
130         if (IS_ERR(env))
131                 RETURN(PTR_ERR(env));
132
133         /* Do NOT call "ccc_env_thread_io()" again to prevent reinitializing */
134         io = &ccc_env_info(env)->cti_io;
135         if (cl_io_rw_init(env, io, session->lis_cmd == OBD_BRW_WRITE?CIT_WRITE:
136                                                                       CIT_READ,
137                           pos, len) == 0) {
138                 struct ccc_io *cio;
139                 sio = slp_env_io(env);
140                 cio = ccc_env_io(env);
141                 /* XXX this is not right: cio->cui_iov can be modified. */
142                 cio->cui_iov = (struct iovec *)iovec;
143                 cio->cui_nrsegs = iovlen;
144                 cio->cui_tot_nrsegs = iovlen;
145                 sio->sio_session = session;
146                 err = cl_io_loop(env, io);
147         } else {
148                 /* XXX WTF? */
149                 LBUG();
150         }
151         cl_io_fini(env, io);
152         cl_env_put(env, &refcheck);
153
154         if (err < 0)
155                 RETURN(err);
156
157         RETURN(len);
158 }
159
160 static
161 struct llu_io_session *get_io_session(struct inode *ino, int ngroups, int cmd)
162 {
163         struct llu_io_session *session;
164
165         OBD_ALLOC_PTR(session);
166         if (!session)
167                 return NULL;
168
169         I_REF(ino);
170         session->lis_inode = ino;
171         session->lis_cmd = cmd;
172         return session;
173 }
174
175 static void put_io_session(struct llu_io_session *session)
176 {
177         I_RELE(session->lis_inode);
178         OBD_FREE_PTR(session);
179 }
180
181 static int llu_file_rwx(struct inode *ino,
182                         struct ioctx *ioctx,
183                         int read)
184 {
185         struct llu_io_session *session;
186         ssize_t cc;
187         int cmd = read ? OBD_BRW_READ : OBD_BRW_WRITE;
188         ENTRY;
189
190         LASSERT(ioctx->ioctx_iovlen > 0);
191
192         liblustre_wait_event(0);
193
194         if (ioctx->ioctx_xtvlen == 0)
195                 RETURN(0);
196
197         /* XXX consider other types later */
198         if (S_ISDIR(llu_i2stat(ino)->st_mode))
199                 RETURN(-EISDIR);
200         if (!S_ISREG(llu_i2stat(ino)->st_mode))
201                 RETURN(-EOPNOTSUPP);
202
203         session = get_io_session(ino, ioctx->ioctx_xtvlen * 2, cmd);
204         if (!session)
205                 RETURN(-ENOMEM);
206
207         cc = _sysio_enumerate_extents(ioctx->ioctx_xtv, ioctx->ioctx_xtvlen,
208                                       ioctx->ioctx_iov, ioctx->ioctx_iovlen,
209                                       llu_file_prwv, session);
210
211         if (cc >= 0) {
212                 LASSERT(!ioctx->ioctx_cc);
213                 ioctx->ioctx_private = session;
214                 cc = 0;
215         } else {
216                 put_io_session(session);
217         }
218
219         liblustre_wait_event(0);
220         RETURN(cc);
221 }
222
223 void llu_io_init(struct cl_io *io, struct inode *inode, int write)
224 {
225         struct llu_inode_info *lli = llu_i2info(inode);
226
227         io->u.ci_rw.crw_nonblock = lli->lli_open_flags & O_NONBLOCK;
228         if (write)
229                 io->u.ci_wr.wr_append = lli->lli_open_flags & O_APPEND;
230         io->ci_obj  = llu_i2info(inode)->lli_clob;
231
232         if ((lli->lli_open_flags & O_APPEND) && write)
233                 io->ci_lockreq = CILR_MANDATORY;
234         else
235                 io->ci_lockreq = CILR_NEVER;
236 }
237
238 int llu_iop_read(struct inode *ino,
239                  struct ioctx *ioctx)
240 {
241         struct intnl_stat *st = llu_i2stat(ino);
242         struct lu_env *env;
243         struct cl_io  *io;
244         int refcheck;
245         int ret;
246
247         /* BUG: 5972 */
248         st->st_atime = CFS_CURRENT_TIME;
249
250         env = cl_env_get(&refcheck);
251         if (IS_ERR(env))
252                 RETURN(PTR_ERR(env));
253
254         io = ccc_env_thread_io(env);
255         llu_io_init(io, ino, 0);
256
257         ret = llu_file_rwx(ino, ioctx, 1);
258
259         cl_env_put(env, &refcheck);
260         return ret;
261 }
262
263 int llu_iop_write(struct inode *ino,
264                   struct ioctx *ioctx)
265 {
266         struct intnl_stat *st = llu_i2stat(ino);
267         struct lu_env *env;
268         struct cl_io  *io;
269         int refcheck;
270         int ret;
271
272         st->st_mtime = st->st_ctime = CFS_CURRENT_TIME;
273
274         env = cl_env_get(&refcheck);
275         if (IS_ERR(env))
276                 RETURN(PTR_ERR(env));
277
278         io = ccc_env_thread_io(env);
279         llu_io_init(io, ino, 1);
280
281         ret = llu_file_rwx(ino, ioctx, 0);
282         cl_env_put(env, &refcheck);
283         return ret;
284 }
285
286 int llu_iop_iodone(struct ioctx *ioctx)
287 {
288         struct llu_io_session *session;
289         struct lu_env *env;
290         struct cl_io  *io;
291         int refcheck;
292         ENTRY;
293
294         liblustre_wait_event(0);
295
296         env = cl_env_get(&refcheck);
297         if (IS_ERR(env))
298                 RETURN(PTR_ERR(env));
299
300         io = &ccc_env_info(env)->cti_io;
301         cl_io_fini(env, io);
302         cl_env_put(env, &refcheck);
303         session = (struct llu_io_session *) ioctx->ioctx_private;
304         LASSERT(session);
305         LASSERT(!IS_ERR(session));
306
307         if (session->lis_rc == 0) {
308                 ioctx->ioctx_cc = session->lis_rwcount;
309         } else {
310                 LASSERT(session->lis_rc < 0);
311                 ioctx->ioctx_cc = -1;
312                 ioctx->ioctx_errno = -session->lis_rc;
313         }
314
315         put_io_session(session);
316         ioctx->ioctx_private = NULL;
317         liblustre_wait_event(0);
318
319         RETURN(1);
320 }