mirror of https://gitee.com/openkylin/linux.git
Merge branch 'afs-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs
Pull afs/fscache fixes from David Howells: - Fix the default return of fscache_maybe_release_page() when a cache isn't in use - it prevents a filesystem from releasing pages. This can cause a system to OOM. - Fix a potential uninitialised variable in AFS. - Fix AFS unlink's handling of the nlink count. It needs to use the nlink manipulation functions so that inode structs of deleted inodes actually get scheduled for destruction. - Fix error handling in afs_write_end() so that the page gets unlocked and put if we can't fill the unwritten portion. * 'afs-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs: afs: Fix missing error handling in afs_write_end() afs: Fix unlink afs: Potential uninitialized variable in afs_extract_data() fscache: Fix the default for fscache_maybe_release_page()
This commit is contained in:
commit
50d0f78f5c
37
fs/afs/dir.c
37
fs/afs/dir.c
|
@ -895,20 +895,38 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
|
||||||
* However, if we didn't have a callback promise outstanding, or it was
|
* However, if we didn't have a callback promise outstanding, or it was
|
||||||
* outstanding on a different server, then it won't break it either...
|
* outstanding on a different server, then it won't break it either...
|
||||||
*/
|
*/
|
||||||
static int afs_dir_remove_link(struct dentry *dentry, struct key *key)
|
static int afs_dir_remove_link(struct dentry *dentry, struct key *key,
|
||||||
|
unsigned long d_version_before,
|
||||||
|
unsigned long d_version_after)
|
||||||
{
|
{
|
||||||
|
bool dir_valid;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
/* There were no intervening changes on the server if the version
|
||||||
|
* number we got back was incremented by exactly 1.
|
||||||
|
*/
|
||||||
|
dir_valid = (d_version_after == d_version_before + 1);
|
||||||
|
|
||||||
if (d_really_is_positive(dentry)) {
|
if (d_really_is_positive(dentry)) {
|
||||||
struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
|
struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
|
||||||
|
|
||||||
if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
|
if (dir_valid) {
|
||||||
kdebug("AFS_VNODE_DELETED");
|
drop_nlink(&vnode->vfs_inode);
|
||||||
clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
|
if (vnode->vfs_inode.i_nlink == 0) {
|
||||||
|
set_bit(AFS_VNODE_DELETED, &vnode->flags);
|
||||||
ret = afs_validate(vnode, key);
|
clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
|
||||||
if (ret == -ESTALE)
|
}
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
} else {
|
||||||
|
clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
|
||||||
|
|
||||||
|
if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
|
||||||
|
kdebug("AFS_VNODE_DELETED");
|
||||||
|
|
||||||
|
ret = afs_validate(vnode, key);
|
||||||
|
if (ret == -ESTALE)
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
_debug("nlink %d [val %d]", vnode->vfs_inode.i_nlink, ret);
|
_debug("nlink %d [val %d]", vnode->vfs_inode.i_nlink, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -923,6 +941,7 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
|
||||||
struct afs_fs_cursor fc;
|
struct afs_fs_cursor fc;
|
||||||
struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode;
|
struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode;
|
||||||
struct key *key;
|
struct key *key;
|
||||||
|
unsigned long d_version = (unsigned long)dentry->d_fsdata;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
_enter("{%x:%u},{%pd}",
|
_enter("{%x:%u},{%pd}",
|
||||||
|
@ -955,7 +974,9 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
|
||||||
afs_vnode_commit_status(&fc, dvnode, fc.cb_break);
|
afs_vnode_commit_status(&fc, dvnode, fc.cb_break);
|
||||||
ret = afs_end_vnode_operation(&fc);
|
ret = afs_end_vnode_operation(&fc);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
ret = afs_dir_remove_link(dentry, key);
|
ret = afs_dir_remove_link(
|
||||||
|
dentry, key, d_version,
|
||||||
|
(unsigned long)dvnode->status.data_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_key:
|
error_key:
|
||||||
|
|
|
@ -377,6 +377,10 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
|
||||||
}
|
}
|
||||||
|
|
||||||
read_sequnlock_excl(&vnode->cb_lock);
|
read_sequnlock_excl(&vnode->cb_lock);
|
||||||
|
|
||||||
|
if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
|
||||||
|
clear_nlink(&vnode->vfs_inode);
|
||||||
|
|
||||||
if (valid)
|
if (valid)
|
||||||
goto valid;
|
goto valid;
|
||||||
|
|
||||||
|
|
|
@ -885,7 +885,7 @@ int afs_extract_data(struct afs_call *call, void *buf, size_t count,
|
||||||
{
|
{
|
||||||
struct afs_net *net = call->net;
|
struct afs_net *net = call->net;
|
||||||
enum afs_call_state state;
|
enum afs_call_state state;
|
||||||
u32 remote_abort;
|
u32 remote_abort = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
_enter("{%s,%zu},,%zu,%d",
|
_enter("{%s,%zu},,%zu,%d",
|
||||||
|
|
|
@ -198,7 +198,7 @@ int afs_write_end(struct file *file, struct address_space *mapping,
|
||||||
ret = afs_fill_page(vnode, key, pos + copied,
|
ret = afs_fill_page(vnode, key, pos + copied,
|
||||||
len - copied, page);
|
len - copied, page);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
goto out;
|
||||||
}
|
}
|
||||||
SetPageUptodate(page);
|
SetPageUptodate(page);
|
||||||
}
|
}
|
||||||
|
@ -206,10 +206,12 @@ int afs_write_end(struct file *file, struct address_space *mapping,
|
||||||
set_page_dirty(page);
|
set_page_dirty(page);
|
||||||
if (PageDirty(page))
|
if (PageDirty(page))
|
||||||
_debug("dirtied");
|
_debug("dirtied");
|
||||||
|
ret = copied;
|
||||||
|
|
||||||
|
out:
|
||||||
unlock_page(page);
|
unlock_page(page);
|
||||||
put_page(page);
|
put_page(page);
|
||||||
|
return ret;
|
||||||
return copied;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -755,7 +755,7 @@ bool fscache_maybe_release_page(struct fscache_cookie *cookie,
|
||||||
{
|
{
|
||||||
if (fscache_cookie_valid(cookie) && PageFsCache(page))
|
if (fscache_cookie_valid(cookie) && PageFsCache(page))
|
||||||
return __fscache_maybe_release_page(cookie, page, gfp);
|
return __fscache_maybe_release_page(cookie, page, gfp);
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue