1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43#include "../../include/linux/libcfs/libcfs.h"
44#include "../include/obd_class.h"
45#include "../include/obd_support.h"
46#include "../include/obd.h"
47
48#include "../include/lustre_dlm.h"
49#include "../include/lustre_lite.h"
50#include "../include/lustre_mdc.h"
51#include <linux/pagemap.h>
52#include <linux/file.h>
53
54#include "../include/cl_object.h"
55#include "../include/lclient.h"
56#include "../llite/llite_internal.h"
57
58static const struct cl_lock_descr whole_file = {
59 .cld_start = 0,
60 .cld_end = CL_PAGE_EOF,
61 .cld_mode = CLM_READ
62};
63
64
65
66
67
68
69
70blkcnt_t dirty_cnt(struct inode *inode)
71{
72 blkcnt_t cnt = 0;
73 struct ccc_object *vob = cl_inode2ccc(inode);
74 void *results[1];
75
76 if (inode->i_mapping)
77 cnt += radix_tree_gang_lookup_tag(&inode->i_mapping->page_tree,
78 results, 0, 1,
79 PAGECACHE_TAG_DIRTY);
80 if (cnt == 0 && atomic_read(&vob->cob_mmap_cnt) > 0)
81 cnt = 1;
82
83 return (cnt > 0) ? 1 : 0;
84}
85
86int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io,
87 struct inode *inode, struct cl_object *clob, int agl)
88{
89 struct cl_lock_descr *descr = &ccc_env_info(env)->cti_descr;
90 struct cl_inode_info *lli = cl_i2info(inode);
91 const struct lu_fid *fid = lu_object_fid(&clob->co_lu);
92 struct ccc_io *cio = ccc_env_io(env);
93 struct cl_lock *lock;
94 int result;
95
96 result = 0;
97 if (!(lli->lli_flags & LLIF_MDS_SIZE_LOCK)) {
98 CDEBUG(D_DLMTRACE, "Glimpsing inode "DFID"\n", PFID(fid));
99 if (lli->lli_has_smd) {
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114 *descr = whole_file;
115 descr->cld_obj = clob;
116 descr->cld_mode = CLM_PHANTOM;
117 descr->cld_enq_flags = CEF_ASYNC | CEF_MUST;
118 if (agl)
119 descr->cld_enq_flags |= CEF_AGL;
120 cio->cui_glimpse = 1;
121
122
123
124
125
126
127
128
129 lock = cl_lock_request(env, io, descr, "glimpse",
130 current);
131 cio->cui_glimpse = 0;
132
133 if (!lock)
134 return 0;
135
136 if (IS_ERR(lock))
137 return PTR_ERR(lock);
138
139 LASSERT(agl == 0);
140 result = cl_wait(env, lock);
141 if (result == 0) {
142 cl_merge_lvb(env, inode);
143 if (cl_isize_read(inode) > 0 &&
144 inode->i_blocks == 0) {
145
146
147
148
149
150
151 inode->i_blocks = dirty_cnt(inode);
152 }
153 cl_unuse(env, lock);
154 }
155 cl_lock_release(env, lock, "glimpse", current);
156 } else {
157 CDEBUG(D_DLMTRACE, "No objects for inode\n");
158 cl_merge_lvb(env, inode);
159 }
160 }
161
162 return result;
163}
164
165static int cl_io_get(struct inode *inode, struct lu_env **envout,
166 struct cl_io **ioout, int *refcheck)
167{
168 struct lu_env *env;
169 struct cl_io *io;
170 struct cl_inode_info *lli = cl_i2info(inode);
171 struct cl_object *clob = lli->lli_clob;
172 int result;
173
174 if (S_ISREG(cl_inode_mode(inode))) {
175 env = cl_env_get(refcheck);
176 if (!IS_ERR(env)) {
177 io = ccc_env_thread_io(env);
178 io->ci_obj = clob;
179 *envout = env;
180 *ioout = io;
181 result = 1;
182 } else
183 result = PTR_ERR(env);
184 } else
185 result = 0;
186 return result;
187}
188
189int cl_glimpse_size0(struct inode *inode, int agl)
190{
191
192
193
194
195
196
197
198
199
200
201 struct lu_env *env = NULL;
202 struct cl_io *io = NULL;
203 int result;
204 int refcheck;
205
206 result = cl_io_get(inode, &env, &io, &refcheck);
207 if (result > 0) {
208again:
209 io->ci_verify_layout = 1;
210 result = cl_io_init(env, io, CIT_MISC, io->ci_obj);
211 if (result > 0)
212
213
214
215
216 result = io->ci_result;
217 else if (result == 0)
218 result = cl_glimpse_lock(env, io, inode, io->ci_obj,
219 agl);
220
221 OBD_FAIL_TIMEOUT(OBD_FAIL_GLIMPSE_DELAY, 2);
222 cl_io_fini(env, io);
223 if (unlikely(io->ci_need_restart))
224 goto again;
225 cl_env_put(env, &refcheck);
226 }
227 return result;
228}
229
230int cl_local_size(struct inode *inode)
231{
232 struct lu_env *env = NULL;
233 struct cl_io *io = NULL;
234 struct ccc_thread_info *cti;
235 struct cl_object *clob;
236 struct cl_lock_descr *descr;
237 struct cl_lock *lock;
238 int result;
239 int refcheck;
240
241 if (!cl_i2info(inode)->lli_has_smd)
242 return 0;
243
244 result = cl_io_get(inode, &env, &io, &refcheck);
245 if (result <= 0)
246 return result;
247
248 clob = io->ci_obj;
249 result = cl_io_init(env, io, CIT_MISC, clob);
250 if (result > 0)
251 result = io->ci_result;
252 else if (result == 0) {
253 cti = ccc_env_info(env);
254 descr = &cti->cti_descr;
255
256 *descr = whole_file;
257 descr->cld_obj = clob;
258 lock = cl_lock_peek(env, io, descr, "localsize", current);
259 if (lock) {
260 cl_merge_lvb(env, inode);
261 cl_unuse(env, lock);
262 cl_lock_release(env, lock, "localsize", current);
263 result = 0;
264 } else
265 result = -ENODATA;
266 }
267 cl_io_fini(env, io);
268 cl_env_put(env, &refcheck);
269 return result;
270}
271