Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F150733614
D31640.id94155.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D31640.id94155.diff
View Options
diff --git a/sys/fs/nfs/nfs_var.h.nodeall b/sys/fs/nfs/nfs_var.h
--- a/sys/fs/nfs/nfs_var.h.nodeall
+++ b/sys/fs/nfs/nfs_var.h
@@ -551,6 +551,8 @@
void nfscl_freenfsclds(struct nfsclds *);
int nfsrpc_allocate(vnode_t, off_t, off_t, struct nfsvattr *, int *,
struct ucred *, NFSPROC_T *, void *);
+int nfsrpc_deallocate(vnode_t, off_t, off_t, struct nfsvattr *, int *,
+ struct ucred *, NFSPROC_T *, void *);
int nfsrpc_copy_file_range(vnode_t, off_t *, vnode_t, off_t *, size_t *,
unsigned int, int *, struct nfsvattr *, int *, struct nfsvattr *,
struct ucred *, bool, bool *);
diff --git a/sys/fs/nfsclient/nfs_clrpcops.c.nodeall b/sys/fs/nfsclient/nfs_clrpcops.c
--- a/sys/fs/nfsclient/nfs_clrpcops.c.nodeall
+++ b/sys/fs/nfsclient/nfs_clrpcops.c
@@ -132,6 +132,8 @@
static int nfsrpc_writerpc(vnode_t , struct uio *, int *, int *,
struct ucred *, nfsv4stateid_t *, NFSPROC_T *, struct nfsvattr *, int *,
void *);
+static int nfsrpc_deallocaterpc(vnode_t, off_t, off_t, nfsv4stateid_t *,
+ struct nfsvattr *, int *, struct ucred *, NFSPROC_T *, void *);
static int nfsrpc_createv23(vnode_t , char *, int, struct vattr *,
nfsquad_t, int, struct ucred *, NFSPROC_T *, struct nfsvattr *,
struct nfsvattr *, struct nfsfh **, int *, int *, void *);
@@ -2085,6 +2087,116 @@
m_freem(nd->nd_mrep);
*iomode = committed;
if (nd->nd_repstat && !error)
+ error = nd->nd_repstat;
+ return (error);
+}
+
+/*
+ * Do an nfs deallocate operation.
+ */
+int
+nfsrpc_deallocate(vnode_t vp, off_t offs, off_t len, struct nfsvattr *nap,
+ int *attrflagp, struct ucred *cred, NFSPROC_T *p, void *stuff)
+{
+ int error, expireret = 0, openerr, retrycnt;
+ uint32_t clidrev = 0;
+ struct nfsmount *nmp = VFSTONFS(vp->v_mount);
+ struct nfsfh *nfhp;
+ nfsv4stateid_t stateid;
+ void *lckp;
+
+ if (nmp->nm_clp != NULL)
+ clidrev = nmp->nm_clp->nfsc_clientidrev;
+ retrycnt = 0;
+ do {
+ lckp = NULL;
+ openerr = 1;
+ nfhp = VTONFS(vp)->n_fhp;
+ error = nfscl_getstateid(vp, nfhp->nfh_fh, nfhp->nfh_len,
+ NFSV4OPEN_ACCESSWRITE, 0, cred, p, &stateid, &lckp);
+ if (error != 0) {
+ /*
+ * No Open stateid, so try and open the file
+ * now.
+ */
+ openerr = nfsrpc_open(vp, FWRITE, cred, p);
+ if (openerr == 0)
+ nfscl_getstateid(vp, nfhp->nfh_fh,
+ nfhp->nfh_len, NFSV4OPEN_ACCESSWRITE, 0,
+ cred, p, &stateid, &lckp);
+ }
+ error = nfsrpc_deallocaterpc(vp, offs, len, &stateid, nap,
+ attrflagp, cred, p, stuff);
+ if (error == NFSERR_STALESTATEID)
+ nfscl_initiate_recovery(nmp->nm_clp);
+ if (lckp != NULL)
+ nfscl_lockderef(lckp);
+ if (openerr == 0)
+ nfsrpc_close(vp, 0, p);
+ if (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
+ error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
+ error == NFSERR_OLDSTATEID || error == NFSERR_BADSESSION) {
+ (void) nfs_catnap(PZERO, error, "nfs_deallocate");
+ } else if ((error == NFSERR_EXPIRED ||
+ error == NFSERR_BADSTATEID) && clidrev != 0) {
+ expireret = nfscl_hasexpired(nmp->nm_clp, clidrev, p);
+ }
+ retrycnt++;
+ } while (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
+ error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
+ error == NFSERR_BADSESSION ||
+ (error == NFSERR_OLDSTATEID && retrycnt < 20) ||
+ ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
+ expireret == 0 && clidrev != 0 && retrycnt < 4));
+ if (error && retrycnt >= 4)
+ error = EIO;
+ return (error);
+}
+
+/*
+ * The actual deallocate RPC.
+ */
+static int
+nfsrpc_deallocaterpc(vnode_t vp, off_t offs, off_t len,
+ nfsv4stateid_t *stateidp, struct nfsvattr *nap, int *attrflagp,
+ struct ucred *cred, NFSPROC_T *p, void *stuff)
+{
+ uint32_t *tl;
+ struct nfsnode *np = VTONFS(vp);
+ int error, wccflag;
+ struct nfsrv_descript nfsd;
+ struct nfsrv_descript *nd = &nfsd;
+ nfsattrbit_t attrbits;
+
+ *attrflagp = 0;
+ NFSCL_REQSTART(nd, NFSPROC_DEALLOCATE, vp);
+ nfsm_stateidtom(nd, stateidp, NFSSTATEID_PUTSTATEID);
+ NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER);
+ txdr_hyper(offs, tl);
+ tl += 2;
+ txdr_hyper(len, tl);
+ NFSWRITEGETATTR_ATTRBIT(&attrbits);
+ NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
+ *tl = txdr_unsigned(NFSV4OP_GETATTR);
+ nfsrv_putattrbit(nd, &attrbits);
+ error = nfscl_request(nd, vp, p, cred, stuff);
+ if (error != 0)
+ return (error);
+ wccflag = 0;
+ error = nfscl_wcc_data(nd, vp, nap, attrflagp, &wccflag, stuff);
+ if (error != 0)
+ goto nfsmout;
+ if (nd->nd_repstat == 0) {
+ NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
+ error = nfsm_loadattr(nd, nap);
+ if (error != 0)
+ goto nfsmout;
+ *attrflagp = NFS_LATTR_NOSHRINK;
+ }
+ NFSWRITERPC_SETTIME(wccflag, np, nap, 1);
+nfsmout:
+ m_freem(nd->nd_mrep);
+ if (nd->nd_repstat != 0 && error == 0)
error = nd->nd_repstat;
return (error);
}
diff --git a/sys/fs/nfsclient/nfs_clvnops.c.nodeall b/sys/fs/nfsclient/nfs_clvnops.c
--- a/sys/fs/nfsclient/nfs_clvnops.c.nodeall
+++ b/sys/fs/nfsclient/nfs_clvnops.c
@@ -146,6 +146,7 @@
static vop_setacl_t nfs_setacl;
static vop_advise_t nfs_advise;
static vop_allocate_t nfs_allocate;
+static vop_deallocate_t nfs_deallocate;
static vop_copy_file_range_t nfs_copy_file_range;
static vop_ioctl_t nfs_ioctl;
static vop_getextattr_t nfs_getextattr;
@@ -193,6 +194,7 @@
.vop_setacl = nfs_setacl,
.vop_advise = nfs_advise,
.vop_allocate = nfs_allocate,
+ .vop_deallocate = nfs_deallocate,
.vop_copy_file_range = nfs_copy_file_range,
.vop_ioctl = nfs_ioctl,
.vop_getextattr = nfs_getextattr,
@@ -3671,6 +3673,85 @@
*/
if (error != 0)
error = vop_stdallocate(ap);
+ if (attrflag != 0) {
+ ret = nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
+ if (error == 0 && ret != 0)
+ error = ret;
+ }
+ if (error != 0)
+ error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
+ return (error);
+}
+
+/*
+ * nfs deallocate call
+ */
+static int
+nfs_deallocate(struct vop_deallocate_args *ap)
+{
+ struct vnode *vp = ap->a_vp;
+ struct thread *td = curthread;
+ struct nfsvattr nfsva;
+ struct nfsmount *nmp;
+ off_t tlen;
+ int attrflag, error, ret;
+
+ error = 0;
+ attrflag = 0;
+ nmp = VFSTONFS(vp->v_mount);
+ mtx_lock(&nmp->nm_mtx);
+ if (NFSHASNFSV4(nmp) && nmp->nm_minorvers >= NFSV42_MINORVERSION &&
+ (nmp->nm_privflag & NFSMNTP_NODEALLOCATE) == 0) {
+ mtx_unlock(&nmp->nm_mtx);
+ tlen = omin(OFF_MAX - *ap->a_offset, *ap->a_len);
+ NFSCL_DEBUG(4, "dealloc: off=%jd len=%jd maxfilesize=%ju\n",
+ (intmax_t)*ap->a_offset, (intmax_t)tlen,
+ (uintmax_t)nmp->nm_maxfilesize);
+ if ((uint64_t)*ap->a_offset >= nmp->nm_maxfilesize) {
+ /* Avoid EFBIG error return from the NFSv4.2 server. */
+ *ap->a_offset = VTONFS(vp)->n_size;
+ *ap->a_len = 0;
+ return (0);
+ }
+ if ((uint64_t)*ap->a_offset + tlen > nmp->nm_maxfilesize)
+ tlen = nmp->nm_maxfilesize - *ap->a_offset;
+ if (error == 0)
+ error = ncl_vinvalbuf(vp, V_SAVE, td, 1);
+ if (error == 0) {
+ vnode_pager_purge_range(vp, *ap->a_offset,
+ *ap->a_offset + tlen);
+ error = nfsrpc_deallocate(vp, *ap->a_offset, tlen,
+ &nfsva, &attrflag, ap->a_cred, td, NULL);
+ NFSCL_DEBUG(4, "dealloc: rpc=%d\n", error);
+ }
+ if (error == 0) {
+ NFSCL_DEBUG(4, "dealloc: attrflag=%d na_size=%ju\n",
+ attrflag, (uintmax_t)nfsva.na_size);
+ if (attrflag != 0) {
+ if ((uint64_t)*ap->a_offset + tlen >=
+ nfsva.na_size)
+ *ap->a_offset = nfsva.na_size;
+ else
+ *ap->a_offset += tlen;
+ }
+ *ap->a_len = 0;
+ } else if (error == NFSERR_NOTSUPP) {
+ mtx_lock(&nmp->nm_mtx);
+ nmp->nm_privflag |= NFSMNTP_NODEALLOCATE;
+ mtx_unlock(&nmp->nm_mtx);
+ }
+ } else {
+ mtx_unlock(&nmp->nm_mtx);
+ error = EIO;
+ }
+ /*
+ * If the NFS server cannot perform the Deallocate operation, just call
+ * vop_stddeallocate() to perform it.
+ */
+ if (error != 0 && error != NFSERR_FBIG && error != NFSERR_INVAL) {
+ error = vop_stddeallocate(ap);
+ NFSCL_DEBUG(4, "dealloc: stddeallocate=%d\n", error);
+ }
if (attrflag != 0) {
ret = nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
if (error == 0 && ret != 0)
diff --git a/sys/fs/nfsclient/nfsmount.h.nodeall b/sys/fs/nfsclient/nfsmount.h
--- a/sys/fs/nfsclient/nfsmount.h.nodeall
+++ b/sys/fs/nfsclient/nfsmount.h
@@ -124,6 +124,7 @@
#define NFSMNTP_NOADVISE 0x00000100
#define NFSMNTP_NOALLOCATE 0x00000200
#define NFSMNTP_DELEGISSUED 0x00000400
+#define NFSMNTP_NODEALLOCATE 0x00000800
/* New mount flags only used by the kernel via nmount(2). */
#define NFSMNT_TLS 0x00000001
diff --git a/sys/kern/vfs_default.c.nodeall b/sys/kern/vfs_default.c
--- a/sys/kern/vfs_default.c.nodeall
+++ b/sys/kern/vfs_default.c
@@ -93,7 +93,6 @@
static int vop_stdread_pgcache(struct vop_read_pgcache_args *ap);
static int vop_stdstat(struct vop_stat_args *ap);
static int vop_stdvput_pair(struct vop_vput_pair_args *ap);
-static int vop_stddeallocate(struct vop_deallocate_args *ap);
/*
* This vnode table stores what we want to do if the filesystem doesn't
@@ -1126,7 +1125,7 @@
return (error);
}
-static int
+int
vop_stddeallocate(struct vop_deallocate_args *ap)
{
struct vnode *vp;
diff --git a/sys/sys/vnode.h.nodeall b/sys/sys/vnode.h
--- a/sys/sys/vnode.h.nodeall
+++ b/sys/sys/vnode.h
@@ -861,6 +861,7 @@
int vop_stdadvlockasync(struct vop_advlockasync_args *ap);
int vop_stdadvlockpurge(struct vop_advlockpurge_args *ap);
int vop_stdallocate(struct vop_allocate_args *ap);
+int vop_stddeallocate(struct vop_deallocate_args *ap);
int vop_stdset_text(struct vop_set_text_args *ap);
int vop_stdpathconf(struct vop_pathconf_args *);
int vop_stdpoll(struct vop_poll_args *);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Apr 4, 5:03 PM (5 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30830581
Default Alt Text
D31640.id94155.diff (9 KB)
Attached To
Mode
D31640: add a nfs_deallocate VOP
Attached
Detach File
Event Timeline
Log In to Comment