aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/gfs2/ops_file.c187
1 files changed, 9 insertions, 178 deletions
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index 80f3ff0bba7b..372dbcb3f7f3 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -43,27 +43,6 @@
43#include "util.h" 43#include "util.h"
44#include "eaops.h" 44#include "eaops.h"
45 45
46/* "bad" is for NFS support */
47struct filldir_bad_entry {
48 char *fbe_name;
49 unsigned int fbe_length;
50 u64 fbe_offset;
51 struct gfs2_inum fbe_inum;
52 unsigned int fbe_type;
53};
54
55struct filldir_bad {
56 struct gfs2_sbd *fdb_sbd;
57
58 struct filldir_bad_entry *fdb_entry;
59 unsigned int fdb_entry_num;
60 unsigned int fdb_entry_off;
61
62 char *fdb_name;
63 unsigned int fdb_name_size;
64 unsigned int fdb_name_off;
65};
66
67/* For regular, non-NFS */ 46/* For regular, non-NFS */
68struct filldir_reg { 47struct filldir_reg {
69 struct gfs2_sbd *fdr_sbd; 48 struct gfs2_sbd *fdr_sbd;
@@ -149,7 +128,7 @@ static loff_t gfs2_llseek(struct file *file, loff_t offset, int origin)
149} 128}
150 129
151/** 130/**
152 * filldir_reg_func - Report a directory entry to the caller of gfs2_dir_read() 131 * filldir_func - Report a directory entry to the caller of gfs2_dir_read()
153 * @opaque: opaque data used by the function 132 * @opaque: opaque data used by the function
154 * @name: the name of the directory entry 133 * @name: the name of the directory entry
155 * @length: the length of the name 134 * @length: the length of the name
@@ -160,9 +139,9 @@ static loff_t gfs2_llseek(struct file *file, loff_t offset, int origin)
160 * Returns: 0 on success, 1 if buffer full 139 * Returns: 0 on success, 1 if buffer full
161 */ 140 */
162 141
163static int filldir_reg_func(void *opaque, const char *name, unsigned int length, 142static int filldir_func(void *opaque, const char *name, unsigned int length,
164 u64 offset, struct gfs2_inum *inum, 143 u64 offset, struct gfs2_inum *inum,
165 unsigned int type) 144 unsigned int type)
166{ 145{
167 struct filldir_reg *fdr = (struct filldir_reg *)opaque; 146 struct filldir_reg *fdr = (struct filldir_reg *)opaque;
168 struct gfs2_sbd *sdp = fdr->fdr_sbd; 147 struct gfs2_sbd *sdp = fdr->fdr_sbd;
@@ -174,11 +153,9 @@ static int filldir_reg_func(void *opaque, const char *name, unsigned int length,
174 return 1; 153 return 1;
175 154
176 if (fdr->fdr_prefetch && !(length == 1 && *name == '.')) { 155 if (fdr->fdr_prefetch && !(length == 1 && *name == '.')) {
177 gfs2_glock_prefetch_num(sdp, 156 gfs2_glock_prefetch_num(sdp, inum->no_addr, &gfs2_inode_glops,
178 inum->no_addr, &gfs2_inode_glops,
179 LM_ST_SHARED, LM_FLAG_TRY | LM_FLAG_ANY); 157 LM_ST_SHARED, LM_FLAG_TRY | LM_FLAG_ANY);
180 gfs2_glock_prefetch_num(sdp, 158 gfs2_glock_prefetch_num(sdp, inum->no_addr, &gfs2_iopen_glops,
181 inum->no_addr, &gfs2_iopen_glops,
182 LM_ST_SHARED, LM_FLAG_TRY); 159 LM_ST_SHARED, LM_FLAG_TRY);
183 } 160 }
184 161
@@ -186,7 +163,7 @@ static int filldir_reg_func(void *opaque, const char *name, unsigned int length,
186} 163}
187 164
188/** 165/**
189 * readdir_reg - Read directory entries from a directory 166 * gfs2_readdir - Read directory entries from a directory
190 * @file: The directory to read from 167 * @file: The directory to read from
191 * @dirent: Buffer for dirents 168 * @dirent: Buffer for dirents
192 * @filldir: Function used to do the copying 169 * @filldir: Function used to do the copying
@@ -194,7 +171,7 @@ static int filldir_reg_func(void *opaque, const char *name, unsigned int length,
194 * Returns: errno 171 * Returns: errno
195 */ 172 */
196 173
197static int readdir_reg(struct file *file, void *dirent, filldir_t filldir) 174static int gfs2_readdir(struct file *file, void *dirent, filldir_t filldir)
198{ 175{
199 struct inode *dir = file->f_mapping->host; 176 struct inode *dir = file->f_mapping->host;
200 struct gfs2_inode *dip = GFS2_I(dir); 177 struct gfs2_inode *dip = GFS2_I(dir);
@@ -215,7 +192,7 @@ static int readdir_reg(struct file *file, void *dirent, filldir_t filldir)
215 return error; 192 return error;
216 } 193 }
217 194
218 error = gfs2_dir_read(dir, &offset, &fdr, filldir_reg_func); 195 error = gfs2_dir_read(dir, &offset, &fdr, filldir_func);
219 196
220 gfs2_glock_dq_uninit(&d_gh); 197 gfs2_glock_dq_uninit(&d_gh);
221 198
@@ -224,152 +201,6 @@ static int readdir_reg(struct file *file, void *dirent, filldir_t filldir)
224 return error; 201 return error;
225} 202}
226 203
227/**
228 * filldir_bad_func - Report a directory entry to the caller of gfs2_dir_read()
229 * @opaque: opaque data used by the function
230 * @name: the name of the directory entry
231 * @length: the length of the name
232 * @offset: the entry's offset in the directory
233 * @inum: the inode number the entry points to
234 * @type: the type of inode the entry points to
235 *
236 * For supporting NFS.
237 *
238 * Returns: 0 on success, 1 if buffer full
239 */
240
241static int filldir_bad_func(void *opaque, const char *name, unsigned int length,
242 u64 offset, struct gfs2_inum *inum,
243 unsigned int type)
244{
245 struct filldir_bad *fdb = (struct filldir_bad *)opaque;
246 struct gfs2_sbd *sdp = fdb->fdb_sbd;
247 struct filldir_bad_entry *fbe;
248
249 if (fdb->fdb_entry_off == fdb->fdb_entry_num ||
250 fdb->fdb_name_off + length > fdb->fdb_name_size)
251 return 1;
252
253 fbe = &fdb->fdb_entry[fdb->fdb_entry_off];
254 fbe->fbe_name = fdb->fdb_name + fdb->fdb_name_off;
255 memcpy(fbe->fbe_name, name, length);
256 fbe->fbe_length = length;
257 fbe->fbe_offset = offset;
258 fbe->fbe_inum = *inum;
259 fbe->fbe_type = type;
260
261 fdb->fdb_entry_off++;
262 fdb->fdb_name_off += length;
263
264 if (!(length == 1 && *name == '.')) {
265 gfs2_glock_prefetch_num(sdp,
266 inum->no_addr, &gfs2_inode_glops,
267 LM_ST_SHARED, LM_FLAG_TRY | LM_FLAG_ANY);
268 gfs2_glock_prefetch_num(sdp,
269 inum->no_addr, &gfs2_iopen_glops,
270 LM_ST_SHARED, LM_FLAG_TRY);
271 }
272
273 return 0;
274}
275
276/**
277 * readdir_bad - Read directory entries from a directory
278 * @file: The directory to read from
279 * @dirent: Buffer for dirents
280 * @filldir: Function used to do the copying
281 *
282 * For supporting NFS.
283 *
284 * Returns: errno
285 */
286
287static int readdir_bad(struct file *file, void *dirent, filldir_t filldir)
288{
289 struct inode *dir = file->f_mapping->host;
290 struct gfs2_inode *dip = GFS2_I(dir);
291 struct gfs2_sbd *sdp = GFS2_SB(dir);
292 struct filldir_reg fdr;
293 unsigned int entries, size;
294 struct filldir_bad *fdb;
295 struct gfs2_holder d_gh;
296 u64 offset = file->f_pos;
297 unsigned int x;
298 struct filldir_bad_entry *fbe;
299 int error;
300
301 entries = gfs2_tune_get(sdp, gt_entries_per_readdir);
302 size = sizeof(struct filldir_bad) +
303 entries * (sizeof(struct filldir_bad_entry) + GFS2_FAST_NAME_SIZE);
304
305 fdb = kzalloc(size, GFP_KERNEL);
306 if (!fdb)
307 return -ENOMEM;
308
309 fdb->fdb_sbd = sdp;
310 fdb->fdb_entry = (struct filldir_bad_entry *)(fdb + 1);
311 fdb->fdb_entry_num = entries;
312 fdb->fdb_name = ((char *)fdb) + sizeof(struct filldir_bad) +
313 entries * sizeof(struct filldir_bad_entry);
314 fdb->fdb_name_size = entries * GFS2_FAST_NAME_SIZE;
315
316 gfs2_holder_init(dip->i_gl, LM_ST_SHARED, GL_ATIME, &d_gh);
317 error = gfs2_glock_nq_atime(&d_gh);
318 if (error) {
319 gfs2_holder_uninit(&d_gh);
320 goto out;
321 }
322
323 error = gfs2_dir_read(dir, &offset, fdb, filldir_bad_func);
324
325 gfs2_glock_dq_uninit(&d_gh);
326
327 fdr.fdr_sbd = sdp;
328 fdr.fdr_prefetch = 0;
329 fdr.fdr_filldir = filldir;
330 fdr.fdr_opaque = dirent;
331
332 for (x = 0; x < fdb->fdb_entry_off; x++) {
333 fbe = &fdb->fdb_entry[x];
334
335 error = filldir_reg_func(&fdr,
336 fbe->fbe_name, fbe->fbe_length,
337 fbe->fbe_offset,
338 &fbe->fbe_inum, fbe->fbe_type);
339 if (error) {
340 file->f_pos = fbe->fbe_offset;
341 error = 0;
342 goto out;
343 }
344 }
345
346 file->f_pos = offset;
347
348out:
349 kfree(fdb);
350 return error;
351}
352
353/**
354 * gfs2_readdir - Read directory entries from a directory
355 * @file: The directory to read from
356 * @dirent: Buffer for dirents
357 * @filldir: Function used to do the copying
358 *
359 * Returns: errno
360 */
361
362static int gfs2_readdir(struct file *file, void *dirent, filldir_t filldir)
363{
364 int error;
365
366 if (strcmp(current->comm, "nfsd") != 0)
367 error = readdir_reg(file, dirent, filldir);
368 else
369 error = readdir_bad(file, dirent, filldir);
370
371 return error;
372}
373 204
374static const u32 iflags_to_gfs2[32] = { 205static const u32 iflags_to_gfs2[32] = {
375 [iflag_Sync] = GFS2_DIF_SYNC, 206 [iflag_Sync] = GFS2_DIF_SYNC,