Messages in this thread | | | Date | Sun, 12 Feb 2012 15:08:28 +0100 | Subject | Re: [PATCH 2/2] [RFC] fadvise: Add _VOLATILE,_ISVOLATILE, and _NONVOLATILE flags | From | Dmitry Adamushko <> |
| |
On 10 February 2012 01:16, John Stultz <john.stultz@linaro.org> wrote:
[ ... ]
> +/* > + * Mark a region as nonvolatile, returns 1 if any pages in the region > + * were purged. > + */ > +long mapping_range_nonvolatile(struct address_space *mapping, > + pgoff_t start_index, pgoff_t end_index) > +{ > + struct volatile_range *new; > + struct range_tree_node *node; > + int ret = 0; > + u64 start, end; > + start = (u64)start_index; > + end = (u64)end_index; > + > + mutex_lock(&mapping->vlist_mutex); > + node = range_tree_in_range(mapping->volatile_root, start, end); > + while (node) { > + struct volatile_range *vrange; > + vrange = container_of(node, struct volatile_range, range_node); > + > + ret |= vrange->purged;
again, racing with volatile_shrink() here, so we can return a stale state.
> + > + if (start <= node->start && end >= node->end) { > + vrange_del(vrange); > + } else if (node->start >= start) { > + volatile_range_shrink(vrange, end+1, node->end); > + } else if (node->end <= end) { > + volatile_range_shrink(vrange, node->start, start-1); > + } else { > + /* create new node */ > + new = vrange_alloc(); /* XXX ENOMEM HERE? */ > + > + new->mapping = mapping; > + new->range_node.start = end + 1; > + new->range_node.end = node->end;
new->purged = vrange->purged ?
> + volatile_range_shrink(vrange, node->start, start-1); > + mapping->volatile_root = > + range_tree_add(mapping->volatile_root, > + &new->range_node); > + if (range_on_lru(new)) > + lru_add(new); > + break; > + } > + node = range_tree_in_range(mapping->volatile_root, start, end); > + } > + mutex_unlock(&mapping->vlist_mutex); > + > + return ret; > +} > +
Also, I have a question about mapping_range_volatile().
+long mapping_range_volatile(struct address_space *mapping, + pgoff_t start_index, pgoff_t end_index) +{ + struct volatile_range *new; + struct range_tree_node *node; + + u64 start, end; + int purged = 0; + start = (u64)start_index; + end = (u64)end_index; + + new = vrange_alloc(); + if (!new) + return -ENOMEM; + + mutex_lock(&mapping->vlist_mutex); + + node = range_tree_in_range_adjacent(mapping->volatile_root, start, end); + while (node) { + struct volatile_range *vrange; + + /* Already entirely marked volatile, so we're done */ + if (node->start < start && node->end > end) { + /* don't need the allocated value */ + kfree(new); + return 0; + } + + /* Grab containing volatile range */ + vrange = container_of(node, struct volatile_range, range_node); + + /* resize range */ + start = min_t(u64, start, node->start); + end = max_t(u64, end, node->end); + purged |= vrange->purged; + + vrange_del(vrange); + + /* get the next possible overlap */ + node = range_tree_in_range(mapping->volatile_root, start, end); + } + + new->mapping = mapping; + new->range_node.start = start; + new->range_node.end = end; + new->purged = purged;
I'm wondering whether this 'inheritance' is always desirable.
Say,
mapping_range_volatile(mapping, X, X + 1); ... time goes by and volatile_shrink() has been called for this region.
now, a user does the following (is it considered bad user-behavior?)
mapping_range_volatile(mapping, Y = X - big_value, Z = X + big_value);
This new range will 'inherit' purged=1 from the old one and won't be on the lru_list. Yet, it's much bigger than the old one and so many pages are not really 'volatile'.
-- Dmitry -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |