AFS fixes
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEqG5UsNXhtOCrfGQP+7dXa6fLC2sFAl6Ucx4ACgkQ+7dXa6fL C2txgBAAl657FUIh1GtLgR5UuXSW2UOLQp+quArI8jXaDDAZBf6p4WIqztasy8F3 jRKsAIMNdyjxu1i6Qam8SdoTfph64gTLb+l5qgyE7frfpCqK0mugbXOAAxUlnFdJ j6kjyoXqVcEBSsEUMHJsF84Ag2uv3EWRWyGjOpKhuA52iT+3sWIVR3uKmPIGwFoH wzDnhXiEvzVoEOsZF6jbXvJhvHLoWlDEK8nVqZH+7F/L8RYOH2HXW9NC/r92Z317 Y+uzNgW3Ayw3NEdwpdv8piP1t9beJhkeguPKQGJr8yqNB3MhLy8ioKHLibo/U3hp q5165vVFf5M/2T5KDAepqcJHVxBRb2Aco7ELKWDgwuJMBGbaJncz9ZXMwHkhOZu3 aagedb+n7+yxheMZfch3sAWiIISruUJTGEG6NYlNqXz2toPiR6PbJ9jR/h15xlTG 6l6J1C4xAVRJg+qXgekzlIbncMqno7I8ij4kLsKYihc4kHAc15YR0l+PL3ocgaJA 4sadrqx9Hr+pxmx+qlrBtXEoXeyXFvBXLN6g/az67ydaT5tt7tvHUhnsXgBUPBRD XramKJaZcuS1BtxDFuB1MweBBPRDVOVBHjucIKE7s9nT4qsjCP7vWvkzmD1o7BVt cCzX7rXfgwionQ8YstE+jJ+m1uzQdR/gx6oDcxH8iIAvMvUV0f8= =o13s -----END PGP SIGNATURE----- Merge tag 'afs-fixes-20200413' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs Pull AFS fixes from David Howells: - Fix the decoding of fetched file status records so that the xdr pointer is advanced under all circumstances. - Fix the decoding of a fetched file status record that indicates an inline abort (ie. an error) so that it sets the flag saying the decoder stored the abort code. - Fix the decoding of the result of the rename operation so that it doesn't skip the decoding of the second fetched file status (ie. that of the dest dir) in the case that the source and dest dirs were the same as this causes the xdr pointer not to be advanced, leading to incorrect decoding of subsequent parts of the reply. - Fix the dump of a bad YFSFetchStatus record to dump the full length. - Fix a race between local editing of directory contents and accessing the dir for reading or d_revalidate by using the same lock in both. - Fix afs_d_revalidate() to not accidentally reverse the version on a dentry when it's meant to be bringing it forward. * tag 'afs-fixes-20200413' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs: afs: Fix afs_d_validate() to set the right directory version afs: Fix race between post-modification dir edit and readdir/d_revalidate afs: Fix length of dump of bad YFSFetchStatus record afs: Fix rename operation status delivery afs: Fix decoding of inline abort codes from version 1 status records afs: Fix missing XDR advance in xdr_decode_{AFS,YFS}FSFetchStatus()
This commit is contained in:
commit
f4cd66682b
108
fs/afs/dir.c
108
fs/afs/dir.c
|
@ -1032,7 +1032,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
|
|||
struct dentry *parent;
|
||||
struct inode *inode;
|
||||
struct key *key;
|
||||
afs_dataversion_t dir_version;
|
||||
afs_dataversion_t dir_version, invalid_before;
|
||||
long de_version;
|
||||
int ret;
|
||||
|
||||
|
@ -1084,8 +1084,8 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
|
|||
if (de_version == (long)dir_version)
|
||||
goto out_valid_noupdate;
|
||||
|
||||
dir_version = dir->invalid_before;
|
||||
if (de_version - (long)dir_version >= 0)
|
||||
invalid_before = dir->invalid_before;
|
||||
if (de_version - (long)invalid_before >= 0)
|
||||
goto out_valid;
|
||||
|
||||
_debug("dir modified");
|
||||
|
@ -1275,6 +1275,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
|||
struct afs_fs_cursor fc;
|
||||
struct afs_vnode *dvnode = AFS_FS_I(dir);
|
||||
struct key *key;
|
||||
afs_dataversion_t data_version;
|
||||
int ret;
|
||||
|
||||
mode |= S_IFDIR;
|
||||
|
@ -1295,7 +1296,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
|||
|
||||
ret = -ERESTARTSYS;
|
||||
if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
|
||||
afs_dataversion_t data_version = dvnode->status.data_version + 1;
|
||||
data_version = dvnode->status.data_version + 1;
|
||||
|
||||
while (afs_select_fileserver(&fc)) {
|
||||
fc.cb_break = afs_calc_vnode_cb_break(dvnode);
|
||||
|
@ -1316,10 +1317,14 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
|||
goto error_key;
|
||||
}
|
||||
|
||||
if (ret == 0 &&
|
||||
test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
|
||||
afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
|
||||
afs_edit_dir_for_create);
|
||||
if (ret == 0) {
|
||||
down_write(&dvnode->validate_lock);
|
||||
if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
|
||||
dvnode->status.data_version == data_version)
|
||||
afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
|
||||
afs_edit_dir_for_create);
|
||||
up_write(&dvnode->validate_lock);
|
||||
}
|
||||
|
||||
key_put(key);
|
||||
kfree(scb);
|
||||
|
@ -1360,6 +1365,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
|
|||
struct afs_fs_cursor fc;
|
||||
struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode = NULL;
|
||||
struct key *key;
|
||||
afs_dataversion_t data_version;
|
||||
int ret;
|
||||
|
||||
_enter("{%llx:%llu},{%pd}",
|
||||
|
@ -1391,7 +1397,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
|
|||
|
||||
ret = -ERESTARTSYS;
|
||||
if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
|
||||
afs_dataversion_t data_version = dvnode->status.data_version + 1;
|
||||
data_version = dvnode->status.data_version + 1;
|
||||
|
||||
while (afs_select_fileserver(&fc)) {
|
||||
fc.cb_break = afs_calc_vnode_cb_break(dvnode);
|
||||
|
@ -1404,9 +1410,12 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
|
|||
ret = afs_end_vnode_operation(&fc);
|
||||
if (ret == 0) {
|
||||
afs_dir_remove_subdir(dentry);
|
||||
if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
|
||||
down_write(&dvnode->validate_lock);
|
||||
if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
|
||||
dvnode->status.data_version == data_version)
|
||||
afs_edit_dir_remove(dvnode, &dentry->d_name,
|
||||
afs_edit_dir_for_rmdir);
|
||||
up_write(&dvnode->validate_lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1544,10 +1553,15 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
|
|||
ret = afs_end_vnode_operation(&fc);
|
||||
if (ret == 0 && !(scb[1].have_status || scb[1].have_error))
|
||||
ret = afs_dir_remove_link(dvnode, dentry, key);
|
||||
if (ret == 0 &&
|
||||
test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
|
||||
afs_edit_dir_remove(dvnode, &dentry->d_name,
|
||||
afs_edit_dir_for_unlink);
|
||||
|
||||
if (ret == 0) {
|
||||
down_write(&dvnode->validate_lock);
|
||||
if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
|
||||
dvnode->status.data_version == data_version)
|
||||
afs_edit_dir_remove(dvnode, &dentry->d_name,
|
||||
afs_edit_dir_for_unlink);
|
||||
up_write(&dvnode->validate_lock);
|
||||
}
|
||||
}
|
||||
|
||||
if (need_rehash && ret < 0 && ret != -ENOENT)
|
||||
|
@ -1573,6 +1587,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
|
|||
struct afs_status_cb *scb;
|
||||
struct afs_vnode *dvnode = AFS_FS_I(dir);
|
||||
struct key *key;
|
||||
afs_dataversion_t data_version;
|
||||
int ret;
|
||||
|
||||
mode |= S_IFREG;
|
||||
|
@ -1597,7 +1612,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
|
|||
|
||||
ret = -ERESTARTSYS;
|
||||
if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
|
||||
afs_dataversion_t data_version = dvnode->status.data_version + 1;
|
||||
data_version = dvnode->status.data_version + 1;
|
||||
|
||||
while (afs_select_fileserver(&fc)) {
|
||||
fc.cb_break = afs_calc_vnode_cb_break(dvnode);
|
||||
|
@ -1618,9 +1633,12 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
|
|||
goto error_key;
|
||||
}
|
||||
|
||||
if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
|
||||
down_write(&dvnode->validate_lock);
|
||||
if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
|
||||
dvnode->status.data_version == data_version)
|
||||
afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
|
||||
afs_edit_dir_for_create);
|
||||
up_write(&dvnode->validate_lock);
|
||||
|
||||
kfree(scb);
|
||||
key_put(key);
|
||||
|
@ -1648,6 +1666,7 @@ static int afs_link(struct dentry *from, struct inode *dir,
|
|||
struct afs_vnode *dvnode = AFS_FS_I(dir);
|
||||
struct afs_vnode *vnode = AFS_FS_I(d_inode(from));
|
||||
struct key *key;
|
||||
afs_dataversion_t data_version;
|
||||
int ret;
|
||||
|
||||
_enter("{%llx:%llu},{%llx:%llu},{%pd}",
|
||||
|
@ -1672,7 +1691,7 @@ static int afs_link(struct dentry *from, struct inode *dir,
|
|||
|
||||
ret = -ERESTARTSYS;
|
||||
if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
|
||||
afs_dataversion_t data_version = dvnode->status.data_version + 1;
|
||||
data_version = dvnode->status.data_version + 1;
|
||||
|
||||
if (mutex_lock_interruptible_nested(&vnode->io_lock, 1) < 0) {
|
||||
afs_end_vnode_operation(&fc);
|
||||
|
@ -1702,9 +1721,12 @@ static int afs_link(struct dentry *from, struct inode *dir,
|
|||
goto error_key;
|
||||
}
|
||||
|
||||
if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
|
||||
down_write(&dvnode->validate_lock);
|
||||
if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
|
||||
dvnode->status.data_version == data_version)
|
||||
afs_edit_dir_add(dvnode, &dentry->d_name, &vnode->fid,
|
||||
afs_edit_dir_for_link);
|
||||
up_write(&dvnode->validate_lock);
|
||||
|
||||
key_put(key);
|
||||
kfree(scb);
|
||||
|
@ -1732,6 +1754,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
|
|||
struct afs_status_cb *scb;
|
||||
struct afs_vnode *dvnode = AFS_FS_I(dir);
|
||||
struct key *key;
|
||||
afs_dataversion_t data_version;
|
||||
int ret;
|
||||
|
||||
_enter("{%llx:%llu},{%pd},%s",
|
||||
|
@ -1759,7 +1782,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
|
|||
|
||||
ret = -ERESTARTSYS;
|
||||
if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
|
||||
afs_dataversion_t data_version = dvnode->status.data_version + 1;
|
||||
data_version = dvnode->status.data_version + 1;
|
||||
|
||||
while (afs_select_fileserver(&fc)) {
|
||||
fc.cb_break = afs_calc_vnode_cb_break(dvnode);
|
||||
|
@ -1780,9 +1803,12 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
|
|||
goto error_key;
|
||||
}
|
||||
|
||||
if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
|
||||
down_write(&dvnode->validate_lock);
|
||||
if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
|
||||
dvnode->status.data_version == data_version)
|
||||
afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
|
||||
afs_edit_dir_for_symlink);
|
||||
up_write(&dvnode->validate_lock);
|
||||
|
||||
key_put(key);
|
||||
kfree(scb);
|
||||
|
@ -1812,6 +1838,8 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||
struct dentry *tmp = NULL, *rehash = NULL;
|
||||
struct inode *new_inode;
|
||||
struct key *key;
|
||||
afs_dataversion_t orig_data_version;
|
||||
afs_dataversion_t new_data_version;
|
||||
bool new_negative = d_is_negative(new_dentry);
|
||||
int ret;
|
||||
|
||||
|
@ -1890,10 +1918,6 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||
|
||||
ret = -ERESTARTSYS;
|
||||
if (afs_begin_vnode_operation(&fc, orig_dvnode, key, true)) {
|
||||
afs_dataversion_t orig_data_version;
|
||||
afs_dataversion_t new_data_version;
|
||||
struct afs_status_cb *new_scb = &scb[1];
|
||||
|
||||
orig_data_version = orig_dvnode->status.data_version + 1;
|
||||
|
||||
if (orig_dvnode != new_dvnode) {
|
||||
|
@ -1904,7 +1928,6 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||
new_data_version = new_dvnode->status.data_version + 1;
|
||||
} else {
|
||||
new_data_version = orig_data_version;
|
||||
new_scb = &scb[0];
|
||||
}
|
||||
|
||||
while (afs_select_fileserver(&fc)) {
|
||||
|
@ -1912,7 +1935,7 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||
fc.cb_break_2 = afs_calc_vnode_cb_break(new_dvnode);
|
||||
afs_fs_rename(&fc, old_dentry->d_name.name,
|
||||
new_dvnode, new_dentry->d_name.name,
|
||||
&scb[0], new_scb);
|
||||
&scb[0], &scb[1]);
|
||||
}
|
||||
|
||||
afs_vnode_commit_status(&fc, orig_dvnode, fc.cb_break,
|
||||
|
@ -1930,18 +1953,25 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||
if (ret == 0) {
|
||||
if (rehash)
|
||||
d_rehash(rehash);
|
||||
if (test_bit(AFS_VNODE_DIR_VALID, &orig_dvnode->flags))
|
||||
afs_edit_dir_remove(orig_dvnode, &old_dentry->d_name,
|
||||
afs_edit_dir_for_rename_0);
|
||||
down_write(&orig_dvnode->validate_lock);
|
||||
if (test_bit(AFS_VNODE_DIR_VALID, &orig_dvnode->flags) &&
|
||||
orig_dvnode->status.data_version == orig_data_version)
|
||||
afs_edit_dir_remove(orig_dvnode, &old_dentry->d_name,
|
||||
afs_edit_dir_for_rename_0);
|
||||
if (orig_dvnode != new_dvnode) {
|
||||
up_write(&orig_dvnode->validate_lock);
|
||||
|
||||
if (!new_negative &&
|
||||
test_bit(AFS_VNODE_DIR_VALID, &new_dvnode->flags))
|
||||
afs_edit_dir_remove(new_dvnode, &new_dentry->d_name,
|
||||
afs_edit_dir_for_rename_1);
|
||||
down_write(&new_dvnode->validate_lock);
|
||||
}
|
||||
if (test_bit(AFS_VNODE_DIR_VALID, &new_dvnode->flags) &&
|
||||
orig_dvnode->status.data_version == new_data_version) {
|
||||
if (!new_negative)
|
||||
afs_edit_dir_remove(new_dvnode, &new_dentry->d_name,
|
||||
afs_edit_dir_for_rename_1);
|
||||
|
||||
if (test_bit(AFS_VNODE_DIR_VALID, &new_dvnode->flags))
|
||||
afs_edit_dir_add(new_dvnode, &new_dentry->d_name,
|
||||
&vnode->fid, afs_edit_dir_for_rename_2);
|
||||
}
|
||||
|
||||
new_inode = d_inode(new_dentry);
|
||||
if (new_inode) {
|
||||
|
@ -1957,14 +1987,10 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||
* Note that if we ever implement RENAME_EXCHANGE, we'll have
|
||||
* to update both dentries with opposing dir versions.
|
||||
*/
|
||||
if (new_dvnode != orig_dvnode) {
|
||||
afs_update_dentry_version(&fc, old_dentry, &scb[1]);
|
||||
afs_update_dentry_version(&fc, new_dentry, &scb[1]);
|
||||
} else {
|
||||
afs_update_dentry_version(&fc, old_dentry, &scb[0]);
|
||||
afs_update_dentry_version(&fc, new_dentry, &scb[0]);
|
||||
}
|
||||
afs_update_dentry_version(&fc, old_dentry, &scb[1]);
|
||||
afs_update_dentry_version(&fc, new_dentry, &scb[1]);
|
||||
d_move(old_dentry, new_dentry);
|
||||
up_write(&new_dvnode->validate_lock);
|
||||
goto error_tmp;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ static int afs_do_silly_rename(struct afs_vnode *dvnode, struct afs_vnode *vnode
|
|||
{
|
||||
struct afs_fs_cursor fc;
|
||||
struct afs_status_cb *scb;
|
||||
afs_dataversion_t dir_data_version;
|
||||
int ret = -ERESTARTSYS;
|
||||
|
||||
_enter("%pd,%pd", old, new);
|
||||
|
@ -31,7 +32,7 @@ static int afs_do_silly_rename(struct afs_vnode *dvnode, struct afs_vnode *vnode
|
|||
|
||||
trace_afs_silly_rename(vnode, false);
|
||||
if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
|
||||
afs_dataversion_t dir_data_version = dvnode->status.data_version + 1;
|
||||
dir_data_version = dvnode->status.data_version + 1;
|
||||
|
||||
while (afs_select_fileserver(&fc)) {
|
||||
fc.cb_break = afs_calc_vnode_cb_break(dvnode);
|
||||
|
@ -54,12 +55,15 @@ static int afs_do_silly_rename(struct afs_vnode *dvnode, struct afs_vnode *vnode
|
|||
dvnode->silly_key = key_get(key);
|
||||
}
|
||||
|
||||
if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
|
||||
down_write(&dvnode->validate_lock);
|
||||
if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
|
||||
dvnode->status.data_version == dir_data_version) {
|
||||
afs_edit_dir_remove(dvnode, &old->d_name,
|
||||
afs_edit_dir_for_silly_0);
|
||||
if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
|
||||
afs_edit_dir_add(dvnode, &new->d_name,
|
||||
&vnode->fid, afs_edit_dir_for_silly_1);
|
||||
}
|
||||
up_write(&dvnode->validate_lock);
|
||||
}
|
||||
|
||||
kfree(scb);
|
||||
|
@ -181,10 +185,14 @@ static int afs_do_silly_unlink(struct afs_vnode *dvnode, struct afs_vnode *vnode
|
|||
clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
|
||||
}
|
||||
}
|
||||
if (ret == 0 &&
|
||||
test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
|
||||
afs_edit_dir_remove(dvnode, &dentry->d_name,
|
||||
afs_edit_dir_for_unlink);
|
||||
if (ret == 0) {
|
||||
down_write(&dvnode->validate_lock);
|
||||
if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
|
||||
dvnode->status.data_version == dir_data_version)
|
||||
afs_edit_dir_remove(dvnode, &dentry->d_name,
|
||||
afs_edit_dir_for_unlink);
|
||||
up_write(&dvnode->validate_lock);
|
||||
}
|
||||
}
|
||||
|
||||
kfree(scb);
|
||||
|
|
|
@ -65,6 +65,7 @@ static int xdr_decode_AFSFetchStatus(const __be32 **_bp,
|
|||
bool inline_error = (call->operation_ID == afs_FS_InlineBulkStatus);
|
||||
u64 data_version, size;
|
||||
u32 type, abort_code;
|
||||
int ret;
|
||||
|
||||
abort_code = ntohl(xdr->abort_code);
|
||||
|
||||
|
@ -78,7 +79,7 @@ static int xdr_decode_AFSFetchStatus(const __be32 **_bp,
|
|||
*/
|
||||
status->abort_code = abort_code;
|
||||
scb->have_error = true;
|
||||
return 0;
|
||||
goto good;
|
||||
}
|
||||
|
||||
pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version));
|
||||
|
@ -87,7 +88,8 @@ static int xdr_decode_AFSFetchStatus(const __be32 **_bp,
|
|||
|
||||
if (abort_code != 0 && inline_error) {
|
||||
status->abort_code = abort_code;
|
||||
return 0;
|
||||
scb->have_error = true;
|
||||
goto good;
|
||||
}
|
||||
|
||||
type = ntohl(xdr->type);
|
||||
|
@ -123,13 +125,16 @@ static int xdr_decode_AFSFetchStatus(const __be32 **_bp,
|
|||
data_version |= (u64)ntohl(xdr->data_version_hi) << 32;
|
||||
status->data_version = data_version;
|
||||
scb->have_status = true;
|
||||
|
||||
good:
|
||||
ret = 0;
|
||||
advance:
|
||||
*_bp = (const void *)*_bp + sizeof(*xdr);
|
||||
return 0;
|
||||
return ret;
|
||||
|
||||
bad:
|
||||
xdr_dump_bad(*_bp);
|
||||
return afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
|
||||
ret = afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
|
||||
goto advance;
|
||||
}
|
||||
|
||||
static time64_t xdr_decode_expiry(struct afs_call *call, u32 expiry)
|
||||
|
@ -981,16 +986,16 @@ static int afs_deliver_fs_rename(struct afs_call *call)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* unmarshall the reply once we've received all of it */
|
||||
/* If the two dirs are the same, we have two copies of the same status
|
||||
* report, so we just decode it twice.
|
||||
*/
|
||||
bp = call->buffer;
|
||||
ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (call->out_dir_scb != call->out_scb) {
|
||||
ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
xdr_decode_AFSVolSync(&bp, call->out_volsync);
|
||||
|
||||
_leave(" = 0 [done]");
|
||||
|
|
|
@ -165,15 +165,15 @@ static void xdr_dump_bad(const __be32 *bp)
|
|||
int i;
|
||||
|
||||
pr_notice("YFS XDR: Bad status record\n");
|
||||
for (i = 0; i < 5 * 4 * 4; i += 16) {
|
||||
for (i = 0; i < 6 * 4 * 4; i += 16) {
|
||||
memcpy(x, bp, 16);
|
||||
bp += 4;
|
||||
pr_notice("%03x: %08x %08x %08x %08x\n",
|
||||
i, ntohl(x[0]), ntohl(x[1]), ntohl(x[2]), ntohl(x[3]));
|
||||
}
|
||||
|
||||
memcpy(x, bp, 4);
|
||||
pr_notice("0x50: %08x\n", ntohl(x[0]));
|
||||
memcpy(x, bp, 8);
|
||||
pr_notice("0x60: %08x %08x\n", ntohl(x[0]), ntohl(x[1]));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -186,13 +186,14 @@ static int xdr_decode_YFSFetchStatus(const __be32 **_bp,
|
|||
const struct yfs_xdr_YFSFetchStatus *xdr = (const void *)*_bp;
|
||||
struct afs_file_status *status = &scb->status;
|
||||
u32 type;
|
||||
int ret;
|
||||
|
||||
status->abort_code = ntohl(xdr->abort_code);
|
||||
if (status->abort_code != 0) {
|
||||
if (status->abort_code == VNOVNODE)
|
||||
status->nlink = 0;
|
||||
scb->have_error = true;
|
||||
return 0;
|
||||
goto good;
|
||||
}
|
||||
|
||||
type = ntohl(xdr->type);
|
||||
|
@ -220,13 +221,16 @@ static int xdr_decode_YFSFetchStatus(const __be32 **_bp,
|
|||
status->size = xdr_to_u64(xdr->size);
|
||||
status->data_version = xdr_to_u64(xdr->data_version);
|
||||
scb->have_status = true;
|
||||
|
||||
good:
|
||||
ret = 0;
|
||||
advance:
|
||||
*_bp += xdr_size(xdr);
|
||||
return 0;
|
||||
return ret;
|
||||
|
||||
bad:
|
||||
xdr_dump_bad(*_bp);
|
||||
return afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
|
||||
ret = afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
|
||||
goto advance;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1153,11 +1157,9 @@ static int yfs_deliver_fs_rename(struct afs_call *call)
|
|||
ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (call->out_dir_scb != call->out_scb) {
|
||||
ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
xdr_decode_YFSVolSync(&bp, call->out_volsync);
|
||||
_leave(" = 0 [done]");
|
||||
|
|
Loading…
Reference in New Issue