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#include "../../include/linux/libcfs/libcfs.h"
40#include "../include/obd_class.h"
41#include "../include/obd_support.h"
42#include "../include/obd.h"
43
44#include "../include/lustre_dlm.h"
45#include "../include/lustre_mdc.h"
46#include <linux/pagemap.h>
47#include <linux/file.h>
48
49#include "../include/cl_object.h"
50#include "../llite/llite_internal.h"
51
52static const struct cl_lock_descr whole_file = {
53 .cld_start = 0,
54 .cld_end = CL_PAGE_EOF,
55 .cld_mode = CLM_READ
56};
57
58
59
60
61
62
63
64blkcnt_t dirty_cnt(struct inode *inode)
65{
66 blkcnt_t cnt = 0;
67 struct vvp_object *vob = cl_inode2vvp(inode);
68 void *results[1];
69
70 if (inode->i_mapping)
71 cnt += radix_tree_gang_lookup_tag(&inode->i_mapping->page_tree,
72 results, 0, 1,
73 PAGECACHE_TAG_DIRTY);
74 if (cnt == 0 && atomic_read(&vob->vob_mmap_cnt) > 0)
75 cnt = 1;
76
77 return (cnt > 0) ? 1 : 0;
78}
79
80int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io,
81 struct inode *inode, struct cl_object *clob, int agl)
82{
83 struct ll_inode_info *lli = ll_i2info(inode);
84 const struct lu_fid *fid = lu_object_fid(&clob->co_lu);
85 int result;
86
87 result = 0;
88 if (!(lli->lli_flags & LLIF_MDS_SIZE_LOCK)) {
89 CDEBUG(D_DLMTRACE, "Glimpsing inode " DFID "\n", PFID(fid));
90 if (lli->lli_has_smd) {
91 struct cl_lock *lock = vvp_env_lock(env);
92 struct cl_lock_descr *descr = &lock->cll_descr;
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108 *descr = whole_file;
109 descr->cld_obj = clob;
110 descr->cld_mode = CLM_READ;
111 descr->cld_enq_flags = CEF_ASYNC | CEF_MUST;
112 if (agl)
113 descr->cld_enq_flags |= CEF_AGL;
114
115
116
117
118
119
120
121
122 result = cl_lock_request(env, io, lock);
123 if (result < 0)
124 return result;
125
126 if (!agl) {
127 ll_merge_attr(env, inode);
128 if (i_size_read(inode) > 0 &&
129 inode->i_blocks == 0) {
130
131
132
133
134
135
136 inode->i_blocks = dirty_cnt(inode);
137 }
138 }
139 cl_lock_release(env, lock);
140 } else {
141 CDEBUG(D_DLMTRACE, "No objects for inode\n");
142 ll_merge_attr(env, inode);
143 }
144 }
145
146 return result;
147}
148
149static int cl_io_get(struct inode *inode, struct lu_env **envout,
150 struct cl_io **ioout, int *refcheck)
151{
152 struct lu_env *env;
153 struct cl_io *io;
154 struct ll_inode_info *lli = ll_i2info(inode);
155 struct cl_object *clob = lli->lli_clob;
156 int result;
157
158 if (S_ISREG(inode->i_mode)) {
159 env = cl_env_get(refcheck);
160 if (!IS_ERR(env)) {
161 io = vvp_env_thread_io(env);
162 io->ci_obj = clob;
163 *envout = env;
164 *ioout = io;
165 result = 1;
166 } else {
167 result = PTR_ERR(env);
168 }
169 } else {
170 result = 0;
171 }
172 return result;
173}
174
175int cl_glimpse_size0(struct inode *inode, int agl)
176{
177
178
179
180
181
182
183
184
185
186
187 struct lu_env *env = NULL;
188 struct cl_io *io = NULL;
189 int result;
190 int refcheck;
191
192 result = cl_io_get(inode, &env, &io, &refcheck);
193 if (result > 0) {
194again:
195 io->ci_verify_layout = 1;
196 result = cl_io_init(env, io, CIT_MISC, io->ci_obj);
197 if (result > 0)
198
199
200
201
202 result = io->ci_result;
203 else if (result == 0)
204 result = cl_glimpse_lock(env, io, inode, io->ci_obj,
205 agl);
206
207 OBD_FAIL_TIMEOUT(OBD_FAIL_GLIMPSE_DELAY, 2);
208 cl_io_fini(env, io);
209 if (unlikely(io->ci_need_restart))
210 goto again;
211 cl_env_put(env, &refcheck);
212 }
213 return result;
214}
215
216int cl_local_size(struct inode *inode)
217{
218 struct lu_env *env = NULL;
219 struct cl_io *io = NULL;
220 struct cl_object *clob;
221 int result;
222 int refcheck;
223
224 if (!ll_i2info(inode)->lli_has_smd)
225 return 0;
226
227 result = cl_io_get(inode, &env, &io, &refcheck);
228 if (result <= 0)
229 return result;
230
231 clob = io->ci_obj;
232 result = cl_io_init(env, io, CIT_MISC, clob);
233 if (result > 0) {
234 result = io->ci_result;
235 } else if (result == 0) {
236 struct cl_lock *lock = vvp_env_lock(env);
237
238 lock->cll_descr = whole_file;
239 lock->cll_descr.cld_enq_flags = CEF_PEEK;
240 lock->cll_descr.cld_obj = clob;
241 result = cl_lock_request(env, io, lock);
242 if (result == 0) {
243 ll_merge_attr(env, inode);
244 cl_lock_release(env, lock);
245 }
246 }
247 cl_io_fini(env, io);
248 cl_env_put(env, &refcheck);
249 return result;
250}
251