Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 190760
b: refs/heads/master
c: c61ea31
h: refs/heads/master
v: v3
  • Loading branch information
David Howells authored and Linus Torvalds committed May 11, 2010
1 parent e8a4143 commit d2ac4e6
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 13 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7d6fb7bd1919517937ec390f6ca2d7bcf4f89fb6
refs/heads/master: c61ea31dac0319ec64b33725917bda81fc293a25
1 change: 1 addition & 0 deletions trunk/fs/cachefiles/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ struct cachefiles_object {
loff_t i_size; /* object size */
unsigned long flags;
#define CACHEFILES_OBJECT_ACTIVE 0 /* T if marked active */
#define CACHEFILES_OBJECT_BURIED 1 /* T if preemptively buried */
atomic_t usage; /* object usage count */
uint8_t type; /* object type */
uint8_t new; /* T if object new */
Expand Down
98 changes: 86 additions & 12 deletions trunk/fs/cachefiles/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,59 @@ static noinline void cachefiles_printk_object(struct cachefiles_object *object,
kfree(keybuf);
}

/*
* mark the owner of a dentry, if there is one, to indicate that that dentry
* has been preemptively deleted
* - the caller must hold the i_mutex on the dentry's parent as required to
* call vfs_unlink(), vfs_rmdir() or vfs_rename()
*/
static void cachefiles_mark_object_buried(struct cachefiles_cache *cache,
struct dentry *dentry)
{
struct cachefiles_object *object;
struct rb_node *p;

_enter(",'%*.*s'",
dentry->d_name.len, dentry->d_name.len, dentry->d_name.name);

write_lock(&cache->active_lock);

p = cache->active_nodes.rb_node;
while (p) {
object = rb_entry(p, struct cachefiles_object, active_node);
if (object->dentry > dentry)
p = p->rb_left;
else if (object->dentry < dentry)
p = p->rb_right;
else
goto found_dentry;
}

write_unlock(&cache->active_lock);
_leave(" [no owner]");
return;

/* found the dentry for */
found_dentry:
kdebug("preemptive burial: OBJ%x [%s] %p",
object->fscache.debug_id,
fscache_object_states[object->fscache.state],
dentry);

if (object->fscache.state < FSCACHE_OBJECT_DYING) {
printk(KERN_ERR "\n");
printk(KERN_ERR "CacheFiles: Error:"
" Can't preemptively bury live object\n");
cachefiles_printk_object(object, NULL);
} else if (test_and_set_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) {
printk(KERN_ERR "CacheFiles: Error:"
" Object already preemptively buried\n");
}

write_unlock(&cache->active_lock);
_leave(" [owner marked]");
}

/*
* record the fact that an object is now active
*/
Expand Down Expand Up @@ -219,7 +272,8 @@ static int cachefiles_mark_object_active(struct cachefiles_cache *cache,
*/
static int cachefiles_bury_object(struct cachefiles_cache *cache,
struct dentry *dir,
struct dentry *rep)
struct dentry *rep,
bool preemptive)
{
struct dentry *grave, *trap;
char nbuffer[8 + 8 + 1];
Expand All @@ -229,11 +283,16 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
dir->d_name.len, dir->d_name.len, dir->d_name.name,
rep->d_name.len, rep->d_name.len, rep->d_name.name);

_debug("remove %p from %p", rep, dir);

/* non-directories can just be unlinked */
if (!S_ISDIR(rep->d_inode->i_mode)) {
_debug("unlink stale object");
ret = vfs_unlink(dir->d_inode, rep);

if (preemptive)
cachefiles_mark_object_buried(cache, rep);

mutex_unlock(&dir->d_inode->i_mutex);

if (ret == -EIO)
Expand Down Expand Up @@ -325,6 +384,9 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
if (ret != 0 && ret != -ENOMEM)
cachefiles_io_error(cache, "Rename failed with error %d", ret);

if (preemptive)
cachefiles_mark_object_buried(cache, rep);

unlock_rename(cache->graveyard, dir);
dput(grave);
_leave(" = 0");
Expand All @@ -340,7 +402,7 @@ int cachefiles_delete_object(struct cachefiles_cache *cache,
struct dentry *dir;
int ret;

_enter(",{%p}", object->dentry);
_enter(",OBJ%x{%p}", object->fscache.debug_id, object->dentry);

ASSERT(object->dentry);
ASSERT(object->dentry->d_inode);
Expand All @@ -350,15 +412,25 @@ int cachefiles_delete_object(struct cachefiles_cache *cache,

mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);

/* we need to check that our parent is _still_ our parent - it may have
* been renamed */
if (dir == object->dentry->d_parent) {
ret = cachefiles_bury_object(cache, dir, object->dentry);
} else {
/* it got moved, presumably by cachefilesd culling it, so it's
* no longer in the key path and we can ignore it */
if (test_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) {
/* object allocation for the same key preemptively deleted this
* object's file so that it could create its own file */
_debug("object preemptively buried");
mutex_unlock(&dir->d_inode->i_mutex);
ret = 0;
} else {
/* we need to check that our parent is _still_ our parent - it
* may have been renamed */
if (dir == object->dentry->d_parent) {
ret = cachefiles_bury_object(cache, dir,
object->dentry, false);
} else {
/* it got moved, presumably by cachefilesd culling it,
* so it's no longer in the key path and we can ignore
* it */
mutex_unlock(&dir->d_inode->i_mutex);
ret = 0;
}
}

dput(dir);
Expand All @@ -381,7 +453,9 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
const char *name;
int ret, nlen;

_enter("{%p},,%s,", parent->dentry, key);
_enter("OBJ%x{%p},OBJ%x,%s,",
parent->fscache.debug_id, parent->dentry,
object->fscache.debug_id, key);

cache = container_of(parent->fscache.cache,
struct cachefiles_cache, cache);
Expand Down Expand Up @@ -509,7 +583,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
* mutex) */
object->dentry = NULL;

ret = cachefiles_bury_object(cache, dir, next);
ret = cachefiles_bury_object(cache, dir, next, true);
dput(next);
next = NULL;

Expand Down Expand Up @@ -828,7 +902,7 @@ int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir,
/* actually remove the victim (drops the dir mutex) */
_debug("bury");

ret = cachefiles_bury_object(cache, dir, victim);
ret = cachefiles_bury_object(cache, dir, victim, false);
if (ret < 0)
goto error;

Expand Down

0 comments on commit d2ac4e6

Please sign in to comment.