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