aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/fuse/dev.c42
-rw-r--r--fs/fuse/file.c10
-rw-r--r--fs/fuse/fuse_i.h5
3 files changed, 43 insertions, 14 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 60c222517ccd..99325547604f 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -172,6 +172,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
172 fuse_putback_request() */ 172 fuse_putback_request() */
173 for (i = 1; i < FUSE_MAX_OUTSTANDING; i++) 173 for (i = 1; i < FUSE_MAX_OUTSTANDING; i++)
174 up(&fc->outstanding_sem); 174 up(&fc->outstanding_sem);
175
176 fuse_put_request(fc, req);
175} 177}
176 178
177/* 179/*
@@ -180,13 +182,15 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
180 * occurred during communication with userspace, or the device file 182 * occurred during communication with userspace, or the device file
181 * was closed. In case of a background request the reference to the 183 * was closed. In case of a background request the reference to the
182 * stored objects are released. The requester thread is woken up (if 184 * stored objects are released. The requester thread is woken up (if
183 * still waiting), and finally the reference to the request is 185 * still waiting), the 'end' callback is called if given, else the
184 * released 186 * reference to the request is released
185 * 187 *
186 * Called with fuse_lock, unlocks it 188 * Called with fuse_lock, unlocks it
187 */ 189 */
188static void request_end(struct fuse_conn *fc, struct fuse_req *req) 190static void request_end(struct fuse_conn *fc, struct fuse_req *req)
189{ 191{
192 void (*end) (struct fuse_conn *, struct fuse_req *) = req->end;
193 req->end = NULL;
190 list_del(&req->list); 194 list_del(&req->list);
191 req->state = FUSE_REQ_FINISHED; 195 req->state = FUSE_REQ_FINISHED;
192 spin_unlock(&fuse_lock); 196 spin_unlock(&fuse_lock);
@@ -197,16 +201,10 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
197 up_read(&fc->sbput_sem); 201 up_read(&fc->sbput_sem);
198 } 202 }
199 wake_up(&req->waitq); 203 wake_up(&req->waitq);
200 if (req->in.h.opcode == FUSE_INIT) 204 if (end)
201 process_init_reply(fc, req); 205 end(fc, req);
202 else if (req->in.h.opcode == FUSE_RELEASE && req->inode == NULL) { 206 else
203 /* Special case for failed iget in CREATE */ 207 fuse_put_request(fc, req);
204 u64 nodeid = req->in.h.nodeid;
205 fuse_reset_request(req);
206 fuse_send_forget(fc, req, nodeid, 1);
207 return;
208 }
209 fuse_put_request(fc, req);
210} 208}
211 209
212/* 210/*
@@ -387,6 +385,7 @@ void fuse_send_init(struct fuse_conn *fc)
387 req->out.argvar = 1; 385 req->out.argvar = 1;
388 req->out.args[0].size = sizeof(struct fuse_init_out); 386 req->out.args[0].size = sizeof(struct fuse_init_out);
389 req->out.args[0].value = &req->misc.init_out; 387 req->out.args[0].value = &req->misc.init_out;
388 req->end = process_init_reply;
390 request_send_background(fc, req); 389 request_send_background(fc, req);
391} 390}
392 391
@@ -864,17 +863,32 @@ static void end_requests(struct fuse_conn *fc, struct list_head *head)
864 * The requests are set to interrupted and finished, and the request 863 * The requests are set to interrupted and finished, and the request
865 * waiter is woken up. This will make request_wait_answer() wait 864 * waiter is woken up. This will make request_wait_answer() wait
866 * until the request is unlocked and then return. 865 * until the request is unlocked and then return.
866 *
867 * If the request is asynchronous, then the end function needs to be
868 * called after waiting for the request to be unlocked (if it was
869 * locked).
867 */ 870 */
868static void end_io_requests(struct fuse_conn *fc) 871static void end_io_requests(struct fuse_conn *fc)
869{ 872{
870 while (!list_empty(&fc->io)) { 873 while (!list_empty(&fc->io)) {
871 struct fuse_req *req; 874 struct fuse_req *req =
872 req = list_entry(fc->io.next, struct fuse_req, list); 875 list_entry(fc->io.next, struct fuse_req, list);
876 void (*end) (struct fuse_conn *, struct fuse_req *) = req->end;
877
873 req->interrupted = 1; 878 req->interrupted = 1;
874 req->out.h.error = -ECONNABORTED; 879 req->out.h.error = -ECONNABORTED;
875 req->state = FUSE_REQ_FINISHED; 880 req->state = FUSE_REQ_FINISHED;
876 list_del_init(&req->list); 881 list_del_init(&req->list);
877 wake_up(&req->waitq); 882 wake_up(&req->waitq);
883 if (end) {
884 req->end = NULL;
885 /* The end function will consume this reference */
886 __fuse_get_request(req);
887 spin_unlock(&fuse_lock);
888 wait_event(req->waitq, !req->locked);
889 end(fc, req);
890 spin_lock(&fuse_lock);
891 }
878 } 892 }
879} 893}
880 894
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 52557664a89e..043d5b36846d 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -113,6 +113,14 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir)
113 return err; 113 return err;
114} 114}
115 115
116/* Special case for failed iget in CREATE */
117static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req)
118{
119 u64 nodeid = req->in.h.nodeid;
120 fuse_reset_request(req);
121 fuse_send_forget(fc, req, nodeid, 1);
122}
123
116void fuse_send_release(struct fuse_conn *fc, struct fuse_file *ff, 124void fuse_send_release(struct fuse_conn *fc, struct fuse_file *ff,
117 u64 nodeid, struct inode *inode, int flags, int isdir) 125 u64 nodeid, struct inode *inode, int flags, int isdir)
118{ 126{
@@ -128,6 +136,8 @@ void fuse_send_release(struct fuse_conn *fc, struct fuse_file *ff,
128 req->in.args[0].size = sizeof(struct fuse_release_in); 136 req->in.args[0].size = sizeof(struct fuse_release_in);
129 req->in.args[0].value = inarg; 137 req->in.args[0].value = inarg;
130 request_send_background(fc, req); 138 request_send_background(fc, req);
139 if (!inode)
140 req->end = fuse_release_end;
131 kfree(ff); 141 kfree(ff);
132} 142}
133 143
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index e6381db41df9..145098056ca6 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -120,6 +120,8 @@ enum fuse_req_state {
120 FUSE_REQ_FINISHED 120 FUSE_REQ_FINISHED
121}; 121};
122 122
123struct fuse_conn;
124
123/** 125/**
124 * A request to the client 126 * A request to the client
125 */ 127 */
@@ -186,6 +188,9 @@ struct fuse_req {
186 188
187 /** File used in the request (or NULL) */ 189 /** File used in the request (or NULL) */
188 struct file *file; 190 struct file *file;
191
192 /** Request completion callback */
193 void (*end)(struct fuse_conn *, struct fuse_req *);
189}; 194};
190 195
191/** 196/**