Merge branch 'stable-3.2' into pandora-3.2
[pandora-kernel.git] / fs / aufs / f_op_sp.c
1 /*
2  * Copyright (C) 2005-2013 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         struct au_pin pin;
181         struct au_wr_dir_args wr_dir_args = {
182                 .force_btgt     = -1,
183                 .flags          = 0
184         };
185         struct au_cp_generic cpg = {
186                 .dentry = dentry,
187                 .bdst   = -1,
188                 .bsrc   = -1,
189                 .len    = -1,
190                 .pin    = &pin,
191                 .flags  = AuCpup_DTIME
192         };
193
194         AuDbg("%.*s\n", AuDLNPair(dentry));
195
196         di_read_unlock(dentry, AuLock_IR);
197         di_write_lock_child(dentry);
198         err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
199         if (unlikely(err < 0))
200                 goto out;
201         cpg.bdst = err;
202         err = 0;
203         if (cpg.bdst == au_dbstart(dentry))
204                 goto out; /* success */
205
206         err = au_pin(&pin, dentry, cpg.bdst, au_opt_udba(dentry->d_sb),
207                      AuPin_MNT_WRITE);
208         if (!err) {
209                 err = au_sio_cpup_simple(&cpg);
210                 au_unpin(&pin);
211         }
212
213 out:
214         di_downgrade_lock(dentry, AuLock_IR);
215         return err;
216 }
217
218 static int au_do_open_sp(struct file *file, int flags)
219 {
220         int err;
221         struct dentry *dentry;
222         struct super_block *sb;
223         struct file *h_file;
224         struct inode *h_inode;
225
226         dentry = file->f_dentry;
227         AuDbg("%.*s\n", AuDLNPair(dentry));
228
229         /*
230          * try copying-up.
231          * operate on the ro branch is not an error.
232          */
233         au_cpup_sp(dentry); /* ignore */
234
235         /* prepare h_file */
236         err = au_do_open_nondir(file, vfsub_file_flags(file));
237         if (unlikely(err))
238                 goto out;
239
240         sb = dentry->d_sb;
241         h_file = au_hf_top(file);
242         h_inode = h_file->f_dentry->d_inode;
243         di_read_unlock(dentry, AuLock_IR);
244         fi_write_unlock(file);
245         si_read_unlock(sb);
246         /* open this fifo in aufs */
247         err = h_inode->i_fop->open(file->f_dentry->d_inode, file);
248         si_noflush_read_lock(sb);
249         fi_write_lock(file);
250         di_read_lock_child(dentry, AuLock_IR);
251         if (!err)
252                 au_init_fop_sp(file);
253
254 out:
255         return err;
256 }
257
258 static int aufs_open_sp(struct inode *inode, struct file *file)
259 {
260         int err;
261         struct super_block *sb;
262
263         sb = file->f_dentry->d_sb;
264         si_read_lock(sb, AuLock_FLUSH);
265         err = au_do_open(file, au_do_open_sp, /*fidir*/NULL);
266         si_read_unlock(sb);
267         return err;
268 }
269
270 /* ---------------------------------------------------------------------- */
271
272 void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev)
273 {
274         init_special_inode(inode, mode, rdev);
275
276         switch (mode & S_IFMT) {
277         case S_IFIFO:
278                 inode->i_fop = &au_sp_fop[AuSp_FIFO].fop;
279                 /*FALLTHROUGH*/
280         case S_IFCHR:
281         case S_IFBLK:
282         case S_IFSOCK:
283                 break;
284         default:
285                 AuDebugOn(1);
286         }
287 }
288
289 int au_special_file(umode_t mode)
290 {
291         int ret;
292
293         ret = 0;
294         switch (mode & S_IFMT) {
295         case S_IFIFO:
296 #if 0
297         case S_IFCHR:
298         case S_IFBLK:
299         case S_IFSOCK:
300 #endif
301                 ret = 1;
302         }
303
304         return ret;
305 }