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
402
fs/afs/cache.c
Normal file
402
fs/afs/cache.c
Normal file
|
@ -0,0 +1,402 @@
|
|||
/* AFS caching stuff
|
||||
*
|
||||
* Copyright (C) 2008 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 License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include "internal.h"
|
||||
|
||||
static uint16_t afs_cell_cache_get_key(const void *cookie_netfs_data,
|
||||
void *buffer, uint16_t buflen);
|
||||
static uint16_t afs_cell_cache_get_aux(const void *cookie_netfs_data,
|
||||
void *buffer, uint16_t buflen);
|
||||
static enum fscache_checkaux afs_cell_cache_check_aux(void *cookie_netfs_data,
|
||||
const void *buffer,
|
||||
uint16_t buflen);
|
||||
|
||||
static uint16_t afs_vlocation_cache_get_key(const void *cookie_netfs_data,
|
||||
void *buffer, uint16_t buflen);
|
||||
static uint16_t afs_vlocation_cache_get_aux(const void *cookie_netfs_data,
|
||||
void *buffer, uint16_t buflen);
|
||||
static enum fscache_checkaux afs_vlocation_cache_check_aux(
|
||||
void *cookie_netfs_data, const void *buffer, uint16_t buflen);
|
||||
|
||||
static uint16_t afs_volume_cache_get_key(const void *cookie_netfs_data,
|
||||
void *buffer, uint16_t buflen);
|
||||
|
||||
static uint16_t afs_vnode_cache_get_key(const void *cookie_netfs_data,
|
||||
void *buffer, uint16_t buflen);
|
||||
static void afs_vnode_cache_get_attr(const void *cookie_netfs_data,
|
||||
uint64_t *size);
|
||||
static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data,
|
||||
void *buffer, uint16_t buflen);
|
||||
static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data,
|
||||
const void *buffer,
|
||||
uint16_t buflen);
|
||||
static void afs_vnode_cache_now_uncached(void *cookie_netfs_data);
|
||||
|
||||
struct fscache_netfs afs_cache_netfs = {
|
||||
.name = "afs",
|
||||
.version = 0,
|
||||
};
|
||||
|
||||
struct fscache_cookie_def afs_cell_cache_index_def = {
|
||||
.name = "AFS.cell",
|
||||
.type = FSCACHE_COOKIE_TYPE_INDEX,
|
||||
.get_key = afs_cell_cache_get_key,
|
||||
.get_aux = afs_cell_cache_get_aux,
|
||||
.check_aux = afs_cell_cache_check_aux,
|
||||
};
|
||||
|
||||
struct fscache_cookie_def afs_vlocation_cache_index_def = {
|
||||
.name = "AFS.vldb",
|
||||
.type = FSCACHE_COOKIE_TYPE_INDEX,
|
||||
.get_key = afs_vlocation_cache_get_key,
|
||||
.get_aux = afs_vlocation_cache_get_aux,
|
||||
.check_aux = afs_vlocation_cache_check_aux,
|
||||
};
|
||||
|
||||
struct fscache_cookie_def afs_volume_cache_index_def = {
|
||||
.name = "AFS.volume",
|
||||
.type = FSCACHE_COOKIE_TYPE_INDEX,
|
||||
.get_key = afs_volume_cache_get_key,
|
||||
};
|
||||
|
||||
struct fscache_cookie_def afs_vnode_cache_index_def = {
|
||||
.name = "AFS.vnode",
|
||||
.type = FSCACHE_COOKIE_TYPE_DATAFILE,
|
||||
.get_key = afs_vnode_cache_get_key,
|
||||
.get_attr = afs_vnode_cache_get_attr,
|
||||
.get_aux = afs_vnode_cache_get_aux,
|
||||
.check_aux = afs_vnode_cache_check_aux,
|
||||
.now_uncached = afs_vnode_cache_now_uncached,
|
||||
};
|
||||
|
||||
/*
|
||||
* set the key for the index entry
|
||||
*/
|
||||
static uint16_t afs_cell_cache_get_key(const void *cookie_netfs_data,
|
||||
void *buffer, uint16_t bufmax)
|
||||
{
|
||||
const struct afs_cell *cell = cookie_netfs_data;
|
||||
uint16_t klen;
|
||||
|
||||
_enter("%p,%p,%u", cell, buffer, bufmax);
|
||||
|
||||
klen = strlen(cell->name);
|
||||
if (klen > bufmax)
|
||||
return 0;
|
||||
|
||||
memcpy(buffer, cell->name, klen);
|
||||
return klen;
|
||||
}
|
||||
|
||||
/*
|
||||
* provide new auxiliary cache data
|
||||
*/
|
||||
static uint16_t afs_cell_cache_get_aux(const void *cookie_netfs_data,
|
||||
void *buffer, uint16_t bufmax)
|
||||
{
|
||||
const struct afs_cell *cell = cookie_netfs_data;
|
||||
uint16_t dlen;
|
||||
|
||||
_enter("%p,%p,%u", cell, buffer, bufmax);
|
||||
|
||||
dlen = cell->vl_naddrs * sizeof(cell->vl_addrs[0]);
|
||||
dlen = min(dlen, bufmax);
|
||||
dlen &= ~(sizeof(cell->vl_addrs[0]) - 1);
|
||||
|
||||
memcpy(buffer, cell->vl_addrs, dlen);
|
||||
return dlen;
|
||||
}
|
||||
|
||||
/*
|
||||
* check that the auxiliary data indicates that the entry is still valid
|
||||
*/
|
||||
static enum fscache_checkaux afs_cell_cache_check_aux(void *cookie_netfs_data,
|
||||
const void *buffer,
|
||||
uint16_t buflen)
|
||||
{
|
||||
_leave(" = OKAY");
|
||||
return FSCACHE_CHECKAUX_OKAY;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* set the key for the index entry
|
||||
*/
|
||||
static uint16_t afs_vlocation_cache_get_key(const void *cookie_netfs_data,
|
||||
void *buffer, uint16_t bufmax)
|
||||
{
|
||||
const struct afs_vlocation *vlocation = cookie_netfs_data;
|
||||
uint16_t klen;
|
||||
|
||||
_enter("{%s},%p,%u", vlocation->vldb.name, buffer, bufmax);
|
||||
|
||||
klen = strnlen(vlocation->vldb.name, sizeof(vlocation->vldb.name));
|
||||
if (klen > bufmax)
|
||||
return 0;
|
||||
|
||||
memcpy(buffer, vlocation->vldb.name, klen);
|
||||
|
||||
_leave(" = %u", klen);
|
||||
return klen;
|
||||
}
|
||||
|
||||
/*
|
||||
* provide new auxiliary cache data
|
||||
*/
|
||||
static uint16_t afs_vlocation_cache_get_aux(const void *cookie_netfs_data,
|
||||
void *buffer, uint16_t bufmax)
|
||||
{
|
||||
const struct afs_vlocation *vlocation = cookie_netfs_data;
|
||||
uint16_t dlen;
|
||||
|
||||
_enter("{%s},%p,%u", vlocation->vldb.name, buffer, bufmax);
|
||||
|
||||
dlen = sizeof(struct afs_cache_vlocation);
|
||||
dlen -= offsetof(struct afs_cache_vlocation, nservers);
|
||||
if (dlen > bufmax)
|
||||
return 0;
|
||||
|
||||
memcpy(buffer, (uint8_t *)&vlocation->vldb.nservers, dlen);
|
||||
|
||||
_leave(" = %u", dlen);
|
||||
return dlen;
|
||||
}
|
||||
|
||||
/*
|
||||
* check that the auxiliary data indicates that the entry is still valid
|
||||
*/
|
||||
static
|
||||
enum fscache_checkaux afs_vlocation_cache_check_aux(void *cookie_netfs_data,
|
||||
const void *buffer,
|
||||
uint16_t buflen)
|
||||
{
|
||||
const struct afs_cache_vlocation *cvldb;
|
||||
struct afs_vlocation *vlocation = cookie_netfs_data;
|
||||
uint16_t dlen;
|
||||
|
||||
_enter("{%s},%p,%u", vlocation->vldb.name, buffer, buflen);
|
||||
|
||||
/* check the size of the data is what we're expecting */
|
||||
dlen = sizeof(struct afs_cache_vlocation);
|
||||
dlen -= offsetof(struct afs_cache_vlocation, nservers);
|
||||
if (dlen != buflen)
|
||||
return FSCACHE_CHECKAUX_OBSOLETE;
|
||||
|
||||
cvldb = container_of(buffer, struct afs_cache_vlocation, nservers);
|
||||
|
||||
/* if what's on disk is more valid than what's in memory, then use the
|
||||
* VL record from the cache */
|
||||
if (!vlocation->valid || vlocation->vldb.rtime == cvldb->rtime) {
|
||||
memcpy((uint8_t *)&vlocation->vldb.nservers, buffer, dlen);
|
||||
vlocation->valid = 1;
|
||||
_leave(" = SUCCESS [c->m]");
|
||||
return FSCACHE_CHECKAUX_OKAY;
|
||||
}
|
||||
|
||||
/* need to update the cache if the cached info differs */
|
||||
if (memcmp(&vlocation->vldb, buffer, dlen) != 0) {
|
||||
/* delete if the volume IDs for this name differ */
|
||||
if (memcmp(&vlocation->vldb.vid, &cvldb->vid,
|
||||
sizeof(cvldb->vid)) != 0
|
||||
) {
|
||||
_leave(" = OBSOLETE");
|
||||
return FSCACHE_CHECKAUX_OBSOLETE;
|
||||
}
|
||||
|
||||
_leave(" = UPDATE");
|
||||
return FSCACHE_CHECKAUX_NEEDS_UPDATE;
|
||||
}
|
||||
|
||||
_leave(" = OKAY");
|
||||
return FSCACHE_CHECKAUX_OKAY;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* set the key for the volume index entry
|
||||
*/
|
||||
static uint16_t afs_volume_cache_get_key(const void *cookie_netfs_data,
|
||||
void *buffer, uint16_t bufmax)
|
||||
{
|
||||
const struct afs_volume *volume = cookie_netfs_data;
|
||||
uint16_t klen;
|
||||
|
||||
_enter("{%u},%p,%u", volume->type, buffer, bufmax);
|
||||
|
||||
klen = sizeof(volume->type);
|
||||
if (klen > bufmax)
|
||||
return 0;
|
||||
|
||||
memcpy(buffer, &volume->type, sizeof(volume->type));
|
||||
|
||||
_leave(" = %u", klen);
|
||||
return klen;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* set the key for the index entry
|
||||
*/
|
||||
static uint16_t afs_vnode_cache_get_key(const void *cookie_netfs_data,
|
||||
void *buffer, uint16_t bufmax)
|
||||
{
|
||||
const struct afs_vnode *vnode = cookie_netfs_data;
|
||||
uint16_t klen;
|
||||
|
||||
_enter("{%x,%x,%llx},%p,%u",
|
||||
vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
|
||||
buffer, bufmax);
|
||||
|
||||
klen = sizeof(vnode->fid.vnode);
|
||||
if (klen > bufmax)
|
||||
return 0;
|
||||
|
||||
memcpy(buffer, &vnode->fid.vnode, sizeof(vnode->fid.vnode));
|
||||
|
||||
_leave(" = %u", klen);
|
||||
return klen;
|
||||
}
|
||||
|
||||
/*
|
||||
* provide updated file attributes
|
||||
*/
|
||||
static void afs_vnode_cache_get_attr(const void *cookie_netfs_data,
|
||||
uint64_t *size)
|
||||
{
|
||||
const struct afs_vnode *vnode = cookie_netfs_data;
|
||||
|
||||
_enter("{%x,%x,%llx},",
|
||||
vnode->fid.vnode, vnode->fid.unique,
|
||||
vnode->status.data_version);
|
||||
|
||||
*size = vnode->status.size;
|
||||
}
|
||||
|
||||
/*
|
||||
* provide new auxiliary cache data
|
||||
*/
|
||||
static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data,
|
||||
void *buffer, uint16_t bufmax)
|
||||
{
|
||||
const struct afs_vnode *vnode = cookie_netfs_data;
|
||||
uint16_t dlen;
|
||||
|
||||
_enter("{%x,%x,%Lx},%p,%u",
|
||||
vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
|
||||
buffer, bufmax);
|
||||
|
||||
dlen = sizeof(vnode->fid.unique) + sizeof(vnode->status.data_version);
|
||||
if (dlen > bufmax)
|
||||
return 0;
|
||||
|
||||
memcpy(buffer, &vnode->fid.unique, sizeof(vnode->fid.unique));
|
||||
buffer += sizeof(vnode->fid.unique);
|
||||
memcpy(buffer, &vnode->status.data_version,
|
||||
sizeof(vnode->status.data_version));
|
||||
|
||||
_leave(" = %u", dlen);
|
||||
return dlen;
|
||||
}
|
||||
|
||||
/*
|
||||
* check that the auxiliary data indicates that the entry is still valid
|
||||
*/
|
||||
static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data,
|
||||
const void *buffer,
|
||||
uint16_t buflen)
|
||||
{
|
||||
struct afs_vnode *vnode = cookie_netfs_data;
|
||||
uint16_t dlen;
|
||||
|
||||
_enter("{%x,%x,%llx},%p,%u",
|
||||
vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
|
||||
buffer, buflen);
|
||||
|
||||
/* check the size of the data is what we're expecting */
|
||||
dlen = sizeof(vnode->fid.unique) + sizeof(vnode->status.data_version);
|
||||
if (dlen != buflen) {
|
||||
_leave(" = OBSOLETE [len %hx != %hx]", dlen, buflen);
|
||||
return FSCACHE_CHECKAUX_OBSOLETE;
|
||||
}
|
||||
|
||||
if (memcmp(buffer,
|
||||
&vnode->fid.unique,
|
||||
sizeof(vnode->fid.unique)
|
||||
) != 0) {
|
||||
unsigned unique;
|
||||
|
||||
memcpy(&unique, buffer, sizeof(unique));
|
||||
|
||||
_leave(" = OBSOLETE [uniq %x != %x]",
|
||||
unique, vnode->fid.unique);
|
||||
return FSCACHE_CHECKAUX_OBSOLETE;
|
||||
}
|
||||
|
||||
if (memcmp(buffer + sizeof(vnode->fid.unique),
|
||||
&vnode->status.data_version,
|
||||
sizeof(vnode->status.data_version)
|
||||
) != 0) {
|
||||
afs_dataversion_t version;
|
||||
|
||||
memcpy(&version, buffer + sizeof(vnode->fid.unique),
|
||||
sizeof(version));
|
||||
|
||||
_leave(" = OBSOLETE [vers %llx != %llx]",
|
||||
version, vnode->status.data_version);
|
||||
return FSCACHE_CHECKAUX_OBSOLETE;
|
||||
}
|
||||
|
||||
_leave(" = SUCCESS");
|
||||
return FSCACHE_CHECKAUX_OKAY;
|
||||
}
|
||||
|
||||
/*
|
||||
* indication the cookie is no longer uncached
|
||||
* - this function is called when the backing store currently caching a cookie
|
||||
* is removed
|
||||
* - the netfs should use this to clean up any markers indicating cached pages
|
||||
* - this is mandatory for any object that may have data
|
||||
*/
|
||||
static void afs_vnode_cache_now_uncached(void *cookie_netfs_data)
|
||||
{
|
||||
struct afs_vnode *vnode = cookie_netfs_data;
|
||||
struct pagevec pvec;
|
||||
pgoff_t first;
|
||||
int loop, nr_pages;
|
||||
|
||||
_enter("{%x,%x,%Lx}",
|
||||
vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version);
|
||||
|
||||
pagevec_init(&pvec, 0);
|
||||
first = 0;
|
||||
|
||||
for (;;) {
|
||||
/* grab a bunch of pages to clean */
|
||||
nr_pages = pagevec_lookup(&pvec, vnode->vfs_inode.i_mapping,
|
||||
first,
|
||||
PAGEVEC_SIZE - pagevec_count(&pvec));
|
||||
if (!nr_pages)
|
||||
break;
|
||||
|
||||
for (loop = 0; loop < nr_pages; loop++)
|
||||
ClearPageFsCache(pvec.pages[loop]);
|
||||
|
||||
first = pvec.pages[nr_pages - 1]->index + 1;
|
||||
|
||||
pvec.nr = nr_pages;
|
||||
pagevec_release(&pvec);
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
_leave("");
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue