Risistemato il POSIX file locking
[gapil.git] / fileadv.tex
index a9ba273833e2f891f7e4bcacf9071ddb773be1de..8b7246259fcc4b3176c252dde95c0206bab25d83 100644 (file)
@@ -1266,7 +1266,28 @@ La seconda tipologia 
 lettura che in scrittura) da parte di altri processi mentre lo si sta
 scrivendo. Si parla di \textsl{blocco esclusivo} appunto perché un solo
 processo alla volta può richiedere un \textit{exclusive lock} su un file per
-proteggere il suo accesso in scrittura.
+proteggere il suo accesso in scrittura. 
+
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|c|c|c|}
+    \hline
+    \textbf{Richiesta} & \multicolumn{3}{|c|}{\textbf{Stato del file}}\\
+    \cline{2-4}
+                       &Nessun lock&\textit{Read lock}&\textit{Write lock}\\
+    \hline
+    \hline
+    \textit{Read lock} & SI & SI & NO \\
+    \textit{Write lock}& SI & NO & NO \\
+    \hline    
+  \end{tabular}
+  \caption{Tipologie di file locking.}
+  \label{tab:file_file_lock}
+\end{table}
+
+
 
 In Linux sono disponibili due interfacce per utilizzare l'\textit{advisory
   locking}, la prima è quella derivata da BSD, che è basata sulla funzione
@@ -1281,10 +1302,13 @@ inizia sempre con il richiedere l'opportuno \textit{file lock} (un
 lettura) prima di eseguire l'accesso ad un file.  Se il lock viene acquisito
 il processo prosegue l'esecuzione, altrimenti (a meno di non aver richiesto un
 comportamento non bloccante) viene posto in stato di sleep. Una volta finite
-le operazioni sul file si deve provvedere a rimuovere il lock.  Si ricordi che
-la condizione per acquisire uno \textit{shared lock} è che il file non abbia
-già un \textit{exclusive lock} attivo, mentre per acquisire un
-\textit{exclusive lock} non deve essere presente nessun tipo di blocco.
+le operazioni sul file si deve provvedere a rimuovere il lock. La situazione
+delle varie possibilità è riassunta in \tabref{tab:file_file_lock}.
+
+%%  Si ricordi che
+%% la condizione per acquisire uno \textit{shared lock} è che il file non abbia
+%% già un \textit{exclusive lock} attivo, mentre per acquisire un
+%% \textit{exclusive lock} non deve essere presente nessun tipo di blocco.
 
 
 \subsection{La funzione \func{flock}}
@@ -1335,20 +1359,20 @@ richiedere un \textit{file lock}, ed ovviamente devono essere usati in maniera
 alternativa. Se si specifica anche \macro{LOCK\_NB} la funzione non si
 bloccherà qualora il lock non possa essere acquisito, ma ritornerà subito con
 un errore di \macro{EWOULDBLOCK}. Per rilasciare un lock si dovrà invece usare
-\macro{LOCK\_NB}.
+\macro{LOCK\_UN}.
 
 La semantica del file locking di BSD è diversa da quella del file locking
 POSIX, in particolare per quanto riguarda il comportamento dei lock nei
 confronti delle due funzioni \func{dup} e \func{fork}.  Per capire queste
-differenze occorre prima descrivere con maggiore dettaglio come viene
-realizzato il file locking nel kernel.
+differenze occorre descrivere con maggiore dettaglio come viene realizzato il
+file locking nel kernel in entrambe le interfacce.
 
 In \figref{fig:file_flock_struct} si è riportato uno schema essenziale
