4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
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
27 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2011, 2013, Intel Corporation.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lustre/liblustre/rw.c
38 * Lustre Light block IO
41 #define DEBUG_SUBSYSTEM S_LLITE
51 #include <sys/types.h>
53 #include <libcfs/libcfs.h>
54 #include <lustre/lustre_idl.h>
55 #include <liblustre.h>
56 #include <cl_object.h>
58 #include <lustre_dlm.h>
60 #include <obd_class.h>
61 #include <obd_support.h>
62 #include "llite_lib.h"
64 int llu_merge_lvb(const struct lu_env *env, struct inode *inode)
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);
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;
80 inode_init_lvb(inode, &lvb);
82 cl_object_attr_lock(obj);
83 rc = cl_object_attr_get(env, obj, attr);
84 cl_object_attr_unlock(obj);
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;
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;
104 ssize_t llu_file_prwv(const struct iovec *iovec, int iovlen,
105 _SYSIO_OFF_T pos, ssize_t len,
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);
118 /* in a large iov read/write we'll be repeatedly called.
119 * so give a chance to answer cancel ast here
121 liblustre_wait_event(0);
123 if (len == 0 || iovlen == 0)
126 if (pos + len > lli->lli_maxbytes)
129 env = cl_env_get(&refcheck);
131 RETURN(PTR_ERR(env));
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:
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);
152 cl_env_put(env, &refcheck);
161 struct llu_io_session *get_io_session(struct inode *ino, int ngroups, int cmd)
163 struct llu_io_session *session;
165 OBD_ALLOC_PTR(session);
170 session->lis_inode = ino;
171 session->lis_cmd = cmd;
175 static void put_io_session(struct llu_io_session *session)
177 I_RELE(session->lis_inode);
178 OBD_FREE_PTR(session);
181 static int llu_file_rwx(struct inode *ino,
185 struct llu_io_session *session;
187 int cmd = read ? OBD_BRW_READ : OBD_BRW_WRITE;
190 LASSERT(ioctx->ioctx_iovlen > 0);
192 liblustre_wait_event(0);
194 if (ioctx->ioctx_xtvlen == 0)
197 /* XXX consider other types later */
198 if (S_ISDIR(llu_i2stat(ino)->st_mode))
200 if (!S_ISREG(llu_i2stat(ino)->st_mode))
203 session = get_io_session(ino, ioctx->ioctx_xtvlen * 2, cmd);
207 cc = _sysio_enumerate_extents(ioctx->ioctx_xtv, ioctx->ioctx_xtvlen,
208 ioctx->ioctx_iov, ioctx->ioctx_iovlen,
209 llu_file_prwv, session);
212 LASSERT(!ioctx->ioctx_cc);
213 ioctx->ioctx_private = session;
216 put_io_session(session);
219 liblustre_wait_event(0);
223 void llu_io_init(struct cl_io *io, struct inode *inode, int write)
225 struct llu_inode_info *lli = llu_i2info(inode);
227 io->u.ci_rw.crw_nonblock = lli->lli_open_flags & O_NONBLOCK;
229 io->u.ci_wr.wr_append = lli->lli_open_flags & O_APPEND;
230 io->ci_obj = llu_i2info(inode)->lli_clob;
232 if ((lli->lli_open_flags & O_APPEND) && write)
233 io->ci_lockreq = CILR_MANDATORY;
235 io->ci_lockreq = CILR_NEVER;
238 int llu_iop_read(struct inode *ino,
241 struct intnl_stat *st = llu_i2stat(ino);
248 st->st_atime = CFS_CURRENT_TIME;
250 env = cl_env_get(&refcheck);
252 RETURN(PTR_ERR(env));
254 io = ccc_env_thread_io(env);
255 llu_io_init(io, ino, 0);
257 ret = llu_file_rwx(ino, ioctx, 1);
259 cl_env_put(env, &refcheck);
263 int llu_iop_write(struct inode *ino,
266 struct intnl_stat *st = llu_i2stat(ino);
272 st->st_mtime = st->st_ctime = CFS_CURRENT_TIME;
274 env = cl_env_get(&refcheck);
276 RETURN(PTR_ERR(env));
278 io = ccc_env_thread_io(env);
279 llu_io_init(io, ino, 1);
281 ret = llu_file_rwx(ino, ioctx, 0);
282 cl_env_put(env, &refcheck);
286 int llu_iop_iodone(struct ioctx *ioctx)
288 struct llu_io_session *session;
294 liblustre_wait_event(0);
296 env = cl_env_get(&refcheck);
298 RETURN(PTR_ERR(env));
300 io = &ccc_env_info(env)->cti_io;
302 cl_env_put(env, &refcheck);
303 session = (struct llu_io_session *) ioctx->ioctx_private;
305 LASSERT(!IS_ERR(session));
307 if (session->lis_rc == 0) {
308 ioctx->ioctx_cc = session->lis_rwcount;
310 LASSERT(session->lis_rc < 0);
311 ioctx->ioctx_cc = -1;
312 ioctx->ioctx_errno = -session->lis_rc;
315 put_io_session(session);
316 ioctx->ioctx_private = NULL;
317 liblustre_wait_event(0);