diff --git a/fs/cachefiles/bind.c b/fs/cachefiles/bind.c index 3a88bef9ed4b4f77a8d1f6e1ad91d9caf9a55f78..8c84bfcde99114b5b73f075376f7d2a3ab166929 100644 --- a/fs/cachefiles/bind.c +++ b/fs/cachefiles/bind.c @@ -206,7 +206,7 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache) fsdef->dentry = cachedir; fsdef->fscache.cookie = NULL; - ret = cachefiles_check_object_type(fsdef); + ret = cachefiles_check_object_type(fsdef, cache); if (ret < 0) goto error_unsupported; diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h index 97c4b4c639b4a43ed594feaeb8b4b5ed712ec45e..96d96926017e7778e05aca3562d9804a90317e2d 100644 --- a/fs/cachefiles/internal.h +++ b/fs/cachefiles/internal.h @@ -368,7 +368,8 @@ static inline void cachefiles_end_secure(struct cachefiles_cache *cache, /* * xattr.c */ -extern int cachefiles_check_object_type(struct cachefiles_object *object); +extern int cachefiles_check_object_type(struct cachefiles_object *object, + struct cachefiles_cache *cache); extern int cachefiles_set_object_xattr(struct cachefiles_object *object, struct cachefiles_xattr *auxdata); extern int cachefiles_update_object_xattr(struct cachefiles_object *object, diff --git a/fs/cachefiles/xattr.c b/fs/cachefiles/xattr.c index 4aadace026d27ddadd99e1ffb2e7b8c7c4ad3078..bac55fc7359e576f162ff5016d1ca48de903d2ef 100644 --- a/fs/cachefiles/xattr.c +++ b/fs/cachefiles/xattr.c @@ -45,7 +45,8 @@ static int cachefiles_check_new_obj_xattr(struct cachefiles_object *object); * check the type label on an object * - done using xattrs */ -int cachefiles_check_object_type(struct cachefiles_object *object) +int cachefiles_check_object_type(struct cachefiles_object *object, + struct cachefiles_cache *cache) { struct dentry *dentry = object->dentry; char type[3], xtype[3]; @@ -62,8 +63,12 @@ int cachefiles_check_object_type(struct cachefiles_object *object) _enter("%p{%s}", object, type); /* attempt to install a type label directly */ - ret = vfs_setxattr(dentry, cachefiles_xattr_cache, type, 2, - XATTR_CREATE); + ret = mnt_want_write(cache->mnt); + if (ret == 0) { + ret = vfs_setxattr(dentry, cachefiles_xattr_cache, type, 2, + XATTR_CREATE); + mnt_drop_write(cache->mnt); + } if (ret == 0) { _debug("SET"); /* we succeeded */ goto error; @@ -123,6 +128,7 @@ int cachefiles_set_object_xattr(struct cachefiles_object *object, struct cachefiles_xattr *auxdata) { struct dentry *dentry = object->dentry; + struct cachefiles_cache *cache; int ret; ASSERT(dentry); @@ -132,15 +138,22 @@ int cachefiles_set_object_xattr(struct cachefiles_object *object, /* attempt to install the cache metadata directly */ _debug("SET #%u", auxdata->len); + cache = container_of(object->fscache.cache, + struct cachefiles_cache, cache); + clear_bit(FSCACHE_COOKIE_AUX_UPDATED, &object->fscache.cookie->flags); - if (data_new_version(object->fscache.cookie)) - ret = cachefiles_set_new_obj_xattr(object); - else if (volume_new_version(object->fscache.cookie)) - ret = cachefiles_set_new_vol_xattr(object); - else - ret = vfs_setxattr(dentry, cachefiles_xattr_cache, - &auxdata->type, auxdata->len, - XATTR_CREATE); + ret = mnt_want_write(cache->mnt); + if (ret == 0) { + if (data_new_version(object->fscache.cookie)) + ret = cachefiles_set_new_obj_xattr(object); + else if (volume_new_version(object->fscache.cookie)) + ret = cachefiles_set_new_vol_xattr(object); + else + ret = vfs_setxattr(dentry, cachefiles_xattr_cache, + &auxdata->type, auxdata->len, + XATTR_CREATE); + mnt_drop_write(cache->mnt); + } if (ret < 0 && ret != -ENOMEM) cachefiles_io_error_obj( object, @@ -157,6 +170,7 @@ int cachefiles_update_object_xattr(struct cachefiles_object *object, struct cachefiles_xattr *auxdata) { struct dentry *dentry = object->dentry; + struct cachefiles_cache *cache; int ret; if (!dentry) @@ -167,10 +181,17 @@ int cachefiles_update_object_xattr(struct cachefiles_object *object, /* attempt to install the cache metadata directly */ _debug("SET #%u", auxdata->len); + cache = container_of(object->fscache.cache, + struct cachefiles_cache, cache); + clear_bit(FSCACHE_COOKIE_AUX_UPDATED, &object->fscache.cookie->flags); - ret = vfs_setxattr(dentry, cachefiles_xattr_cache, - &auxdata->type, auxdata->len, - XATTR_REPLACE); + ret = mnt_want_write(cache->mnt); + if (ret == 0) { + ret = vfs_setxattr(dentry, cachefiles_xattr_cache, + &auxdata->type, auxdata->len, + XATTR_REPLACE); + mnt_drop_write(cache->mnt); + } if (ret < 0 && ret != -ENOMEM) cachefiles_io_error_obj( object, @@ -222,6 +243,7 @@ int cachefiles_check_old_object_xattr(struct cachefiles_object *object, struct cachefiles_xattr *auxdata) { struct cachefiles_xattr *auxbuf; + struct cachefiles_cache *cache; unsigned int len = sizeof(struct cachefiles_xattr) + 512; struct dentry *dentry = object->dentry; int ret; @@ -279,10 +301,17 @@ int cachefiles_check_old_object_xattr(struct cachefiles_object *object, BUG(); } + cache = container_of(object->fscache.cache, + struct cachefiles_cache, cache); + /* update the current label */ - ret = vfs_setxattr(dentry, cachefiles_xattr_cache, - &auxdata->type, auxdata->len, - XATTR_REPLACE); + ret = mnt_want_write(cache->mnt); + if (ret == 0) { + ret = vfs_setxattr(dentry, cachefiles_xattr_cache, + &auxdata->type, auxdata->len, + XATTR_REPLACE); + mnt_drop_write(cache->mnt); + } if (ret < 0) { cachefiles_io_error_obj(object, "Can't update xattr on %lu" @@ -364,7 +393,11 @@ int cachefiles_remove_object_xattr(struct cachefiles_cache *cache, { int ret; - ret = vfs_removexattr(dentry, cachefiles_xattr_cache); + ret = mnt_want_write(cache->mnt); + if (ret == 0) { + ret = vfs_removexattr(dentry, cachefiles_xattr_cache); + mnt_drop_write(cache->mnt); + } if (ret < 0) { if (ret == -ENOENT || ret == -ENODATA) ret = 0;