4 * Copyright (C) 1992 Rick Sladkey
7 #include <linux/falloc.h>
8 #include <linux/nfs_fs.h>
9 #include "delegation.h"
17 #ifdef CONFIG_NFS_V4_2
21 #define NFSDBG_FACILITY NFSDBG_FILE
24 nfs4_file_open(struct inode
*inode
, struct file
*filp
)
26 struct nfs_open_context
*ctx
;
27 struct dentry
*dentry
= filp
->f_path
.dentry
;
28 struct dentry
*parent
= NULL
;
30 unsigned openflags
= filp
->f_flags
;
35 * If no cached dentry exists or if it's negative, NFSv4 handled the
36 * opens in ->lookup() or ->create().
38 * We only get this far for a cached positive dentry. We skipped
39 * revalidation, so handle it here by dropping the dentry and returning
40 * -EOPENSTALE. The VFS will retry the lookup/create/open.
43 dprintk("NFS: open file(%pd2)\n", dentry
);
45 err
= nfs_check_flags(openflags
);
49 if ((openflags
& O_ACCMODE
) == 3)
52 /* We can't create new files here */
53 openflags
&= ~(O_CREAT
|O_EXCL
);
55 parent
= dget_parent(dentry
);
56 dir
= d_inode(parent
);
58 ctx
= alloc_nfs_open_context(filp
->f_path
.dentry
, filp
->f_mode
);
63 attr
.ia_valid
= ATTR_OPEN
;
64 if (openflags
& O_TRUNC
) {
65 attr
.ia_valid
|= ATTR_SIZE
;
67 nfs_sync_inode(inode
);
70 inode
= NFS_PROTO(dir
)->open_context(dir
, ctx
, openflags
, &attr
, NULL
);
84 if (inode
!= d_inode(dentry
))
87 nfs_set_verifier(dentry
, nfs_save_change_attribute(dir
));
88 nfs_file_set_open_context(filp
, ctx
);
89 nfs_fscache_open_file(inode
, filp
);
93 put_nfs_open_context(ctx
);
105 * Flush all dirty pages, and check for write errors.
108 nfs4_file_flush(struct file
*file
, fl_owner_t id
)
110 struct inode
*inode
= file_inode(file
);
112 dprintk("NFS: flush(%pD2)\n", file
);
114 nfs_inc_stats(inode
, NFSIOS_VFSFLUSH
);
115 if ((file
->f_mode
& FMODE_WRITE
) == 0)
119 * If we're holding a write delegation, then check if we're required
120 * to flush the i/o on close. If not, then just start the i/o now.
122 if (!nfs4_delegation_flush_on_close(inode
))
123 return filemap_fdatawrite(file
->f_mapping
);
125 /* Flush writes to the server and return any errors */
126 return vfs_fsync(file
, 0);
130 nfs4_file_fsync(struct file
*file
, loff_t start
, loff_t end
, int datasync
)
133 struct inode
*inode
= file_inode(file
);
135 trace_nfs_fsync_enter(inode
);
137 nfs_inode_dio_wait(inode
);
139 ret
= filemap_write_and_wait_range(inode
->i_mapping
, start
, end
);
142 mutex_lock(&inode
->i_mutex
);
143 ret
= nfs_file_fsync_commit(file
, start
, end
, datasync
);
145 ret
= pnfs_sync_inode(inode
, !!datasync
);
146 mutex_unlock(&inode
->i_mutex
);
148 * If nfs_file_fsync_commit detected a server reboot, then
149 * resend all dirty pages that might have been covered by
150 * the NFS_CONTEXT_RESEND_WRITES flag
154 } while (ret
== -EAGAIN
);
156 trace_nfs_fsync_exit(inode
, ret
);
160 #ifdef CONFIG_NFS_V4_2
161 static loff_t
nfs4_file_llseek(struct file
*filep
, loff_t offset
, int whence
)
168 ret
= nfs42_proc_llseek(filep
, offset
, whence
);
169 if (ret
!= -ENOTSUPP
)
172 return nfs_file_llseek(filep
, offset
, whence
);
176 static long nfs42_fallocate(struct file
*filep
, int mode
, loff_t offset
, loff_t len
)
178 struct inode
*inode
= file_inode(filep
);
181 if (!S_ISREG(inode
->i_mode
))
184 if ((mode
!= 0) && (mode
!= (FALLOC_FL_PUNCH_HOLE
| FALLOC_FL_KEEP_SIZE
)))
187 ret
= inode_newsize_ok(inode
, offset
+ len
);
191 if (mode
& FALLOC_FL_PUNCH_HOLE
)
192 return nfs42_proc_deallocate(filep
, offset
, len
);
193 return nfs42_proc_allocate(filep
, offset
, len
);
195 #endif /* CONFIG_NFS_V4_2 */
197 const struct file_operations nfs4_file_operations
= {
198 #ifdef CONFIG_NFS_V4_2
199 .llseek
= nfs4_file_llseek
,
201 .llseek
= nfs_file_llseek
,
203 .read_iter
= nfs_file_read
,
204 .write_iter
= nfs_file_write
,
205 .mmap
= nfs_file_mmap
,
206 .open
= nfs4_file_open
,
207 .flush
= nfs4_file_flush
,
208 .release
= nfs_file_release
,
209 .fsync
= nfs4_file_fsync
,
212 .splice_read
= nfs_file_splice_read
,
213 .splice_write
= iter_file_splice_write
,
214 #ifdef CONFIG_NFS_V4_2
215 .fallocate
= nfs42_fallocate
,
216 #endif /* CONFIG_NFS_V4_2 */
217 .check_flags
= nfs_check_flags
,
218 .setlease
= simple_nosetlease
,