afs: Don't invalidate callback if AFS_VNODE_DIR_VALID not set
[sfrench/cifs-2.6.git] / fs / afs / inode.c
index 9cedc3fc1b7744679010f4aae412c92925cd3b3a..bf8f56e851dfe0f3775e66ee8fe616460e915050 100644 (file)
@@ -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);
@@ -106,7 +136,7 @@ int afs_fetch_status(struct afs_vnode *vnode, struct key *key, bool new_inode)
               vnode->flags);
 
        ret = -ERESTARTSYS;
-       if (afs_begin_vnode_operation(&fc, vnode, key)) {
+       if (afs_begin_vnode_operation(&fc, vnode, key, true)) {
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(vnode);
                        afs_fs_fetch_file_status(&fc, NULL, new_inode);
@@ -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;
 
@@ -399,12 +430,9 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
                        vnode->cb_s_break = vnode->cb_interest->server->cb_s_break;
                        vnode->cb_v_break = vnode->volume->cb_v_break;
                        valid = false;
-               } else if (vnode->status.type == AFS_FTYPE_DIR &&
-                          (!test_bit(AFS_VNODE_DIR_VALID, &vnode->flags) ||
-                           vnode->cb_expires_at - 10 <= now)) {
+               } else if (test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) {
                        valid = false;
-               } else if (test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags) ||
-                          vnode->cb_expires_at - 10 <= now) {
+               } else if (vnode->cb_expires_at - 10 <= now) {
                        valid = false;
                } else {
                        valid = true;
@@ -542,7 +570,10 @@ void afs_evict_inode(struct inode *inode)
        }
 #endif
 
+       afs_prune_wb_keys(vnode);
        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("");
@@ -583,7 +614,7 @@ int afs_setattr(struct dentry *dentry, struct iattr *attr)
        }
 
        ret = -ERESTARTSYS;
-       if (afs_begin_vnode_operation(&fc, vnode, key)) {
+       if (afs_begin_vnode_operation(&fc, vnode, key, false)) {
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(vnode);
                        afs_fs_setattr(&fc, attr);