diff options
Diffstat (limited to 'fs/afs/inode.c')
-rw-r--r-- | fs/afs/inode.c | 43 |
1 files changed, 38 insertions, 5 deletions
diff --git a/fs/afs/inode.c b/fs/afs/inode.c index 9cedc3fc1b77..c4652b42d545 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -29,10 +29,36 @@ static const struct inode_operations afs_symlink_inode_operations = { .listxattr = afs_listxattr, }; +static noinline void dump_vnode(struct afs_vnode *vnode, struct afs_vnode *parent_vnode) +{ + static unsigned long once_only; + + pr_warn("kAFS: AFS vnode with undefined type %u\n", + vnode->status.type); + pr_warn("kAFS: A=%d m=%o s=%llx v=%llx\n", + vnode->status.abort_code, + vnode->status.mode, + vnode->status.size, + vnode->status.data_version); + pr_warn("kAFS: vnode %llx:%llx:%x\n", + vnode->fid.vid, + vnode->fid.vnode, + vnode->fid.unique); + if (parent_vnode) + pr_warn("kAFS: dir %llx:%llx:%x\n", + parent_vnode->fid.vid, + parent_vnode->fid.vnode, + parent_vnode->fid.unique); + + if (!test_and_set_bit(0, &once_only)) + dump_stack(); +} + /* * Initialise an inode from the vnode status. */ -static int afs_inode_init_from_status(struct afs_vnode *vnode, struct key *key) +static int afs_inode_init_from_status(struct afs_vnode *vnode, struct key *key, + struct afs_vnode *parent_vnode) { struct inode *inode = AFS_VNODE_TO_I(vnode); @@ -80,12 +106,16 @@ static int afs_inode_init_from_status(struct afs_vnode *vnode, struct key *key) inode_nohighmem(inode); break; default: - printk("kAFS: AFS vnode with undefined type\n"); + dump_vnode(vnode, parent_vnode); read_sequnlock_excl(&vnode->cb_lock); return afs_protocol_error(NULL, -EBADMSG, afs_eproto_file_type); } - inode->i_blocks = 0; + /* + * Estimate 512 bytes blocks used, rounded up to nearest 1K + * for consistency with other AFS clients. + */ + inode->i_blocks = ((i_size_read(inode) + 1023) >> 10) << 1; vnode->invalid_before = vnode->status.data_version; read_sequnlock_excl(&vnode->cb_lock); @@ -270,7 +300,8 @@ static void afs_get_inode_cache(struct afs_vnode *vnode) */ struct inode *afs_iget(struct super_block *sb, struct key *key, struct afs_fid *fid, struct afs_file_status *status, - struct afs_callback *cb, struct afs_cb_interest *cbi) + struct afs_callback *cb, struct afs_cb_interest *cbi, + struct afs_vnode *parent_vnode) { struct afs_iget_data data = { .fid = *fid }; struct afs_super_info *as; @@ -327,7 +358,7 @@ struct inode *afs_iget(struct super_block *sb, struct key *key, vnode->cb_expires_at += ktime_get_real_seconds(); } - ret = afs_inode_init_from_status(vnode, key); + ret = afs_inode_init_from_status(vnode, key, parent_vnode); if (ret < 0) goto bad_inode; @@ -543,6 +574,8 @@ void afs_evict_inode(struct inode *inode) #endif afs_put_permits(rcu_access_pointer(vnode->permit_cache)); + key_put(vnode->silly_key); + vnode->silly_key = NULL; key_put(vnode->lock_key); vnode->lock_key = NULL; _leave(""); |