Blame view

fs/afs/inode.c 12.2 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 */
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
32
  /*
   * map the AFS file status to the inode member variables
   */
00d3b7a45   David Howells   [AFS]: Add securi...
33
  static int afs_inode_map_status(struct afs_vnode *vnode, struct key *key)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
  {
  	struct inode *inode = AFS_VNODE_TO_I(vnode);
260a98031   David Howells   [AFS]: Add "direc...
36
  	_debug("FS: ft=%d lk=%d sz=%llu ver=%Lu mod=%hu",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
  	       vnode->status.type,
  	       vnode->status.nlink,
ba3e0e1ac   David S. Miller   [AFS]: Fix u64 pr...
39
  	       (unsigned long long) vnode->status.size,
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
40
  	       vnode->status.data_version,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
44
45
46
  	       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...
47
  		inode->i_fop	= &afs_file_operations;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
  		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:
  		inode->i_mode	= S_IFLNK | vnode->status.mode;
  		inode->i_op	= &page_symlink_inode_operations;
  		break;
  	default:
  		printk("kAFS: AFS vnode with undefined type
  ");
  		return -EBADMSG;
  	}
9b3f26c91   David Howells   FS-Cache: Make kA...
63
64
65
66
  #ifdef CONFIG_AFS_FSCACHE
  	if (vnode->status.size != inode->i_size)
  		fscache_attr_changed(vnode->cache);
  #endif
bfe868486   Miklos Szeredi   filesystems: add ...
67
  	set_nlink(inode, vnode->status.nlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
69
70
71
72
73
  	inode->i_uid		= vnode->status.owner;
  	inode->i_gid		= 0;
  	inode->i_size		= vnode->status.size;
  	inode->i_ctime.tv_sec	= vnode->status.mtime_server;
  	inode->i_ctime.tv_nsec	= 0;
  	inode->i_atime		= inode->i_mtime = inode->i_ctime;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
  	inode->i_blocks		= 0;
d6e43f751   David Howells   AFS: Use i_genera...
75
76
  	inode->i_generation	= vnode->fid.unique;
  	inode->i_version	= vnode->status.data_version;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
78
79
80
  	inode->i_mapping->a_ops	= &afs_fs_aops;
  
  	/* check to see whether a symbolic link is really a mountpoint */
  	if (vnode->status.type == AFS_FTYPE_SYMLINK) {
00d3b7a45   David Howells   [AFS]: Add securi...
81
  		afs_mntpt_check_symlink(vnode, key);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
83
  		if (test_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
85
86
87
88
89
90
  			inode->i_mode	= S_IFDIR | vnode->status.mode;
  			inode->i_op	= &afs_mntpt_inode_operations;
  			inode->i_fop	= &afs_mntpt_file_operations;
  		}
  	}
  
  	return 0;
ec26815ad   David Howells   [AFS]: Clean up t...
91
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
95
96
97
98
99
100
   * 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...
101
  		inode->i_generation == data->fid.unique;
ec26815ad   David Howells   [AFS]: Clean up t...
102
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
  /*
bec5eb614   wanglei   AFS: Implement an...
105
106
107
108
109
110
111
112
113
114
   * 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
115
116
117
118
119
120
121
122
   * 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...
123
  	inode->i_generation = data->fid.unique;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
125
126
127
  	vnode->fid = data->fid;
  	vnode->volume = data->volume;
  
  	return 0;
ec26815ad   David Howells   [AFS]: Clean up t...
128
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
  /*
bec5eb614   wanglei   AFS: Implement an...
131
132
133
134
135
136
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
   * 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 ...
174
  	set_nlink(inode, 2);
bec5eb614   wanglei   AFS: Implement an...
175
176
177
178
179
180
181
182
183
184
  	inode->i_uid		= 0;
  	inode->i_gid		= 0;
  	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...
185
186
  	set_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags);
  	inode->i_flags |= S_AUTOMOUNT | S_NOATIME;
bec5eb614   wanglei   AFS: Implement an...
187
188
189
190
191
192
  	unlock_new_inode(inode);
  	_leave(" = %p", inode);
  	return inode;
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
194
   * inode retrieval
   */
260a98031   David Howells   [AFS]: Add "direc...
195
196
197
  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
198
199
200
201
202
203
  {
  	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
204
  	_enter(",{%x:%u.%u},,", fid->vid, fid->vnode, fid->unique);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205
206
207
208
209
210
211
212
  
  	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 ...
213
  		return ERR_PTR(-ENOMEM);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
  	}
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
215
216
  	_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
217
218
219
220
  	vnode = AFS_FS_I(inode);
  
  	/* deal with an existing inode */
  	if (!(inode->i_state & I_NEW)) {
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
221
222
  		_leave(" = %p", inode);
  		return inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
  	}
260a98031   David Howells   [AFS]: Add "direc...
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
  	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;
  			vnode->cb_expires = get_seconds();
  		} else {
  			vnode->cb_version = cb->version;
  			vnode->cb_expiry = cb->expiry;
  			vnode->cb_type = cb->type;
  			vnode->cb_expires = vnode->cb_expiry + get_seconds();
  		}
  	}
9b3f26c91   David Howells   FS-Cache: Make kA...
248
249
250
251
252
253
254
255
  	/* 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,
  					      vnode);
  #endif
00d3b7a45   David Howells   [AFS]: Add securi...
256
  	ret = afs_inode_map_status(vnode, key);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
257
  	if (ret < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
259
260
  		goto bad_inode;
  
  	/* success */
260a98031   David Howells   [AFS]: Add "direc...
261
  	clear_bit(AFS_VNODE_UNSET, &vnode->flags);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
262
  	inode->i_flags |= S_NOATIME;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
  	unlock_new_inode(inode);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
264
265
  	_leave(" = %p [CB { v=%u t=%u }]", inode, vnode->cb_version, vnode->cb_type);
  	return inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
267
  
  	/* failure */
ec26815ad   David Howells   [AFS]: Clean up t...
268
  bad_inode:
9b3f26c91   David Howells   FS-Cache: Make kA...
269
270
271
272
  #ifdef CONFIG_AFS_FSCACHE
  	fscache_relinquish_cookie(vnode->cache, 0);
  	vnode->cache = NULL;
  #endif
aa7fa240c   David Howells   iget: use iget_fa...
273
  	iget_failed(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
  	_leave(" = %d [bad]", ret);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
275
  	return ERR_PTR(ret);
ec26815ad   David Howells   [AFS]: Clean up t...
276
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278
  /*
416351f28   David Howells   AFS: AFS fixups
279
280
281
282
283
   * 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...
284
  	_enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
416351f28   David Howells   AFS: AFS fixups
285
286
  
  	/* nuke all the non-dirty pages that aren't locked, mapped or being
0f300ca92   David Howells   AFS: fix a couple...
287
288
289
290
291
292
  	 * 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
293
294
295
  }
  
  /*
260a98031   David Howells   [AFS]: Add "direc...
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
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
   * 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)) {
  		if (vnode->cb_expires < get_seconds() + 10) {
  			_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
350
351
  	if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags))
  		afs_zap_data(vnode);
260a98031   David Howells   [AFS]: Add "direc...
352
353
354
355
356
357
358
359
360
361
362
363
364
365
  
  	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
366
367
   * read the attributes of an inode
   */
416351f28   David Howells   AFS: AFS fixups
368
  int afs_getattr(struct vfsmount *mnt, struct dentry *dentry,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369
370
  		      struct kstat *stat)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
  	struct inode *inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
372
373
  
  	inode = dentry->d_inode;
d6e43f751   David Howells   AFS: Use i_genera...
374
  	_enter("{ ino=%lu v=%u }", inode->i_ino, inode->i_generation);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
  	generic_fillattr(inode, stat);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377
  	return 0;
ec26815ad   David Howells   [AFS]: Clean up t...
378
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
380
  /*
bec5eb614   wanglei   AFS: Implement an...
381
382
383
384
385
386
387
388
389
390
391
392
393
   * 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
394
395
   * clear an AFS inode
   */
b57922d97   Al Viro   convert remaining...
396
  void afs_evict_inode(struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
  {
00d3b7a45   David Howells   [AFS]: Add securi...
398
  	struct afs_permits *permits;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
399
400
401
  	struct afs_vnode *vnode;
  
  	vnode = AFS_FS_I(inode);
416351f28   David Howells   AFS: AFS fixups
402
  	_enter("{%x:%u.%d} v=%u x=%u t=%u }",
260a98031   David Howells   [AFS]: Add "direc...
403
  	       vnode->fid.vid,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404
  	       vnode->fid.vnode,
260a98031   David Howells   [AFS]: Add "direc...
405
  	       vnode->fid.unique,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
407
  	       vnode->cb_version,
  	       vnode->cb_expiry,
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
408
  	       vnode->cb_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
410
411
412
  	_debug("CLEAR INODE %p", inode);
  
  	ASSERTCMP(inode->i_ino, ==, vnode->fid.vnode);
b57922d97   Al Viro   convert remaining...
413
414
  	truncate_inode_pages(&inode->i_data, 0);
  	end_writeback(inode);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
415
416
417
418
419
420
421
422
423
  	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
424

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

9b3f26c91   David Howells   FS-Cache: Make kA...
428
429
  #ifdef CONFIG_AFS_FSCACHE
  	fscache_relinquish_cookie(vnode->cache, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430
431
  	vnode->cache = NULL;
  #endif
00d3b7a45   David Howells   [AFS]: Add securi...
432
433
434
435
436
437
  	mutex_lock(&vnode->permits_lock);
  	permits = vnode->permits;
  	rcu_assign_pointer(vnode->permits, NULL);
  	mutex_unlock(&vnode->permits_lock);
  	if (permits)
  		call_rcu(&permits->rcu, afs_zap_permits);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
  	_leave("");
ec26815ad   David Howells   [AFS]: Clean up t...
439
  }
31143d5d5   David Howells   AFS: implement ba...
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
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
  
  /*
   * set the attributes of an inode
   */
  int afs_setattr(struct dentry *dentry, struct iattr *attr)
  {
  	struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
  	struct key *key;
  	int ret;
  
  	_enter("{%x:%u},{n=%s},%x",
  	       vnode->fid.vid, vnode->fid.vnode, dentry->d_name.name,
  	       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;
  }