Blame view

fs/coda/cnode.c 4.68 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
  /* cnode related routines for the coda kernel code
     (C) 1996 Peter Braam
     */
  
  #include <linux/types.h>
  #include <linux/string.h>
  #include <linux/time.h>
  
  #include <linux/coda.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
  #include <linux/coda_psdev.h>
31a203df9   Al Viro   take coda-private...
11
  #include "coda_linux.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
16
  
  static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2)
  {
  	return memcmp(fid1, fid2, sizeof(*fid1)) == 0;
  }
754661f14   Arjan van de Ven   [PATCH] mark stru...
17
  static const struct inode_operations coda_symlink_inode_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  	.readlink	= generic_readlink,
  	.follow_link	= page_follow_link_light,
  	.put_link	= page_put_link,
  	.setattr	= coda_setattr,
  };
  
  /* cnode.c */
  static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr)
  {
          coda_vattr_to_iattr(inode, attr);
  
          if (S_ISREG(inode->i_mode)) {
                  inode->i_op = &coda_file_inode_operations;
                  inode->i_fop = &coda_file_operations;
          } else if (S_ISDIR(inode->i_mode)) {
                  inode->i_op = &coda_dir_inode_operations;
                  inode->i_fop = &coda_dir_operations;
          } else if (S_ISLNK(inode->i_mode)) {
  		inode->i_op = &coda_symlink_inode_operations;
  		inode->i_data.a_ops = &coda_symlink_aops;
  		inode->i_mapping = &inode->i_data;
  	} else
                  init_special_inode(inode, inode->i_mode, huge_decode_dev(attr->va_rdev));
  }
  
  static int coda_test_inode(struct inode *inode, void *data)
  {
  	struct CodaFid *fid = (struct CodaFid *)data;
b5ce1d83a   Yoshihisa Abe   Coda: add spin lo...
46
47
  	struct coda_inode_info *cii = ITOC(inode);
  	return coda_fideq(&cii->c_fid, fid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
50
51
52
  }
  
  static int coda_set_inode(struct inode *inode, void *data)
  {
  	struct CodaFid *fid = (struct CodaFid *)data;
b5ce1d83a   Yoshihisa Abe   Coda: add spin lo...
53
54
  	struct coda_inode_info *cii = ITOC(inode);
  	cii->c_fid = *fid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
56
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  struct inode * coda_iget(struct super_block * sb, struct CodaFid * fid,
  			 struct coda_vattr * attr)
  {
  	struct inode *inode;
  	struct coda_inode_info *cii;
  	unsigned long hash = coda_f2i(fid);
  
  	inode = iget5_locked(sb, hash, coda_test_inode, coda_set_inode, fid);
  
  	if (!inode)
  		return ERR_PTR(-ENOMEM);
  
  	if (inode->i_state & I_NEW) {
  		cii = ITOC(inode);
  		/* we still need to set i_ino for things like stat(2) */
  		inode->i_ino = hash;
b5ce1d83a   Yoshihisa Abe   Coda: add spin lo...
73
  		/* inode is locked and unique, no need to grab cii->c_lock */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  		cii->c_mapcount = 0;
  		unlock_new_inode(inode);
  	}
  
  	/* always replace the attributes, type might have changed */
  	coda_fill_inode(inode, attr);
  	return inode;
  }
  
  /* this is effectively coda_iget:
     - get attributes (might be cached)
     - get the inode for the fid using vfs iget
     - link the two up if this is needed
     - fill in the attributes
  */
f4947fbce   Al Viro   coda: switch coda...
89
  struct inode *coda_cnode_make(struct CodaFid *fid, struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
  {
          struct coda_vattr attr;
f4947fbce   Al Viro   coda: switch coda...
92
  	struct inode *inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
94
95
96
          int error;
          
  	/* We get inode numbers from Venus -- see venus source */
  	error = venus_getattr(sb, fid, &attr);
f4947fbce   Al Viro   coda: switch coda...
97
98
  	if (error)
  		return ERR_PTR(error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99

f4947fbce   Al Viro   coda: switch coda...
100
101
  	inode = coda_iget(sb, fid, &attr);
  	if (IS_ERR(inode))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
103
  		printk("coda_cnode_make: coda_iget failed
  ");
f4947fbce   Al Viro   coda: switch coda...
104
  	return inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
  }
b5ce1d83a   Yoshihisa Abe   Coda: add spin lo...
106
107
108
109
110
111
112
113
  /* Although we treat Coda file identifiers as immutable, there is one
   * special case for files created during a disconnection where they may
   * not be globally unique. When an identifier collision is detected we
   * first try to flush the cached inode from the kernel and finally
   * resort to renaming/rehashing in-place. Userspace remembers both old
   * and new values of the identifier to handle any in-flight upcalls.
   * The real solution is to use globally unique UUIDs as identifiers, but
   * retrofitting the existing userspace code for this is non-trivial. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
115
116
  void coda_replace_fid(struct inode *inode, struct CodaFid *oldfid, 
  		      struct CodaFid *newfid)
  {
b5ce1d83a   Yoshihisa Abe   Coda: add spin lo...
117
  	struct coda_inode_info *cii = ITOC(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
119
  	unsigned long hash = coda_f2i(newfid);
  	
c5d3237c2   Eric Sesterhenn   BUG_ON() Conversi...
120
  	BUG_ON(!coda_fideq(&cii->c_fid, oldfid));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
  
  	/* replace fid and rehash inode */
  	/* XXX we probably need to hold some lock here! */
  	remove_inode_hash(inode);
  	cii->c_fid = *newfid;
  	inode->i_ino = hash;
  	__insert_inode_hash(inode, hash);
  }
  
  /* convert a fid to an inode. */
  struct inode *coda_fid_to_inode(struct CodaFid *fid, struct super_block *sb) 
  {
  	struct inode *inode;
  	unsigned long hash = coda_f2i(fid);
  
  	if ( !sb ) {
  		printk("coda_fid_to_inode: no sb!
  ");
  		return NULL;
  	}
ed31a7dd6   Jan Harkes   coda: use ilookup5
141
  	inode = ilookup5(sb, hash, coda_test_inode, fid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
143
144
145
146
147
148
149
150
151
152
  	if ( !inode )
  		return NULL;
  
  	/* we should never see newly created inodes because we intentionally
  	 * fail in the initialization callback */
  	BUG_ON(inode->i_state & I_NEW);
  
  	return inode;
  }
  
  /* the CONTROL inode is made without asking attributes from Venus */
0b2c4e39c   Al Viro   coda: deal correc...
153
  struct inode *coda_cnode_makectl(struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
  {
0b2c4e39c   Al Viro   coda: deal correc...
155
156
157
158
159
160
161
  	struct inode *inode = new_inode(sb);
  	if (inode) {
  		inode->i_ino = CTL_INO;
  		inode->i_op = &coda_ioctl_inode_operations;
  		inode->i_fop = &coda_ioctl_operations;
  		inode->i_mode = 0444;
  		return inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
  	}
0b2c4e39c   Al Viro   coda: deal correc...
163
  	return ERR_PTR(-ENOMEM);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
  }