Blame view
fs/nfs/nfs4file.c
5.87 KB
ce4ef7c0a NFS: Split out NF... |
1 2 3 4 5 |
/* * linux/fs/nfs/file.c * * Copyright (C) 1992 Rick Sladkey */ |
f4ac1674f nfs: Add ALLOCATE... |
6 |
#include <linux/fs.h> |
bea51b30b nfs42: add NFS_IO... |
7 |
#include <linux/file.h> |
f4ac1674f nfs: Add ALLOCATE... |
8 |
#include <linux/falloc.h> |
ce4ef7c0a NFS: Split out NF... |
9 |
#include <linux/nfs_fs.h> |
0f42a6a9b nfs: use btrfs io... |
10 |
#include <uapi/linux/btrfs.h> /* BTRFS_IOC_CLONE/BTRFS_IOC_CLONE_RANGE */ |
5445b1fbd NFSv4: Respect th... |
11 |
#include "delegation.h" |
ce4ef7c0a NFS: Split out NF... |
12 |
#include "internal.h" |
5445b1fbd NFSv4: Respect th... |
13 |
#include "iostat.h" |
a4ff14688 NFS4: Open files ... |
14 |
#include "fscache.h" |
ce4ef7c0a NFS: Split out NF... |
15 |
#include "pnfs.h" |
81b79afb5 NFSv4: Allow trac... |
16 |
#include "nfstrace.h" |
1c6dcbe5c NFS: Implement SEEK |
17 18 19 |
#ifdef CONFIG_NFS_V4_2 #include "nfs42.h" #endif |
ce4ef7c0a NFS: Split out NF... |
20 21 22 23 24 25 |
#define NFSDBG_FACILITY NFSDBG_FILE static int nfs4_file_open(struct inode *inode, struct file *filp) { struct nfs_open_context *ctx; |
be62a1a8f nfs: use file_den... |
26 |
struct dentry *dentry = file_dentry(filp); |
ce4ef7c0a NFS: Split out NF... |
27 28 29 30 31 |
struct dentry *parent = NULL; struct inode *dir; unsigned openflags = filp->f_flags; struct iattr attr; int err; |
ce4ef7c0a NFS: Split out NF... |
32 33 34 35 36 37 38 39 |
/* * If no cached dentry exists or if it's negative, NFSv4 handled the * opens in ->lookup() or ->create(). * * We only get this far for a cached positive dentry. We skipped * revalidation, so handle it here by dropping the dentry and returning * -EOPENSTALE. The VFS will retry the lookup/create/open. */ |
6de1472f1 nfs: use %p[dD] i... |
40 41 |
dprintk("NFS: open file(%pd2) ", dentry); |
ce4ef7c0a NFS: Split out NF... |
42 |
|
18a600897 nfs: verify open ... |
43 44 45 |
err = nfs_check_flags(openflags); if (err) return err; |
ce4ef7c0a NFS: Split out NF... |
46 47 48 49 50 51 52 |
if ((openflags & O_ACCMODE) == 3) openflags--; /* We can't create new files here */ openflags &= ~(O_CREAT|O_EXCL); parent = dget_parent(dentry); |
2b0143b5c VFS: normal files... |
53 |
dir = d_inode(parent); |
ce4ef7c0a NFS: Split out NF... |
54 |
|
be62a1a8f nfs: use file_den... |
55 |
ctx = alloc_nfs_open_context(file_dentry(filp), filp->f_mode); |
ce4ef7c0a NFS: Split out NF... |
56 57 58 59 60 61 62 63 |
err = PTR_ERR(ctx); if (IS_ERR(ctx)) goto out; attr.ia_valid = ATTR_OPEN; if (openflags & O_TRUNC) { attr.ia_valid |= ATTR_SIZE; attr.ia_size = 0; |
9e1681c2e NFSv4: Truncating... |
64 |
nfs_sync_inode(inode); |
ce4ef7c0a NFS: Split out NF... |
65 |
} |
c5c3fb5f9 NFS: Make opened ... |
66 |
inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr, NULL); |
ce4ef7c0a NFS: Split out NF... |
67 68 69 70 71 72 73 74 75 76 77 78 79 |
if (IS_ERR(inode)) { err = PTR_ERR(inode); switch (err) { case -EPERM: case -EACCES: case -EDQUOT: case -ENOSPC: case -EROFS: goto out_put_ctx; default: goto out_drop; } } |
2b0143b5c VFS: normal files... |
80 |
if (inode != d_inode(dentry)) |
ce4ef7c0a NFS: Split out NF... |
81 82 83 84 |
goto out_drop; nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); nfs_file_set_open_context(filp, ctx); |
f1fe29b4a NFS: Use i_writec... |
85 |
nfs_fscache_open_file(inode, filp); |
ce4ef7c0a NFS: Split out NF... |
86 87 88 89 90 91 92 93 94 95 96 97 98 |
err = 0; out_put_ctx: put_nfs_open_context(ctx); out: dput(parent); return err; out_drop: d_drop(dentry); err = -EOPENSTALE; goto out_put_ctx; } |
5445b1fbd NFSv4: Respect th... |
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
/* * Flush all dirty pages, and check for write errors. */ static int nfs4_file_flush(struct file *file, fl_owner_t id) { struct inode *inode = file_inode(file); dprintk("NFS: flush(%pD2) ", file); nfs_inc_stats(inode, NFSIOS_VFSFLUSH); if ((file->f_mode & FMODE_WRITE) == 0) return 0; /* * If we're holding a write delegation, then check if we're required * to flush the i/o on close. If not, then just start the i/o now. */ if (!nfs4_delegation_flush_on_close(inode)) return filemap_fdatawrite(file->f_mapping); /* Flush writes to the server and return any errors */ return vfs_fsync(file, 0); } |
1c6dcbe5c NFS: Implement SEEK |
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
#ifdef CONFIG_NFS_V4_2 static loff_t nfs4_file_llseek(struct file *filep, loff_t offset, int whence) { loff_t ret; switch (whence) { case SEEK_HOLE: case SEEK_DATA: ret = nfs42_proc_llseek(filep, offset, whence); if (ret != -ENOTSUPP) return ret; default: return nfs_file_llseek(filep, offset, whence); } } |
f4ac1674f nfs: Add ALLOCATE... |
139 140 141 142 143 144 145 146 |
static long nfs42_fallocate(struct file *filep, int mode, loff_t offset, loff_t len) { struct inode *inode = file_inode(filep); long ret; if (!S_ISREG(inode->i_mode)) return -EOPNOTSUPP; |
624bd5b7b nfs: Add DEALLOCA... |
147 |
if ((mode != 0) && (mode != (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE))) |
f4ac1674f nfs: Add ALLOCATE... |
148 149 150 151 152 |
return -EOPNOTSUPP; ret = inode_newsize_ok(inode, offset + len); if (ret < 0) return ret; |
624bd5b7b nfs: Add DEALLOCA... |
153 |
if (mode & FALLOC_FL_PUNCH_HOLE) |
f830f7ddd NFS: Reduce time ... |
154 155 |
return nfs42_proc_deallocate(filep, offset, len); return nfs42_proc_allocate(filep, offset, len); |
f4ac1674f nfs: Add ALLOCATE... |
156 |
} |
bea51b30b nfs42: add NFS_IO... |
157 |
|
04b38d601 vfs: pull btrfs c... |
158 159 |
static int nfs42_clone_file_range(struct file *src_file, loff_t src_off, struct file *dst_file, loff_t dst_off, u64 count) |
bea51b30b nfs42: add NFS_IO... |
160 161 |
{ struct inode *dst_inode = file_inode(dst_file); |
811b7b85d nfs42: respect cl... |
162 |
struct nfs_server *server = NFS_SERVER(dst_inode); |
04b38d601 vfs: pull btrfs c... |
163 |
struct inode *src_inode = file_inode(src_file); |
811b7b85d nfs42: respect cl... |
164 |
unsigned int bs = server->clone_blksize; |
21fad313d nfs: allow intra-... |
165 |
bool same_inode = false; |
bea51b30b nfs42: add NFS_IO... |
166 |
int ret; |
811b7b85d nfs42: respect cl... |
167 168 169 170 |
/* check alignment w.r.t. clone_blksize */ ret = -EINVAL; if (bs) { if (!IS_ALIGNED(src_off, bs) || !IS_ALIGNED(dst_off, bs)) |
04b38d601 vfs: pull btrfs c... |
171 |
goto out; |
811b7b85d nfs42: respect cl... |
172 |
if (!IS_ALIGNED(count, bs) && i_size_read(src_inode) != (src_off + count)) |
04b38d601 vfs: pull btrfs c... |
173 |
goto out; |
811b7b85d nfs42: respect cl... |
174 |
} |
04b38d601 vfs: pull btrfs c... |
175 176 |
if (src_inode == dst_inode) same_inode = true; |
21fad313d nfs: allow intra-... |
177 |
|
bea51b30b nfs42: add NFS_IO... |
178 |
/* XXX: do we lock at all? what if server needs CB_RECALL_LAYOUT? */ |
21fad313d nfs: allow intra-... |
179 |
if (same_inode) { |
5955102c9 wrappers for ->i_... |
180 |
inode_lock(src_inode); |
21fad313d nfs: allow intra-... |
181 |
} else if (dst_inode < src_inode) { |
5955102c9 wrappers for ->i_... |
182 183 |
inode_lock_nested(dst_inode, I_MUTEX_PARENT); inode_lock_nested(src_inode, I_MUTEX_CHILD); |
bea51b30b nfs42: add NFS_IO... |
184 |
} else { |
5955102c9 wrappers for ->i_... |
185 186 |
inode_lock_nested(src_inode, I_MUTEX_PARENT); inode_lock_nested(dst_inode, I_MUTEX_CHILD); |
bea51b30b nfs42: add NFS_IO... |
187 188 189 190 191 192 193 194 195 196 |
} /* flush all pending writes on both src and dst so that server * has the latest data */ ret = nfs_sync_inode(src_inode); if (ret) goto out_unlock; ret = nfs_sync_inode(dst_inode); if (ret) goto out_unlock; |
04b38d601 vfs: pull btrfs c... |
197 |
ret = nfs42_proc_clone(src_file, dst_file, src_off, dst_off, count); |
bea51b30b nfs42: add NFS_IO... |
198 199 200 201 202 203 204 |
/* truncate inode page cache of the dst range so that future reads can fetch * new data from server */ if (!ret) truncate_inode_pages_range(&dst_inode->i_data, dst_off, dst_off + count - 1); out_unlock: |
21fad313d nfs: allow intra-... |
205 |
if (same_inode) { |
5955102c9 wrappers for ->i_... |
206 |
inode_unlock(src_inode); |
21fad313d nfs: allow intra-... |
207 |
} else if (dst_inode < src_inode) { |
5955102c9 wrappers for ->i_... |
208 209 |
inode_unlock(src_inode); inode_unlock(dst_inode); |
bea51b30b nfs42: add NFS_IO... |
210 |
} else { |
5955102c9 wrappers for ->i_... |
211 212 |
inode_unlock(dst_inode); inode_unlock(src_inode); |
bea51b30b nfs42: add NFS_IO... |
213 |
} |
04b38d601 vfs: pull btrfs c... |
214 |
out: |
bea51b30b nfs42: add NFS_IO... |
215 216 |
return ret; } |
6b7153da2 nfs: reduce the a... |
217 |
#endif /* CONFIG_NFS_V4_2 */ |
bea51b30b nfs42: add NFS_IO... |
218 |
|
ce4ef7c0a NFS: Split out NF... |
219 |
const struct file_operations nfs4_file_operations = { |
3aa2d199f nfs: switch to ->... |
220 |
.read_iter = nfs_file_read, |
edaf43694 nfs: switch to ->... |
221 |
.write_iter = nfs_file_write, |
ce4ef7c0a NFS: Split out NF... |
222 223 |
.mmap = nfs_file_mmap, .open = nfs4_file_open, |
5445b1fbd NFSv4: Respect th... |
224 |
.flush = nfs4_file_flush, |
ce4ef7c0a NFS: Split out NF... |
225 |
.release = nfs_file_release, |
4ff79bc70 nfs: remove nfs4_... |
226 |
.fsync = nfs_file_fsync, |
ce4ef7c0a NFS: Split out NF... |
227 228 229 |
.lock = nfs_lock, .flock = nfs_flock, .splice_read = nfs_file_splice_read, |
4da54c218 nfs: switch to it... |
230 |
.splice_write = iter_file_splice_write, |
ce4ef7c0a NFS: Split out NF... |
231 |
.check_flags = nfs_check_flags, |
1c994a090 locks: consolidat... |
232 |
.setlease = simple_nosetlease, |
6b7153da2 nfs: reduce the a... |
233 234 235 |
#ifdef CONFIG_NFS_V4_2 .llseek = nfs4_file_llseek, .fallocate = nfs42_fallocate, |
04b38d601 vfs: pull btrfs c... |
236 |
.clone_file_range = nfs42_clone_file_range, |
6b7153da2 nfs: reduce the a... |
237 238 239 |
#else .llseek = nfs_file_llseek, #endif |
ce4ef7c0a NFS: Split out NF... |
240 |
}; |