-dell'implementazione del file locking in Linux; il punto fondamentale da
-capire è che un lock, qualunque sia l'interfaccia che si usa, anche se
-richiesto attraverso un file descriptor, agisce sempre su un file; perciò le
-informazioni relative agli eventuali \textit{file lock} sono mantenute a
-livello di inode,\footnote{in particolare, come accennato in
+dell'implementazione del file locking in stile BSD in Linux; il punto
+fondamentale da capire è che un lock, qualunque sia l'interfaccia che si usa,
+anche se richiesto attraverso un file descriptor, agisce sempre su un file;
+perciò le informazioni relative agli eventuali \textit{file lock} sono
+mantenute a livello di inode,\footnote{in particolare, come accennato in
   \figref{fig:file_flock_struct}, i \textit{file lock} sono mantenuti un una
   \textit{linked list}\index{linked list} di strutture \var{file\_lock}. La
   lista è referenziata dall'indirizzo di partenza mantenuto dal campo
@@ -1373,44 +1397,44 @@ elemento.\footnote{cio
 lock creati con \func{flock} la semantica della funzione prevede che sia
 \func{dup} che \func{fork} non creino ulteriori istanze di un \textit{file
   lock} quanto piuttosto degli ulteriori riferimenti allo stesso. Questo viene
-realizzato dal kernel associando ad ogni nuovo \textit{file lock} un
-puntatore\footnote{il puntatore è mantenuto nel campo \var{fl\_file} di
-  \var{file\_lock}, e viene utilizzato solo per i lock creati con la semantica
-  BSD.} alla voce nella \textit{file table} da cui si è richiesto il blocco,
-che così ne identifica il titolare.
-
-Questa struttura comporta che, quando si richiede la rimozione di un file
-lock, il kernel acconsenta solo se la richiesta proviene da un file descriptor
-che fa riferimento ad una voce nella file table corrispondente a quella
-registrata nel blocco.  Allora se ricordiamo quanto visto in
-\secref{sec:file_dup} e \secref{sec:file_sharing}, e cioè che i file
-descriptor duplicati e quelli ereditati in un processo figlio puntano sempre
-alla stessa voce nella file table, si può capire immediatamente quali sono le
-conseguenze nei confronti delle funzioni \func{dup} e \func{fork}.
-
-Sarà cioè possibile rimuovere un file lock attraverso uno qualunque dei file
-descriptor che fanno riferimento alla stessa voce nella file table, quindi
-anche se questo è diverso da quello con cui lo si è
-creato,\footnote{attenzione, questo non vale se il file descriptor fa
-  riferimento allo stesso file, ma attraverso una voce diversa della file
-  table, come accade tutte le volte che si apre più volte lo stesso file.} o
-se si esegue la rimozione in un processo figlio; inoltre una volta tolto un
-file lock, la rimozione avrà effetto su tutti i file descriptor che
-condividono la stessa voce nella file table, e quindi, nel caso di file
-descriptor ereditati attraverso una \func{fork}, anche su processi diversi.
+realizzato dal kernel secondo lo schema di \figref{fig:file_flock_struct},
+associando ad ogni nuovo \textit{file lock} un puntatore\footnote{il puntatore
+  è mantenuto nel campo \var{fl\_file} di \var{file\_lock}, e viene utilizzato
+  solo per i lock creati con la semantica BSD.} alla voce nella \textit{file
+  table} da cui si è richiesto il blocco, che così ne identifica il titolare.
+
+Questa struttura prevede che, quando si richiede la rimozione di un file lock,
+il kernel acconsenta solo se la richiesta proviene da un file descriptor che
+fa riferimento ad una voce nella file table corrispondente a quella registrata
+nel blocco.  Allora se ricordiamo quanto visto in \secref{sec:file_dup} e
+\secref{sec:file_sharing}, e cioè che i file descriptor duplicati e quelli
+ereditati in un processo figlio puntano sempre alla stessa voce nella file
+table, si può capire immediatamente quali sono le conseguenze nei confronti
+delle funzioni \func{dup} e \func{fork}.
+
+Sarà così possibile rimuovere un file lock attraverso uno qualunque dei file
+descriptor che fanno riferimento alla stessa voce nella file table, anche se
+questo è diverso da quello con cui lo si è creato,\footnote{attenzione, questo
+  non vale se il file descriptor fa riferimento allo stesso file, ma
+  attraverso una voce diversa della file table, come accade tutte le volte che
+  si apre più volte lo stesso file.} o se si esegue la rimozione in un
+processo figlio; inoltre una volta tolto un file lock, la rimozione avrà
+effetto su tutti i file descriptor che condividono la stessa voce nella file
+table, e quindi, nel caso di file descriptor ereditati attraverso una
+\func{fork}, anche su processi diversi.
 
 Infine, per evitare che la terminazione imprevista di un processo lasci attivi
 dei file lock, quando un file viene chiuso il kernel provveda anche a
 rimuovere tutti i lock ad esso associati. Anche in questo caso occorre tenere
 presente cosa succede quando si hanno file descriptor duplicati; in tal caso
 infatti il file non verrà effettivamente chiuso (ed il lock rimosso) fintanto
-che non viene rilasciata la relativa voce nella file table; la rimozione cioè
-avverrà solo quando tutti i file descriptor che fanno riferimento alla stessa
-voce sono stati chiusi, quindi, nel caso ci siano processi figli che
-mantengono ancora aperto un file descriptor, il lock non sarà rilasciato.
+che non viene rilasciata la relativa voce nella file table; e questo avverrà
+solo quando tutti i file descriptor che fanno riferimento alla stessa voce
+sono stati chiusi.  Quindi, nel caso ci siano duplicati o processi figli che
+mantengono ancora aperto un file descriptor, il lock non viene rilasciato.
 
-Si tenga presente che \func{flock} non è in grado di funzionare per i file
-mantenuti su NFS, in questo caso, se si ha la necessità di eseguire il
+Si tenga presente infine che \func{flock} non è in grado di funzionare per i
+file mantenuti su NFS, in questo caso, se si ha la necessità di eseguire il
 \textit{file locking}, occorre usare l'interfaccia basata su \func{fcntl} che
 può funzionare anche attraverso NFS, a condizione che sia il client che il
 server supportino questa funzionalità.
@@ -1421,9 +1445,9 @@ server supportino questa funzionalit
 
 La seconda interfaccia per l'\textit{advisory locking} disponibile in Linux è
 quella standardizzata da POSIX, basata sulla funzione \func{fcntl}. Abbiamo
-già trattato questa funzione nelle sue molteplici funzionalità in
-\secref{sec:file_fcntl}; quando la si impiega per il \textit{file locking}
-però essa viene usata solo secondo il prototipo:
+già trattato questa funzione nelle sue molteplici possibilità di utilizzo in
+\secref{sec:file_fcntl}. Quando la si impiega per il \textit{file locking}
+essa viene usata solo secondo il prototipo:
 \begin{prototype}{fcntl.h}{int fcntl(int fd, int cmd, struct flock *lock)}
   
   Applica o rimuove un \textit{file lock} sul file \param{fd}.
@@ -1451,12 +1475,12 @@ per
 Al contrario di quanto avviene con l'interfaccia basata su \func{flock} con
 \func{fcntl} è possibile bloccare anche delle singole sezioni di un file;
 inoltre la funzione permette di leggere le informazioni relative ai blocchi
-esistenti.  Per poter fare tutto questo la funzione utilizza come terzo
-argomento una apposita struttura \var{flock} (la cui definizione è riportata
-in \figref{fig:struct_flock}) che contiene tutte le specifiche di un dato file
+esistenti.  Per questo la funzione utilizza come terzo argomento una apposita
+struttura \var{flock} (la cui definizione è riportata in
+\figref{fig:struct_flock}) che contiene tutte le specifiche di un dato file
 lock.
 
-\begin{figure}[!htb]
+\begin{figure}[!bht]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
     \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
@@ -1475,46 +1499,33 @@ struct flock {
   \label{fig:struct_flock}
 \end{figure}
 
-L'operazione effettivamente svolta dalla funzione è stabilita dal valore
-dall'argomento \param{cmd} che, come già riportato in \secref{sec:file_fcntl},
-specifica l'azione da compiere; i valori relativi al file locking sono tre:
-\begin{basedescript}{\desclabelwidth{2.0cm}}
-\item[\macro{F\_GETLK}] verifica se il file lock specificato dalla struttura
-  puntata da \param{lock} non è bloccato da qualche altro lock: in caso
-  affermativo sovrascrive la struttura con i valori relativi a quest'ultimo,
-  altrimenti si limita a impostarne il campo \var{l\_type} con
-  \macro{F\_UNLCK}.
-\item[\macro{F\_SETLK}] se il campo \var{l\_type} della struttura puntata da
-  \param{lock} è \macro{F\_RDLCK} o \macro{F\_WRLCK} richiede il
-  corrispondente file lock, se è \macro{F\_UNLCK} lo rilascia. Nel caso la
-  richiesta non possa essere soddisfatta a causa di un lock preesistente la
-  funzione ritorna immediatamente con un errore di \macro{EACCES} o di
-  \macro{EAGAIN}.
-\item[\macro{F\_SETLKW}] è identica a \macro{F\_SETLK}, ma se la richiesta di
-  un lock non può essere soddisfatta per la presenza di un altro blocco, mette
-  il processo in stato di attesa fintanto che il lock precedente non viene
-  rilasciato. Se l'attesa viene interrotta da un segnale la funzione ritorna
-  con un errore di \macro{EINTR}.
-\end{basedescript}
 
-Come accennato nell'interfaccia POSIX ogni file lock viene associato ad una
-struttura \func{flock}; i tre campi \var{l\_whence}, \var{l\_start} e
+I primi tre campi della struttura, \var{l\_whence}, \var{l\_start} e
 \var{l\_len}, servono a specificare la sezione del file a cui fa riferimento
-il lock, \var{l\_start} specifica il byte di partenza, e \var{l\_len} la
-lunghezza della sezione; \var{l\_whence} infine imposta il riferimento da cui
-contare \var{l\_start} e segue la stessa semantica dell'omonimo argomento di
-\func{lseek}, coi tre possibili valori \macro{SEEK\_SET}, \macro{SEEK\_CUR} e
-\macro{SEEK\_END} (si vedano le relative descrizioni in
-\secref{sec:file_lseek}).
+il lock: \var{l\_start} specifica il byte di partenza, \var{l\_len} la
+lunghezza della sezione e infine \var{l\_whence} imposta il riferimento da cui
+contare \var{l\_start}. Il valore di \var{l\_whence} segue la stessa semantica
+dell'omonimo argomento di \func{lseek}, coi tre possibili valori
+\macro{SEEK\_SET}, \macro{SEEK\_CUR} e \macro{SEEK\_END}, (si vedano le
+relative descrizioni in \secref{sec:file_lseek}).
 
 Si tenga presente che un lock può essere richiesto anche per una regione al di
 là della corrente fine del file, così che una eventuale estensione dello
-stesso resti coperta dal blocco. Se si specifica un valore nullo per
+stesso resti coperta dal blocco. Inoltre se si specifica un valore nullo per
 \var{l\_len} il blocco si considera esteso fino alla dimensione massima del
 file; in questo modo è possibile bloccare una qualunque regione a partire da
 un certo punto fino alla fine del file, coprendo automaticamente quanto
 eventualmente aggiunto in coda allo stesso.
 
+Il tipo di file lock richiesto viene specificato dal campo \var{l\_type}, esso
+può assumere i tre valori definiti dalle costanti riportate in
+\tabref{tab:file_flock_type}, che permettono di richiedere rispettivamente uno
+\textit{shared lock}, un \textit{esclusive lock}, e la rimozione di un lock
+precedentemente acquisito. Infine il campo \var{l\_pid} viene usato solo in
+caso di lettura, quando si chiama \func{fcntl} con \macro{F\_GETLK}, e riporta
+il \acr{pid} del processo che detiene il lock.
+
+
 \begin{table}[htb]
   \centering
   \footnotesize
@@ -1532,55 +1543,103 @@ eventualmente aggiunto in coda allo stesso.
   \label{tab:file_flock_type}
 \end{table}
 
-Il tipo di file lock richiesto viene specificato dal campo \var{l\_type}, esso
-può assumere i tre valori riportati in \tabref{tab:file_flock_type}, che
-permettono di richiedere rispettivamente uno \textit{shared lock}, un
-\textit{esclusive lock}, e la rimozione di un lock precedentemente acquisito.
+L'operazione effettivamente svolta dalla funzione è stabilita dal valore
+dall'argomento \param{cmd} che, come già riportato in \secref{sec:file_fcntl},
+specifica l'azione da compiere; i valori relativi al file locking sono tre:
+\begin{basedescript}{\desclabelwidth{2.0cm}}
+\item[\macro{F\_GETLK}] verifica se il file lock specificato dalla struttura
+  puntata da \param{lock} può essere acquisito: in caso negativo sovrascrive
+  la struttura \param{flock} con i valori relativi al lock già esistente che
+  ne blocca l'acquisizione, altrimenti si limita a impostarne il campo
+  \var{l\_type} con il valore \macro{F\_UNLCK}. 
+\item[\macro{F\_SETLK}] se il campo \var{l\_type} della struttura puntata da
+  \param{lock} è \macro{F\_RDLCK} o \macro{F\_WRLCK} richiede il
+  corrispondente file lock, se è \macro{F\_UNLCK} lo rilascia. Nel caso la
+  richiesta non possa essere soddisfatta a causa di un lock preesistente la
+  funzione ritorna immediatamente con un errore di \macro{EACCES} o di
+  \macro{EAGAIN}.
+\item[\macro{F\_SETLKW}] è identica a \macro{F\_SETLK}, ma se la richiesta di
+  un lock non può essere soddisfatta per la presenza di un altro blocco, mette
+  il processo in stato di attesa fintanto che il lock precedente non viene
+  rilasciato. Se l'attesa viene interrotta da un segnale la funzione ritorna
+  con un errore di \macro{EINTR}.
+\end{basedescript}
+
+Si noti che il comando \macro{F\_GETLK} non serve a rilevare una presenza
+generica di lock su un file, perché se ne esistono di compatibili con quello
+richiesto, la funzione ritorna comunque impostando \var{l\_type} a
+\macro{F\_UNLCK}. Inoltre a seconda del valore di \var{l\_type} si potrà
+controllare l'esistenza di un qualunque tipo di lock (con \macro{F\_WRLCK}) o
+dei soli lock esclusivi (con \macro{F\_RDLCK}). Si consideri poi che può
+esserci più di un lock che impedisce l'acquisizione di quello richiesto, ma la
+funzione ne riporterà sempre soltanto uno, impostando opportunamente
+\var{l\_whence} a \macro{SEEK\_SET} ed i valori \var{l\_start} e \var{l\_len}
+per indicare quale è la regione effettivamente bloccata.
+
+Infine si tenga presente che effettuare un controllo con il comando
+\macro{F\_GETLK} e poi tentare l'acquisizione con \macro{F\_SETLK} non è una
+operazione atomica (un altro processo potrebbe acquisire un lock fra le due
+chiamate) per cui si deve sempre verificare il codice di ritorno di
+\func{fcntl}\footnote{controllare il codice di ritorno delle funzioni invocate
+  è comunque una buona norma di programmazione, che permette di evitare un
+  sacco di errori difficili da tracciare proprio perché non vengono rilevati.}
+quando la si invoca con \macro{F\_SETLK} per controllare che il lock sia stato
+effettivamente acquisito.
+
+Un'ultima considerazione riguardo il funzionamento del file locking POSIX
+riguarda la loro caratteristica di operare su delle sezioni di file: è
+possibile con una sola chiamata rimuovere più lock separati (indicando in
+\var{flock} una regione che li copra tutti), o rimuovere solo una parte di un
+lock preesistente (indicando una sezione contenuta in un altro lock), o di
+coprire con un nuovo lock altri lock già ottenuti. In tutti questi casi il
+kernel si preoccupa di accorpare o suddividere le regioni bloccate,
+aggiornando opportunamente le strutture interne usate per il file locking.
 
 \begin{figure}[htb]
-  \centering
-  \includegraphics[width=13cm]{img/file_posix_lock}
+  \centering \includegraphics[width=13cm]{img/file_posix_lock}
   \caption{Schema dell'architettura del file locking, nel caso particolare  
     del suo utilizzo secondo l'interfaccia standard POSIX.}
   \label{fig:file_posix_lock}
 \end{figure}
 
-Infine il campo \var{l\_pid} riporta (viene usato solo in lettura, quando si
-chiama \func{fcntl} con \macro{F\_GETLK}) qual'è il processo cui appartiene il
-file lock. Nella semantica POSIX infatti il comportamento dei lock è diverso
-rispetto a quanto visto in precedenza per \func{flock}. Lo schema della
-struttura usata in questo caso è riportato in \figref{fig:file_posix_lock};
-come si vede essa è molto simile a quanto visto in
-\figref{fig:file_flock_struct} per \func{flock}:\footnote{in questo caso si
-  sono evidenziati nella figura i campi di \var{file\_lock} significativi per
-  la semantica POSIX, in particolare adesso ciascun lock contiene, oltre al
-  \acr{pid} del processo in \var{fl\_pid}, la sezione di file che viene
-  bloccata grazie ai campi \var{fl\_start} e \var{fl\_end}.  La struttura è
-  comunque la stessa, solo che in questo caso nel campo \var{fl\_flags} è
-  impostato il bit \macro{FL\_POSIX} ed il campo \var{fl\_file} non viene
-  usato.} il lock è sempre associato all'inode, solo che in questo caso la
-titolarità non viene identificata con il riferimento ad una voce nella file
-table, ma con il valore del \acr{pid} del processo.
-
-Tutto ciò significa che la rimozione di un blocco viene effettuata
-controllando che il \acr{pid} del processo richiedente corrisponda a quello
-contenuto nel lock. Questa diversa modalità ha delle conseguenze precise
-riguardo il comportamento dei lock POSIX. La prima conseguenza è che un lock
-POSIX non viene mai ereditato attraverso una \func{fork}, dato che il processo
-figlio avrà un \acr{pid} diverso, mentre passa indenne attraverso una
-\func{exec} in quanto il \acr{pid} resta lo stesso.  Questo comporta che, al
-contrario di quanto avveniva con la semantica BSD, quando processo termina
-tutti i file lock da esso detenuti vengono immediatamente rilasciati.
+Come accennato nella semantica POSIX si ha un comportamento del file locking
+diverso rispetto a quanto visto in \secref{sec:file_flock}.  Lo schema della
+struttura usata dal kernel in questo caso è riportato in
+\figref{fig:file_posix_lock}; come si vede essa è molto simile a quanto visto
+in \figref{fig:file_flock_struct} per \func{flock}:\footnote{in questo caso
+  nella figura si sono evidenziati solo i campi di \var{file\_lock}
+  significativi per la semantica POSIX, in particolare adesso ciascuna
+  struttura contiene, oltre al \acr{pid} del processo in \var{fl\_pid}, la
+  sezione di file che viene bloccata grazie ai campi \var{fl\_start} e
+  \var{fl\_end}.  La struttura è comunque la stessa, solo che in questo caso
+  nel campo \var{fl\_flags} è impostato il bit \macro{FL\_POSIX} ed il campo
+  \var{fl\_file} non viene usato.} il lock è sempre associato all'inode, solo
+che in questo caso la titolarità non viene identificata con il riferimento ad
+una voce nella file table, ma con il valore del \acr{pid} del processo.
+
+Tutto ciò significa che la rimozione di un lock viene effettuata controllando
+che il \acr{pid} del processo richiedente corrisponda a quello contenuto nel
+lock. Questa diversa modalità ha delle conseguenze precise riguardo il
+comportamento dei lock POSIX. La prima conseguenza è che un lock POSIX non
+viene mai ereditato attraverso una \func{fork}, dato che il processo figlio
+avrà un \acr{pid} diverso, mentre passa indenne attraverso una \func{exec} in
+quanto il \acr{pid} resta lo stesso.  Questo comporta che, al contrario di
+quanto avveniva con la semantica BSD, quando processo termina tutti i file
+lock da esso detenuti vengono immediatamente rilasciati.
 
 La seconda conseguenza è che qualunque file descriptor che faccia riferimento
 allo stesso file (che sia stato ottenuto con una \func{dup} o con una
-\func{open} non fa differenza) può essere usato per rimuovere un lock, dato
-che quello che conta è solo il \acr{pid} del processo. Da questo deriva una
-ulteriore sottile differenza di comportamento: dato che alla chiusura di un
-file i lock ad esso associati vengono rimossi, nella semantica POSIX basterà
-chiudere un file descriptor per cancellare tutti i lock relativi al file cui
-esso faceva riferimento, anche se questi fossero stati creati usando altri
-file descriptor che restano aperti.
+\func{open} in questo caso non fa differenza) può essere usato per rimuovere
+un lock, dato che quello che conta è solo il \acr{pid} del processo. Da questo
+deriva una ulteriore sottile differenza di comportamento: dato che alla
+chiusura di un file i lock ad esso associati vengono rimossi, nella semantica
+POSIX basterà chiudere un file descriptor qualunque per cancellare tutti i
+lock relativi al file cui esso faceva riferimento, anche se questi fossero
+stati creati usando altri file descriptor che restano aperti.
+
+
+\subsection{La funzione \func{lockf}}
+\label{sec:file_lockf}
 
 Abbiamo visto come l'interfaccia POSIX per il file locking sia molto più
 potente e flessibile di quella di BSD, ma è anche molto più complicata da
@@ -1611,7 +1670,7 @@ che specifica quale azione eseguire; i valori possibili sono riportati in
 \begin{table}[htb]
   \centering
   \footnotesize
-  \begin{tabular}[c]{|l|p{8cm}|}
+  \begin{tabular}[c]{|l|p{7cm}|}
     \hline
     \textbf{Valore} & \textbf{Significato} \\
     \hline