xref: /openbmc/linux/fs/orangefs/dir.c (revision 82d37f19)
15db11c21SMike Marshall /*
25db11c21SMike Marshall  * (C) 2001 Clemson University and The University of Chicago
35db11c21SMike Marshall  *
45db11c21SMike Marshall  * See COPYING in top-level directory.
55db11c21SMike Marshall  */
65db11c21SMike Marshall 
75db11c21SMike Marshall #include "protocol.h"
8575e9461SMike Marshall #include "orangefs-kernel.h"
9575e9461SMike Marshall #include "orangefs-bufmap.h"
105db11c21SMike Marshall 
115db11c21SMike Marshall struct readdir_handle_s {
125db11c21SMike Marshall 	int buffer_index;
138bb8aefdSYi Liu 	struct orangefs_readdir_response_s readdir_response;
145db11c21SMike Marshall 	void *dents_buf;
155db11c21SMike Marshall };
165db11c21SMike Marshall 
175db11c21SMike Marshall /*
181808f8ccSMike Marshall  * decode routine used by kmod to deal with the blob sent from
191808f8ccSMike Marshall  * userspace for readdirs. The blob contains zero or more of these
201808f8ccSMike Marshall  * sub-blobs:
211808f8ccSMike Marshall  *   __u32 - represents length of the character string that follows.
221808f8ccSMike Marshall  *   string - between 1 and ORANGEFS_NAME_MAX bytes long.
231808f8ccSMike Marshall  *   padding - (if needed) to cause the __u32 plus the string to be
241808f8ccSMike Marshall  *             eight byte aligned.
251808f8ccSMike Marshall  *   khandle - sizeof(khandle) bytes.
265db11c21SMike Marshall  */
278092895fSAl Viro static long decode_dirents(char *ptr, size_t size,
288bb8aefdSYi Liu                            struct orangefs_readdir_response_s *readdir)
295db11c21SMike Marshall {
305db11c21SMike Marshall 	int i;
318bb8aefdSYi Liu 	struct orangefs_readdir_response_s *rd =
328bb8aefdSYi Liu 		(struct orangefs_readdir_response_s *) ptr;
335db11c21SMike Marshall 	char *buf = ptr;
341808f8ccSMike Marshall 	int khandle_size = sizeof(struct orangefs_khandle);
351808f8ccSMike Marshall 	size_t offset = offsetof(struct orangefs_readdir_response_s,
361808f8ccSMike Marshall 				dirent_array);
371808f8ccSMike Marshall 	/* 8 reflects eight byte alignment */
381808f8ccSMike Marshall 	int smallest_blob = khandle_size + 8;
391808f8ccSMike Marshall 	__u32 len;
401808f8ccSMike Marshall 	int aligned_len;
411808f8ccSMike Marshall 	int sizeof_u32 = sizeof(__u32);
421808f8ccSMike Marshall 	long ret;
435db11c21SMike Marshall 
441808f8ccSMike Marshall 	gossip_debug(GOSSIP_DIR_DEBUG, "%s: size:%zu:\n", __func__, size);
451808f8ccSMike Marshall 
461808f8ccSMike Marshall 	/* size is = offset on empty dirs, > offset on non-empty dirs... */
471808f8ccSMike Marshall 	if (size < offset) {
481808f8ccSMike Marshall 		gossip_err("%s: size:%zu: offset:%zu:\n",
491808f8ccSMike Marshall 			   __func__,
501808f8ccSMike Marshall 			   size,
511808f8ccSMike Marshall 			   offset);
521808f8ccSMike Marshall 		ret = -EINVAL;
531808f8ccSMike Marshall 		goto out;
541808f8ccSMike Marshall 	}
551808f8ccSMike Marshall 
561808f8ccSMike Marshall         if ((size == offset) && (readdir->orangefs_dirent_outcount != 0)) {
571808f8ccSMike Marshall 		gossip_err("%s: size:%zu: dirent_outcount:%d:\n",
581808f8ccSMike Marshall 			   __func__,
591808f8ccSMike Marshall 			   size,
601808f8ccSMike Marshall 			   readdir->orangefs_dirent_outcount);
611808f8ccSMike Marshall 		ret = -EINVAL;
621808f8ccSMike Marshall 		goto out;
631808f8ccSMike Marshall 	}
648092895fSAl Viro 
655db11c21SMike Marshall 	readdir->token = rd->token;
668bb8aefdSYi Liu 	readdir->orangefs_dirent_outcount = rd->orangefs_dirent_outcount;
678bb8aefdSYi Liu 	readdir->dirent_array = kcalloc(readdir->orangefs_dirent_outcount,
685db11c21SMike Marshall 					sizeof(*readdir->dirent_array),
695db11c21SMike Marshall 					GFP_KERNEL);
701808f8ccSMike Marshall 	if (readdir->dirent_array == NULL) {
711808f8ccSMike Marshall 		gossip_err("%s: kcalloc failed.\n", __func__);
721808f8ccSMike Marshall 		ret = -ENOMEM;
731808f8ccSMike Marshall 		goto out;
741808f8ccSMike Marshall 	}
758092895fSAl Viro 
761808f8ccSMike Marshall 	buf += offset;
771808f8ccSMike Marshall 	size -= offset;
788092895fSAl Viro 
798bb8aefdSYi Liu 	for (i = 0; i < readdir->orangefs_dirent_outcount; i++) {
801808f8ccSMike Marshall 		if (size < smallest_blob) {
811808f8ccSMike Marshall 			gossip_err("%s: size:%zu: smallest_blob:%d:\n",
821808f8ccSMike Marshall 				   __func__,
831808f8ccSMike Marshall 				   size,
841808f8ccSMike Marshall 				   smallest_blob);
851808f8ccSMike Marshall 			ret = -EINVAL;
861808f8ccSMike Marshall 			goto free;
871808f8ccSMike Marshall 		}
888092895fSAl Viro 
898092895fSAl Viro 		len = *(__u32 *)buf;
901808f8ccSMike Marshall 		if ((len < 1) || (len > ORANGEFS_NAME_MAX)) {
911808f8ccSMike Marshall 			gossip_err("%s: len:%d:\n", __func__, len);
921808f8ccSMike Marshall 			ret = -EINVAL;
931808f8ccSMike Marshall 			goto free;
941808f8ccSMike Marshall 		}
958092895fSAl Viro 
961808f8ccSMike Marshall 		gossip_debug(GOSSIP_DIR_DEBUG,
971808f8ccSMike Marshall 			     "%s: size:%zu: len:%d:\n",
981808f8ccSMike Marshall 			     __func__,
991808f8ccSMike Marshall 			     size,
1001808f8ccSMike Marshall 			     len);
1011808f8ccSMike Marshall 
1021808f8ccSMike Marshall 		readdir->dirent_array[i].d_name = buf + sizeof_u32;
1039be68b08SAl Viro 		readdir->dirent_array[i].d_length = len;
1048092895fSAl Viro 
1057d221485SMartin Brandenburg 		/*
1061808f8ccSMike Marshall 		 * Calculate "aligned" length of this string and its
1071808f8ccSMike Marshall 		 * associated __u32 descriptor.
1087d221485SMartin Brandenburg 		 */
1091808f8ccSMike Marshall 		aligned_len = ((sizeof_u32 + len + 1) + 7) & ~7;
1101808f8ccSMike Marshall 		gossip_debug(GOSSIP_DIR_DEBUG,
1111808f8ccSMike Marshall 			     "%s: aligned_len:%d:\n",
1121808f8ccSMike Marshall 			     __func__,
1131808f8ccSMike Marshall 			     aligned_len);
1148092895fSAl Viro 
1151808f8ccSMike Marshall 		/*
1161808f8ccSMike Marshall 		 * The end of the blob should coincide with the end
1171808f8ccSMike Marshall 		 * of the last sub-blob.
1181808f8ccSMike Marshall 		 */
1191808f8ccSMike Marshall 		if (size < aligned_len + khandle_size) {
1201808f8ccSMike Marshall 			gossip_err("%s: ran off the end of the blob.\n",
1211808f8ccSMike Marshall 				   __func__);
1221808f8ccSMike Marshall 			ret = -EINVAL;
1231808f8ccSMike Marshall 			goto free;
1241808f8ccSMike Marshall 		}
1251808f8ccSMike Marshall 		size -= aligned_len + khandle_size;
1261808f8ccSMike Marshall 
1271808f8ccSMike Marshall 		buf += aligned_len;
1288092895fSAl Viro 
1295db11c21SMike Marshall 		readdir->dirent_array[i].khandle =
1308bb8aefdSYi Liu 			*(struct orangefs_khandle *) buf;
1311808f8ccSMike Marshall 		buf += khandle_size;
1325db11c21SMike Marshall 	}
1331808f8ccSMike Marshall 	ret = buf - ptr;
1341808f8ccSMike Marshall 	gossip_debug(GOSSIP_DIR_DEBUG, "%s: returning:%ld:\n", __func__, ret);
1351808f8ccSMike Marshall 	goto out;
1361808f8ccSMike Marshall 
1371808f8ccSMike Marshall free:
1388092895fSAl Viro 	kfree(readdir->dirent_array);
1398092895fSAl Viro 	readdir->dirent_array = NULL;
1401808f8ccSMike Marshall 
1411808f8ccSMike Marshall out:
1421808f8ccSMike Marshall 	return ret;
1435db11c21SMike Marshall }
1445db11c21SMike Marshall 
1455db11c21SMike Marshall static long readdir_handle_ctor(struct readdir_handle_s *rhandle, void *buf,
1468092895fSAl Viro 				size_t size, int buffer_index)
1475db11c21SMike Marshall {
1485db11c21SMike Marshall 	long ret;
1495db11c21SMike Marshall 
1505db11c21SMike Marshall 	if (buf == NULL) {
1515db11c21SMike Marshall 		gossip_err
1525db11c21SMike Marshall 		    ("Invalid NULL buffer specified in readdir_handle_ctor\n");
1535db11c21SMike Marshall 		return -ENOMEM;
1545db11c21SMike Marshall 	}
1555db11c21SMike Marshall 	if (buffer_index < 0) {
1565db11c21SMike Marshall 		gossip_err
1575db11c21SMike Marshall 		    ("Invalid buffer index specified in readdir_handle_ctor\n");
1585db11c21SMike Marshall 		return -EINVAL;
1595db11c21SMike Marshall 	}
1605db11c21SMike Marshall 	rhandle->buffer_index = buffer_index;
1615db11c21SMike Marshall 	rhandle->dents_buf = buf;
1628092895fSAl Viro 	ret = decode_dirents(buf, size, &rhandle->readdir_response);
1635db11c21SMike Marshall 	if (ret < 0) {
1645db11c21SMike Marshall 		gossip_err("Could not decode readdir from buffer %ld\n", ret);
1655db11c21SMike Marshall 		rhandle->buffer_index = -1;
1665db11c21SMike Marshall 		gossip_debug(GOSSIP_DIR_DEBUG, "vfree %p\n", buf);
1675db11c21SMike Marshall 		vfree(buf);
1685db11c21SMike Marshall 		rhandle->dents_buf = NULL;
1695db11c21SMike Marshall 	}
1705db11c21SMike Marshall 	return ret;
1715db11c21SMike Marshall }
1725db11c21SMike Marshall 
17382d37f19SAl Viro static void readdir_handle_dtor(struct readdir_handle_s *rhandle)
1745db11c21SMike Marshall {
1755db11c21SMike Marshall 	if (rhandle == NULL)
1765db11c21SMike Marshall 		return;
1775db11c21SMike Marshall 
1785db11c21SMike Marshall 	/* kfree(NULL) is safe */
1795db11c21SMike Marshall 	kfree(rhandle->readdir_response.dirent_array);
1805db11c21SMike Marshall 	rhandle->readdir_response.dirent_array = NULL;
1815db11c21SMike Marshall 
1825db11c21SMike Marshall 	if (rhandle->buffer_index >= 0) {
18382d37f19SAl Viro 		orangefs_readdir_index_put(rhandle->buffer_index);
1845db11c21SMike Marshall 		rhandle->buffer_index = -1;
1855db11c21SMike Marshall 	}
1865db11c21SMike Marshall 	if (rhandle->dents_buf) {
1875db11c21SMike Marshall 		gossip_debug(GOSSIP_DIR_DEBUG, "vfree %p\n",
1885db11c21SMike Marshall 			     rhandle->dents_buf);
1895db11c21SMike Marshall 		vfree(rhandle->dents_buf);
1905db11c21SMike Marshall 		rhandle->dents_buf = NULL;
1915db11c21SMike Marshall 	}
1925db11c21SMike Marshall }
1935db11c21SMike Marshall 
1945db11c21SMike Marshall /*
1955db11c21SMike Marshall  * Read directory entries from an instance of an open directory.
1965db11c21SMike Marshall  */
1978bb8aefdSYi Liu static int orangefs_readdir(struct file *file, struct dir_context *ctx)
1985db11c21SMike Marshall {
1998bb8aefdSYi Liu 	struct orangefs_bufmap *bufmap = NULL;
2005db11c21SMike Marshall 	int ret = 0;
2015db11c21SMike Marshall 	int buffer_index;
20288309aaeSMike Marshall 	/*
20388309aaeSMike Marshall 	 * ptoken supports Orangefs' distributed directory logic, added
20488309aaeSMike Marshall 	 * in 2.9.2.
20588309aaeSMike Marshall 	 */
2065db11c21SMike Marshall 	__u64 *ptoken = file->private_data;
2075db11c21SMike Marshall 	__u64 pos = 0;
2085db11c21SMike Marshall 	ino_t ino = 0;
2095db11c21SMike Marshall 	struct dentry *dentry = file->f_path.dentry;
2108bb8aefdSYi Liu 	struct orangefs_kernel_op_s *new_op = NULL;
2118bb8aefdSYi Liu 	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(dentry->d_inode);
2125db11c21SMike Marshall 	int buffer_full = 0;
2135db11c21SMike Marshall 	struct readdir_handle_s rhandle;
2145db11c21SMike Marshall 	int i = 0;
2155db11c21SMike Marshall 	int len = 0;
2165db11c21SMike Marshall 	ino_t current_ino = 0;
2175db11c21SMike Marshall 	char *current_entry = NULL;
2185db11c21SMike Marshall 	long bytes_decoded;
2195db11c21SMike Marshall 
22088309aaeSMike Marshall 	gossip_debug(GOSSIP_DIR_DEBUG,
22188309aaeSMike Marshall 		     "%s: ctx->pos:%lld, ptoken = %llu\n",
2225db11c21SMike Marshall 		     __func__,
2235db11c21SMike Marshall 		     lld(ctx->pos),
2245db11c21SMike Marshall 		     llu(*ptoken));
2255db11c21SMike Marshall 
2265db11c21SMike Marshall 	pos = (__u64) ctx->pos;
2275db11c21SMike Marshall 
2285db11c21SMike Marshall 	/* are we done? */
2298bb8aefdSYi Liu 	if (pos == ORANGEFS_READDIR_END) {
2305db11c21SMike Marshall 		gossip_debug(GOSSIP_DIR_DEBUG,
2315db11c21SMike Marshall 			     "Skipping to termination path\n");
2325db11c21SMike Marshall 		return 0;
2335db11c21SMike Marshall 	}
2345db11c21SMike Marshall 
2355db11c21SMike Marshall 	gossip_debug(GOSSIP_DIR_DEBUG,
2368bb8aefdSYi Liu 		     "orangefs_readdir called on %s (pos=%llu)\n",
2375db11c21SMike Marshall 		     dentry->d_name.name, llu(pos));
2385db11c21SMike Marshall 
2395db11c21SMike Marshall 	rhandle.buffer_index = -1;
2405db11c21SMike Marshall 	rhandle.dents_buf = NULL;
2415db11c21SMike Marshall 	memset(&rhandle.readdir_response, 0, sizeof(rhandle.readdir_response));
2425db11c21SMike Marshall 
2438bb8aefdSYi Liu 	new_op = op_alloc(ORANGEFS_VFS_OP_READDIR);
2445db11c21SMike Marshall 	if (!new_op)
2455db11c21SMike Marshall 		return -ENOMEM;
2465db11c21SMike Marshall 
2475db11c21SMike Marshall 	new_op->uses_shared_memory = 1;
2488bb8aefdSYi Liu 	new_op->upcall.req.readdir.refn = orangefs_inode->refn;
2497d221485SMartin Brandenburg 	new_op->upcall.req.readdir.max_dirent_count =
2507d221485SMartin Brandenburg 	    ORANGEFS_MAX_DIRENT_COUNT_READDIR;
2515db11c21SMike Marshall 
2525db11c21SMike Marshall 	gossip_debug(GOSSIP_DIR_DEBUG,
2535db11c21SMike Marshall 		     "%s: upcall.req.readdir.refn.khandle: %pU\n",
2545db11c21SMike Marshall 		     __func__,
2555db11c21SMike Marshall 		     &new_op->upcall.req.readdir.refn.khandle);
2565db11c21SMike Marshall 
2575db11c21SMike Marshall 	new_op->upcall.req.readdir.token = *ptoken;
2585db11c21SMike Marshall 
2595db11c21SMike Marshall get_new_buffer_index:
2607d221485SMartin Brandenburg 	ret = orangefs_readdir_index_get(&bufmap, &buffer_index);
2615db11c21SMike Marshall 	if (ret < 0) {
2627d221485SMartin Brandenburg 		gossip_lerr("orangefs_readdir: orangefs_readdir_index_get() failure (%d)\n",
2635db11c21SMike Marshall 			    ret);
2645db11c21SMike Marshall 		goto out_free_op;
2655db11c21SMike Marshall 	}
2665db11c21SMike Marshall 	new_op->upcall.req.readdir.buf_index = buffer_index;
2675db11c21SMike Marshall 
2685db11c21SMike Marshall 	ret = service_operation(new_op,
2698bb8aefdSYi Liu 				"orangefs_readdir",
2705db11c21SMike Marshall 				get_interruptible_flag(dentry->d_inode));
2715db11c21SMike Marshall 
2725db11c21SMike Marshall 	gossip_debug(GOSSIP_DIR_DEBUG,
2735db11c21SMike Marshall 		     "Readdir downcall status is %d.  ret:%d\n",
2745db11c21SMike Marshall 		     new_op->downcall.status,
2755db11c21SMike Marshall 		     ret);
2765db11c21SMike Marshall 
2775db11c21SMike Marshall 	if (ret == -EAGAIN && op_state_purged(new_op)) {
2785db11c21SMike Marshall 		/*
2795db11c21SMike Marshall 		 * readdir shared memory aread has been wiped due to
2805db11c21SMike Marshall 		 * pvfs2-client-core restarting, so we must get a new
2815db11c21SMike Marshall 		 * index into the shared memory.
2825db11c21SMike Marshall 		 */
2835db11c21SMike Marshall 		gossip_debug(GOSSIP_DIR_DEBUG,
2845db11c21SMike Marshall 			"%s: Getting new buffer_index for retry of readdir..\n",
2855db11c21SMike Marshall 			 __func__);
28682d37f19SAl Viro 		orangefs_readdir_index_put(buffer_index);
2875db11c21SMike Marshall 		goto get_new_buffer_index;
2885db11c21SMike Marshall 	}
2895db11c21SMike Marshall 
2905db11c21SMike Marshall 	if (ret == -EIO && op_state_purged(new_op)) {
2915db11c21SMike Marshall 		gossip_err("%s: Client is down. Aborting readdir call.\n",
2925db11c21SMike Marshall 			__func__);
29382d37f19SAl Viro 		orangefs_readdir_index_put(buffer_index);
2945db11c21SMike Marshall 		goto out_free_op;
2955db11c21SMike Marshall 	}
2965db11c21SMike Marshall 
2975db11c21SMike Marshall 	if (ret < 0 || new_op->downcall.status != 0) {
2985db11c21SMike Marshall 		gossip_debug(GOSSIP_DIR_DEBUG,
2995db11c21SMike Marshall 			     "Readdir request failed.  Status:%d\n",
3005db11c21SMike Marshall 			     new_op->downcall.status);
30182d37f19SAl Viro 		orangefs_readdir_index_put(buffer_index);
3025db11c21SMike Marshall 		if (ret >= 0)
3035db11c21SMike Marshall 			ret = new_op->downcall.status;
3045db11c21SMike Marshall 		goto out_free_op;
3055db11c21SMike Marshall 	}
3065db11c21SMike Marshall 
3075db11c21SMike Marshall 	bytes_decoded =
3085db11c21SMike Marshall 		readdir_handle_ctor(&rhandle,
3095db11c21SMike Marshall 				    new_op->downcall.trailer_buf,
3108092895fSAl Viro 				    new_op->downcall.trailer_size,
3115db11c21SMike Marshall 				    buffer_index);
3125db11c21SMike Marshall 	if (bytes_decoded < 0) {
3138bb8aefdSYi Liu 		gossip_err("orangefs_readdir: Could not decode trailer buffer into a readdir response %d\n",
3145db11c21SMike Marshall 			ret);
3155db11c21SMike Marshall 		ret = bytes_decoded;
31682d37f19SAl Viro 		orangefs_readdir_index_put(buffer_index);
3175db11c21SMike Marshall 		goto out_free_op;
3185db11c21SMike Marshall 	}
3195db11c21SMike Marshall 
3205db11c21SMike Marshall 	if (bytes_decoded != new_op->downcall.trailer_size) {
3218bb8aefdSYi Liu 		gossip_err("orangefs_readdir: # bytes decoded (%ld) "
32288309aaeSMike Marshall 			   "!= trailer size (%ld)\n",
3235db11c21SMike Marshall 			   bytes_decoded,
3245db11c21SMike Marshall 			   (long)new_op->downcall.trailer_size);
3255db11c21SMike Marshall 		ret = -EINVAL;
3265db11c21SMike Marshall 		goto out_destroy_handle;
3275db11c21SMike Marshall 	}
3285db11c21SMike Marshall 
32988309aaeSMike Marshall 	/*
3308bb8aefdSYi Liu 	 *  orangefs doesn't actually store dot and dot-dot, but
33188309aaeSMike Marshall 	 *  we need to have them represented.
33288309aaeSMike Marshall 	 */
3335db11c21SMike Marshall 	if (pos == 0) {
3345db11c21SMike Marshall 		ino = get_ino_from_khandle(dentry->d_inode);
3355db11c21SMike Marshall 		gossip_debug(GOSSIP_DIR_DEBUG,
3365db11c21SMike Marshall 			     "%s: calling dir_emit of \".\" with pos = %llu\n",
3375db11c21SMike Marshall 			     __func__,
3385db11c21SMike Marshall 			     llu(pos));
3395db11c21SMike Marshall 		ret = dir_emit(ctx, ".", 1, ino, DT_DIR);
34088309aaeSMike Marshall 		pos += 1;
3415db11c21SMike Marshall 	}
3425db11c21SMike Marshall 
3435db11c21SMike Marshall 	if (pos == 1) {
3445db11c21SMike Marshall 		ino = get_parent_ino_from_dentry(dentry);
3455db11c21SMike Marshall 		gossip_debug(GOSSIP_DIR_DEBUG,
3465db11c21SMike Marshall 			     "%s: calling dir_emit of \"..\" with pos = %llu\n",
3475db11c21SMike Marshall 			     __func__,
3485db11c21SMike Marshall 			     llu(pos));
3495db11c21SMike Marshall 		ret = dir_emit(ctx, "..", 2, ino, DT_DIR);
35088309aaeSMike Marshall 		pos += 1;
3515db11c21SMike Marshall 	}
3525db11c21SMike Marshall 
35388309aaeSMike Marshall 	/*
3548bb8aefdSYi Liu 	 * we stored ORANGEFS_ITERATE_NEXT in ctx->pos last time around
35588309aaeSMike Marshall 	 * to prevent "finding" dot and dot-dot on any iteration
35688309aaeSMike Marshall 	 * other than the first.
35788309aaeSMike Marshall 	 */
3588bb8aefdSYi Liu 	if (ctx->pos == ORANGEFS_ITERATE_NEXT)
35988309aaeSMike Marshall 		ctx->pos = 0;
36088309aaeSMike Marshall 
36188309aaeSMike Marshall 	for (i = ctx->pos;
3628bb8aefdSYi Liu 	     i < rhandle.readdir_response.orangefs_dirent_outcount;
36388309aaeSMike Marshall 	     i++) {
3645db11c21SMike Marshall 		len = rhandle.readdir_response.dirent_array[i].d_length;
3655db11c21SMike Marshall 		current_entry = rhandle.readdir_response.dirent_array[i].d_name;
3668bb8aefdSYi Liu 		current_ino = orangefs_khandle_to_ino(
3675db11c21SMike Marshall 			&(rhandle.readdir_response.dirent_array[i].khandle));
3685db11c21SMike Marshall 
3695db11c21SMike Marshall 		gossip_debug(GOSSIP_DIR_DEBUG,
37088309aaeSMike Marshall 			     "calling dir_emit for %s with len %d"
37188309aaeSMike Marshall 			     ", ctx->pos %ld\n",
3725db11c21SMike Marshall 			     current_entry,
3735db11c21SMike Marshall 			     len,
37488309aaeSMike Marshall 			     (unsigned long)ctx->pos);
37588309aaeSMike Marshall 		/*
37688309aaeSMike Marshall 		 * type is unknown. We don't return object type
37788309aaeSMike Marshall 		 * in the dirent_array. This leaves getdents
37888309aaeSMike Marshall 		 * clueless about type.
37988309aaeSMike Marshall 		 */
3805db11c21SMike Marshall 		ret =
3815db11c21SMike Marshall 		    dir_emit(ctx, current_entry, len, current_ino, DT_UNKNOWN);
38288309aaeSMike Marshall 		if (!ret)
38388309aaeSMike Marshall 			break;
3845db11c21SMike Marshall 		ctx->pos++;
38588309aaeSMike Marshall 		gossip_debug(GOSSIP_DIR_DEBUG,
3865db11c21SMike Marshall 			      "%s: ctx->pos:%lld\n",
3875db11c21SMike Marshall 			      __func__,
3885db11c21SMike Marshall 			      lld(ctx->pos));
3895db11c21SMike Marshall 
3905db11c21SMike Marshall 	}
3915db11c21SMike Marshall 
39288309aaeSMike Marshall 	/*
39388309aaeSMike Marshall 	 * we ran all the way through the last batch, set up for
39488309aaeSMike Marshall 	 * getting another batch...
39588309aaeSMike Marshall 	 */
39688309aaeSMike Marshall 	if (ret) {
3975db11c21SMike Marshall 		*ptoken = rhandle.readdir_response.token;
3988bb8aefdSYi Liu 		ctx->pos = ORANGEFS_ITERATE_NEXT;
3995db11c21SMike Marshall 	}
4005db11c21SMike Marshall 
4015db11c21SMike Marshall 	/*
4025db11c21SMike Marshall 	 * Did we hit the end of the directory?
4035db11c21SMike Marshall 	 */
4048bb8aefdSYi Liu 	if (rhandle.readdir_response.token == ORANGEFS_READDIR_END &&
4055db11c21SMike Marshall 	    !buffer_full) {
40688309aaeSMike Marshall 		gossip_debug(GOSSIP_DIR_DEBUG,
4078bb8aefdSYi Liu 		"End of dir detected; setting ctx->pos to ORANGEFS_READDIR_END.\n");
4088bb8aefdSYi Liu 		ctx->pos = ORANGEFS_READDIR_END;
4095db11c21SMike Marshall 	}
4105db11c21SMike Marshall 
4115db11c21SMike Marshall out_destroy_handle:
41282d37f19SAl Viro 	readdir_handle_dtor(&rhandle);
4135db11c21SMike Marshall out_free_op:
4145db11c21SMike Marshall 	op_release(new_op);
4158bb8aefdSYi Liu 	gossip_debug(GOSSIP_DIR_DEBUG, "orangefs_readdir returning %d\n", ret);
4165db11c21SMike Marshall 	return ret;
4175db11c21SMike Marshall }
4185db11c21SMike Marshall 
4198bb8aefdSYi Liu static int orangefs_dir_open(struct inode *inode, struct file *file)
4205db11c21SMike Marshall {
4215db11c21SMike Marshall 	__u64 *ptoken;
4225db11c21SMike Marshall 
4235db11c21SMike Marshall 	file->private_data = kmalloc(sizeof(__u64), GFP_KERNEL);
4245db11c21SMike Marshall 	if (!file->private_data)
4255db11c21SMike Marshall 		return -ENOMEM;
4265db11c21SMike Marshall 
4275db11c21SMike Marshall 	ptoken = file->private_data;
4288bb8aefdSYi Liu 	*ptoken = ORANGEFS_READDIR_START;
4295db11c21SMike Marshall 	return 0;
4305db11c21SMike Marshall }
4315db11c21SMike Marshall 
4328bb8aefdSYi Liu static int orangefs_dir_release(struct inode *inode, struct file *file)
4335db11c21SMike Marshall {
4348bb8aefdSYi Liu 	orangefs_flush_inode(inode);
4355db11c21SMike Marshall 	kfree(file->private_data);
4365db11c21SMike Marshall 	return 0;
4375db11c21SMike Marshall }
4385db11c21SMike Marshall 
4398bb8aefdSYi Liu /** ORANGEFS implementation of VFS directory operations */
4408bb8aefdSYi Liu const struct file_operations orangefs_dir_operations = {
4415db11c21SMike Marshall 	.read = generic_read_dir,
4428bb8aefdSYi Liu 	.iterate = orangefs_readdir,
4438bb8aefdSYi Liu 	.open = orangefs_dir_open,
4448bb8aefdSYi Liu 	.release = orangefs_dir_release,
4455db11c21SMike Marshall };
446