aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p/vfs_file.c
diff options
context:
space:
mode:
authorLatchesar Ionkov <lucho@ionkov.net>2006-03-02 05:54:30 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-02 11:33:07 -0500
commit6a3124a3946c16159c3faf83e62ffdb5d1134b3a (patch)
tree989f1e89ed0971824db973af5347b879e12c67cd /fs/9p/vfs_file.c
parent77a3313551afd53c90012e5a87f7f2b2195fc67e (diff)
[PATCH] v9fs: fix atomic create open
In order to assure atomic create+open v9fs stores the open fid produced by v9fs_vfs_create in the dentry, from where v9fs_file_open retrieves it and associates it with the open file. This patch modifies v9fs to use nameidata.intent.open values to do the atomic create+open. Signed-off-by: Latchesar Ionkov <lucho@ionkov.net> Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/9p/vfs_file.c')
-rw-r--r--fs/9p/vfs_file.c106
1 files changed, 40 insertions, 66 deletions
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index c7e14d917215..de3a129698da 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -53,94 +53,70 @@
53int v9fs_file_open(struct inode *inode, struct file *file) 53int v9fs_file_open(struct inode *inode, struct file *file)
54{ 54{
55 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); 55 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
56 struct v9fs_fid *v9fid, *fid; 56 struct v9fs_fid *vfid;
57 struct v9fs_fcall *fcall = NULL; 57 struct v9fs_fcall *fcall = NULL;
58 int open_mode = 0; 58 int omode;
59 unsigned int iounit = 0; 59 int fid = V9FS_NOFID;
60 int newfid = -1; 60 int err;
61 long result = -1;
62 61
63 dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file); 62 dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file);
64 63
65 v9fid = v9fs_fid_get_created(file->f_dentry); 64 vfid = v9fs_fid_lookup(file->f_dentry);
66 if (!v9fid) 65 if (!vfid) {
67 v9fid = v9fs_fid_lookup(file->f_dentry);
68
69 if (!v9fid) {
70 dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n"); 66 dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n");
71 return -EBADF; 67 return -EBADF;
72 } 68 }
73 69
74 if (!v9fid->fidcreate) { 70 fid = v9fs_get_idpool(&v9ses->fidpool);
75 fid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); 71 if (fid < 0) {
76 if (fid == NULL) {
77 dprintk(DEBUG_ERROR, "Out of Memory\n");
78 return -ENOMEM;
79 }
80
81 fid->fidopen = 0;
82 fid->fidcreate = 0;
83 fid->fidclunked = 0;
84 fid->iounit = 0;
85 fid->v9ses = v9ses;
86
87 newfid = v9fs_get_idpool(&v9ses->fidpool);
88 if (newfid < 0) {
89 eprintk(KERN_WARNING, "newfid fails!\n"); 72 eprintk(KERN_WARNING, "newfid fails!\n");
90 return -ENOSPC; 73 return -ENOSPC;
91 } 74 }
92 75
93 result = 76 err = v9fs_t_walk(v9ses, vfid->fid, fid, NULL, NULL);
94 v9fs_t_walk(v9ses, v9fid->fid, newfid, NULL, NULL); 77 if (err < 0) {
95
96 if (result < 0) {
97 v9fs_put_idpool(newfid, &v9ses->fidpool);
98 dprintk(DEBUG_ERROR, "rewalk didn't work\n"); 78 dprintk(DEBUG_ERROR, "rewalk didn't work\n");
99 return -EBADF; 79 goto put_fid;
80 }
81
82 vfid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL);
83 if (vfid == NULL) {
84 dprintk(DEBUG_ERROR, "out of memory\n");
85 goto clunk_fid;
100 } 86 }
101 87
102 fid->fid = newfid;
103 v9fid = fid;
104 /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */ 88 /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */
105 /* translate open mode appropriately */ 89 /* translate open mode appropriately */
106 open_mode = file->f_flags & 0x3; 90 omode = v9fs_uflags2omode(file->f_flags);
91 err = v9fs_t_open(v9ses, fid, omode, &fcall);
92 if (err < 0) {
93 PRINT_FCALL_ERROR("open failed", fcall);
94 goto destroy_vfid;
95 }
107 96
108 if (file->f_flags & O_EXCL) 97 file->private_data = vfid;
109 open_mode |= V9FS_OEXCL; 98 vfid->fid = fid;
99 vfid->fidopen = 1;
100 vfid->fidclunked = 0;
101 vfid->iounit = fcall->params.ropen.iounit;
102 vfid->rdir_pos = 0;
103 vfid->rdir_fcall = NULL;
104 vfid->filp = file;
105 kfree(fcall);
110 106
111 if (v9ses->extended) { 107 return 0;
112 if (file->f_flags & O_TRUNC)
113 open_mode |= V9FS_OTRUNC;
114 108
115 if (file->f_flags & O_APPEND) 109destroy_vfid:
116 open_mode |= V9FS_OAPPEND; 110 v9fs_fid_destroy(vfid);
117 }
118 111
119 result = v9fs_t_open(v9ses, newfid, open_mode, &fcall); 112clunk_fid:
120 if (result < 0) { 113 v9fs_t_clunk(v9ses, fid);
121 PRINT_FCALL_ERROR("open failed", fcall);
122 kfree(fcall);
123 return result;
124 }
125 114
126 iounit = fcall->params.ropen.iounit; 115put_fid:
116 v9fs_put_idpool(fid, &v9ses->fidpool);
127 kfree(fcall); 117 kfree(fcall);
128 } else {
129 /* create case */
130 newfid = v9fid->fid;
131 iounit = v9fid->iounit;
132 v9fid->fidcreate = 0;
133 }
134
135 file->private_data = v9fid;
136
137 v9fid->rdir_pos = 0;
138 v9fid->rdir_fcall = NULL;
139 v9fid->fidopen = 1;
140 v9fid->filp = file;
141 v9fid->iounit = iounit;
142 118
143 return 0; 119 return err;
144} 120}
145 121
146/** 122/**
@@ -289,9 +265,7 @@ v9fs_file_write(struct file *filp, const char __user * data,
289 total += result; 265 total += result;
290 } while (count); 266 } while (count);
291 267
292 if(inode->i_mapping->nrpages)
293 invalidate_inode_pages2(inode->i_mapping); 268 invalidate_inode_pages2(inode->i_mapping);
294
295 return total; 269 return total;
296} 270}
297 271