xref: /openbmc/linux/fs/orangefs/dir.c (revision 2ad4b6f5)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
25db11c21SMike Marshall /*
3382f4581SMartin Brandenburg  * Copyright 2017 Omnibond Systems, L.L.C.
45db11c21SMike Marshall  */
55db11c21SMike Marshall 
65db11c21SMike Marshall #include "protocol.h"
7575e9461SMike Marshall #include "orangefs-kernel.h"
8575e9461SMike Marshall #include "orangefs-bufmap.h"
95db11c21SMike Marshall 
10480e3e53SMartin Brandenburg struct orangefs_dir_part {
11480e3e53SMartin Brandenburg 	struct orangefs_dir_part *next;
12480e3e53SMartin Brandenburg 	size_t len;
13480e3e53SMartin Brandenburg };
14480e3e53SMartin Brandenburg 
15480e3e53SMartin Brandenburg struct orangefs_dir {
16480e3e53SMartin Brandenburg 	__u64 token;
17480e3e53SMartin Brandenburg 	struct orangefs_dir_part *part;
18480e3e53SMartin Brandenburg 	loff_t end;
19480e3e53SMartin Brandenburg 	int error;
20480e3e53SMartin Brandenburg };
21480e3e53SMartin Brandenburg 
22480e3e53SMartin Brandenburg #define PART_SHIFT (24)
23480e3e53SMartin Brandenburg #define PART_SIZE (1<<24)
24480e3e53SMartin Brandenburg #define PART_MASK (~(PART_SIZE - 1))
25480e3e53SMartin Brandenburg 
265db11c21SMike Marshall /*
27382f4581SMartin Brandenburg  * There can be up to 512 directory entries.  Each entry is encoded as
28382f4581SMartin Brandenburg  * follows:
29382f4581SMartin Brandenburg  * 4 bytes: string size (n)
30382f4581SMartin Brandenburg  * n bytes: string
31382f4581SMartin Brandenburg  * 1 byte: trailing zero
32382f4581SMartin Brandenburg  * padding to 8 bytes
33382f4581SMartin Brandenburg  * 16 bytes: khandle
34382f4581SMartin Brandenburg  * padding to 8 bytes
35382f4581SMartin Brandenburg  *
36382f4581SMartin Brandenburg  * The trailer_buf starts with a struct orangefs_readdir_response_s
37382f4581SMartin Brandenburg  * which must be skipped to get to the directory data.
38480e3e53SMartin Brandenburg  *
39480e3e53SMartin Brandenburg  * The data which is received from the userspace daemon is termed a
40480e3e53SMartin Brandenburg  * part and is stored in a linked list in case more than one part is
41480e3e53SMartin Brandenburg  * needed for a large directory.
42480e3e53SMartin Brandenburg  *
43480e3e53SMartin Brandenburg  * The position pointer (ctx->pos) encodes the part and offset on which
44480e3e53SMartin Brandenburg  * to begin reading at.  Bits above PART_SHIFT encode the part and bits
45480e3e53SMartin Brandenburg  * below PART_SHIFT encode the offset.  Parts are stored in a linked
46480e3e53SMartin Brandenburg  * list which grows as data is received from the server.  The overhead
47480e3e53SMartin Brandenburg  * associated with managing the list is presumed to be small compared to
48480e3e53SMartin Brandenburg  * the overhead of communicating with the server.
49480e3e53SMartin Brandenburg  *
50480e3e53SMartin Brandenburg  * As data is received from the server, it is placed at the end of the
51480e3e53SMartin Brandenburg  * part list.  Data is parsed from the current position as it is needed.
52480e3e53SMartin Brandenburg  * When data is determined to be corrupt, it is either because the
53480e3e53SMartin Brandenburg  * userspace component has sent back corrupt data or because the file
54480e3e53SMartin Brandenburg  * pointer has been moved to an invalid location.  Since the two cannot
55480e3e53SMartin Brandenburg  * be differentiated, return EIO.
56480e3e53SMartin Brandenburg  *
57480e3e53SMartin Brandenburg  * Part zero is synthesized to contains `.' and `..'.  Part one is the
58480e3e53SMartin Brandenburg  * first part of the part list.
59382f4581SMartin Brandenburg  */
60382f4581SMartin Brandenburg 
do_readdir(struct orangefs_inode_s * oi,struct orangefs_dir * od,struct dentry * dentry,struct orangefs_kernel_op_s * op)61480e3e53SMartin Brandenburg static int do_readdir(struct orangefs_inode_s *oi,
62480e3e53SMartin Brandenburg     struct orangefs_dir *od, struct dentry *dentry,
63480e3e53SMartin Brandenburg     struct orangefs_kernel_op_s *op)
645db11c21SMike Marshall {
65382f4581SMartin Brandenburg 	struct orangefs_readdir_response_s *resp;
66382f4581SMartin Brandenburg 	int bufi, r;
675db11c21SMike Marshall 
685db11c21SMike Marshall 	/*
69382f4581SMartin Brandenburg 	 * Despite the badly named field, readdir does not use shared
70382f4581SMartin Brandenburg 	 * memory.  However, there are a limited number of readdir
71382f4581SMartin Brandenburg 	 * slots, which must be allocated here.  This flag simply tells
72382f4581SMartin Brandenburg 	 * the op scheduler to return the op here for retry.
735db11c21SMike Marshall 	 */
74382f4581SMartin Brandenburg 	op->uses_shared_memory = 1;
75382f4581SMartin Brandenburg 	op->upcall.req.readdir.refn = oi->refn;
76382f4581SMartin Brandenburg 	op->upcall.req.readdir.token = od->token;
77382f4581SMartin Brandenburg 	op->upcall.req.readdir.max_dirent_count =
78382f4581SMartin Brandenburg 	    ORANGEFS_MAX_DIRENT_COUNT_READDIR;
795db11c21SMike Marshall 
80382f4581SMartin Brandenburg again:
81382f4581SMartin Brandenburg 	bufi = orangefs_readdir_index_get();
82382f4581SMartin Brandenburg 	if (bufi < 0) {
83382f4581SMartin Brandenburg 		od->error = bufi;
84382f4581SMartin Brandenburg 		return bufi;
85382f4581SMartin Brandenburg 	}
865db11c21SMike Marshall 
87382f4581SMartin Brandenburg 	op->upcall.req.readdir.buf_index = bufi;
885db11c21SMike Marshall 
89382f4581SMartin Brandenburg 	r = service_operation(op, "orangefs_readdir",
90382f4581SMartin Brandenburg 	    get_interruptible_flag(dentry->d_inode));
91382f4581SMartin Brandenburg 
92382f4581SMartin Brandenburg 	orangefs_readdir_index_put(bufi);
93382f4581SMartin Brandenburg 
94382f4581SMartin Brandenburg 	if (op_state_purged(op)) {
95382f4581SMartin Brandenburg 		if (r == -EAGAIN) {
96382f4581SMartin Brandenburg 			vfree(op->downcall.trailer_buf);
97382f4581SMartin Brandenburg 			goto again;
98382f4581SMartin Brandenburg 		} else if (r == -EIO) {
99382f4581SMartin Brandenburg 			vfree(op->downcall.trailer_buf);
100382f4581SMartin Brandenburg 			od->error = r;
101382f4581SMartin Brandenburg 			return r;
102382f4581SMartin Brandenburg 		}
103382f4581SMartin Brandenburg 	}
104382f4581SMartin Brandenburg 
105382f4581SMartin Brandenburg 	if (r < 0) {
106382f4581SMartin Brandenburg 		vfree(op->downcall.trailer_buf);
107382f4581SMartin Brandenburg 		od->error = r;
108382f4581SMartin Brandenburg 		return r;
109382f4581SMartin Brandenburg 	} else if (op->downcall.status) {
110382f4581SMartin Brandenburg 		vfree(op->downcall.trailer_buf);
111382f4581SMartin Brandenburg 		od->error = op->downcall.status;
112382f4581SMartin Brandenburg 		return op->downcall.status;
113382f4581SMartin Brandenburg 	}
114382f4581SMartin Brandenburg 
115480e3e53SMartin Brandenburg 	/*
116480e3e53SMartin Brandenburg 	 * The maximum size is size per entry times the 512 entries plus
117480e3e53SMartin Brandenburg 	 * the header.  This is well under the limit.
118480e3e53SMartin Brandenburg 	 */
119480e3e53SMartin Brandenburg 	if (op->downcall.trailer_size > PART_SIZE) {
120480e3e53SMartin Brandenburg 		vfree(op->downcall.trailer_buf);
121480e3e53SMartin Brandenburg 		od->error = -EIO;
122480e3e53SMartin Brandenburg 		return -EIO;
123480e3e53SMartin Brandenburg 	}
124480e3e53SMartin Brandenburg 
125382f4581SMartin Brandenburg 	resp = (struct orangefs_readdir_response_s *)
126382f4581SMartin Brandenburg 	    op->downcall.trailer_buf;
127382f4581SMartin Brandenburg 	od->token = resp->token;
128480e3e53SMartin Brandenburg 	return 0;
129382f4581SMartin Brandenburg }
130382f4581SMartin Brandenburg 
parse_readdir(struct orangefs_dir * od,struct orangefs_kernel_op_s * op)131480e3e53SMartin Brandenburg static int parse_readdir(struct orangefs_dir *od,
132480e3e53SMartin Brandenburg     struct orangefs_kernel_op_s *op)
133480e3e53SMartin Brandenburg {
134480e3e53SMartin Brandenburg 	struct orangefs_dir_part *part, *new;
135480e3e53SMartin Brandenburg 	size_t count;
136480e3e53SMartin Brandenburg 
137480e3e53SMartin Brandenburg 	count = 1;
138480e3e53SMartin Brandenburg 	part = od->part;
1392f713b5cSMartin Brandenburg 	while (part) {
140480e3e53SMartin Brandenburg 		count++;
1412f713b5cSMartin Brandenburg 		if (part->next)
1422f713b5cSMartin Brandenburg 			part = part->next;
1432f713b5cSMartin Brandenburg 		else
1442f713b5cSMartin Brandenburg 			break;
145480e3e53SMartin Brandenburg 	}
146480e3e53SMartin Brandenburg 
147480e3e53SMartin Brandenburg 	new = (void *)op->downcall.trailer_buf;
148480e3e53SMartin Brandenburg 	new->next = NULL;
149480e3e53SMartin Brandenburg 	new->len = op->downcall.trailer_size -
150480e3e53SMartin Brandenburg 	    sizeof(struct orangefs_readdir_response_s);
151480e3e53SMartin Brandenburg 	if (!od->part)
152480e3e53SMartin Brandenburg 		od->part = new;
153480e3e53SMartin Brandenburg 	else
154480e3e53SMartin Brandenburg 		part->next = new;
155480e3e53SMartin Brandenburg 	count++;
156480e3e53SMartin Brandenburg 	od->end = count << PART_SHIFT;
157480e3e53SMartin Brandenburg 
1585db11c21SMike Marshall 	return 0;
1595db11c21SMike Marshall }
1605db11c21SMike Marshall 
orangefs_dir_more(struct orangefs_inode_s * oi,struct orangefs_dir * od,struct dentry * dentry)161480e3e53SMartin Brandenburg static int orangefs_dir_more(struct orangefs_inode_s *oi,
162480e3e53SMartin Brandenburg     struct orangefs_dir *od, struct dentry *dentry)
163480e3e53SMartin Brandenburg {
164480e3e53SMartin Brandenburg 	struct orangefs_kernel_op_s *op;
165480e3e53SMartin Brandenburg 	int r;
166480e3e53SMartin Brandenburg 
167480e3e53SMartin Brandenburg 	op = op_alloc(ORANGEFS_VFS_OP_READDIR);
168480e3e53SMartin Brandenburg 	if (!op) {
169480e3e53SMartin Brandenburg 		od->error = -ENOMEM;
170480e3e53SMartin Brandenburg 		return -ENOMEM;
171480e3e53SMartin Brandenburg 	}
172480e3e53SMartin Brandenburg 	r = do_readdir(oi, od, dentry, op);
173480e3e53SMartin Brandenburg 	if (r) {
174480e3e53SMartin Brandenburg 		od->error = r;
175480e3e53SMartin Brandenburg 		goto out;
176480e3e53SMartin Brandenburg 	}
177480e3e53SMartin Brandenburg 	r = parse_readdir(od, op);
178480e3e53SMartin Brandenburg 	if (r) {
179480e3e53SMartin Brandenburg 		od->error = r;
180480e3e53SMartin Brandenburg 		goto out;
181480e3e53SMartin Brandenburg 	}
182480e3e53SMartin Brandenburg 
183480e3e53SMartin Brandenburg 	od->error = 0;
184480e3e53SMartin Brandenburg out:
185480e3e53SMartin Brandenburg 	op_release(op);
186480e3e53SMartin Brandenburg 	return od->error;
187480e3e53SMartin Brandenburg }
188480e3e53SMartin Brandenburg 
fill_from_part(struct orangefs_dir_part * part,struct dir_context * ctx)189480e3e53SMartin Brandenburg static int fill_from_part(struct orangefs_dir_part *part,
190480e3e53SMartin Brandenburg     struct dir_context *ctx)
191480e3e53SMartin Brandenburg {
192480e3e53SMartin Brandenburg 	const int offset = sizeof(struct orangefs_readdir_response_s);
193480e3e53SMartin Brandenburg 	struct orangefs_khandle *khandle;
194480e3e53SMartin Brandenburg 	__u32 *len, padlen;
195480e3e53SMartin Brandenburg 	loff_t i;
196480e3e53SMartin Brandenburg 	char *s;
197480e3e53SMartin Brandenburg 	i = ctx->pos & ~PART_MASK;
198480e3e53SMartin Brandenburg 
199480e3e53SMartin Brandenburg 	/* The file offset from userspace is too large. */
200480e3e53SMartin Brandenburg 	if (i > part->len)
201bf15ba7cSMartin Brandenburg 		return 1;
202bf15ba7cSMartin Brandenburg 
203bf15ba7cSMartin Brandenburg 	/*
204bf15ba7cSMartin Brandenburg 	 * If the seek pointer is positioned just before an entry it
205bf15ba7cSMartin Brandenburg 	 * should find the next entry.
206bf15ba7cSMartin Brandenburg 	 */
207bf15ba7cSMartin Brandenburg 	if (i % 8)
208bf15ba7cSMartin Brandenburg 		i = i + (8 - i%8)%8;
209480e3e53SMartin Brandenburg 
210480e3e53SMartin Brandenburg 	while (i < part->len) {
211480e3e53SMartin Brandenburg 		if (part->len < i + sizeof *len)
212bf15ba7cSMartin Brandenburg 			break;
213480e3e53SMartin Brandenburg 		len = (void *)part + offset + i;
214480e3e53SMartin Brandenburg 		/*
215480e3e53SMartin Brandenburg 		 * len is the size of the string itself.  padlen is the
216480e3e53SMartin Brandenburg 		 * total size of the encoded string.
217480e3e53SMartin Brandenburg 		 */
218480e3e53SMartin Brandenburg 		padlen = (sizeof *len + *len + 1) +
219480e3e53SMartin Brandenburg 		    (8 - (sizeof *len + *len + 1)%8)%8;
220480e3e53SMartin Brandenburg 		if (part->len < i + padlen + sizeof *khandle)
221bf15ba7cSMartin Brandenburg 			goto next;
222480e3e53SMartin Brandenburg 		s = (void *)part + offset + i + sizeof *len;
223480e3e53SMartin Brandenburg 		if (s[*len] != 0)
224bf15ba7cSMartin Brandenburg 			goto next;
225480e3e53SMartin Brandenburg 		khandle = (void *)part + offset + i + padlen;
226480e3e53SMartin Brandenburg 		if (!dir_emit(ctx, s, *len,
227480e3e53SMartin Brandenburg 		    orangefs_khandle_to_ino(khandle),
228480e3e53SMartin Brandenburg 		    DT_UNKNOWN))
229480e3e53SMartin Brandenburg 			return 0;
230480e3e53SMartin Brandenburg 		i += padlen + sizeof *khandle;
231480e3e53SMartin Brandenburg 		i = i + (8 - i%8)%8;
232480e3e53SMartin Brandenburg 		BUG_ON(i > part->len);
233480e3e53SMartin Brandenburg 		ctx->pos = (ctx->pos & PART_MASK) | i;
234bf15ba7cSMartin Brandenburg 		continue;
235bf15ba7cSMartin Brandenburg next:
236bf15ba7cSMartin Brandenburg 		i += 8;
237480e3e53SMartin Brandenburg 	}
238480e3e53SMartin Brandenburg 	return 1;
239480e3e53SMartin Brandenburg }
240480e3e53SMartin Brandenburg 
orangefs_dir_fill(struct orangefs_inode_s * oi,struct orangefs_dir * od,struct dentry * dentry,struct dir_context * ctx)241382f4581SMartin Brandenburg static int orangefs_dir_fill(struct orangefs_inode_s *oi,
242382f4581SMartin Brandenburg     struct orangefs_dir *od, struct dentry *dentry,
243382f4581SMartin Brandenburg     struct dir_context *ctx)
244382f4581SMartin Brandenburg {
245480e3e53SMartin Brandenburg 	struct orangefs_dir_part *part;
246480e3e53SMartin Brandenburg 	size_t count;
2475db11c21SMike Marshall 
248480e3e53SMartin Brandenburg 	count = ((ctx->pos & PART_MASK) >> PART_SHIFT) - 1;
249480e3e53SMartin Brandenburg 
250480e3e53SMartin Brandenburg 	part = od->part;
251480e3e53SMartin Brandenburg 	while (part->next && count) {
252480e3e53SMartin Brandenburg 		count--;
253480e3e53SMartin Brandenburg 		part = part->next;
2545db11c21SMike Marshall 	}
255480e3e53SMartin Brandenburg 	/* This means the userspace file offset is invalid. */
256480e3e53SMartin Brandenburg 	if (count) {
257382f4581SMartin Brandenburg 		od->error = -EIO;
258382f4581SMartin Brandenburg 		return -EIO;
2595db11c21SMike Marshall 	}
2605db11c21SMike Marshall 
261480e3e53SMartin Brandenburg 	while (part && part->len) {
262480e3e53SMartin Brandenburg 		int r;
263480e3e53SMartin Brandenburg 		r = fill_from_part(part, ctx);
264480e3e53SMartin Brandenburg 		if (r < 0) {
265480e3e53SMartin Brandenburg 			od->error = r;
266480e3e53SMartin Brandenburg 			return r;
267480e3e53SMartin Brandenburg 		} else if (r == 0) {
268480e3e53SMartin Brandenburg 			/* Userspace buffer is full. */
269480e3e53SMartin Brandenburg 			break;
270480e3e53SMartin Brandenburg 		} else {
271480e3e53SMartin Brandenburg 			/*
272480e3e53SMartin Brandenburg 			 * The part ran out of data.  Move to the next
273480e3e53SMartin Brandenburg 			 * part. */
274480e3e53SMartin Brandenburg 			ctx->pos = (ctx->pos & PART_MASK) +
275480e3e53SMartin Brandenburg 			    (1 << PART_SHIFT);
276480e3e53SMartin Brandenburg 			part = part->next;
277480e3e53SMartin Brandenburg 		}
278480e3e53SMartin Brandenburg 	}
279480e3e53SMartin Brandenburg 	return 0;
280480e3e53SMartin Brandenburg }
281480e3e53SMartin Brandenburg 
orangefs_dir_llseek(struct file * file,loff_t offset,int whence)282942835d6SMartin Brandenburg static loff_t orangefs_dir_llseek(struct file *file, loff_t offset,
283942835d6SMartin Brandenburg     int whence)
284942835d6SMartin Brandenburg {
285942835d6SMartin Brandenburg 	struct orangefs_dir *od = file->private_data;
286942835d6SMartin Brandenburg 	/*
287942835d6SMartin Brandenburg 	 * Delete the stored data so userspace sees new directory
288942835d6SMartin Brandenburg 	 * entries.
289942835d6SMartin Brandenburg 	 */
290942835d6SMartin Brandenburg 	if (!whence && offset < od->end) {
291942835d6SMartin Brandenburg 		struct orangefs_dir_part *part = od->part;
292942835d6SMartin Brandenburg 		while (part) {
293942835d6SMartin Brandenburg 			struct orangefs_dir_part *next = part->next;
294942835d6SMartin Brandenburg 			vfree(part);
295942835d6SMartin Brandenburg 			part = next;
296942835d6SMartin Brandenburg 		}
297942835d6SMartin Brandenburg 		od->token = ORANGEFS_ITERATE_START;
298942835d6SMartin Brandenburg 		od->part = NULL;
299942835d6SMartin Brandenburg 		od->end = 1 << PART_SHIFT;
300942835d6SMartin Brandenburg 	}
301942835d6SMartin Brandenburg 	return default_llseek(file, offset, whence);
302942835d6SMartin Brandenburg }
303942835d6SMartin Brandenburg 
orangefs_dir_iterate(struct file * file,struct dir_context * ctx)304382f4581SMartin Brandenburg static int orangefs_dir_iterate(struct file *file,
305382f4581SMartin Brandenburg     struct dir_context *ctx)
306382f4581SMartin Brandenburg {
307382f4581SMartin Brandenburg 	struct orangefs_inode_s *oi;
308382f4581SMartin Brandenburg 	struct orangefs_dir *od;
309382f4581SMartin Brandenburg 	struct dentry *dentry;
310382f4581SMartin Brandenburg 	int r;
3115db11c21SMike Marshall 
312382f4581SMartin Brandenburg 	dentry = file->f_path.dentry;
313382f4581SMartin Brandenburg 	oi = ORANGEFS_I(dentry->d_inode);
314382f4581SMartin Brandenburg 	od = file->private_data;
3155db11c21SMike Marshall 
316382f4581SMartin Brandenburg 	if (od->error)
317382f4581SMartin Brandenburg 		return od->error;
3189f5e2f7fSAl Viro 
319382f4581SMartin Brandenburg 	if (ctx->pos == 0) {
320382f4581SMartin Brandenburg 		if (!dir_emit_dot(file, ctx))
321382f4581SMartin Brandenburg 			return 0;
3225db11c21SMike Marshall 		ctx->pos++;
323382f4581SMartin Brandenburg 	}
324382f4581SMartin Brandenburg 	if (ctx->pos == 1) {
325382f4581SMartin Brandenburg 		if (!dir_emit_dotdot(file, ctx))
326382f4581SMartin Brandenburg 			return 0;
327480e3e53SMartin Brandenburg 		ctx->pos = 1 << PART_SHIFT;
3285db11c21SMike Marshall 	}
3295db11c21SMike Marshall 
330480e3e53SMartin Brandenburg 	/*
331480e3e53SMartin Brandenburg 	 * The seek position is in the first synthesized part but is not
332480e3e53SMartin Brandenburg 	 * valid.
333480e3e53SMartin Brandenburg 	 */
334480e3e53SMartin Brandenburg 	if ((ctx->pos & PART_MASK) == 0)
335480e3e53SMartin Brandenburg 		return -EIO;
336480e3e53SMartin Brandenburg 
337382f4581SMartin Brandenburg 	r = 0;
338382f4581SMartin Brandenburg 
33972f66b83SMartin Brandenburg 	/*
34072f66b83SMartin Brandenburg 	 * Must read more if the user has sought past what has been read
34172f66b83SMartin Brandenburg 	 * so far.  Stop a user who has sought past the end.
34272f66b83SMartin Brandenburg 	 */
3437b796ae3SMartin Brandenburg 	while (od->token != ORANGEFS_ITERATE_END &&
344480e3e53SMartin Brandenburg 	    ctx->pos > od->end) {
34572f66b83SMartin Brandenburg 		r = orangefs_dir_more(oi, od, dentry);
34672f66b83SMartin Brandenburg 		if (r)
34772f66b83SMartin Brandenburg 			return r;
34872f66b83SMartin Brandenburg 	}
3497b796ae3SMartin Brandenburg 	if (od->token == ORANGEFS_ITERATE_END && ctx->pos > od->end)
35072f66b83SMartin Brandenburg 		return -EIO;
35172f66b83SMartin Brandenburg 
35272f66b83SMartin Brandenburg 	/* Then try to fill if there's any left in the buffer. */
353480e3e53SMartin Brandenburg 	if (ctx->pos < od->end) {
354382f4581SMartin Brandenburg 		r = orangefs_dir_fill(oi, od, dentry, ctx);
355382f4581SMartin Brandenburg 		if (r)
356382f4581SMartin Brandenburg 			return r;
3575db11c21SMike Marshall 	}
3585db11c21SMike Marshall 
35972f66b83SMartin Brandenburg 	/* Finally get some more and try to fill. */
3607b796ae3SMartin Brandenburg 	if (od->token != ORANGEFS_ITERATE_END) {
361382f4581SMartin Brandenburg 		r = orangefs_dir_more(oi, od, dentry);
362382f4581SMartin Brandenburg 		if (r)
363382f4581SMartin Brandenburg 			return r;
364382f4581SMartin Brandenburg 		r = orangefs_dir_fill(oi, od, dentry, ctx);
3655db11c21SMike Marshall 	}
3665db11c21SMike Marshall 
367382f4581SMartin Brandenburg 	return r;
3685db11c21SMike Marshall }
3695db11c21SMike Marshall 
orangefs_dir_open(struct inode * inode,struct file * file)3708bb8aefdSYi Liu static int orangefs_dir_open(struct inode *inode, struct file *file)
3715db11c21SMike Marshall {
372382f4581SMartin Brandenburg 	struct orangefs_dir *od;
373382f4581SMartin Brandenburg 	file->private_data = kmalloc(sizeof(struct orangefs_dir),
374382f4581SMartin Brandenburg 	    GFP_KERNEL);
3755db11c21SMike Marshall 	if (!file->private_data)
3765db11c21SMike Marshall 		return -ENOMEM;
377382f4581SMartin Brandenburg 	od = file->private_data;
3787b796ae3SMartin Brandenburg 	od->token = ORANGEFS_ITERATE_START;
379480e3e53SMartin Brandenburg 	od->part = NULL;
380480e3e53SMartin Brandenburg 	od->end = 1 << PART_SHIFT;
381382f4581SMartin Brandenburg 	od->error = 0;
3825db11c21SMike Marshall 	return 0;
3835db11c21SMike Marshall }
3845db11c21SMike Marshall 
orangefs_dir_release(struct inode * inode,struct file * file)3858bb8aefdSYi Liu static int orangefs_dir_release(struct inode *inode, struct file *file)
3865db11c21SMike Marshall {
387382f4581SMartin Brandenburg 	struct orangefs_dir *od = file->private_data;
388480e3e53SMartin Brandenburg 	struct orangefs_dir_part *part = od->part;
389480e3e53SMartin Brandenburg 	while (part) {
390480e3e53SMartin Brandenburg 		struct orangefs_dir_part *next = part->next;
391480e3e53SMartin Brandenburg 		vfree(part);
392480e3e53SMartin Brandenburg 		part = next;
393480e3e53SMartin Brandenburg 	}
394382f4581SMartin Brandenburg 	kfree(od);
3955db11c21SMike Marshall 	return 0;
3965db11c21SMike Marshall }
3975db11c21SMike Marshall 
3988bb8aefdSYi Liu const struct file_operations orangefs_dir_operations = {
399942835d6SMartin Brandenburg 	.llseek = orangefs_dir_llseek,
4005db11c21SMike Marshall 	.read = generic_read_dir,
401*2ad4b6f5SMike Marshall 	.iterate_shared = orangefs_dir_iterate,
4028bb8aefdSYi Liu 	.open = orangefs_dir_open,
403382f4581SMartin Brandenburg 	.release = orangefs_dir_release
4045db11c21SMike Marshall };
405