|
@@ -120,6 +120,7 @@ static void cachefiles_mark_object_buried(struct cachefiles_cache *cache,
|
|
}
|
|
}
|
|
|
|
|
|
write_unlock(&cache->active_lock);
|
|
write_unlock(&cache->active_lock);
|
|
|
|
+ trace_cachefiles_mark_buried(NULL, dentry, why);
|
|
_leave(" [no owner]");
|
|
_leave(" [no owner]");
|
|
return;
|
|
return;
|
|
|
|
|
|
@@ -130,6 +131,8 @@ found_dentry:
|
|
object->fscache.state->name,
|
|
object->fscache.state->name,
|
|
dentry);
|
|
dentry);
|
|
|
|
|
|
|
|
+ trace_cachefiles_mark_buried(object, dentry, why);
|
|
|
|
+
|
|
if (fscache_object_is_live(&object->fscache)) {
|
|
if (fscache_object_is_live(&object->fscache)) {
|
|
pr_err("\n");
|
|
pr_err("\n");
|
|
pr_err("Error: Can't preemptively bury live object\n");
|
|
pr_err("Error: Can't preemptively bury live object\n");
|
|
@@ -158,13 +161,15 @@ static int cachefiles_mark_object_active(struct cachefiles_cache *cache,
|
|
try_again:
|
|
try_again:
|
|
write_lock(&cache->active_lock);
|
|
write_lock(&cache->active_lock);
|
|
|
|
|
|
|
|
+ dentry = object->dentry;
|
|
|
|
+ trace_cachefiles_mark_active(object, dentry);
|
|
|
|
+
|
|
if (test_and_set_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags)) {
|
|
if (test_and_set_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags)) {
|
|
pr_err("Error: Object already active\n");
|
|
pr_err("Error: Object already active\n");
|
|
cachefiles_printk_object(object, NULL);
|
|
cachefiles_printk_object(object, NULL);
|
|
BUG();
|
|
BUG();
|
|
}
|
|
}
|
|
|
|
|
|
- dentry = object->dentry;
|
|
|
|
_p = &cache->active_nodes.rb_node;
|
|
_p = &cache->active_nodes.rb_node;
|
|
while (*_p) {
|
|
while (*_p) {
|
|
_parent = *_p;
|
|
_parent = *_p;
|
|
@@ -191,6 +196,8 @@ try_again:
|
|
/* an old object from a previous incarnation is hogging the slot - we
|
|
/* an old object from a previous incarnation is hogging the slot - we
|
|
* need to wait for it to be destroyed */
|
|
* need to wait for it to be destroyed */
|
|
wait_for_old_object:
|
|
wait_for_old_object:
|
|
|
|
+ trace_cachefiles_wait_active(object, dentry, xobject);
|
|
|
|
+
|
|
if (fscache_object_is_live(&xobject->fscache)) {
|
|
if (fscache_object_is_live(&xobject->fscache)) {
|
|
pr_err("\n");
|
|
pr_err("\n");
|
|
pr_err("Error: Unexpected object collision\n");
|
|
pr_err("Error: Unexpected object collision\n");
|
|
@@ -248,12 +255,12 @@ wait_for_old_object:
|
|
|
|
|
|
ASSERT(!test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags));
|
|
ASSERT(!test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags));
|
|
|
|
|
|
- cache->cache.ops->put_object(&xobject->fscache);
|
|
|
|
|
|
+ cache->cache.ops->put_object(&xobject->fscache, cachefiles_obj_put_wait_retry);
|
|
goto try_again;
|
|
goto try_again;
|
|
|
|
|
|
requeue:
|
|
requeue:
|
|
clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags);
|
|
clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags);
|
|
- cache->cache.ops->put_object(&xobject->fscache);
|
|
|
|
|
|
+ cache->cache.ops->put_object(&xobject->fscache, cachefiles_obj_put_wait_timeo);
|
|
_leave(" = -ETIMEDOUT");
|
|
_leave(" = -ETIMEDOUT");
|
|
return -ETIMEDOUT;
|
|
return -ETIMEDOUT;
|
|
}
|
|
}
|
|
@@ -265,6 +272,11 @@ void cachefiles_mark_object_inactive(struct cachefiles_cache *cache,
|
|
struct cachefiles_object *object,
|
|
struct cachefiles_object *object,
|
|
blkcnt_t i_blocks)
|
|
blkcnt_t i_blocks)
|
|
{
|
|
{
|
|
|
|
+ struct dentry *dentry = object->dentry;
|
|
|
|
+ struct inode *inode = d_backing_inode(dentry);
|
|
|
|
+
|
|
|
|
+ trace_cachefiles_mark_inactive(object, dentry, inode);
|
|
|
|
+
|
|
write_lock(&cache->active_lock);
|
|
write_lock(&cache->active_lock);
|
|
rb_erase(&object->active_node, &cache->active_nodes);
|
|
rb_erase(&object->active_node, &cache->active_nodes);
|
|
clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags);
|
|
clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags);
|
|
@@ -288,6 +300,7 @@ void cachefiles_mark_object_inactive(struct cachefiles_cache *cache,
|
|
* - unlocks the directory mutex
|
|
* - unlocks the directory mutex
|
|
*/
|
|
*/
|
|
static int cachefiles_bury_object(struct cachefiles_cache *cache,
|
|
static int cachefiles_bury_object(struct cachefiles_cache *cache,
|
|
|
|
+ struct cachefiles_object *object,
|
|
struct dentry *dir,
|
|
struct dentry *dir,
|
|
struct dentry *rep,
|
|
struct dentry *rep,
|
|
bool preemptive,
|
|
bool preemptive,
|
|
@@ -312,6 +325,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
cachefiles_io_error(cache, "Unlink security error");
|
|
cachefiles_io_error(cache, "Unlink security error");
|
|
} else {
|
|
} else {
|
|
|
|
+ trace_cachefiles_unlink(object, rep, why);
|
|
ret = vfs_unlink(d_inode(dir), rep, NULL);
|
|
ret = vfs_unlink(d_inode(dir), rep, NULL);
|
|
|
|
|
|
if (preemptive)
|
|
if (preemptive)
|
|
@@ -413,6 +427,7 @@ try_again:
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
cachefiles_io_error(cache, "Rename security error %d", ret);
|
|
cachefiles_io_error(cache, "Rename security error %d", ret);
|
|
} else {
|
|
} else {
|
|
|
|
+ trace_cachefiles_rename(object, rep, grave, why);
|
|
ret = vfs_rename(d_inode(dir), rep,
|
|
ret = vfs_rename(d_inode(dir), rep,
|
|
d_inode(cache->graveyard), grave, NULL, 0);
|
|
d_inode(cache->graveyard), grave, NULL, 0);
|
|
if (ret != 0 && ret != -ENOMEM)
|
|
if (ret != 0 && ret != -ENOMEM)
|
|
@@ -458,7 +473,7 @@ int cachefiles_delete_object(struct cachefiles_cache *cache,
|
|
/* we need to check that our parent is _still_ our parent - it
|
|
/* we need to check that our parent is _still_ our parent - it
|
|
* may have been renamed */
|
|
* may have been renamed */
|
|
if (dir == object->dentry->d_parent) {
|
|
if (dir == object->dentry->d_parent) {
|
|
- ret = cachefiles_bury_object(cache, dir,
|
|
|
|
|
|
+ ret = cachefiles_bury_object(cache, object, dir,
|
|
object->dentry, false,
|
|
object->dentry, false,
|
|
FSCACHE_OBJECT_WAS_RETIRED);
|
|
FSCACHE_OBJECT_WAS_RETIRED);
|
|
} else {
|
|
} else {
|
|
@@ -486,6 +501,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
|
|
{
|
|
{
|
|
struct cachefiles_cache *cache;
|
|
struct cachefiles_cache *cache;
|
|
struct dentry *dir, *next = NULL;
|
|
struct dentry *dir, *next = NULL;
|
|
|
|
+ struct inode *inode;
|
|
struct path path;
|
|
struct path path;
|
|
unsigned long start;
|
|
unsigned long start;
|
|
const char *name;
|
|
const char *name;
|
|
@@ -529,13 +545,17 @@ lookup_again:
|
|
start = jiffies;
|
|
start = jiffies;
|
|
next = lookup_one_len(name, dir, nlen);
|
|
next = lookup_one_len(name, dir, nlen);
|
|
cachefiles_hist(cachefiles_lookup_histogram, start);
|
|
cachefiles_hist(cachefiles_lookup_histogram, start);
|
|
- if (IS_ERR(next))
|
|
|
|
|
|
+ if (IS_ERR(next)) {
|
|
|
|
+ trace_cachefiles_lookup(object, next, NULL);
|
|
goto lookup_error;
|
|
goto lookup_error;
|
|
|
|
+ }
|
|
|
|
|
|
- _debug("next -> %p %s", next, d_backing_inode(next) ? "positive" : "negative");
|
|
|
|
|
|
+ inode = d_backing_inode(next);
|
|
|
|
+ trace_cachefiles_lookup(object, next, inode);
|
|
|
|
+ _debug("next -> %p %s", next, inode ? "positive" : "negative");
|
|
|
|
|
|
if (!key)
|
|
if (!key)
|
|
- object->new = !d_backing_inode(next);
|
|
|
|
|
|
+ object->new = !inode;
|
|
|
|
|
|
/* if this element of the path doesn't exist, then the lookup phase
|
|
/* if this element of the path doesn't exist, then the lookup phase
|
|
* failed, and we can release any readers in the certain knowledge that
|
|
* failed, and we can release any readers in the certain knowledge that
|
|
@@ -558,6 +578,8 @@ lookup_again:
|
|
start = jiffies;
|
|
start = jiffies;
|
|
ret = vfs_mkdir(d_inode(dir), next, 0);
|
|
ret = vfs_mkdir(d_inode(dir), next, 0);
|
|
cachefiles_hist(cachefiles_mkdir_histogram, start);
|
|
cachefiles_hist(cachefiles_mkdir_histogram, start);
|
|
|
|
+ if (!key)
|
|
|
|
+ trace_cachefiles_mkdir(object, next, ret);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
goto create_error;
|
|
goto create_error;
|
|
|
|
|
|
@@ -587,6 +609,7 @@ lookup_again:
|
|
start = jiffies;
|
|
start = jiffies;
|
|
ret = vfs_create(d_inode(dir), next, S_IFREG, true);
|
|
ret = vfs_create(d_inode(dir), next, S_IFREG, true);
|
|
cachefiles_hist(cachefiles_create_histogram, start);
|
|
cachefiles_hist(cachefiles_create_histogram, start);
|
|
|
|
+ trace_cachefiles_create(object, next, ret);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
goto create_error;
|
|
goto create_error;
|
|
|
|
|
|
@@ -629,7 +652,8 @@ lookup_again:
|
|
* mutex) */
|
|
* mutex) */
|
|
object->dentry = NULL;
|
|
object->dentry = NULL;
|
|
|
|
|
|
- ret = cachefiles_bury_object(cache, dir, next, true,
|
|
|
|
|
|
+ ret = cachefiles_bury_object(cache, object, dir, next,
|
|
|
|
+ true,
|
|
FSCACHE_OBJECT_IS_STALE);
|
|
FSCACHE_OBJECT_IS_STALE);
|
|
dput(next);
|
|
dput(next);
|
|
next = NULL;
|
|
next = NULL;
|
|
@@ -955,7 +979,7 @@ int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir,
|
|
/* actually remove the victim (drops the dir mutex) */
|
|
/* actually remove the victim (drops the dir mutex) */
|
|
_debug("bury");
|
|
_debug("bury");
|
|
|
|
|
|
- ret = cachefiles_bury_object(cache, dir, victim, false,
|
|
|
|
|
|
+ ret = cachefiles_bury_object(cache, NULL, dir, victim, false,
|
|
FSCACHE_OBJECT_WAS_CULLED);
|
|
FSCACHE_OBJECT_WAS_CULLED);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
goto error;
|
|
goto error;
|