Commit 03341d2cc91c700fc38883e572043a6a8f17dd5c
Committed by
Trond Myklebust
1 parent
a60d2ebd93
Exists in
master
and in
6 other branches
pnfsblock: merge extents
Replace a stub, so that extents underlying the layouts are properly added, merged, or ignored as necessary. Signed-off-by: Fred Isaman <iisaman@citi.umich.edu> [pnfsblock: delete the new node before put it] Signed-off-by: Mingyang Guo <guomingyang@nrchpc.ac.cn> Signed-off-by: Benny Halevy <bhalevy@panasas.com> Signed-off-by: Peng Tao <peng_tao@emc.com> Signed-off-by: Benny Halevy <bhalevy@tonian.com> Signed-off-by: Jim Rees <rees@umich.edu> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Showing 2 changed files with 119 additions and 0 deletions Side-by-side Diff
fs/nfs/blocklayout/blocklayout.h
... | ... | @@ -80,6 +80,14 @@ |
80 | 80 | EXTENT_LISTS = 2, |
81 | 81 | }; |
82 | 82 | |
83 | +static inline int bl_choose_list(enum exstate4 state) | |
84 | +{ | |
85 | + if (state == PNFS_BLOCK_READ_DATA || state == PNFS_BLOCK_NONE_DATA) | |
86 | + return RO_EXTENT; | |
87 | + else | |
88 | + return RW_EXTENT; | |
89 | +} | |
90 | + | |
83 | 91 | struct pnfs_block_layout { |
84 | 92 | struct pnfs_layout_hdr bl_layout; |
85 | 93 | struct pnfs_inval_markings bl_inval; /* tracks INVAL->RW transition */ |
86 | 94 | |
... | ... | @@ -137,6 +145,11 @@ |
137 | 145 | /* blocklayoutdm.c */ |
138 | 146 | void bl_free_block_dev(struct pnfs_block_dev *bdev); |
139 | 147 | |
148 | +/* extents.c */ | |
140 | 149 | void bl_put_extent(struct pnfs_block_extent *be); |
150 | +struct pnfs_block_extent *bl_alloc_extent(void); | |
151 | +int bl_add_merge_extent(struct pnfs_block_layout *bl, | |
152 | + struct pnfs_block_extent *new); | |
153 | + | |
141 | 154 | #endif /* FS_NFS_NFS4BLOCKLAYOUT_H */ |
fs/nfs/blocklayout/extents.c
... | ... | @@ -87,4 +87,110 @@ |
87 | 87 | } |
88 | 88 | dprintk("****************\n"); |
89 | 89 | } |
90 | + | |
91 | +static inline int | |
92 | +extents_consistent(struct pnfs_block_extent *old, struct pnfs_block_extent *new) | |
93 | +{ | |
94 | + /* Note this assumes new->be_f_offset >= old->be_f_offset */ | |
95 | + return (new->be_state == old->be_state) && | |
96 | + ((new->be_state == PNFS_BLOCK_NONE_DATA) || | |
97 | + ((new->be_v_offset - old->be_v_offset == | |
98 | + new->be_f_offset - old->be_f_offset) && | |
99 | + new->be_mdev == old->be_mdev)); | |
100 | +} | |
101 | + | |
102 | +/* Adds new to appropriate list in bl, modifying new and removing existing | |
103 | + * extents as appropriate to deal with overlaps. | |
104 | + * | |
105 | + * See bl_find_get_extent for list constraints. | |
106 | + * | |
107 | + * Refcount on new is already set. If end up not using it, or error out, | |
108 | + * need to put the reference. | |
109 | + * | |
110 | + * bl->bl_ext_lock is held by caller. | |
111 | + */ | |
112 | +int | |
113 | +bl_add_merge_extent(struct pnfs_block_layout *bl, | |
114 | + struct pnfs_block_extent *new) | |
115 | +{ | |
116 | + struct pnfs_block_extent *be, *tmp; | |
117 | + sector_t end = new->be_f_offset + new->be_length; | |
118 | + struct list_head *list; | |
119 | + | |
120 | + dprintk("%s enter with be=%p\n", __func__, new); | |
121 | + print_bl_extent(new); | |
122 | + list = &bl->bl_extents[bl_choose_list(new->be_state)]; | |
123 | + print_elist(list); | |
124 | + | |
125 | + /* Scan for proper place to insert, extending new to the left | |
126 | + * as much as possible. | |
127 | + */ | |
128 | + list_for_each_entry_safe(be, tmp, list, be_node) { | |
129 | + if (new->be_f_offset < be->be_f_offset) | |
130 | + break; | |
131 | + if (end <= be->be_f_offset + be->be_length) { | |
132 | + /* new is a subset of existing be*/ | |
133 | + if (extents_consistent(be, new)) { | |
134 | + dprintk("%s: new is subset, ignoring\n", | |
135 | + __func__); | |
136 | + bl_put_extent(new); | |
137 | + return 0; | |
138 | + } else | |
139 | + goto out_err; | |
140 | + } else if (new->be_f_offset <= | |
141 | + be->be_f_offset + be->be_length) { | |
142 | + /* new overlaps or abuts existing be */ | |
143 | + if (extents_consistent(be, new)) { | |
144 | + /* extend new to fully replace be */ | |
145 | + new->be_length += new->be_f_offset - | |
146 | + be->be_f_offset; | |
147 | + new->be_f_offset = be->be_f_offset; | |
148 | + new->be_v_offset = be->be_v_offset; | |
149 | + dprintk("%s: removing %p\n", __func__, be); | |
150 | + list_del(&be->be_node); | |
151 | + bl_put_extent(be); | |
152 | + } else if (new->be_f_offset != | |
153 | + be->be_f_offset + be->be_length) | |
154 | + goto out_err; | |
155 | + } | |
156 | + } | |
157 | + /* Note that if we never hit the above break, be will not point to a | |
158 | + * valid extent. However, in that case &be->be_node==list. | |
159 | + */ | |
160 | + list_add_tail(&new->be_node, &be->be_node); | |
161 | + dprintk("%s: inserting new\n", __func__); | |
162 | + print_elist(list); | |
163 | + /* Scan forward for overlaps. If we find any, extend new and | |
164 | + * remove the overlapped extent. | |
165 | + */ | |
166 | + be = list_prepare_entry(new, list, be_node); | |
167 | + list_for_each_entry_safe_continue(be, tmp, list, be_node) { | |
168 | + if (end < be->be_f_offset) | |
169 | + break; | |
170 | + /* new overlaps or abuts existing be */ | |
171 | + if (extents_consistent(be, new)) { | |
172 | + if (end < be->be_f_offset + be->be_length) { | |
173 | + /* extend new to fully cover be */ | |
174 | + end = be->be_f_offset + be->be_length; | |
175 | + new->be_length = end - new->be_f_offset; | |
176 | + } | |
177 | + dprintk("%s: removing %p\n", __func__, be); | |
178 | + list_del(&be->be_node); | |
179 | + bl_put_extent(be); | |
180 | + } else if (end != be->be_f_offset) { | |
181 | + list_del(&new->be_node); | |
182 | + goto out_err; | |
183 | + } | |
184 | + } | |
185 | + dprintk("%s: after merging\n", __func__); | |
186 | + print_elist(list); | |
187 | + /* FIXME - The per-list consistency checks have all been done, | |
188 | + * should now check cross-list consistency. | |
189 | + */ | |
190 | + return 0; | |
191 | + | |
192 | + out_err: | |
193 | + bl_put_extent(new); | |
194 | + return -EIO; | |
195 | +} |