mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-09-08 17:18:05 -04:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
327
fs/cachefiles/xattr.c
Normal file
327
fs/cachefiles/xattr.c
Normal file
|
@ -0,0 +1,327 @@
|
|||
/* CacheFiles extended attribute management
|
||||
*
|
||||
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public Licence
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the Licence, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/fsnotify.h>
|
||||
#include <linux/quotaops.h>
|
||||
#include <linux/xattr.h>
|
||||
#include <linux/slab.h>
|
||||
#include "internal.h"
|
||||
|
||||
static const char cachefiles_xattr_cache[] =
|
||||
XATTR_USER_PREFIX "CacheFiles.cache";
|
||||
|
||||
/*
|
||||
* check the type label on an object
|
||||
* - done using xattrs
|
||||
*/
|
||||
int cachefiles_check_object_type(struct cachefiles_object *object)
|
||||
{
|
||||
struct dentry *dentry = object->dentry;
|
||||
char type[3], xtype[3];
|
||||
int ret;
|
||||
|
||||
ASSERT(dentry);
|
||||
ASSERT(dentry->d_inode);
|
||||
|
||||
if (!object->fscache.cookie)
|
||||
strcpy(type, "C3");
|
||||
else
|
||||
snprintf(type, 3, "%02x", object->fscache.cookie->def->type);
|
||||
|
||||
_enter("%p{%s}", object, type);
|
||||
|
||||
/* attempt to install a type label directly */
|
||||
ret = vfs_setxattr(dentry, cachefiles_xattr_cache, type, 2,
|
||||
XATTR_CREATE);
|
||||
if (ret == 0) {
|
||||
_debug("SET"); /* we succeeded */
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ret != -EEXIST) {
|
||||
pr_err("Can't set xattr on %*.*s [%lu] (err %d)\n",
|
||||
dentry->d_name.len, dentry->d_name.len,
|
||||
dentry->d_name.name, dentry->d_inode->i_ino,
|
||||
-ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* read the current type label */
|
||||
ret = vfs_getxattr(dentry, cachefiles_xattr_cache, xtype, 3);
|
||||
if (ret < 0) {
|
||||
if (ret == -ERANGE)
|
||||
goto bad_type_length;
|
||||
|
||||
pr_err("Can't read xattr on %*.*s [%lu] (err %d)\n",
|
||||
dentry->d_name.len, dentry->d_name.len,
|
||||
dentry->d_name.name, dentry->d_inode->i_ino,
|
||||
-ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* check the type is what we're expecting */
|
||||
if (ret != 2)
|
||||
goto bad_type_length;
|
||||
|
||||
if (xtype[0] != type[0] || xtype[1] != type[1])
|
||||
goto bad_type;
|
||||
|
||||
ret = 0;
|
||||
|
||||
error:
|
||||
_leave(" = %d", ret);
|
||||
return ret;
|
||||
|
||||
bad_type_length:
|
||||
pr_err("Cache object %lu type xattr length incorrect\n",
|
||||
dentry->d_inode->i_ino);
|
||||
ret = -EIO;
|
||||
goto error;
|
||||
|
||||
bad_type:
|
||||
xtype[2] = 0;
|
||||
pr_err("Cache object %*.*s [%lu] type %s not %s\n",
|
||||
dentry->d_name.len, dentry->d_name.len,
|
||||
dentry->d_name.name, dentry->d_inode->i_ino,
|
||||
xtype, type);
|
||||
ret = -EIO;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* set the state xattr on a cache file
|
||||
*/
|
||||
int cachefiles_set_object_xattr(struct cachefiles_object *object,
|
||||
struct cachefiles_xattr *auxdata)
|
||||
{
|
||||
struct dentry *dentry = object->dentry;
|
||||
int ret;
|
||||
|
||||
ASSERT(dentry);
|
||||
|
||||
_enter("%p,#%d", object, auxdata->len);
|
||||
|
||||
/* attempt to install the cache metadata directly */
|
||||
_debug("SET #%u", auxdata->len);
|
||||
|
||||
ret = vfs_setxattr(dentry, cachefiles_xattr_cache,
|
||||
&auxdata->type, auxdata->len,
|
||||
XATTR_CREATE);
|
||||
if (ret < 0 && ret != -ENOMEM)
|
||||
cachefiles_io_error_obj(
|
||||
object,
|
||||
"Failed to set xattr with error %d", ret);
|
||||
|
||||
_leave(" = %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* update the state xattr on a cache file
|
||||
*/
|
||||
int cachefiles_update_object_xattr(struct cachefiles_object *object,
|
||||
struct cachefiles_xattr *auxdata)
|
||||
{
|
||||
struct dentry *dentry = object->dentry;
|
||||
int ret;
|
||||
|
||||
ASSERT(dentry);
|
||||
|
||||
_enter("%p,#%d", object, auxdata->len);
|
||||
|
||||
/* attempt to install the cache metadata directly */
|
||||
_debug("SET #%u", auxdata->len);
|
||||
|
||||
ret = vfs_setxattr(dentry, cachefiles_xattr_cache,
|
||||
&auxdata->type, auxdata->len,
|
||||
XATTR_REPLACE);
|
||||
if (ret < 0 && ret != -ENOMEM)
|
||||
cachefiles_io_error_obj(
|
||||
object,
|
||||
"Failed to update xattr with error %d", ret);
|
||||
|
||||
_leave(" = %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* check the consistency between the backing cache and the FS-Cache cookie
|
||||
*/
|
||||
int cachefiles_check_auxdata(struct cachefiles_object *object)
|
||||
{
|
||||
struct cachefiles_xattr *auxbuf;
|
||||
enum fscache_checkaux validity;
|
||||
struct dentry *dentry = object->dentry;
|
||||
ssize_t xlen;
|
||||
int ret;
|
||||
|
||||
ASSERT(dentry);
|
||||
ASSERT(dentry->d_inode);
|
||||
ASSERT(object->fscache.cookie->def->check_aux);
|
||||
|
||||
auxbuf = kmalloc(sizeof(struct cachefiles_xattr) + 512, GFP_KERNEL);
|
||||
if (!auxbuf)
|
||||
return -ENOMEM;
|
||||
|
||||
xlen = vfs_getxattr(dentry, cachefiles_xattr_cache,
|
||||
&auxbuf->type, 512 + 1);
|
||||
ret = -ESTALE;
|
||||
if (xlen < 1 ||
|
||||
auxbuf->type != object->fscache.cookie->def->type)
|
||||
goto error;
|
||||
|
||||
xlen--;
|
||||
validity = fscache_check_aux(&object->fscache, &auxbuf->data, xlen);
|
||||
if (validity != FSCACHE_CHECKAUX_OKAY)
|
||||
goto error;
|
||||
|
||||
ret = 0;
|
||||
error:
|
||||
kfree(auxbuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* check the state xattr on a cache file
|
||||
* - return -ESTALE if the object should be deleted
|
||||
*/
|
||||
int cachefiles_check_object_xattr(struct cachefiles_object *object,
|
||||
struct cachefiles_xattr *auxdata)
|
||||
{
|
||||
struct cachefiles_xattr *auxbuf;
|
||||
struct dentry *dentry = object->dentry;
|
||||
int ret;
|
||||
|
||||
_enter("%p,#%d", object, auxdata->len);
|
||||
|
||||
ASSERT(dentry);
|
||||
ASSERT(dentry->d_inode);
|
||||
|
||||
auxbuf = kmalloc(sizeof(struct cachefiles_xattr) + 512, cachefiles_gfp);
|
||||
if (!auxbuf) {
|
||||
_leave(" = -ENOMEM");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* read the current type label */
|
||||
ret = vfs_getxattr(dentry, cachefiles_xattr_cache,
|
||||
&auxbuf->type, 512 + 1);
|
||||
if (ret < 0) {
|
||||
if (ret == -ENODATA)
|
||||
goto stale; /* no attribute - power went off
|
||||
* mid-cull? */
|
||||
|
||||
if (ret == -ERANGE)
|
||||
goto bad_type_length;
|
||||
|
||||
cachefiles_io_error_obj(object,
|
||||
"Can't read xattr on %lu (err %d)",
|
||||
dentry->d_inode->i_ino, -ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* check the on-disk object */
|
||||
if (ret < 1)
|
||||
goto bad_type_length;
|
||||
|
||||
if (auxbuf->type != auxdata->type)
|
||||
goto stale;
|
||||
|
||||
auxbuf->len = ret;
|
||||
|
||||
/* consult the netfs */
|
||||
if (object->fscache.cookie->def->check_aux) {
|
||||
enum fscache_checkaux result;
|
||||
unsigned int dlen;
|
||||
|
||||
dlen = auxbuf->len - 1;
|
||||
|
||||
_debug("checkaux %s #%u",
|
||||
object->fscache.cookie->def->name, dlen);
|
||||
|
||||
result = fscache_check_aux(&object->fscache,
|
||||
&auxbuf->data, dlen);
|
||||
|
||||
switch (result) {
|
||||
/* entry okay as is */
|
||||
case FSCACHE_CHECKAUX_OKAY:
|
||||
goto okay;
|
||||
|
||||
/* entry requires update */
|
||||
case FSCACHE_CHECKAUX_NEEDS_UPDATE:
|
||||
break;
|
||||
|
||||
/* entry requires deletion */
|
||||
case FSCACHE_CHECKAUX_OBSOLETE:
|
||||
goto stale;
|
||||
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* update the current label */
|
||||
ret = vfs_setxattr(dentry, cachefiles_xattr_cache,
|
||||
&auxdata->type, auxdata->len,
|
||||
XATTR_REPLACE);
|
||||
if (ret < 0) {
|
||||
cachefiles_io_error_obj(object,
|
||||
"Can't update xattr on %lu"
|
||||
" (error %d)",
|
||||
dentry->d_inode->i_ino, -ret);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
okay:
|
||||
ret = 0;
|
||||
|
||||
error:
|
||||
kfree(auxbuf);
|
||||
_leave(" = %d", ret);
|
||||
return ret;
|
||||
|
||||
bad_type_length:
|
||||
pr_err("Cache object %lu xattr length incorrect\n",
|
||||
dentry->d_inode->i_ino);
|
||||
ret = -EIO;
|
||||
goto error;
|
||||
|
||||
stale:
|
||||
ret = -ESTALE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* remove the object's xattr to mark it stale
|
||||
*/
|
||||
int cachefiles_remove_object_xattr(struct cachefiles_cache *cache,
|
||||
struct dentry *dentry)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = vfs_removexattr(dentry, cachefiles_xattr_cache);
|
||||
if (ret < 0) {
|
||||
if (ret == -ENOENT || ret == -ENODATA)
|
||||
ret = 0;
|
||||
else if (ret != -ENOMEM)
|
||||
cachefiles_io_error(cache,
|
||||
"Can't remove xattr from %lu"
|
||||
" (error %d)",
|
||||
dentry->d_inode->i_ino, -ret);
|
||||
}
|
||||
|
||||
_leave(" = %d", ret);
|
||||
return ret;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue