Merge branch 'stable-3.2' into pandora-3.2
[pandora-kernel.git] / fs / aufs / f_op_sp.c
1 /*
2  * Copyright (C) 2005-2012 Junjiro R. Okajima
3  *
4  * This program, aufs is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18
19 /*
20  * file operations for special files.
21  * while they exist in aufs virtually,
22  * their file I/O is handled out of aufs.
23  */
24
25 #include "aufs.h"
26
27 static ssize_t aufs_aio_read_sp(struct kiocb *kio, const struct iovec *iov,
28                                 unsigned long nv, loff_t pos)
29 {
30         ssize_t err;
31         aufs_bindex_t bstart;
32         unsigned char wbr;
33         struct file *file, *h_file;
34         struct super_block *sb;
35
36         file = kio->ki_filp;
37         sb = file->f_dentry->d_sb;
38         si_read_lock(sb, AuLock_FLUSH);
39         fi_read_lock(file);
40         bstart = au_fbstart(file);
41         h_file = au_hf_top(file);
42         fi_read_unlock(file);
43         wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
44         si_read_unlock(sb);
45
46         /* do not change the file in kio */
47         AuDebugOn(!h_file->f_op || !h_file->f_op->aio_read);
48         err = h_file->f_op->aio_read(kio, iov, nv, pos);
49         if (err > 0 && wbr)
50                 file_accessed(h_file);
51
52         return err;
53 }
54
55 static ssize_t aufs_aio_write_sp(struct kiocb *kio, const struct iovec *iov,
56                                  unsigned long nv, loff_t pos)
57 {
58         ssize_t err;
59         aufs_bindex_t bstart;
60         unsigned char wbr;
61         struct super_block *sb;
62         struct file *file, *h_file;
63
64         file = kio->ki_filp;
65         sb = file->f_dentry->d_sb;
66         si_read_lock(sb, AuLock_FLUSH);
67         fi_read_lock(file);
68         bstart = au_fbstart(file);
69         h_file = au_hf_top(file);
70         fi_read_unlock(file);
71         wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
72         si_read_unlock(sb);
73
74         /* do not change the file in kio */
75         AuDebugOn(!h_file->f_op || !h_file->f_op->aio_write);
76         err = h_file->f_op->aio_write(kio, iov, nv, pos);
77         if (err > 0 && wbr)
78                 file_update_time(h_file);
79
80         return err;
81 }
82
83 /* ---------------------------------------------------------------------- */
84
85 static int aufs_release_sp(struct inode *inode, struct file *file)
86 {
87         int err;
88         struct file *h_file;
89
90         fi_read_lock(file);
91         h_file = au_hf_top(file);
92         fi_read_unlock(file);
93         /* close this fifo in aufs */
94         err = h_file->f_op->release(inode, file); /* ignore */
95         aufs_release_nondir(inode, file); /* ignore */
96         return err;
97 }
98
99 /* ---------------------------------------------------------------------- */
100
101 /* currently, support only FIFO */
102 enum {
103         AuSp_FIFO, AuSp_FIFO_R, AuSp_FIFO_W, AuSp_FIFO_RW,
104         /* AuSp_SOCK, AuSp_CHR, AuSp_BLK, */
105         AuSp_Last
106 };
107 static int aufs_open_sp(struct inode *inode, struct file *file);
108 static struct au_sp_fop {
109         int                     done;
110         struct file_operations  fop;    /* not 'const' */
111         spinlock_t              spin;
112 } au_sp_fop[AuSp_Last] = {
113         [AuSp_FIFO] = {
114                 .fop    = {
115                         .owner  = THIS_MODULE,
116                         .open   = aufs_open_sp
117                 }
118         }
119 };
120
121 static void au_init_fop_sp(struct file *file)
122 {
123         struct au_sp_fop *p;
124         int i;
125         struct file *h_file;
126
127         p = au_sp_fop;
128         if (unlikely(!p->done)) {
129                 /* initialize first time only */
130                 static DEFINE_SPINLOCK(spin);
131
132                 spin_lock(&spin);
133                 if (!p->done) {
134                         BUILD_BUG_ON(sizeof(au_sp_fop)/sizeof(*au_sp_fop)
135                                      != AuSp_Last);
136                         for (i = 0; i < AuSp_Last; i++)
137                                 spin_lock_init(&p[i].spin);
138                         p->done = 1;
139                 }
140                 spin_unlock(&spin);
141         }
142
143         switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
144         case FMODE_READ:
145                 i = AuSp_FIFO_R;
146                 break;
147         case FMODE_WRITE:
148                 i = AuSp_FIFO_W;
149                 break;
150         case FMODE_READ | FMODE_WRITE:
151                 i = AuSp_FIFO_RW;
152                 break;
153         default:
154                 BUG();
155         }
156
157         p += i;
158         if (unlikely(!p->done)) {
159                 /* initialize first time only */
160                 h_file = au_hf_top(file);
161                 spin_lock(&p->spin);
162                 if (!p->done) {
163                         p->fop = *h_file->f_op;
164                         p->fop.owner = THIS_MODULE;
165                         if (p->fop.aio_read)
166                                 p->fop.aio_read = aufs_aio_read_sp;
167                         if (p->fop.aio_write)
168                                 p->fop.aio_write = aufs_aio_write_sp;
169                         p->fop.release = aufs_release_sp;
170                         p->done = 1;
171                 }
172                 spin_unlock(&p->spin);
173         }
174         file->f_op = &p->fop;
175 }
176
177 static int au_cpup_sp(struct dentry *dentry)
178 {
179         int err;
180         aufs_bindex_t bcpup;
181         struct au_pin pin;
182         struct au_wr_dir_args wr_dir_args = {
183                 .force_btgt     = -1,
184                 .flags          = 0
185         };
186
187         AuDbg("%.*s\n", AuDLNPair(dentry));
188
189         di_read_unlock(dentry, AuLock_IR);
190         di_write_lock_child(dentry);
191         err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
192         if (unlikely(err < 0))
193                 goto out;
194         bcpup = err;
195         err = 0;
196         if (bcpup == au_dbstart(dentry))
197                 goto out; /* success */
198
199         err = au_pin(&pin, dentry, bcpup, au_opt_udba(dentry->d_sb),
200                      AuPin_MNT_WRITE);
201         if (!err) {
202                 err = au_sio_cpup_simple(dentry, bcpup, -1, AuCpup_DTIME);
203                 au_unpin(&pin);
204         }
205
206 out:
207         di_downgrade_lock(dentry, AuLock_IR);
208         return err;
209 }
210
211 static int au_do_open_sp(struct file *file, int flags)
212 {
213         int err;
214         struct dentry *dentry;
215         struct super_block *sb;
216         struct file *h_file;
217         struct inode *h_inode;
218
219         dentry = file->f_dentry;
220         AuDbg("%.*s\n", AuDLNPair(dentry));
221
222         /*
223          * try copying-up.
224          * operate on the ro branch is not an error.
225          */
226         au_cpup_sp(dentry); /* ignore */
227
228         /* prepare h_file */
229         err = au_do_open_nondir(file, vfsub_file_flags(file));
230         if (unlikely(err))
231                 goto out;
232
233         sb = dentry->d_sb;
234         h_file = au_hf_top(file);
235         h_inode = h_file->f_dentry->d_inode;
236         di_read_unlock(dentry, AuLock_IR);
237         fi_write_unlock(file);
238         si_read_unlock(sb);
239         /* open this fifo in aufs */
240         err = h_inode->i_fop->open(file->f_dentry->d_inode, file);
241         si_noflush_read_lock(sb);
242         fi_write_lock(file);
243         di_read_lock_child(dentry, AuLock_IR);
244         if (!err)
245                 au_init_fop_sp(file);
246
247 out:
248         return err;
249 }
250
251 static int aufs_open_sp(struct inode *inode, struct file *file)
252 {
253         int err;
254         struct super_block *sb;
255
256         sb = file->f_dentry->d_sb;
257         si_read_lock(sb, AuLock_FLUSH);
258         err = au_do_open(file, au_do_open_sp, /*fidir*/NULL);
259         si_read_unlock(sb);
260         return err;
261 }
262
263 /* ---------------------------------------------------------------------- */
264
265 void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev)
266 {
267         init_special_inode(inode, mode, rdev);
268
269         switch (mode & S_IFMT) {
270         case S_IFIFO:
271                 inode->i_fop = &au_sp_fop[AuSp_FIFO].fop;
272                 /*FALLTHROUGH*/
273         case S_IFCHR:
274         case S_IFBLK:
275         case S_IFSOCK:
276                 break;
277         default:
278                 AuDebugOn(1);
279         }
280 }
281
282 int au_special_file(umode_t mode)
283 {
284         int ret;
285
286         ret = 0;
287         switch (mode & S_IFMT) {
288         case S_IFIFO:
289 #if 0
290         case S_IFCHR:
291         case S_IFBLK:
292         case S_IFSOCK:
293 #endif
294                 ret = 1;
295         }
296
297         return ret;
298 }