^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright 2017 Omnibond Systems, L.L.C.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include "protocol.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include "orangefs-kernel.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "orangefs-bufmap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) struct orangefs_dir_part {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) struct orangefs_dir_part *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) struct orangefs_dir {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) __u64 token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) struct orangefs_dir_part *part;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) loff_t end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define PART_SHIFT (24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define PART_SIZE (1<<24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define PART_MASK (~(PART_SIZE - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * There can be up to 512 directory entries. Each entry is encoded as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * follows:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * 4 bytes: string size (n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * n bytes: string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * 1 byte: trailing zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * padding to 8 bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * 16 bytes: khandle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * padding to 8 bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * The trailer_buf starts with a struct orangefs_readdir_response_s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * which must be skipped to get to the directory data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * The data which is received from the userspace daemon is termed a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * part and is stored in a linked list in case more than one part is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * needed for a large directory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * The position pointer (ctx->pos) encodes the part and offset on which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * to begin reading at. Bits above PART_SHIFT encode the part and bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * below PART_SHIFT encode the offset. Parts are stored in a linked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * list which grows as data is received from the server. The overhead
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * associated with managing the list is presumed to be small compared to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * the overhead of communicating with the server.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * As data is received from the server, it is placed at the end of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * part list. Data is parsed from the current position as it is needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * When data is determined to be corrupt, it is either because the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * userspace component has sent back corrupt data or because the file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * pointer has been moved to an invalid location. Since the two cannot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * be differentiated, return EIO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * Part zero is synthesized to contains `.' and `..'. Part one is the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * first part of the part list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static int do_readdir(struct orangefs_inode_s *oi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct orangefs_dir *od, struct dentry *dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct orangefs_kernel_op_s *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct orangefs_readdir_response_s *resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) int bufi, r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * Despite the badly named field, readdir does not use shared
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * memory. However, there are a limited number of readdir
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * slots, which must be allocated here. This flag simply tells
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * the op scheduler to return the op here for retry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) op->uses_shared_memory = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) op->upcall.req.readdir.refn = oi->refn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) op->upcall.req.readdir.token = od->token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) op->upcall.req.readdir.max_dirent_count =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) ORANGEFS_MAX_DIRENT_COUNT_READDIR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) again:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) bufi = orangefs_readdir_index_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (bufi < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) od->error = bufi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return bufi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) op->upcall.req.readdir.buf_index = bufi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) r = service_operation(op, "orangefs_readdir",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) get_interruptible_flag(dentry->d_inode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) orangefs_readdir_index_put(bufi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (op_state_purged(op)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (r == -EAGAIN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) vfree(op->downcall.trailer_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) goto again;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) } else if (r == -EIO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) vfree(op->downcall.trailer_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) od->error = r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (r < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) vfree(op->downcall.trailer_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) od->error = r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) } else if (op->downcall.status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) vfree(op->downcall.trailer_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) od->error = op->downcall.status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return op->downcall.status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * The maximum size is size per entry times the 512 entries plus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * the header. This is well under the limit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (op->downcall.trailer_size > PART_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) vfree(op->downcall.trailer_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) od->error = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) resp = (struct orangefs_readdir_response_s *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) op->downcall.trailer_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) od->token = resp->token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static int parse_readdir(struct orangefs_dir *od,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct orangefs_kernel_op_s *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct orangefs_dir_part *part, *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) size_t count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) part = od->part;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) while (part) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (part->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) part = part->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) new = (void *)op->downcall.trailer_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) new->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) new->len = op->downcall.trailer_size -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) sizeof(struct orangefs_readdir_response_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (!od->part)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) od->part = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) part->next = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) od->end = count << PART_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static int orangefs_dir_more(struct orangefs_inode_s *oi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct orangefs_dir *od, struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct orangefs_kernel_op_s *op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) op = op_alloc(ORANGEFS_VFS_OP_READDIR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (!op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) od->error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) r = do_readdir(oi, od, dentry, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) od->error = r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) r = parse_readdir(od, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) od->error = r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) od->error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) op_release(op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return od->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static int fill_from_part(struct orangefs_dir_part *part,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) struct dir_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) const int offset = sizeof(struct orangefs_readdir_response_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct orangefs_khandle *khandle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) __u32 *len, padlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) loff_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) char *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) i = ctx->pos & ~PART_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) /* The file offset from userspace is too large. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (i > part->len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * If the seek pointer is positioned just before an entry it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * should find the next entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (i % 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) i = i + (8 - i%8)%8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) while (i < part->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (part->len < i + sizeof *len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) len = (void *)part + offset + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * len is the size of the string itself. padlen is the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * total size of the encoded string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) padlen = (sizeof *len + *len + 1) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) (8 - (sizeof *len + *len + 1)%8)%8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (part->len < i + padlen + sizeof *khandle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) s = (void *)part + offset + i + sizeof *len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (s[*len] != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) khandle = (void *)part + offset + i + padlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (!dir_emit(ctx, s, *len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) orangefs_khandle_to_ino(khandle),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) DT_UNKNOWN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) i += padlen + sizeof *khandle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) i = i + (8 - i%8)%8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) BUG_ON(i > part->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) ctx->pos = (ctx->pos & PART_MASK) | i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) i += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static int orangefs_dir_fill(struct orangefs_inode_s *oi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) struct orangefs_dir *od, struct dentry *dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) struct dir_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) struct orangefs_dir_part *part;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) size_t count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) count = ((ctx->pos & PART_MASK) >> PART_SHIFT) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) part = od->part;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) while (part->next && count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) part = part->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /* This means the userspace file offset is invalid. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) od->error = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) while (part && part->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) r = fill_from_part(part, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (r < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) od->error = r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) } else if (r == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) /* Userspace buffer is full. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * The part ran out of data. Move to the next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * part. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) ctx->pos = (ctx->pos & PART_MASK) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) (1 << PART_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) part = part->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) static loff_t orangefs_dir_llseek(struct file *file, loff_t offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) int whence)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) struct orangefs_dir *od = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) * Delete the stored data so userspace sees new directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) * entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (!whence && offset < od->end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) struct orangefs_dir_part *part = od->part;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) while (part) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) struct orangefs_dir_part *next = part->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) vfree(part);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) part = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) od->token = ORANGEFS_ITERATE_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) od->part = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) od->end = 1 << PART_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return default_llseek(file, offset, whence);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static int orangefs_dir_iterate(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) struct dir_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) struct orangefs_inode_s *oi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) struct orangefs_dir *od;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) struct dentry *dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) dentry = file->f_path.dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) oi = ORANGEFS_I(dentry->d_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) od = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (od->error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return od->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (ctx->pos == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (!dir_emit_dot(file, ctx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) ctx->pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (ctx->pos == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (!dir_emit_dotdot(file, ctx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) ctx->pos = 1 << PART_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * The seek position is in the first synthesized part but is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * valid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if ((ctx->pos & PART_MASK) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) r = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) * Must read more if the user has sought past what has been read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) * so far. Stop a user who has sought past the end.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) while (od->token != ORANGEFS_ITERATE_END &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) ctx->pos > od->end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) r = orangefs_dir_more(oi, od, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (od->token == ORANGEFS_ITERATE_END && ctx->pos > od->end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /* Then try to fill if there's any left in the buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (ctx->pos < od->end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) r = orangefs_dir_fill(oi, od, dentry, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) /* Finally get some more and try to fill. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (od->token != ORANGEFS_ITERATE_END) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) r = orangefs_dir_more(oi, od, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) r = orangefs_dir_fill(oi, od, dentry, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static int orangefs_dir_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) struct orangefs_dir *od;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) file->private_data = kmalloc(sizeof(struct orangefs_dir),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (!file->private_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) od = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) od->token = ORANGEFS_ITERATE_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) od->part = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) od->end = 1 << PART_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) od->error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) static int orangefs_dir_release(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) struct orangefs_dir *od = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) struct orangefs_dir_part *part = od->part;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) while (part) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) struct orangefs_dir_part *next = part->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) vfree(part);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) part = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) kfree(od);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) const struct file_operations orangefs_dir_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) .llseek = orangefs_dir_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) .read = generic_read_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) .iterate = orangefs_dir_iterate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) .open = orangefs_dir_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) .release = orangefs_dir_release
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) };