2 #define _FILE_OFFSET_BITS 64
13 /* Add a new device to lafs.
14 * This just sets up the internal data structures.
15 * We at least need to lafs_write_dev() to write metadata out, and may want some
16 * mount call to connect this to an active lafs.
19 static int destroy(struct lafs_device *dev)
25 static int get_logical_block_size(int fd)
33 if ((stb.st_mode & S_IFMT) != S_IFBLK)
35 sprintf(path, "/sys/dev/block/%d:%d/queue/logical_block_size",
36 major(stb.st_rdev), minor(stb.st_rdev));
37 sfd = open(path, O_RDONLY);
39 int n = read(sfd, buf, sizeof(buf));
50 struct lafs_device *lafs_add_device(struct lafs *fs, char *devname, int fd,
51 loff_t segblocks, loff_t strideblocks,
52 int width, int usage_inum)
54 struct lafs_device *dev = talloc(fs, struct lafs_device);
55 struct lafs_device *d2;
56 unsigned long long size;
60 memset(dev, 0, sizeof(*dev));
63 dev->devnum = fs->loaded_devs++;
64 dev->name = talloc_strdup(dev, devname);
67 dev->stride = strideblocks;
68 dev->segment_size = segblocks;
69 dev->usage_inum = usage_inum;
75 if (dev->segment_size > fs->max_segment)
76 fs->max_segment = dev->segment_size;
78 if (dev->width * dev->stride <= dev->segment_size) {
79 dev->tables_per_seg = dev->segment_size /
80 dev->width / dev->stride;
81 dev->rows_per_table = dev->stride;
82 dev->segment_stride = dev->segment_size;
84 dev->tables_per_seg = 1;
85 dev->rows_per_table = dev->segment_size / dev->width;
86 dev->segment_stride = dev->rows_per_table;
88 gettimeofday(&dev->ctime, NULL);
90 talloc_set_destructor(dev, destroy);
92 /* now need to work out where the metadata goes and how much room
93 * is left for segments.
94 * Device block needs 1K and goes once at start and once at end.
95 * Start location is 1K in unless basic block size is larger
97 if (ioctl(fd, BLKGETSIZE64, &size) < 0)
98 size = lseek64(fd, 0, SEEK_END);
99 devblk = get_logical_block_size(fd);
100 if (devblk < LAFS_DEVBLK_SIZE)
101 devblk = LAFS_DEVBLK_SIZE;
103 size &= ~(unsigned long long)(devblk-1);
107 dev->devaddr[0] = devblk;
111 dev->devaddr[1] = size - devblk;
112 /* State block has size set by 'fs->statesize'.
113 * We have two at the start of the device and two at the end.
114 * If stride*width < segment size we put them at multiples of width*stride
115 * If stride*width > segment size we put them at multiples of statesize
117 /* FIXME just do the simple version for now */
118 if (dev->width != 1 || dev->stride != 1)
120 if (devblk < fs->statesize)
121 devblk = fs->statesize;
122 dev->stateaddr[0] = 2 * devblk;
123 dev->stateaddr[1] = 3 * devblk;
124 dev->stateaddr[2] = size - 2*devblk;
125 dev->stateaddr[3] = size - 3*devblk;
127 /* segments need to align with width*stride too - later */
128 dev->segment_offset = 4 * devblk;
129 dev->segment_stride = dev->segment_size;
130 dev->segment_count = (dev->stateaddr[3] - dev->segment_offset) / fs->blocksize / dev->segment_size;
133 dev->tablesize = ((dev->segment_count + (fs->blocksize >> USAGE_SHIFT) + 1)
134 / (fs->blocksize >> USAGE_SHIFT));
136 dev->size = dev->segment_count * dev->segment_size;
138 /* Need to find a suitable offset */
140 for (d2 = dev->next; d2 ; d2 = d2->next) {
141 if (dev->start < d2->start + d2->size &&
142 dev->start + dev->size > d2->start) {
143 dev->start = d2->start + d2->size;
144 /* start again from top */
149 for (seg = 0; seg < dev->segment_count; seg++)
150 if (lafs_add_free_seg(fs, dev->devnum, seg) == 0)