Blame view

fs/afs/inode.c 12.5 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
  /*
   * Copyright (c) 2002 Red Hat, Inc. All rights reserved.
   *
   * This software may be freely redistributed under the terms of the
   * GNU General Public License.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   *
44d1b980c   David Woodhouse   Fix various old e...
11
   * Authors: David Woodhouse <dwmw2@infradead.org>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
16
17
18
   *          David Howells <dhowells@redhat.com>
   *
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/init.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
  #include <linux/fs.h>
  #include <linux/pagemap.h>
e8edc6e03   Alexey Dobriyan   Detach sched.h fr...
21
  #include <linux/sched.h>
bec5eb614   wanglei   AFS: Implement an...
22
23
  #include <linux/mount.h>
  #include <linux/namei.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
26
27
28
29
  #include "internal.h"
  
  struct afs_iget_data {
  	struct afs_fid		fid;
  	struct afs_volume	*volume;	/* volume on which resides */
  };
d3e3b7eac   David Howells   afs: Add metadata...
30
31
32
33
  static const struct inode_operations afs_symlink_inode_operations = {
  	.get_link	= page_get_link,
  	.listxattr	= afs_listxattr,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
  /*
   * map the AFS file status to the inode member variables
   */
00d3b7a45   David Howells   [AFS]: Add securi...
37
  static int afs_inode_map_status(struct afs_vnode *vnode, struct key *key)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
39
  {
  	struct inode *inode = AFS_VNODE_TO_I(vnode);
260a98031   David Howells   [AFS]: Add "direc...
40
  	_debug("FS: ft=%d lk=%d sz=%llu ver=%Lu mod=%hu",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
  	       vnode->status.type,
  	       vnode->status.nlink,
ba3e0e1ac   David S. Miller   [AFS]: Fix u64 pr...
43
  	       (unsigned long long) vnode->status.size,
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
44
  	       vnode->status.data_version,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
47
48
49
50
  	       vnode->status.mode);
  
  	switch (vnode->status.type) {
  	case AFS_FTYPE_FILE:
  		inode->i_mode	= S_IFREG | vnode->status.mode;
  		inode->i_op	= &afs_file_inode_operations;
00d3b7a45   David Howells   [AFS]: Add securi...
51
  		inode->i_fop	= &afs_file_operations;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
53
54
55
56
57
58
  		break;
  	case AFS_FTYPE_DIR:
  		inode->i_mode	= S_IFDIR | vnode->status.mode;
  		inode->i_op	= &afs_dir_inode_operations;
  		inode->i_fop	= &afs_dir_file_operations;
  		break;
  	case AFS_FTYPE_SYMLINK:
944c74f47   David Howells   afs: Distinguish ...
59
60
61
62
63
64
65
66
67
68
69
70
71
  		/* Symlinks with a mode of 0644 are actually mountpoints. */
  		if ((vnode->status.mode & 0777) == 0644) {
  			inode->i_flags |= S_AUTOMOUNT;
  
  			spin_lock(&vnode->lock);
  			set_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags);
  			spin_unlock(&vnode->lock);
  
  			inode->i_mode	= S_IFDIR | 0555;
  			inode->i_op	= &afs_mntpt_inode_operations;
  			inode->i_fop	= &afs_mntpt_file_operations;
  		} else {
  			inode->i_mode	= S_IFLNK | vnode->status.mode;
d3e3b7eac   David Howells   afs: Add metadata...
72
  			inode->i_op	= &afs_symlink_inode_operations;
944c74f47   David Howells   afs: Distinguish ...
73
  		}
21fc61c73   Al Viro   don't put symlink...
74
  		inode_nohighmem(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
76
77
78
79
80
  		break;
  	default:
  		printk("kAFS: AFS vnode with undefined type
  ");
  		return -EBADMSG;
  	}
9b3f26c91   David Howells   FS-Cache: Make kA...
81
82
83
84
  #ifdef CONFIG_AFS_FSCACHE
  	if (vnode->status.size != inode->i_size)
  		fscache_attr_changed(vnode->cache);
  #endif
bfe868486   Miklos Szeredi   filesystems: add ...
85
  	set_nlink(inode, vnode->status.nlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
  	inode->i_uid		= vnode->status.owner;
6186f0788   Marc Dionne   afs: Populate gro...
87
  	inode->i_gid            = vnode->status.group;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
  	inode->i_size		= vnode->status.size;
ab94f5d0d   Marc Dionne   afs: Populate and...
89
  	inode->i_ctime.tv_sec	= vnode->status.mtime_client;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
  	inode->i_ctime.tv_nsec	= 0;
  	inode->i_atime		= inode->i_mtime = inode->i_ctime;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
  	inode->i_blocks		= 0;
d6e43f751   David Howells   AFS: Use i_genera...
93
94
  	inode->i_generation	= vnode->fid.unique;
  	inode->i_version	= vnode->status.data_version;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
  	inode->i_mapping->a_ops	= &afs_fs_aops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
  	return 0;
ec26815ad   David Howells   [AFS]: Clean up t...
97
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
102
103
104
105
106
   * iget5() comparator
   */
  static int afs_iget5_test(struct inode *inode, void *opaque)
  {
  	struct afs_iget_data *data = opaque;
  
  	return inode->i_ino == data->fid.vnode &&
d6e43f751   David Howells   AFS: Use i_genera...
107
  		inode->i_generation == data->fid.unique;
ec26815ad   David Howells   [AFS]: Clean up t...
108
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
  /*
bec5eb614   wanglei   AFS: Implement an...
111
112
113
114
115
116
117
118
119
120
   * iget5() comparator for inode created by autocell operations
   *
   * These pseudo inodes don't match anything.
   */
  static int afs_iget5_autocell_test(struct inode *inode, void *opaque)
  {
  	return 0;
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
123
124
125
126
127
128
   * iget5() inode initialiser
   */
  static int afs_iget5_set(struct inode *inode, void *opaque)
  {
  	struct afs_iget_data *data = opaque;
  	struct afs_vnode *vnode = AFS_FS_I(inode);
  
  	inode->i_ino = data->fid.vnode;
d6e43f751   David Howells   AFS: Use i_genera...
129
  	inode->i_generation = data->fid.unique;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
131
132
133
  	vnode->fid = data->fid;
  	vnode->volume = data->volume;
  
  	return 0;
ec26815ad   David Howells   [AFS]: Clean up t...
134
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
  /*
bec5eb614   wanglei   AFS: Implement an...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
   * inode retrieval for autocell
   */
  struct inode *afs_iget_autocell(struct inode *dir, const char *dev_name,
  				int namesz, struct key *key)
  {
  	struct afs_iget_data data;
  	struct afs_super_info *as;
  	struct afs_vnode *vnode;
  	struct super_block *sb;
  	struct inode *inode;
  	static atomic_t afs_autocell_ino;
  
  	_enter("{%x:%u},%*.*s,",
  	       AFS_FS_I(dir)->fid.vid, AFS_FS_I(dir)->fid.vnode,
  	       namesz, namesz, dev_name ?: "");
  
  	sb = dir->i_sb;
  	as = sb->s_fs_info;
  	data.volume = as->volume;
  	data.fid.vid = as->volume->vid;
  	data.fid.unique = 0;
  	data.fid.vnode = 0;
  
  	inode = iget5_locked(sb, atomic_inc_return(&afs_autocell_ino),
  			     afs_iget5_autocell_test, afs_iget5_set,
  			     &data);
  	if (!inode) {
  		_leave(" = -ENOMEM");
  		return ERR_PTR(-ENOMEM);
  	}
  
  	_debug("GOT INODE %p { ino=%lu, vl=%x, vn=%x, u=%x }",
  	       inode, inode->i_ino, data.fid.vid, data.fid.vnode,
  	       data.fid.unique);
  
  	vnode = AFS_FS_I(inode);
  
  	/* there shouldn't be an existing inode */
  	BUG_ON(!(inode->i_state & I_NEW));
  
  	inode->i_size		= 0;
  	inode->i_mode		= S_IFDIR | S_IRUGO | S_IXUGO;
  	inode->i_op		= &afs_autocell_inode_operations;
bfe868486   Miklos Szeredi   filesystems: add ...
180
  	set_nlink(inode, 2);
a0a5386ac   Eric W. Biederman   afs: Support inte...
181
182
  	inode->i_uid		= GLOBAL_ROOT_UID;
  	inode->i_gid		= GLOBAL_ROOT_GID;
bec5eb614   wanglei   AFS: Implement an...
183
184
185
186
187
188
189
190
  	inode->i_ctime.tv_sec	= get_seconds();
  	inode->i_ctime.tv_nsec	= 0;
  	inode->i_atime		= inode->i_mtime = inode->i_ctime;
  	inode->i_blocks		= 0;
  	inode->i_version	= 0;
  	inode->i_generation	= 0;
  
  	set_bit(AFS_VNODE_PSEUDODIR, &vnode->flags);
d18610b0c   David Howells   AFS: Use d_automo...
191
192
  	set_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags);
  	inode->i_flags |= S_AUTOMOUNT | S_NOATIME;
bec5eb614   wanglei   AFS: Implement an...
193
194
195
196
197
198
  	unlock_new_inode(inode);
  	_leave(" = %p", inode);
  	return inode;
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
   * inode retrieval
   */
260a98031   David Howells   [AFS]: Add "direc...
201
202
203
  struct inode *afs_iget(struct super_block *sb, struct key *key,
  		       struct afs_fid *fid, struct afs_file_status *status,
  		       struct afs_callback *cb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
205
206
207
208
209
  {
  	struct afs_iget_data data = { .fid = *fid };
  	struct afs_super_info *as;
  	struct afs_vnode *vnode;
  	struct inode *inode;
  	int ret;
416351f28   David Howells   AFS: AFS fixups
210
  	_enter(",{%x:%u.%u},,", fid->vid, fid->vnode, fid->unique);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
212
213
214
215
216
217
218
  
  	as = sb->s_fs_info;
  	data.volume = as->volume;
  
  	inode = iget5_locked(sb, fid->vnode, afs_iget5_test, afs_iget5_set,
  			     &data);
  	if (!inode) {
  		_leave(" = -ENOMEM");
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
219
  		return ERR_PTR(-ENOMEM);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
  	}
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
221
222
  	_debug("GOT INODE %p { vl=%x vn=%x, u=%x }",
  	       inode, fid->vid, fid->vnode, fid->unique);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
224
225
226
  	vnode = AFS_FS_I(inode);
  
  	/* deal with an existing inode */
  	if (!(inode->i_state & I_NEW)) {
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
227
228
  		_leave(" = %p", inode);
  		return inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
  	}
260a98031   David Howells   [AFS]: Add "direc...
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
  	if (!status) {
  		/* it's a remotely extant inode */
  		set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags);
  		ret = afs_vnode_fetch_status(vnode, NULL, key);
  		if (ret < 0)
  			goto bad_inode;
  	} else {
  		/* it's an inode we just created */
  		memcpy(&vnode->status, status, sizeof(vnode->status));
  
  		if (!cb) {
  			/* it's a symlink we just created (the fileserver
  			 * didn't give us a callback) */
  			vnode->cb_version = 0;
  			vnode->cb_expiry = 0;
  			vnode->cb_type = 0;
56e714312   Tina Ruchandani   afs: Prevent call...
246
  			vnode->cb_expires = ktime_get_real_seconds();
260a98031   David Howells   [AFS]: Add "direc...
247
248
249
250
  		} else {
  			vnode->cb_version = cb->version;
  			vnode->cb_expiry = cb->expiry;
  			vnode->cb_type = cb->type;
56e714312   Tina Ruchandani   afs: Prevent call...
251
252
  			vnode->cb_expires = vnode->cb_expiry +
  				ktime_get_real_seconds();
260a98031   David Howells   [AFS]: Add "direc...
253
254
  		}
  	}
9b3f26c91   David Howells   FS-Cache: Make kA...
255
256
257
258
259
260
  	/* set up caching before mapping the status, as map-status reads the
  	 * first page of symlinks to see if they're really mountpoints */
  	inode->i_size = vnode->status.size;
  #ifdef CONFIG_AFS_FSCACHE
  	vnode->cache = fscache_acquire_cookie(vnode->volume->cache,
  					      &afs_vnode_cache_index_def,
94d30ae90   David Howells   FS-Cache: Provide...
261
  					      vnode, true);
9b3f26c91   David Howells   FS-Cache: Make kA...
262
  #endif
00d3b7a45   David Howells   [AFS]: Add securi...
263
  	ret = afs_inode_map_status(vnode, key);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
264
  	if (ret < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
266
267
  		goto bad_inode;
  
  	/* success */
260a98031   David Howells   [AFS]: Add "direc...
268
  	clear_bit(AFS_VNODE_UNSET, &vnode->flags);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
269
  	inode->i_flags |= S_NOATIME;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
  	unlock_new_inode(inode);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
271
272
  	_leave(" = %p [CB { v=%u t=%u }]", inode, vnode->cb_version, vnode->cb_type);
  	return inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
274
  
  	/* failure */
ec26815ad   David Howells   [AFS]: Clean up t...
275
  bad_inode:
9b3f26c91   David Howells   FS-Cache: Make kA...
276
277
278
279
  #ifdef CONFIG_AFS_FSCACHE
  	fscache_relinquish_cookie(vnode->cache, 0);
  	vnode->cache = NULL;
  #endif
aa7fa240c   David Howells   iget: use iget_fa...
280
  	iget_failed(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281
  	_leave(" = %d [bad]", ret);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
282
  	return ERR_PTR(ret);
ec26815ad   David Howells   [AFS]: Clean up t...
283
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
  /*
416351f28   David Howells   AFS: AFS fixups
286
287
288
289
290
   * mark the data attached to an inode as obsolete due to a write on the server
   * - might also want to ditch all the outstanding writes and dirty pages
   */
  void afs_zap_data(struct afs_vnode *vnode)
  {
0f300ca92   David Howells   AFS: fix a couple...
291
  	_enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
416351f28   David Howells   AFS: AFS fixups
292
293
  
  	/* nuke all the non-dirty pages that aren't locked, mapped or being
0f300ca92   David Howells   AFS: fix a couple...
294
295
296
297
298
299
  	 * written back in a regular file and completely discard the pages in a
  	 * directory or symlink */
  	if (S_ISREG(vnode->vfs_inode.i_mode))
  		invalidate_remote_inode(&vnode->vfs_inode);
  	else
  		invalidate_inode_pages2(vnode->vfs_inode.i_mapping);
416351f28   David Howells   AFS: AFS fixups
300
301
302
  }
  
  /*
260a98031   David Howells   [AFS]: Add "direc...
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
   * validate a vnode/inode
   * - there are several things we need to check
   *   - parent dir data changes (rm, rmdir, rename, mkdir, create, link,
   *     symlink)
   *   - parent dir metadata changed (security changes)
   *   - dentry data changed (write, truncate)
   *   - dentry metadata changed (security changes)
   */
  int afs_validate(struct afs_vnode *vnode, struct key *key)
  {
  	int ret;
  
  	_enter("{v={%x:%u} fl=%lx},%x",
  	       vnode->fid.vid, vnode->fid.vnode, vnode->flags,
  	       key_serial(key));
  
  	if (vnode->cb_promised &&
  	    !test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags) &&
  	    !test_bit(AFS_VNODE_MODIFIED, &vnode->flags) &&
  	    !test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) {
56e714312   Tina Ruchandani   afs: Prevent call...
323
  		if (vnode->cb_expires < ktime_get_real_seconds() + 10) {
260a98031   David Howells   [AFS]: Add "direc...
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
  			_debug("callback expired");
  			set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags);
  		} else {
  			goto valid;
  		}
  	}
  
  	if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
  		goto valid;
  
  	mutex_lock(&vnode->validate_lock);
  
  	/* if the promise has expired, we need to check the server again to get
  	 * a new promise - note that if the (parent) directory's metadata was
  	 * changed then the security may be different and we may no longer have
  	 * access */
  	if (!vnode->cb_promised ||
  	    test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags)) {
  		_debug("not promised");
  		ret = afs_vnode_fetch_status(vnode, NULL, key);
  		if (ret < 0)
  			goto error_unlock;
  		_debug("new promise [fl=%lx]", vnode->flags);
  	}
  
  	if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
  		_debug("file already deleted");
  		ret = -ESTALE;
  		goto error_unlock;
  	}
  
  	/* if the vnode's data version number changed then its contents are
  	 * different */
416351f28   David Howells   AFS: AFS fixups
357
358
  	if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags))
  		afs_zap_data(vnode);
260a98031   David Howells   [AFS]: Add "direc...
359
360
361
362
363
364
365
366
367
368
369
370
371
372
  
  	clear_bit(AFS_VNODE_MODIFIED, &vnode->flags);
  	mutex_unlock(&vnode->validate_lock);
  valid:
  	_leave(" = 0");
  	return 0;
  
  error_unlock:
  	mutex_unlock(&vnode->validate_lock);
  	_leave(" = %d", ret);
  	return ret;
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
374
   * read the attributes of an inode
   */
a528d35e8   David Howells   statx: Add a syst...
375
376
  int afs_getattr(const struct path *path, struct kstat *stat,
  		u32 request_mask, unsigned int query_flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377
  {
a528d35e8   David Howells   statx: Add a syst...
378
  	struct inode *inode = d_inode(path->dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379

d6e43f751   David Howells   AFS: Use i_genera...
380
  	_enter("{ ino=%lu v=%u }", inode->i_ino, inode->i_generation);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382
  	generic_fillattr(inode, stat);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
383
  	return 0;
ec26815ad   David Howells   [AFS]: Clean up t...
384
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
385

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
  /*
bec5eb614   wanglei   AFS: Implement an...
387
388
389
390
391
392
393
394
395
396
397
398
399
   * discard an AFS inode
   */
  int afs_drop_inode(struct inode *inode)
  {
  	_enter("");
  
  	if (test_bit(AFS_VNODE_PSEUDODIR, &AFS_FS_I(inode)->flags))
  		return generic_delete_inode(inode);
  	else
  		return generic_drop_inode(inode);
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
400
401
   * clear an AFS inode
   */
b57922d97   Al Viro   convert remaining...
402
  void afs_evict_inode(struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
  {
00d3b7a45   David Howells   [AFS]: Add securi...
404
  	struct afs_permits *permits;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405
406
407
  	struct afs_vnode *vnode;
  
  	vnode = AFS_FS_I(inode);
416351f28   David Howells   AFS: AFS fixups
408
  	_enter("{%x:%u.%d} v=%u x=%u t=%u }",
260a98031   David Howells   [AFS]: Add "direc...
409
  	       vnode->fid.vid,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410
  	       vnode->fid.vnode,
260a98031   David Howells   [AFS]: Add "direc...
411
  	       vnode->fid.unique,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
412
413
  	       vnode->cb_version,
  	       vnode->cb_expiry,
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
414
  	       vnode->cb_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
416
417
418
  	_debug("CLEAR INODE %p", inode);
  
  	ASSERTCMP(inode->i_ino, ==, vnode->fid.vnode);
91b0abe36   Johannes Weiner   mm + fs: store sh...
419
  	truncate_inode_pages_final(&inode->i_data);
dbd5768f8   Jan Kara   vfs: Rename end_w...
420
  	clear_inode(inode);
b57922d97   Al Viro   convert remaining...
421

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
422
423
424
425
426
427
428
429
430
  	afs_give_up_callback(vnode);
  
  	if (vnode->server) {
  		spin_lock(&vnode->server->fs_lock);
  		rb_erase(&vnode->server_rb, &vnode->server->fs_vnodes);
  		spin_unlock(&vnode->server->fs_lock);
  		afs_put_server(vnode->server);
  		vnode->server = NULL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431

31143d5d5   David Howells   AFS: implement ba...
432
  	ASSERT(list_empty(&vnode->writebacks));
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
433
  	ASSERT(!vnode->cb_promised);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434

9b3f26c91   David Howells   FS-Cache: Make kA...
435
436
  #ifdef CONFIG_AFS_FSCACHE
  	fscache_relinquish_cookie(vnode->cache, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
438
  	vnode->cache = NULL;
  #endif
00d3b7a45   David Howells   [AFS]: Add securi...
439
440
  	mutex_lock(&vnode->permits_lock);
  	permits = vnode->permits;
1d7e4ebf2   Andreea-Cristina Bernat   afs: inode: Repla...
441
  	RCU_INIT_POINTER(vnode->permits, NULL);
00d3b7a45   David Howells   [AFS]: Add securi...
442
443
444
  	mutex_unlock(&vnode->permits_lock);
  	if (permits)
  		call_rcu(&permits->rcu, afs_zap_permits);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
445
  	_leave("");
ec26815ad   David Howells   [AFS]: Clean up t...
446
  }
31143d5d5   David Howells   AFS: implement ba...
447
448
449
450
451
452
  
  /*
   * set the attributes of an inode
   */
  int afs_setattr(struct dentry *dentry, struct iattr *attr)
  {
2b0143b5c   David Howells   VFS: normal files...
453
  	struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
31143d5d5   David Howells   AFS: implement ba...
454
455
  	struct key *key;
  	int ret;
a455589f1   Al Viro   assorted conversi...
456
457
  	_enter("{%x:%u},{n=%pd},%x",
  	       vnode->fid.vid, vnode->fid.vnode, dentry,
31143d5d5   David Howells   AFS: implement ba...
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
  	       attr->ia_valid);
  
  	if (!(attr->ia_valid & (ATTR_SIZE | ATTR_MODE | ATTR_UID | ATTR_GID |
  				ATTR_MTIME))) {
  		_leave(" = 0 [unsupported]");
  		return 0;
  	}
  
  	/* flush any dirty data outstanding on a regular file */
  	if (S_ISREG(vnode->vfs_inode.i_mode)) {
  		filemap_write_and_wait(vnode->vfs_inode.i_mapping);
  		afs_writeback_all(vnode);
  	}
  
  	if (attr->ia_valid & ATTR_FILE) {
  		key = attr->ia_file->private_data;
  	} else {
  		key = afs_request_key(vnode->volume->cell);
  		if (IS_ERR(key)) {
  			ret = PTR_ERR(key);
  			goto error;
  		}
  	}
  
  	ret = afs_vnode_setattr(vnode, key, attr);
  	if (!(attr->ia_valid & ATTR_FILE))
  		key_put(key);
  
  error:
  	_leave(" = %d", ret);
  	return ret;
  }