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 { 128bb8aefdSYi Liu struct orangefs_readdir_response_s readdir_response; 135db11c21SMike Marshall void *dents_buf; 145db11c21SMike Marshall }; 155db11c21SMike Marshall 165db11c21SMike Marshall /* 171808f8ccSMike Marshall * decode routine used by kmod to deal with the blob sent from 181808f8ccSMike Marshall * userspace for readdirs. The blob contains zero or more of these 191808f8ccSMike Marshall * sub-blobs: 201808f8ccSMike Marshall * __u32 - represents length of the character string that follows. 211808f8ccSMike Marshall * string - between 1 and ORANGEFS_NAME_MAX bytes long. 221808f8ccSMike Marshall * padding - (if needed) to cause the __u32 plus the string to be 231808f8ccSMike Marshall * eight byte aligned. 241808f8ccSMike Marshall * khandle - sizeof(khandle) bytes. 255db11c21SMike Marshall */ 268092895fSAl Viro static long decode_dirents(char *ptr, size_t size, 278bb8aefdSYi Liu struct orangefs_readdir_response_s *readdir) 285db11c21SMike Marshall { 295db11c21SMike Marshall int i; 308bb8aefdSYi Liu struct orangefs_readdir_response_s *rd = 318bb8aefdSYi Liu (struct orangefs_readdir_response_s *) ptr; 325db11c21SMike Marshall char *buf = ptr; 331808f8ccSMike Marshall int khandle_size = sizeof(struct orangefs_khandle); 341808f8ccSMike Marshall size_t offset = offsetof(struct orangefs_readdir_response_s, 351808f8ccSMike Marshall dirent_array); 361808f8ccSMike Marshall /* 8 reflects eight byte alignment */ 371808f8ccSMike Marshall int smallest_blob = khandle_size + 8; 381808f8ccSMike Marshall __u32 len; 391808f8ccSMike Marshall int aligned_len; 401808f8ccSMike Marshall int sizeof_u32 = sizeof(__u32); 411808f8ccSMike Marshall long ret; 425db11c21SMike Marshall 431808f8ccSMike Marshall gossip_debug(GOSSIP_DIR_DEBUG, "%s: size:%zu:\n", __func__, size); 441808f8ccSMike Marshall 451808f8ccSMike Marshall /* size is = offset on empty dirs, > offset on non-empty dirs... */ 461808f8ccSMike Marshall if (size < offset) { 471808f8ccSMike Marshall gossip_err("%s: size:%zu: offset:%zu:\n", 481808f8ccSMike Marshall __func__, 491808f8ccSMike Marshall size, 501808f8ccSMike Marshall offset); 511808f8ccSMike Marshall ret = -EINVAL; 521808f8ccSMike Marshall goto out; 531808f8ccSMike Marshall } 541808f8ccSMike Marshall 551808f8ccSMike Marshall if ((size == offset) && (readdir->orangefs_dirent_outcount != 0)) { 561808f8ccSMike Marshall gossip_err("%s: size:%zu: dirent_outcount:%d:\n", 571808f8ccSMike Marshall __func__, 581808f8ccSMike Marshall size, 591808f8ccSMike Marshall readdir->orangefs_dirent_outcount); 601808f8ccSMike Marshall ret = -EINVAL; 611808f8ccSMike Marshall goto out; 621808f8ccSMike Marshall } 638092895fSAl Viro 645db11c21SMike Marshall readdir->token = rd->token; 658bb8aefdSYi Liu readdir->orangefs_dirent_outcount = rd->orangefs_dirent_outcount; 668bb8aefdSYi Liu readdir->dirent_array = kcalloc(readdir->orangefs_dirent_outcount, 675db11c21SMike Marshall sizeof(*readdir->dirent_array), 685db11c21SMike Marshall GFP_KERNEL); 691808f8ccSMike Marshall if (readdir->dirent_array == NULL) { 701808f8ccSMike Marshall gossip_err("%s: kcalloc failed.\n", __func__); 711808f8ccSMike Marshall ret = -ENOMEM; 721808f8ccSMike Marshall goto out; 731808f8ccSMike Marshall } 748092895fSAl Viro 751808f8ccSMike Marshall buf += offset; 761808f8ccSMike Marshall size -= offset; 778092895fSAl Viro 788bb8aefdSYi Liu for (i = 0; i < readdir->orangefs_dirent_outcount; i++) { 791808f8ccSMike Marshall if (size < smallest_blob) { 801808f8ccSMike Marshall gossip_err("%s: size:%zu: smallest_blob:%d:\n", 811808f8ccSMike Marshall __func__, 821808f8ccSMike Marshall size, 831808f8ccSMike Marshall smallest_blob); 841808f8ccSMike Marshall ret = -EINVAL; 851808f8ccSMike Marshall goto free; 861808f8ccSMike Marshall } 878092895fSAl Viro 888092895fSAl Viro len = *(__u32 *)buf; 891808f8ccSMike Marshall if ((len < 1) || (len > ORANGEFS_NAME_MAX)) { 901808f8ccSMike Marshall gossip_err("%s: len:%d:\n", __func__, len); 911808f8ccSMike Marshall ret = -EINVAL; 921808f8ccSMike Marshall goto free; 931808f8ccSMike Marshall } 948092895fSAl Viro 951808f8ccSMike Marshall gossip_debug(GOSSIP_DIR_DEBUG, 961808f8ccSMike Marshall "%s: size:%zu: len:%d:\n", 971808f8ccSMike Marshall __func__, 981808f8ccSMike Marshall size, 991808f8ccSMike Marshall len); 1001808f8ccSMike Marshall 1011808f8ccSMike Marshall readdir->dirent_array[i].d_name = buf + sizeof_u32; 1029be68b08SAl Viro readdir->dirent_array[i].d_length = len; 1038092895fSAl Viro 1047d221485SMartin Brandenburg /* 1051808f8ccSMike Marshall * Calculate "aligned" length of this string and its 1061808f8ccSMike Marshall * associated __u32 descriptor. 1077d221485SMartin Brandenburg */ 1081808f8ccSMike Marshall aligned_len = ((sizeof_u32 + len + 1) + 7) & ~7; 1091808f8ccSMike Marshall gossip_debug(GOSSIP_DIR_DEBUG, 1101808f8ccSMike Marshall "%s: aligned_len:%d:\n", 1111808f8ccSMike Marshall __func__, 1121808f8ccSMike Marshall aligned_len); 1138092895fSAl Viro 1141808f8ccSMike Marshall /* 1151808f8ccSMike Marshall * The end of the blob should coincide with the end 1161808f8ccSMike Marshall * of the last sub-blob. 1171808f8ccSMike Marshall */ 1181808f8ccSMike Marshall if (size < aligned_len + khandle_size) { 1191808f8ccSMike Marshall gossip_err("%s: ran off the end of the blob.\n", 1201808f8ccSMike Marshall __func__); 1211808f8ccSMike Marshall ret = -EINVAL; 1221808f8ccSMike Marshall goto free; 1231808f8ccSMike Marshall } 1241808f8ccSMike Marshall size -= aligned_len + khandle_size; 1251808f8ccSMike Marshall 1261808f8ccSMike Marshall buf += aligned_len; 1278092895fSAl Viro 1285db11c21SMike Marshall readdir->dirent_array[i].khandle = 1298bb8aefdSYi Liu *(struct orangefs_khandle *) buf; 1301808f8ccSMike Marshall buf += khandle_size; 1315db11c21SMike Marshall } 1321808f8ccSMike Marshall ret = buf - ptr; 1331808f8ccSMike Marshall gossip_debug(GOSSIP_DIR_DEBUG, "%s: returning:%ld:\n", __func__, ret); 1341808f8ccSMike Marshall goto out; 1351808f8ccSMike Marshall 1361808f8ccSMike Marshall free: 1378092895fSAl Viro kfree(readdir->dirent_array); 1388092895fSAl Viro readdir->dirent_array = NULL; 1391808f8ccSMike Marshall 1401808f8ccSMike Marshall out: 1411808f8ccSMike Marshall return ret; 1425db11c21SMike Marshall } 1435db11c21SMike Marshall 1445db11c21SMike Marshall static long readdir_handle_ctor(struct readdir_handle_s *rhandle, void *buf, 145ee3b8d37SMartin Brandenburg size_t size) 1465db11c21SMike Marshall { 1475db11c21SMike Marshall long ret; 1485db11c21SMike Marshall 1495db11c21SMike Marshall if (buf == NULL) { 1505db11c21SMike Marshall gossip_err 1515db11c21SMike Marshall ("Invalid NULL buffer specified in readdir_handle_ctor\n"); 1525db11c21SMike Marshall return -ENOMEM; 1535db11c21SMike Marshall } 1545db11c21SMike Marshall rhandle->dents_buf = buf; 1558092895fSAl Viro ret = decode_dirents(buf, size, &rhandle->readdir_response); 1565db11c21SMike Marshall if (ret < 0) { 1575db11c21SMike Marshall gossip_err("Could not decode readdir from buffer %ld\n", ret); 1585db11c21SMike Marshall gossip_debug(GOSSIP_DIR_DEBUG, "vfree %p\n", buf); 1595db11c21SMike Marshall vfree(buf); 1605db11c21SMike Marshall rhandle->dents_buf = NULL; 1615db11c21SMike Marshall } 1625db11c21SMike Marshall return ret; 1635db11c21SMike Marshall } 1645db11c21SMike Marshall 16582d37f19SAl Viro static void readdir_handle_dtor(struct readdir_handle_s *rhandle) 1665db11c21SMike Marshall { 1675db11c21SMike Marshall if (rhandle == NULL) 1685db11c21SMike Marshall return; 1695db11c21SMike Marshall 1705db11c21SMike Marshall /* kfree(NULL) is safe */ 1715db11c21SMike Marshall kfree(rhandle->readdir_response.dirent_array); 1725db11c21SMike Marshall rhandle->readdir_response.dirent_array = NULL; 1735db11c21SMike Marshall 1745db11c21SMike Marshall if (rhandle->dents_buf) { 1755db11c21SMike Marshall gossip_debug(GOSSIP_DIR_DEBUG, "vfree %p\n", 1765db11c21SMike Marshall rhandle->dents_buf); 1775db11c21SMike Marshall vfree(rhandle->dents_buf); 1785db11c21SMike Marshall rhandle->dents_buf = NULL; 1795db11c21SMike Marshall } 1805db11c21SMike Marshall } 1815db11c21SMike Marshall 1825db11c21SMike Marshall /* 1835db11c21SMike Marshall * Read directory entries from an instance of an open directory. 1845db11c21SMike Marshall */ 1858bb8aefdSYi Liu static int orangefs_readdir(struct file *file, struct dir_context *ctx) 1865db11c21SMike Marshall { 1878bb8aefdSYi Liu struct orangefs_bufmap *bufmap = NULL; 1885db11c21SMike Marshall int ret = 0; 1895db11c21SMike Marshall int buffer_index; 19088309aaeSMike Marshall /* 19188309aaeSMike Marshall * ptoken supports Orangefs' distributed directory logic, added 19288309aaeSMike Marshall * in 2.9.2. 19388309aaeSMike Marshall */ 1945db11c21SMike Marshall __u64 *ptoken = file->private_data; 1955db11c21SMike Marshall __u64 pos = 0; 1965db11c21SMike Marshall ino_t ino = 0; 1975db11c21SMike Marshall struct dentry *dentry = file->f_path.dentry; 1988bb8aefdSYi Liu struct orangefs_kernel_op_s *new_op = NULL; 1998bb8aefdSYi Liu struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(dentry->d_inode); 2005db11c21SMike Marshall int buffer_full = 0; 2015db11c21SMike Marshall struct readdir_handle_s rhandle; 2025db11c21SMike Marshall int i = 0; 2035db11c21SMike Marshall int len = 0; 2045db11c21SMike Marshall ino_t current_ino = 0; 2055db11c21SMike Marshall char *current_entry = NULL; 2065db11c21SMike Marshall long bytes_decoded; 2075db11c21SMike Marshall 20888309aaeSMike Marshall gossip_debug(GOSSIP_DIR_DEBUG, 20988309aaeSMike Marshall "%s: ctx->pos:%lld, ptoken = %llu\n", 2105db11c21SMike Marshall __func__, 2115db11c21SMike Marshall lld(ctx->pos), 2125db11c21SMike Marshall llu(*ptoken)); 2135db11c21SMike Marshall 2145db11c21SMike Marshall pos = (__u64) ctx->pos; 2155db11c21SMike Marshall 2165db11c21SMike Marshall /* are we done? */ 2178bb8aefdSYi Liu if (pos == ORANGEFS_READDIR_END) { 2185db11c21SMike Marshall gossip_debug(GOSSIP_DIR_DEBUG, 2195db11c21SMike Marshall "Skipping to termination path\n"); 2205db11c21SMike Marshall return 0; 2215db11c21SMike Marshall } 2225db11c21SMike Marshall 2235db11c21SMike Marshall gossip_debug(GOSSIP_DIR_DEBUG, 2248bb8aefdSYi Liu "orangefs_readdir called on %s (pos=%llu)\n", 2255db11c21SMike Marshall dentry->d_name.name, llu(pos)); 2265db11c21SMike Marshall 2275db11c21SMike Marshall rhandle.dents_buf = NULL; 2285db11c21SMike Marshall memset(&rhandle.readdir_response, 0, sizeof(rhandle.readdir_response)); 2295db11c21SMike Marshall 2308bb8aefdSYi Liu new_op = op_alloc(ORANGEFS_VFS_OP_READDIR); 2315db11c21SMike Marshall if (!new_op) 2325db11c21SMike Marshall return -ENOMEM; 2335db11c21SMike Marshall 234ee3b8d37SMartin Brandenburg /* 235ee3b8d37SMartin Brandenburg * Only the indices are shared. No memory is actually shared, but the 236ee3b8d37SMartin Brandenburg * mechanism is used. 237ee3b8d37SMartin Brandenburg */ 2385db11c21SMike Marshall new_op->uses_shared_memory = 1; 2398bb8aefdSYi Liu new_op->upcall.req.readdir.refn = orangefs_inode->refn; 2407d221485SMartin Brandenburg new_op->upcall.req.readdir.max_dirent_count = 2417d221485SMartin Brandenburg ORANGEFS_MAX_DIRENT_COUNT_READDIR; 2425db11c21SMike Marshall 2435db11c21SMike Marshall gossip_debug(GOSSIP_DIR_DEBUG, 2445db11c21SMike Marshall "%s: upcall.req.readdir.refn.khandle: %pU\n", 2455db11c21SMike Marshall __func__, 2465db11c21SMike Marshall &new_op->upcall.req.readdir.refn.khandle); 2475db11c21SMike Marshall 2485db11c21SMike Marshall new_op->upcall.req.readdir.token = *ptoken; 2495db11c21SMike Marshall 2505db11c21SMike Marshall get_new_buffer_index: 2517d221485SMartin Brandenburg ret = orangefs_readdir_index_get(&bufmap, &buffer_index); 2525db11c21SMike Marshall if (ret < 0) { 2537d221485SMartin Brandenburg gossip_lerr("orangefs_readdir: orangefs_readdir_index_get() failure (%d)\n", 2545db11c21SMike Marshall ret); 2555db11c21SMike Marshall goto out_free_op; 2565db11c21SMike Marshall } 2575db11c21SMike Marshall new_op->upcall.req.readdir.buf_index = buffer_index; 2585db11c21SMike Marshall 2595db11c21SMike Marshall ret = service_operation(new_op, 2608bb8aefdSYi Liu "orangefs_readdir", 2615db11c21SMike Marshall get_interruptible_flag(dentry->d_inode)); 2625db11c21SMike Marshall 2635db11c21SMike Marshall gossip_debug(GOSSIP_DIR_DEBUG, 2645db11c21SMike Marshall "Readdir downcall status is %d. ret:%d\n", 2655db11c21SMike Marshall new_op->downcall.status, 2665db11c21SMike Marshall ret); 2675db11c21SMike Marshall 268ee3b8d37SMartin Brandenburg orangefs_readdir_index_put(buffer_index); 269ee3b8d37SMartin Brandenburg 2705db11c21SMike Marshall if (ret == -EAGAIN && op_state_purged(new_op)) { 271ee3b8d37SMartin Brandenburg /* Client-core indices are invalid after it restarted. */ 2725db11c21SMike Marshall gossip_debug(GOSSIP_DIR_DEBUG, 2735db11c21SMike Marshall "%s: Getting new buffer_index for retry of readdir..\n", 2745db11c21SMike Marshall __func__); 2755db11c21SMike Marshall goto get_new_buffer_index; 2765db11c21SMike Marshall } 2775db11c21SMike Marshall 2785db11c21SMike Marshall if (ret == -EIO && op_state_purged(new_op)) { 2795db11c21SMike Marshall gossip_err("%s: Client is down. Aborting readdir call.\n", 2805db11c21SMike Marshall __func__); 2815db11c21SMike Marshall goto out_free_op; 2825db11c21SMike Marshall } 2835db11c21SMike Marshall 2845db11c21SMike Marshall if (ret < 0 || new_op->downcall.status != 0) { 2855db11c21SMike Marshall gossip_debug(GOSSIP_DIR_DEBUG, 2865db11c21SMike Marshall "Readdir request failed. Status:%d\n", 2875db11c21SMike Marshall new_op->downcall.status); 2885db11c21SMike Marshall if (ret >= 0) 2895db11c21SMike Marshall ret = new_op->downcall.status; 2905db11c21SMike Marshall goto out_free_op; 2915db11c21SMike Marshall } 2925db11c21SMike Marshall 2935db11c21SMike Marshall bytes_decoded = 2945db11c21SMike Marshall readdir_handle_ctor(&rhandle, 2955db11c21SMike Marshall new_op->downcall.trailer_buf, 296ee3b8d37SMartin Brandenburg new_op->downcall.trailer_size); 2975db11c21SMike Marshall if (bytes_decoded < 0) { 2988bb8aefdSYi Liu gossip_err("orangefs_readdir: Could not decode trailer buffer into a readdir response %d\n", 2995db11c21SMike Marshall ret); 3005db11c21SMike Marshall ret = bytes_decoded; 3015db11c21SMike Marshall goto out_free_op; 3025db11c21SMike Marshall } 3035db11c21SMike Marshall 3045db11c21SMike Marshall if (bytes_decoded != new_op->downcall.trailer_size) { 3058bb8aefdSYi Liu gossip_err("orangefs_readdir: # bytes decoded (%ld) " 30688309aaeSMike Marshall "!= trailer size (%ld)\n", 3075db11c21SMike Marshall bytes_decoded, 3085db11c21SMike Marshall (long)new_op->downcall.trailer_size); 3095db11c21SMike Marshall ret = -EINVAL; 3105db11c21SMike Marshall goto out_destroy_handle; 3115db11c21SMike Marshall } 3125db11c21SMike Marshall 31388309aaeSMike Marshall /* 3148bb8aefdSYi Liu * orangefs doesn't actually store dot and dot-dot, but 31588309aaeSMike Marshall * we need to have them represented. 31688309aaeSMike Marshall */ 3175db11c21SMike Marshall if (pos == 0) { 3185db11c21SMike Marshall ino = get_ino_from_khandle(dentry->d_inode); 3195db11c21SMike Marshall gossip_debug(GOSSIP_DIR_DEBUG, 3205db11c21SMike Marshall "%s: calling dir_emit of \".\" with pos = %llu\n", 3215db11c21SMike Marshall __func__, 3225db11c21SMike Marshall llu(pos)); 3235db11c21SMike Marshall ret = dir_emit(ctx, ".", 1, ino, DT_DIR); 32488309aaeSMike Marshall pos += 1; 3255db11c21SMike Marshall } 3265db11c21SMike Marshall 3275db11c21SMike Marshall if (pos == 1) { 3285db11c21SMike Marshall ino = get_parent_ino_from_dentry(dentry); 3295db11c21SMike Marshall gossip_debug(GOSSIP_DIR_DEBUG, 3305db11c21SMike Marshall "%s: calling dir_emit of \"..\" with pos = %llu\n", 3315db11c21SMike Marshall __func__, 3325db11c21SMike Marshall llu(pos)); 3335db11c21SMike Marshall ret = dir_emit(ctx, "..", 2, ino, DT_DIR); 33488309aaeSMike Marshall pos += 1; 3355db11c21SMike Marshall } 3365db11c21SMike Marshall 33788309aaeSMike Marshall /* 3388bb8aefdSYi Liu * we stored ORANGEFS_ITERATE_NEXT in ctx->pos last time around 33988309aaeSMike Marshall * to prevent "finding" dot and dot-dot on any iteration 34088309aaeSMike Marshall * other than the first. 34188309aaeSMike Marshall */ 3428bb8aefdSYi Liu if (ctx->pos == ORANGEFS_ITERATE_NEXT) 34388309aaeSMike Marshall ctx->pos = 0; 34488309aaeSMike Marshall 34588309aaeSMike Marshall for (i = ctx->pos; 3468bb8aefdSYi Liu i < rhandle.readdir_response.orangefs_dirent_outcount; 34788309aaeSMike Marshall i++) { 3485db11c21SMike Marshall len = rhandle.readdir_response.dirent_array[i].d_length; 3495db11c21SMike Marshall current_entry = rhandle.readdir_response.dirent_array[i].d_name; 3508bb8aefdSYi Liu current_ino = orangefs_khandle_to_ino( 3515db11c21SMike Marshall &(rhandle.readdir_response.dirent_array[i].khandle)); 3525db11c21SMike Marshall 3535db11c21SMike Marshall gossip_debug(GOSSIP_DIR_DEBUG, 35488309aaeSMike Marshall "calling dir_emit for %s with len %d" 35588309aaeSMike Marshall ", ctx->pos %ld\n", 3565db11c21SMike Marshall current_entry, 3575db11c21SMike Marshall len, 35888309aaeSMike Marshall (unsigned long)ctx->pos); 35988309aaeSMike Marshall /* 36088309aaeSMike Marshall * type is unknown. We don't return object type 36188309aaeSMike Marshall * in the dirent_array. This leaves getdents 36288309aaeSMike Marshall * clueless about type. 36388309aaeSMike Marshall */ 3645db11c21SMike Marshall ret = 3655db11c21SMike Marshall dir_emit(ctx, current_entry, len, current_ino, DT_UNKNOWN); 36688309aaeSMike Marshall if (!ret) 36788309aaeSMike Marshall break; 3685db11c21SMike Marshall ctx->pos++; 36988309aaeSMike Marshall gossip_debug(GOSSIP_DIR_DEBUG, 3705db11c21SMike Marshall "%s: ctx->pos:%lld\n", 3715db11c21SMike Marshall __func__, 3725db11c21SMike Marshall lld(ctx->pos)); 3735db11c21SMike Marshall 3745db11c21SMike Marshall } 3755db11c21SMike Marshall 37688309aaeSMike Marshall /* 37788309aaeSMike Marshall * we ran all the way through the last batch, set up for 37888309aaeSMike Marshall * getting another batch... 37988309aaeSMike Marshall */ 38088309aaeSMike Marshall if (ret) { 3815db11c21SMike Marshall *ptoken = rhandle.readdir_response.token; 3828bb8aefdSYi Liu ctx->pos = ORANGEFS_ITERATE_NEXT; 3835db11c21SMike Marshall } 3845db11c21SMike Marshall 3855db11c21SMike Marshall /* 3865db11c21SMike Marshall * Did we hit the end of the directory? 3875db11c21SMike Marshall */ 3888bb8aefdSYi Liu if (rhandle.readdir_response.token == ORANGEFS_READDIR_END && 3895db11c21SMike Marshall !buffer_full) { 39088309aaeSMike Marshall gossip_debug(GOSSIP_DIR_DEBUG, 3918bb8aefdSYi Liu "End of dir detected; setting ctx->pos to ORANGEFS_READDIR_END.\n"); 3928bb8aefdSYi Liu ctx->pos = ORANGEFS_READDIR_END; 3935db11c21SMike Marshall } 3945db11c21SMike Marshall 3955db11c21SMike Marshall out_destroy_handle: 39682d37f19SAl Viro readdir_handle_dtor(&rhandle); 3975db11c21SMike Marshall out_free_op: 3985db11c21SMike Marshall op_release(new_op); 3998bb8aefdSYi Liu gossip_debug(GOSSIP_DIR_DEBUG, "orangefs_readdir returning %d\n", ret); 4005db11c21SMike Marshall return ret; 4015db11c21SMike Marshall } 4025db11c21SMike Marshall 4038bb8aefdSYi Liu static int orangefs_dir_open(struct inode *inode, struct file *file) 4045db11c21SMike Marshall { 4055db11c21SMike Marshall __u64 *ptoken; 4065db11c21SMike Marshall 4075db11c21SMike Marshall file->private_data = kmalloc(sizeof(__u64), GFP_KERNEL); 4085db11c21SMike Marshall if (!file->private_data) 4095db11c21SMike Marshall return -ENOMEM; 4105db11c21SMike Marshall 4115db11c21SMike Marshall ptoken = file->private_data; 4128bb8aefdSYi Liu *ptoken = ORANGEFS_READDIR_START; 4135db11c21SMike Marshall return 0; 4145db11c21SMike Marshall } 4155db11c21SMike Marshall 4168bb8aefdSYi Liu static int orangefs_dir_release(struct inode *inode, struct file *file) 4175db11c21SMike Marshall { 4188bb8aefdSYi Liu orangefs_flush_inode(inode); 4195db11c21SMike Marshall kfree(file->private_data); 4205db11c21SMike Marshall return 0; 4215db11c21SMike Marshall } 4225db11c21SMike Marshall 4238bb8aefdSYi Liu /** ORANGEFS implementation of VFS directory operations */ 4248bb8aefdSYi Liu const struct file_operations orangefs_dir_operations = { 4255db11c21SMike Marshall .read = generic_read_dir, 4268bb8aefdSYi Liu .iterate = orangefs_readdir, 4278bb8aefdSYi Liu .open = orangefs_dir_open, 4288bb8aefdSYi Liu .release = orangefs_dir_release, 4295db11c21SMike Marshall }; 430