nfs-ganesha 1.4

fsal_lock.c

Go to the documentation of this file.
00001 /*
00002  * Copyright IBM Corporation, 2010
00003  *  Contributor: Aneesh Kumar K.v  <aneesh.kumar@linux.vnet.ibm.com>
00004  *
00005  *
00006  * This software is a server that implements the NFS protocol.
00007  *
00008  *
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 3 of the License, or (at your option) any later version.
00013  * 
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  * 
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  * 
00023  *
00024  */
00025 #ifdef HAVE_CONFIG_H
00026 #include "config.h"
00027 #endif
00028 
00029 #include "fsal.h"
00030 #include "fsal_internal.h"
00031 #include "fsal_convert.h"
00032 
00062 fsal_status_t VFSFSAL_lock_op( fsal_file_t       * p_file_descriptor,   /* IN */
00063                                fsal_handle_t     * p_filehandle,        /* IN */
00064                                fsal_op_context_t * p_context,           /* IN */
00065                                void              * p_owner,             /* IN (opaque to FSAL) */
00066                                fsal_lock_op_t      lock_op,             /* IN */
00067                                fsal_lock_param_t   request_lock,        /* IN */
00068                                fsal_lock_param_t * conflicting_lock)    /* OUT */
00069 {
00070   int retval;
00071   struct flock lock_args;
00072   int fcntl_comm;
00073   vfsfsal_file_t * pfd = (vfsfsal_file_t *) p_file_descriptor;
00074 
00075   if(p_file_descriptor == NULL || p_filehandle == NULL || p_context == NULL)
00076     {
00077       if(p_file_descriptor == NULL)
00078         LogDebug(COMPONENT_FSAL, "p_file_descriptor argument is NULL.");
00079       if(p_filehandle == NULL)
00080         LogDebug(COMPONENT_FSAL, "p_filehandle argument is NULL.");
00081       if(p_context == NULL)
00082         LogDebug(COMPONENT_FSAL, "p_context argument is NULL.");
00083       Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lock_op);
00084     }
00085 
00086   if(p_owner != NULL)
00087     Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_lock_op);
00088 
00089   if(conflicting_lock == NULL && lock_op == FSAL_OP_LOCKT)
00090     {
00091       LogDebug(COMPONENT_FSAL, "conflicting_lock argument can't"
00092                " be NULL with lock_op  = LOCKT");
00093       Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lock_op);
00094     }
00095 
00096   LogFullDebug(COMPONENT_FSAL, "Locking: op:%d type:%d start:%"PRIu64" length:%zu ", lock_op,
00097                request_lock.lock_type, request_lock.lock_start, request_lock.lock_length);
00098 
00099   if(lock_op == FSAL_OP_LOCKT)
00100     fcntl_comm = F_GETLK;
00101   else if(lock_op == FSAL_OP_LOCK || lock_op == FSAL_OP_UNLOCK)
00102     fcntl_comm = F_SETLK;
00103   else
00104     {
00105       LogDebug(COMPONENT_FSAL, "ERROR: Lock operation requested was not TEST, READ, or WRITE.");
00106       Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_lock_op);      
00107     }
00108 
00109   if(request_lock.lock_type == FSAL_LOCK_R)
00110     lock_args.l_type = F_RDLCK;
00111   else if(request_lock.lock_type == FSAL_LOCK_W)
00112     lock_args.l_type = F_WRLCK;
00113   else
00114     {
00115       LogDebug(COMPONENT_FSAL, "ERROR: The requested lock type was not read or write.");
00116       Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_lock_op);
00117     }
00118 
00119   if(lock_op == FSAL_OP_UNLOCK)
00120     lock_args.l_type = F_UNLCK;
00121 
00122   lock_args.l_len = request_lock.lock_length;
00123   lock_args.l_start = request_lock.lock_start;
00124   lock_args.l_whence = SEEK_SET;
00125 
00126   errno = 0;
00127   retval = fcntl(pfd->fd, fcntl_comm, &lock_args);
00128   if(retval && lock_op == FSAL_OP_LOCK)
00129     {
00130       if(conflicting_lock != NULL)
00131         {
00132           fcntl_comm = F_GETLK;
00133           retval = fcntl(pfd->fd, fcntl_comm, &lock_args);
00134           if(retval)
00135             {
00136               LogCrit(COMPONENT_FSAL, "After failing a lock request, I couldn't even"
00137                       " get the details of who owns the lock.");
00138               Return(posix2fsal_error(errno), errno, INDEX_FSAL_lock_op);
00139             }
00140           if(conflicting_lock != NULL)
00141             {
00142               conflicting_lock->lock_length = lock_args.l_len;
00143               conflicting_lock->lock_start = lock_args.l_start;
00144               conflicting_lock->lock_type = lock_args.l_type;
00145             }
00146         }
00147       Return(posix2fsal_error(errno), errno, INDEX_FSAL_lock_op);
00148     }
00149 
00150   /* F_UNLCK is returned then the tested operation would be possible. */
00151   if(conflicting_lock != NULL)
00152     {
00153       if(lock_op == FSAL_OP_LOCKT && lock_args.l_type != F_UNLCK)
00154         {
00155           conflicting_lock->lock_length = lock_args.l_len;
00156           conflicting_lock->lock_start = lock_args.l_start;
00157           conflicting_lock->lock_type = lock_args.l_type;
00158         }
00159       else
00160         {
00161           conflicting_lock->lock_length = 0;
00162           conflicting_lock->lock_start = 0;
00163           conflicting_lock->lock_type = FSAL_NO_LOCK;
00164         }
00165     }
00166 
00167   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_lock_op);
00168 }